blob: 2629ccfcfa468bcb882df804932eec0072d2131a [file] [log] [blame]
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +04001{{ define "schema-form" }}
2 {{ $readonly := .ReadOnly }}
3 {{ $networks := .AvailableNetworks }}
giof6ad2982024-08-23 17:42:49 +04004 {{ $clusters := .AvailableClusters }}
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +04005 {{ $data := .Data }}
gio44f621b2024-04-29 09:44:38 +04006 {{ range $f := .Schema.Fields }}
7 {{ $name := $f.Name }}
8 {{ $schema := $f.Schema }}
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +04009 {{ if eq $schema.Kind 0 }}
gio44f621b2024-04-29 09:44:38 +040010 <label {{ if $schema.Advanced }}hidden{{ end }}>
11 <input type="checkbox" role="swtich" name="{{ $name }}" oninput="valueChanged({{ $name }}, this.checked)" {{ if $readonly }}disabled{{ end }} {{ if index $data $name }}checked{{ end }} />
12 {{ $schema.Name }}
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040013 </label>
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +040014 {{ else if eq $schema.Kind 7 }}
gio44f621b2024-04-29 09:44:38 +040015 <label {{ if $schema.Advanced }}hidden{{ end }}>
16 {{ $schema.Name }}
17 <input type="text" name="{{ $name }}" oninput="valueChanged({{ $name }}, parseInt(this.value))" {{ if $readonly }}disabled{{ end }} value="{{ index $data $name }}" />
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +040018 </label>
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040019 {{ else if eq $schema.Kind 1 }}
gio44f621b2024-04-29 09:44:38 +040020 <label {{ if $schema.Advanced }}hidden{{ end }}>
21 {{ $schema.Name }}
gio7fbd4ad2024-08-27 10:06:39 +040022 <input type="text" name="{{ $name }}" oninput="valueChanged({{ $name }}, this.value)" {{ if $readonly }}disabled{{ end }} value="{{ index $data $name }}" />
23 </label>
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040024 {{ else if eq $schema.Kind 4 }}
gio44f621b2024-04-29 09:44:38 +040025 <label {{ if $schema.Advanced }}hidden{{ end }}>
26 {{ $schema.Name }}
27 <input type="text" name="{{ $name }}" oninput="valueChanged({{ $name }}, this.value)" {{ if $readonly }}disabled{{ end }} value="{{ index $data $name }}" />
28 </label>
giof6ad2982024-08-23 17:42:49 +040029 {{ else if eq $schema.Kind 12 }}
30 <label {{ if $schema.Advanced }}hidden{{ end }}>
31 {{ $schema.Name }}
32 <details class="dropdown">
33 {{ $selectedCluster := index $data $name }}
gio488554f2024-10-02 16:41:26 +040034 {{ if not $selectedCluster }}
35 {{ $selectedCluster = "default" }}
36 {{ end }}
giof6ad2982024-08-23 17:42:49 +040037 <summary id="{{ $name }}">{{ $selectedCluster }}</summary>
38 <ul>
39 {{ range $clusters }}
40 {{ $selected := eq $selectedCluster .Name }}
41 <li>
42 <label>
43 <input type="radio" name="{{ $name }}" oninput="clusterSelected('{{ $name }}', '{{ .Name }}', this.checked)" {{ if $selected }}checked{{ end }} />
44 {{ .Name }}
45 </label>
46 </li>
47 {{ end }}
48 </ul>
49 </details>
50 </label>
Giorgi Lekveishvili7c427602024-01-04 00:13:55 +040051 {{ else if eq $schema.Kind 3 }}
gio44f621b2024-04-29 09:44:38 +040052 <label {{ if $schema.Advanced }}hidden{{ end }}>
53 {{ $schema.Name }}
giobb338e22024-07-18 18:09:22 +040054 <details class="dropdown">
55 {{ $selectedNetwork := index $data $name }}
56 <summary id="{{ $name }}">{{ $selectedNetwork }}</summary>
57 <ul>
58 {{ range $networks }}
59 {{ $selected := eq $selectedNetwork .Name }}
60 <li>
61 <label>
giof6ad2982024-08-23 17:42:49 +040062 <input type="radio" name="{{ $name }}" oninput="networkSelected('{{ $name }}', '{{ .Name }}', '{{ .Name }} - {{ .Domain }}', this.checked)" {{ if $selected }}checked{{ end }} />
63 {{ .Name }} - {{ .Domain }}
giobb338e22024-07-18 18:09:22 +040064 </label>
65 </li>
66 {{ end }}
67 </ul>
68 </details>
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +040069 </label>
gio4ece99c2024-07-18 11:05:50 +040070 {{ else if eq $schema.Kind 10 }}
71 <label {{ if $schema.Advanced }}hidden{{ end }}>
72 {{ $schema.Name }}
73 <details class="dropdown">
74 {{ $selectedNetworks := index $data $name }}
75 <summary id="{{ $name }}">{{ $selectedNetworks | join "," }}</summary>
76 <ul>
77 {{ range $networks }}
78 {{ $networkName := .Name }}
79 {{ $selected := false }}
80 {{ range $selectedNetworks }}
81 {{ if eq . $networkName }}
82 {{ $selected = true }}
83 {{ end }}
84 {{ end }}
85 <li>
86 <label>
87 <input type="checkbox" name="{{ $networkName }}" oninput="multiNetworkSelected('{{ $name }}', '{{ $networkName }}', this.checked)" {{ if $selected }}checked{{ end }} />
giof6ad2982024-08-23 17:42:49 +040088 {{ .Name }} - {{ .Domain }}
gio4ece99c2024-07-18 11:05:50 +040089 </label>
90 </li>
91 {{ end }}
92 </ul>
93 </details>
94 </label>
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +040095 {{ else if eq $schema.Kind 5 }}
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +040096 {{ $auth := index $data $name }}
97 {{ $authEnabled := false }}
98 {{ $authGroups := "" }}
99 {{ if and $auth (index $auth "enabled") }}{{ $authEnabled = true }}{{ end }}
100 {{ if and $auth (index $auth "groups") }}{{ $authGroups = index $auth "groups" }}{{ end }}
gio44f621b2024-04-29 09:44:38 +0400101 <label {{ if $schema.Advanced }}hidden{{ end }}>
102 <input type="checkbox" role="swtich" name="authEnabled" oninput="valueChanged('{{- $name -}}.enabled', this.checked)" {{ if $readonly }}disabled{{ end }} {{ if $authEnabled }}checked{{ end }} />
103 <span>Require authentication</span>
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400104 </label>
gio44f621b2024-04-29 09:44:38 +0400105 <label for="authGroups">
106 <span>Authentication groups</span>
107 <input type="text" name="authGroups" oninput="valueChanged('{{- $name -}}.groups', this.value)" {{ if $readonly }}disabled{{ end }} value="{{ $authGroups }}" />
108 </label>
Giorgi Lekveishvilib6a58062024-04-02 16:49:19 +0400109 {{ else if eq $schema.Kind 6 }}
110 {{ $sshKey := index $data $name }}
111 {{ $public := "" }}
112 {{ $private := "" }}
113 {{ if $sshKey }}{{ $public = index $sshKey "public" }}{{ end }}
114 {{ if $sshKey }}{{ $private = index $sshKey "private" }}{{ end }}
gio44f621b2024-04-29 09:44:38 +0400115 <label {{ if $schema.Advanced }}hidden{{ end }}>
116 <span>Public Key</span>
117 <textarea name="{{ $name }}-public" disabled>{{ $public }}</textarea>
Giorgi Lekveishvilib6a58062024-04-02 16:49:19 +0400118 </label>
gio44f621b2024-04-29 09:44:38 +0400119 <label {{ if $schema.Advanced }}hidden{{ end }}>
120 <span>Private Key</span>
121 <textarea name="{{ $name }}-private" disabled>{{ $private }}</textarea>
Giorgi Lekveishvilib6a58062024-04-02 16:49:19 +0400122 </label>
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400123 {{ end }}
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400124 {{ end }}
125{{ end }}
126
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400127{{ define "header" }}
Davit Tabidzed1b742e2024-07-15 16:01:52 +0400128 {{ .App.Icon }}
129 <h1>{{ .App.Name }}</h1>
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400130{{ end }}
gio18d5c682024-05-02 10:30:57 +0400131
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400132{{ define "extra_menu" }}
gio1cd65152024-08-16 08:18:49 +0400133 <li><a href="/app/{{ .App.Slug }}" {{ if eq $.CurrentPage .App.Name }}class="primary"{{ end }}>{{ .App.Name }}</a></li>
134 {{ if (and (not $.Instance) $.Task) }}
135 <li><a href="/instance/{{ $.CurrentPage }}" class="primary">{{ $.CurrentPage }}</a></li>
136 {{ end }}
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400137 {{ range .Instances }}
gio1cd65152024-08-16 08:18:49 +0400138 <li><a href="/instance/{{ .Id }}" {{ if eq $.CurrentPage .Id }}class="primary"{{ end }}>{{ .Id }}</a></li>
gio778577f2024-04-29 09:44:38 +0400139 {{ end }}
140{{ end }}
141
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400142{{ define "content"}}
143 {{ $schema := .App.Schema }}
144 {{ $networks := .AvailableNetworks }}
giof6ad2982024-08-23 17:42:49 +0400145 {{ $clusters := .AvailableClusters }}
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400146 {{ $instance := .Instance }}
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400147
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400148 <form id="config-form">
149 {{ if $instance }}
giof6ad2982024-08-23 17:42:49 +0400150 {{ template "schema-form" (dict "Schema" $schema "AvailableNetworks" $networks "AvailableClusters" $clusters "ReadOnly" false "Data" ($instance.InputToValues $schema)) }}
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400151 {{ else }}
giof6ad2982024-08-23 17:42:49 +0400152 {{ template "schema-form" (dict "Schema" $schema "AvailableNetworks" $networks "AvailableClusters" $clusters "ReadOnly" false "Data" (dict)) }}
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400153 {{ end }}
154 {{ if $instance }}
155 <div class="grid">
156 <button type="submit" id="submit" name="update">Update</button>
157 <button type="submit" id="uninstall" name="remove">Uninstall</button>
158 </div>
159 {{ else }}
160 <button type="submit" id="submit">{{ if $instance }}Update{{ else }}Install{{ end }}</button>
161 {{ end }}
162 </form>
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400163
164<div id="toast-failure" class="toast hidden">
165 <svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2S2 6.477 2 12s4.477 10 10 10Zm3-6L9 8m0 8l6-8"/></svg> {{ if $instance }}Update failed{{ else}}Install failed{{ end }}
166</div>
167
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400168<div id="toast-uninstall-failure" class="toast hidden">
169 <svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2S2 6.477 2 12s4.477 10 10 10Zm3-6L9 8m0 8l6-8"/></svg> Failed to uninstall application
170</div>
171
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400172<script>
gio3cdee592024-04-17 10:15:56 +0400173 let config = {{ if $instance }}JSON.parse({{ toJson ($instance.InputToValues $schema) }}){{ else }}{}{{ end }};
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400174
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400175 function setValue(name, value, config) {
176 let items = name.split(".")
177 for (let i = 0; i < items.length - 1; i++) {
178 if (!(items[i] in config)) {
179 config[items[i]] = {}
180 }
181 config = config[items[i]];
182 }
183 config[items[items.length - 1]] = value;
gio4ece99c2024-07-18 11:05:50 +0400184 }
185
186 function getValue(name, value) {
187 let items = name.split(".")
188 for (let i = 0; i < items.length - 1; i++) {
189 if (!(items[i] in config)) {
190 config[items[i]] = {}
191 }
192 config = config[items[i]];
193 }
194 return config[items[items.length - 1]];
195 }
196
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400197 function valueChanged(name, value) {
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400198 setValue(name, value, config);
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400199 }
200
giof6ad2982024-08-23 17:42:49 +0400201 function clusterSelected(name, cluster, selected) {
202 console.log(selected);
203 setValue(name, cluster, config);
204 let summary = document.getElementById(name);
205 summary.innerHTML = cluster;
206 summary.parentNode.removeAttribute("open");
207 }
208
209 function networkSelected(name, network, label, selected) {
giobb338e22024-07-18 18:09:22 +0400210 console.log(selected);
211 setValue(name, network, config);
212 let summary = document.getElementById(name);
giof6ad2982024-08-23 17:42:49 +0400213 summary.innerHTML = label;
giobb338e22024-07-18 18:09:22 +0400214 summary.parentNode.removeAttribute("open");
215 }
216
gio4ece99c2024-07-18 11:05:50 +0400217 function multiNetworkSelected(name, network, selected) {
218 let v = getValue(name, config);
219 if (v === undefined) {
220 v = [];
221 }
222 if (selected) {
223 v.push(network);
224 } else {
225 v = v.filter((n) => n != network);
226 }
227 setValue(name, v, config);
228 document.getElementById(name).innerHTML = v.join(",");
229 }
230
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400231 function disableForm() {
232 document.querySelectorAll("#config-form input").forEach((i) => i.setAttribute("disabled", ""));
233 document.querySelectorAll("#config-form select").forEach((i) => i.setAttribute("disabled", ""));
234 document.querySelectorAll("#config-form button").forEach((i) => i.setAttribute("disabled", ""));
235 }
236
237 function enableForm() {
238 document.querySelectorAll("[aria-busy]").forEach((i) => i.removeAttribute("aria-busy"));
239 document.querySelectorAll("#config-form input").forEach((i) => i.removeAttribute("disabled"));
240 document.querySelectorAll("#config-form select").forEach((i) => i.removeAttribute("disabled"));
241 document.querySelectorAll("#config-form button").forEach((i) => i.removeAttribute("disabled"));
242 }
243
244 function installStarted() {
245 const submit = document.getElementById("submit");
246 submit.setAttribute("aria-busy", true);
247 submit.innerHTML = {{ if $instance }}"Updating ..."{{ else }}"Installing ..."{{ end }};
248 disableForm();
249 }
250
251 function uninstallStarted() {
252 const submit = document.getElementById("uninstall");
253 submit.setAttribute("aria-busy", true);
254 submit.innerHTML = "Uninstalling ...";
255 disableForm();
256 }
257
258 function actionFinished(toast) {
259 enableForm();
260 toast.classList.remove("hidden");
261 setTimeout(
262 () => toast.classList.add("hidden"),
263 2000,
264 );
265 }
266
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400267 function installFailed() {
268 actionFinished(document.getElementById("toast-failure"));
269 }
270
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400271 function uninstallFailed() {
272 actionFinished(document.getElementById("toast-uninstall-failure"));
273 }
274
gio44f621b2024-04-29 09:44:38 +0400275 const submitAddr = {{ if $instance }}"/api/instance/{{ $instance.Id }}/update"{{ else }}"/api/app/{{ .App.Slug }}/install"{{ end }};
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400276
277 async function install() {
278 installStarted();
279 const resp = await fetch(submitAddr, {
gio778577f2024-04-29 09:44:38 +0400280 method: "POST",
281 headers: {
282 "Content-Type": "application/json",
283 "Accept": "application/json",
284 },
285 body: JSON.stringify(config),
286 });
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400287 if (resp.status === 200) {
gio778577f2024-04-29 09:44:38 +0400288 window.location = await resp.text();
289 } else {
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400290 installFailed();
291 }
292 }
293
294 async function uninstall() {
295 {{ if $instance }}
296 uninstallStarted();
297 const resp = await fetch("/api/instance/{{ $instance.Id }}/remove", {
298 method: "POST",
299 });
300 if (resp.status === 200) {
gio778577f2024-04-29 09:44:38 +0400301 window.location = await resp.text();
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400302 } else {
303 uninstallFailed();
304 }
305 {{ end }}
306 }
307
giof9f0bee2024-06-11 20:10:05 +0400308 const configForm = document.getElementById("config-form");
309 if (configForm) {
310 configForm.addEventListener("submit", (event) => {
311 event.preventDefault();
312 if (event.submitter.id === "submit") {
313 install();
314 } if (event.submitter.id === "uninstall") {
315 uninstall();
316 }
317 });
318 }
Giorgi Lekveishvili4257b902023-07-07 17:08:42 +0400319</script>
Davit Tabidze3ec24cf2024-05-22 14:06:02 +0400320
321{{end}}