Skip to content

Commit 7300c30

Browse files
committed
new validations & set default configs
1 parent c141309 commit 7300c30

File tree

8 files changed

+127
-47
lines changed

8 files changed

+127
-47
lines changed

apps/csv2sql/lib/csv2sql/config/loader.ex

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,40 @@ defmodule Csv2sql.Config.Loader do
3030
@insertion_chunk_size 100
3131
@min_insertion_chunk_size 1
3232

33+
@spec get_defaults() :: map()
34+
def get_defaults do
35+
%{
36+
date_patterns: [%{id: 1, pattern: @date_pattern}],
37+
datetime_patterns: [%{id: 1, pattern: @datetime_pattern}],
38+
db_type: @db_type,
39+
drop_existing_tables: false,
40+
insert_data: false,
41+
insert_schema: true,
42+
log: false,
43+
ordered: false,
44+
parse_datetime: true,
45+
remove_illegal_characters: false,
46+
schema_infer_chunk_size: @schema_infer_chunk_size,
47+
db_worker_count: @default_db_worker_count,
48+
varchar_limit: @varchar_limit,
49+
insertion_chunk_size: @insertion_chunk_size
50+
}
51+
end
52+
53+
@spec get_constraints() :: map()
54+
def get_constraints do
55+
%{
56+
schema_infer_chunk_size: %{
57+
min: @min_schema_infer_chunk_size,
58+
max: @max_schema_infer_chunk_size
59+
},
60+
varchar_limit: %{min: @min_varchar_limit, max: @max_varchar_limit},
61+
worker_count: %{min: @min_worker_count, max: @max_worker_count},
62+
db_worker_count: %{min: @min_db_worker_count, max: @max_db_worker_count},
63+
insertion_chunk_size: %{min: @min_insertion_chunk_size, max: @max_insertion_chunk_size}
64+
}
65+
end
66+
3367
@spec load(map) :: :ok
3468
def load(args), do: Application.put_env(:csv2sql, :config, prepare_configs(args))
3569

apps/dashboard/assets/js/app.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ let hooks = {
1515
new bootstrap.Tooltip(this.el);
1616

1717
this.handleEvent("save-config", ({ config }) => {
18-
console.log("write to local", JSON.stringify(config))
19-
localStorage.setItem("config", JSON.stringify(config))
18+
localStorage.setItem("config", JSON.stringify(config));
2019
}
2120
)
2221
}

apps/dashboard/lib/dashboard/config.ex

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ end
99
defmodule DashBoard.Config do
1010
use Ecto.Schema
1111
import Ecto.Changeset
12+
import ShorterMaps
1213

1314
@primary_key false
1415
embedded_schema do
@@ -46,21 +47,8 @@ defmodule DashBoard.Config do
4647
end
4748

4849
def get_defaults do
49-
%__MODULE__{
50-
db_type: :mysql,
51-
db_worker_count: 10,
52-
drop_existing_tables: false,
53-
insert_data: true,
54-
insert_schema: true,
55-
insertion_chunk_size: 100,
56-
log: false,
57-
ordered: false,
58-
parse_datetime: true,
59-
remove_illegal_characters: false,
60-
schema_infer_chunk_size: 100,
61-
varchar_limit: 200,
62-
worker_count: System.schedulers_online()
63-
}
50+
Csv2sql.Config.Loader.get_defaults()
51+
|> Map.put(:source_directory, get_source_directory())
6452
end
6553

6654
def changeset(params), do: changeset(%__MODULE__{}, params)
@@ -78,6 +66,7 @@ defmodule DashBoard.Config do
7866
changeset =
7967
config
8068
|> cast(params, attrs_to_cast)
69+
|> validate_limit_constraints(Csv2sql.Config.Loader.get_constraints())
8170
|> validate_source_directory()
8271
|> validate_path(:schema_path, true)
8372
|> cast_embed(:db_attrs)
@@ -88,6 +77,21 @@ defmodule DashBoard.Config do
8877
%{changeset | action: :insert}
8978
end
9079

80+
defp validate_limit_constraints(changeset, constants) do
81+
Enum.reduce(
82+
constants,
83+
changeset,
84+
fn {key, ~M{min, max}}, changeset ->
85+
validate_number(
86+
changeset,
87+
key,
88+
greater_than_or_equal_to: min,
89+
less_than_or_equal_to: max
90+
)
91+
end
92+
)
93+
end
94+
9195
defp validate_source_directory(changeset) do
9296
changeset
9397
|> validate_path(:source_directory)
@@ -109,25 +113,40 @@ defmodule DashBoard.Config do
109113
end
110114
end
111115

112-
defp add_csv_count(%Ecto.Changeset{valid?: true} = changeset) do
113-
csv_count =
116+
defp add_csv_count(changeset) do
117+
source_directory = get_change(changeset, :source_directory)
118+
119+
if File.dir?(source_directory) do
120+
csv_count =
121+
source_directory
122+
|> File.ls!()
123+
|> Enum.filter(&is_csv?/1)
124+
|> Enum.count()
125+
126+
if csv_count == 0,
127+
do: add_error(changeset, :source_directory, "No CSVs found at path"),
128+
else: put_change(changeset, :csv_count, csv_count)
129+
else
114130
changeset
115-
|> get_change(:source_directory)
116-
|> File.ls!()
117-
|> Enum.filter(&is_csv?/1)
118-
|> Enum.count()
119-
120-
if csv_count == 0,
121-
do: add_error(changeset, :source_directory, "No CSVs found at path"),
122-
else: put_change(changeset, :csv_count, csv_count)
131+
end
123132
end
124133

125-
defp add_csv_count(changeset), do: changeset
126-
127134
defp is_csv?(filepath) do
128135
filepath
129136
|> String.trim()
130137
|> String.slice(-4..-1)
131138
|> String.downcase() == ".csv"
132139
end
140+
141+
defp get_source_directory() do
142+
case :os.type() do
143+
{:win32, _} ->
144+
username = System.shell("echo %USERNAME%") |> elem(0) |> String.trim()
145+
"C:/Users/#{username}/Desktop"
146+
147+
{:unix, _} ->
148+
{op, _exit_code} = System.cmd("eval", ["echo ~$USER"])
149+
String.trim(op)
150+
end
151+
end
133152
end

apps/dashboard/lib/dashboard/date_pattern.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ defmodule DashBoard.DatePattern do
88
field(:pattern, :string)
99
end
1010

11+
def changeset(params), do: changeset(%__MODULE__{}, params)
12+
1113
def changeset(struct, params) do
1214
struct
1315
|> cast(params, [:id, :pattern])

apps/dashboard/lib/dashboard/date_time_pattern.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ defmodule DashBoard.DateTimePattern do
88
field(:pattern, :string)
99
end
1010

11+
def changeset(params), do: changeset(%__MODULE__{}, params)
12+
1113
def changeset(struct, params) do
1214
struct
1315
|> cast(params, [:id, :pattern])

apps/dashboard/lib/dashboard_web/live/config_live.ex

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ defmodule DashboardWeb.Live.ConfigLive do
5353
tooltip="TODO: popup title"
5454
placeholder="Worker count">
5555
<:input let={f}>
56-
<%= text_input f, :worker_count, type: "number", class: "form-control", placeholder: "Worker count" %>
56+
<%= text_input f, :worker_count, type: "number", class: "form-control", placeholder: "Worker count",
57+
max: @constraints.worker_count.max, min: @constraints.worker_count.min %>
58+
<%= error_tag(f, :worker_count) %>
5759
</:input>
5860
</.config_item>
5961
@@ -64,7 +66,9 @@ defmodule DashboardWeb.Live.ConfigLive do
6466
tooltip="TODO: popup title"
6567
placeholder="Chunk Size">
6668
<:input let={f}>
67-
<%= text_input f, :schema_infer_chunk_size, type: "number", class: "form-control", placeholder: "Chunk Size" %>
69+
<%= text_input f, :schema_infer_chunk_size, type: "number", class: "form-control", placeholder: "Chunk Size",
70+
max: @constraints.schema_infer_chunk_size.max, min: @constraints.schema_infer_chunk_size.min %>
71+
<%= error_tag(f, :schema_infer_chunk_size) %>
6872
</:input>
6973
</.config_item>
7074
@@ -104,7 +108,7 @@ defmodule DashboardWeb.Live.ConfigLive do
104108
</div>
105109
106110
<!-- Database Configurations -->
107-
<div class="card m-4 d-flex w-75 m-auto mt-4">
111+
<div class={"card m-4 d-flex w-75 m-auto mt-4 #{unless(db_needed(@changeset), do: "invisible")}"}>
108112
<header>
109113
<IconSvg.db_settings class="m-2"/>
110114
<span class="font-monospace small fst-italic fw-bold"> Database Configurations </span>
@@ -123,7 +127,7 @@ defmodule DashboardWeb.Live.ConfigLive do
123127
<:input let={f}>
124128
<div class="d-flex flex-column">
125129
<div class="form-check">
126-
<%= radio_button f, :db_type, :mysql, class: "form-check-input mt-4", id: "mysql_db_type", checked: "checked" %>
130+
<%= radio_button f, :db_type, :mysql, class: "form-check-input mt-4", id: "mysql_db_type", checked: "checked", disable: !db_needed(@changeset) %>
127131
<label class="form-check-label mysql-label" for="mysql_db_type">
128132
<IconSvg.mysql_icon {%{width: 100, height: 100}} />
129133
</label>
@@ -237,7 +241,9 @@ defmodule DashboardWeb.Live.ConfigLive do
237241
tooltip="TODO: popup title"
238242
placeholder="Varchar size">
239243
<:input let={f}>
240-
<%= text_input f, :varchar_limit, type: "number", class: "form-control", placeholder: "Varchar size" %>
244+
<%= text_input f, :varchar_limit, type: "number", class: "form-control", placeholder: "Varchar size",
245+
max: @constraints.varchar_limit.max, min: @constraints.varchar_limit.min %>
246+
<%= error_tag(f, :varchar_limit) %>
241247
</:input>
242248
</.config_item>
243249
@@ -249,7 +255,9 @@ defmodule DashboardWeb.Live.ConfigLive do
249255
tooltip="TODO: popup title"
250256
placeholder="DB Worker count">
251257
<:input let={f}>
252-
<%= text_input f, :db_worker_count, type: "number", class: "form-control", placeholder: "DB Worker count" %>
258+
<%= text_input f, :db_worker_count, type: "number", class: "form-control", placeholder: "DB Worker count",
259+
max: @constraints.db_worker_count.max, min: @constraints.db_worker_count.min %>
260+
<%= error_tag(f, :db_worker_count) %>
253261
</:input>
254262
</.config_item>
255263
@@ -260,7 +268,9 @@ defmodule DashboardWeb.Live.ConfigLive do
260268
tooltip="TODO: popup title"
261269
placeholder="Insertion Chunk Size">
262270
<:input let={f}>
263-
<%= text_input f, :insertion_chunk_size, type: "number", class: "form-control", placeholder: "Insertion Chunk size" %>
271+
<%= text_input f, :insertion_chunk_size, type: "number", class: "form-control", placeholder: "Insertion Chunk size",
272+
max: @constraints.insertion_chunk_size.max, min: @constraints.insertion_chunk_size.min %>
273+
<%= error_tag(f, :insertion_chunk_size) %>
264274
</:input>
265275
</.config_item>
266276
</div>
@@ -296,4 +306,9 @@ defmodule DashboardWeb.Live.ConfigLive do
296306
</.form>
297307
"""
298308
end
309+
310+
defp db_needed(changeset) do
311+
Ecto.Changeset.get_field(changeset, :insert_schema) ||
312+
Ecto.Changeset.get_field(changeset, :insert_data)
313+
end
299314
end

apps/dashboard/lib/dashboard_web/live/main_live.ex

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ defmodule DashboardWeb.Live.MainLive do
88

99
@impl true
1010
def mount(_params, _session, socket) do
11-
localstorage_config = (get_connect_params(socket) || %{}) |> Map.get("localConfig", %{})
11+
local_storage_config = (get_connect_params(socket) || %{}) |> Map.get("localConfig", %{})
12+
13+
local_storage_config =
14+
for {key, val} <- local_storage_config, into: %{}, do: {String.to_existing_atom(key), val}
15+
1216
# Check for DB connection on config load from local storage
1317
timer_ref = Process.send_after(self(), :check_db_connection, @debounce_time)
1418

@@ -19,8 +23,9 @@ defmodule DashboardWeb.Live.MainLive do
1923
path_validator_debouncer: nil,
2024
db_connection_debouncer: timer_ref,
2125
db_connection_established: false,
22-
changeset: Config.get_defaults() |> Config.changeset(localstorage_config),
23-
matching_date_time: nil
26+
changeset: Config.get_defaults() |> Map.merge(local_storage_config) |> Config.changeset(),
27+
matching_date_time: nil,
28+
constraints: Csv2sql.Config.Loader.get_constraints()
2429
)}
2530
end
2631

apps/dashboard/lib/dashboard_web/live/modals/date_time_patterns_modal.ex

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,16 @@ defmodule DashboardWeb.Live.Modal.DateTimePatternsModal do
4949
<div class="d-flex flex-row">
5050
<div class="input-group mb-3">
5151
<span class="input-group-text fw-bold pe-2 pt-1"><%= index %>.</span>
52-
<%= text_input date_patterns_form, :pattern, class: input_class(index, :date, @matching_date_time), placeholder: "Pattern", list: "date-patterns-suggestions" %>
52+
<%= text_input date_patterns_form, :pattern, disabled: index == 1, class: input_class(index, :date, @matching_date_time), placeholder: "Pattern", list: "date-patterns-suggestions" %>
5353
</div>
5454
5555
<%= hidden_input(date_patterns_form, :id) %>
5656
57-
<div role="button" phx-click="remove-date-pattern" phx-value-attrid={Ecto.Changeset.get_field(date_patterns_form.source, :id)}>
58-
<IconSvg.remove_icon class="ms-2 pt-1"/>
59-
</div>
57+
<%= unless index == 1 do %>
58+
<div role="button" phx-click="remove-date-pattern" phx-value-attrid={Ecto.Changeset.get_field(date_patterns_form.source, :id)}>
59+
<IconSvg.remove_icon class="ms-2 pt-1"/>
60+
</div>
61+
<% end %>
6062
</div>
6163
<% end %>
6264
<% else %>
@@ -78,14 +80,16 @@ defmodule DashboardWeb.Live.Modal.DateTimePatternsModal do
7880
<div class="d-flex flex-row">
7981
<div class="input-group mb-3">
8082
<span class="input-group-text fw-bold pe-2 pt-1"><%= index %>.</span>
81-
<%= text_input date_time_patterns_form, :pattern, class: input_class(index, :date_time, @matching_date_time), placeholder: "Pattern", list: "date-time-patterns-suggestions" %>
83+
<%= text_input date_time_patterns_form, :pattern, disabled: index == 1, class: input_class(index, :date_time, @matching_date_time), placeholder: "Pattern", list: "date-time-patterns-suggestions" %>
8284
</div>
8385
8486
<%= hidden_input(date_time_patterns_form, :id) %>
8587
86-
<div role="button" phx-click="remove-date-time-pattern" phx-value-attrid={Ecto.Changeset.get_field(date_time_patterns_form.source, :id)}>
87-
<IconSvg.remove_icon class="ms-2 pt-1"/>
88-
</div>
88+
<%= unless index == 1 do %>
89+
<div role="button" phx-click="remove-date-time-pattern" phx-value-attrid={Ecto.Changeset.get_field(date_time_patterns_form.source, :id)}>
90+
<IconSvg.remove_icon class="ms-2 pt-1"/>
91+
</div>
92+
<% end %>
8993
</div>
9094
<% end %>
9195
<% else %>

0 commit comments

Comments
 (0)