Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data section resource deletion warning #15499

Merged
merged 38 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6b566d8
TS conversions of components required to create generic deletion comp…
mike12345567 Jan 29, 2025
795df85
More TS fixes.
mike12345567 Jan 29, 2025
b8e5512
Remove table word, pass this in instead
mike12345567 Jan 29, 2025
1b8a229
Functions to get source type and usage endpoint for screens.
mike12345567 Jan 30, 2025
47fdd0f
Still requires tests, but main body of endpoint to check screen usage.
mike12345567 Jan 30, 2025
1d32474
Merge branch 'master' of github.com:Budibase/budibase into feature/pr…
mike12345567 Jan 31, 2025
d6fb87d
Creating structures for testing usage endpoint.
mike12345567 Jan 31, 2025
5a737ff
Completing test cases for usage endpoint.
mike12345567 Jan 31, 2025
be301df
Merge branch 'master' of github.com:Budibase/budibase into feature/pr…
mike12345567 Feb 3, 2025
b214019
Frontend usage of API.
mike12345567 Feb 3, 2025
a1409f4
implementing usage API in the modal.
mike12345567 Feb 3, 2025
be33f59
Getting tables and views to be deleted through the new generic modal.
mike12345567 Feb 3, 2025
c311d64
Updating queries to use the same mechanism.
mike12345567 Feb 3, 2025
6c0e33a
Merge branch 'master' of github.com:Budibase/budibase into feature/pr…
mike12345567 Feb 4, 2025
cbc13ad
Updating datasource to delete through it.
mike12345567 Feb 4, 2025
5c97771
Adding internal knowledge check to usage.
mike12345567 Feb 4, 2025
3bb0cde
Changing messaging for deletion.
mike12345567 Feb 4, 2025
4809973
Small fixes.
mike12345567 Feb 4, 2025
78c1633
Remove input.
mike12345567 Feb 5, 2025
877f30b
No input required for deletion.
mike12345567 Feb 5, 2025
555cc15
Updates to design, removing alert.
mike12345567 Feb 5, 2025
880f27e
Changing how messaging is generated.
mike12345567 Feb 5, 2025
d04ce5c
Merge branch 'master' of github.com:Budibase/budibase into feature/pr…
mike12345567 Feb 6, 2025
fdf82a6
Some updates, deleting external tables does delete data so warn about…
mike12345567 Feb 6, 2025
399cf0e
Removing unused elements.
mike12345567 Feb 6, 2025
e1f43c4
Merge branch 'master' into feature/pre-empt-data-source-deletion
mike12345567 Feb 6, 2025
e8c79bc
Most PR comments.
mike12345567 Feb 6, 2025
c060d46
Merge branch 'feature/pre-empt-data-source-deletion' of github.com:Bu…
mike12345567 Feb 6, 2025
83fdbcc
export directly.
mike12345567 Feb 6, 2025
a5f2a05
Linting.
mike12345567 Feb 6, 2025
5be6141
Merge branch 'master' into feature/pre-empt-data-source-deletion
mike12345567 Feb 6, 2025
f9c75a2
Final comments.
mike12345567 Feb 6, 2025
c098099
cleanup.
mike12345567 Feb 6, 2025
0750b74
Merge branch 'feature/pre-empt-data-source-deletion' of github.com:Bu…
mike12345567 Feb 6, 2025
ec3cd23
Merge branch 'master' of github.com:Budibase/budibase into feature/pr…
mike12345567 Feb 7, 2025
85b2db1
Majority of comments.
mike12345567 Feb 7, 2025
126befd
Updating UIEvent to an interface.
mike12345567 Feb 7, 2025
6435c9b
Linting.
mike12345567 Feb 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
viewsV2,
} from "@/stores/builder"
import ConfirmDialog from "@/components/common/ConfirmDialog.svelte"
import { helpers } from "@budibase/shared-core"
import { SourceType } from "@budibase/types"
import { goto, params } from "@roxi/routify"
import { DB_TYPE_EXTERNAL } from "@/constants/backend"
Expand Down Expand Up @@ -85,7 +86,7 @@

async function deleteView(view: ViewV2 | View) {
try {
if ("version" in view && view.version === 2) {
if ("version" in view && helpers.views.isCalculationView(view)) {
mike12345567 marked this conversation as resolved.
Show resolved Hide resolved
await viewsV2.delete(view as ViewV2)
} else {
await views.delete(view as View)
Expand All @@ -99,10 +100,10 @@

async function deleteDatasource(datasource: Datasource) {
try {
const isSelected =
get(datasources).selectedDatasourceId === datasource._id
await datasources.delete(datasource)
notifications.success("Datasource deleted")
const isSelected =
get(datasources).selectedDatasourceId === datasource._id
if (isSelected) {
$goto("./datasource")
}
Expand Down
105 changes: 36 additions & 69 deletions packages/server/src/api/routes/tests/screen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import {

const {
basicScreen,
tableScreen,
viewScreen,
queryScreen,
createTableScreen,
createViewScreen,
createQueryScreen,
basicTable,
viewV2,
basicQuery,
Expand All @@ -33,7 +33,7 @@ describe("/screens", () => {

describe("fetch", () => {
it("should be able to create a layout", async () => {
const screens = await config.api.screen.list({ status: 200 })
const screens = await config.api.screen.list()
expect(screens.length).toEqual(1)
expect(screens.some(s => s._id === screen._id)).toEqual(true)
})
Expand Down Expand Up @@ -67,39 +67,30 @@ describe("/screens", () => {
inherits: [role1._id!, role2._id!],
permissionId: BuiltinPermissionID.WRITE,
})
screen1 = await config.api.screen.save(
{
...basicScreen(),
routing: {
roleId: role1._id!,
route: "/foo",
homeScreen: false,
},
screen1 = await config.api.screen.save({
...basicScreen(),
routing: {
roleId: role1._id!,
route: "/foo",
homeScreen: false,
},
{ status: 200 }
)
screen2 = await config.api.screen.save(
{
...basicScreen(),
routing: {
roleId: role2._id!,
route: "/bar",
homeScreen: false,
},
})
screen2 = await config.api.screen.save({
...basicScreen(),
routing: {
roleId: role2._id!,
route: "/bar",
homeScreen: false,
},
{ status: 200 }
)
})
// get into prod app
await config.publish()
})

async function checkScreens(roleId: string, screenIds: string[]) {
await config.loginAsRole(roleId, async () => {
const res = await config.api.application.getDefinition(
config.prodAppId!,
{
status: 200,
}
config.prodAppId!
mike12345567 marked this conversation as resolved.
Show resolved Hide resolved
)
expect(res.screens.length).toEqual(screenIds.length)
expect(res.screens.map(s => s._id).sort()).toEqual(screenIds.sort())
Expand Down Expand Up @@ -129,10 +120,7 @@ describe("/screens", () => {
},
async () => {
const res = await config.api.application.getDefinition(
config.prodAppId!,
{
status: 200,
}
config.prodAppId!
)
const screenIds = [screen._id!, screen1._id!]
expect(res.screens.length).toEqual(screenIds.length)
Expand All @@ -149,9 +137,7 @@ describe("/screens", () => {

it("should be able to create a screen", async () => {
const screen = basicScreen()
const responseScreen = await config.api.screen.save(screen, {
status: 200,
})
const responseScreen = await config.api.screen.save(screen)

expect(responseScreen._rev).toBeDefined()
expect(responseScreen.name).toEqual(screen.name)
Expand All @@ -160,13 +146,13 @@ describe("/screens", () => {

it("should be able to update a screen", async () => {
const screen = basicScreen()
let responseScreen = await config.api.screen.save(screen, { status: 200 })
let responseScreen = await config.api.screen.save(screen)
screen._id = responseScreen._id
screen._rev = responseScreen._rev
screen.name = "edit"
jest.clearAllMocks()

responseScreen = await config.api.screen.save(screen, { status: 200 })
responseScreen = await config.api.screen.save(screen)

expect(responseScreen._rev).toBeDefined()
expect(responseScreen.name).toEqual(screen.name)
Expand All @@ -186,8 +172,7 @@ describe("/screens", () => {
it("should be able to delete the screen", async () => {
const response = await config.api.screen.destroy(
screen._id!,
screen._rev!,
{ status: 200 }
screen._rev!
)
expect(response.message).toBeDefined()
expect(events.screen.deleted).toHaveBeenCalledTimes(1)
Expand All @@ -205,9 +190,7 @@ describe("/screens", () => {
describe("usage", () => {
beforeEach(async () => {
await config.init()
await config.api.screen.save(basicScreen(), {
status: 200,
})
await config.api.screen.save(basicScreen())
})

function confirmScreen(usage: UsageOfScreensResponse, screen: Screen) {
Expand All @@ -217,57 +200,41 @@ describe("/screens", () => {
}

it("should find table usage", async () => {
const table = await config.api.table.save(basicTable(), { status: 200 })
const table = await config.api.table.save(basicTable())
const screen = await config.api.screen.save(
tableScreen("BudibaseDB", table),
{ status: 200 }
createTableScreen("BudibaseDB", table)
)
const usage = await config.api.screen.usage(table._id!, { status: 200 })
const usage = await config.api.screen.usage(table._id!)
expect(usage.sourceType).toEqual(SourceType.TABLE)
confirmScreen(usage, screen)
})

it("should find view usage", async () => {
const table = await config.api.table.save(basicTable(), { status: 200 })
const table = await config.api.table.save(basicTable())
const view = await config.api.viewV2.create(
viewV2.createRequest(table._id!),
{ status: 201 }
)
const screen = await config.api.screen.save(
viewScreen("BudibaseDB", view),
{
status: 200,
}
createViewScreen("BudibaseDB", view)
)
const usage = await config.api.screen.usage(view.id, { status: 200 })
const usage = await config.api.screen.usage(view.id)
expect(usage.sourceType).toEqual(SourceType.VIEW)
confirmScreen(usage, screen)
})

it("should find datasource/query usage", async () => {
const datasource = await config.api.datasource.create(
basicDatasource().datasource,
{
status: 200,
}
basicDatasource().datasource
)
const query = await config.api.query.save(basicQuery(datasource._id!), {
status: 200,
})
const query = await config.api.query.save(basicQuery(datasource._id!))
const screen = await config.api.screen.save(
queryScreen(datasource._id!, query),
{
status: 200,
}
createQueryScreen(datasource._id!, query)
)
const dsUsage = await config.api.screen.usage(datasource._id!, {
status: 200,
})
const dsUsage = await config.api.screen.usage(datasource._id!)
expect(dsUsage.sourceType).toEqual(SourceType.DATASOURCE)
confirmScreen(dsUsage, screen)
const queryUsage = await config.api.screen.usage(query._id!, {
status: 200,
})
const queryUsage = await config.api.screen.usage(query._id!)
expect(queryUsage.sourceType).toEqual(SourceType.QUERY)
confirmScreen(queryUsage, screen)
})
Expand Down
4 changes: 2 additions & 2 deletions packages/server/src/constants/screens.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { roles } from "@budibase/backend-core"
import { BASE_LAYOUT_PROP_IDS } from "./layouts"
import { Screen, Table, Query, ViewV2 } from "@budibase/types"
import { Screen, Table, Query, ViewV2, Component } from "@budibase/types"

export function createHomeScreen(
config: {
Expand Down Expand Up @@ -54,7 +54,7 @@ export function createHomeScreen(
}
}

function heading(text: string) {
function heading(text: string): Component {
return {
_id: "c1bff24cd821e41d18c894ac77a80ef99",
_component: "@budibase/standard-components/heading",
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/sdk/app/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export function getSourceType(sourceId: string): SourceType {
} else if (docIds.isQueryId(sourceId)) {
return SourceType.QUERY
}
throw new Error("Unknown source type - cannot find document type")
throw new Error(`Unknown source type for source "${sourceId}"`)
}
25 changes: 6 additions & 19 deletions packages/server/src/tests/utilities/structures.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { roles, utils } from "@budibase/backend-core"
import {
createHomeScreen,
createTableScreen,
createQueryScreen,
createViewScreen,
} from "../../constants/screens"
import { createHomeScreen } from "../../constants/screens"
import { EMPTY_LAYOUT } from "../../constants/layouts"
import { cloneDeep } from "lodash/fp"
import {
Expand Down Expand Up @@ -40,11 +35,15 @@ import {
WebhookActionType,
BuiltinPermissionID,
DeepPartial,
ViewV2,
} from "@budibase/types"
import { LoopInput } from "../../definitions/automations"
import { merge } from "lodash"
import { generator } from "@budibase/backend-core/tests"
export {
createTableScreen,
createQueryScreen,
createViewScreen,
} from "../../constants/screens"

const { BUILTIN_ROLE_IDS } = roles

Expand Down Expand Up @@ -521,18 +520,6 @@ export function basicScreen(route = "/") {
})
}

export function tableScreen(datasourceName: string, table: Table) {
return createTableScreen(datasourceName, table)
}

export function viewScreen(datasourceName: string, view: ViewV2) {
return createViewScreen(datasourceName, view)
}

export function queryScreen(datasourceId: string, query: Query) {
return createQueryScreen(datasourceId, query)
}

export function powerScreen(route = "/") {
return createHomeScreen({
roleId: BUILTIN_ROLE_IDS.POWER,
Expand Down
12 changes: 6 additions & 6 deletions packages/shared-core/src/sdk/documents/screens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import { Screen } from "@budibase/types"
export function findInSettings(screen: Screen, toFind: string) {
const foundIn: { setting: string; value: string }[] = []
function recurse(props: Record<string, any>, parentKey = "") {
mike12345567 marked this conversation as resolved.
Show resolved Hide resolved
for (let key of Object.keys(props)) {
if (!props[key]) {
for (const [key, value] of Object.entries(props)) {
if (!value) {
continue
}
if (typeof props[key] === "string" && props[key].includes(toFind)) {
if (typeof value === "string" && value.includes(toFind)) {
foundIn.push({
setting: parentKey ? `${parentKey}.${key}` : key,
value: props[key],
value: value,
})
} else if (typeof props[key] === "object") {
recurse(props[key], key)
} else if (typeof value === "object") {
recurse(value, key)
}
}
}
Expand Down
Loading