fix: loading state on start
This commit is contained in:
@@ -60,11 +60,9 @@
|
|||||||
import { errorNotification, handlerNotFoundLoad } from '$lib/common';
|
import { errorNotification, handlerNotFoundLoad } from '$lib/common';
|
||||||
import { appSession, status, disabledButton } from '$lib/store';
|
import { appSession, status, disabledButton } from '$lib/store';
|
||||||
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
|
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
|
||||||
import Loading from '$lib/components/Loading.svelte';
|
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
|
|
||||||
let loading = false;
|
|
||||||
let statusInterval: any = false;
|
let statusInterval: any = false;
|
||||||
|
|
||||||
$disabledButton = !$appSession.isAdmin;
|
$disabledButton = !$appSession.isAdmin;
|
||||||
@@ -72,36 +70,41 @@
|
|||||||
async function deleteDatabase() {
|
async function deleteDatabase() {
|
||||||
const sure = confirm(`Are you sure you would like to delete '${database.name}'?`);
|
const sure = confirm(`Are you sure you would like to delete '${database.name}'?`);
|
||||||
if (sure) {
|
if (sure) {
|
||||||
loading = true;
|
$status.database.initialLoading = true;
|
||||||
try {
|
try {
|
||||||
await del(`/databases/${database.id}`, { id: database.id });
|
await del(`/databases/${database.id}`, { id: database.id });
|
||||||
return await goto('/databases');
|
return await goto('/databases');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
} finally {
|
} finally {
|
||||||
loading = false;
|
$status.database.initialLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function stopDatabase() {
|
async function stopDatabase() {
|
||||||
const sure = confirm($t('database.confirm_stop', { name: database.name }));
|
const sure = confirm($t('database.confirm_stop', { name: database.name }));
|
||||||
if (sure) {
|
if (sure) {
|
||||||
loading = true;
|
$status.database.initialLoading = true;
|
||||||
try {
|
try {
|
||||||
await post(`/databases/${database.id}/stop`, {});
|
await post(`/databases/${database.id}/stop`, {});
|
||||||
return window.location.reload();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
|
} finally {
|
||||||
|
$status.database.initialLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function startDatabase() {
|
async function startDatabase() {
|
||||||
loading = true;
|
$status.database.initialLoading = true;
|
||||||
|
$status.database.loading = true;
|
||||||
try {
|
try {
|
||||||
await post(`/databases/${database.id}/start`, {});
|
await post(`/databases/${database.id}/start`, {});
|
||||||
return window.location.reload();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
|
} finally {
|
||||||
|
$status.database.initialLoading = false;
|
||||||
|
$status.database.loading = false;
|
||||||
|
await getStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function getStatus() {
|
async function getStatus() {
|
||||||
@@ -137,9 +140,6 @@
|
|||||||
|
|
||||||
{#if id !== 'new'}
|
{#if id !== 'new'}
|
||||||
<nav class="nav-side">
|
<nav class="nav-side">
|
||||||
{#if loading}
|
|
||||||
<Loading fullscreen cover />
|
|
||||||
{:else}
|
|
||||||
{#if database.type && database.destinationDockerId && database.version && database.defaultDatabase}
|
{#if database.type && database.destinationDockerId && database.version && database.defaultDatabase}
|
||||||
{#if $status.database.isExited}
|
{#if $status.database.isExited}
|
||||||
<a
|
<a
|
||||||
@@ -317,7 +317,6 @@
|
|||||||
? $t('database.delete_database')
|
? $t('database.delete_database')
|
||||||
: $t('database.permission_denied_delete_database')}><DeleteIcon /></button
|
: $t('database.permission_denied_delete_database')}><DeleteIcon /></button
|
||||||
>
|
>
|
||||||
{/if}
|
|
||||||
</nav>
|
</nav>
|
||||||
{/if}
|
{/if}
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
export let name = '';
|
export let name = '';
|
||||||
export let value = '';
|
export let value = '';
|
||||||
export let isNewSecret = false;
|
export let isNewSecret = false;
|
||||||
|
|||||||
@@ -56,7 +56,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
|
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
|
||||||
import Loading from '$lib/components/Loading.svelte';
|
|
||||||
import { del, get, post } from '$lib/api';
|
import { del, get, post } from '$lib/api';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { t } from '$lib/translations';
|
import { t } from '$lib/translations';
|
||||||
@@ -74,13 +73,12 @@
|
|||||||
!service.version ||
|
!service.version ||
|
||||||
!service.type;
|
!service.type;
|
||||||
|
|
||||||
let loading = false;
|
|
||||||
let statusInterval: any;
|
let statusInterval: any;
|
||||||
|
|
||||||
async function deleteService() {
|
async function deleteService() {
|
||||||
const sure = confirm($t('application.confirm_to_delete', { name: service.name }));
|
const sure = confirm($t('application.confirm_to_delete', { name: service.name }));
|
||||||
if (sure) {
|
if (sure) {
|
||||||
loading = true;
|
$status.service.initialLoading = true;
|
||||||
try {
|
try {
|
||||||
if (service.type && $status.service.isRunning)
|
if (service.type && $status.service.isRunning)
|
||||||
await post(`/services/${service.id}/${service.type}/stop`, {});
|
await post(`/services/${service.id}/${service.type}/stop`, {});
|
||||||
@@ -89,31 +87,36 @@
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
} finally {
|
} finally {
|
||||||
loading = false;
|
$status.service.initialLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function stopService() {
|
async function stopService() {
|
||||||
const sure = confirm($t('database.confirm_stop', { name: service.name }));
|
const sure = confirm($t('database.confirm_stop', { name: service.name }));
|
||||||
if (sure) {
|
if (sure) {
|
||||||
loading = true;
|
$status.service.initialLoading = true;
|
||||||
|
$status.service.loading = true;
|
||||||
try {
|
try {
|
||||||
await post(`/services/${service.id}/${service.type}/stop`, {});
|
await post(`/services/${service.id}/${service.type}/stop`, {});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
} finally {
|
} finally {
|
||||||
loading = false;
|
$status.service.initialLoading = false;
|
||||||
|
$status.service.loading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function startService() {
|
async function startService() {
|
||||||
loading = true;
|
$status.service.initialLoading = true;
|
||||||
|
$status.service.loading = true
|
||||||
try {
|
try {
|
||||||
await post(`/services/${service.id}/${service.type}/start`, {});
|
await post(`/services/${service.id}/${service.type}/start`, {});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
} finally {
|
} finally {
|
||||||
loading = false;
|
$status.service.initialLoading = false;
|
||||||
|
$status.service.loading = false;
|
||||||
|
await getStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function getStatus() {
|
async function getStatus() {
|
||||||
@@ -146,9 +149,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav class="nav-side">
|
<nav class="nav-side">
|
||||||
{#if loading}
|
|
||||||
<Loading fullscreen cover />
|
|
||||||
{:else}
|
|
||||||
{#if service.type && service.destinationDockerId && service.version}
|
{#if service.type && service.destinationDockerId && service.version}
|
||||||
{#if $location}
|
{#if $location}
|
||||||
<a
|
<a
|
||||||
@@ -409,6 +409,5 @@
|
|||||||
? $t('service.delete_service')
|
? $t('service.delete_service')
|
||||||
: $t('service.permission_denied_delete_service')}><DeleteIcon /></button
|
: $t('service.permission_denied_delete_service')}><DeleteIcon /></button
|
||||||
>
|
>
|
||||||
{/if}
|
|
||||||
</nav>
|
</nav>
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@@ -25,14 +25,47 @@
|
|||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { get } from '$lib/api';
|
import { get } from '$lib/api';
|
||||||
import { t } from '$lib/translations';
|
import { t } from '$lib/translations';
|
||||||
|
import pLimit from 'p-limit';
|
||||||
import ServiceLinks from './_ServiceLinks.svelte';
|
import ServiceLinks from './_ServiceLinks.svelte';
|
||||||
|
import { addToast } from '$lib/store';
|
||||||
|
import { saveSecret } from './utils';
|
||||||
|
const limit = pLimit(1);
|
||||||
|
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
|
let batchSecrets = '';
|
||||||
|
|
||||||
async function refreshSecrets() {
|
async function refreshSecrets() {
|
||||||
const data = await get(`/services/${id}/secrets`);
|
const data = await get(`/services/${id}/secrets`);
|
||||||
secrets = [...data.secrets];
|
secrets = [...data.secrets];
|
||||||
}
|
}
|
||||||
|
async function getValues(e: any) {
|
||||||
|
e.preventDefault();
|
||||||
|
const eachValuePair = batchSecrets.split('\n');
|
||||||
|
const batchSecretsPairs = eachValuePair
|
||||||
|
.filter((secret) => !secret.startsWith('#') && secret)
|
||||||
|
.map((secret) => {
|
||||||
|
const [name, ...rest] = secret.split('=');
|
||||||
|
const value = rest.join('=');
|
||||||
|
const cleanValue = value?.replaceAll('"', '') || '';
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
value: cleanValue,
|
||||||
|
isNew: !secrets.find((secret: any) => name === secret.name)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
batchSecretsPairs.map(({ name, value, isNew }) =>
|
||||||
|
limit(() => saveSecret({ name, value, serviceId: id, isNew }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
batchSecrets = '';
|
||||||
|
await refreshSecrets();
|
||||||
|
addToast({
|
||||||
|
message: 'Secrets saved.',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -93,4 +126,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<h2 class="title my-6 font-bold">Paste .env file</h2>
|
||||||
|
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
|
||||||
|
<textarea bind:value={batchSecrets} class="mb-2 min-h-[200px] w-full" />
|
||||||
|
<button class="btn btn-sm bg-applications" type="submit">Batch add secrets</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
42
apps/ui/src/routes/services/[id]/utils.ts
Normal file
42
apps/ui/src/routes/services/[id]/utils.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { post } from '$lib/api';
|
||||||
|
import { t } from '$lib/translations';
|
||||||
|
import { errorNotification } from '$lib/common';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isNew: boolean;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
isBuildSecret?: boolean;
|
||||||
|
isPRMRSecret?: boolean;
|
||||||
|
isNewSecret?: boolean;
|
||||||
|
serviceId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function saveSecret({
|
||||||
|
isNew,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
isBuildSecret,
|
||||||
|
isPRMRSecret,
|
||||||
|
isNewSecret,
|
||||||
|
serviceId
|
||||||
|
}: Props): Promise<void> {
|
||||||
|
if (!name) return errorNotification(`${t.get('forms.name')} ${t.get('forms.is_required')}`);
|
||||||
|
if (!value) return errorNotification(`${t.get('forms.value')} ${t.get('forms.is_required')}`);
|
||||||
|
try {
|
||||||
|
await post(`/services/${serviceId}/secrets`, {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
isBuildSecret,
|
||||||
|
isPRMRSecret,
|
||||||
|
isNew: isNew || false
|
||||||
|
});
|
||||||
|
if (isNewSecret) {
|
||||||
|
name = '';
|
||||||
|
value = '';
|
||||||
|
isBuildSecret = false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user