fixes
This commit is contained in:
@@ -2,7 +2,12 @@
|
||||
export let type: string;
|
||||
export let isAbsolute = true;
|
||||
import * as Icons from '$lib/components/svg/services';
|
||||
const name: any = type && type[0].toUpperCase() + type.substring(1).toLowerCase();
|
||||
const name: any =
|
||||
type &&
|
||||
(type[0].toUpperCase() + type.substring(1).toLowerCase())
|
||||
.replaceAll('.', '')
|
||||
.replaceAll(' ', '')
|
||||
.split('-')[0];
|
||||
</script>
|
||||
|
||||
<svelte:component this={Icons[name.replace('.','').replaceAll(' ','')]} {isAbsolute} />
|
||||
<svelte:component this={Icons[name]} {isAbsolute} />
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"saving": "Saving...",
|
||||
"name": "Name",
|
||||
"value": "Value",
|
||||
"action": "Action",
|
||||
"action": "Actions",
|
||||
"is_required": "is required.",
|
||||
"add": "Add",
|
||||
"set": "Set",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
export let name = '';
|
||||
export let value = '';
|
||||
export let readonly = false;
|
||||
export let isNewSecret = false;
|
||||
|
||||
import { page } from '$app/stores';
|
||||
@@ -55,19 +56,20 @@
|
||||
bind:value={name}
|
||||
required
|
||||
placeholder="EXAMPLE_VARIABLE"
|
||||
readonly={!isNewSecret}
|
||||
readonly={!isNewSecret || readonly}
|
||||
class="w-full"
|
||||
class:bg-coolblack={!isNewSecret}
|
||||
class:border={!isNewSecret}
|
||||
class:border-dashed={!isNewSecret}
|
||||
class:border-coolgray-300={!isNewSecret}
|
||||
class:cursor-not-allowed={!isNewSecret}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<CopyPasswordField
|
||||
id={isNewSecret ? 'secretValue' : 'secretValueNew'}
|
||||
name={isNewSecret ? 'secretValue' : 'secretValueNew'}
|
||||
disabled={readonly}
|
||||
{readonly}
|
||||
isPasswordField={true}
|
||||
bind:value
|
||||
placeholder="J$#@UIO%HO#$U%H"
|
||||
@@ -80,7 +82,7 @@
|
||||
<div class="flex items-center justify-center">
|
||||
<button class="btn btn-sm btn-primary" on:click={() => saveSecret(true)}>Add</button>
|
||||
</div>
|
||||
{:else}
|
||||
{:else if !readonly}
|
||||
<div class="flex flex-row justify-center space-x-2">
|
||||
<div class="flex items-center justify-center">
|
||||
<button class="btn btn-sm btn-primary" on:click={() => saveSecret(false)}>Set</button>
|
||||
|
||||
86
apps/ui/src/routes/services/[id]/_Services/wordpress.svelte
Normal file
86
apps/ui/src/routes/services/[id]/_Services/wordpress.svelte
Normal file
@@ -0,0 +1,86 @@
|
||||
<script lang="ts">
|
||||
import { post } from '$lib/api';
|
||||
import { page } from '$app/stores';
|
||||
import { status } from '$lib/store';
|
||||
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
||||
import Setting from '$lib/components/Setting.svelte';
|
||||
import { browser } from '$app/env';
|
||||
import { errorNotification, getDomain } from '$lib/common';
|
||||
|
||||
export let service: any;
|
||||
const { id } = $page.params;
|
||||
const settings = service.settings;
|
||||
const { ipv4, ipv6 } = settings;
|
||||
|
||||
let ftpUrl = generateUrl(service.wordpress?.ftpPublicPort) || '';
|
||||
let ftpUser = service.wordpress?.ftpUser;
|
||||
let ftpPassword = service.wordpress?.ftpPassword;
|
||||
let ftpLoading = false;
|
||||
let ftpEnabled = service.wordpress?.ftpEnabled || false;
|
||||
|
||||
function generateUrl(publicPort: any) {
|
||||
return browser
|
||||
? `sftp://${settings?.fqdn ? getDomain(settings.fqdn) : ipv4 || ipv6}:${publicPort}`
|
||||
: 'Loading...';
|
||||
}
|
||||
async function changeSettings(name: any) {
|
||||
if (ftpLoading) return;
|
||||
if ($status.service.overallStatus === 'healthy') {
|
||||
ftpLoading = true;
|
||||
if (name === 'ftpEnabled') {
|
||||
ftpEnabled = !ftpEnabled;
|
||||
}
|
||||
|
||||
try {
|
||||
const {
|
||||
publicPort,
|
||||
ftpUser: user,
|
||||
ftpPassword: password
|
||||
} = await post(`/services/${id}/wordpress/ftp`, {
|
||||
ftpEnabled
|
||||
});
|
||||
ftpUrl = generateUrl(publicPort);
|
||||
ftpUser = user;
|
||||
ftpPassword = password;
|
||||
service.wordpress.ftpEnabled = ftpEnabled;
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
ftpLoading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
id="ftpEnabled"
|
||||
bind:setting={ftpEnabled}
|
||||
loading={ftpLoading}
|
||||
disabled={$status.service.overallStatus !== 'healthy'}
|
||||
on:click={() => changeSettings('ftpEnabled')}
|
||||
title="Enable sFTP connection to WordPress data"
|
||||
description="Enables an on-demand sFTP connection to the WordPress data directory. This is useful if you want to use sFTP to upload files."
|
||||
/>
|
||||
</div>
|
||||
{#if service.wordpress?.ftpEnabled}
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="ftpUrl">sFTP Connection URI</label>
|
||||
<CopyPasswordField id="ftpUrl" readonly disabled name="ftpUrl" value={ftpUrl} />
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="ftpUser">User</label>
|
||||
<CopyPasswordField id="ftpUser" readonly disabled name="ftpUser" value={ftpUser} />
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="ftpPassword">Password</label>
|
||||
<CopyPasswordField
|
||||
id="ftpPassword"
|
||||
isPasswordField
|
||||
readonly
|
||||
disabled
|
||||
name="ftpPassword"
|
||||
value={ftpPassword}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
async function handleSubmit(service: any) {
|
||||
try {
|
||||
await post(`/services/${id}/configuration/type`, { type: service.name });
|
||||
await post(`/services/${id}/configuration/type`, { type: service.type });
|
||||
return await goto(from || `/services/${id}`);
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
@@ -50,8 +50,8 @@
|
||||
function doSearch() {
|
||||
filteredServices = services.filter(
|
||||
(service: any) =>
|
||||
service.name.toLowerCase().includes(search.toLowerCase()) ||
|
||||
service.labels?.some((label: string) => label.toLowerCase().includes(search.toLowerCase()))
|
||||
service.name.toLowerCase().includes(search.toLowerCase()) ||
|
||||
service.labels?.some((label: string) => label.toLowerCase().includes(search.toLowerCase()))
|
||||
);
|
||||
}
|
||||
function cleanupSearch() {
|
||||
@@ -62,6 +62,7 @@
|
||||
|
||||
<div class="container lg:mx-auto lg:p-0 px-8 pt-5">
|
||||
<div class="input-group flex w-full">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="btn btn-square cursor-default no-animation hover:bg-error" on:click={cleanupSearch}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -91,15 +92,15 @@
|
||||
<div class="container lg:mx-auto lg:pt-20 lg:p-0 px-8 pt-20">
|
||||
<div class="flex flex-wrap justify-center gap-8">
|
||||
{#each filteredServices as service}
|
||||
{#key service.name}
|
||||
<div class="p-2">
|
||||
<form on:submit|preventDefault={() => handleSubmit(service)}>
|
||||
<button type="submit" class="box-selection relative text-xl font-bold hover:bg-primary">
|
||||
<ServiceIcons type={service.name} />
|
||||
{service.name}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{#key service.name}
|
||||
<div class="p-2">
|
||||
<form on:submit|preventDefault={() => handleSubmit(service)}>
|
||||
<button type="submit" class="box-selection relative text-xl font-bold hover:bg-primary">
|
||||
<ServiceIcons type={service.type} />
|
||||
{service.name}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{/key}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
import ServiceStatus from '$lib/components/ServiceStatus.svelte';
|
||||
import { saveForm } from './utils';
|
||||
import Select from 'svelte-select';
|
||||
import Wordpress from './_Services/wordpress.svelte';
|
||||
|
||||
const { id } = $page.params;
|
||||
$: isDisabled =
|
||||
@@ -86,7 +87,7 @@
|
||||
exposePort: service.exposePort
|
||||
});
|
||||
for (const setting of service.serviceSetting) {
|
||||
if (setting.variableName.startsWith('$$coolify_fqdn') && setting.value) {
|
||||
if (setting.variableName?.startsWith('$$coolify_fqdn') && setting.value) {
|
||||
for (let field of formData) {
|
||||
const [key, value] = field;
|
||||
if (setting.name === key) {
|
||||
@@ -413,7 +414,6 @@
|
||||
{template[oneService].name ||
|
||||
oneService.replace(`${id}-`, '').replace(id, service.type)}
|
||||
</div>
|
||||
|
||||
<ServiceStatus id={oneService} />
|
||||
</div>
|
||||
<div class="grid grid-flow-row gap-2 px-4">
|
||||
@@ -434,6 +434,8 @@
|
||||
name={variable.name}
|
||||
id={variable.name}
|
||||
value={service.fqdn}
|
||||
placeholder={variable.placeholder}
|
||||
required={variable?.required}
|
||||
/>
|
||||
{:else if variable.defaultValue === '$$generate_domain'}
|
||||
<CopyPasswordField
|
||||
@@ -442,6 +444,8 @@
|
||||
name={variable.name}
|
||||
id={variable.name}
|
||||
value={getDomain(service.fqdn) || ''}
|
||||
placeholder={variable.placeholder}
|
||||
required={variable?.required}
|
||||
/>
|
||||
{:else if variable.defaultValue === '$$generate_network'}
|
||||
<CopyPasswordField
|
||||
@@ -450,6 +454,8 @@
|
||||
name={variable.name}
|
||||
id={variable.name}
|
||||
value={service.destinationDocker.network}
|
||||
placeholder={variable.placeholder}
|
||||
required={variable?.required}
|
||||
/>
|
||||
{:else if variable.defaultValue === 'true' || variable.defaultValue === 'false'}
|
||||
{#if variable.value === 'true' || variable.value === 'false'}
|
||||
@@ -461,6 +467,8 @@
|
||||
name={variable.name}
|
||||
bind:value={variable.value}
|
||||
form="saveForm"
|
||||
placeholder={variable.placeholder}
|
||||
required={variable?.required}
|
||||
>
|
||||
<option value="true">enabled</option>
|
||||
<option value="false">disabled</option>
|
||||
@@ -474,6 +482,8 @@
|
||||
name={variable.name}
|
||||
bind:value={variable.defaultValue}
|
||||
form="saveForm"
|
||||
placeholder={variable.placeholder}
|
||||
required={variable?.required}
|
||||
>
|
||||
<option value="true">true</option>
|
||||
<option value="false"> false</option>
|
||||
@@ -487,21 +497,40 @@
|
||||
name={variable.name}
|
||||
id={variable.name}
|
||||
value={variable.value}
|
||||
placeholder={variable.placeholder}
|
||||
required={variable?.required}
|
||||
/>
|
||||
{:else if variable.type === 'textarea'}
|
||||
<textarea
|
||||
class="w-full"
|
||||
value={variable.value}
|
||||
readonly={isDisabled}
|
||||
disabled={isDisabled}
|
||||
class:resize-none={$status.service.overallStatus === 'healthy'}
|
||||
rows="5"
|
||||
name={variable.name}
|
||||
id={variable.name}
|
||||
placeholder={variable.placeholder}
|
||||
required={variable?.required}
|
||||
/>
|
||||
{:else}
|
||||
<CopyPasswordField
|
||||
placeholder={variable.defaultValue || 'optional'}
|
||||
isPasswordField={variable.id.startsWith('secret')}
|
||||
required={variable?.required}
|
||||
readonly={isDisabled}
|
||||
disabled={isDisabled}
|
||||
readonly={variable.readonly || isDisabled}
|
||||
disabled={variable.readonly || isDisabled}
|
||||
name={variable.name}
|
||||
id={variable.name}
|
||||
value={variable.value}
|
||||
placeholder={variable.placeholder}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{#if template[oneService].name.toLowerCase() === 'wordpress' && service.type.startsWith('wordpress')}
|
||||
<Wordpress {service} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
export let secrets: any;
|
||||
export let service: any;
|
||||
import Secret from './_Secret.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { get } from '$lib/api';
|
||||
@@ -84,7 +83,7 @@
|
||||
{#each secrets as secret}
|
||||
{#key secret.id}
|
||||
<tr>
|
||||
<Secret name={secret.name} value={secret.value} on:refresh={refreshSecrets} />
|
||||
<Secret name={secret.name} value={secret.value} readonly={secret.readonly} on:refresh={refreshSecrets} />
|
||||
</tr>
|
||||
{/key}
|
||||
{/each}
|
||||
|
||||
@@ -43,27 +43,36 @@ export async function saveSecret({
|
||||
|
||||
export async function saveForm(formData: any, service: any) {
|
||||
const settings = service.serviceSetting.map((setting: { name: string }) => setting.name);
|
||||
const secrets = service.serviceSecret.map((secret: { name: string }) => secret.name);
|
||||
const baseCoolifySetting = ['name', 'fqdn', 'exposePort', 'version'];
|
||||
for (let field of formData) {
|
||||
const [key, value] = field;
|
||||
service.serviceSetting = service.serviceSetting.map((setting: any) => {
|
||||
if (setting.name === key) {
|
||||
setting.changed = true;
|
||||
setting.value = value;
|
||||
}
|
||||
return setting;
|
||||
});
|
||||
if (!settings.includes(key) && !baseCoolifySetting.includes(key)) {
|
||||
service.serviceSetting.push({
|
||||
id: service.id,
|
||||
if (secrets.includes(key)) {
|
||||
await post(`/services/${service.id}/secrets`, {
|
||||
name: key,
|
||||
value: value,
|
||||
isNew: true
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
service.serviceSetting = service.serviceSetting.map((setting: any) => {
|
||||
if (setting.name === key) {
|
||||
setting.changed = true;
|
||||
setting.value = value;
|
||||
}
|
||||
return setting;
|
||||
});
|
||||
if (!settings.includes(key) && !baseCoolifySetting.includes(key)) {
|
||||
service.serviceSetting.push({
|
||||
id: service.id,
|
||||
name: key,
|
||||
value: value,
|
||||
isNew: true
|
||||
});
|
||||
}
|
||||
if (baseCoolifySetting.includes(key)) {
|
||||
service[key] = value;
|
||||
}
|
||||
}
|
||||
if (baseCoolifySetting.includes(key)) {
|
||||
service[key] = value;
|
||||
}
|
||||
|
||||
}
|
||||
await post(`/services/${service.id}`, { ...service });
|
||||
const { service: reloadedService } = await get(`/services/${service.id}`);
|
||||
|
||||
Reference in New Issue
Block a user