This commit is contained in:
Andras Bacsai 2022-10-26 14:12:27 +02:00
parent 0d12f3043b
commit dad3d42d14
7 changed files with 66 additions and 37 deletions

View File

@ -0,0 +1,11 @@
/*
Warnings:
- A unique constraint covering the columns `[serviceId,containerId,path]` on the table `ServicePersistentStorage` will be added. If there are existing duplicate values, this will fail.
*/
-- DropIndex
DROP INDEX "ServicePersistentStorage_serviceId_path_key";
-- CreateIndex
CREATE UNIQUE INDEX "ServicePersistentStorage_serviceId_containerId_path_key" ON "ServicePersistentStorage"("serviceId", "containerId", "path");

View File

@ -203,7 +203,7 @@ model ServicePersistentStorage {
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
service Service @relation(fields: [serviceId], references: [id]) service Service @relation(fields: [serviceId], references: [id])
@@unique([serviceId, path]) @@unique([serviceId, containerId, path])
} }
model Secret { model Secret {

View File

@ -75,12 +75,12 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
} }
} }
} }
const customVolumes = await prisma.servicePersistentStorage.findMany({ where: { serviceId: service } }) const customVolumes = await prisma.servicePersistentStorage.findMany({ where: { serviceId: id } })
let volumes = arm ? template.services[service].volumesArm : template.services[service].volumes let volumes = arm ? template.services[service].volumesArm : template.services[service].volumes
if (customVolumes.length > 0) { if (customVolumes.length > 0) {
for (const customVolume of customVolumes) { for (const customVolume of customVolumes) {
const { volumeName, path } = customVolume const { volumeName, path, containerId } = customVolume
if (!volumes.includes(`${volumeName}:${path}`)) { if (!volumes.includes(`${volumeName}:${path}`) && containerId === service) {
volumes.push(`${volumeName}:${path}`) volumes.push(`${volumeName}:${path}`)
} }
} }
@ -102,7 +102,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
labels: makeLabelForServices(type), labels: makeLabelForServices(type),
...defaultComposeConfiguration(network), ...defaultComposeConfiguration(network),
} }
// Generate files for builds // Generate files for builds
if (template.services[service]?.files?.length > 0) { if (template.services[service]?.files?.length > 0) {
if (!template.services[service].build) { if (!template.services[service].build) {

View File

@ -613,9 +613,8 @@ export async function saveServiceStorage(request: FastifyRequest<SaveServiceStor
export async function deleteServiceStorage(request: FastifyRequest<DeleteServiceStorage>) { export async function deleteServiceStorage(request: FastifyRequest<DeleteServiceStorage>) {
try { try {
const { id } = request.params const { storageId } = request.body
const { path } = request.body await prisma.servicePersistentStorage.deleteMany({ where: { id: storageId } });
await prisma.servicePersistentStorage.deleteMany({ where: { serviceId: id, path } });
return {} return {}
} catch ({ status, message }) { } catch ({ status, message }) {
return errorHandler({ status, message }) return errorHandler({ status, message })

View File

@ -74,7 +74,7 @@ export interface SaveServiceStorage extends OnlyId {
export interface DeleteServiceStorage extends OnlyId { export interface DeleteServiceStorage extends OnlyId {
Body: { Body: {
path: string, storageId: string,
} }
} }
export interface ServiceStartStop { export interface ServiceStartStop {

View File

@ -56,14 +56,20 @@
return errorNotification(error); return errorNotification(error);
} }
} }
async function removeStorage(path: string) { async function removeStorage(removableStorage: any) {
try { try {
await del(`/services/${id}/storages`, { path: storage.path }); const { id: storageId, volumeName, path } = removableStorage;
dispatch('refresh'); const sure = confirm(
addToast({ `Are you sure you want to delete this storage ${volumeName + ':' + path}?`
message: $t('application.storage.storage_deleted'), );
type: 'success' if (sure) {
}); await del(`/services/${id}/storages`, { storageId });
dispatch('refresh');
addToast({
message: $t('application.storage.storage_deleted'),
type: 'success'
});
}
} catch (error) { } catch (error) {
return errorNotification(error); return errorNotification(error);
} }
@ -97,13 +103,13 @@
{:else if isNew} {:else if isNew}
<form id="saveVolumesForm" on:submit|preventDefault={saveStorage}> <form id="saveVolumesForm" on:submit|preventDefault={saveStorage}>
<div class="grid grid-col-1 lg:grid-cols-2 lg:space-x-4 pt-8"> <div class="grid grid-col-1 lg:grid-cols-2 lg:space-x-4 pt-8">
<div class="flex flex-row gap-2"> <div class="flex flex-row">
<div class="flex flex-col"> <div class="flex flex-col w-full">
<label for="name" class="pb-2 uppercase font-bold">Container</label> <label for="name" class="pb-2 uppercase font-bold">Container</label>
<select <select
form="saveVolumesForm" form="saveVolumesForm"
name="containerId" name="containerId"
class="w-full lg:w-64 font-normal" class="w-full lg:w-64"
disabled={storage.predefined} disabled={storage.predefined}
readonly={storage.predefined} readonly={storage.predefined}
bind:value={storage.containerId} bind:value={storage.containerId}
@ -125,7 +131,7 @@
{/if} {/if}
</select> </select>
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col w-full">
<label for="name" class="pb-2 uppercase font-bold">Path</label> <label for="name" class="pb-2 uppercase font-bold">Path</label>
<input <input
name="path" name="path"
@ -138,21 +144,25 @@
/> />
</div> </div>
</div> </div>
<div class="pt-8"> <div class="pt-8">
<div class="flex items-center justify-center w-full lg:w-64"> <button type="submit" class="btn btn-sm btn-primary w-full lg:w-64"
<button type="submit" class="btn btn-sm btn-primary w-full">{$t('forms.add')}</button> >{$t('forms.add')}</button
</div> >
</div> </div>
</div> </div>
</form> </form>
{:else} {:else}
<div class="flex lg:flex-row flex-col items-center gap-2 py-1"> <div class="flex lg:flex-row flex-col items-center gap-2 py-1">
<input disabled readonly class="w-full" value={`${storage.containerId}`} /> <input
disabled
readonly
class="w-full"
value={`${services.find((s) => s.id === storage.containerId).name || storage.containerId}`}
/>
<input disabled readonly class="w-full" value={`${storage.volumeName}:${storage.path}`} /> <input disabled readonly class="w-full" value={`${storage.volumeName}:${storage.path}`} />
<button <button
class="btn btn-sm btn-error" class="btn btn-sm btn-error"
on:click|stopPropagation|preventDefault={() => removeStorage(storage.path)} on:click|stopPropagation|preventDefault={() => removeStorage(storage)}
>{$t('forms.remove')}</button >{$t('forms.remove')}</button
> >
</div> </div>

View File

@ -62,20 +62,29 @@
<div class="font-bold uppercase">Volume ID : Mount Dir</div> <div class="font-bold uppercase">Volume ID : Mount Dir</div>
</div> </div>
</div> </div>
{#each persistentStorages.filter((s) => s.predefined) as storage}
{#key storage.id}
<Storage on:refresh={refreshStorage} {storage} {services} />
{/key}
{/each}
{/if} {/if}
{#each persistentStorages.filter((s) => s.predefined) as storage}
{#key storage.id} {#if persistentStorages.filter((s) => !s.predefined).length > 0}
<Storage on:refresh={refreshStorage} {storage} {services} /> <div class="title" class:pt-10={persistentStorages.filter((s) => s.predefined).length > 0}>
{/key} Custom Volumes
{/each} </div>
{#each persistentStorages.filter((s) => !s.predefined) as storage}
{#key storage.id}
<Storage on:refresh={refreshStorage} {storage} {services} />
{/key}
{/each}
{/if}
<div class="title" class:pt-10={persistentStorages.filter((s) => s.predefined).length > 0}> <div class="title" class:pt-10={persistentStorages.filter((s) => s.predefined).length > 0}>
Custom Volumes Add New Volume
</div> </div>
{#each persistentStorages.filter((s) => !s.predefined) as storage}
{#key storage.id}
<Storage on:refresh={refreshStorage} {storage} />
{/key}
{/each}
<Storage on:refresh={refreshStorage} isNew {services} /> <Storage on:refresh={refreshStorage} isNew {services} />
</div> </div>
</div> </div>