Add prettier and run prettier command via lint-staged (#448)

This commit is contained in:
Nihal Maskey
2023-10-16 20:07:16 +05:45
committed by GitHub
parent c908a32448
commit dbc954e7f1
186 changed files with 4263 additions and 1409 deletions

View File

@@ -30,51 +30,86 @@ THE SOFTWARE.
<template #description>
{{ $t('templates.app.description') }}
</template>
<template #header>
</template>
<template #header></template>
<template #buttons>
<VueSelect
v-model="lang"
:options="i18nPacks"
:clearable="false"
:reduce="s => s.value"
:reduce="(s) => s.value"
:disabled="languageLoading"
>
<template #selected-option="{ label }">
<span class="has-icon">
<i v-if="languageLoading" class="icon fas fa-spinner fa-pulse"></i>
<i v-else class="icon fas fa-language"></i>
<i
v-if="languageLoading"
class="icon fas fa-spinner fa-pulse"
></i>
<i
v-else
class="icon fas fa-language"
></i>
<span>{{ label }}</span>
</span>
</template>
</VueSelect>
<a v-if="splitColumn" class="button is-primary is-outline is-hidden-touch" @click="splitColumnToggle">
<a
v-if="splitColumn"
class="button is-primary is-outline is-hidden-touch"
@click="splitColumnToggle"
>
{{ $t('templates.app.singleColumnMode') }}
</a>
<a v-else class="button is-primary is-hidden-touch" @click="splitColumnToggle">
<a
v-else
class="button is-primary is-hidden-touch"
@click="splitColumnToggle"
>
{{ $t('templates.app.splitColumnMode') }}
</a>
</template>
</Header>
<div class="main container" :style="{ display: ready ? undefined : 'none' }">
<div
class="main container"
:style="{ display: ready ? undefined : 'none' }"
>
<div class="columns is-multiline">
<div :class="`column ${splitColumn ? 'is-half column-scroll-y' : 'is-full'} is-full-touch`">
<div
:class="`column ${
splitColumn ? 'is-half column-scroll-y' : 'is-full'
} is-full-touch`"
>
<h2>{{ $t('templates.app.perWebsiteConfig') }}</h2>
<div class="tabs">
<ul>
<li v-for="data in activeDomains" :class="data[1] === active ? 'is-active' : undefined">
<a class="domain" @click="active = data[1]">
<li
v-for="data in activeDomains"
:class="data[1] === active ? 'is-active' : undefined"
>
<a
class="domain"
@click="active = data[1]"
>
{{ data[0].server.domain.computed }}{{ changes(data[1]) }}
<i v-if="warnings(data[1])" class="fas fa-exclamation-triangle"></i>
<i
v-if="warnings(data[1])"
class="fas fa-exclamation-triangle"
></i>
</a>
<a class="remove" @click="remove(data[1])">
<a
class="remove"
@click="remove(data[1])"
>
<i class="fas fa-times"></i>
</a>
</li>
<li>
<a @click="add"><i class="fas fa-plus"></i> {{ $t('templates.app.addSite') }}</a>
<a @click="add">
<i class="fas fa-plus"></i>
{{ $t('templates.app.addSite') }}
</a>
</li>
</ul>
</div>
@@ -93,12 +128,21 @@ THE SOFTWARE.
<DropletCallout></DropletCallout>
<h2>{{ $t('templates.app.setup') }}</h2>
<Setup :data="{ domains: domains.filter(d => d !== null), global, confFiles }"></Setup>
<Setup
:data="{ domains: domains.filter((d) => d !== null), global, confFiles }"
></Setup>
</div>
<div :class="`column ${splitColumn ? 'is-half column-scroll-y' : 'is-full'} is-full-touch`">
<div
:class="`column ${
splitColumn ? 'is-half column-scroll-y' : 'is-full'
} is-full-touch`"
>
<h2>{{ $t('templates.app.configFiles') }}</h2>
<div ref="files" class="columns is-multiline files">
<div
ref="files"
class="columns is-multiline files"
>
<component
:is="getPrismComponent(confContents[0])"
v-for="confContents in confFilesOutput"
@@ -189,31 +233,42 @@ THE SOFTWARE.
},
computed: {
activeDomains() {
return this.$data.domains.map((domain, index) => [domain, index]).filter(d => d[0] !== null);
return this.$data.domains
.map((domain, index) => [domain, index])
.filter((d) => d[0] !== null);
},
confFiles() {
return generators(this.$data.domains.filter(d => d !== null), this.$data.global);
return generators(
this.$data.domains.filter((d) => d !== null),
this.$data.global,
);
},
confFilesWithDirectory() {
return Object.entries(this.confFiles).reduce((obj, [ file, content ]) => ({
...obj,
[`${this.$data.global.nginx.nginxConfigDirectory.computed}/${file}`]: content,
}), {});
return Object.entries(this.confFiles).reduce(
(obj, [file, content]) => ({
...obj,
[`${this.$data.global.nginx.nginxConfigDirectory.computed}/${file}`]:
content,
}),
{},
);
},
lang: {
get() {
return this.$data.global.app.lang.value;
},
set (value) {
set(value) {
this.$data.global.app.lang.value = value;
this.$data.global.app.lang.computed = value;
},
},
i18nPacks() {
return availablePacks.map(pack => ({
label: this.$t(`languages.${pack}`) + (pack === this.$i18n.locale
? ''
: ` - ${this.$t(`languages.${pack}`, pack)}`),
return availablePacks.map((pack) => ({
label:
this.$t(`languages.${pack}`) +
(pack === this.$i18n.locale
? ''
: ` - ${this.$t(`languages.${pack}`, pack)}`),
value: pack,
}));
},
@@ -241,23 +296,25 @@ THE SOFTWARE.
if (!availablePacks.includes(data.value)) data.computed = data.default;
// Update the locale
setLanguagePack(data.computed).then(() => {
// Done
info('Language set to', data.computed);
this.$data.languagePrevious = data.computed;
this.$data.languageLoading = false;
setLanguagePack(data.computed)
.then(() => {
// Done
info('Language set to', data.computed);
this.$data.languagePrevious = data.computed;
this.$data.languageLoading = false;
// Analytics
this.languageSetEvent(!interactive);
}).catch((err) => {
// Error
error(`Failed to set language to ${data.computed}`, err);
// Analytics
this.languageSetEvent(!interactive);
})
.catch((err) => {
// Error
error(`Failed to set language to ${data.computed}`, err);
// Fallback to last known good
data.value = this.$data.languagePrevious;
data.computed = this.$data.languagePrevious;
this.$data.languageLoading = false;
});
// Fallback to last known good
data.value = this.$data.languagePrevious;
data.computed = this.$data.languagePrevious;
this.$data.languageLoading = false;
});
},
deep: true,
},
@@ -267,10 +324,20 @@ THE SOFTWARE.
// Fallback to the window hash if no search query params, from the Angular version of nginxconfig
// The config file watcher will handle setting the app as ready
const query = window.location.search || window.location.hash.slice(1);
const imported = await importData(query, this.$data.domains, this.$data.global, this.$nextTick);
const imported = await importData(
query,
this.$data.domains,
this.$data.global,
this.$nextTick,
);
// Apply browser language if not specified in query
if (!imported || !imported.global || !imported.global.app || !imported.global.app.lang) {
if (
!imported ||
!imported.global ||
!imported.global.app ||
!imported.global.app.lang
) {
const language = browserLanguage(availablePacks);
if (language) this.lang = language;
}
@@ -286,14 +353,17 @@ THE SOFTWARE.
const changes = Object.entries(data).reduce((prev, current) => {
if (current[0] === 'presets') return prev; // Ignore changes from presets
if (!isObject(current[1])) return prev; // Ignore non-objects (things that aren't tabs)
prev += Object.keys(current[1]).filter(key => isChanged(current[1][key], current[0], key)).length;
prev += Object.keys(current[1]).filter((key) =>
isChanged(current[1][key], current[0], key),
).length;
return prev;
}, 0);
if (changes) return ` (${changes.toLocaleString()})`;
return '';
},
warnings(index) {
if (!Object.prototype.hasOwnProperty.call(this.$refs, `domain-${index}`)) return false;
if (!Object.prototype.hasOwnProperty.call(this.$refs, `domain-${index}`))
return false;
return this.$refs[`domain-${index}`][0].hasWarnings || false;
},
add() {
@@ -301,9 +371,16 @@ THE SOFTWARE.
// Avoid dupe domains
let count = 1;
while (this.$data.domains.some(d => d && d.server.domain.computed === data.server.domain.computed)) {
while (
this.$data.domains.some(
(d) => d && d.server.domain.computed === data.server.domain.computed,
)
) {
count++;
data.server.domain.computed = data.server.domain.default.replace('.com', `${count}.com`);
data.server.domain.computed = data.server.domain.default.replace(
'.com',
`${count}.com`,
);
}
data.server.domain.value = data.server.domain.computed;
@@ -317,7 +394,8 @@ THE SOFTWARE.
remove(index) {
const name = this.$data.domains[index].server.domain.computed;
this.$data.domains[index] = null;
if (this.$data.active === index) this.$data.active = this.$data.domains.findIndex(d => d !== null);
if (this.$data.active === index)
this.$data.active = this.$data.domains.findIndex((d) => d !== null);
// Analytics
this.removeSiteEvent(this.activeDomains.length, name);
@@ -329,7 +407,9 @@ THE SOFTWARE.
// but with previous as this so that we don't highlight any changes
if (!this.$data.ready) {
this.$data.confFilesPrevious = this.confFilesWithDirectory;
this.$nextTick(() => { this.$data.ready = true; });
this.$nextTick(() => {
this.$data.ready = true;
});
}
// Do the diff!
@@ -344,23 +424,31 @@ THE SOFTWARE.
try {
// Calculate the diff & highlight after render
const diffConf = diff(newConf, oldConf, {
highlightFunction: value => `<mark>${value}</mark>`,
highlightFunction: (value) => `<mark>${value}</mark>`,
});
this.$data.confFilesOutput = Object.entries(diffConf).map(([ file, { name, content } ]) => {
const diffName = name.filter(x => !x.removed).map(x => x.value).join('');
const diffContent = content.filter(x => !x.removed).map(x => x.value).join('');
this.$data.confFilesOutput = Object.entries(diffConf).map(
([file, { name, content }]) => {
const diffName = name
.filter((x) => !x.removed)
.map((x) => x.value)
.join('');
const diffContent = content
.filter((x) => !x.removed)
.map((x) => x.value)
.join('');
return [
diffName,
diffContent,
`${sha2_256(diffName)}-${sha2_256(diffContent)}`,
file,
];
});
return [
diffName,
diffContent,
`${sha2_256(diffName)}-${sha2_256(diffContent)}`,
file,
];
},
);
} catch (err) {
// If diff generation goes wrong, don't show any diff
error('Failed to compute and highlight diff', err);
this.$data.confFilesOutput = Object.entries(newConf).map(([ name, content ]) => {
this.$data.confFilesOutput = Object.entries(newConf).map(([name, content]) => {
const safeName = escape(name);
const safeContent = escape(content);
@@ -374,7 +462,7 @@ THE SOFTWARE.
}
// Once rendered, begin looking for changes again
this.$nextTick(() => this.$data.confWatcherWaiting = false);
this.$nextTick(() => (this.$data.confWatcherWaiting = false));
},
splitColumnToggle() {
this.$data.splitColumn = !this.$data.splitColumn;
@@ -420,12 +508,12 @@ THE SOFTWARE.
},
getPrismComponent(confName) {
switch (confName) {
case '/etc/nginx/Dockerfile':
return 'DockerPrism';
case '/etc/nginx/docker-compose.yaml':
return 'YamlPrism';
default:
return 'NginxPrism';
case '/etc/nginx/Dockerfile':
return 'DockerPrism';
case '/etc/nginx/docker-compose.yaml':
return 'YamlPrism';
default:
return 'NginxPrism';
}
},
},

View File

@@ -25,7 +25,10 @@ THE SOFTWARE.
-->
<template>
<div class="callout floating" :style="style">
<div
class="callout floating"
:style="style"
>
<div class="close">
<p>
{{ $t('templates.callouts.contribute.wantToContributeChanges') }}
@@ -61,10 +64,12 @@ THE SOFTWARE.
return this.$data.scrolled && !this.$data.closed;
},
style() {
return this.visible ? undefined : {
const nonVisibleStyle = {
opacity: 0,
pointerEvents: 'none',
};
return this.visible ? undefined : nonVisibleStyle;
},
},
mounted() {

View File

@@ -33,10 +33,16 @@ THE SOFTWARE.
<div class="panel">
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="tabClass(tab.key)">
<li
v-for="tab in tabs"
:class="tabClass(tab.key)"
>
<a @click="showTab(tab.key)">
{{ $t(tab.display) }}{{ changes(tab.key) }}
<i v-if="warnings(tab.key)" class="fas fa-exclamation-triangle"></i>
<i
v-if="warnings(tab.key)"
class="fas fa-exclamation-triangle"
></i>
</a>
</li>
</ul>
@@ -53,11 +59,21 @@ THE SOFTWARE.
></component>
<div class="navigation-buttons">
<a v-if="previousTab !== false" class="button is-mini" @click="showPreviousTab">
<i class="fas fa-long-arrow-alt-left"></i> <span>{{ $t('common.back') }}</span>
<a
v-if="previousTab !== false"
class="button is-mini"
@click="showPreviousTab"
>
<i class="fas fa-long-arrow-alt-left"></i>
<span>{{ $t('common.back') }}</span>
</a>
<a v-if="nextTab !== false" class="button is-primary is-mini" @click="showNextTab">
<span>{{ $t('common.next') }}</span> <i class="fas fa-long-arrow-alt-right"></i>
<a
v-if="nextTab !== false"
class="button is-primary is-mini"
@click="showNextTab"
>
<span>{{ $t('common.next') }}</span>
<i class="fas fa-long-arrow-alt-right"></i>
</a>
</div>
</div>
@@ -81,12 +97,12 @@ THE SOFTWARE.
export default {
name: 'Domain',
delegated, // Data the parent will present here
delegated, // Data the parent will present here
components: {
Presets,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data() {
return {
@@ -96,25 +112,26 @@ THE SOFTWARE.
},
computed: {
nextTab() {
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
const index = tabs.indexOf(this.$data.active) + 1;
if (index < tabs.length) return tabs[index];
return false;
},
previousTab() {
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
const index = tabs.indexOf(this.$data.active) - 1;
if (index >= 0) return tabs[index];
return false;
},
hasWarnings() {
return Object.values(this.$refs).some(ref => ref[0].hasWarnings || false);
return Object.values(this.$refs).some((ref) => ref[0].hasWarnings || false);
},
},
methods: {
changesCount(tab) {
return Object.keys(this.$props.data[tab])
.filter(key => isChanged(this.$props.data[tab][key], tab, key)).length;
return Object.keys(this.$props.data[tab]).filter((key) =>
isChanged(this.$props.data[tab][key], tab, key),
).length;
},
changes(tab) {
const changes = this.changesCount(tab);
@@ -135,7 +152,7 @@ THE SOFTWARE.
const classes = [];
if (tab === this.$data.active) classes.push('is-active');
if (this.changesCount(tab)) classes.push('is-changed');
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
if (tabs.indexOf(tab) < tabs.indexOf(this.$data.active)) classes.push('is-before');
return classes.join(' ');
},

View File

@@ -34,8 +34,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${httpsChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="https" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.https.enableEncryptedSslConnection') }}
<PrettyCheck
v-model="https"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.https.enableEncryptedSslConnection',
)
}}
</PrettyCheck>
</div>
</div>
@@ -43,7 +50,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="http2Enabled" class="field is-horizontal">
<div
v-if="http2Enabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.https.http2') }}</label>
</div>
@@ -51,7 +61,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${http2Changed ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="http2" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="http2"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.https.enableHttp2Connections') }}
</PrettyCheck>
</div>
@@ -60,7 +73,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="http3Enabled" class="field is-horizontal is-aligned-top">
<div
v-if="http3Enabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label has-small-margin-top">
<label class="label">{{ $t('templates.domainSections.https.http3') }}</label>
</div>
@@ -68,26 +84,42 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${http3Changed ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="http3" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="http3"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.https.enableHttp3Connections') }}
</PrettyCheck>
</div>
</div>
<div v-if="showHttp3Warning" class="control">
<div
v-if="showHttp3Warning"
class="control"
>
<label class="text message is-warning">
<span class="message-body">
{{ $t('templates.domainSections.https.http3IsANonStandardModule') }}
<ExternalLink
:text="$t('templates.domainSections.https.http3NginxQuicReadme')"
:text="
$t('templates.domainSections.https.http3NginxQuicReadme')
"
link="https://quic.nginx.org/README"
></ExternalLink>
{{ $t('templates.domainSections.https.http3OrThe') }}
<ExternalLink
:text="$t('templates.domainSections.https.http3CloudflareQuicheProject')"
:text="
$t(
'templates.domainSections.https.http3CloudflareQuicheProject',
)
"
link="https://github.com/cloudflare/quiche/tree/master/nginx"
></ExternalLink>
{{ $t('templates.domainSections.https.http3ForBuildingNginxWithHttp3') }}
{{
$t(
'templates.domainSections.https.http3ForBuildingNginxWithHttp3',
)
}}
</span>
</label>
</div>
@@ -95,7 +127,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="forceHttpsEnabled" class="field is-horizontal">
<div
v-if="forceHttpsEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.https.forceHttps') }}</label>
</div>
@@ -103,7 +138,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${forceHttpsChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="forceHttps" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="forceHttps"
class="p-default p-curve p-fill p-icon"
>
(http://{{ $parent.$props.data.server.domain.computed }}
<i class="fas fa-long-arrow-alt-right"></i>
https://{{ $parent.$props.data.server.domain.computed }})
@@ -114,7 +152,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="hstsEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="hstsEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.https.hsts') }}</label>
</div>
@@ -122,23 +163,42 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${hstsChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="hsts" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.https.enableStrictTransportSecurity') }}
<PrettyCheck
v-model="hsts"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.https.enableStrictTransportSecurity',
)
}}
</PrettyCheck>
</div>
</div>
<div v-if="hstsSubdomainsEnabled" :class="`control${hstsSubdomainsChanged ? ' is-changed' : ''}`">
<div
v-if="hstsSubdomainsEnabled"
:class="`control${hstsSubdomainsChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="hstsSubdomains" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="hstsSubdomains"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.https.enableIncludeSubDomains') }}
</PrettyCheck>
</div>
</div>
<div v-if="hstsPreloadEnabled" :class="`control${hstsPreloadChanged ? ' is-changed' : ''}`">
<div
v-if="hstsPreloadEnabled"
:class="`control${hstsPreloadChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="hstsPreload" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="hstsPreload"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.https.enablePreload') }}
</PrettyCheck>
</div>
@@ -147,18 +207,29 @@ THE SOFTWARE.
</div>
</div>
<div v-if="certTypeEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="certTypeEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.https.certificationType') }}</label>
<label class="label">
{{ $t('templates.domainSections.https.certificationType') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div
v-for="(name, value) in $props.data.certType.options"
:class="`control${certTypeChanged && value === certType ? ' is-changed' : ''}`"
:class="`control${
certTypeChanged && value === certType ? ' is-changed' : ''
}`"
>
<div class="radio">
<PrettyRadio v-model="certType" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="certType"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -167,9 +238,14 @@ THE SOFTWARE.
</div>
</div>
<div v-if="letsEncryptEmailEnabled" class="field is-horizontal">
<div
v-if="letsEncryptEmailEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.https.letsEncryptEmail') }}</label>
<label class="label">
{{ $t('templates.domainSections.https.letsEncryptEmail') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -185,7 +261,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="sslCertificateEnabled" class="field is-horizontal">
<div
v-if="sslCertificateEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">ssl_certificate</label>
</div>
@@ -203,7 +282,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="sslCertificateKeyEnabled" class="field is-horizontal">
<div
v-if="sslCertificateKeyEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">ssl_certificate_key</label>
</div>
@@ -284,20 +366,20 @@ THE SOFTWARE.
};
export default {
name: 'DomainHTTPS', // Component name
display: 'common.https', // Display name for tab (i18n key)
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainHTTPS', // Component name
display: 'common.https', // Display name for tab (i18n key)
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
ExternalLink,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: {
...computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
showHttp3Warning() {
return this.$props.data.http3.computed;
},
@@ -342,14 +424,18 @@ THE SOFTWARE.
// hstsSubdomains
if (this.$props.data.hsts.computed) {
this.$props.data.hstsSubdomains.enabled = true;
this.$props.data.hstsSubdomains.computed = this.$props.data.hstsSubdomains.value;
this.$props.data.hstsSubdomains.computed =
this.$props.data.hstsSubdomains.value;
} else {
this.$props.data.hstsSubdomains.enabled = false;
this.$props.data.hstsSubdomains.computed = false;
}
// hstsPreload
if (this.$props.data.hsts.computed && this.$props.data.hstsSubdomains.computed) {
if (
this.$props.data.hsts.computed &&
this.$props.data.hstsSubdomains.computed
) {
this.$props.data.hstsPreload.enabled = true;
this.$props.data.hstsPreload.computed = this.$props.data.hstsPreload.value;
} else {
@@ -373,12 +459,14 @@ THE SOFTWARE.
this.$props.data.sslCertificateKey.computed = '';
} else {
// First, check its valid
if (!Object.keys(data.options).includes(data.computed)) data.computed = data.default;
if (!Object.keys(data.options).includes(data.computed))
data.computed = data.default;
// Show the correct fields
if (data.computed === 'letsEncrypt') {
this.$props.data.letsEncryptEmail.enabled = true;
this.$props.data.letsEncryptEmail.computed = this.$props.data.letsEncryptEmail.value;
this.$props.data.letsEncryptEmail.computed =
this.$props.data.letsEncryptEmail.value;
this.$props.data.sslCertificate.enabled = false;
this.$props.data.sslCertificate.computed = '';
@@ -386,9 +474,11 @@ THE SOFTWARE.
this.$props.data.sslCertificateKey.computed = '';
} else {
this.$props.data.sslCertificate.enabled = true;
this.$props.data.sslCertificate.computed = this.$props.data.sslCertificate.value;
this.$props.data.sslCertificate.computed =
this.$props.data.sslCertificate.value;
this.$props.data.sslCertificateKey.enabled = true;
this.$props.data.sslCertificateKey.computed = this.$props.data.sslCertificateKey.value;
this.$props.data.sslCertificateKey.computed =
this.$props.data.sslCertificateKey.value;
this.$props.data.letsEncryptEmail.enabled = false;
this.$props.data.letsEncryptEmail.computed = '';

View File

@@ -34,4 +34,4 @@ import Logging from './logging';
import Restrict from './restrict';
import Onion from './onion';
export default [ Server, HTTPS, PHP, Python, ReverseProxy, Routing, Logging, Restrict, Onion ];
export default [Server, HTTPS, PHP, Python, ReverseProxy, Routing, Logging, Restrict, Onion];

View File

@@ -28,18 +28,28 @@ THE SOFTWARE.
<div>
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">access_log {{ $t('templates.domainSections.logging.byDomain') }}</label>
<label class="label">
access_log {{ $t('templates.domainSections.logging.byDomain') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${accessLogEnabledChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="accessLogEnabled" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="accessLogEnabled"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.logging.enableForThisDomain') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.accessLogEnabled.computed" :class="`control field is-horizontal is-expanded${accessLogPathChanged ? ' is-changed' : ''}`">
<div
v-if="$props.data.accessLogEnabled.computed"
:class="`control field is-horizontal is-expanded${
accessLogPathChanged ? ' is-changed' : ''
}`"
>
<input
v-model="accessLogPath"
class="input"
@@ -51,9 +61,14 @@ THE SOFTWARE.
</div>
</div>
<div v-if="$props.data.accessLogEnabled.computed" class="field is-horizontal">
<div
v-if="$props.data.accessLogEnabled.computed"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">access_log {{ $t('templates.domainSections.logging.arguments') }}</label>
<label class="label">
access_log {{ $t('templates.domainSections.logging.arguments') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -71,13 +86,18 @@ THE SOFTWARE.
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">access_log {{ $t('templates.domainSections.logging.forRedirects') }}</label>
<label class="label">
access_log {{ $t('templates.domainSections.logging.forRedirects') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${redirectAccessLogChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="redirectAccessLog" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="redirectAccessLog"
class="p-default p-curve p-fill p-icon"
>
{{ $t('common.enable') }}
</PrettyCheck>
</div>
@@ -88,17 +108,27 @@ THE SOFTWARE.
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">error_log {{ $t('templates.domainSections.logging.byDomain') }}</label>
<label class="label">
error_log {{ $t('templates.domainSections.logging.byDomain') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${errorLogEnabledChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="errorLogEnabled" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="errorLogEnabled"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.logging.enableForThisDomain') }}
</PrettyCheck>
</div>
<div v-if="$props.data.errorLogEnabled.computed" :class="`control field is-horizontal is-expanded${errorLogPathChanged ? ' is-changed' : ''}`">
<div
v-if="$props.data.errorLogEnabled.computed"
:class="`control field is-horizontal is-expanded${
errorLogPathChanged ? ' is-changed' : ''
}`"
>
<input
v-model="errorLogPath"
class="input"
@@ -112,18 +142,29 @@ THE SOFTWARE.
</div>
</div>
<div v-if="$props.data.errorLogEnabled.computed" class="field is-horizontal">
<div
v-if="$props.data.errorLogEnabled.computed"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">error_log {{ $t('templates.domainSections.logging.level') }}</label>
<label class="label">
error_log {{ $t('templates.domainSections.logging.level') }}
</label>
</div>
<div class="field-body">
<div class="field is-horizontal">
<div
v-for="value in $props.data.errorLogLevel.options"
:class="`control${errorLogLevelChanged && value === errorLogLevel ? ' is-changed' : ''}`"
:class="`control${
errorLogLevelChanged && value === errorLogLevel ? ' is-changed' : ''
}`"
>
<div class="radio">
<PrettyRadio v-model="errorLogLevel" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="errorLogLevel"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ value }}
</PrettyRadio>
</div>
@@ -134,13 +175,18 @@ THE SOFTWARE.
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">error_log {{ $t('templates.domainSections.logging.forRedirects') }}</label>
<label class="label">
error_log {{ $t('templates.domainSections.logging.forRedirects') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${redirectErrorLogChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="redirectErrorLog" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="redirectErrorLog"
class="p-default p-curve p-fill p-icon"
>
{{ $t('common.enable') }}
</PrettyCheck>
</div>
@@ -154,7 +200,15 @@ THE SOFTWARE.
<script>
import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults';
import { accessLogPathDefault, accessLogParamsDefault, errorLogPathDefault, errorLogPathDisabled, errorLogLevelDefault, errorLogLevelOptions, errorLogLevelDisabled } from '../../util/logging';
import {
accessLogPathDefault,
accessLogParamsDefault,
errorLogPathDefault,
errorLogPathDisabled,
errorLogLevelDefault,
errorLogLevelOptions,
errorLogLevelDisabled,
} from '../../util/logging';
import PrettyCheck from '../inputs/checkbox';
import PrettyRadio from '../inputs/radio';
@@ -195,18 +249,18 @@ THE SOFTWARE.
};
export default {
name: 'DomainLogging', // Component name
display: 'common.logging', // Display name for tab (i18n key)
key: 'logging', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainLogging', // Component name
display: 'common.logging', // Display name for tab (i18n key)
key: 'logging', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'logging'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'logging'), // Getters & setters for the delegated data
watch: {
'$props.data.errorLogLevel': {
handler(data) {
@@ -216,7 +270,8 @@ THE SOFTWARE.
this.$props.data.errorLogPath.computed = errorLogPathDisabled;
} else if (!this.$props.data.errorLogPath.enabled) {
this.$props.data.errorLogPath.enabled = true;
this.$props.data.errorLogPath.computed = this.$props.data.errorLogPath.value;
this.$props.data.errorLogPath.computed =
this.$props.data.errorLogPath.value;
}
},
deep: true,

View File

@@ -28,39 +28,65 @@ THE SOFTWARE.
<div>
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-margin-top">
<label class="label">{{ $t('templates.domainSections.onion.onionLocation') }}</label>
<label class="label">
{{ $t('templates.domainSections.onion.onionLocation') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${onionLocationChanged ? ' is-changed' : ''}`">
<input v-model="onionLocation" class="input" type="text" :placeholder="$props.data.onionLocation.placeholder" />
<input
v-model="onionLocation"
class="input"
type="text"
:placeholder="$props.data.onionLocation.placeholder"
/>
</div>
<template v-if="!onionLocationChanged">
<div class="control">
<label class="text">
{{ $t('templates.domainSections.onion.provideAnOnionLocationToSetOnionLocationHeader') }}
{{
$t(
'templates.domainSections.onion.provideAnOnionLocationToSetOnionLocationHeader',
)
}}
</label>
</div>
<div class="control">
<label class="text">
{{ $t('templates.domainSections.onion.letsVisitorsKnownOnionServicesIsAvailable') }}
{{
$t(
'templates.domainSections.onion.letsVisitorsKnownOnionServicesIsAvailable',
)
}}
</label>
</div>
<div class="control">
<label class="text">
<ExternalLink
:text="$t('templates.domainSections.onion.learnMoreAboutOnionServices')"
:text="
$t(
'templates.domainSections.onion.learnMoreAboutOnionServices',
)
"
link="https://community.torproject.org/onion-services/"
></ExternalLink>
</label>
</div>
</template>
<div v-if="incorrectEnding" class="control">
<div
v-if="incorrectEnding"
class="control"
>
<label class="text message is-warning">
<span class="message-body">
{{ $t('templates.domainSections.onion.onionLocationExpectedToEndWithOnion') }}
{{
$t(
'templates.domainSections.onion.onionLocationExpectedToEndWithOnion',
)
}}
</span>
</label>
</div>
@@ -84,20 +110,23 @@ THE SOFTWARE.
};
export default {
name: 'DomainOnion', // Component name
display: 'templates.domainSections.onion.onion', // Display name for tab (i18n key)
key: 'onion', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainOnion', // Component name
display: 'templates.domainSections.onion.onion', // Display name for tab (i18n key)
key: 'onion', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
ExternalLink,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: {
...computedFromDefaults(defaults, 'onion'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'onion'), // Getters & setters for the delegated data
incorrectEnding() {
return this.onionLocationChanged && !this.$props.data.onionLocation.computed.endsWith('.onion');
return (
this.onionLocationChanged &&
!this.$props.data.onionLocation.computed.endsWith('.onion')
);
},
hasWarnings() {
return this.incorrectEnding;

View File

@@ -26,7 +26,10 @@ THE SOFTWARE.
<template>
<div>
<div v-if="!phpEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="!phpEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('common.php') }}</label>
</div>
@@ -36,10 +39,18 @@ THE SOFTWARE.
<label class="text">
{{ $t('templates.domainSections.php.phpIsDisabled') }}
<template v-if="$parent.$props.data.reverseProxy.reverseProxy.computed">
<br />{{ $t('templates.domainSections.php.phpCannotBeEnabledWithReverseProxy') }}
<br />
{{
$t(
'templates.domainSections.php.phpCannotBeEnabledWithReverseProxy',
)
}}
</template>
<template v-if="$parent.$props.data.python.python.computed">
<br />{{ $t('templates.domainSections.php.phpCannotBeEnabledWithPython') }}
<br />
{{
$t('templates.domainSections.php.phpCannotBeEnabledWithPython')
}}
</template>
</label>
</div>
@@ -47,7 +58,10 @@ THE SOFTWARE.
</div>
</div>
<div v-else class="field is-horizontal">
<div
v-else
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('common.php') }}</label>
</div>
@@ -55,7 +69,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${phpChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="php" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="php"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.php.enablePhp') }}
</PrettyCheck>
</div>
@@ -64,7 +81,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="phpServerEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="phpServerEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label has-margin-top">
<label class="label">{{ $t('templates.domainSections.php.phpServer') }}</label>
</div>
@@ -76,7 +96,7 @@ THE SOFTWARE.
v-model="phpServer"
:options="phpServerOptions"
:clearable="false"
:reduce="s => s.value"
:reduce="(s) => s.value"
></VueSelect>
</div>
@@ -84,15 +104,25 @@ THE SOFTWARE.
v-if="phpServerCustomEnabled"
:class="`control${phpServerCustomChanged ? ' is-changed' : ''}`"
>
<input v-model="phpServerCustom" class="input" type="text" :placeholder="$props.data.phpServerCustom.default" />
<input
v-model="phpServerCustom"
class="input"
type="text"
:placeholder="$props.data.phpServerCustom.default"
/>
</div>
</div>
</div>
</div>
<div v-if="phpBackupServerEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="phpBackupServerEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label has-margin-top">
<label class="label">{{ $t('templates.domainSections.php.phpBackupServer') }}</label>
<label class="label">
{{ $t('templates.domainSections.php.phpBackupServer') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -102,7 +132,7 @@ THE SOFTWARE.
v-model="phpBackupServer"
:options="phpBackupServerOptions"
:clearable="false"
:reduce="s => s.value"
:reduce="(s) => s.value"
></VueSelect>
</div>
@@ -110,13 +140,21 @@ THE SOFTWARE.
v-if="phpBackupServerCustomEnabled"
:class="`control${phpBackupServerCustomChanged ? ' is-changed' : ''}`"
>
<input v-model="phpBackupServerCustom" class="input" type="text" :placeholder="$props.data.phpBackupServerCustom.default" />
<input
v-model="phpBackupServerCustom"
class="input"
type="text"
:placeholder="$props.data.phpBackupServerCustom.default"
/>
</div>
</div>
</div>
</div>
<div v-if="wordPressRulesEnabled" class="field is-horizontal">
<div
v-if="wordPressRulesEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.php.wordPressRules') }}</label>
</div>
@@ -124,7 +162,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${wordPressRulesChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="wordPressRules" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="wordPressRules"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.php.enableWordPressRules') }}
</PrettyCheck>
</div>
@@ -133,7 +174,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="drupalRulesEnabled" class="field is-horizontal">
<div
v-if="drupalRulesEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.php.drupalRules') }}</label>
</div>
@@ -141,7 +185,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${drupalRulesChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="drupalRules" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="drupalRules"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.php.enableDrupalRules') }}
</PrettyCheck>
</div>
@@ -150,7 +197,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="magentoRulesEnabled" class="field is-horizontal">
<div
v-if="magentoRulesEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.php.magentoRules') }}</label>
</div>
@@ -158,7 +208,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${magentoRulesChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="magentoRules" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="magentoRules"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.php.enableMagentoRules') }}
</PrettyCheck>
</div>
@@ -167,7 +220,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="joomlaRulesEnabled" class="field is-horizontal">
<div
v-if="joomlaRulesEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.php.joomlaRules') }}</label>
</div>
@@ -175,7 +231,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${joomlaRulesChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="joomlaRules" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="joomlaRules"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.php.enableJoomlaRules') }}
</PrettyCheck>
</div>
@@ -206,7 +265,7 @@ THE SOFTWARE.
'/var/run/php/php8.1-fpm.sock': 'templates.domainSections.php.php81Socket',
'/var/run/php/php8.2-fpm.sock': 'templates.domainSections.php.php82Socket',
'/var/run/php/php-fpm.sock': 'templates.domainSections.php.phpSocket',
'custom': 'templates.domainSections.php.custom',
custom: 'templates.domainSections.php.custom',
};
const hiddenValues = ['', 'custom'];
@@ -253,26 +312,28 @@ THE SOFTWARE.
};
export default {
name: 'DomainPHP', // Component name
display: 'common.php', // Display name for tab (i18n key)
key: 'php', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainPHP', // Component name
display: 'common.php', // Display name for tab (i18n key)
key: 'php', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
VueSelect,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: {
...computedFromDefaults(defaults, 'php'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'php'), // Getters & setters for the delegated data
phpServerOptions() {
return Object.entries(this.$props.data.phpServer.options)
.map(([key, value]) => this.formattedOption(key, value));
return Object.entries(this.$props.data.phpServer.options).map(([key, value]) =>
this.formattedOption(key, value),
);
},
phpBackupServerOptions() {
return Object.entries(this.$props.data.phpBackupServer.options)
.map(([key, value]) => this.formattedOption(key, value));
return Object.entries(this.$props.data.phpBackupServer.options).map(
([key, value]) => this.formattedOption(key, value),
);
},
},
watch: {
@@ -297,13 +358,16 @@ THE SOFTWARE.
this.$props.data.phpServer.enabled = true;
this.$props.data.phpServer.computed = this.$props.data.phpServer.value;
this.$props.data.phpBackupServer.enabled = true;
this.$props.data.phpBackupServer.computed = this.$props.data.phpBackupServer.value;
this.$props.data.phpBackupServer.computed =
this.$props.data.phpBackupServer.value;
this.$props.data.wordPressRules.enabled = true;
this.$props.data.wordPressRules.computed = this.$props.data.wordPressRules.value;
this.$props.data.wordPressRules.computed =
this.$props.data.wordPressRules.value;
this.$props.data.drupalRules.enabled = true;
this.$props.data.drupalRules.computed = this.$props.data.drupalRules.value;
this.$props.data.magentoRules.enabled = true;
this.$props.data.magentoRules.computed = this.$props.data.magentoRules.value;
this.$props.data.magentoRules.computed =
this.$props.data.magentoRules.value;
this.$props.data.joomlaRules.enabled = true;
this.$props.data.joomlaRules.computed = this.$props.data.joomlaRules.value;
} else {
@@ -361,13 +425,14 @@ THE SOFTWARE.
},
// Ensure 'Custom'/'Disabled' get translated in VueSelect on language switch
'$i18n.locale'() {
if (!this.$refs.phpServerSelect)
return false;
const updated = this.phpServerOptions
.find(x => x.value === this.$refs.phpServerSelect.$data._value.value);
if (!this.$refs.phpServerSelect) return false;
const updated = this.phpServerOptions.find(
(x) => x.value === this.$refs.phpServerSelect.$data._value.value,
);
if (updated) this.$refs.phpServerSelect.$data._value = updated;
const updatedBackup = this.phpBackupServerOptions
.find(x => x.value === this.$refs.phpBackupServerSelect.$data._value.value);
const updatedBackup = this.phpBackupServerOptions.find(
(x) => x.value === this.$refs.phpBackupServerSelect.$data._value.value,
);
if (updatedBackup) this.$refs.phpBackupServerSelect.$data._value = updatedBackup;
},
},

View File

@@ -26,15 +26,25 @@ THE SOFTWARE.
<template>
<div class="container">
<div class="header-group" :style="{ cursor: interacted ? 'pointer' : undefined }" @click="toggleCollapse">
<div
class="header-group"
:style="{ cursor: interacted ? 'pointer' : undefined }"
@click="toggleCollapse"
>
<h3>{{ $t('templates.domainSections.presets.presets') }}</h3>
<a v-if="interacted" class="button is-tiny">
<a
v-if="interacted"
class="button is-tiny"
>
<i :class="`fas fa-angle-${expanded ? 'up' : 'down'}`"></i>
</a>
</div>
<template v-if="!$parent.$props.data.hasUserInteraction || expanded">
<div v-if="$parent.$props.data.hasUserInteraction" class="message is-warning">
<div
v-if="$parent.$props.data.hasUserInteraction"
class="message is-warning"
>
<p class="message-body">
{{ $t('templates.domainSections.presets.itLooksLikeYouCustomisedTheConfig') }}
</p>
@@ -64,11 +74,13 @@ THE SOFTWARE.
display: 'templates.domainSections.presets.frontend', // i18n key
enabled: true,
computedCheck(data) {
return !data.php.php.computed
&& !data.python.python.computed
&& !data.reverseProxy.reverseProxy.computed
&& data.routing.index.computed === 'index.html'
&& data.routing.fallbackHtml.computed;
return (
!data.php.php.computed &&
!data.python.python.computed &&
!data.reverseProxy.reverseProxy.computed &&
data.routing.index.computed === 'index.html' &&
data.routing.fallbackHtml.computed
);
},
},
php: {
@@ -76,14 +88,16 @@ THE SOFTWARE.
display: 'common.php', // i18n key
enabled: true,
computedCheck(data) {
return data.php.php.computed
&& data.routing.index.computed === 'index.php'
&& data.routing.fallbackPhp.computed
&& !data.routing.fallbackHtml.computed
&& !data.php.wordPressRules.computed
&& !data.php.drupalRules.computed
&& !data.php.magentoRules.computed
&& !data.php.joomlaRules.computed;
return (
data.php.php.computed &&
data.routing.index.computed === 'index.php' &&
data.routing.fallbackPhp.computed &&
!data.routing.fallbackHtml.computed &&
!data.php.wordPressRules.computed &&
!data.php.drupalRules.computed &&
!data.php.magentoRules.computed &&
!data.php.joomlaRules.computed
);
},
},
django: {
@@ -91,9 +105,11 @@ THE SOFTWARE.
display: 'common.django', // i18n key
enabled: true,
computedCheck(data) {
return data.python.python.computed
&& data.python.djangoRules.computed
&& !data.routing.root.computed;
return (
data.python.python.computed &&
data.python.djangoRules.computed &&
!data.routing.root.computed
);
},
},
nodejs: {
@@ -101,8 +117,7 @@ THE SOFTWARE.
display: 'templates.domainSections.presets.nodeJs', // i18n key
enabled: true,
computedCheck(data) {
return data.reverseProxy.reverseProxy.computed
&& !data.routing.root.computed;
return data.reverseProxy.reverseProxy.computed && !data.routing.root.computed;
},
},
singlePageApplication: {
@@ -110,9 +125,11 @@ THE SOFTWARE.
display: 'templates.domainSections.presets.singlePageApplication', // i18n key
enabled: true,
computedCheck(data) {
return data.php.php.computed
&& data.routing.index.computed === 'index.html'
&& data.routing.fallbackHtml.computed;
return (
data.php.php.computed &&
data.routing.index.computed === 'index.html' &&
data.routing.fallbackHtml.computed
);
},
},
wordPress: {
@@ -120,13 +137,15 @@ THE SOFTWARE.
display: 'common.wordPress', // i18n key
enabled: true,
computedCheck(data) {
return data.routing.index.computed === 'index.php'
&& data.routing.fallbackPhp.computed
&& !data.routing.fallbackHtml.computed
&& data.php.wordPressRules.computed
&& !data.php.drupalRules.computed
&& !data.php.magentoRules.computed
&& !data.php.joomlaRules.computed;
return (
data.routing.index.computed === 'index.php' &&
data.routing.fallbackPhp.computed &&
!data.routing.fallbackHtml.computed &&
data.php.wordPressRules.computed &&
!data.php.drupalRules.computed &&
!data.php.magentoRules.computed &&
!data.php.joomlaRules.computed
);
},
},
drupal: {
@@ -134,13 +153,15 @@ THE SOFTWARE.
display: 'common.drupal', // i18n key
enabled: true,
computedCheck(data) {
return data.routing.index.computed === 'index.php'
&& data.routing.fallbackPhp.computed
&& !data.routing.fallbackHtml.computed
&& !data.php.wordPressRules.computed
&& data.php.drupalRules.computed
&& !data.php.magentoRules.computed
&& !data.php.joomlaRules.computed;
return (
data.routing.index.computed === 'index.php' &&
data.routing.fallbackPhp.computed &&
!data.routing.fallbackHtml.computed &&
!data.php.wordPressRules.computed &&
data.php.drupalRules.computed &&
!data.php.magentoRules.computed &&
!data.php.joomlaRules.computed
);
},
},
magento: {
@@ -148,13 +169,15 @@ THE SOFTWARE.
display: 'common.magento', // i18n key
enabled: true,
computedCheck(data) {
return data.routing.index.computed === 'index.php'
&& data.routing.fallbackPhp.computed
&& !data.routing.fallbackHtml.computed
&& !data.php.wordPressRules.computed
&& !data.php.drupalRules.computed
&& data.php.magentoRules.computed
&& !data.php.joomlaRules.computed;
return (
data.routing.index.computed === 'index.php' &&
data.routing.fallbackPhp.computed &&
!data.routing.fallbackHtml.computed &&
!data.php.wordPressRules.computed &&
!data.php.drupalRules.computed &&
data.php.magentoRules.computed &&
!data.php.joomlaRules.computed
);
},
},
joomla: {
@@ -162,24 +185,26 @@ THE SOFTWARE.
display: 'common.joomla', // i18n key
enabled: true,
computedCheck(data) {
return data.routing.index.computed === 'index.php'
&& data.routing.fallbackPhp.computed
&& !data.routing.fallbackHtml.computed
&& !data.php.wordPressRules.computed
&& !data.php.drupalRules.computed
&& !data.php.magentoRules.computed
&& data.php.joomlaRules.computed;
return (
data.routing.index.computed === 'index.php' &&
data.routing.fallbackPhp.computed &&
!data.routing.fallbackHtml.computed &&
!data.php.wordPressRules.computed &&
!data.php.drupalRules.computed &&
!data.php.magentoRules.computed &&
data.php.joomlaRules.computed
);
},
},
};
export default {
name: 'DomainPresets', // Component name
display: 'templates.domainSections.presets.presets', // Display name for tab (i18n key)
key: 'presets', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainPresets', // Component name
display: 'templates.domainSections.presets.presets', // Display name for tab (i18n key)
key: 'presets', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data() {
return {
@@ -187,7 +212,7 @@ THE SOFTWARE.
};
},
computed: {
...computedFromDefaults(defaults, 'presets', false), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'presets', false), // Getters & setters for the delegated data
interacted() {
return this.$parent.$props.data.hasUserInteraction;
},
@@ -197,8 +222,9 @@ THE SOFTWARE.
'$parent.$props.data': {
handler(data) {
// This might cause recursion, but seems not to
Object.keys(this.$props.data).forEach(preset => {
this.$props.data[preset].computed = this.$props.data[preset].computedCheck(data);
Object.keys(this.$props.data).forEach((preset) => {
this.$props.data[preset].computed =
this.$props.data[preset].computedCheck(data);
});
},
deep: true,
@@ -207,7 +233,7 @@ THE SOFTWARE.
methods: {
setPreset(key) {
// Set that we're using this preset
Object.keys(this.$props.data).forEach(preset => this[preset] = preset === key);
Object.keys(this.$props.data).forEach((preset) => (this[preset] = preset === key));
this.presetEvent(key, this.interacted);
// Restore some specific defaults first
@@ -226,49 +252,49 @@ THE SOFTWARE.
this.$parent.resetValue('routing', 'fallbackPhp');
switch (key) {
case 'frontend':
this.$parent.setValue('php', 'php', false);
this.$parent.setValue('routing', 'index', 'index.html');
this.$parent.setValue('routing', 'fallbackHtml', true);
break;
case 'frontend':
this.$parent.setValue('php', 'php', false);
this.$parent.setValue('routing', 'index', 'index.html');
this.$parent.setValue('routing', 'fallbackHtml', true);
break;
case 'php':
// Defaults should be PHP
break;
case 'php':
// Defaults should be PHP
break;
case 'django':
this.$parent.setValue('php', 'php', false);
this.$parent.setValue('python', 'python', true);
this.$parent.setValue('python', 'djangoRules', true);
this.$parent.setValue('routing', 'root', false);
break;
case 'django':
this.$parent.setValue('php', 'php', false);
this.$parent.setValue('python', 'python', true);
this.$parent.setValue('python', 'djangoRules', true);
this.$parent.setValue('routing', 'root', false);
break;
case 'nodejs':
this.$parent.setValue('php', 'php', false);
this.$parent.setValue('reverseProxy', 'reverseProxy', true);
this.$parent.setValue('routing', 'root', false);
break;
case 'nodejs':
this.$parent.setValue('php', 'php', false);
this.$parent.setValue('reverseProxy', 'reverseProxy', true);
this.$parent.setValue('routing', 'root', false);
break;
case 'singlePageApplication':
this.$parent.setValue('routing', 'index', 'index.html');
this.$parent.setValue('routing', 'fallbackHtml', true);
break;
case 'singlePageApplication':
this.$parent.setValue('routing', 'index', 'index.html');
this.$parent.setValue('routing', 'fallbackHtml', true);
break;
case 'wordPress':
this.$parent.setValue('php', 'wordPressRules', true);
break;
case 'wordPress':
this.$parent.setValue('php', 'wordPressRules', true);
break;
case 'drupal':
this.$parent.setValue('php', 'drupalRules', true);
break;
case 'drupal':
this.$parent.setValue('php', 'drupalRules', true);
break;
case 'magento':
this.$parent.setValue('php', 'magentoRules', true);
break;
case 'magento':
this.$parent.setValue('php', 'magentoRules', true);
break;
case 'joomla':
this.$parent.setValue('php', 'joomlaRules', true);
break;
case 'joomla':
this.$parent.setValue('php', 'joomlaRules', true);
break;
}
},
presetEvent(name, overwrite = false) {

View File

@@ -26,7 +26,10 @@ THE SOFTWARE.
<template>
<div>
<div v-if="!pythonEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="!pythonEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('common.python') }}</label>
</div>
@@ -36,10 +39,20 @@ THE SOFTWARE.
<label class="text">
{{ $t('templates.domainSections.python.pythonIsDisabled') }}
<template v-if="$parent.$props.data.reverseProxy.reverseProxy.computed">
<br />{{ $t('templates.domainSections.python.pythonCannotBeEnabledWithReverseProxy') }}
<br />
{{
$t(
'templates.domainSections.python.pythonCannotBeEnabledWithReverseProxy',
)
}}
</template>
<template v-if="$parent.$props.data.php.php.computed">
<br />{{ $t('templates.domainSections.python.pythonCannotBeEnabledWithPhp') }}
<br />
{{
$t(
'templates.domainSections.python.pythonCannotBeEnabledWithPhp',
)
}}
</template>
</label>
</div>
@@ -47,7 +60,10 @@ THE SOFTWARE.
</div>
</div>
<div v-else class="field is-horizontal">
<div
v-else
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('common.python') }}</label>
</div>
@@ -55,7 +71,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${pythonChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="python" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="python"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.python.enablePython') }}
</PrettyCheck>
</div>
@@ -64,7 +83,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="djangoRulesEnabled" class="field is-horizontal">
<div
v-if="djangoRulesEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.python.djangoRules') }}</label>
</div>
@@ -72,7 +94,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${djangoRulesChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="djangoRules" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="djangoRules"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.python.enableDjangoRules') }}
</PrettyCheck>
</div>
@@ -100,15 +125,15 @@ THE SOFTWARE.
};
export default {
name: 'DomainPython', // Component name
display: 'common.python', // Display name for tab (i18n key)
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainPython', // Component name
display: 'common.python', // Display name for tab (i18n key)
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'python'), // Getters & setters for the delegated data
watch: {

View File

@@ -36,8 +36,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${getMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="getMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="getMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -52,8 +59,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${postMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="postMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="postMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -68,8 +82,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${putMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="putMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="putMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -84,8 +105,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${patchMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="patchMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="patchMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -100,8 +128,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${deleteMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="deleteMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="deleteMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -118,8 +153,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${headMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="headMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="headMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -134,8 +176,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${connectMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="connectMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="connectMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -150,8 +199,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${optionsMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="optionsMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="optionsMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -166,8 +222,15 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${traceMethodChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="traceMethod" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.restrict.disableForThisDomain') }}
<PrettyCheck
v-model="traceMethod"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.domainSections.restrict.disableForThisDomain',
)
}}
</PrettyCheck>
</div>
</div>
@@ -176,9 +239,14 @@ THE SOFTWARE.
</div>
</div>
</div>
<div v-if="hasAtLeastOneEnabled" class="field is-horizontal">
<div
v-if="hasAtLeastOneEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.restrict.responseCode') }}</label>
<label class="label">
{{ $t('templates.domainSections.restrict.responseCode') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -247,25 +315,29 @@ THE SOFTWARE.
};
export default {
name: 'DomainRestrict', // Component name
display: 'common.restrict', // Display name for tab (i18n key)
key: 'restrict', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainRestrict', // Component name
display: 'common.restrict', // Display name for tab (i18n key)
key: 'restrict', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data () {
data() {
return {
validResponseCode: true,
};
},
computed: {
...computedFromDefaults(defaults, 'restrict'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'restrict'), // Getters & setters for the delegated data
hasAtLeastOneEnabled() {
return (Object.keys(this.$props.data).filter(k => this.$props.data[k].computed && k !== 'responseCode')).length > 0;
return (
Object.keys(this.$props.data).filter(
(k) => this.$props.data[k].computed && k !== 'responseCode',
).length > 0
);
},
},
watch: {

View File

@@ -26,7 +26,10 @@ THE SOFTWARE.
<template>
<div>
<div v-if="!reverseProxyEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="!reverseProxyEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('common.reverseProxy') }}</label>
</div>
@@ -36,10 +39,20 @@ THE SOFTWARE.
<label class="text">
{{ $t('templates.domainSections.reverseProxy.reverseProxyIsDisabled') }}
<template v-if="$parent.$props.data.php.php.computed">
<br />{{ $t('templates.domainSections.reverseProxy.reverseProxyCannotBeEnabledWithPhp') }}
<br />
{{
$t(
'templates.domainSections.reverseProxy.reverseProxyCannotBeEnabledWithPhp',
)
}}
</template>
<template v-if="$parent.$props.data.python.python.computed">
<br />{{ $t('templates.domainSections.reverseProxy.reverseProxyCannotBeEnabledWithPython') }}
<br />
{{
$t(
'templates.domainSections.reverseProxy.reverseProxyCannotBeEnabledWithPython',
)
}}
</template>
</label>
</div>
@@ -47,7 +60,10 @@ THE SOFTWARE.
</div>
</div>
<div v-else class="field is-horizontal">
<div
v-else
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('common.reverseProxy') }}</label>
</div>
@@ -55,7 +71,10 @@ THE SOFTWARE.
<div :class="`field${reverseProxyChanged ? ' is-changed' : ''}`">
<div class="control">
<div class="checkbox">
<PrettyCheck v-model="reverseProxy" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="reverseProxy"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.reverseProxy.enableReverseProxy') }}
</PrettyCheck>
</div>
@@ -64,7 +83,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="pathEnabled" class="field is-horizontal">
<div
v-if="pathEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('common.path') }}</label>
</div>
@@ -82,7 +104,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="proxyPassEnabled" class="field is-horizontal">
<div
v-if="proxyPassEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">proxy_pass</label>
</div>
@@ -100,9 +125,14 @@ THE SOFTWARE.
</div>
</div>
<div v-if="proxyHostHeaderEnabled" class="field is-horizontal">
<div
v-if="proxyHostHeaderEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.reverseProxy.proxyHostHeader') }}</label>
<label class="label">
{{ $t('templates.domainSections.reverseProxy.proxyHostHeader') }}
</label>
</div>
<div class="field-body">
<div :class="`field${proxyHostHeaderChanged ? ' is-changed' : ''}`">
@@ -145,17 +175,17 @@ THE SOFTWARE.
};
export default {
name: 'DomainReverseProxy', // Component name
display: 'common.reverseProxy', // Display name for tab (i18n key)
key: 'reverseProxy', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainReverseProxy', // Component name
display: 'common.reverseProxy', // Display name for tab (i18n key)
key: 'reverseProxy', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'reverseProxy'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'reverseProxy'), // Getters & setters for the delegated data
watch: {
// If the PHP or Python is enabled, the Reverse proxy will be forced off
'$parent.$props.data': {
@@ -166,7 +196,8 @@ THE SOFTWARE.
this.$props.data.reverseProxy.computed = false;
} else {
this.$props.data.reverseProxy.enabled = true;
this.$props.data.reverseProxy.computed = this.$props.data.reverseProxy.value;
this.$props.data.reverseProxy.computed =
this.$props.data.reverseProxy.value;
}
},
deep: true,
@@ -180,7 +211,8 @@ THE SOFTWARE.
this.$props.data.proxyPass.enabled = true;
this.$props.data.proxyPass.computed = this.$props.data.proxyPass.value;
this.$props.data.proxyHostHeader.enabled = true;
this.$props.data.proxyHostHeader.computed = this.$props.data.proxyHostHeader.value;
this.$props.data.proxyHostHeader.computed =
this.$props.data.proxyHostHeader.value;
} else {
this.$props.data.path.enabled = false;
this.$props.data.path.computed = '';

View File

@@ -34,7 +34,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${rootChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="root" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="root"
class="p-default p-curve p-fill p-icon"
>
{{ $t('common.enable') }}
</PrettyCheck>
</div>
@@ -43,7 +46,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="indexEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="indexEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">index</label>
</div>
@@ -54,7 +60,11 @@ THE SOFTWARE.
:class="`control${indexChanged && value === index ? ' is-changed' : ''}`"
>
<div class="radio">
<PrettyRadio v-model="index" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="index"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ value }}
</PrettyRadio>
</div>
@@ -63,22 +73,39 @@ THE SOFTWARE.
</div>
</div>
<div v-if="fallbackHtmlEnabled || fallbackPhpEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="fallbackHtmlEnabled || fallbackPhpEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.routing.fallbackRouting') }}</label>
<label class="label">
{{ $t('templates.domainSections.routing.fallbackRouting') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div v-if="fallbackHtmlEnabled" :class="`control${fallbackHtmlChanged ? ' is-changed' : ''}`">
<div
v-if="fallbackHtmlEnabled"
:class="`control${fallbackHtmlChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="fallbackHtml" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="fallbackHtml"
class="p-default p-curve p-fill p-icon"
>
index.html
</PrettyCheck>
</div>
</div>
<div v-if="fallbackPhpEnabled" :class="`control${fallbackPhpChanged ? ' is-changed' : ''}`">
<div
v-if="fallbackPhpEnabled"
:class="`control${fallbackPhpChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="fallbackPhp" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="fallbackPhp"
class="p-default p-curve p-fill p-icon"
>
index.php
</PrettyCheck>
</div>
@@ -87,9 +114,14 @@ THE SOFTWARE.
</div>
</div>
<div v-if="fallbackPhpPathEnabled" class="field is-horizontal">
<div
v-if="fallbackPhpPathEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.routing.fallbackRoutingPhpPath') }}</label>
<label class="label">
{{ $t('templates.domainSections.routing.fallbackRoutingPhpPath') }}
</label>
</div>
<div class="field-body">
<div :class="`field${fallbackPhpPathChanged ? ' is-changed' : ''}`">
@@ -105,15 +137,23 @@ THE SOFTWARE.
</div>
</div>
<div v-if="legacyPhpRoutingEnabled" class="field is-horizontal">
<div
v-if="legacyPhpRoutingEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.routing.legacyPhpRouting') }}</label>
<label class="label">
{{ $t('templates.domainSections.routing.legacyPhpRouting') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${legacyPhpRoutingChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="legacyPhpRouting" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="legacyPhpRouting"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.domainSections.routing.enableLegacyRouting') }}
</PrettyCheck>
</div>
@@ -159,18 +199,18 @@ THE SOFTWARE.
};
export default {
name: 'DomainRouting', // Component name
display: 'templates.domainSections.routing.routing', // Display name for tab (i18n key)
key: 'routing', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainRouting', // Component name
display: 'templates.domainSections.routing.routing', // Display name for tab (i18n key)
key: 'routing', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'routing'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'routing'), // Getters & setters for the delegated data
watch: {
// Disable all options (expect legacy php) if root is disabled
'$props.data.root': {
@@ -179,7 +219,8 @@ THE SOFTWARE.
this.$props.data.index.enabled = true;
this.$props.data.index.computed = this.$props.data.index.value;
this.$props.data.fallbackHtml.enabled = true;
this.$props.data.fallbackHtml.computed = this.$props.data.fallbackHtml.value;
this.$props.data.fallbackHtml.computed =
this.$props.data.fallbackHtml.value;
this.$props.data.fallbackPhp.enabled = true;
this.$props.data.fallbackPhp.computed = this.$props.data.fallbackPhp.value;
} else {
@@ -199,7 +240,8 @@ THE SOFTWARE.
// This might cause recursion, but seems not to
if (data.fallbackHtml.computed && data.fallbackPhp.computed) {
this.$props.data.fallbackPhpPath.enabled = true;
this.$props.data.fallbackPhpPath.computed = this.$props.data.fallbackPhpPath.value;
this.$props.data.fallbackPhpPath.computed =
this.$props.data.fallbackPhpPath.value;
} else {
this.$props.data.fallbackPhpPath.enabled = false;
this.$props.data.fallbackPhpPath.computed = '';

View File

@@ -30,32 +30,59 @@ THE SOFTWARE.
<div class="field">
<label class="label">{{ $t('templates.domainSections.server.domain') }}</label>
<div :class="`control${domainChanged ? ' is-changed' : ''}`">
<input v-model="domain" class="input" type="text" :placeholder="domainDefault" />
<input
v-model="domain"
class="input"
type="text"
:placeholder="domainDefault"
/>
</div>
</div>
<div class="field">
<label class="label">{{ $t('common.path') }}</label>
<div :class="`control${pathChanged ? ' is-changed' : ''}`">
<input v-model="path" class="input" type="text" :placeholder="`/var/www/${domain}`" />
<input
v-model="path"
class="input"
type="text"
:placeholder="`/var/www/${domain}`"
/>
</div>
</div>
<div class="field">
<label class="label">{{ $t('templates.domainSections.server.documentRoot') }}</label>
<label class="label">
{{ $t('templates.domainSections.server.documentRoot') }}
</label>
<div :class="`control${documentRootChanged ? ' is-changed' : ''}`">
<input v-model="documentRoot" class="input" type="text" :placeholder="documentRootDefault" />
<input
v-model="documentRoot"
class="input"
type="text"
:placeholder="documentRootDefault"
/>
</div>
</div>
</div>
<div v-if="duplicateDomain" class="field">
<div
v-if="duplicateDomain"
class="field"
>
<div class="control">
<label class="text message is-warning">
<span class="message-body">
{{ $t('templates.domainSections.server.oneOrMoreOtherDomainsAreAlsoNamed') }}
<code class="slim">{{ $props.data.domain.computed }}</code>.
{{ $t('templates.domainSections.server.thisWillCauseIssuesWithConfigGeneration') }}
{{
$t('templates.domainSections.server.oneOrMoreOtherDomainsAreAlsoNamed')
}}
<code class="slim">{{ $props.data.domain.computed }}</code>
.
{{
$t(
'templates.domainSections.server.thisWillCauseIssuesWithConfigGeneration',
)
}}
</span>
</label>
</div>
@@ -63,13 +90,18 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.server.wwwSubdomain') }}</label>
<label class="label">
{{ $t('templates.domainSections.server.wwwSubdomain') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${wwwSubdomainChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="wwwSubdomain" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="wwwSubdomain"
class="p-default p-curve p-fill p-icon"
>
(www.{{ $props.data.domain.computed }})
</PrettyCheck>
</div>
@@ -78,15 +110,23 @@ THE SOFTWARE.
</div>
</div>
<div v-if="cdnSubdomainEnabled" class="field is-horizontal">
<div
v-if="cdnSubdomainEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.server.cdnSubdomain') }}</label>
<label class="label">
{{ $t('templates.domainSections.server.cdnSubdomain') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${cdnSubdomainChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="cdnSubdomain" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="cdnSubdomain"
class="p-default p-curve p-fill p-icon"
>
(cdn.{{ $props.data.domain.computed }})
</PrettyCheck>
</div>
@@ -97,14 +137,21 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.domainSections.server.redirectSubdomains') }}</label>
<label class="label">
{{ $t('templates.domainSections.server.redirectSubdomains') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${redirectSubdomainsChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="redirectSubdomains" class="p-default p-curve p-fill p-icon">
({{ wwwSubdomain ? `${domain}, ` : '' }}*.{{ $props.data.domain.computed }}
<PrettyCheck
v-model="redirectSubdomains"
class="p-default p-curve p-fill p-icon"
>
({{ wwwSubdomain ? `${domain}, ` : '' }}*.{{
$props.data.domain.computed
}}
<i class="fas fa-long-arrow-alt-right"></i>
{{ wwwSubdomain ? 'www.' : '' }}{{ $props.data.domain.computed }})
</PrettyCheck>
@@ -121,22 +168,28 @@ THE SOFTWARE.
<div class="field-body">
<div class="field has-addons">
<div class="control">
<a class="button is-static">
IPv4
</a>
<a class="button is-static">IPv4</a>
</div>
<div :class="`control is-expanded${listenIpv4Changed ? ' is-changed' : ''}`">
<input v-model="listenIpv4" class="input" type="text" :placeholder="listenIpv4Default" />
<input
v-model="listenIpv4"
class="input"
type="text"
:placeholder="listenIpv4Default"
/>
</div>
</div>
<div class="field has-addons">
<div class="control">
<a class="button is-static">
IPv6
</a>
<a class="button is-static">IPv6</a>
</div>
<div :class="`control is-expanded${listenIpv6Changed ? ' is-changed' : ''}`">
<input v-model="listenIpv6" class="input" type="text" :placeholder="listenIpv6Default" />
<input
v-model="listenIpv6"
class="input"
type="text"
:placeholder="listenIpv6Default"
/>
</div>
</div>
</div>
@@ -187,21 +240,24 @@ THE SOFTWARE.
};
export default {
name: 'DomainServer', // Component name
display: 'templates.domainSections.server.server', // Display name for tab (i18n key)
key: 'server', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainServer', // Component name
display: 'templates.domainSections.server.server', // Display name for tab (i18n key)
key: 'server', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: {
...computedFromDefaults(defaults, 'server'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'server'), // Getters & setters for the delegated data
duplicateDomain() {
return this.$parent.$parent.$data.domains
.filter(d => d && d.server.domain.computed === this.$props.data.domain.computed).length > 1;
return (
this.$parent.$parent.$data.domains.filter(
(d) => d && d.server.domain.computed === this.$props.data.domain.computed,
).length > 1
);
},
hasWarnings() {
return this.duplicateDomain;
@@ -234,7 +290,8 @@ THE SOFTWARE.
// This might cause recursion, but seems not to
if (data.computed) {
this.$props.data.cdnSubdomain.enabled = true;
this.$props.data.cdnSubdomain.computed = this.$props.data.cdnSubdomain.value;
this.$props.data.cdnSubdomain.computed =
this.$props.data.cdnSubdomain.value;
} else {
this.$props.data.cdnSubdomain.enabled = false;
this.$props.data.cdnSubdomain.computed = false;

View File

@@ -55,12 +55,14 @@ THE SOFTWARE.
<ExternalLink
:text="$t('templates.footer.balintSzekeres')"
link="https://b4lint.hu/"
></ExternalLink>,
></ExternalLink>
,
{{ $t('templates.footer.maintainedBy') }}
<ExternalLink
:text="$t('templates.footer.digitalOcean')"
link="https://github.com/digitalocean/nginxconfig.io"
></ExternalLink>.
></ExternalLink>
.
</p>
</div>
</div>
@@ -76,10 +78,11 @@ THE SOFTWARE.
},
methods: {
handleScrollToTop: () => {
window.scrollTo({top: 0});
window.scrollTo({ top: 0 });
document.querySelectorAll('.column-scroll-y')
.forEach(column => column.scrollTo({ top: 0 }));
document
.querySelectorAll('.column-scroll-y')
.forEach((column) => column.scrollTo({ top: 0 }));
},
},
};

View File

@@ -28,10 +28,16 @@ THE SOFTWARE.
<div class="panel">
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="tabClass(tab.key)">
<li
v-for="tab in tabs"
:class="tabClass(tab.key)"
>
<a @click="showTab(tab.key)">
{{ $t(tab.display) }}{{ changes(tab.key) }}
<i v-if="warnings(tab.key)" class="fas fa-exclamation-triangle"></i>
<i
v-if="warnings(tab.key)"
class="fas fa-exclamation-triangle"
></i>
</a>
</li>
</ul>
@@ -48,11 +54,21 @@ THE SOFTWARE.
></component>
<div class="navigation-buttons">
<a v-if="previousTab !== false" class="button is-mini" @click="showPreviousTab">
<i class="fas fa-long-arrow-alt-left"></i> <span>{{ $t('common.back') }}</span>
<a
v-if="previousTab !== false"
class="button is-mini"
@click="showPreviousTab"
>
<i class="fas fa-long-arrow-alt-left"></i>
<span>{{ $t('common.back') }}</span>
</a>
<a v-if="nextTab !== false" class="button is-primary is-mini" @click="showNextTab">
<span>{{ $t('common.next') }}</span> <i class="fas fa-long-arrow-alt-right"></i>
<a
v-if="nextTab !== false"
class="button is-primary is-mini"
@click="showNextTab"
>
<span>{{ $t('common.next') }}</span>
<i class="fas fa-long-arrow-alt-right"></i>
</a>
</div>
</div>
@@ -70,9 +86,9 @@ THE SOFTWARE.
export default {
name: 'Global',
delegated, // Data the parent will present here
delegated, // Data the parent will present here
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data() {
return {
@@ -82,13 +98,13 @@ THE SOFTWARE.
},
computed: {
nextTab() {
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
const index = tabs.indexOf(this.$data.active) + 1;
if (index < tabs.length) return tabs[index];
return false;
},
previousTab() {
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
const index = tabs.indexOf(this.$data.active) - 1;
if (index >= 0) return tabs[index];
return false;
@@ -96,8 +112,9 @@ THE SOFTWARE.
},
methods: {
changesCount(tab) {
return Object.keys(this.$props.data[tab])
.filter(key => isChanged(this.$props.data[tab][key], tab, key)).length;
return Object.keys(this.$props.data[tab]).filter((key) =>
isChanged(this.$props.data[tab][key], tab, key),
).length;
},
changes(tab) {
const changes = this.changesCount(tab);
@@ -118,7 +135,7 @@ THE SOFTWARE.
const classes = [];
if (tab === this.$data.active) classes.push('is-active');
if (this.changesCount(tab)) classes.push('is-changed');
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
if (tabs.indexOf(tab) < tabs.indexOf(this.$data.active)) classes.push('is-before');
return classes.join(' ');
},

View File

@@ -32,13 +32,20 @@ THE SOFTWARE.
</div>
<div class="field-body">
<div class="field is-horizontal is-aligned-top">
<a class="button is-primary is-tiny" @click="applyDockerTweaks">
<a
class="button is-primary is-tiny"
@click="applyDockerTweaks"
>
{{ $t('templates.globalSections.docker.applyDockerTweaks') }}
</a>
<p>
{{ $t('templates.globalSections.docker.applyDockerTweaksForNginx') }}
<br />
<small v-html="$t('templates.globalSections.docker.applyDockerTweaksExplainer')"></small>
<small
v-html="
$t('templates.globalSections.docker.applyDockerTweaksExplainer')
"
></small>
</p>
</div>
</div>
@@ -51,7 +58,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${dockerfileChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="dockerfile" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="dockerfile"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.docker.includeDockerfile') }}
</PrettyCheck>
</div>
@@ -59,15 +69,23 @@ THE SOFTWARE.
</div>
</div>
</div>
<div v-if="dockerfile" class="field is-horizontal">
<div
v-if="dockerfile"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.docker.dockerCompose') }}</label>
<label class="label">
{{ $t('templates.globalSections.docker.dockerCompose') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${dockerComposeChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="dockerCompose" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="dockerCompose"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.docker.includeDockerCompose') }}
</PrettyCheck>
</div>
@@ -96,15 +114,15 @@ THE SOFTWARE.
};
export default {
name: 'GlobalDocker', // Component name
display: 'templates.globalSections.docker.docker', // Display name for tab (i18n key)
key: 'docker', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalDocker', // Component name
display: 'templates.globalSections.docker.docker', // Display name for tab (i18n key)
key: 'docker', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'docker'), // Getters & setters for the delegated data
watch: {
@@ -113,7 +131,8 @@ THE SOFTWARE.
handler(data) {
if (data.computed) {
this.$props.data.dockerCompose.enabled = true;
this.$props.data.dockerCompose.computed = this.$props.data.dockerCompose.value;
this.$props.data.dockerCompose.computed =
this.$props.data.dockerCompose.value;
} else {
this.$props.data.dockerCompose.enabled = false;
this.$props.data.dockerCompose.computed = false;

View File

@@ -34,7 +34,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${portReuseChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="portReuse" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="portReuse"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.https.enableReuseOfPort') }}
</PrettyCheck>
</div>
@@ -43,7 +46,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="!sslProfileEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="!sslProfileEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.https.sslProfile') }}</label>
</div>
@@ -61,17 +67,25 @@ THE SOFTWARE.
<template v-else>
<div class="field is-horizontal is-aligned-top">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.https.sslProfile') }}</label>
<label class="label">
{{ $t('templates.globalSections.https.sslProfile') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div class="field">
<div
v-for="(name, value) in $props.data.sslProfile.options"
:class="`control${sslProfileChanged && value === sslProfile ? ' is-changed' : ''}`"
:class="`control${
sslProfileChanged && value === sslProfile ? ' is-changed' : ''
}`"
>
<div class="radio">
<PrettyRadio v-model="sslProfile" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="sslProfile"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -83,24 +97,40 @@ THE SOFTWARE.
<div class="field is-horizontal is-aligned-top">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.https.ocspDnsResolvers') }}</label>
<label class="label">
{{ $t('templates.globalSections.https.ocspDnsResolvers') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${ocspCloudflareChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="ocspCloudflare" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="ocspCloudflare"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.https.cloudflareResolver') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspCloudflare.computed" class="control field is-horizontal is-expanded">
<div
v-if="$props.data.ocspCloudflare.computed"
class="control field is-horizontal is-expanded"
>
<div
v-for="(name, value) in $props.data.ocspCloudflareType.options"
:class="`control${ocspCloudflareTypeChanged && value === ocspCloudflareType ? ' is-changed' : ''}`"
:class="`control${
ocspCloudflareTypeChanged && value === ocspCloudflareType
? ' is-changed'
: ''
}`"
>
<div class="radio">
<PrettyRadio v-model="ocspCloudflareType" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="ocspCloudflareType"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -109,18 +139,32 @@ THE SOFTWARE.
<div :class="`control${ocspGoogleChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="ocspGoogle" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="ocspGoogle"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.https.googlePublicDns') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspGoogle.computed" class="control field is-horizontal is-expanded">
<div
v-if="$props.data.ocspGoogle.computed"
class="control field is-horizontal is-expanded"
>
<div
v-for="(name, value) in $props.data.ocspGoogleType.options"
:class="`control${ocspGoogleTypeChanged && value === ocspGoogleType ? ' is-changed' : ''}`"
:class="`control${
ocspGoogleTypeChanged && value === ocspGoogleType
? ' is-changed'
: ''
}`"
>
<div class="radio">
<PrettyRadio v-model="ocspGoogleType" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="ocspGoogleType"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -129,18 +173,32 @@ THE SOFTWARE.
<div :class="`control${ocspOpenDnsChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="ocspOpenDns" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="ocspOpenDns"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.https.openDns') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspOpenDns.computed" class="control field is-horizontal is-expanded">
<div
v-if="$props.data.ocspOpenDns.computed"
class="control field is-horizontal is-expanded"
>
<div
v-for="(name, value) in $props.data.ocspOpenDnsType.options"
:class="`control${ocspOpenDnsTypeChanged && value === ocspOpenDnsType ? ' is-changed' : ''}`"
:class="`control${
ocspOpenDnsTypeChanged && value === ocspOpenDnsType
? ' is-changed'
: ''
}`"
>
<div class="radio">
<PrettyRadio v-model="ocspOpenDnsType" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="ocspOpenDnsType"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -149,18 +207,32 @@ THE SOFTWARE.
<div :class="`control${ocspQuad9Changed ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="ocspQuad9" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="ocspQuad9"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.https.quad9') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspQuad9.computed" class="control field is-horizontal is-expanded">
<div
v-if="$props.data.ocspQuad9.computed"
class="control field is-horizontal is-expanded"
>
<div
v-for="(name, value) in $props.data.ocspQuad9Type.options"
:class="`control${ocspQuad9TypeChanged && value === ocspQuad9Type ? ' is-changed' : ''}`"
:class="`control${
ocspQuad9TypeChanged && value === ocspQuad9Type
? ' is-changed'
: ''
}`"
>
<div class="radio">
<PrettyRadio v-model="ocspQuad9Type" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="ocspQuad9Type"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -169,18 +241,32 @@ THE SOFTWARE.
<div :class="`control${ocspVerisignChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="ocspVerisign" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="ocspVerisign"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.https.verisign') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspVerisign.computed" class="control field is-horizontal is-expanded">
<div
v-if="$props.data.ocspVerisign.computed"
class="control field is-horizontal is-expanded"
>
<div
v-for="(name, value) in $props.data.ocspVerisignType.options"
:class="`control${ocspVerisignTypeChanged && value === ocspVerisignType ? ' is-changed' : ''}`"
:class="`control${
ocspVerisignTypeChanged && value === ocspVerisignType
? ' is-changed'
: ''
}`"
>
<div class="radio">
<PrettyRadio v-model="ocspVerisignType" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="ocspVerisignType"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -190,9 +276,14 @@ THE SOFTWARE.
</div>
</div>
<div v-if="letsEncryptRootEnabled" class="field is-horizontal">
<div
v-if="letsEncryptRootEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.https.letsEncryptWebroot') }}</label>
<label class="label">
{{ $t('templates.globalSections.https.letsEncryptWebroot') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -208,9 +299,14 @@ THE SOFTWARE.
</div>
</div>
<div v-if="letsEncryptCertRootEnabled" class="field is-horizontal">
<div
v-if="letsEncryptCertRootEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.https.letsEncryptCertRoot') }}</label>
<label class="label">
{{ $t('templates.globalSections.https.letsEncryptCertRoot') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -246,10 +342,9 @@ THE SOFTWARE.
enabled: true,
};
const validOptionCheck = data => {
const validOptionCheck = (data) => {
if (data.enabled)
if (!Object.keys(data.options).includes(data.computed))
data.computed = data.default;
if (!Object.keys(data.options).includes(data.computed)) data.computed = data.default;
};
const defaults = {
@@ -302,18 +397,18 @@ THE SOFTWARE.
};
export default {
name: 'GlobalHTTPS', // Component name
display: 'common.https', // Display name for tab (i18n key)
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalHTTPS', // Component name
display: 'common.https', // Display name for tab (i18n key)
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
watch: {
// Check SSL profile is valid
'$props.data.sslProfile': {
@@ -343,29 +438,45 @@ THE SOFTWARE.
},
'$parent.$parent.$data.domains': {
handler(data) {
let httpsEnabled = false, leEnabled = false;
let httpsEnabled = false,
leEnabled = false;
for (const domain of data) {
// Enable HTTPS server settings if any site uses HTTPS
if (domain && domain.https && domain.https.https && domain.https.https.computed) {
if (
domain &&
domain.https &&
domain.https.https &&
domain.https.https.computed
) {
this.$props.data.sslProfile.enabled = true;
this.$props.data.sslProfile.computed = this.$props.data.sslProfile.value;
this.$props.data.sslProfile.computed =
this.$props.data.sslProfile.value;
this.$props.data.ocspCloudflare.enabled = true;
this.$props.data.ocspCloudflare.computed = this.$props.data.ocspCloudflare.value;
this.$props.data.ocspCloudflare.computed =
this.$props.data.ocspCloudflare.value;
this.$props.data.ocspGoogle.enabled = true;
this.$props.data.ocspGoogle.computed = this.$props.data.ocspGoogle.value;
this.$props.data.ocspGoogle.computed =
this.$props.data.ocspGoogle.value;
this.$props.data.ocspOpenDns.enabled = true;
this.$props.data.ocspOpenDns.computed = this.$props.data.ocspOpenDns.value;
this.$props.data.ocspOpenDns.computed =
this.$props.data.ocspOpenDns.value;
this.$props.data.letsEncryptRoot.enabled = true;
this.$props.data.letsEncryptRoot.computed = this.$props.data.letsEncryptRoot.value;
this.$props.data.letsEncryptRoot.computed =
this.$props.data.letsEncryptRoot.value;
httpsEnabled = true;
}
// Enable LE webroot if any site uses LE
if (domain && domain.https && domain.https.certType
&& domain.https.certType.computed === 'letsEncrypt') {
if (
domain &&
domain.https &&
domain.https.certType &&
domain.https.certType.computed === 'letsEncrypt'
) {
this.$props.data.letsEncryptRoot.enabled = true;
this.$props.data.letsEncryptRoot.computed = this.$props.data.letsEncryptRoot.value;
this.$props.data.letsEncryptRoot.computed =
this.$props.data.letsEncryptRoot.value;
leEnabled = true;
}
}

View File

@@ -34,4 +34,4 @@ import NGINX from './nginx';
import Docker from './docker';
import Tools from './tools';
export default [ HTTPS, Security, Python, ReverseProxy, Performance, Logging, NGINX, Docker, Tools ];
export default [HTTPS, Security, Python, ReverseProxy, Performance, Logging, NGINX, Docker, Tools];

View File

@@ -34,12 +34,20 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${errorLogEnabledChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="errorLogEnabled" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="errorLogEnabled"
class="p-default p-curve p-fill p-icon"
>
{{ $t('common.enable') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.errorLogEnabled.computed" :class="`control field is-horizontal is-expanded${errorLogPathChanged ? ' is-changed' : ''}`">
<div
v-if="$props.data.errorLogEnabled.computed"
:class="`control field is-horizontal is-expanded${
errorLogPathChanged ? ' is-changed' : ''
}`"
>
<input
v-model="errorLogPath"
class="input"
@@ -51,18 +59,29 @@ THE SOFTWARE.
</div>
</div>
<div v-if="$props.data.errorLogEnabled.computed" class="field is-horizontal">
<div
v-if="$props.data.errorLogEnabled.computed"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">error_log {{ $t('templates.globalSections.logging.level') }}</label>
<label class="label">
error_log {{ $t('templates.globalSections.logging.level') }}
</label>
</div>
<div class="field-body">
<div class="field is-horizontal">
<div
v-for="value in $props.data.errorLogLevel.options"
:class="`control${errorLogLevelChanged && value === errorLogLevel ? ' is-changed' : ''}`"
:class="`control${
errorLogLevelChanged && value === errorLogLevel ? ' is-changed' : ''
}`"
>
<div class="radio">
<PrettyRadio v-model="errorLogLevel" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="errorLogLevel"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ value }}
</PrettyRadio>
</div>
@@ -79,8 +98,16 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${logNotFoundChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="logNotFound" class="p-default p-curve p-fill p-icon">
{{ $t('templates.globalSections.logging.enableFileNotFoundErrorLogging') }} error_log
<PrettyCheck
v-model="logNotFound"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.globalSections.logging.enableFileNotFoundErrorLogging',
)
}}
error_log
</PrettyCheck>
</div>
</div>
@@ -94,65 +121,119 @@ THE SOFTWARE.
</div>
<div class="field-body">
<div class="field">
<div v-if="cloudflareEnabled" :class="`control${cloudflareChanged ? ' is-changed' : ''}`">
<div
v-if="cloudflareEnabled"
:class="`control${cloudflareChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="cloudflare" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="cloudflare"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.enableCloudflare') }}
</PrettyCheck>
</div>
</div>
<div v-if="cfRayEnabled" :class="`control${cfRayChanged ? ' is-changed' : ''}`">
<div
v-if="cfRayEnabled"
:class="`control${cfRayChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="cfRay" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="cfRay"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.cfRay') }}
</PrettyCheck>
</div>
</div>
<div v-if="cfConnectingIpEnabled" :class="`control${cfConnectingIpChanged ? ' is-changed' : ''}`">
<div
v-if="cfConnectingIpEnabled"
:class="`control${cfConnectingIpChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="cfConnectingIp" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="cfConnectingIp"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.cfConnectingIp') }}
</PrettyCheck>
</div>
</div>
<div v-if="xForwardedForEnabled" :class="`control${xForwardedForChanged ? ' is-changed' : ''}`">
<div
v-if="xForwardedForEnabled"
:class="`control${xForwardedForChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="xForwardedFor" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="xForwardedFor"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.xForwardedFor') }}
</PrettyCheck>
</div>
</div>
<div v-if="xForwardedProtoEnabled" :class="`control${xForwardedProtoChanged ? ' is-changed' : ''}`">
<div
v-if="xForwardedProtoEnabled"
:class="`control${xForwardedProtoChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="xForwardedProto" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="xForwardedProto"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.xForwardedProto') }}
</PrettyCheck>
</div>
</div>
<div v-if="trueClientIpEnabled" :class="`control${trueClientIpChanged ? ' is-changed' : ''}`">
<div
v-if="trueClientIpEnabled"
:class="`control${trueClientIpChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="trueClientIp" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="trueClientIp"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.trueClientIp') }}
</PrettyCheck>
</div>
</div>
<div v-if="cfIpCountryEnabled" :class="`control${cfIpCountryChanged ? ' is-changed' : ''}`">
<div
v-if="cfIpCountryEnabled"
:class="`control${cfIpCountryChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="cfIpCountry" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="cfIpCountry"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.cfIpCountry') }}
</PrettyCheck>
</div>
</div>
<div v-if="cfVisitorEnabled" :class="`control${cfVisitorChanged ? ' is-changed' : ''}`">
<div
v-if="cfVisitorEnabled"
:class="`control${cfVisitorChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="cfVisitor" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="cfVisitor"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.cfVisitor') }}
</PrettyCheck>
</div>
</div>
<div v-if="cdnLoopEnabled" :class="`control${cdnLoopChanged ? ' is-changed' : ''}`">
<div
v-if="cdnLoopEnabled"
:class="`control${cdnLoopChanged ? ' is-changed' : ''}`"
>
<div class="checkbox">
<PrettyCheck v-model="cdnLoop" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="cdnLoop"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.logging.cdnLoop') }}
</PrettyCheck>
</div>
@@ -166,7 +247,11 @@ THE SOFTWARE.
<script>
import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults';
import { errorLogPathDefault, errorLogLevelDefault, errorLogLevelOptions } from '../../util/logging';
import {
errorLogPathDefault,
errorLogLevelDefault,
errorLogLevelOptions,
} from '../../util/logging';
import PrettyCheck from '../inputs/checkbox';
import PrettyRadio from '../inputs/radio';
@@ -227,18 +312,18 @@ THE SOFTWARE.
};
export default {
name: 'GlobalLogging', // Component name
display: 'common.logging', // Display name for tab (i18n key)
key: 'logging', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalLogging', // Component name
display: 'common.logging', // Display name for tab (i18n key)
key: 'logging', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'logging'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'logging'), // Getters & setters for the delegated data
watch: {
// Show Cloudflare header options if Cloudflare is enabled
'$props.data.cloudflare': {
@@ -247,13 +332,17 @@ THE SOFTWARE.
this.$props.data.cfRay.enabled = true;
this.$props.data.cfRay.computed = this.$props.data.cfRay.value;
this.$props.data.cfConnectingIp.enabled = true;
this.$props.data.cfConnectingIp.computed = this.$props.data.cfConnectingIp.value;
this.$props.data.cfConnectingIp.computed =
this.$props.data.cfConnectingIp.value;
this.$props.data.xForwardedFor.enabled = true;
this.$props.data.xForwardedFor.computed = this.$props.data.xForwardedFor.value;
this.$props.data.xForwardedFor.computed =
this.$props.data.xForwardedFor.value;
this.$props.data.xForwardedProto.enabled = true;
this.$props.data.xForwardedProto.computed = this.$props.data.xForwardedProto.value;
this.$props.data.xForwardedProto.computed =
this.$props.data.xForwardedProto.value;
this.$props.data.trueClientIp.enabled = true;
this.$props.data.trueClientIp.computed = this.$props.data.trueClientIp.value;
this.$props.data.trueClientIp.computed =
this.$props.data.trueClientIp.value;
this.$props.data.cfIpCountry.enabled = true;
this.$props.data.cfIpCountry.computed = this.$props.data.cfIpCountry.value;
this.$props.data.cfVisitor.enabled = true;

View File

@@ -28,7 +28,9 @@ THE SOFTWARE.
<div>
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.nginx.nginxConfigDirectory') }}</label>
<label class="label">
{{ $t('templates.globalSections.nginx.nginxConfigDirectory') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -103,7 +105,11 @@ THE SOFTWARE.
</div>
<div class="field-body">
<div class="field has-addons">
<div :class="`control is-expanded${clientMaxBodySizeChanged ? ' is-changed' : ''}`">
<div
:class="`control is-expanded${
clientMaxBodySizeChanged ? ' is-changed' : ''
}`"
>
<input
v-model.number="clientMaxBodySize"
class="input"
@@ -171,10 +177,7 @@ THE SOFTWARE.
},
workerProcesses: {
default: 'auto',
options: [
'auto',
...Array.from({ length: 16 }, (_, i) => i + 1),
],
options: ['auto', ...Array.from({ length: 16 }, (_, i) => i + 1)],
enabled: true,
},
user: {
@@ -202,17 +205,17 @@ THE SOFTWARE.
};
export default {
name: 'GlobalNGINX', // Component name
display: 'common.nginx', // Display name for tab (i18n key)
key: 'nginx', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalNGINX', // Component name
display: 'common.nginx', // Display name for tab (i18n key)
key: 'nginx', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
VueSelect,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'nginx'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'nginx'), // Getters & setters for the delegated data
watch: {
// Clean nginx directory of trailing slashes
'$props.data.nginxConfigDirectory': {
@@ -229,8 +232,7 @@ THE SOFTWARE.
handler(data) {
// This might cause recursion, but seems not to
if (data.enabled)
if (!data.options.includes(data.computed))
data.computed = data.default;
if (!data.options.includes(data.computed)) data.computed = data.default;
},
deep: true,
},
@@ -238,9 +240,7 @@ THE SOFTWARE.
'$props.data.clientMaxBodySize': {
handler(data) {
// This might cause recursion, but seems not to
if (data.enabled)
if (data.computed < 0)
data.computed = 0;
if (data.enabled) if (data.computed < 0) data.computed = 0;
},
deep: true,
},
@@ -249,8 +249,7 @@ THE SOFTWARE.
handler(data) {
// This might cause recursion, but seems not to
if (data.enabled)
if (!data.options.includes(data.computed))
data.computed = data.default;
if (!data.options.includes(data.computed)) data.computed = data.default;
},
deep: true,
},
@@ -259,8 +258,7 @@ THE SOFTWARE.
handler(data) {
// This might cause recursion, but seems not to
if (data.enabled)
if (!data.options.includes(data.computed))
data.computed = data.default;
if (!data.options.includes(data.computed)) data.computed = data.default;
},
deep: true,
},

View File

@@ -28,14 +28,23 @@ THE SOFTWARE.
<div>
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.performance.disableHtmlCaching') }}</label>
<label class="label">
{{ $t('templates.globalSections.performance.disableHtmlCaching') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${disableHtmlCachingChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="disableHtmlCaching" class="p-default p-curve p-fill p-icon">
{{ $t('templates.globalSections.performance.enableDisableHtmlCaching') }}
<PrettyCheck
v-model="disableHtmlCaching"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.globalSections.performance.enableDisableHtmlCaching',
)
}}
</PrettyCheck>
</div>
</div>
@@ -45,14 +54,21 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.performance.gzipCompression') }}</label>
<label class="label">
{{ $t('templates.globalSections.performance.gzipCompression') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${gzipCompressionChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="gzipCompression" class="p-default p-curve p-fill p-icon">
{{ $t('templates.globalSections.performance.enableGzipCompression') }}
<PrettyCheck
v-model="gzipCompression"
class="p-default p-curve p-fill p-icon"
>
{{
$t('templates.globalSections.performance.enableGzipCompression')
}}
</PrettyCheck>
</div>
</div>
@@ -62,27 +78,51 @@ THE SOFTWARE.
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">{{ $t('templates.globalSections.performance.brotliCompression') }}</label>
<label class="label">
{{ $t('templates.globalSections.performance.brotliCompression') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${brotliCompressionChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="brotliCompression" class="p-default p-curve p-fill p-icon">
{{ $t('templates.globalSections.performance.enableBrotliCompression') }}
<PrettyCheck
v-model="brotliCompression"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.globalSections.performance.enableBrotliCompression',
)
}}
</PrettyCheck>
</div>
</div>
<div v-if="showBrotliWarning" class="control">
<div
v-if="showBrotliWarning"
class="control"
>
<label class="text message is-warning">
<span class="message-body">
{{ $t('templates.globalSections.performance.brotliIsANonStandardModule') }}
{{
$t(
'templates.globalSections.performance.brotliIsANonStandardModule',
)
}}
<ExternalLink
:text="$t('templates.globalSections.performance.brotliGoogleNgxBrotliProject')"
:text="
$t(
'templates.globalSections.performance.brotliGoogleNgxBrotliProject',
)
"
link="https://github.com/google/ngx_brotli"
></ExternalLink>
{{ $t('templates.globalSections.performance.brotliForBuildingNginxWithBrotli') }}
{{
$t(
'templates.globalSections.performance.brotliForBuildingNginxWithBrotli',
)
}}
</span>
</label>
</div>
@@ -92,7 +132,9 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.performance.expirationForAssets') }}</label>
<label class="label">
{{ $t('templates.globalSections.performance.expirationForAssets') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -110,7 +152,9 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.performance.expirationForMedia') }}</label>
<label class="label">
{{ $t('templates.globalSections.performance.expirationForMedia') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -128,7 +172,9 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.performance.expirationForSvgs') }}</label>
<label class="label">
{{ $t('templates.globalSections.performance.expirationForSvgs') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -146,7 +192,9 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.performance.expirationForFonts') }}</label>
<label class="label">
{{ $t('templates.globalSections.performance.expirationForFonts') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -202,19 +250,19 @@ THE SOFTWARE.
};
export default {
name: 'GlobalPerformance', // Component name
display: 'templates.globalSections.performance.performance', // Display name for tab (i18n key)
key: 'performance', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalPerformance', // Component name
display: 'templates.globalSections.performance.performance', // Display name for tab (i18n key)
key: 'performance', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
ExternalLink,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: {
...computedFromDefaults(defaults, 'performance'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'performance'), // Getters & setters for the delegated data
showBrotliWarning() {
return this.$props.data.brotliCompression.computed;
},

View File

@@ -26,9 +26,14 @@ THE SOFTWARE.
<template>
<div>
<div v-if="!pythonServerEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="!pythonServerEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.python.pythonServer') }}</label>
<label class="label">
{{ $t('templates.globalSections.python.pythonServer') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -41,9 +46,14 @@ THE SOFTWARE.
</div>
</div>
<div v-else class="field is-horizontal">
<div
v-else
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.python.pythonServer') }}</label>
<label class="label">
{{ $t('templates.globalSections.python.pythonServer') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -73,12 +83,12 @@ THE SOFTWARE.
};
export default {
name: 'GlobalPython', // Component name
display: 'common.python', // Display name for tab (i18n key)
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalPython', // Component name
display: 'common.python', // Display name for tab (i18n key)
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'python'), // Getters & setters for the delegated data
watch: {
@@ -86,9 +96,15 @@ THE SOFTWARE.
'$parent.$parent.$data.domains': {
handler(data) {
for (const domain of data) {
if (domain && domain.python && domain.python.python && domain.python.python.computed) {
if (
domain &&
domain.python &&
domain.python.python &&
domain.python.python.computed
) {
this.$props.data.pythonServer.enabled = true;
this.$props.data.pythonServer.computed = this.$props.data.pythonServer.value;
this.$props.data.pythonServer.computed =
this.$props.data.pythonServer.value;
return;
}
}

View File

@@ -26,7 +26,10 @@ THE SOFTWARE.
<template>
<div>
<div v-if="!reverseProxyEnabled" class="field is-horizontal is-aligned-top">
<div
v-if="!reverseProxyEnabled"
class="field is-horizontal is-aligned-top"
>
<div class="field-label">
<label class="label">{{ $t('common.reverseProxy') }}</label>
</div>
@@ -34,7 +37,11 @@ THE SOFTWARE.
<div class="field">
<div class="control">
<label class="text">
{{ $t('templates.globalSections.reverseProxy.reverseProxyMustBeEnabledOnOneSite') }}
{{
$t(
'templates.globalSections.reverseProxy.reverseProxyMustBeEnabledOnOneSite',
)
}}
</label>
</div>
</div>
@@ -48,7 +55,11 @@ THE SOFTWARE.
</div>
<div class="field-body">
<div class="field has-addons">
<div :class="`control is-expanded${proxyConnectTimeoutChanged ? ' is-changed' : ''}`">
<div
:class="`control is-expanded${
proxyConnectTimeoutChanged ? ' is-changed' : ''
}`"
>
<input
v-model.number="proxyConnectTimeout"
class="input"
@@ -73,7 +84,11 @@ THE SOFTWARE.
</div>
<div class="field-body">
<div class="field has-addons">
<div :class="`control is-expanded${proxySendTimeoutChanged ? ' is-changed' : ''}`">
<div
:class="`control is-expanded${
proxySendTimeoutChanged ? ' is-changed' : ''
}`"
>
<input
v-model.number="proxySendTimeout"
class="input"
@@ -98,7 +113,11 @@ THE SOFTWARE.
</div>
<div class="field-body">
<div class="field has-addons">
<div :class="`control is-expanded${proxyReadTimeoutChanged ? ' is-changed' : ''}`">
<div
:class="`control is-expanded${
proxyReadTimeoutChanged ? ' is-changed' : ''
}`"
>
<input
v-model.number="proxyReadTimeout"
class="input"
@@ -125,11 +144,21 @@ THE SOFTWARE.
<div class="field">
<div class="field">
<div
v-for="(name, value) in $props.data.proxyCoexistenceXForwarded.options"
:class="`control${proxyCoexistenceXForwardedChanged && value === proxyCoexistenceXForwarded ? ' is-changed' : ''}`"
v-for="(name, value) in $props.data.proxyCoexistenceXForwarded
.options"
:class="`control${
proxyCoexistenceXForwardedChanged &&
value === proxyCoexistenceXForwarded
? ' is-changed'
: ''
}`"
>
<div class="radio">
<PrettyRadio v-model="proxyCoexistenceXForwarded" :value="value" class="p-default p-round p-fill p-icon">
<PrettyRadio
v-model="proxyCoexistenceXForwarded"
:value="value"
class="p-default p-round p-fill p-icon"
>
{{ $t(name) }}
</PrettyRadio>
</div>
@@ -173,7 +202,7 @@ THE SOFTWARE.
},
};
const validTimeout = data => {
const validTimeout = (data) => {
let val = parseFloat(data.computed);
// Use default if we've got an invalid setting
@@ -186,38 +215,46 @@ THE SOFTWARE.
};
export default {
name: 'GlobalReverseProxy', // Component name
display: 'common.reverseProxy', // Display name for tab (i18n key)
key: 'reverseProxy', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalReverseProxy', // Component name
display: 'common.reverseProxy', // Display name for tab (i18n key)
key: 'reverseProxy', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data() {
return {
reverseProxyEnabled: false,
};
},
computed: computedFromDefaults(defaults, 'reverseProxy'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'reverseProxy'), // Getters & setters for the delegated data
watch: {
// Disable all options if Reverse proxy is disabled
'$parent.$parent.$data.domains': {
handler(data) {
for (const domain of data) {
if (domain && domain.reverseProxy && domain.reverseProxy.reverseProxy
&& domain.reverseProxy.reverseProxy.computed) {
if (
domain &&
domain.reverseProxy &&
domain.reverseProxy.reverseProxy &&
domain.reverseProxy.reverseProxy.computed
) {
this.$data.reverseProxyEnabled = true;
this.$props.data.proxyConnectTimeout.enabled = true;
this.$props.data.proxyConnectTimeout.computed = this.$props.data.proxyConnectTimeout.value;
this.$props.data.proxyConnectTimeout.computed =
this.$props.data.proxyConnectTimeout.value;
this.$props.data.proxySendTimeout.enabled = true;
this.$props.data.proxySendTimeout.computed = this.$props.data.proxySendTimeout.value;
this.$props.data.proxySendTimeout.computed =
this.$props.data.proxySendTimeout.value;
this.$props.data.proxyReadTimeout.enabled = true;
this.$props.data.proxyReadTimeout.computed = this.$props.data.proxyReadTimeout.value;
this.$props.data.proxyReadTimeout.computed =
this.$props.data.proxyReadTimeout.value;
this.$props.data.proxyCoexistenceXForwarded.enabled = true;
this.$props.data.proxyCoexistenceXForwarded.computed = this.$props.data.proxyCoexistenceXForwarded.value;
this.$props.data.proxyCoexistenceXForwarded.computed =
this.$props.data.proxyCoexistenceXForwarded.value;
return;
}
}

View File

@@ -43,7 +43,9 @@ THE SOFTWARE.
</div>
</div>
<div :class="`field is-horizontal${hasWordPress && !hasUnsafeEval ? ' is-aligned-top' : ''}`">
<div
:class="`field is-horizontal${hasWordPress && !hasUnsafeEval ? ' is-aligned-top' : ''}`"
>
<div class="field-label">
<label class="label">Content-Security-Policy</label>
</div>
@@ -57,11 +59,18 @@ THE SOFTWARE.
:placeholder="$props.data.contentSecurityPolicy.default"
/>
</div>
<div v-if="hasWordPress && !hasWordPressUnsafeEval" class="control">
<div
v-if="hasWordPress && !hasWordPressUnsafeEval"
class="control"
>
<label class="text message is-warning">
<span
class="message-body"
v-html="$t('templates.globalSections.security.whenUsingWordPressUnsafeEvalIsOftenRequiredToAllowFunctionality')"
v-html="
$t(
'templates.globalSections.security.whenUsingWordPressUnsafeEvalIsOftenRequiredToAllowFunctionality',
)
"
/>
</label>
</div>
@@ -95,7 +104,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${serverTokensChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="serverTokens" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="serverTokens"
class="p-default p-curve p-fill p-icon"
>
{{ $t('common.enable') }}
</PrettyCheck>
</div>
@@ -112,7 +124,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${limitReqChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="limitReq" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="limitReq"
class="p-default p-curve p-fill p-icon"
>
{{ $t('common.enable') }}
</PrettyCheck>
</div>
@@ -129,7 +144,10 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${securityTxt ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="securityTxt" class="p-default p-curve p-fill p-icon">
<PrettyCheck
v-model="securityTxt"
class="p-default p-curve p-fill p-icon"
>
{{ $t('common.enable') }}
</PrettyCheck>
</div>
@@ -138,7 +156,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="$props.data.securityTxt.computed" class="field is-horizontal">
<div
v-if="$props.data.securityTxt.computed"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">security.txt path</label>
</div>
@@ -180,7 +201,8 @@ THE SOFTWARE.
enabled: true,
},
contentSecurityPolicy: {
default: 'default-src \'self\' http: https: ws: wss: data: blob: \'unsafe-inline\'; frame-ancestors \'self\';',
default:
"default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';",
enabled: true,
},
permissionsPolicy: {
@@ -206,25 +228,30 @@ THE SOFTWARE.
};
export default {
name: 'GlobalSecurity', // Component name
display: 'templates.globalSections.security.security', // Display name for tab (i18n key)
key: 'security', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalSecurity', // Component name
display: 'templates.globalSections.security.security', // Display name for tab (i18n key)
key: 'security', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
VueSelect,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
computed: {
...computedFromDefaults(defaults, 'security'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'security'), // Getters & setters for the delegated data
hasWordPress() {
return this.$parent.$parent.$data.domains.some(d => d && d.php.wordPressRules.computed);
return this.$parent.$parent.$data.domains.some(
(d) => d && d.php.wordPressRules.computed,
);
},
hasWordPressUnsafeEval() {
return this.$props.data.contentSecurityPolicy.computed
.match(/(default|script)-src[^;]+'self'[^;]+'unsafe-inline'[^;]+'unsafe-eval'[^;]*;/) !== null;
return (
this.$props.data.contentSecurityPolicy.computed.match(
/(default|script)-src[^;]+'self'[^;]+'unsafe-inline'[^;]+'unsafe-eval'[^;]*;/,
) !== null
);
},
hasWarnings() {
return this.hasWordPress && !this.hasWordPressUnsafeEval;
@@ -236,8 +263,7 @@ THE SOFTWARE.
handler(data) {
// This might cause recursion, but seems not to
if (data.enabled)
if (!data.options.includes(data.computed))
data.computed = data.default;
if (!data.options.includes(data.computed)) data.computed = data.default;
},
deep: true,
},

View File

@@ -28,14 +28,23 @@ THE SOFTWARE.
<div>
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.tools.modularizedStructure') }}</label>
<label class="label">
{{ $t('templates.globalSections.tools.modularizedStructure') }}
</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${modularizedStructureChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="modularizedStructure" class="p-default p-curve p-fill p-icon">
{{ $t('templates.globalSections.tools.enableModularizedConfigFiles') }}
<PrettyCheck
v-model="modularizedStructure"
class="p-default p-curve p-fill p-icon"
>
{{
$t(
'templates.globalSections.tools.enableModularizedConfigFiles',
)
}}
</PrettyCheck>
</div>
</div>
@@ -43,7 +52,10 @@ THE SOFTWARE.
</div>
</div>
<div v-if="symlinkVhostEnabled" class="field is-horizontal">
<div
v-if="symlinkVhostEnabled"
class="field is-horizontal"
>
<div class="field-label">
<label class="label"></label>
</div>
@@ -51,8 +63,12 @@ THE SOFTWARE.
<div class="field">
<div :class="`control${symlinkVhostChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="symlinkVhost" class="p-default p-curve p-fill p-icon">
{{ $t('templates.globalSections.tools.enableSymLinksFrom') }} sites-available/
<PrettyCheck
v-model="symlinkVhost"
class="p-default p-curve p-fill p-icon"
>
{{ $t('templates.globalSections.tools.enableSymLinksFrom') }}
sites-available/
{{ $t('templates.globalSections.tools.to') }} sites-enabled/
</PrettyCheck>
</div>
@@ -63,7 +79,9 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.tools.shareConfiguration') }}</label>
<label class="label">
{{ $t('templates.globalSections.tools.shareConfiguration') }}
</label>
</div>
<div class="field-body">
<div class="field">
@@ -82,22 +100,39 @@ THE SOFTWARE.
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ $t('templates.globalSections.tools.resetConfiguration') }}</label>
<label class="label">
{{ $t('templates.globalSections.tools.resetConfiguration') }}
</label>
</div>
<div class="field-body">
<div class="field is-grouped">
<div class="control">
<a class="button is-danger is-outline is-mini" @click="resetGlobal">
<a
class="button is-danger is-outline is-mini"
@click="resetGlobal"
>
{{ $t('templates.globalSections.tools.resetGlobalConfig') }}
</a>
</div>
<div v-if="hasDomain" class="control">
<a class="button is-danger is-outline is-mini" @click="resetDomains">
<div
v-if="hasDomain"
class="control"
>
<a
class="button is-danger is-outline is-mini"
@click="resetDomains"
>
{{ $t('templates.globalSections.tools.resetAllDomains') }}
</a>
</div>
<div v-if="hasDomain" class="control">
<a class="button is-danger is-outline is-mini" @click="removeDomains">
<div
v-if="hasDomain"
class="control"
>
<a
class="button is-danger is-outline is-mini"
@click="removeDomains"
>
{{ $t('templates.globalSections.tools.removeAllDomains') }}
</a>
</div>
@@ -106,22 +141,30 @@ THE SOFTWARE.
</div>
<div class="field is-horizontal">
<div class="field-label">
</div>
<div class="field-label"></div>
<div class="field-body is-vertical">
<div v-for="domainData in $parent.$parent.activeDomains" class="field is-horizontal">
<div
v-for="domainData in $parent.$parent.activeDomains"
class="field is-horizontal"
>
<div class="field-label">
<label class="label">{{ domainData[0].server.domain.computed }}</label>
</div>
<div class="field-body">
<div class="field is-grouped">
<div class="control">
<a class="button is-danger is-outline is-mini" @click="resetDomain(domainData[1])">
<a
class="button is-danger is-outline is-mini"
@click="resetDomain(domainData[1])"
>
{{ $t('templates.globalSections.tools.resetDomainConfig') }}
</a>
</div>
<div class="control">
<a class="button is-danger is-outline is-mini" @click="removeDomain(domainData[1])">
<a
class="button is-danger is-outline is-mini"
@click="removeDomain(domainData[1])"
>
{{ $t('templates.globalSections.tools.removeDomain') }}
</a>
</div>
@@ -131,12 +174,21 @@ THE SOFTWARE.
</div>
</div>
<Modal ref="confirmModal" :title="confirmTitle">
<Modal
ref="confirmModal"
:title="confirmTitle"
>
<p>{{ confirmBody }}</p>
<a class="button is-danger is-outline" @click="doConfirmAction">
<a
class="button is-danger is-outline"
@click="doConfirmAction"
>
{{ $t('templates.globalSections.tools.yesImSure') }}
</a>
<a class="button is-outline" @click="$refs.confirmModal.close()">
<a
class="button is-outline"
@click="$refs.confirmModal.close()"
>
{{ $t('templates.globalSections.tools.noCancel') }}
</a>
</Modal>
@@ -163,16 +215,16 @@ THE SOFTWARE.
};
export default {
name: 'GlobalTools', // Component name
display: 'templates.globalSections.tools.tools', // Display name for tab (i18n key)
key: 'tools', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalTools', // Component name
display: 'templates.globalSections.tools.tools', // Display name for tab (i18n key)
key: 'tools', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
Modal,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data() {
return {
@@ -182,7 +234,7 @@ THE SOFTWARE.
};
},
computed: {
...computedFromDefaults(defaults, 'tools'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'tools'), // Getters & setters for the delegated data
hasDomain() {
return this.$parent.$parent.activeDomains.length > 0;
},
@@ -204,7 +256,8 @@ THE SOFTWARE.
handler(data) {
if (data.computed) {
this.$props.data.symlinkVhost.enabled = true;
this.$props.data.symlinkVhost.computed = this.$props.data.symlinkVhost.value;
this.$props.data.symlinkVhost.computed =
this.$props.data.symlinkVhost.value;
} else {
this.$props.data.symlinkVhost.enabled = false;
this.$props.data.symlinkVhost.computed = false;
@@ -227,8 +280,8 @@ THE SOFTWARE.
doResetDomain(domain) {
if (!domain) return;
Object.values(domain).forEach(category => {
Object.values(category).forEach(property => {
Object.values(domain).forEach((category) => {
Object.values(category).forEach((property) => {
property.value = property.default;
property.computed = property.default;
});
@@ -246,8 +299,8 @@ THE SOFTWARE.
this.resetGlobalEvent();
// Do the reset
Object.values(this.$parent.$props.data).forEach(category => {
Object.values(category).forEach(property => {
Object.values(this.$parent.$props.data).forEach((category) => {
Object.values(category).forEach((property) => {
property.value = property.default;
property.computed = property.default;
});
@@ -262,7 +315,9 @@ THE SOFTWARE.
this.confirm(
this.$t('templates.globalSections.tools.resetDomainConfig'),
`${this.$t('templates.globalSections.tools.areYouSureYouWantToResetAllConfigurationOptionsForThe')}
`${this.$t(
'templates.globalSections.tools.areYouSureYouWantToResetAllConfigurationOptionsForThe',
)}
${domain.server.domain.computed}
${this.$t('templates.globalSections.tools.domain')}`,
() => {
@@ -300,7 +355,9 @@ THE SOFTWARE.
() => {
// Analytics
this.resetDomainsEvent(
this.$parent.$parent.activeDomains.map(x => x[0].server.domain.computed),
this.$parent.$parent.activeDomains.map(
(x) => x[0].server.domain.computed,
),
this.$parent.$parent.activeDomains.length,
);
@@ -318,7 +375,9 @@ THE SOFTWARE.
() => {
// Analytics
this.removeDomainsEvent(
this.$parent.$parent.activeDomains.map(x => x[0].server.domain.computed),
this.$parent.$parent.activeDomains.map(
(x) => x[0].server.domain.computed,
),
this.$parent.$parent.activeDomains.length,
);
@@ -350,7 +409,10 @@ THE SOFTWARE.
});
// Also fire the general site removal event
this.$parent.$parent.removeSiteEvent(this.$parent.$parent.activeDomains.length - 1, name);
this.$parent.$parent.removeSiteEvent(
this.$parent.$parent.activeDomains.length - 1,
name,
);
},
resetDomainsEvent(names, count) {
analytics({
@@ -370,7 +432,10 @@ THE SOFTWARE.
// Also fire the general site removal event
for (let i = 0; i < this.$parent.$parent.$data.domains.length; i++)
this.$parent.$parent.removeSiteEvent(this.$parent.$parent.activeDomains.length - i - 1, names[i]);
this.$parent.$parent.removeSiteEvent(
this.$parent.$parent.activeDomains.length - i - 1,
names[i],
);
},
select(event) {
event.target.setSelectionRange(0, event.target.value.length);

View File

@@ -34,8 +34,14 @@ THE SOFTWARE.
</template>
<!-- Load in all other slots -->
<template v-for="(_, slot) in $slots" #[slot]="scope">
<slot :name="slot" v-bind="scope || {}" />
<template
v-for="(_, slot) in $slots"
#[slot]="scope"
>
<slot
:name="slot"
v-bind="scope || {}"
/>
</template>
</PrettyCheck>
</template>

View File

@@ -34,8 +34,14 @@ THE SOFTWARE.
</template>
<!-- Load in all other slots -->
<template v-for="(_, slot) in $slots" #[slot]="scope">
<slot :name="slot" v-bind="scope || {}" />
<template
v-for="(_, slot) in $slots"
#[slot]="scope"
>
<slot
:name="slot"
v-bind="scope || {}"
/>
</template>
</PrettyRadio>
</template>

View File

@@ -25,7 +25,10 @@ THE SOFTWARE.
-->
<template>
<div :class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`" @copied="copied">
<div
:class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`"
@copied="copied"
>
<h3 v-html="name"></h3>
<pre><code class="language-docker" v-html="conf"></code></pre>
</div>

View File

@@ -25,7 +25,10 @@ THE SOFTWARE.
-->
<template>
<div :class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`" @copied="copied">
<div
:class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`"
@copied="copied"
>
<h3 v-html="name"></h3>
<pre><code class="language-nginx" v-html="conf"></code></pre>
</div>

View File

@@ -25,7 +25,10 @@ THE SOFTWARE.
-->
<template>
<div :class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`" @copied="copied">
<div
:class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`"
@copied="copied"
>
<h3 v-html="name"></h3>
<pre><code class="language-yaml" v-html="conf"></code></pre>
</div>

View File

@@ -29,7 +29,10 @@ THE SOFTWARE.
<div class="panel">
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="tabClass(tab.key)">
<li
v-for="tab in tabs"
:class="tabClass(tab.key)"
>
<a @click="showTab(tab.key)">{{ $t(tab.display) }}</a>
</li>
</ul>
@@ -45,18 +48,38 @@ THE SOFTWARE.
></component>
<div class="navigation-buttons">
<a v-if="previousTab !== false" class="button is-mini" @click="showPreviousTab">
<i class="fas fa-long-arrow-alt-left"></i> <span>{{ $t('common.back') }}</span>
<a
v-if="previousTab !== false"
class="button is-mini"
@click="showPreviousTab"
>
<i class="fas fa-long-arrow-alt-left"></i>
<span>{{ $t('common.back') }}</span>
</a>
<a v-if="nextTab !== false" class="button is-primary is-mini" @click="showNextTab">
<span>{{ $t('common.next') }}</span> <i class="fas fa-long-arrow-alt-right"></i>
<a
v-if="nextTab !== false"
class="button is-primary is-mini"
@click="showNextTab"
>
<span>{{ $t('common.next') }}</span>
<i class="fas fa-long-arrow-alt-right"></i>
</a>
</div>
</div>
<div class="buttons is-centered">
<a class="button is-success" @click="downloadTar">{{ $t('templates.setup.downloadConfig') }}</a>
<a ref="copyTar" class="button is-primary">{{ $t('templates.setup.copyBase64') }}</a>
<a
class="button is-success"
@click="downloadTar"
>
{{ $t('templates.setup.downloadConfig') }}
</a>
<a
ref="copyTar"
class="button is-primary"
>
{{ $t('templates.setup.copyBase64') }}
</a>
</div>
</div>
</template>
@@ -80,22 +103,24 @@ THE SOFTWARE.
},
computed: {
nextTab() {
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
const index = tabs.indexOf(this.$data.active) + 1;
if (index < tabs.length) return tabs[index];
return false;
},
previousTab() {
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
const index = tabs.indexOf(this.$data.active) - 1;
if (index >= 0) return tabs[index];
return false;
},
domainCount() {
return this.$props.data.domains.filter(d => d !== null).length;
return this.$props.data.domains.filter((d) => d !== null).length;
},
tarName() {
const domains = this.$props.data.domains.filter(d => d !== null).map(d => d.server.domain.computed);
const domains = this.$props.data.domains
.filter((d) => d !== null)
.map((d) => d.server.domain.computed);
return `nginxconfig.io-${domains.join(',')}.tar.gz`;
},
},
@@ -105,7 +130,7 @@ THE SOFTWARE.
methods: {
tabClass(tab) {
if (tab === this.$data.active) return 'is-active';
const tabs = this.$data.tabs.map(t => t.key);
const tabs = this.$data.tabs.map((t) => t.key);
if (tabs.indexOf(tab) < tabs.indexOf(this.$data.active)) return 'is-before';
return undefined;
},
@@ -114,12 +139,18 @@ THE SOFTWARE.
// Add all our config files to the tar
for (const fileName in this.$props.data.confFiles) {
if (!Object.prototype.hasOwnProperty.call(this.$props.data.confFiles, fileName)) continue;
if (!Object.prototype.hasOwnProperty.call(this.$props.data.confFiles, fileName))
continue;
data[fileName] = { contents: this.$props.data.confFiles[fileName] };
// If symlinks are enabled and this is in sites-available, symlink to sites-enabled
if (this.$props.data.global.tools.symlinkVhost.computed && fileName.startsWith('sites-available'))
data[fileName.replace(/^sites-available/, 'sites-enabled')] = { target: `../${fileName}` };
if (
this.$props.data.global.tools.symlinkVhost.computed &&
fileName.startsWith('sites-available')
)
data[fileName.replace(/^sites-available/, 'sites-enabled')] = {
target: `../${fileName}`,
};
}
return new Tar(data).gz();
@@ -160,7 +191,7 @@ THE SOFTWARE.
text: this.copyTar,
});
clipboard.on('success', e => {
clipboard.on('success', (e) => {
const originalTextCopy = elm.textContent;
elm.textContent = this.$t('templates.app.copied');
e.clearSelection();

View File

@@ -29,7 +29,9 @@ THE SOFTWARE.
<ol v-if="letsEncryptActive">
<li>
<p>
{{ $t('templates.setupSections.certbot.commentOutSslDirectivesInConfiguration') }}
{{
$t('templates.setupSections.certbot.commentOutSslDirectivesInConfiguration')
}}
<br />
</p>
<BashPrism
@@ -71,7 +73,9 @@ THE SOFTWARE.
<li>
<p>
{{ $t('templates.setupSections.certbot.uncommentSslDirectivesInConfiguration') }}
{{
$t('templates.setupSections.certbot.uncommentSslDirectivesInConfiguration')
}}
<br />
</p>
<BashPrism
@@ -94,7 +98,11 @@ THE SOFTWARE.
<li>
<p>
{{ $t('templates.setupSections.certbot.configureCertbotToReloadNginxOnCertificateRenewal') }}
{{
$t(
'templates.setupSections.certbot.configureCertbotToReloadNginxOnCertificateRenewal',
)
}}
<br />
</p>
<BashPrism
@@ -108,12 +116,19 @@ THE SOFTWARE.
</li>
</ol>
<div v-else class="field is-horizontal">
<div
v-else
class="field is-horizontal"
>
<div class="field-body">
<div class="field">
<div class="control">
<label class="text">
{{ $t('templates.setupSections.certbot.certbotDoesNotNeedToBeSetupForYourConfiguration') }}
{{
$t(
'templates.setupSections.certbot.certbotDoesNotNeedToBeSetupForYourConfiguration',
)
}}
</label>
</div>
</div>
@@ -152,26 +167,38 @@ THE SOFTWARE.
if (!this.$props.data.global.tools.modularizedStructure.computed)
return `${this.$props.data.global.nginx.nginxConfigDirectory.computed}/nginx.conf`;
const enabledAvailable = this.$props.data.global.tools.symlinkVhost.computed ? 'available' : 'enabled';
const enabledAvailable = this.$props.data.global.tools.symlinkVhost.computed
? 'available'
: 'enabled';
return this.$props.data.domains
.filter(domain => domain.https.certType.computed === 'letsEncrypt')
.map(domain => `${this.$props.data.global.nginx.nginxConfigDirectory.computed}/sites-${enabledAvailable}/${domain.server.domain.computed}.conf`)
.filter((domain) => domain.https.certType.computed === 'letsEncrypt')
.map(
(domain) =>
`${this.$props.data.global.nginx.nginxConfigDirectory.computed}/sites-${enabledAvailable}/${domain.server.domain.computed}.conf`,
)
.join(' ');
},
certbotCmds() {
return this.$props.data.domains
.filter(domain => domain.https.certType.computed === 'letsEncrypt')
.map(domain => (
.filter((domain) => domain.https.certType.computed === 'letsEncrypt')
.map((domain) =>
[
'certbot certonly --webroot',
`-d ${domain.server.domain.computed}`,
domain.server.wwwSubdomain.computed ? `-d www.${domain.server.domain.computed}` : null,
domain.server.cdnSubdomain.computed ? `-d cdn.${domain.server.domain.computed}` : null,
domain.server.wwwSubdomain.computed
? `-d www.${domain.server.domain.computed}`
: null,
domain.server.cdnSubdomain.computed
? `-d cdn.${domain.server.domain.computed}`
: null,
`--email ${domain.https.letsEncryptEmail.computed}`,
`-w ${this.letsEncryptDir}`,
'-n --agree-tos --force-renewal',
].filter(x => x !== null).join(' ')
)).join('\n');
]
.filter((x) => x !== null)
.join(' '),
)
.join('\n');
},
},
methods: {

View File

@@ -29,26 +29,52 @@ THE SOFTWARE.
<ol>
<li>
<p>
<span v-html="$t('templates.setupSections.download.downloadTheGeneratedConfig')"></span>
<b>&nbsp;<a @click="$parent.downloadTar">{{ $parent.tarName }}</a></b>
<span
v-html="$t('templates.setupSections.download.downloadTheGeneratedConfig')"
></span>
<b>
&nbsp;
<a @click="$parent.downloadTar">{{ $parent.tarName }}</a>
</b>
<br />
<span v-html="$t('templates.setupSections.download.andUploadItToYourServers')"></span>
<code class="slim">{{ $props.data.global.nginx.nginxConfigDirectory.computed }}</code>
<span
v-html="$t('templates.setupSections.download.andUploadItToYourServers')"
></span>
<code class="slim">
{{ $props.data.global.nginx.nginxConfigDirectory.computed }}
</code>
{{ $t('templates.setupSections.download.directory') }}
</p>
<p>
{{ $t('templates.setupSections.download.or') }}
<b>
<a ref="copyTar">
{{ $t('templates.setupSections.download.copyBase64StringOfCompressedConfig') }}</a>
{{
$t(
'templates.setupSections.download.copyBase64StringOfCompressedConfig',
)
}}
</a>
</b>
<span v-html="$t('templates.setupSections.download.pasteItInYourServersCommandLineAndExecute')"></span>
<span
v-html="
$t(
'templates.setupSections.download.pasteItInYourServersCommandLineAndExecute',
)
"
></span>
</p>
</li>
<li>
<p>
<span v-html="$t('templates.setupSections.download.navigateToYourNginxConfigurationDirectoryOnYourServer')"></span>
<span
v-html="
$t(
'templates.setupSections.download.navigateToYourNginxConfigurationDirectoryOnYourServer',
)
"
></span>
<br />
<BashPrism
:key="$props.data.global.nginx.nginxConfigDirectory.computed"
@@ -60,7 +86,13 @@ THE SOFTWARE.
<li>
<p>
<span v-html="$t('templates.setupSections.download.createABackupOfYourCurrentNginxConfiguration')"></span>
<span
v-html="
$t(
'templates.setupSections.download.createABackupOfYourCurrentNginxConfiguration',
)
"
></span>
<br />
<BashPrism
cmd="tar -czvf nginx_$(date +'%F_%H-%M-%S').tar.gz nginx.conf sites-available/ sites-enabled/ nginxconfig.io/"
@@ -71,7 +103,13 @@ THE SOFTWARE.
<li>
<p>
<span v-html="$t('templates.setupSections.download.extractTheNewCompressedConfigurationArchiveUsingTar')"></span>
<span
v-html="
$t(
'templates.setupSections.download.extractTheNewCompressedConfigurationArchiveUsingTar',
)
"
></span>
<br />
<BashPrism
:key="$parent.tarName"

View File

@@ -27,7 +27,8 @@ THE SOFTWARE.
<template>
<div>
<p>
<b>{{ $t('templates.setupSections.goLive.letsGoLive') }}</b> 🎉
<b>{{ $t('templates.setupSections.goLive.letsGoLive') }}</b>
🎉
</p>
<p>
{{ $t('templates.setupSections.goLive.reloadNginxToLoadInYourNewConfiguration') }}

View File

@@ -29,4 +29,4 @@ import SSL from './ssl';
import Certbot from './certbot';
import GoLive from './go_live';
export default [ Download, SSL, Certbot, GoLive ];
export default [Download, SSL, Certbot, GoLive];

View File

@@ -29,7 +29,13 @@ THE SOFTWARE.
<ol v-if="diffieHellmanValue || letsEncryptActive">
<li v-if="diffieHellmanValue">
<p>
<span v-html="$t('templates.setupSections.ssl.generateDiffieHellmanKeysByRunningThisCommandOnYourServer')"></span>
<span
v-html="
$t(
'templates.setupSections.ssl.generateDiffieHellmanKeysByRunningThisCommandOnYourServer',
)
"
></span>
<br />
<BashPrism
:key="`${$props.data.global.nginx.nginxConfigDirectory.computed}-${diffieHellmanValue}`"
@@ -41,7 +47,13 @@ THE SOFTWARE.
<li v-if="letsEncryptActive">
<p>
<span v-html="$t('templates.setupSections.ssl.createACommonAcmeChallengeDirectoryForLetsEncrypt')"></span>
<span
v-html="
$t(
'templates.setupSections.ssl.createACommonAcmeChallengeDirectoryForLetsEncrypt',
)
"
></span>
<br />
<BashPrism
:key="letsEncryptDir"
@@ -57,12 +69,19 @@ THE SOFTWARE.
</li>
</ol>
<div v-else class="field is-horizontal">
<div
v-else
class="field is-horizontal"
>
<div class="field-body">
<div class="field">
<div class="control">
<label class="text">
{{ $t('templates.setupSections.ssl.noAdditionalStepsAreNeededToSetUpSslForNginx') }}
{{
$t(
'templates.setupSections.ssl.noAdditionalStepsAreNeededToSetUpSslForNginx',
)
}}
</label>
</div>
</div>
@@ -94,13 +113,13 @@ THE SOFTWARE.
},
diffieHellmanValue() {
switch (this.$props.data.global.https.sslProfile.computed) {
case 'intermediate':
return 2048;
case 'old':
return 1024;
case 'modern':
default:
return 0;
case 'intermediate':
return 2048;
case 'old':
return 1024;
case 'modern':
default:
return 0;
}
},
letsEncryptActive() {