Getting tables and views to be deleted through the new generic modal.

This commit is contained in:
mike12345567 2025-02-03 16:25:50 +00:00
parent a1409f43fa
commit be33f59ff0
5 changed files with 76 additions and 227 deletions

View File

@ -1,175 +0,0 @@
<script>
import { goto, params } from "@roxi/routify"
import { appStore, tables, datasources, screenStore } from "@/stores/builder"
import { InlineAlert, Link, Input, notifications } from "@budibase/bbui"
import ConfirmDialog from "@/components/common/ConfirmDialog.svelte"
import { DB_TYPE_EXTERNAL } from "@/constants/backend"
export let table
let confirmDeleteDialog
let screensPossiblyAffected = []
let viewsMessage = ""
let deleteTableName
const getViewsMessage = () => {
const views = Object.values(table?.views ?? [])
if (views.length < 1) {
return ""
}
if (views.length === 1) {
return ", including 1 view"
}
return `, including ${views.length} views`
}
export const show = () => {
viewsMessage = getViewsMessage()
screensPossiblyAffected = $screenStore.screens
.filter(
screen => screen.autoTableId === table._id && screen.routing?.route
)
.map(screen => ({
text: screen.routing.route,
url: `/builder/app/${$appStore.appId}/design/${screen._id}`,
}))
confirmDeleteDialog.show()
}
async function deleteTable() {
const isSelected = $params.tableId === table._id
try {
await tables.delete(table)
if (table.sourceType === DB_TYPE_EXTERNAL) {
await datasources.fetch()
}
notifications.success("Table deleted")
if (isSelected) {
$goto(`./datasource/${table.datasourceId}`)
}
} catch (error) {
notifications.error(`Error deleting table - ${error.message}`)
}
}
function hideDeleteDialog() {
deleteTableName = ""
}
const autofillTableName = () => {
deleteTableName = table.name
}
</script>
<ConfirmDialog
bind:this={confirmDeleteDialog}
okText="Delete Table"
onOk={deleteTable}
onCancel={hideDeleteDialog}
title="Confirm Deletion"
disabled={deleteTableName !== table.name}
>
<div class="content">
<p class="firstWarning">
Are you sure you wish to delete the table
<span class="tableNameLine">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<b on:click={autofillTableName} class="tableName">{table.name}</b>
<span>?</span>
</span>
</p>
<p class="secondWarning">All table data will be deleted{viewsMessage}.</p>
<p class="thirdWarning">This action <b>cannot be undone</b>.</p>
{#if screensPossiblyAffected.length > 0}
<div class="affectedScreens">
<InlineAlert
header="The following screens were originally generated from this table and may no longer function as expected"
>
<ul class="affectedScreensList">
{#each screensPossiblyAffected as item}
<li>
<Link quiet overBackground target="_blank" href={item.url}
>{item.text}</Link
>
</li>
{/each}
</ul>
</InlineAlert>
</div>
{/if}
<p class="fourthWarning">Please enter the table name below to confirm.</p>
<Input bind:value={deleteTableName} placeholder={table.name} />
</div>
</ConfirmDialog>
<style>
.content {
margin-top: 0;
max-width: 320px;
}
.firstWarning {
margin: 0 0 12px;
max-width: 100%;
}
.tableNameLine {
display: inline-flex;
max-width: 100%;
vertical-align: bottom;
}
.tableName {
flex-grow: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
}
.secondWarning {
margin: 0;
max-width: 100%;
}
.thirdWarning {
margin: 0 0 12px;
max-width: 100%;
}
.affectedScreens {
margin: 18px 0;
max-width: 100%;
margin-bottom: 24px;
}
.affectedScreens :global(.spectrum-InLineAlert) {
max-width: 100%;
}
.affectedScreensList {
padding: 0;
margin-bottom: 0;
}
.affectedScreensList li {
display: block;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-top: 4px;
}
.fourthWarning {
margin: 12px 0 6px;
max-width: 100%;
}
</style>

View File

@ -8,7 +8,7 @@
import NavItem from "@/components/common/NavItem.svelte"
import { isActive } from "@roxi/routify"
import EditModal from "./EditModal.svelte"
import DeleteConfirmationModal from "./DeleteConfirmationModal.svelte"
import DeleteConfirmationModal from "../../modals/DeleteDataConfirmationModal.svelte"
import { Icon } from "@budibase/bbui"
import { DB_TYPE_EXTERNAL } from "@/constants/backend"
@ -65,4 +65,4 @@
{/if}
</NavItem>
<EditModal {table} bind:this={editModal} />
<DeleteConfirmationModal {table} bind:this={deleteConfirmationModal} />
<DeleteConfirmationModal source={table} bind:this={deleteConfirmationModal} />

View File

@ -1,16 +1,24 @@
<script lang="ts">
import { InlineAlert, Link, Input } from "@budibase/bbui"
import { appStore, screenStore } from "@/stores/builder"
import { InlineAlert, Link, Input, notifications } from "@budibase/bbui"
import {
appStore,
datasources,
screenStore,
tables,
views,
viewsV2,
} from "@/stores/builder"
import ConfirmDialog from "@/components/common/ConfirmDialog.svelte"
import type { Table, ViewV2, Datasource, Query } from "@budibase/types"
import { SourceType } from "@budibase/types"
import { goto, params } from "@roxi/routify"
import { DB_TYPE_EXTERNAL } from "@/constants/backend"
import type { Table, ViewV2, View, Datasource, Query } from "@budibase/types"
export let source: Table | ViewV2 | Datasource | Query | undefined
export let type: "table" | "view" | "datasource" | "query"
export let deleteSourceFn: () => Promise<void>
let confirmDeleteDialog: any
let affectedScreens: { text: string; url: string }[] = []
let sourceType: SourceType | undefined = undefined
let viewsMessage: string = ""
let deleteSourceName: string | undefined
@ -43,6 +51,7 @@
viewsMessage = getViewsMessage()
const usage = await screenStore.usageOfScreens(getSourceID())
affectedScreens = processScreens(usage.screens)
sourceType = usage.sourceType
confirmDeleteDialog.show()
}
@ -62,19 +71,68 @@
const autofillSourceName = () => {
deleteSourceName = source?.name
}
async function deleteTable(table: Table & { datasourceId?: string }) {
const isSelected = $params.tableId === table._id
try {
await tables.delete({
_id: table._id!,
_rev: table._rev!,
})
if (table.sourceType === DB_TYPE_EXTERNAL) {
await datasources.fetch()
}
notifications.success("Table deleted")
if (isSelected) {
$goto(`./datasource/${table.datasourceId}`)
}
} catch (error: any) {
notifications.error(`Error deleting table - ${error.message}`)
}
}
async function deleteView(view: ViewV2 | View) {
try {
if ("version" in view && view.version === 2) {
await viewsV2.delete(view as ViewV2)
} else {
await views.delete(view as View)
}
notifications.success("View deleted")
} catch (error) {
console.error(error)
notifications.error("Error deleting view")
}
}
async function deleteSource() {
if (!source || !sourceType) {
throw new Error("Unable to delete - no data source found.")
}
switch (sourceType) {
case SourceType.TABLE:
return await deleteTable(source as Table)
case SourceType.VIEW:
return await deleteView(source as ViewV2)
case SourceType.DATASOURCE:
case SourceType.QUERY:
}
}
</script>
<ConfirmDialog
bind:this={confirmDeleteDialog}
okText={`Delete ${type}`}
onOk={deleteSourceFn}
okText={`Delete ${sourceType}`}
onOk={deleteSource}
onCancel={hideDeleteDialog}
title="Confirm Deletion"
disabled={deleteSourceName !== source?.name}
>
<div class="content">
<p class="firstWarning">
Are you sure you wish to delete the {type}
Are you sure you wish to delete the {sourceType}
<span class="sourceNameLine">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
@ -83,13 +141,15 @@
</span>
</p>
<p class="secondWarning">All {type} data will be deleted{viewsMessage}.</p>
<p class="secondWarning">
All {sourceType} data will be deleted{viewsMessage}.
</p>
<p class="thirdWarning">This action <b>cannot be undone</b>.</p>
{#if affectedScreens.length > 0}
<div class="affectedScreens">
<InlineAlert
header={`The following screens were originally generated from this ${type} and may no longer function as expected`}
header={`The following screens use this ${sourceType} and may no longer function as expected`}
>
<ul class="affectedScreensList">
{#each affectedScreens as item}

View File

@ -1,35 +0,0 @@
<script>
import { views, viewsV2 } from "@/stores/builder"
import ConfirmDialog from "@/components/common/ConfirmDialog.svelte"
import { notifications } from "@budibase/bbui"
export let view
let confirmDeleteDialog
export const show = () => {
confirmDeleteDialog.show()
}
async function deleteView() {
try {
if (view.version === 2) {
await viewsV2.delete(view)
} else {
await views.delete(view)
}
notifications.success("View deleted")
} catch (error) {
console.error(error)
notifications.error("Error deleting view")
}
}
</script>
<ConfirmDialog
bind:this={confirmDeleteDialog}
body={`Are you sure you wish to delete the view '${view.name}'? Your data will be deleted and this action cannot be undone.`}
okText="Delete View"
onOk={deleteView}
title="Confirm Deletion"
/>

View File

@ -10,9 +10,8 @@
import { Icon, ActionButton, ActionMenu, MenuItem } from "@budibase/bbui"
import { params, url } from "@roxi/routify"
import EditViewModal from "./EditViewModal.svelte"
import DeleteViewModal from "./DeleteViewModal.svelte"
import EditTableModal from "@/components/backend/TableNavigator/TableNavItem/EditModal.svelte"
import DeleteTableModal from "@/components/backend/TableNavigator/TableNavItem/DeleteConfirmationModal.svelte"
import DeleteConfirmationModal from "@/components/backend/modals/DeleteDataConfirmationModal.svelte"
import { UserAvatars } from "@budibase/frontend-core"
import { DB_TYPE_EXTERNAL } from "@/constants/backend"
import { TableNames } from "@/constants"
@ -314,12 +313,12 @@
{#if table && tableEditable}
<EditTableModal {table} bind:this={editTableModal} />
<DeleteTableModal {table} bind:this={deleteTableModal} />
<DeleteConfirmationModal source={table} bind:this={deleteTableModal} />
{/if}
{#if editableView}
<EditViewModal view={editableView} bind:this={editViewModal} />
<DeleteViewModal view={editableView} bind:this={deleteViewModal} />
<DeleteConfirmationModal source={editableView} bind:this={deleteViewModal} />
{/if}
<style>