Adding Custom domains (#247)
* WIP * wip * Finished doing most of the work
This commit is contained in:
@@ -4,11 +4,13 @@
|
||||
<div class="flex bg-gray-50">
|
||||
<div class="w-full md:w-4/5 lg:w-3/5 md:mx-auto md:max-w-4xl px-4">
|
||||
<div class="pt-4 pb-0">
|
||||
<a href="#" @click.prevent="goBack" class="flex text-blue mb-2 font-semibold text-sm">
|
||||
<a href="#" class="flex text-blue mb-2 font-semibold text-sm" @click.prevent="goBack">
|
||||
<svg class="w-3 h-3 text-blue mt-1 mr-1" viewBox="0 0 6 10" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M5 9L1 5L5 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
Go back
|
||||
</a>
|
||||
@@ -20,24 +22,30 @@
|
||||
<div class="flex">
|
||||
<extra-menu :form="form" />
|
||||
|
||||
<v-button target="_blank" :to="{name:'forms.show_public', params: {slug: form.slug}}"
|
||||
color="white" class="mr-2 text-blue-600 hidden sm:block"
|
||||
v-track.view_form_click="{form_id:form.id, form_slug:form.slug}">
|
||||
<v-button v-track.view_form_click="{form_id:form.id, form_slug:form.slug}" target="_blank"
|
||||
:href="form.share_url" color="white"
|
||||
class="mr-2 text-blue-600 hidden sm:block"
|
||||
>
|
||||
<svg class="w-6 h-6 inline -mt-1" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M1 12C1 12 5 4 12 4C19 4 23 12 23 12C23 12 19 20 12 20C5 20 1 12 1 12Z"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</v-button>
|
||||
<v-button class="text-white" @click="openEdit">
|
||||
<svg class="inline mr-1 -mt-1" width="18" height="17" viewBox="0 0 18 17" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.99998 15.6662H16.5M1.5 15.6662H2.89545C3.3031 15.6662 3.50693 15.6662 3.69874 15.6202C3.8688 15.5793 4.03138 15.512 4.1805 15.4206C4.34869 15.3175 4.49282 15.1734 4.78107 14.8852L15.25 4.4162C15.9404 3.72585 15.9404 2.60656 15.25 1.9162C14.5597 1.22585 13.4404 1.22585 12.75 1.9162L2.28105 12.3852C1.9928 12.6734 1.84867 12.8175 1.7456 12.9857C1.65422 13.1348 1.58688 13.2974 1.54605 13.4675C1.5 13.6593 1.5 13.8631 1.5 14.2708V15.6662Z"
|
||||
stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
Edit form
|
||||
</v-button>
|
||||
@@ -52,16 +60,18 @@
|
||||
<span>- Edited {{ form.last_edited_human }}</span>
|
||||
</p>
|
||||
<div v-if="['draft','closed'].includes(form.visibility) || (form.tags && form.tags.length > 0)" class="mt-2 flex items-center flex-wrap gap-3">
|
||||
<span v-if="form.visibility=='draft'"
|
||||
class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-1 text-xs font-medium text-yellow-600 ring-1 ring-inset ring-gray-500/10 dark:text-white dark:bg-gray-700">
|
||||
<span v-if="form.visibility=='draft'"
|
||||
class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-1 text-xs font-medium text-yellow-600 ring-1 ring-inset ring-gray-500/10 dark:text-white dark:bg-gray-700"
|
||||
>
|
||||
Draft - not publicly accessible
|
||||
</span>
|
||||
<span v-else-if="form.visibility=='closed'"
|
||||
class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-1 text-xs font-medium text-yellow-600 ring-1 ring-inset ring-gray-500/10 dark:text-white dark:bg-gray-700">
|
||||
<span v-else-if="form.visibility=='closed'"
|
||||
class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-1 text-xs font-medium text-yellow-600 ring-1 ring-inset ring-gray-500/10 dark:text-white dark:bg-gray-700"
|
||||
>
|
||||
Closed - won't accept new submissions
|
||||
</span>
|
||||
<span v-for="(tag,i) in form.tags" :key="tag"
|
||||
class="inline-flex items-center rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 dark:text-white dark:bg-gray-700"
|
||||
class="inline-flex items-center rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 dark:text-white dark:bg-gray-700"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
@@ -69,14 +79,14 @@
|
||||
|
||||
<p v-if="form.closes_at" class="text-yellow-500">
|
||||
<span v-if="form.is_closed"> This form stopped accepting submissions on the {{
|
||||
displayClosesDate
|
||||
}} </span>
|
||||
displayClosesDate
|
||||
}} </span>
|
||||
<span v-else> This form will stop accepting submissions on the {{ displayClosesDate }} </span>
|
||||
</p>
|
||||
<p v-if="form.max_submissions_count > 0" class="text-yellow-500">
|
||||
<span v-if="form.max_number_of_submissions_reached"> The form is now closed because it reached its limit of {{
|
||||
form.max_submissions_count
|
||||
}} submissions. </span>
|
||||
form.max_submissions_count
|
||||
}} submissions. </span>
|
||||
<span v-else> This form will stop accepting submissions after {{ form.max_submissions_count }} submissions. </span>
|
||||
</p>
|
||||
|
||||
@@ -84,15 +94,16 @@
|
||||
|
||||
<div class="border-b border-gray-200 dark:border-gray-700">
|
||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center">
|
||||
<li class="mr-6" v-for="(tab, i) in tabsList" :key="i+1">
|
||||
<li v-for="(tab, i) in tabsList" :key="i+1" class="mr-6">
|
||||
<router-link :to="{ name: tab.route }"
|
||||
class="hover:no-underline inline-block py-4 rounded-t-lg border-b-2 text-gray-500 hover:text-gray-600"
|
||||
active-class="text-blue-600 hover:text-blue-900 dark:text-blue-500 dark:hover:text-blue-500 border-blue-600 dark:border-blue-500"
|
||||
>{{tab.name}}</router-link>
|
||||
class="hover:no-underline inline-block py-4 rounded-t-lg border-b-2 text-gray-500 hover:text-gray-600"
|
||||
active-class="text-blue-600 hover:text-blue-900 dark:text-blue-500 dark:hover:text-blue-500 border-blue-600 dark:border-blue-500"
|
||||
>
|
||||
{{ tab.name }}
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,7 +118,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div v-else-if="loading" class="text-center w-full p-5">
|
||||
<loader class="h-6 w-6 mx-auto"/>
|
||||
<loader class="h-6 w-6 mx-auto" />
|
||||
</div>
|
||||
<div v-else class="text-center w-full p-5">
|
||||
Form not found.
|
||||
@@ -119,9 +130,9 @@
|
||||
import axios from 'axios'
|
||||
import store from '~/store'
|
||||
import Form from 'vform'
|
||||
import {mapGetters, mapState} from 'vuex'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import ProTag from '../../../components/common/ProTag.vue'
|
||||
import VButton from "../../../components/common/Button.vue";
|
||||
import VButton from '../../../components/common/Button.vue'
|
||||
import ExtraMenu from '../../../components/pages/forms/show/ExtraMenu.vue'
|
||||
import SeoMeta from '../../../mixins/seo-meta.js'
|
||||
import FormCleanings from '../../../components/pages/forms/show/FormCleanings.vue'
|
||||
@@ -143,18 +154,18 @@ export default {
|
||||
},
|
||||
mixins: [SeoMeta],
|
||||
|
||||
beforeRouteEnter(to, from, next) {
|
||||
beforeRouteEnter (to, from, next) {
|
||||
loadForms()
|
||||
next()
|
||||
},
|
||||
|
||||
beforeRouteLeave(to, from, next) {
|
||||
beforeRouteLeave (to, from, next) {
|
||||
this.workingForm = null
|
||||
next()
|
||||
},
|
||||
middleware: 'auth',
|
||||
|
||||
data() {
|
||||
data () {
|
||||
return {
|
||||
metaTitle: 'Home',
|
||||
tabsList: [
|
||||
@@ -183,59 +194,59 @@ export default {
|
||||
workspacesLoading: state => state['open/workspaces'].loading
|
||||
}),
|
||||
workingForm: {
|
||||
get() {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
},
|
||||
set(value) {
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
}
|
||||
},
|
||||
workspace() {
|
||||
workspace () {
|
||||
if (!this.form) return null
|
||||
return this.$store.getters['open/workspaces/getById'](this.form.workspace_id)
|
||||
},
|
||||
form() {
|
||||
form () {
|
||||
return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
|
||||
},
|
||||
formEndpoint: () => '/api/open/forms/{id}',
|
||||
loading() {
|
||||
loading () {
|
||||
return this.formsLoading || this.workspacesLoading
|
||||
},
|
||||
displayClosesDate() {
|
||||
displayClosesDate () {
|
||||
if (this.form.closes_at) {
|
||||
let dateObj = new Date(this.form.closes_at)
|
||||
return dateObj.getFullYear() + "-" +
|
||||
String(dateObj.getMonth() + 1).padStart(2, '0') + "-" +
|
||||
String(dateObj.getDate()).padStart(2, '0') + " " +
|
||||
String(dateObj.getHours()).padStart(2, '0') + ":" +
|
||||
const dateObj = new Date(this.form.closes_at)
|
||||
return dateObj.getFullYear() + '-' +
|
||||
String(dateObj.getMonth() + 1).padStart(2, '0') + '-' +
|
||||
String(dateObj.getDate()).padStart(2, '0') + ' ' +
|
||||
String(dateObj.getHours()).padStart(2, '0') + ':' +
|
||||
String(dateObj.getMinutes()).padStart(2, '0')
|
||||
}
|
||||
return "";
|
||||
return ''
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
form() {
|
||||
form () {
|
||||
this.workingForm = new Form(this.form)
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
mounted () {
|
||||
if (this.form) {
|
||||
this.workingForm = new Form(this.form)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
openCrisp() {
|
||||
openCrisp () {
|
||||
window.$crisp.push(['do', 'chat:show'])
|
||||
window.$crisp.push(['do', 'chat:open'])
|
||||
},
|
||||
goBack() {
|
||||
this.$router.push({name: 'home'})
|
||||
goBack () {
|
||||
this.$router.push({ name: 'home' })
|
||||
},
|
||||
openEdit() {
|
||||
this.$router.push({name: 'forms.edit', params: {slug: this.form.slug}})
|
||||
openEdit () {
|
||||
this.$router.push({ name: 'forms.edit', params: { slug: this.form.slug } })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,92 @@
|
||||
<template>
|
||||
<div>
|
||||
<h3 class="font-semibold text-2xl text-gray-900">Workspace settings</h3>
|
||||
<small class="text-gray-600">Manage your workspaces.</small>
|
||||
|
||||
<div v-if="loading" class="w-full text-blue-500 text-center">
|
||||
<loader class="h-10 w-10 p-5"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-for="workspace in workspaces" :key="workspace.id"
|
||||
class="mt-4 p-4 flex group bg-white hover:bg-gray-50 dark:bg-notion-dark items-center"
|
||||
>
|
||||
<div class="flex space-x-4 flex-grow items-center cursor-pointer" role="button" @click.prevent="switchWorkspace(workspace)">
|
||||
<img v-if="isUrl(workspace.icon)" :src="workspace.icon" :alt="workspace.name + ' icon'"
|
||||
class="rounded-full h-12 w-12"
|
||||
>
|
||||
<div v-else class="rounded-2xl bg-gray-100 h-12 w-12 text-2xl pt-2 text-center overflow-hidden"
|
||||
v-text="workspace.icon"
|
||||
/>
|
||||
<div class="space-y-4 py-1">
|
||||
<div class="font-bold truncate">{{workspace.name}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="workspaces.length > 1"
|
||||
class="block md:hidden group-hover:block text-red-500 p-2 rounded hover:bg-red-50" role="button"
|
||||
@click="deleteWorkspace(workspace)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-y-4 flex-wrap-reverse">
|
||||
<div class="flex-grow">
|
||||
<h3 class="font-semibold text-2xl text-gray-900">
|
||||
Workspace settings
|
||||
</h3>
|
||||
<small class="text-gray-600">Manage your workspaces.</small>
|
||||
</div>
|
||||
<v-button :loading="loading" class="mt-4" @click="workspaceModal=true">
|
||||
<svg class="inline text-white mr-1 h-4 w-4" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.99996 1.16699V12.8337M1.16663 7.00033H12.8333" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<v-button color="outline-blue" :loading="loading" @click="workspaceModal=true">
|
||||
<svg class="inline -mt-1 mr-1 h-4 w-4" viewBox="0 0 14 14" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M6.99996 1.16699V12.8337M1.16663 7.00033H12.8333" stroke="currentColor" stroke-width="1.67"
|
||||
stroke-linecap="round" stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
Create new workspace
|
||||
</v-button>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="w-full text-blue-500 text-center">
|
||||
<loader class="h-10 w-10 p-5" />
|
||||
</div>
|
||||
<div v-else-if="workspace">
|
||||
<div class="mt-4 flex group bg-white items-center">
|
||||
<div class="flex space-x-4 flex-grow items-center">
|
||||
<img v-if="isUrl(workspace.icon)" :src="workspace.icon" :alt="workspace.name + ' icon'"
|
||||
class="rounded-full h-12 w-12"
|
||||
>
|
||||
<div v-else class="rounded-2xl bg-gray-100 h-12 w-12 text-2xl pt-2 text-center overflow-hidden"
|
||||
v-text="workspace.icon"
|
||||
/>
|
||||
<div class="space-y-4 py-1">
|
||||
<div class="font-bold truncate">
|
||||
{{ workspace.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="customDomainsEnabled">
|
||||
<text-area-input v-model="customDomains" name="custom_domain" class="mt-4" :required="false"
|
||||
:disabled="!workspace.is_pro"
|
||||
label="Workspace Custom Domains" wrapper-class="" placeholder="yourdomain.com - 1 per line"
|
||||
/>
|
||||
<p class="text-gray-500 text-sm">
|
||||
Read our <a href="#"
|
||||
@click.prevent="$crisp.push(['do', 'helpdesk:article:open', ['en', 'how-to-use-my-own-domain-9m77g7']])"
|
||||
>custom
|
||||
domain instructions</a> to learn how to use your own domain.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<div class="flex flex-wrap justify-between gap-2 mt-4">
|
||||
<v-button v-if="customDomainsEnabled" class="w-full sm:w-auto" :loading="customDomainsLoading" @click="saveChanges">
|
||||
<svg class="w-4 h-4 text-white inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17 21V13H7V21M7 3V8H15M19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V5C3 4.46957 3.21071 3.96086 3.58579 3.58579C3.96086 3.21071 4.46957 3 5 3H16L21 8V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21Z"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
Save Domains
|
||||
</v-button>
|
||||
<v-button v-if="workspaces.length > 1" color="white" class="group w-full sm:w-auto" :loading="loading"
|
||||
@click="deleteWorkspace(workspace)"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 -mt-1 inline group-hover:text-red-700" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
Remove workspace
|
||||
</v-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Workspace modal -->
|
||||
<modal :show="workspaceModal" @close="workspaceModal=false" max-width="lg">
|
||||
<modal :show="workspaceModal" max-width="lg" @close="workspaceModal=false">
|
||||
<template #icon>
|
||||
<svg class="w-8 h-8" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M12 8V16M8 12H16M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
<template #title>
|
||||
@@ -62,25 +104,28 @@
|
||||
</div>
|
||||
|
||||
<div class="w-full mt-6">
|
||||
<v-button :loading="form.busy" class="w-full my-3">Save</v-button>
|
||||
<v-button :loading="form.busy" class="w-full my-3">
|
||||
Save
|
||||
</v-button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Form from 'vform'
|
||||
import {mapActions, mapState} from 'vuex'
|
||||
import { mapActions, mapState } from 'vuex'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import TextAreaInput from '../../components/forms/TextAreaInput.vue'
|
||||
import axios from 'axios'
|
||||
import * as domain from 'domain'
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
scrollToTop: false,
|
||||
components: { TextAreaInput },
|
||||
mixins: [SeoMeta],
|
||||
scrollToTop: false,
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Workspaces',
|
||||
@@ -88,37 +133,65 @@ export default {
|
||||
name: '',
|
||||
emoji: ''
|
||||
}),
|
||||
workspaceModal: false
|
||||
workspaceModal: false,
|
||||
customDomains: '',
|
||||
customDomainsLoading: false
|
||||
}),
|
||||
|
||||
mounted() {
|
||||
mounted () {
|
||||
this.loadWorkspaces()
|
||||
this.initCustomDomains()
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
workspaces: state => state['open/workspaces'].content,
|
||||
loading: state => state['open/workspaces'].loading
|
||||
})
|
||||
}),
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
},
|
||||
customDomainsEnabled () {
|
||||
return window.config.custom_domains_enabled
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions({
|
||||
loadWorkspaces: 'open/workspaces/loadIfEmpty'
|
||||
}),
|
||||
switchWorkspace(workspace) {
|
||||
this.$store.commit('open/workspaces/setCurrentId', workspace.id)
|
||||
this.$router.push({name: 'home'})
|
||||
this.$store.dispatch('open/forms/load', workspace.id)
|
||||
saveChanges () {
|
||||
if (this.customDomainsLoading) return
|
||||
this.customDomainsLoading = true
|
||||
// Update the workspace custom domain
|
||||
axios.put('/api/open/workspaces/' + this.workspace.id + '/custom-domains', {
|
||||
custom_domains: this.customDomains.split('\n')
|
||||
.map(domain => domain.trim())
|
||||
.filter(domain => domain && domain.length > 0)
|
||||
}).then(() => {
|
||||
this.alertSuccess('Custom domains saved.')
|
||||
}).catch((error) => {
|
||||
this.alertError('Failed to update custom domains: ' + error.response.data.message)
|
||||
}).finally(() => {
|
||||
this.customDomainsLoading = false
|
||||
})
|
||||
},
|
||||
deleteWorkspace(workspace) {
|
||||
initCustomDomains () {
|
||||
if (!this.workspace) return
|
||||
this.customDomains = this.workspace.custom_domains.join('\n')
|
||||
},
|
||||
deleteWorkspace (workspace) {
|
||||
if (this.workspaces.length <= 1) {
|
||||
this.alertError('You cannot delete your only workspace.')
|
||||
return
|
||||
}
|
||||
this.alertConfirm('Do you really want to delete this workspace? All forms created in this workspace will be removed.', () => {
|
||||
this.$store.dispatch('open/workspaces/delete', workspace.id).then(() => {
|
||||
this.alertSuccess('Workspace successfully removed.')
|
||||
})
|
||||
})
|
||||
},
|
||||
isUrl(str) {
|
||||
isUrl (str) {
|
||||
const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
||||
@@ -127,11 +200,17 @@ export default {
|
||||
'(\\#[-a-z\\d_]*)?$', 'i') // fragment locator
|
||||
return !!pattern.test(str)
|
||||
},
|
||||
async createWorkspace() {
|
||||
const {data} = await this.form.post('/api/open/workspaces/create')
|
||||
async createWorkspace () {
|
||||
const { data } = await this.form.post('/api/open/workspaces/create')
|
||||
this.$store.dispatch('open/workspaces/load')
|
||||
this.workspaceModal = false
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
workspace () {
|
||||
this.initCustomDomains()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user