mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-10 23:50:12 +00:00
Merge branch 'feat/delete_confirmation' into 'develop'
Resolve "Add confirmation when the user wants to delete a table, database or group" Closes #167 See merge request bramw/baserow!108
This commit is contained in:
commit
731d6022b9
19 changed files with 579 additions and 65 deletions
changelog.md
web-frontend/modules
|
@ -7,7 +7,9 @@
|
|||
* Added Ubuntu installation guide documentation.
|
||||
* Added Email field.
|
||||
* Added importer abstraction including a CSV and tabular paste importer.
|
||||
* Added ability to navigate dropdown menus with arrow keys
|
||||
* Added ability to navigate dropdown menus with arrow keys.
|
||||
* Added confirmation modals when the user wants to delete a group, application, table,
|
||||
view or field.
|
||||
* Fixed bug in the web-frontend URL validation where a '*' was invalidates.
|
||||
|
||||
## Released (2020-10-06)
|
||||
|
|
|
@ -50,6 +50,28 @@ export class ApplicationType extends Registerable {
|
|||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return an array where the first element is the describing name of the
|
||||
* dependents in singular and the second element in plural. Can be null if there
|
||||
* aren't any dependants.
|
||||
*
|
||||
* Example: ['table', 'tables']
|
||||
* Result in singular: There is 1 table
|
||||
* Result in plural: There are 2 tables
|
||||
*/
|
||||
getDependentsName() {
|
||||
return [null, null]
|
||||
}
|
||||
|
||||
/**
|
||||
* When deleting or listing an application we might want to give a quick overview
|
||||
* which children / dependents there are. This method should return a list
|
||||
* containing an object with an id, iconClass and name.
|
||||
*/
|
||||
getDependents() {
|
||||
return []
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.type = this.getType()
|
||||
|
|
|
@ -15,6 +15,11 @@ a {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
|
|
|
@ -40,3 +40,4 @@
|
|||
@import 'grid';
|
||||
@import 'table_preview';
|
||||
@import 'file_upload';
|
||||
@import 'delete_section';
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
.delete-section {
|
||||
position: relative;
|
||||
border: solid 1px $color-neutral-200;
|
||||
border-radius: 3px;
|
||||
padding: 31px 16px 16px 16px;
|
||||
}
|
||||
|
||||
.delete-section__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid $color-error-300;
|
||||
border-radius: 3px;
|
||||
background-color: $color-error-100;
|
||||
color: $color-error-900;
|
||||
line-height: 28px;
|
||||
padding: 0 10px;
|
||||
|
||||
@include absolute(-14px, auto, auto, 12px);
|
||||
}
|
||||
|
||||
.delete-section__label-icon {
|
||||
background-color: $white;
|
||||
border: solid 2px $color-error-400;
|
||||
color: $color-error-900;
|
||||
border-radius: 100%;
|
||||
text-align: center;
|
||||
margin-right: 8px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
line-height: 14px;
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
.delete-section__list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
line-height: 18px;
|
||||
font-size: 14px;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 12px;
|
||||
color: $color-neutral-500;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-section__list-icon {
|
||||
@extend .fa-fw;
|
||||
|
||||
position: relative;
|
||||
top: -1px;
|
||||
color: $color-neutral-300;
|
||||
font-size: 10px;
|
||||
margin-right: 8px;
|
||||
}
|
|
@ -29,6 +29,7 @@
|
|||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<DeleteGroupModal ref="deleteGroupModal" :group="group" />
|
||||
</Context>
|
||||
</h2>
|
||||
<ul class="dashboard__group-items">
|
||||
|
@ -79,10 +80,14 @@
|
|||
import { mapGetters } from 'vuex'
|
||||
|
||||
import CreateApplicationContext from '@baserow/modules/core/components/application/CreateApplicationContext'
|
||||
import DeleteGroupModal from '@baserow/modules/core/components/group/DeleteGroupModal'
|
||||
import editGroup from '@baserow/modules/core/mixins/editGroup'
|
||||
|
||||
export default {
|
||||
components: { CreateApplicationContext },
|
||||
components: {
|
||||
CreateApplicationContext,
|
||||
DeleteGroupModal,
|
||||
},
|
||||
mixins: [editGroup],
|
||||
props: {
|
||||
group: {
|
||||
|
|
106
web-frontend/modules/core/components/group/DeleteGroupModal.vue
Normal file
106
web-frontend/modules/core/components/group/DeleteGroupModal.vue
Normal file
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<Modal>
|
||||
<h2 class="box__title">Delete {{ group.name }}</h2>
|
||||
<Error :error="error"></Error>
|
||||
<div>
|
||||
<p>
|
||||
Are you sure you want to delete the group
|
||||
<strong>{{ group.name }}</strong
|
||||
>?
|
||||
<span v-if="applications.length > 0">
|
||||
The following
|
||||
<template v-if="applications.length == 1"
|
||||
>application including its data is</template
|
||||
>
|
||||
<template v-else>applications including their data are</template>
|
||||
going to be permanently deleted:</span
|
||||
>
|
||||
</p>
|
||||
<div class="delete-section" v-if="applications.length > 0">
|
||||
<div class="delete-section__label">
|
||||
<div class="delete-section__label-icon">
|
||||
<i class="fas fa-exclamation"></i>
|
||||
</div>
|
||||
Will also be permanently deleted
|
||||
</div>
|
||||
<ul class="delete-section__list">
|
||||
<li v-for="application in applications" :key="application.id">
|
||||
<i
|
||||
class="delete-section__list-icon fas fa-database"
|
||||
:class="'fa-' + application._.type.iconClass"
|
||||
></i>
|
||||
{{ application.name }}
|
||||
<small>{{ getApplicationDependentsText(application) }}</small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="align-right">
|
||||
<button
|
||||
class="button button--large button--error"
|
||||
:class="{ 'button--loading': loading }"
|
||||
:disabled="loading"
|
||||
@click="deleteGroup()"
|
||||
>
|
||||
Delete group
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import modal from '@baserow/modules/core/mixins/modal'
|
||||
import error from '@baserow/modules/core/mixins/error'
|
||||
|
||||
export default {
|
||||
name: 'DeleteGroupModal',
|
||||
mixins: [modal, error],
|
||||
props: {
|
||||
group: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
getAllOfGroup: 'application/getAllOfGroup',
|
||||
}),
|
||||
applications() {
|
||||
return this.getAllOfGroup(this.group)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async deleteGroup() {
|
||||
this.hideError()
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('group/delete', this.group)
|
||||
this.hide()
|
||||
} catch (error) {
|
||||
this.handleError(error, 'application')
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
},
|
||||
getApplicationDependentsText(application) {
|
||||
const dependents = this.$registry
|
||||
.get('application', application.type)
|
||||
.getDependents(application)
|
||||
const names = this.$registry
|
||||
.get('application', application.type)
|
||||
.getDependentsName(application)
|
||||
const name = dependents.length === 1 ? names[0] : names[1]
|
||||
return `including ${dependents.length} ${name}`
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -35,15 +35,18 @@
|
|||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<DeleteGroupModal ref="deleteGroupModal" :group="group" />
|
||||
</Context>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DeleteGroupModal from '@baserow/modules/core/components/group/DeleteGroupModal'
|
||||
import editGroup from '@baserow/modules/core/mixins/editGroup'
|
||||
|
||||
export default {
|
||||
name: 'GroupsContextItem',
|
||||
components: { DeleteGroupModal },
|
||||
mixins: [editGroup],
|
||||
props: {
|
||||
group: {
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<Modal>
|
||||
<h2 class="box__title">Delete {{ application.name }}</h2>
|
||||
<Error :error="error"></Error>
|
||||
<div>
|
||||
<p>
|
||||
Are you sure you want to delete the
|
||||
{{ application._.type.name | lowercase }}
|
||||
<strong>{{ application.name }}</strong
|
||||
>?
|
||||
<span v-if="dependents.length > 0"
|
||||
>The following {{ dependentsName }}
|
||||
<template v-if="dependents.length === 1">is</template>
|
||||
<template v-else>are</template>
|
||||
also going to be permanently deleted:</span
|
||||
>
|
||||
</p>
|
||||
<div v-if="dependents.length > 0" class="delete-section">
|
||||
<div class="delete-section__label">
|
||||
<div class="delete-section__label-icon">
|
||||
<i class="fas fa-exclamation"></i>
|
||||
</div>
|
||||
Will also be permanently deleted
|
||||
</div>
|
||||
<ul class="delete-section__list">
|
||||
<li v-for="dependent in dependents" :key="dependent.id">
|
||||
<i
|
||||
class="delete-section__list-icon fas fa-database"
|
||||
:class="'fa-' + dependent.iconClass"
|
||||
></i>
|
||||
{{ dependent.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="align-right">
|
||||
<button
|
||||
class="button button--large button--error"
|
||||
:class="{ 'button--loading': loading }"
|
||||
:disabled="loading"
|
||||
@click="deleteApplication()"
|
||||
>
|
||||
Delete {{ application._.type.name | lowercase }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modal from '@baserow/modules/core/mixins/modal'
|
||||
import error from '@baserow/modules/core/mixins/error'
|
||||
|
||||
export default {
|
||||
name: 'DeleteApplicationModal',
|
||||
mixins: [modal, error],
|
||||
props: {
|
||||
application: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dependentsName() {
|
||||
const names = this.$registry
|
||||
.get('application', this.application.type)
|
||||
.getDependentsName(this.application)
|
||||
return this.dependents.length === 1 ? names[0] : names[1]
|
||||
},
|
||||
dependents() {
|
||||
return this.$registry
|
||||
.get('application', this.application.type)
|
||||
.getDependents(this.application)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async deleteApplication() {
|
||||
this.hideError()
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('application/delete', this.application)
|
||||
this.hide()
|
||||
} catch (error) {
|
||||
this.handleError(error, 'application')
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -35,12 +35,16 @@
|
|||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @click="deleteApplication(application)">
|
||||
<a @click="deleteApplication()">
|
||||
<i class="context__menu-icon fas fa-fw fa-trash"></i>
|
||||
Delete {{ application._.type.name | lowercase }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<DeleteApplicationModal
|
||||
ref="deleteApplicationModal"
|
||||
:application="application"
|
||||
/>
|
||||
</Context>
|
||||
</div>
|
||||
<template
|
||||
|
@ -58,9 +62,11 @@
|
|||
|
||||
<script>
|
||||
import { notifyIf } from '@baserow/modules/core/utils/error'
|
||||
import DeleteApplicationModal from './DeleteApplicationModal'
|
||||
|
||||
export default {
|
||||
name: 'SidebarApplication',
|
||||
components: { DeleteApplicationModal },
|
||||
props: {
|
||||
application: {
|
||||
type: Object,
|
||||
|
@ -126,17 +132,9 @@ export default {
|
|||
}
|
||||
)
|
||||
},
|
||||
async deleteApplication(application) {
|
||||
deleteApplication() {
|
||||
this.$refs.context.hide()
|
||||
this.setLoading(application, true)
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('application/delete', application)
|
||||
} catch (error) {
|
||||
notifyIf(error, 'application')
|
||||
}
|
||||
|
||||
this.setLoading(application, false)
|
||||
this.$refs.deleteApplicationModal.show()
|
||||
},
|
||||
getSelectedApplicationComponent(application) {
|
||||
const type = this.$registry.get('application', application.type)
|
||||
|
|
|
@ -41,17 +41,9 @@ export default {
|
|||
|
||||
this.setLoading(group, false)
|
||||
},
|
||||
async deleteGroup(group) {
|
||||
deleteGroup(group) {
|
||||
this.$refs.context.hide()
|
||||
this.setLoading(group, true)
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('group/delete', group)
|
||||
} catch (error) {
|
||||
notifyIf(error, 'group')
|
||||
}
|
||||
|
||||
this.setLoading(group, false)
|
||||
this.$refs.deleteGroupModal.show()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -754,6 +754,26 @@
|
|||
dignissim mauris dictum imperdiet. Mauris ultrices ac eros at
|
||||
fringilla. Praesent ut tincidunt dui.
|
||||
</p>
|
||||
<div class="delete-section">
|
||||
<div class="delete-section__label">
|
||||
<div class="delete-section__label-icon">
|
||||
<i class="fas fa-exclamation"></i>
|
||||
</div>
|
||||
Will also be permanently deleted
|
||||
</div>
|
||||
<ul class="delete-section__list">
|
||||
<li>
|
||||
<i class="delete-section__list-icon fas fa-database"></i>
|
||||
Vehicles
|
||||
<small>including 12 tables</small>
|
||||
</li>
|
||||
<li>
|
||||
<i class="delete-section__list-icon fas fa-database"></i>
|
||||
Webshop
|
||||
<small>including 12 tables</small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__box modal__box--with-sidebar">
|
||||
<a class="modal__close">
|
||||
|
|
|
@ -19,6 +19,20 @@ export class DatabaseApplicationType extends ApplicationType {
|
|||
return Sidebar
|
||||
}
|
||||
|
||||
getDependentsName() {
|
||||
return ['table', 'tables']
|
||||
}
|
||||
|
||||
getDependents(database) {
|
||||
return database.tables.map((table) => {
|
||||
return {
|
||||
id: table.id,
|
||||
iconClass: 'table',
|
||||
name: table.name,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
populate(application) {
|
||||
const values = super.populate(application)
|
||||
values.tables.forEach((object, index, tables) => populateTable(object))
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
<template>
|
||||
<Modal>
|
||||
<h2 class="box__title">Delete {{ field.name }}</h2>
|
||||
<Error :error="error"></Error>
|
||||
<div>
|
||||
<p>
|
||||
Are you sure you want to delete the field
|
||||
<strong>{{ field.name }}</strong
|
||||
>? All the data, filters and sortings related to the field will be
|
||||
permanently deleted.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<div class="align-right">
|
||||
<button
|
||||
class="button button--large button--error"
|
||||
:class="{ 'button--loading': loading }"
|
||||
:disabled="loading"
|
||||
@click="deleteField()"
|
||||
>
|
||||
Delete field
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modal from '@baserow/modules/core/mixins/modal'
|
||||
import error from '@baserow/modules/core/mixins/error'
|
||||
|
||||
export default {
|
||||
name: 'DeleteFieldModal',
|
||||
mixins: [modal, error],
|
||||
props: {
|
||||
field: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async deleteField() {
|
||||
this.hideError()
|
||||
this.loading = true
|
||||
const { field } = this
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('field/deleteCall', field)
|
||||
this.$emit('delete')
|
||||
this.$store.dispatch('field/forceDelete', field)
|
||||
this.hide()
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 404) {
|
||||
this.$emit('delete')
|
||||
this.$store.dispatch('field/forceDelete', field)
|
||||
this.hide()
|
||||
} else {
|
||||
this.handleError(error, 'field')
|
||||
}
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -26,23 +26,32 @@
|
|||
</li>
|
||||
<slot></slot>
|
||||
<li v-if="!field.primary">
|
||||
<a @click="deleteField(field)">
|
||||
<a @click="deleteField()">
|
||||
<i class="context__menu-icon fas fa-fw fa-trash"></i>
|
||||
Delete field
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<DeleteFieldModal
|
||||
v-if="!field.primary"
|
||||
ref="deleteFieldModal"
|
||||
:field="field"
|
||||
@delete="$emit('delete')"
|
||||
/>
|
||||
</Context>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { notifyIf } from '@baserow/modules/core/utils/error'
|
||||
import context from '@baserow/modules/core/mixins/context'
|
||||
import UpdateFieldContext from '@baserow/modules/database/components/field/UpdateFieldContext'
|
||||
import DeleteFieldModal from './DeleteFieldModal'
|
||||
|
||||
export default {
|
||||
name: 'FieldContext',
|
||||
components: { UpdateFieldContext },
|
||||
components: {
|
||||
UpdateFieldContext,
|
||||
DeleteFieldModal,
|
||||
},
|
||||
mixins: [context],
|
||||
props: {
|
||||
table: {
|
||||
|
@ -58,24 +67,9 @@ export default {
|
|||
setLoading(field, value) {
|
||||
this.$store.dispatch('field/setItemLoading', { field, value })
|
||||
},
|
||||
async deleteField(field) {
|
||||
deleteField() {
|
||||
this.$refs.context.hide()
|
||||
this.setLoading(field, true)
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('field/deleteCall', field)
|
||||
this.$emit('delete')
|
||||
this.$store.dispatch('field/forceDelete', field)
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 404) {
|
||||
this.$emit('delete')
|
||||
this.$store.dispatch('field/forceDelete', field)
|
||||
} else {
|
||||
notifyIf(error, 'field')
|
||||
}
|
||||
}
|
||||
|
||||
this.setLoading(field, false)
|
||||
this.$refs.deleteFieldModal.show()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<Modal>
|
||||
<h2 class="box__title">Delete {{ table.name }}</h2>
|
||||
<Error :error="error"></Error>
|
||||
<div>
|
||||
<p>
|
||||
Are you sure you want to delete the table
|
||||
<strong>{{ table.name }}</strong
|
||||
>? All the the related views and data will be permanently deleted.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<div class="align-right">
|
||||
<button
|
||||
class="button button--large button--error"
|
||||
:class="{ 'button--loading': loading }"
|
||||
:disabled="loading"
|
||||
@click="deleteTable()"
|
||||
>
|
||||
Delete table
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modal from '@baserow/modules/core/mixins/modal'
|
||||
import error from '@baserow/modules/core/mixins/error'
|
||||
|
||||
export default {
|
||||
name: 'DeleteTableModal',
|
||||
mixins: [modal, error],
|
||||
props: {
|
||||
database: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
table: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async deleteTable() {
|
||||
this.hideError()
|
||||
this.loading = true
|
||||
const { database, table } = this
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('table/delete', { database, table })
|
||||
this.hide()
|
||||
} catch (error) {
|
||||
this.handleError(error, 'table')
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -24,21 +24,28 @@
|
|||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @click="deleteTable(database, table)">
|
||||
<a @click="deleteTable()">
|
||||
<i class="context__menu-icon fas fa-fw fa-trash"></i>
|
||||
Delete
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<DeleteTableModal
|
||||
ref="deleteTableModal"
|
||||
:database="database"
|
||||
:table="table"
|
||||
/>
|
||||
</Context>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { notifyIf } from '@baserow/modules/core/utils/error'
|
||||
import DeleteTableModal from './DeleteTableModal'
|
||||
|
||||
export default {
|
||||
name: 'SidebarItem',
|
||||
components: { DeleteTableModal },
|
||||
props: {
|
||||
database: {
|
||||
type: Object,
|
||||
|
@ -75,17 +82,9 @@ export default {
|
|||
}
|
||||
)
|
||||
},
|
||||
async deleteTable(database, table) {
|
||||
deleteTable() {
|
||||
this.$refs.context.hide()
|
||||
this.setLoading(database, true)
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('table/delete', { database, table })
|
||||
} catch (error) {
|
||||
notifyIf(error, 'table')
|
||||
}
|
||||
|
||||
this.setLoading(database, false)
|
||||
this.$refs.deleteTableModal.show()
|
||||
},
|
||||
enableRename() {
|
||||
this.$refs.context.hide()
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<Modal>
|
||||
<h2 class="box__title">Delete {{ view.name }}</h2>
|
||||
<Error :error="error"></Error>
|
||||
<div>
|
||||
<p>
|
||||
Are you sure you want to delete the view <strong>{{ view.name }}</strong
|
||||
>? The table data will be preserved, but the filters, sortings and field
|
||||
widths related to the view will be deleted.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<div class="align-right">
|
||||
<button
|
||||
class="button button--large button--error"
|
||||
:class="{ 'button--loading': loading }"
|
||||
:disabled="loading"
|
||||
@click="deleteView()"
|
||||
>
|
||||
Delete view
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modal from '@baserow/modules/core/mixins/modal'
|
||||
import error from '@baserow/modules/core/mixins/error'
|
||||
|
||||
export default {
|
||||
name: 'DeleteViewModal',
|
||||
mixins: [modal, error],
|
||||
props: {
|
||||
view: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async deleteView() {
|
||||
this.hideError()
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('view/delete', this.view)
|
||||
this.hide()
|
||||
} catch (error) {
|
||||
this.handleError(error, 'view')
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -33,22 +33,25 @@
|
|||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @click="deleteView(view)">
|
||||
<a @click="deleteView()">
|
||||
<i class="context__menu-icon fas fa-fw fa-trash"></i>
|
||||
Delete view
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</Context>
|
||||
<DeleteViewModal ref="deleteViewModal" :view="view" />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import context from '@baserow/modules/core/mixins/context'
|
||||
import { notifyIf } from '@baserow/modules/core/utils/error'
|
||||
import DeleteViewModal from './DeleteViewModal'
|
||||
|
||||
export default {
|
||||
name: 'ViewsContextItem',
|
||||
components: { DeleteViewModal },
|
||||
mixins: [context],
|
||||
props: {
|
||||
view: {
|
||||
|
@ -80,17 +83,9 @@ export default {
|
|||
|
||||
this.setLoading(view, false)
|
||||
},
|
||||
async deleteView(view) {
|
||||
deleteView() {
|
||||
this.$refs.context.hide()
|
||||
this.setLoading(view, true)
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('view/delete', view)
|
||||
} catch (error) {
|
||||
notifyIf(error, 'view')
|
||||
}
|
||||
|
||||
this.setLoading(view, false)
|
||||
this.$refs.deleteViewModal.show()
|
||||
},
|
||||
selectView(view) {
|
||||
this.$nuxt.$router.push({
|
||||
|
|
Loading…
Add table
Reference in a new issue