Add app configure location view
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
<script setup>
|
||||
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { Button, SingleSelect, InputGroup, FormGroup, TextInput } from 'pankow';
|
||||
import AppsModel from '../../models/AppsModel.js';
|
||||
import DomainsModel from '../../models/DomainsModel.js';
|
||||
|
||||
const props = defineProps([ 'app' ]);
|
||||
|
||||
const appsModel = AppsModel.create();
|
||||
const domainsModel = DomainsModel.create();
|
||||
|
||||
const domains = ref([]);
|
||||
const busy = ref(false);
|
||||
const errorMessage = ref('');
|
||||
const overwriteDns = ref(false);
|
||||
const needsOverwriteDns = ref(false);
|
||||
const domain = ref('');
|
||||
const subdomain = ref('');
|
||||
const provider = computed(() => {
|
||||
const d = domains.value.find(d => d.domain === domain.value);
|
||||
return d ? d.provider : '';
|
||||
});
|
||||
const secondaryDomains = ref({});
|
||||
const aliasDomains = ref([]);
|
||||
|
||||
function onAddAliasDomain() {
|
||||
aliasDomains.value.push({
|
||||
domain: '',
|
||||
subdomain: ''
|
||||
});
|
||||
}
|
||||
|
||||
function onRemoveAliasDomain(index) {
|
||||
aliasDomains.value.splice(index, 1);
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
busy.value = true;
|
||||
errorMessage.value = '';
|
||||
needsOverwriteDns.value = false;
|
||||
|
||||
const checkForDomains = [{
|
||||
domain: domain.value,
|
||||
subdomain: subdomain.value,
|
||||
}];
|
||||
|
||||
for (const d in secondaryDomains.value) checkForDomains.push({ domain: secondaryDomains.value[d].domain, subdomain: secondaryDomains.value[d].subdomain });
|
||||
for (const d of aliasDomains.value) checkForDomains.push({ domain: d.domain, subdomain: d.subdomain });
|
||||
|
||||
for (const d of checkForDomains) {
|
||||
const [error, result] = await domainsModel.checkRecords(d.domain, d.subdomain);
|
||||
if (error) {
|
||||
errorMessage.value = error.body ? error.body.message : 'Internal error';
|
||||
busy.value = false;
|
||||
return console.error(error);
|
||||
}
|
||||
if (result.needsOverwrite) return needsOverwriteDns.value = true;
|
||||
}
|
||||
|
||||
const data = {
|
||||
overwriteDns: overwriteDns.value,
|
||||
subdomain: subdomain.value,
|
||||
domain: domain.value,
|
||||
ports: {}, // TODO
|
||||
secondaryDomains: secondaryDomains.value,
|
||||
redirectDomains: [], // TODO
|
||||
aliasDomains: aliasDomains.value,
|
||||
};
|
||||
|
||||
const [error] = await appsModel.configure(props.app.id, 'location', data);
|
||||
if (error) {
|
||||
errorMessage.value = error.body ? error.body.message : 'Internal error';
|
||||
busy.value = false;
|
||||
return console.error(error);
|
||||
}
|
||||
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const [error, result] = await domainsModel.list();
|
||||
if (error) return console.error(error);
|
||||
|
||||
domains.value = result;
|
||||
|
||||
subdomain.value = props.app.subdomain;
|
||||
domain.value = props.app.domain;
|
||||
|
||||
// map manifest httpPorts into existing secondary domains from app
|
||||
secondaryDomains.value = props.app.manifest.httpPorts || {};
|
||||
for (const d of props.app.secondaryDomains) {
|
||||
if (!secondaryDomains.value[d.environmentVariable]) continue;
|
||||
secondaryDomains.value[d.environmentVariable].domain = d.domain;
|
||||
secondaryDomains.value[d.environmentVariable].subdomain = d.subdomain;
|
||||
}
|
||||
|
||||
aliasDomains.value = props.app.aliasDomains;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<form @submit.prevent="onSubmit()" autocomplete="off" novalidate>
|
||||
<fieldset :disabled="busy">
|
||||
<input type="submit" style="display: none;" :disabled="app.error || app.taskId"/>
|
||||
|
||||
<FormGroup>
|
||||
<label>{{ $t('app.location.location') }}</label>
|
||||
<div class="has-error" v-if="errorMessage">{{ errorMessage }}</div>
|
||||
|
||||
<InputGroup style="flex-grow: 1">
|
||||
<TextInput style="flex-grow: 1" v-model="subdomain" :placeholder="$t('app.location.locationPlaceholder')"/>
|
||||
<SingleSelect :disabled="busy" :options="domains" v-model="domain" option-key="domain" option-label="domain"/>
|
||||
</InputGroup>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup v-for="secondaryDomain in secondaryDomains" :key="secondaryDomain.containerPort">
|
||||
<label :for="'secondaryDomainInput' + secondaryDomain.containerPort">{{ secondaryDomain.title }}</label>
|
||||
<small>{{ secondaryDomain.description }}</small>
|
||||
<InputGroup style="flex-grow: 1">
|
||||
<TextInput style="flex-grow: 1" :id="'secondaryDomainInput' + secondaryDomain.containerPort" v-model="secondaryDomain.subdomain" :placeholder="$t('appstore.installDialog.locationPlaceholder')"/>
|
||||
<SingleSelect :disabled="busy" :options="domains" v-model="secondaryDomain.domain" option-key="domain" option-label="domain"/>
|
||||
</InputGroup>
|
||||
</FormGroup>
|
||||
|
||||
<div v-if="app.manifest.multiDomain">
|
||||
<label>{{ $t('app.location.aliases') }} <sup><a href="https://docs.cloudron.io/apps/#aliases" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
|
||||
<div style="display: flex; gap: 10px; margin-bottom: 10px" v-for="(aliasDomain, index) in aliasDomains" :key="aliasDomain">
|
||||
<InputGroup style="flex-grow: 1">
|
||||
<TextInput style="flex-grow: 1" v-model="aliasDomain.subdomain" :placeholder="$t('app.location.locationPlaceholder')"/>
|
||||
<SingleSelect :disabled="busy" :options="domains" v-model="aliasDomain.domain" option-key="domain" option-label="domain"/>
|
||||
</InputGroup>
|
||||
<Button danger tool :disabled="busy" icon="fa-solid fa-trash" @click="onRemoveAliasDomain(index)"/>
|
||||
</div>
|
||||
|
||||
<div class="actionable" v-if="!busy" @click="onAddAliasDomain()">{{ $t('app.location.addAliasAction') }}</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<p class="text-bold text-warning" v-if="provider === 'noop' || provider === 'manual'" v-html="$t('appstore.installDialog.manualWarning', { location: ((subdomain ? subdomain + '.' : '') + domain) })"></p>
|
||||
|
||||
<br/>
|
||||
|
||||
<Button @click="onSubmit()" :loading="busy" :disabled="busy || app.error || app.taskId" v-tooltip="app.error ? 'App is in error state' : (app.taskId ? 'App is busy' : '')">{{ $t('app.location.saveAction') }}</Button>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user