Refactor analytics events (#209)
* Refactor analytics.js * Update analytics calls in app.vue * Update analytics calls in presets.vue * Update analytics calls in tools.vue (and app.vue) * Update analytics calls in global.vue * Update analytics calls in domain.vue * Update analytics calls in setup.vue * Add list of all events to analytics.js * Add custom copy to clipboard that emits event * Emit the events from the components * Update copyright year in all files touched * Update analytics calls in download.vue * Update analytics calls in ssl.vue * Update analytics calls in certbot.vue * Update analytics calls in domain.vue * Update analytics calls in app.vue * Note down 'Code snippet copied' eventspull/214/head
parent
c86fb3cf76
commit
3fdccfa68a
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -101,6 +101,7 @@ THE SOFTWARE.
|
|||
:name="confContents[0]"
|
||||
:conf="confContents[1]"
|
||||
:half="Object.keys(confFilesOutput).length > 1 && !splitColumn"
|
||||
@copied="codeCopiedEvent(confContents[3])"
|
||||
></component>
|
||||
</template>
|
||||
</div>
|
||||
|
@ -125,7 +126,6 @@ THE SOFTWARE.
|
|||
import isObject from '../util/is_object';
|
||||
import analytics from '../util/analytics';
|
||||
import browserLanguage from '../util/browser_language';
|
||||
import { toSep } from '../util/language_pack_name';
|
||||
import { defaultPack } from '../util/language_pack_default';
|
||||
import { availablePacks } from '../util/language_pack_context';
|
||||
|
||||
|
@ -149,8 +149,8 @@ THE SOFTWARE.
|
|||
Global,
|
||||
Setup,
|
||||
NginxPrism,
|
||||
'YamlPrism': () => import('./prism/yaml'),
|
||||
'DockerPrism': () => import('./prism/docker'),
|
||||
YamlPrism: () => import('./prism/yaml'),
|
||||
DockerPrism: () => import('./prism/docker'),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -171,9 +171,10 @@ THE SOFTWARE.
|
|||
splitColumn: false,
|
||||
confWatcherWaiting: false,
|
||||
confFilesPrevious: {},
|
||||
confFilesOutput: {},
|
||||
confFilesOutput: [],
|
||||
languageLoading: false,
|
||||
languagePrevious: defaultPack,
|
||||
interactiveEvents: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -214,8 +215,12 @@ THE SOFTWARE.
|
|||
},
|
||||
'$data.global.app.lang': {
|
||||
handler(data) {
|
||||
// Lock out the dropdown
|
||||
this.$data.languageLoading = true;
|
||||
|
||||
// Store if we should fire the event when this is done loading
|
||||
const interactive = this.$data.interactiveEvents;
|
||||
|
||||
// Ensure valid pack
|
||||
if (!availablePacks.includes(data.value)) data.computed = data.default;
|
||||
|
||||
|
@ -227,7 +232,7 @@ THE SOFTWARE.
|
|||
this.$data.languageLoading = false;
|
||||
|
||||
// Analytics
|
||||
analytics(`set_language_${toSep(data.computed, '_')}`, 'Language');
|
||||
this.languageSetEvent(!interactive);
|
||||
}).catch((err) => {
|
||||
// Error
|
||||
console.log('Failed to set language to', data.computed);
|
||||
|
@ -255,8 +260,10 @@ THE SOFTWARE.
|
|||
if (language) this.lang = language;
|
||||
}
|
||||
|
||||
// Send an initial GA event for column mode
|
||||
// Initial analytics events
|
||||
this.splitColumnEvent(true);
|
||||
for (let i = 0; i < this.activeDomains.length; i++) this.addSiteEvent(i + 1, true);
|
||||
this.$data.interactiveEvents = true;
|
||||
},
|
||||
methods: {
|
||||
changes(index) {
|
||||
|
@ -285,15 +292,16 @@ THE SOFTWARE.
|
|||
this.$data.domains.push(data);
|
||||
this.$data.active = this.$data.domains.length - 1;
|
||||
|
||||
// GA
|
||||
analytics('add_site', 'Sites', undefined, this.activeDomains.length);
|
||||
// Analytics
|
||||
this.addSiteEvent(this.activeDomains.length);
|
||||
},
|
||||
remove(index) {
|
||||
const name = this.$data.domains[index].server.domain.computed;
|
||||
this.$set(this.$data.domains, index, null);
|
||||
if (this.$data.active === index) this.$data.active = this.$data.domains.findIndex(d => d !== null);
|
||||
|
||||
// GA
|
||||
analytics('remove_site', 'Sites', undefined, this.activeDomains.length);
|
||||
// Analytics
|
||||
this.removeSiteEvent(this.activeDomains.length, name);
|
||||
},
|
||||
checkChange(oldConf) {
|
||||
// If nothing has changed for a tick, we can use the config files
|
||||
|
@ -319,7 +327,7 @@ THE SOFTWARE.
|
|||
const diffConf = diff(newConf, oldConf, {
|
||||
highlightFunction: value => `<mark>${value}</mark>`,
|
||||
});
|
||||
this.$data.confFilesOutput = Object.values(diffConf).map(({ name, content }) => {
|
||||
this.$data.confFilesOutput = Object.entries(diffConf).map(([ file, { name, content } ]) => {
|
||||
const diffName = name.filter(x => !x.removed).map(x => x.value).join('');
|
||||
const confName = `${escape(this.$data.global.nginx.nginxConfigDirectory.computed)}/${diffName}`;
|
||||
const diffContent = content.filter(x => !x.removed).map(x => x.value).join('');
|
||||
|
@ -328,6 +336,7 @@ THE SOFTWARE.
|
|||
confName,
|
||||
diffContent,
|
||||
`${sha2_256(confName)}-${sha2_256(diffContent)}`,
|
||||
file,
|
||||
];
|
||||
});
|
||||
} catch (e) {
|
||||
|
@ -339,6 +348,7 @@ THE SOFTWARE.
|
|||
confName,
|
||||
content,
|
||||
`${sha2_256(confName)}-${sha2_256(content)}`,
|
||||
name,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
@ -351,7 +361,42 @@ THE SOFTWARE.
|
|||
this.splitColumnEvent();
|
||||
},
|
||||
splitColumnEvent(nonInteraction = false) {
|
||||
analytics('toggle_split_column', 'Button', undefined, Number(this.$data.splitColumn), nonInteraction);
|
||||
analytics({
|
||||
category: 'Split column',
|
||||
action: this.$data.splitColumn ? 'Enabled' : 'Disabled',
|
||||
nonInteraction,
|
||||
});
|
||||
},
|
||||
languageSetEvent(nonInteraction = false) {
|
||||
analytics({
|
||||
category: 'Language',
|
||||
action: 'Set',
|
||||
label: this.$data.global.app.lang.computed,
|
||||
nonInteraction,
|
||||
});
|
||||
},
|
||||
addSiteEvent(count, nonInteraction = false) {
|
||||
analytics({
|
||||
category: 'Site',
|
||||
action: 'Added',
|
||||
value: count,
|
||||
nonInteraction,
|
||||
});
|
||||
},
|
||||
removeSiteEvent(count, name) {
|
||||
analytics({
|
||||
category: 'Site',
|
||||
action: 'Removed',
|
||||
label: name,
|
||||
value: count,
|
||||
});
|
||||
},
|
||||
codeCopiedEvent(file) {
|
||||
analytics({
|
||||
category: 'Config files',
|
||||
action: 'Code snippet copied',
|
||||
label: file,
|
||||
});
|
||||
},
|
||||
getPrismComponent(confName) {
|
||||
switch (confName) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -34,7 +34,7 @@ THE SOFTWARE.
|
|||
<div class="tabs">
|
||||
<ul>
|
||||
<li v-for="tab in tabs" :class="tabClass(tab.key)">
|
||||
<a @click="active = tab.key">{{ $t(tab.display) }}{{ changes(tab.key) }}</a>
|
||||
<a @click="showTab(tab.key)">{{ $t(tab.display) }}{{ changes(tab.key) }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -48,10 +48,10 @@ THE SOFTWARE.
|
|||
></component>
|
||||
|
||||
<div class="navigation-buttons">
|
||||
<a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab">
|
||||
<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="active = nextTab">
|
||||
<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>
|
||||
|
@ -60,6 +60,7 @@ THE SOFTWARE.
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import analytics from '../util/analytics';
|
||||
import isChanged from '../util/is_changed';
|
||||
import Presets from './domain_sections/presets';
|
||||
import * as Sections from './domain_sections';
|
||||
|
@ -127,6 +128,39 @@ THE SOFTWARE.
|
|||
if (tabs.indexOf(tab) < tabs.indexOf(this.$data.active)) classes.push('is-before');
|
||||
return classes.join(' ');
|
||||
},
|
||||
showTab(target) {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Site',
|
||||
action: 'Tab clicked',
|
||||
label: `${this.$data.active}, ${target}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = target;
|
||||
},
|
||||
showPreviousTab() {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Site',
|
||||
action: 'Back clicked',
|
||||
label: `${this.$data.active}, ${this.previousTab}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = this.previousTab;
|
||||
},
|
||||
showNextTab() {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Site',
|
||||
action: 'Next clicked',
|
||||
label: `${this.$data.active}, ${this.nextTab}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = this.nextTab;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -56,7 +56,7 @@ THE SOFTWARE.
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<div class="control" v-if="incorrectEnding">
|
||||
<div v-if="incorrectEnding" class="control">
|
||||
<label class="text message is-warning">
|
||||
<span class="message-body">
|
||||
{{ $t('templates.domainSections.onion.onionLocationExpectedToEndWithOnion') }}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -56,7 +56,6 @@ THE SOFTWARE.
|
|||
import delegatedFromDefaults from '../../util/delegated_from_defaults';
|
||||
import computedFromDefaults from '../../util/computed_from_defaults';
|
||||
import analytics from '../../util/analytics';
|
||||
import camelToSnake from '../../util/camel_to_snake';
|
||||
|
||||
const defaults = {
|
||||
frontend: {
|
||||
|
@ -208,7 +207,7 @@ THE SOFTWARE.
|
|||
setPreset(key) {
|
||||
// Set that we're using this preset
|
||||
Object.keys(this.$props.data).forEach(preset => this[preset] = preset === key);
|
||||
analytics(`apply_${camelToSnake(key)}`, 'Presets');
|
||||
this.presetEvent(key, this.interacted);
|
||||
|
||||
// Restore some specific defaults first
|
||||
this.$parent.resetValue('server', 'domain');
|
||||
|
@ -271,6 +270,13 @@ THE SOFTWARE.
|
|||
break;
|
||||
}
|
||||
},
|
||||
presetEvent(name, overwrite = false) {
|
||||
analytics({
|
||||
category: 'Preset',
|
||||
action: overwrite ? 'Overwritten' : 'Applied', // TODO: Is overwritten the best word here?
|
||||
label: name,
|
||||
});
|
||||
},
|
||||
toggleCollapse() {
|
||||
if (this.interacted) {
|
||||
this.expanded = !this.expanded;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -29,7 +29,7 @@ THE SOFTWARE.
|
|||
<div class="tabs">
|
||||
<ul>
|
||||
<li v-for="tab in tabs" :class="tabClass(tab.key)">
|
||||
<a @click="active = tab.key">{{ $t(tab.display) }}{{ changes(tab.key) }}</a>
|
||||
<a @click="showTab(tab.key)">{{ $t(tab.display) }}{{ changes(tab.key) }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -43,10 +43,10 @@ THE SOFTWARE.
|
|||
></component>
|
||||
|
||||
<div class="navigation-buttons">
|
||||
<a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab">
|
||||
<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="active = nextTab">
|
||||
<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>
|
||||
|
@ -54,6 +54,7 @@ THE SOFTWARE.
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import analytics from '../util/analytics';
|
||||
import isChanged from '../util/is_changed';
|
||||
import * as Sections from './global_sections';
|
||||
|
||||
|
@ -113,6 +114,39 @@ THE SOFTWARE.
|
|||
if (tabs.indexOf(tab) < tabs.indexOf(this.$data.active)) classes.push('is-before');
|
||||
return classes.join(' ');
|
||||
},
|
||||
showTab(target) {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Global',
|
||||
action: 'Tab clicked',
|
||||
label: `${this.$data.active}, ${target}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = target;
|
||||
},
|
||||
showPreviousTab() {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Global',
|
||||
action: 'Back clicked',
|
||||
label: `${this.$data.active}, ${this.previousTab}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = this.previousTab;
|
||||
},
|
||||
showNextTab() {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Global',
|
||||
action: 'Next clicked',
|
||||
label: `${this.$data.active}, ${this.nextTab}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = this.nextTab;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -243,7 +243,10 @@ THE SOFTWARE.
|
|||
this.$t('templates.globalSections.tools.resetGlobalConfig'),
|
||||
this.$t('templates.globalSections.tools.resetGlobalConfigBody'),
|
||||
() => {
|
||||
analytics('reset_global', 'Reset');
|
||||
// Analytics
|
||||
this.resetGlobalEvent();
|
||||
|
||||
// Do the reset
|
||||
Object.values(this.$parent.$props.data).forEach(category => {
|
||||
Object.values(category).forEach(property => {
|
||||
property.value = property.default;
|
||||
|
@ -264,7 +267,10 @@ THE SOFTWARE.
|
|||
${domain.server.domain.computed}
|
||||
${this.$t('templates.globalSections.tools.domain')}`,
|
||||
() => {
|
||||
analytics('reset_domain', 'Reset', domain.server.domain.computed);
|
||||
// Analytics
|
||||
this.resetDomainEvent(domain.server.domain.computed);
|
||||
|
||||
// Do the reset
|
||||
this.doResetDomain(domain);
|
||||
},
|
||||
);
|
||||
|
@ -280,13 +286,10 @@ THE SOFTWARE.
|
|||
${domain.server.domain.computed}
|
||||
${this.$t('templates.globalSections.tools.domainConfiguration')}`,
|
||||
() => {
|
||||
analytics(
|
||||
'remove_domain',
|
||||
'Remove',
|
||||
domain.server.domain.computed,
|
||||
this.$parent.$parent.activeDomains.length - 1,
|
||||
);
|
||||
// Analytics
|
||||
this.removeDomainEvent(domain.server.domain.computed);
|
||||
|
||||
// Do the removal
|
||||
this.doRemoveDomain(index);
|
||||
},
|
||||
);
|
||||
|
@ -296,13 +299,13 @@ THE SOFTWARE.
|
|||
this.$t('templates.globalSections.tools.resetAllDomainsConfig'),
|
||||
this.$t('templates.globalSections.tools.resetAllDomainsConfigBody'),
|
||||
() => {
|
||||
analytics(
|
||||
'reset_all',
|
||||
'Reset',
|
||||
this.$parent.$parent.activeDomains.map(x => x[0].server.domain.computed).join(','),
|
||||
// Analytics
|
||||
this.resetDomainsEvent(
|
||||
this.$parent.$parent.activeDomains.map(x => x[0].server.domain.computed),
|
||||
this.$parent.$parent.activeDomains.length,
|
||||
);
|
||||
|
||||
// Do the reset
|
||||
for (let i = 0; i < this.$parent.$parent.$data.domains.length; i++) {
|
||||
this.doResetDomain(this.$parent.$parent.$data.domains[i]);
|
||||
}
|
||||
|
@ -314,19 +317,62 @@ THE SOFTWARE.
|
|||
this.$t('templates.globalSections.tools.removeAllDomains'),
|
||||
this.$t('templates.globalSections.tools.removeAllDomainsBody'),
|
||||
() => {
|
||||
analytics(
|
||||
'remove_all',
|
||||
'Remove',
|
||||
this.$parent.$parent.activeDomains.map(x => x[0].server.domain.computed).join(','),
|
||||
// Analytics
|
||||
this.removeDomainsEvent(
|
||||
this.$parent.$parent.activeDomains.map(x => x[0].server.domain.computed),
|
||||
this.$parent.$parent.activeDomains.length,
|
||||
);
|
||||
|
||||
// Do the removal
|
||||
for (let i = 0; i < this.$parent.$parent.$data.domains.length; i++) {
|
||||
this.doRemoveDomain(i);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
resetGlobalEvent() {
|
||||
analytics({
|
||||
category: 'Tools',
|
||||
action: 'Global settings reset',
|
||||
});
|
||||
},
|
||||
resetDomainEvent(name) {
|
||||
analytics({
|
||||
category: 'Tools',
|
||||
action: 'Site reset',
|
||||
label: name,
|
||||
});
|
||||
},
|
||||
removeDomainEvent(name) {
|
||||
analytics({
|
||||
category: 'Tools',
|
||||
action: 'Removed site',
|
||||
label: name,
|
||||
});
|
||||
|
||||
// Also fire the general site removal event
|
||||
this.$parent.$parent.removeSiteEvent(this.$parent.$parent.activeDomains.length - 1, name);
|
||||
},
|
||||
resetDomainsEvent(names, count) {
|
||||
analytics({
|
||||
category: 'Tools',
|
||||
action: 'All sites reset',
|
||||
label: names.join(', '),
|
||||
value: count,
|
||||
});
|
||||
},
|
||||
removeDomainsEvent(names, count) {
|
||||
analytics({
|
||||
category: 'Tools',
|
||||
action: 'All sites removed',
|
||||
label: names.join(', '),
|
||||
value: count,
|
||||
});
|
||||
|
||||
// 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]);
|
||||
},
|
||||
select(event) {
|
||||
event.target.setSelectionRange(0, event.target.value.length);
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -25,7 +25,7 @@ THE SOFTWARE.
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div @copied="copied">
|
||||
<pre><code class="language-bash">{{ cmd }}</code></pre>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -42,5 +42,10 @@ THE SOFTWARE.
|
|||
console.info(`Highlighting ${this.$props.cmd}...`);
|
||||
Prism.highlightAllUnder(this.$el);
|
||||
},
|
||||
methods: {
|
||||
copied(event) {
|
||||
this.$emit('copied', event.detail.text);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -25,7 +25,7 @@ THE SOFTWARE.
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div :class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`">
|
||||
<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>
|
||||
|
@ -46,5 +46,10 @@ THE SOFTWARE.
|
|||
console.info(`Highlighting ${this.$props.name}...`);
|
||||
Prism.highlightAllUnder(this.$el);
|
||||
},
|
||||
methods: {
|
||||
copied(event) {
|
||||
this.$emit('copied', event.detail.text);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -25,7 +25,7 @@ THE SOFTWARE.
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div :class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`">
|
||||
<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>
|
||||
|
@ -45,5 +45,10 @@ THE SOFTWARE.
|
|||
console.info(`Highlighting ${this.$props.name}...`);
|
||||
Prism.highlightAllUnder(this.$el);
|
||||
},
|
||||
methods: {
|
||||
copied(event) {
|
||||
this.$emit('copied', event.detail.text);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -25,7 +25,7 @@ THE SOFTWARE.
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div :class="`column ${half ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`">
|
||||
<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>
|
||||
|
@ -46,5 +46,10 @@ THE SOFTWARE.
|
|||
console.info(`Highlighting ${this.$props.name}...`);
|
||||
Prism.highlightAllUnder(this.$el);
|
||||
},
|
||||
methods: {
|
||||
copied(event) {
|
||||
this.$emit('copied', event.detail.text);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -30,7 +30,7 @@ THE SOFTWARE.
|
|||
<div class="tabs">
|
||||
<ul>
|
||||
<li v-for="tab in tabs" :class="tabClass(tab.key)">
|
||||
<a @click="active = tab.key">{{ $t(tab.display) }}</a>
|
||||
<a @click="showTab(tab.key)">{{ $t(tab.display) }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -44,10 +44,10 @@ THE SOFTWARE.
|
|||
></component>
|
||||
|
||||
<div class="navigation-buttons">
|
||||
<a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab">
|
||||
<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="active = nextTab">
|
||||
<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>
|
||||
|
@ -92,6 +92,9 @@ THE SOFTWARE.
|
|||
if (index >= 0) return tabs[index];
|
||||
return false;
|
||||
},
|
||||
domainCount() {
|
||||
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);
|
||||
return `nginxconfig.io-${domains.join(',')}.tar.gz`;
|
||||
|
@ -123,11 +126,27 @@ THE SOFTWARE.
|
|||
return new Tar(data).gz();
|
||||
},
|
||||
downloadTar() {
|
||||
analytics('download_tar', 'Download', this.tarName);
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Downloaded tar file',
|
||||
label: this.tarName,
|
||||
value: this.domainCount,
|
||||
});
|
||||
|
||||
// Do tar generation
|
||||
this.tarContents().download(this.tarName);
|
||||
},
|
||||
copyTar() {
|
||||
analytics('download_base64', 'Download', this.tarName);
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Copied base64 tar',
|
||||
label: this.tarName,
|
||||
value: this.domainCount,
|
||||
});
|
||||
|
||||
// Do tar generation
|
||||
const path = `${this.$props.data.global.nginx.nginxConfigDirectory.computed}/${this.tarName}`;
|
||||
return this.tarContents().base64(path);
|
||||
},
|
||||
|
@ -155,6 +174,39 @@ THE SOFTWARE.
|
|||
resetText();
|
||||
});
|
||||
},
|
||||
showTab(target) {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Tab clicked',
|
||||
label: `${this.$data.active}, ${target}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = target;
|
||||
},
|
||||
showPreviousTab() {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Back clicked',
|
||||
label: `${this.$data.active}, ${this.previousTab}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = this.previousTab;
|
||||
},
|
||||
showNextTab() {
|
||||
// Analytics
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Next clicked',
|
||||
label: `${this.$data.active}, ${this.nextTab}`,
|
||||
});
|
||||
|
||||
// Go!
|
||||
this.$data.active = this.nextTab;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -34,6 +34,7 @@ THE SOFTWARE.
|
|||
</p>
|
||||
<BashPrism :key="sitesAvailable"
|
||||
:cmd="`sed -i -r 's/(listen .*443)/\\1;#/g; s/(ssl_(certificate|certificate_key|trusted_certificate) )/#;#\\1/g' ${sitesAvailable}`"
|
||||
@copied="codeCopiedEvent('Disable ssl directives')"
|
||||
></BashPrism>
|
||||
</li>
|
||||
|
||||
|
@ -42,7 +43,9 @@ THE SOFTWARE.
|
|||
{{ $t('templates.setupSections.certbot.reloadYourNginxServer') }}
|
||||
<br />
|
||||
</p>
|
||||
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"></BashPrism>
|
||||
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"
|
||||
@copied="codeCopiedEvent('Reload nginx')"
|
||||
></BashPrism>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
@ -50,7 +53,10 @@ THE SOFTWARE.
|
|||
{{ $t('templates.setupSections.certbot.obtainSslCertificatesFromLetsEncrypt') }}
|
||||
<br />
|
||||
</p>
|
||||
<BashPrism :key="certbotCmds" :cmd="certbotCmds"></BashPrism>
|
||||
<BashPrism :key="certbotCmds"
|
||||
:cmd="certbotCmds"
|
||||
@copied="codeCopiedEvent('Obtain certificates using certbot')"
|
||||
></BashPrism>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
@ -58,7 +64,10 @@ THE SOFTWARE.
|
|||
{{ $t('templates.setupSections.certbot.uncommentSslDirectivesInConfiguration') }}
|
||||
<br />
|
||||
</p>
|
||||
<BashPrism :key="sitesAvailable" :cmd="`sed -i -r 's/#?;#//g' ${sitesAvailable}`"></BashPrism>
|
||||
<BashPrism :key="sitesAvailable"
|
||||
:cmd="`sed -i -r 's/#?;#//g' ${sitesAvailable}`"
|
||||
@copied="codeCopiedEvent('Enable ssl directives')"
|
||||
></BashPrism>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
@ -66,7 +75,9 @@ THE SOFTWARE.
|
|||
{{ $t('templates.setupSections.certbot.reloadYourNginxServer') }}
|
||||
<br />
|
||||
</p>
|
||||
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"></BashPrism>
|
||||
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"
|
||||
@copied="codeCopiedEvent('Reload nginx (2)')"
|
||||
></BashPrism>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
@ -74,8 +85,12 @@ THE SOFTWARE.
|
|||
{{ $t('templates.setupSections.certbot.configureCertbotToReloadNginxOnCertificateRenewal') }}
|
||||
<br />
|
||||
</p>
|
||||
<BashPrism cmd="echo -e '#!/bin/bash\nnginx -t && systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh"></BashPrism>
|
||||
<BashPrism cmd="sudo chmod a+x /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh"></BashPrism>
|
||||
<BashPrism cmd="echo -e '#!/bin/bash\nnginx -t && systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh"
|
||||
@copied="codeCopiedEvent('Create nginx auto-restart on renewal')"
|
||||
></BashPrism>
|
||||
<BashPrism cmd="sudo chmod a+x /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh"
|
||||
@copied="codeCopiedEvent('Enable execution of auto-restart')"
|
||||
></BashPrism>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
@ -95,6 +110,7 @@ THE SOFTWARE.
|
|||
|
||||
<script>
|
||||
import BashPrism from '../prism/bash';
|
||||
import analytics from '../../util/analytics';
|
||||
|
||||
export default {
|
||||
name: 'SetupCertbot',
|
||||
|
@ -144,5 +160,14 @@ THE SOFTWARE.
|
|||
)).join('\n');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
codeCopiedEvent(step) {
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Code snippet copied',
|
||||
label: `certbot: ${step}`,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -52,6 +52,7 @@ THE SOFTWARE.
|
|||
<br />
|
||||
<BashPrism :key="$props.data.global.nginx.nginxConfigDirectory.computed"
|
||||
:cmd="`cd ${$props.data.global.nginx.nginxConfigDirectory.computed}`"
|
||||
@copied="codeCopiedEvent('Navigate to nginx config directory')"
|
||||
></BashPrism>
|
||||
</p>
|
||||
</li>
|
||||
|
@ -60,7 +61,9 @@ THE SOFTWARE.
|
|||
<p>
|
||||
<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/"></BashPrism>
|
||||
<BashPrism cmd="tar -czvf nginx_$(date +'%F_%H-%M-%S').tar.gz nginx.conf sites-available/ sites-enabled/ nginxconfig.io/"
|
||||
@copied="codeCopiedEvent('Create nginx config backup tar')"
|
||||
></BashPrism>
|
||||
</p>
|
||||
</li>
|
||||
|
||||
|
@ -68,7 +71,10 @@ THE SOFTWARE.
|
|||
<p>
|
||||
<span v-html="$t('templates.setupSections.download.extractTheNewCompressedConfigurationArchiveUsingTar')"></span>
|
||||
<br />
|
||||
<BashPrism :key="$parent.tarName" :cmd="`tar -xzvf ${$parent.tarName}`"></BashPrism>
|
||||
<BashPrism :key="$parent.tarName"
|
||||
:cmd="`tar -xzvf ${$parent.tarName}`"
|
||||
@copied="codeCopiedEvent('Extract new nginx config tar')"
|
||||
></BashPrism>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
@ -77,6 +83,7 @@ THE SOFTWARE.
|
|||
|
||||
<script>
|
||||
import BashPrism from '../prism/bash';
|
||||
import analytics from '../../util/analytics';
|
||||
|
||||
export default {
|
||||
name: 'SetupDownload',
|
||||
|
@ -91,5 +98,14 @@ THE SOFTWARE.
|
|||
mounted() {
|
||||
this.$parent.setupCopy(this.$refs.copyTar);
|
||||
},
|
||||
methods: {
|
||||
codeCopiedEvent(step) {
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Code snippet copied',
|
||||
label: `download: ${step}`,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -32,13 +32,16 @@ THE SOFTWARE.
|
|||
<p>
|
||||
{{ $t('templates.setupSections.goLive.reloadNginxToLoadInYourNewConfiguration') }}
|
||||
<br />
|
||||
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"></BashPrism>
|
||||
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"
|
||||
@copied="codeCopiedEvent('Reload nginx')"
|
||||
></BashPrism>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BashPrism from '../prism/bash';
|
||||
import analytics from '../../util/analytics';
|
||||
|
||||
export default {
|
||||
name: 'SetupGoLive',
|
||||
|
@ -50,5 +53,14 @@ THE SOFTWARE.
|
|||
props: {
|
||||
data: Object,
|
||||
},
|
||||
methods: {
|
||||
codeCopiedEvent(step) {
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Code snippet copied',
|
||||
label: `goLive: ${step}`,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -33,6 +33,7 @@ THE SOFTWARE.
|
|||
<br />
|
||||
<BashPrism :key="`${$props.data.global.nginx.nginxConfigDirectory.computed}-${diffieHellmanValue}`"
|
||||
:cmd="`openssl dhparam -out ${$props.data.global.nginx.nginxConfigDirectory.computed}/dhparam.pem ${diffieHellmanValue}`"
|
||||
@copied="codeCopiedEvent('Generate diffie-hellman keys')"
|
||||
></BashPrism>
|
||||
</p>
|
||||
</li>
|
||||
|
@ -41,9 +42,13 @@ THE SOFTWARE.
|
|||
<p>
|
||||
<span v-html="$t('templates.setupSections.ssl.createACommonAcmeChallengeDirectoryForLetsEncrypt')"></span>
|
||||
<br />
|
||||
<BashPrism :key="letsEncryptDir" :cmd="`mkdir -p ${letsEncryptDir}`"></BashPrism>
|
||||
<BashPrism :key="letsEncryptDir"
|
||||
:cmd="`mkdir -p ${letsEncryptDir}`"
|
||||
@copied="codeCopiedEvent('Create let\'s encrypt directory')"
|
||||
></BashPrism>
|
||||
<BashPrism :key="`${nginxUser}-${letsEncryptDir}`"
|
||||
:cmd="`chown ${nginxUser} ${letsEncryptDir}`"
|
||||
@copied="codeCopiedEvent('Set let\'s encrypt directory ownership')"
|
||||
></BashPrism>
|
||||
</p>
|
||||
</li>
|
||||
|
@ -65,6 +70,7 @@ THE SOFTWARE.
|
|||
|
||||
<script>
|
||||
import BashPrism from '../prism/bash';
|
||||
import analytics from '../../util/analytics';
|
||||
|
||||
export default {
|
||||
name: 'SetupSSL',
|
||||
|
@ -103,5 +109,14 @@ THE SOFTWARE.
|
|||
return false;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
codeCopiedEvent(step) {
|
||||
analytics({
|
||||
category: 'Setup',
|
||||
action: 'Code snippet copied',
|
||||
label: `ssl: ${step}`,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -24,49 +24,234 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
export default (action, category, label, value, nonInteraction = false) => {
|
||||
export default ({ category, action, label, value, nonInteraction }) => {
|
||||
console.info('Analytics event:', { category, action, label, value, nonInteraction });
|
||||
|
||||
try {
|
||||
const tracker = window.ga.getAll()[0];
|
||||
if (tracker) {
|
||||
tracker.send({
|
||||
hitType: 'event',
|
||||
eventCategory: category,
|
||||
eventAction: action,
|
||||
eventLabel: label,
|
||||
eventValue: value,
|
||||
nonInteraction,
|
||||
});
|
||||
}
|
||||
// Google
|
||||
window.ga('send', 'event', {
|
||||
eventCategory: category,
|
||||
eventAction: action,
|
||||
eventLabel: label,
|
||||
eventValue: value,
|
||||
nonInteraction,
|
||||
});
|
||||
} catch (_) {
|
||||
// If analytics fail, don't block anything else
|
||||
}
|
||||
|
||||
/*try {
|
||||
// gtag.js
|
||||
if (window.gtag) {
|
||||
window.gtag('event', action, {
|
||||
event_category: category,
|
||||
event_label: label,
|
||||
value,
|
||||
});
|
||||
}
|
||||
try {
|
||||
// Segment
|
||||
window.analytics.track(`${category} ${action}`, {
|
||||
label,
|
||||
value,
|
||||
nonInteraction,
|
||||
});
|
||||
} catch (_) {
|
||||
// If analytics fail, don't block anything else
|
||||
}*/
|
||||
|
||||
/*try {
|
||||
// analytics.js
|
||||
if (window.ga) {
|
||||
window.ga('send', {
|
||||
hitType: 'event',
|
||||
eventCategory: category,
|
||||
eventAction: action,
|
||||
eventLabel: label,
|
||||
eventValue: value,
|
||||
nonInteraction,
|
||||
});
|
||||
}
|
||||
} catch (_) {
|
||||
// If analytics fail, don't block anything else
|
||||
}*/
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
All analytics events in app:
|
||||
|
||||
# Initial language set (from browser or query param)
|
||||
|
||||
File: app.vue
|
||||
Category: 'Language'
|
||||
Action: 'Set'
|
||||
Label: language pack name
|
||||
Non-interaction: true
|
||||
|
||||
# User manually changing tool language
|
||||
|
||||
File: app.vue
|
||||
Category: 'Language'
|
||||
Action: 'Set'
|
||||
Label: language pack name
|
||||
Non-interaction: false
|
||||
|
||||
# Initial domains set (from query params)
|
||||
|
||||
File: app.vue
|
||||
Category: 'Site'
|
||||
Action: 'Added'
|
||||
Value: total number of sites active in tool
|
||||
Non-interaction: true
|
||||
|
||||
# User adding a domain
|
||||
|
||||
File: app.vue
|
||||
Category: 'Site'
|
||||
Action: 'Added'
|
||||
Value: total number of sites active in tool
|
||||
Non-interaction: false
|
||||
|
||||
# User removing a domain
|
||||
|
||||
File: app.vue
|
||||
Category: 'Site'
|
||||
Action: 'Removed'
|
||||
Label: domain name being removed
|
||||
Value: total number of sites active in tool after removal
|
||||
|
||||
# Initial split column mode (will always be disabled)
|
||||
|
||||
File: app.vue
|
||||
Category: 'Split column'
|
||||
Action: 'Disabled'
|
||||
Non-interaction: true
|
||||
|
||||
# User changing the column mode
|
||||
|
||||
File: app.vue
|
||||
Category: 'Split column'
|
||||
Action: 'Disabled' / 'Enabled'
|
||||
Non-interaction: false
|
||||
|
||||
# User applying a preset
|
||||
|
||||
File: domain_sections/presets.vue
|
||||
Category: 'Preset'
|
||||
Action: 'Applied'
|
||||
Label: preset internal name
|
||||
|
||||
# User applying a preset with previous customisations
|
||||
|
||||
File: domain_sections/presets.vue
|
||||
Category: 'Preset'
|
||||
Action: 'Overwritten'
|
||||
Label: preset internal name
|
||||
|
||||
# User resetting global settings
|
||||
|
||||
File: global_sections/tools.vue
|
||||
Category: 'Tools'
|
||||
Action: 'Global settings reset'
|
||||
|
||||
# User resetting a domain
|
||||
|
||||
File: global_sections/tools.vue
|
||||
Category: 'Tools'
|
||||
Action: 'Site reset'
|
||||
Label: domain name being reset
|
||||
|
||||
# User removing a domain in the tools tab
|
||||
|
||||
Note: This will also trigger the regular site removal event in app.vue
|
||||
File: global_sections/tools.vue
|
||||
Category: 'Tools'
|
||||
Action: 'Removed site'
|
||||
Label: domain name being removed
|
||||
|
||||
# User resetting all domains
|
||||
|
||||
File: global_sections/tools.vue
|
||||
Category: 'Tools'
|
||||
Action: 'All sites reset'
|
||||
Label: comma-separated list of domain names being reset
|
||||
Value: total number of domains being reset
|
||||
|
||||
# User removing all domains
|
||||
|
||||
Note: This will also trigger the regular site removal event in app.vue for each domain removed
|
||||
File: global_sections/tools.vue
|
||||
Category: 'Tools'
|
||||
Action: 'All sites removed'
|
||||
Label: comma-separated list of domain names being removed
|
||||
Value: total number of domains being removed
|
||||
|
||||
# User clicking a tab in global settings
|
||||
|
||||
File: global.vue
|
||||
Category: 'Global'
|
||||
Action: 'Tab clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking back in global settings
|
||||
|
||||
File: global.vue
|
||||
Category: 'Global'
|
||||
Action: 'Back clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking next in global settings
|
||||
|
||||
File: global.vue
|
||||
Category: 'Global'
|
||||
Action: 'Next clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking a tab in domain settings
|
||||
|
||||
File: domain.vue
|
||||
Category: 'Site'
|
||||
Action: 'Tab clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking back in domain settings
|
||||
|
||||
File: domain.vue
|
||||
Category: 'Site'
|
||||
Action: 'Back clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking next in domain settings
|
||||
|
||||
File: domain.vue
|
||||
Category: 'Site'
|
||||
Action: 'Next clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking a tab in setup
|
||||
|
||||
File: setup.vue
|
||||
Category: 'Setup'
|
||||
Action: 'Tab clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking back in setup
|
||||
|
||||
File: setup.vue
|
||||
Category: 'Setup'
|
||||
Action: 'Back clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User clicking next in setup
|
||||
|
||||
File: setup.vue
|
||||
Category: 'Setup'
|
||||
Action: 'Next clicked'
|
||||
Label: from tab, to tab
|
||||
|
||||
# User downloading the config
|
||||
|
||||
File: setup.vue
|
||||
Category: 'Setup'
|
||||
Action: 'Downloaded tar file'
|
||||
Label: name of the tar file (incl. domain names)
|
||||
Value: total number of active domains
|
||||
|
||||
# User copying the base64 config
|
||||
|
||||
File: setup.vue
|
||||
Category: 'Setup'
|
||||
Action: 'Copied base64 tar'
|
||||
Label: name of the tar file (incl. domain names)
|
||||
Value: total number of active domains
|
||||
|
||||
# User copying a code snippet in setup
|
||||
|
||||
File: setup.vue
|
||||
Category: 'Setup'
|
||||
Action: 'Code snippet copied'
|
||||
Label: tab name: a summary of the code snippet
|
||||
|
||||
# User copying a config file
|
||||
|
||||
File: app.vue
|
||||
Category: 'Config files'
|
||||
Action: 'Code snippet copied'
|
||||
Label: name of file without nginx directory
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2020 DigitalOcean
|
||||
Copyright 2021 DigitalOcean
|
||||
|
||||
This code is licensed under the MIT License.
|
||||
You may obtain a copy of the License at
|
||||
|
@ -24,10 +24,57 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import 'prismjs';
|
||||
import Clipboard from 'clipboard';
|
||||
import Prism from 'prismjs';
|
||||
import 'prismjs/components/prism-nginx';
|
||||
import 'prismjs/components/prism-bash';
|
||||
import 'prismjs/plugins/keep-markup/prism-keep-markup';
|
||||
import 'prismjs/plugins/toolbar/prism-toolbar';
|
||||
import 'prismjs/plugins/toolbar/prism-toolbar.css';
|
||||
import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard';
|
||||
|
||||
// Custom copy to clipboard (based on the Prism one)
|
||||
const copyToClipboard = () => {
|
||||
if (!Prism.plugins.toolbar) {
|
||||
console.warn('Copy to Clipboard loaded before Toolbar.');
|
||||
return;
|
||||
}
|
||||
|
||||
Prism.plugins.toolbar.registerButton('copy-to-clipboard', env => {
|
||||
const linkCopy = document.createElement('button');
|
||||
linkCopy.textContent = 'Copy';
|
||||
|
||||
const element = env.element;
|
||||
const clip = new Clipboard(linkCopy, {
|
||||
'text': () => element.textContent,
|
||||
});
|
||||
|
||||
const resetText = () => {
|
||||
setTimeout(() => {
|
||||
linkCopy.textContent = 'Copy';
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
const emitEvent = () => {
|
||||
linkCopy.dispatchEvent(new CustomEvent('copied', {
|
||||
bubbles: true,
|
||||
detail: { text: element.textContent },
|
||||
}));
|
||||
};
|
||||
|
||||
clip.on('success', () => {
|
||||
linkCopy.textContent = 'Copied!';
|
||||
emitEvent();
|
||||
resetText();
|
||||
});
|
||||
|
||||
clip.on('error', () => {
|
||||
const isMac = navigator.platform.includes('Mac');
|
||||
linkCopy.textContent = `Press ${isMac ? 'Cmd' : 'Ctrl'}+C to copy`;
|
||||
resetText();
|
||||
});
|
||||
|
||||
return linkCopy;
|
||||
});
|
||||
};
|
||||
|
||||
copyToClipboard();
|
||||
|
|
Loading…
Reference in New Issue