Show warning icons in tabs (#260)

* Add unstyled warning to onion tab

* Style the warning icon

* Add warning for http3

* Add warning icon to global security tab

* Surface warnings for domains

* Show warning icon for duplicate domains

* Improve http3 warning string names

* Show warning message/icon for Brotli
pull/266/head
Matt (IPv4) Cowley 2021-05-13 15:28:17 +01:00 committed by GitHub
parent fe5f2b234d
commit 27d090daeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 172 additions and 79 deletions

View File

@ -42,9 +42,9 @@ export default {
certificationType: 'Certification type', certificationType: 'Certification type',
customCertificate: 'Custom certificate', customCertificate: 'Custom certificate',
letsEncryptEmail: `${common.letsEncrypt} email`, letsEncryptEmail: `${common.letsEncrypt} email`,
http3Warning1: 'HTTP/3 isn\'t a standard NGINX module, check the ', http3IsANonStandardModule: 'HTTP/3 isn\'t a standard NGINX module, check the ',
http3Warning2: 'NGINX QUIC readme ', http3NginxQuicReadme: 'NGINX QUIC readme',
http3Warning3: ' or the ', http3OrThe: ' or the ',
http3Warning4: 'Cloudflare quiche project ', http3CloudflareQuicheProject: 'Cloudflare quiche project',
http3Warning5: ' for how to build NGINX with HTTP/3!', http3ForBuildingNginxWithHttp3: ' for how to build NGINX with HTTP/3!',
}; };

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2020 DigitalOcean Copyright 2021 DigitalOcean
This code is licensed under the MIT License. This code is licensed under the MIT License.
You may obtain a copy of the License at You may obtain a copy of the License at
@ -31,6 +31,9 @@ export default {
enableGzipCompression: `${common.enable} gzip compression`, enableGzipCompression: `${common.enable} gzip compression`,
brotliCompression: 'Brotli compression', brotliCompression: 'Brotli compression',
enableBrotliCompression: `${common.enable} brotli compression`, enableBrotliCompression: `${common.enable} brotli compression`,
brotliIsANonStandardModule: 'Brotli isn\'t a standard NGINX module, check the ',
brotliGoogleNgxBrotliProject: 'Google ngx_brotli project',
brotliForBuildingNginxWithBrotli: ' for how to build NGINX with Brotli!',
expirationForAssets: 'Expiration for assets', expirationForAssets: 'Expiration for assets',
expirationForMedia: 'Expiration for media', expirationForMedia: 'Expiration for media',
expirationForSvgs: 'Expiration for SVGs', expirationForSvgs: 'Expiration for SVGs',

View File

@ -42,9 +42,9 @@ export default {
certificationType: 'Type de certification', certificationType: 'Type de certification',
customCertificate: 'Certificat personnalisé', customCertificate: 'Certificat personnalisé',
letsEncryptEmail: `E-mail ${common.letsEncrypt}`, letsEncryptEmail: `E-mail ${common.letsEncrypt}`,
http3Warning1: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate http3IsANonStandardModule: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate
http3Warning2: 'NGINX QUIC readme ', // TODO: translate http3NginxQuicReadme: 'NGINX QUIC readme', // TODO: translate
http3Warning3: ' or the ', // TODO: translate http3OrThe: ' or the ', // TODO: translate
http3Warning4: 'Cloudflare quiche project ', // TODO: translate http3CloudflareQuicheProject: 'Cloudflare quiche project', // TODO: translate
http3Warning5: ' for how to build NGINX with HTTP/3!', // TODO: translate http3ForBuildingNginxWithHttp3: ' for how to build NGINX with HTTP/3!', // TODO: translate
}; };

View File

@ -31,6 +31,9 @@ export default {
enableGzipCompression: `${common.enable} la compression gzip`, enableGzipCompression: `${common.enable} la compression gzip`,
brotliCompression: 'Compression Brotli', brotliCompression: 'Compression Brotli',
enableBrotliCompression: `${common.enable} la compression brotli`, enableBrotliCompression: `${common.enable} la compression brotli`,
brotliIsANonStandardModule: 'Brotli isn\'t a standard NGINX module, check the ', // TODO: translate
brotliGoogleNgxBrotliProject: 'Google ngx_brotli project', // TODO: translate
brotliForBuildingNginxWithBrotli: ' for how to build NGINX with Brotli!', // TODO: translate
expirationForAssets: 'Expiration des assets', expirationForAssets: 'Expiration des assets',
expirationForMedia: 'Expiration des medias', expirationForMedia: 'Expiration des medias',
expirationForSvgs: 'Expiration des SVGs', expirationForSvgs: 'Expiration des SVGs',

View File

@ -42,9 +42,9 @@ export default {
certificationType: 'Tipo de certificação', certificationType: 'Tipo de certificação',
customCertificate: 'Certificado personalizado', customCertificate: 'Certificado personalizado',
letsEncryptEmail: `E-mail do ${common.letsEncrypt}`, letsEncryptEmail: `E-mail do ${common.letsEncrypt}`,
http3Warning1: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate http3IsANonStandardModule: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate
http3Warning2: 'NGINX QUIC readme ', // TODO: translate http3NginxQuicReadme: 'NGINX QUIC readme', // TODO: translate
http3Warning3: ' or the ', // TODO: translate http3OrThe: ' or the ', // TODO: translate
http3Warning4: 'Cloudflare quiche project ', // TODO: translate http3CloudflareQuicheProject: 'Cloudflare quiche project', // TODO: translate
http3Warning5: ' for how to build NGINX with HTTP/3!', // TODO: translate http3ForBuildingNginxWithHttp3: ' for how to build NGINX with HTTP/3!', // TODO: translate
}; };

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2020 DigitalOcean Copyright 2021 DigitalOcean
This code is licensed under the MIT License. This code is licensed under the MIT License.
You may obtain a copy of the License at You may obtain a copy of the License at
@ -31,6 +31,9 @@ export default {
enableGzipCompression: `${common.enable} compressão gzip`, enableGzipCompression: `${common.enable} compressão gzip`,
brotliCompression: 'Compressão Brotli', brotliCompression: 'Compressão Brotli',
enableBrotliCompression: `${common.enable} compressão brotli`, enableBrotliCompression: `${common.enable} compressão brotli`,
brotliIsANonStandardModule: 'Brotli isn\'t a standard NGINX module, check the ', // TODO: translate
brotliGoogleNgxBrotliProject: 'Google ngx_brotli project', // TODO: translate
brotliForBuildingNginxWithBrotli: ' for how to build NGINX with Brotli!', // TODO: translate
expirationForAssets: 'Expiração de ativos', expirationForAssets: 'Expiração de ativos',
expirationForMedia: 'Expiração de mídia', expirationForMedia: 'Expiração de mídia',
expirationForSvgs: 'Expiração de SVGs', expirationForSvgs: 'Expiração de SVGs',

View File

@ -42,9 +42,9 @@ export default {
certificationType: 'Тип сертификации', certificationType: 'Тип сертификации',
customCertificate: 'Другой сертификат', customCertificate: 'Другой сертификат',
letsEncryptEmail: `${common.letsEncrypt} email`, letsEncryptEmail: `${common.letsEncrypt} email`,
http3Warning1: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate http3IsANonStandardModule: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate
http3Warning2: 'NGINX QUIC readme ', // TODO: translate http3NginxQuicReadme: 'NGINX QUIC readme', // TODO: translate
http3Warning3: ' or the ', // TODO: translate http3OrThe: ' or the ', // TODO: translate
http3Warning4: 'Cloudflare quiche project ', // TODO: translate http3CloudflareQuicheProject: 'Cloudflare quiche project', // TODO: translate
http3Warning5: ' for how to build NGINX with HTTP/3!', // TODO: translate http3ForBuildingNginxWithHttp3: ' for how to build NGINX with HTTP/3!', // TODO: translate
}; };

View File

@ -31,6 +31,9 @@ export default {
enableGzipCompression: `${common.enable} gzip сжатие`, enableGzipCompression: `${common.enable} gzip сжатие`,
brotliCompression: 'Brotli сжатие', brotliCompression: 'Brotli сжатие',
enableBrotliCompression: `${common.enable} brotli сжатие`, enableBrotliCompression: `${common.enable} brotli сжатие`,
brotliIsANonStandardModule: 'Brotli isn\'t a standard NGINX module, check the ', // TODO: translate
brotliGoogleNgxBrotliProject: 'Google ngx_brotli project', // TODO: translate
brotliForBuildingNginxWithBrotli: ' for how to build NGINX with Brotli!', // TODO: translate
expirationForAssets: 'Истечение срока для ассетов', expirationForAssets: 'Истечение срока для ассетов',
expirationForMedia: 'Истечение срока для медиа файлов', expirationForMedia: 'Истечение срока для медиа файлов',
expirationForSvgs: 'Истечение срока для SVG файлов', expirationForSvgs: 'Истечение срока для SVG файлов',

View File

@ -42,9 +42,9 @@ export default {
certificationType: '证书类型', certificationType: '证书类型',
customCertificate: '本地证书', customCertificate: '本地证书',
letsEncryptEmail: `${common.letsEncrypt} 邮箱`, letsEncryptEmail: `${common.letsEncrypt} 邮箱`,
http3Warning1: 'HTTP/3 并不是一个标准的 NGINX 模块, 请查看 ', http3IsANonStandardModule: 'HTTP/3 并不是一个标准的 NGINX 模块, 请查看 ',
http3Warning2: 'NGINX QUIC 使用文档', http3NginxQuicReadme: 'NGINX QUIC 使用文档',
http3Warning3: ' 或者 ', http3OrThe: ' 或者 ',
http3Warning4: 'Cloudflare quiche 项目', http3CloudflareQuicheProject: 'Cloudflare quiche 项目',
http3Warning5: ' 以构建支持 HTTP/3 的 NGINX!', http3ForBuildingNginxWithHttp3: ' 以构建支持 HTTP/3 的 NGINX!',
}; };

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2020 DigitalOcean Copyright 2021 DigitalOcean
This code is licensed under the MIT License. This code is licensed under the MIT License.
You may obtain a copy of the License at You may obtain a copy of the License at
@ -31,6 +31,9 @@ export default {
enableGzipCompression: `${common.enable}Gzip压缩`, enableGzipCompression: `${common.enable}Gzip压缩`,
brotliCompression: 'Brotli 压缩', brotliCompression: 'Brotli 压缩',
enableBrotliCompression: `${common.enable}brotli压缩`, enableBrotliCompression: `${common.enable}brotli压缩`,
brotliIsANonStandardModule: 'Brotli isn\'t a standard NGINX module, check the ', // TODO: translate
brotliGoogleNgxBrotliProject: 'Google ngx_brotli project', // TODO: translate
brotliForBuildingNginxWithBrotli: ' for how to build NGINX with Brotli!', // TODO: translate
expirationForAssets: '资源有效期', expirationForAssets: '资源有效期',
expirationForMedia: '媒体资源有效期', expirationForMedia: '媒体资源有效期',
expirationForSvgs: 'SVGs有效期', expirationForSvgs: 'SVGs有效期',

View File

@ -42,9 +42,9 @@ export default {
certificationType: '證書類型', certificationType: '證書類型',
customCertificate: '本地證書', customCertificate: '本地證書',
letsEncryptEmail: `${common.letsEncrypt} 郵箱`, letsEncryptEmail: `${common.letsEncrypt} 郵箱`,
http3Warning1: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate http3IsANonStandardModule: 'HTTP/3 isn\'t a standard NGINX module, check the ', // TODO: translate
http3Warning2: 'NGINX QUIC readme ', // TODO: translate http3NginxQuicReadme: 'NGINX QUIC readme', // TODO: translate
http3Warning3: ' or the ', // TODO: translate http3OrThe: ' or the ', // TODO: translate
http3Warning4: 'Cloudflare quiche project ', // TODO: translate http3CloudflareQuicheProject: 'Cloudflare quiche project', // TODO: translate
http3Warning5: ' for how to build NGINX with HTTP/3!', // TODO: translate http3ForBuildingNginxWithHttp3: ' for how to build NGINX with HTTP/3!', // TODO: translate
}; };

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2020 DigitalOcean Copyright 2021 DigitalOcean
This code is licensed under the MIT License. This code is licensed under the MIT License.
You may obtain a copy of the License at You may obtain a copy of the License at
@ -31,6 +31,9 @@ export default {
enableGzipCompression: `${common.enable}Gzip壓縮`, enableGzipCompression: `${common.enable}Gzip壓縮`,
brotliCompression: 'Brotli 壓縮', brotliCompression: 'Brotli 壓縮',
enableBrotliCompression: `${common.enable}brotli壓縮`, enableBrotliCompression: `${common.enable}brotli壓縮`,
brotliIsANonStandardModule: 'Brotli isn\'t a standard NGINX module, check the ', // TODO: translate
brotliGoogleNgxBrotliProject: 'Google ngx_brotli project', // TODO: translate
brotliForBuildingNginxWithBrotli: ' for how to build NGINX with Brotli!', // TODO: translate
expirationForAssets: '資源有效期', expirationForAssets: '資源有效期',
expirationForMedia: '媒體資源有效期', expirationForMedia: '媒體資源有效期',
expirationForSvgs: 'SVGs有效期', expirationForSvgs: 'SVGs有效期',

View File

@ -53,6 +53,10 @@ THE SOFTWARE.
&.has-margin-top { &.has-margin-top {
margin-top: .75rem; margin-top: .75rem;
} }
&.has-small-margin-top {
margin-top: .25rem;
}
} }
> p { > p {

View File

@ -97,17 +97,24 @@ THE SOFTWARE.
} }
i { i {
font-size: .75em;
margin: 0; margin: 0;
} }
} }
// Handle having the remove icon as well as the add icon
i { i {
font-size: .75em; // Add domain button
&.fa-plus { &.fa-plus {
font-size: .75em;
margin: 0 .35rem 0 0; margin: 0 .35rem 0 0;
} }
// Warning icon
&.fa-exclamation-triangle {
color: $warning-hover;
font-size: .9em;
margin: 0 0 .1rem .35rem;
}
} }
} }
} }

View File

@ -66,6 +66,7 @@ THE SOFTWARE.
<li v-for="data in activeDomains" :class="data[1] === active ? 'is-active' : undefined"> <li v-for="data in activeDomains" :class="data[1] === active ? 'is-active' : undefined">
<a class="domain" @click="active = data[1]"> <a class="domain" @click="active = data[1]">
{{ data[0].server.domain.computed }}{{ changes(data[1]) }} {{ data[0].server.domain.computed }}{{ changes(data[1]) }}
<i v-if="warnings(data[1])" class="fas fa-exclamation-triangle"></i>
</a> </a>
<a class="remove" @click="remove(data[1])"> <a class="remove" @click="remove(data[1])">
<i class="fas fa-times"></i> <i class="fas fa-times"></i>
@ -79,6 +80,7 @@ THE SOFTWARE.
<template v-for="data in activeDomains"> <template v-for="data in activeDomains">
<Domain :key="data[1]" <Domain :key="data[1]"
:ref="`domain-${data[1]}`"
:data="data[0]" :data="data[0]"
:style="{ display: data[1] === active ? undefined : 'none' }" :style="{ display: data[1] === active ? undefined : 'none' }"
></Domain> ></Domain>
@ -284,6 +286,10 @@ THE SOFTWARE.
if (changes) return ` (${changes.toLocaleString()})`; if (changes) return ` (${changes.toLocaleString()})`;
return ''; return '';
}, },
warnings(index) {
if (!Object.prototype.hasOwnProperty.call(this.$refs, `domain-${index}`)) return false;
return this.$refs[`domain-${index}`][0].hasWarnings || false;
},
add() { add() {
const data = clone(Domain.delegated); const data = clone(Domain.delegated);

View File

@ -34,7 +34,10 @@ THE SOFTWARE.
<div class="tabs"> <div class="tabs">
<ul> <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) }}</a> <a @click="showTab(tab.key)">
{{ $t(tab.display) }}{{ changes(tab.key) }}
<i v-if="warnings(tab.key)" class="fas fa-exclamation-triangle"></i>
</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -42,6 +45,7 @@ THE SOFTWARE.
<component :is="tab" <component :is="tab"
v-for="tab in tabs" v-for="tab in tabs"
:key="tab.key" :key="tab.key"
:ref="tab.key"
:data="$props.data[tab.key]" :data="$props.data[tab.key]"
:style="{ display: active === tab.key ? undefined : 'none' }" :style="{ display: active === tab.key ? undefined : 'none' }"
class="container" class="container"
@ -102,6 +106,9 @@ THE SOFTWARE.
if (index >= 0) return tabs[index]; if (index >= 0) return tabs[index];
return false; return false;
}, },
hasWarnings() {
return Object.values(this.$refs).some(ref => ref[0].hasWarnings || false);
},
}, },
methods: { methods: {
changesCount(tab) { changesCount(tab) {
@ -113,6 +120,10 @@ THE SOFTWARE.
if (changes) return ` (${changes.toLocaleString()})`; if (changes) return ` (${changes.toLocaleString()})`;
return ''; return '';
}, },
warnings(tab) {
if (!Object.prototype.hasOwnProperty.call(this.$refs, tab)) return false;
return this.$refs[tab][0].hasWarnings || false;
},
setValue(tab, key, val) { setValue(tab, key, val) {
Object.assign(this.$props.data[tab][key], { value: val, computed: val }); Object.assign(this.$props.data[tab][key], { value: val, computed: val });
}, },

View File

@ -62,8 +62,8 @@ THE SOFTWARE.
</div> </div>
</div> </div>
<div v-if="http3Enabled" class="field is-horizontal"> <div v-if="http3Enabled" class="field is-horizontal is-aligned-top">
<div class="field-label"> <div class="field-label has-small-margin-top">
<label class="label">{{ $t('templates.domainSections.https.http3') }}</label> <label class="label">{{ $t('templates.domainSections.https.http3') }}</label>
</div> </div>
<div class="field-body"> <div class="field-body">
@ -76,6 +76,22 @@ THE SOFTWARE.
</PrettyCheck> </PrettyCheck>
</div> </div>
</div> </div>
<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')"
link="https://quic.nginx.org/README"
></ExternalLink>
{{ $t('templates.domainSections.https.http3OrThe') }}
<ExternalLink :text="$t('templates.domainSections.https.http3CloudflareQuicheProject')"
link="https://github.com/cloudflare/quiche/tree/master/extras/nginx"
></ExternalLink>
{{ $t('templates.domainSections.https.http3ForBuildingNginxWithHttp3') }}
</span>
</label>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -224,23 +240,6 @@ THE SOFTWARE.
</div> </div>
</div> </div>
</div> </div>
<template v-if="$props.data.http3.value">
<br />
<div class="message is-warning">
<div class="message-body">
{{ $t('templates.domainSections.https.http3Warning1') }}
<ExternalLink :text="$t('templates.domainSections.https.http3Warning2')"
link="https://quic.nginx.org/README"
></ExternalLink>
{{ $t('templates.domainSections.https.http3Warning3') }}
<ExternalLink :text="$t('templates.domainSections.https.http3Warning4')"
link="https://github.com/cloudflare/quiche/tree/master/extras/nginx"
></ExternalLink>
{{ $t('templates.domainSections.https.http3Warning5') }}
</div>
</div>
</template>
</div> </div>
</template> </template>
@ -320,7 +319,15 @@ THE SOFTWARE.
props: { 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
showHttp3Warning() {
return this.$props.data.http3.computed;
},
hasWarnings() {
return this.showHttp3Warning;
},
},
watch: { watch: {
// Disable everything if https is disabled // Disable everything if https is disabled
'$props.data.https': { '$props.data.https': {

View File

@ -98,6 +98,9 @@ THE SOFTWARE.
incorrectEnding() { 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;
},
}, },
watch: { watch: {
'$props.data.onionLocation': { '$props.data.onionLocation': {

View File

@ -49,16 +49,17 @@ THE SOFTWARE.
</div> </div>
</div> </div>
<template v-if="duplicateDomain"> <div v-if="duplicateDomain" class="field">
<br /> <div class="control">
<div class="message is-warning"> <label class="text message is-warning">
<div class="message-body"> <span class="message-body">
{{ $t('templates.domainSections.server.oneOrMoreOtherDomainsAreAlsoNamed') }} {{ $t('templates.domainSections.server.oneOrMoreOtherDomainsAreAlsoNamed') }}
<code class="slim">{{ $props.data.domain.computed }}</code>. <code class="slim">{{ $props.data.domain.computed }}</code>.
{{ $t('templates.domainSections.server.thisWillCauseIssuesWithConfigGeneration') }} {{ $t('templates.domainSections.server.thisWillCauseIssuesWithConfigGeneration') }}
</div> </span>
</label>
</div> </div>
</template> </div>
<div class="field is-horizontal"> <div class="field is-horizontal">
<div class="field-label"> <div class="field-label">
@ -204,6 +205,9 @@ THE SOFTWARE.
return this.$parent.$parent.$data.domains return this.$parent.$parent.$data.domains
.filter(d => d && d.server.domain.computed === this.$props.data.domain.computed).length > 1; .filter(d => d && d.server.domain.computed === this.$props.data.domain.computed).length > 1;
}, },
hasWarnings() {
return this.duplicateDomain;
},
}, },
watch: { watch: {
'$props.data.domain': { '$props.data.domain': {

View File

@ -29,7 +29,10 @@ THE SOFTWARE.
<div class="tabs"> <div class="tabs">
<ul> <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) }}</a> <a @click="showTab(tab.key)">
{{ $t(tab.display) }}{{ changes(tab.key) }}
<i v-if="warnings(tab.key)" class="fas fa-exclamation-triangle"></i>
</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -37,6 +40,7 @@ THE SOFTWARE.
<component :is="tab" <component :is="tab"
v-for="tab in tabs" v-for="tab in tabs"
:key="tab.key" :key="tab.key"
:ref="tab.key"
:data="$props.data[tab.key]" :data="$props.data[tab.key]"
:style="{ display: active === tab.key ? undefined : 'none' }" :style="{ display: active === tab.key ? undefined : 'none' }"
class="container" class="container"
@ -99,6 +103,10 @@ THE SOFTWARE.
if (changes) return ` (${changes.toLocaleString()})`; if (changes) return ` (${changes.toLocaleString()})`;
return ''; return '';
}, },
warnings(tab) {
if (!Object.prototype.hasOwnProperty.call(this.$refs, tab)) return false;
return this.$refs[tab][0].hasWarnings || false;
},
setValue(tab, key, val) { setValue(tab, key, val) {
Object.assign(this.$props.data[tab][key], { value: val, computed: val }); Object.assign(this.$props.data[tab][key], { value: val, computed: val });
}, },

View File

@ -44,8 +44,8 @@ THE SOFTWARE.
</div> </div>
</div> </div>
<div class="field is-horizontal"> <div class="field is-horizontal is-aligned-top">
<div class="field-label"> <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>
<div class="field-body"> <div class="field-body">
@ -58,6 +58,19 @@ THE SOFTWARE.
</PrettyCheck> </PrettyCheck>
</div> </div>
</div> </div>
<div v-if="showBrotliWarning" class="control">
<label class="text message is-warning">
<span class="message-body">
{{ $t('templates.globalSections.performance.brotliIsANonStandardModule') }}
<ExternalLink
:text="$t('templates.globalSections.performance.brotliGoogleNgxBrotliProject')"
link="https://github.com/google/ngx_brotli"
></ExternalLink>
{{ $t('templates.globalSections.performance.brotliForBuildingNginxWithBrotli') }}
</span>
</label>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -134,6 +147,7 @@ THE SOFTWARE.
<script> <script>
import PrettyCheck from 'pretty-checkbox-vue/check'; import PrettyCheck from 'pretty-checkbox-vue/check';
import ExternalLink from 'do-vue/src/templates/external_link';
import delegatedFromDefaults from '../../util/delegated_from_defaults'; import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults'; import computedFromDefaults from '../../util/computed_from_defaults';
@ -171,10 +185,19 @@ THE SOFTWARE.
delegated: delegatedFromDefaults(defaults), // Data the parent will present here delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: { components: {
PrettyCheck, PrettyCheck,
ExternalLink,
}, },
props: { 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 computed: {
...computedFromDefaults(defaults, 'performance'), // Getters & setters for the delegated data
showBrotliWarning() {
return this.$props.data.brotliCompression.computed;
},
hasWarnings() {
return this.showBrotliWarning;
},
},
}; };
</script> </script>

View File

@ -55,14 +55,13 @@ THE SOFTWARE.
:placeholder="$props.data.contentSecurityPolicy.default" :placeholder="$props.data.contentSecurityPolicy.default"
/> />
</div> </div>
<template v-if="hasWordPress && !hasUnsafeEval"> <div v-if="hasWordPress && !hasUnsafeEval" class="control">
<br /> <label class="text message is-warning">
<div class="message is-warning"> <span class="message-body"
<div class="message-body" v-html="$t('templates.globalSections.security.whenUsingWordPressUnsafeEvalIsOftenRequiredToAllowFunctionality')"
v-html="$t('templates.globalSections.security.whenUsingWordPressUnsafeEvalIsOftenRequiredToAllowFunctionality')" ></span>
></div> </label>
</div> </div>
</template>
</div> </div>
</div> </div>
</div> </div>
@ -203,6 +202,9 @@ THE SOFTWARE.
hasUnsafeEval() { hasUnsafeEval() {
return this.$props.data.contentSecurityPolicy.computed.includes('\'unsafe-eval\''); return this.$props.data.contentSecurityPolicy.computed.includes('\'unsafe-eval\'');
}, },
hasWarnings() {
return this.hasWordPress && !this.hasUnsafeEval;
},
}, },
watch: { watch: {
// Check referrer policy selection is valid // Check referrer policy selection is valid