feat: Secrets for previews
UI: Some CSS changes
This commit is contained in:
parent
cab7ac7d58
commit
7c683668eb
@ -9,7 +9,8 @@ export default async function ({
|
||||
docker,
|
||||
buildId,
|
||||
baseDirectory,
|
||||
secrets
|
||||
secrets,
|
||||
pullmergeRequestId
|
||||
}) {
|
||||
try {
|
||||
let file = `${workdir}/Dockerfile`;
|
||||
@ -24,8 +25,16 @@ export default async function ({
|
||||
if (secrets.length > 0) {
|
||||
secrets.forEach((secret) => {
|
||||
if (secret.isBuildSecret) {
|
||||
if (pullmergeRequestId) {
|
||||
if (secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
} else {
|
||||
if (!secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
await fs.writeFile(`${file}`, Dockerfile.join('\n'));
|
||||
|
@ -2,8 +2,16 @@ import { buildImage } from '$lib/docker';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
const createDockerfile = async (data, image): Promise<void> => {
|
||||
const { workdir, port, installCommand, buildCommand, startCommand, baseDirectory, secrets } =
|
||||
data;
|
||||
const {
|
||||
workdir,
|
||||
port,
|
||||
installCommand,
|
||||
buildCommand,
|
||||
startCommand,
|
||||
baseDirectory,
|
||||
secrets,
|
||||
pullmergeRequestId
|
||||
} = data;
|
||||
const Dockerfile: Array<string> = [];
|
||||
|
||||
Dockerfile.push(`FROM ${image}`);
|
||||
@ -11,8 +19,16 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
if (secrets.length > 0) {
|
||||
secrets.forEach((secret) => {
|
||||
if (secret.isBuildSecret) {
|
||||
if (pullmergeRequestId) {
|
||||
if (secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
} else {
|
||||
if (!secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Dockerfile.push(`COPY ./${baseDirectory || ''}package*.json ./`);
|
||||
|
@ -2,8 +2,16 @@ import { buildImage } from '$lib/docker';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
const createDockerfile = async (data, image): Promise<void> => {
|
||||
const { workdir, port, installCommand, buildCommand, startCommand, baseDirectory, secrets } =
|
||||
data;
|
||||
const {
|
||||
workdir,
|
||||
port,
|
||||
installCommand,
|
||||
buildCommand,
|
||||
startCommand,
|
||||
baseDirectory,
|
||||
secrets,
|
||||
pullmergeRequestId
|
||||
} = data;
|
||||
const Dockerfile: Array<string> = [];
|
||||
|
||||
Dockerfile.push(`FROM ${image}`);
|
||||
@ -11,8 +19,16 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
if (secrets.length > 0) {
|
||||
secrets.forEach((secret) => {
|
||||
if (secret.isBuildSecret) {
|
||||
if (pullmergeRequestId) {
|
||||
if (secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
} else {
|
||||
if (!secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Dockerfile.push(`COPY ./${baseDirectory || ''}package*.json ./`);
|
||||
|
@ -2,8 +2,16 @@ import { buildImage } from '$lib/docker';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
const createDockerfile = async (data, image): Promise<void> => {
|
||||
const { workdir, port, installCommand, buildCommand, startCommand, baseDirectory, secrets } =
|
||||
data;
|
||||
const {
|
||||
workdir,
|
||||
port,
|
||||
installCommand,
|
||||
buildCommand,
|
||||
startCommand,
|
||||
baseDirectory,
|
||||
secrets,
|
||||
pullmergeRequestId
|
||||
} = data;
|
||||
const Dockerfile: Array<string> = [];
|
||||
|
||||
Dockerfile.push(`FROM ${image}`);
|
||||
@ -11,8 +19,16 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
if (secrets.length > 0) {
|
||||
secrets.forEach((secret) => {
|
||||
if (secret.isBuildSecret) {
|
||||
if (pullmergeRequestId) {
|
||||
if (secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
} else {
|
||||
if (!secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Dockerfile.push(`COPY ./${baseDirectory || ''}package*.json ./`);
|
||||
|
@ -2,8 +2,16 @@ import { buildCacheImageWithNode, buildImage } from '$lib/docker';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
const createDockerfile = async (data, image): Promise<void> => {
|
||||
const { applicationId, tag, workdir, buildCommand, baseDirectory, publishDirectory, secrets } =
|
||||
data;
|
||||
const {
|
||||
applicationId,
|
||||
tag,
|
||||
workdir,
|
||||
buildCommand,
|
||||
baseDirectory,
|
||||
publishDirectory,
|
||||
secrets,
|
||||
pullmergeRequestId
|
||||
} = data;
|
||||
const Dockerfile: Array<string> = [];
|
||||
|
||||
Dockerfile.push(`FROM ${image}`);
|
||||
@ -11,8 +19,16 @@ const createDockerfile = async (data, image): Promise<void> => {
|
||||
if (secrets.length > 0) {
|
||||
secrets.forEach((secret) => {
|
||||
if (secret.isBuildSecret) {
|
||||
if (pullmergeRequestId) {
|
||||
if (secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
} else {
|
||||
if (!secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (buildCommand) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
<script>
|
||||
import { browser } from '$app/env';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
export let value;
|
||||
let showPassword = false;
|
||||
|
||||
export let value;
|
||||
export let disabled = false;
|
||||
export let isPasswordField = false;
|
||||
export let readonly = false;
|
||||
@ -14,7 +14,7 @@
|
||||
export let name;
|
||||
export let placeholder = '';
|
||||
|
||||
let disabledClass = 'bg-coolback disabled:bg-coolblack select-all';
|
||||
let disabledClass = 'bg-coolback disabled:bg-coolblack';
|
||||
let actionsShow = false;
|
||||
let isHttps = browser && window.location.protocol === 'https:';
|
||||
|
||||
@ -29,11 +29,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="relative"
|
||||
on:mouseenter={() => showActions(true)}
|
||||
on:mouseleave={() => showActions(false)}
|
||||
>
|
||||
<div class="relative">
|
||||
{#if !isPasswordField || showPassword}
|
||||
{#if textarea}
|
||||
<textarea
|
||||
@ -77,7 +73,6 @@
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if actionsShow}
|
||||
<div class="absolute top-0 right-0 m-3 cursor-pointer text-warmGray-600 hover:text-white">
|
||||
<div class="flex space-x-2">
|
||||
{#if isPasswordField}
|
||||
@ -141,5 +136,4 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -18,7 +18,6 @@ export const buildPacks = [
|
||||
|
||||
{
|
||||
name: 'static',
|
||||
...defaultBuildAndDeploy,
|
||||
publishDirectory: 'dist',
|
||||
port: 80,
|
||||
fancyName: 'Static',
|
||||
|
@ -1,11 +1,17 @@
|
||||
import { encrypt } from '$lib/crypto';
|
||||
import { encrypt, decrypt } from '$lib/crypto';
|
||||
import { prisma } from './common';
|
||||
|
||||
export async function listSecrets(applicationId: string) {
|
||||
return await prisma.secret.findMany({
|
||||
let secrets = await prisma.secret.findMany({
|
||||
where: { applicationId },
|
||||
orderBy: { createdAt: 'desc' }
|
||||
});
|
||||
secrets = secrets.map((secret) => {
|
||||
secret.value = decrypt(secret.value);
|
||||
return secret;
|
||||
});
|
||||
|
||||
return secrets;
|
||||
}
|
||||
|
||||
export async function createSecret({ id, name, value, isBuildSecret, isPRMRSecret }) {
|
||||
@ -18,6 +24,8 @@ export async function createSecret({ id, name, value, isBuildSecret, isPRMRSecre
|
||||
export async function updateSecret({ id, name, value, isBuildSecret, isPRMRSecret }) {
|
||||
value = encrypt(value);
|
||||
const found = await prisma.secret.findFirst({ where: { applicationId: id, name, isPRMRSecret } });
|
||||
console.log(found);
|
||||
|
||||
if (found) {
|
||||
return await prisma.secret.updateMany({
|
||||
where: { applicationId: id, name, isPRMRSecret },
|
||||
|
@ -13,16 +13,25 @@ export async function buildCacheImageWithNode(data, imageForBuild) {
|
||||
installCommand,
|
||||
buildCommand,
|
||||
debug,
|
||||
secrets
|
||||
secrets,
|
||||
pullmergeRequestId
|
||||
} = data;
|
||||
const Dockerfile: Array<string> = [];
|
||||
Dockerfile.push(`FROM ${imageForBuild}`);
|
||||
Dockerfile.push('WORKDIR /usr/src/app');
|
||||
if (secrets.length > 0) {
|
||||
secrets.forEach((secret) => {
|
||||
if (!secret.isBuildSecret) {
|
||||
if (secret.isBuildSecret) {
|
||||
if (pullmergeRequestId) {
|
||||
if (secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
} else {
|
||||
if (!secret.isPRMRSecret) {
|
||||
Dockerfile.push(`ARG ${secret.name} ${secret.value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// TODO: If build command defined, install command should be the default yarn install
|
||||
|
@ -64,7 +64,6 @@ export default async function (job) {
|
||||
if (destinationDockerId) {
|
||||
destinationType = 'docker';
|
||||
}
|
||||
|
||||
if (destinationType === 'docker') {
|
||||
const docker = dockerInstance({ destinationDocker });
|
||||
const host = getEngine(destinationDocker.engine);
|
||||
@ -205,7 +204,15 @@ export default async function (job) {
|
||||
const envs = [];
|
||||
if (secrets.length > 0) {
|
||||
secrets.forEach((secret) => {
|
||||
if (pullmergeRequestId) {
|
||||
if (secret.isPRMRSecret) {
|
||||
envs.push(`${secret.name}=${secret.value}`);
|
||||
}
|
||||
} else {
|
||||
if (!secret.isPRMRSecret) {
|
||||
envs.push(`${secret.name}=${secret.value}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
await fs.writeFile(`${workdir}/.env`, envs.join('\n'));
|
||||
|
@ -197,7 +197,7 @@
|
||||
value={application.gitSource.name}
|
||||
id="gitSource"
|
||||
disabled
|
||||
class="cursor-pointer bg-coolgray-200 hover:bg-coolgray-500"
|
||||
class="cursor-pointer hover:bg-coolgray-500"
|
||||
/></a
|
||||
>
|
||||
</div>
|
||||
@ -214,7 +214,7 @@
|
||||
value="{application.repository}/{application.branch}"
|
||||
id="repository"
|
||||
disabled
|
||||
class="cursor-pointer bg-coolgray-200 hover:bg-coolgray-500"
|
||||
class="cursor-pointer hover:bg-coolgray-500"
|
||||
/></a
|
||||
>
|
||||
</div>
|
||||
@ -232,7 +232,7 @@
|
||||
value={application.buildPack}
|
||||
id="buildPack"
|
||||
disabled
|
||||
class="cursor-pointer bg-coolgray-200 hover:bg-coolgray-500"
|
||||
class="cursor-pointe hover:bg-coolgray-500"
|
||||
/></a
|
||||
>
|
||||
</div>
|
||||
|
@ -39,8 +39,12 @@ export const get: RequestHandler = async (event) => {
|
||||
return {
|
||||
body: {
|
||||
containers: jsonContainers,
|
||||
applicationSecrets,
|
||||
PRMRSecrets
|
||||
applicationSecrets: applicationSecrets.sort((a, b) => {
|
||||
return ('' + a.name).localeCompare(b.name);
|
||||
}),
|
||||
PRMRSecrets: PRMRSecrets.sort((a, b) => {
|
||||
return ('' + a.name).localeCompare(b.name);
|
||||
})
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
import Secret from '../secrets/_Secret.svelte';
|
||||
import { get } from '$lib/api';
|
||||
import { page } from '$app/stores';
|
||||
import Explainer from '$lib/components/Explainer.svelte';
|
||||
|
||||
const { id } = $page.params;
|
||||
async function refreshSecrets() {
|
||||
@ -41,10 +42,7 @@
|
||||
Previews for <a href={application.fqdn} target="_blank">{getDomain(application.fqdn)}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
Preview secrets. They will overwrite application secrets for PR/MR deployments. Useful for
|
||||
creating staging environments for these deployments.
|
||||
</div>
|
||||
|
||||
<div class="mx-auto max-w-6xl rounded-xl px-6 pt-4">
|
||||
<table class="mx-auto">
|
||||
<thead class=" rounded-xl border-b border-coolgray-500">
|
||||
@ -72,24 +70,29 @@
|
||||
<tbody class="">
|
||||
{#each applicationSecrets as secret}
|
||||
{#key secret.id}
|
||||
<tr class="hover:bg-coolgray-200">
|
||||
<tr class="h-20 transition duration-100 hover:bg-coolgray-400">
|
||||
<Secret
|
||||
PRMRSecret={PRMRSecrets.find((s) => s.name === secret.name)}
|
||||
isPRMRSecret
|
||||
name={secret.name}
|
||||
value={secret.value ? secret.value : 'ENCRYPTED'}
|
||||
value={secret.value}
|
||||
isBuildSecret={secret.isBuildSecret}
|
||||
on:refresh={refreshSecrets}
|
||||
/>
|
||||
</tr>
|
||||
{/key}
|
||||
{/each}
|
||||
<!-- <tr>
|
||||
<Secret isPRMRSecret isNewSecret on:refresh={refreshSecrets} />
|
||||
</tr> -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="flex justify-center py-4 text-center">
|
||||
<Explainer
|
||||
customClass="w-full"
|
||||
text={applicationSecrets.length === 0
|
||||
? "<span class='font-bold text-white text-xl'>Please add secrets to the application first.</span> <br><br>These values overwrite application secrets in PR/MR deployments. Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."
|
||||
: "These values overwrite application secrets in PR/MR deployments. Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."}
|
||||
/>
|
||||
</div>
|
||||
<div class="mx-auto max-w-4xl py-10">
|
||||
<div class="flex flex-wrap justify-center space-x-2">
|
||||
{#if containers.length > 0}
|
||||
|
@ -10,12 +10,12 @@
|
||||
|
||||
import { page } from '$app/stores';
|
||||
import { del, post } from '$lib/api';
|
||||
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
||||
import { errorNotification } from '$lib/form';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let nameEl;
|
||||
let valueEl;
|
||||
const { id } = $page.params;
|
||||
async function removeSecret() {
|
||||
try {
|
||||
@ -30,24 +30,24 @@
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
async function saveSecret() {
|
||||
const nameValid = nameEl.checkValidity();
|
||||
const valueValid = valueEl.checkValidity();
|
||||
if (!nameValid) {
|
||||
return nameEl.reportValidity();
|
||||
}
|
||||
if (!valueValid) {
|
||||
return valueEl.reportValidity();
|
||||
}
|
||||
|
||||
async function saveSecret(isNew = false) {
|
||||
if (!name) return errorNotification('Name is required.');
|
||||
if (!value) return errorNotification('Value is required.');
|
||||
try {
|
||||
await post(`/applications/${id}/secrets.json`, { name, value, isBuildSecret, isPRMRSecret });
|
||||
await post(`/applications/${id}/secrets.json`, {
|
||||
name,
|
||||
value,
|
||||
isBuildSecret,
|
||||
isPRMRSecret,
|
||||
isNew
|
||||
});
|
||||
dispatch('refresh');
|
||||
if (isNewSecret) {
|
||||
name = '';
|
||||
value = '';
|
||||
isBuildSecret = false;
|
||||
}
|
||||
toast.push('Secret saved.');
|
||||
} catch ({ error }) {
|
||||
return errorNotification(error);
|
||||
}
|
||||
@ -61,8 +61,7 @@
|
||||
|
||||
<td class="whitespace-nowrap px-6 py-2 text-sm font-medium text-white">
|
||||
<input
|
||||
id="secretName"
|
||||
bind:this={nameEl}
|
||||
id={isNewSecret ? 'secretName' : 'secretNameNew'}
|
||||
bind:value={name}
|
||||
required
|
||||
placeholder="EXAMPLE_VARIABLE"
|
||||
@ -73,16 +72,13 @@
|
||||
/>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-6 py-2 text-sm font-medium text-white">
|
||||
<input
|
||||
id="secretValue"
|
||||
<CopyPasswordField
|
||||
id={isNewSecret ? 'secretValue' : 'secretValueNew'}
|
||||
name={isNewSecret ? 'secretValue' : 'secretValueNew'}
|
||||
isPasswordField={true}
|
||||
bind:value
|
||||
bind:this={valueEl}
|
||||
required
|
||||
placeholder="J$#@UIO%HO#$U%H"
|
||||
class="-mx-2 w-64 border-2 border-transparent"
|
||||
class:bg-transparent={!isNewSecret && !isPRMRSecret}
|
||||
class:cursor-not-allowed={!isNewSecret && !isPRMRSecret}
|
||||
readonly={!isNewSecret && !isPRMRSecret}
|
||||
/>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-6 py-2 text-center text-sm font-medium text-white">
|
||||
@ -137,15 +133,20 @@
|
||||
<td class="whitespace-nowrap px-6 py-2 text-sm font-medium text-white">
|
||||
{#if isNewSecret}
|
||||
<div class="flex items-center justify-center">
|
||||
<button class="w-24 bg-green-600 hover:bg-green-500" on:click={saveSecret}>Add</button>
|
||||
</div>
|
||||
{:else if isPRMRSecret}
|
||||
<div class="flex items-center justify-center">
|
||||
<button class="w-24 bg-green-600 hover:bg-green-500" on:click={saveSecret}>Set</button>
|
||||
<button class="bg-green-600 hover:bg-green-500" on:click={() => saveSecret(true)}>Add</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex-col space-y-2">
|
||||
<div class="flex items-center justify-center">
|
||||
<button class="w-24 bg-green-600 hover:bg-green-500" on:click={() => saveSecret(false)}
|
||||
>Set</button
|
||||
>
|
||||
</div>
|
||||
{#if !isPRMRSecret}
|
||||
<div class="flex justify-center items-end">
|
||||
<button class="w-24 bg-red-600 hover:bg-red-500" on:click={removeSecret}>Remove</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</td>
|
||||
|
@ -28,10 +28,9 @@ export const post: RequestHandler = async (event) => {
|
||||
if (status === 401) return { status, body };
|
||||
|
||||
const { id } = event.params;
|
||||
const { name, value, isBuildSecret, isPRMRSecret } = await event.request.json();
|
||||
|
||||
const { name, value, isBuildSecret, isPRMRSecret, isNew } = await event.request.json();
|
||||
try {
|
||||
if (!isPRMRSecret) {
|
||||
if (isNew) {
|
||||
const found = await db.isSecretExists({ id, name, isPRMRSecret });
|
||||
if (found) {
|
||||
throw {
|
||||
|
@ -67,10 +67,10 @@
|
||||
<tbody class="">
|
||||
{#each secrets as secret}
|
||||
{#key secret.id}
|
||||
<tr class="hover:bg-coolgray-200">
|
||||
<tr class="h-20 transition duration-100 hover:bg-coolgray-400">
|
||||
<Secret
|
||||
name={secret.name}
|
||||
value={secret.value ? secret.value : 'ENCRYPTED'}
|
||||
value={secret.value}
|
||||
isBuildSecret={secret.isBuildSecret}
|
||||
on:refresh={refreshSecrets}
|
||||
/>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="flex space-x-1 py-5 font-bold">
|
||||
<div class="title">CouchDB</div>
|
||||
</div>
|
||||
<div class="px-10">
|
||||
<div class="space-y-2 px-10">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="defaultDatabase">Default Database</label>
|
||||
<CopyPasswordField
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="flex space-x-1 py-5 font-bold">
|
||||
<div class="title">MongoDB</div>
|
||||
</div>
|
||||
<div class="px-10">
|
||||
<div class="space-y-2 px-10">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="rootUser">Root User</label>
|
||||
<CopyPasswordField
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="flex space-x-1 py-5 font-bold">
|
||||
<div class="title">MySQL</div>
|
||||
</div>
|
||||
<div class=" px-10">
|
||||
<div class="space-y-2 px-10">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="defaultDatabase">Default Database</label>
|
||||
<CopyPasswordField
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="flex space-x-1 py-5 font-bold">
|
||||
<div class="title">PostgreSQL</div>
|
||||
</div>
|
||||
<div class="px-10">
|
||||
<div class="space-y-2 px-10">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="defaultDatabase">Default Database</label>
|
||||
<CopyPasswordField
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="flex space-x-1 py-5 font-bold">
|
||||
<div class="title">Redis</div>
|
||||
</div>
|
||||
<div class="px-10">
|
||||
<div class="space-y-2 px-10">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="dbUserPassword">Password</label>
|
||||
<CopyPasswordField
|
||||
|
@ -7,7 +7,7 @@
|
||||
<div class="flex space-x-1 py-5 font-bold">
|
||||
<div class="title">MinIO Server</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="rootUser">Root User</label>
|
||||
<input
|
||||
name="rootUser"
|
||||
@ -18,7 +18,7 @@
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="rootUserPassword">Root's Password</label>
|
||||
<CopyPasswordField
|
||||
id="rootUserPassword"
|
||||
@ -29,7 +29,7 @@
|
||||
value={service.minio.rootUserPassword}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="publicPort">API Port</label>
|
||||
<input
|
||||
name="publicPort"
|
||||
|
@ -159,7 +159,7 @@
|
||||
: browser && 'http://' + window.location.hostname + ':8404'
|
||||
} target="_blank">stats</a> page.`}
|
||||
/>
|
||||
<div class="px-10 py-5">
|
||||
<div class="space-y-2 px-10 py-5">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="proxyUser">User</label>
|
||||
<CopyPasswordField
|
||||
|
@ -35,10 +35,10 @@ main,
|
||||
}
|
||||
|
||||
input {
|
||||
@apply h-12 w-96 select-all rounded border border-transparent bg-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:bg-transparent md:text-sm;
|
||||
@apply h-12 w-96 rounded border border-transparent bg-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:border disabled:border-dashed disabled:border-coolgray-300 disabled:bg-transparent md:text-sm;
|
||||
}
|
||||
textarea {
|
||||
@apply w-96 select-all rounded border border-transparent bg-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:bg-transparent md:text-sm;
|
||||
@apply w-96 rounded border border-transparent bg-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:border disabled:border-dashed disabled:border-coolgray-300 disabled:bg-transparent md:text-sm;
|
||||
}
|
||||
|
||||
select {
|
||||
|
Loading…
x
Reference in New Issue
Block a user