- {#each $tables.list.filter(table => table.type !== "external") as table}
+ {#each internalTablesBySourceId as table}
+ import { datasources } from "stores/backend"
+
+ datasources.select("datasource_internal_bb_default")
+
+
+
diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/datasource_internal_bb_default/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/datasource_internal_bb_default/index.svelte
new file mode 100644
index 0000000000..540ca20bc1
--- /dev/null
+++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/datasource_internal_bb_default/index.svelte
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+ A little something to get you up and running!
+ If you have no need for this datasource, feel free to delete it.
+
+
+ Tables
+
+
+ {#each internalTablesBySourceId as table}
+
+ {table.name}
+ {#if table.primaryDisplay}
+ Display column: {table.primaryDisplay}
+ {/if}
+
+ {/each}
+
+
+ Create new table
+
+
+
+
+
diff --git a/packages/builder/src/pages/builder/app/[application]/data/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/index.svelte
index 42ee02a308..b2aca1f7f3 100644
--- a/packages/builder/src/pages/builder/app/[application]/data/index.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/data/index.svelte
@@ -7,8 +7,8 @@
let modal
$: setupComplete =
- $datasources.list.find(x => (x._id = "bb_internal"))?.entities.length > 1 ||
- $datasources.list.length > 1
+ $datasources.list.find(x => (x._id = "bb_internal"))?.entities?.length >
+ 1 || $datasources.list.length > 1
onMount(() => {
if (!setupComplete && !$admin.isDev) {
diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts
index dcd092d06a..83d7bb0b8d 100644
--- a/packages/server/src/api/controllers/application.ts
+++ b/packages/server/src/api/controllers/application.ts
@@ -25,8 +25,14 @@ import {
migrations,
} from "@budibase/backend-core"
import { USERS_TABLE_SCHEMA } from "../../constants"
+import { buildDefaultDocs } from "../../db/defaultData/datasource_bb_default"
+
import { removeAppFromUserRoles } from "../../utilities/workerRequests"
-import { clientLibraryPath, stringToReadStream } from "../../utilities"
+import {
+ clientLibraryPath,
+ stringToReadStream,
+ isQsTrue,
+} from "../../utilities"
import { getLocksById } from "../../utilities/redis"
import {
updateClientLibrary,
@@ -117,7 +123,7 @@ const checkAppName = (
}
}
-async function createInstance(template: any) {
+async function createInstance(template: any, includeSampleData: boolean) {
const tenantId = tenancy.isMultiTenant() ? tenancy.getTenantId() : null
const baseAppId = generateAppID(tenantId)
const appId = generateDevAppID(baseAppId)
@@ -149,11 +155,23 @@ async function createInstance(template: any) {
} else {
// create the users table
await db.put(USERS_TABLE_SCHEMA)
+
+ if (includeSampleData) {
+ // create ootb stock db
+ await addDefaultTables(db)
+ }
}
return { _id: appId }
}
+const addDefaultTables = async (db: any) => {
+ const defaultDbDocs = buildDefaultDocs()
+
+ // add in the default db data docs - tables, datasource, rows and links
+ await db.bulkDocs([...defaultDbDocs])
+}
+
export const fetch = async (ctx: any) => {
const dev = ctx.query && ctx.query.status === AppStatus.DEV
const all = ctx.query && ctx.query.status === AppStatus.ALL
@@ -234,7 +252,8 @@ const performAppCreate = async (ctx: any) => {
if (ctx.request.files && ctx.request.files.templateFile) {
instanceConfig.file = ctx.request.files.templateFile
}
- const instance = await createInstance(instanceConfig)
+ const includeSampleData = isQsTrue(ctx.request.body.sampleData)
+ const instance = await createInstance(instanceConfig, includeSampleData)
const appId = instance._id
const db = context.getAppDB()
diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js
index af52be8e26..80bd263d87 100644
--- a/packages/server/src/api/controllers/datasource.js
+++ b/packages/server/src/api/controllers/datasource.js
@@ -6,12 +6,14 @@ const {
BudibaseInternalDB,
getTableParams,
} = require("../../db/utils")
+const { destroy: tableDestroy } = require("./table/internal")
const { BuildSchemaErrors, InvalidColumns } = require("../../constants")
const { getIntegration } = require("../../integrations")
const { getDatasourceAndQuery } = require("./row/utils")
const { invalidateDynamicVariables } = require("../../threads/utils")
const { getAppDB } = require("@budibase/backend-core/context")
const { events } = require("@budibase/backend-core")
+const { db: dbCore } = require("@budibase/backend-core")
exports.fetch = async function (ctx) {
// Get internal tables
@@ -21,11 +23,16 @@ exports.fetch = async function (ctx) {
include_docs: true,
})
)
- const internal = internalTables.rows.map(row => row.doc)
+
+ const internal = internalTables.rows.reduce((acc, row) => {
+ const sourceId = row.doc.sourceId || "bb_internal"
+ acc[sourceId] = acc[sourceId] || []
+ acc[sourceId].push(row.doc)
+ return acc
+ }, {})
const bbInternalDb = {
...BudibaseInternalDB,
- entities: internal,
}
// Get external datasources
@@ -37,11 +44,17 @@ exports.fetch = async function (ctx) {
)
).rows.map(row => row.doc)
- for (let datasource of datasources) {
+ const allDatasources = [bbInternalDb, ...datasources]
+
+ for (let datasource of allDatasources) {
if (datasource.config && datasource.config.auth) {
// strip secrets from response so they don't show in the network request
delete datasource.config.auth
}
+
+ if (datasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE) {
+ datasource.entities = internal[datasource._id]
+ }
}
ctx.body = [bbInternalDb, ...datasources]
@@ -196,20 +209,53 @@ exports.save = async function (ctx) {
ctx.body = response
}
+const destroyInternalTablesBySourceId = async datasourceId => {
+ const db = getAppDB()
+
+ // Get all internal tables
+ const internalTables = await db.allDocs(
+ getTableParams(null, {
+ include_docs: true,
+ })
+ )
+
+ // Filter by datasource and return the docs.
+ const datasourceTableDocs = internalTables.rows.reduce((acc, table) => {
+ if (table.doc.sourceId == datasourceId) {
+ acc.push(table.doc)
+ }
+ return acc
+ }, [])
+
+ // Destroy the tables.
+ for (const table of datasourceTableDocs) {
+ await tableDestroy({
+ params: {
+ tableId: table._id,
+ },
+ })
+ }
+}
+
exports.destroy = async function (ctx) {
const db = getAppDB()
const datasourceId = ctx.params.datasourceId
const datasource = await db.get(datasourceId)
// Delete all queries for the datasource
- const queries = await db.allDocs(getQueryParams(datasourceId, null))
- await db.bulkDocs(
- queries.rows.map(row => ({
- _id: row.id,
- _rev: row.value.rev,
- _deleted: true,
- }))
- )
+
+ if (datasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE) {
+ await destroyInternalTablesBySourceId(datasourceId)
+ } else {
+ const queries = await db.allDocs(getQueryParams(datasourceId, null))
+ await db.bulkDocs(
+ queries.rows.map(row => ({
+ _id: row.id,
+ _rev: row.value.rev,
+ _deleted: true,
+ }))
+ )
+ }
// delete the datasource
await db.remove(datasourceId, ctx.params.revId)
diff --git a/packages/server/src/api/controllers/table/utils.ts b/packages/server/src/api/controllers/table/utils.ts
index 6d17d12f3d..f182e6777d 100644
--- a/packages/server/src/api/controllers/table/utils.ts
+++ b/packages/server/src/api/controllers/table/utils.ts
@@ -95,18 +95,7 @@ export function makeSureTableUpToDate(table: any, tableToSave: any) {
return tableToSave
}
-export async function handleDataImport(user: any, table: any, dataImport: any) {
- if (!dataImport || !dataImport.csvString) {
- return table
- }
-
- const db = getAppDB()
- // Populate the table with rows imported from CSV in a bulk update
- const data = await transform({
- ...dataImport,
- existingTable: table,
- })
-
+export function importToRows(data: any, table: any, user: any = {}) {
let finalData: any = []
for (let i = 0; i < data.length; i++) {
let row = data[i]
@@ -136,6 +125,22 @@ export async function handleDataImport(user: any, table: any, dataImport: any) {
finalData.push(row)
}
+ return finalData
+}
+
+export async function handleDataImport(user: any, table: any, dataImport: any) {
+ if (!dataImport || !dataImport.csvString) {
+ return table
+ }
+
+ const db = getAppDB()
+ // Populate the table with rows imported from CSV in a bulk update
+ const data = await transform({
+ ...dataImport,
+ existingTable: table,
+ })
+
+ let finalData: any = importToRows(data, table, user)
await quotas.addRows(finalData.length, () => db.bulkDocs(finalData), {
tableId: table._id,
diff --git a/packages/server/src/db/defaultData/datasource_bb_default.js b/packages/server/src/db/defaultData/datasource_bb_default.js
new file mode 100644
index 0000000000..f12ee2c97d
--- /dev/null
+++ b/packages/server/src/db/defaultData/datasource_bb_default.js
@@ -0,0 +1,646 @@
+const {
+ FieldTypes,
+ AutoFieldSubTypes,
+ RelationshipTypes,
+} = require("../../constants/index")
+const { importToRows } = require("../../api/controllers/table/utils")
+const { cloneDeep } = require("lodash/fp")
+const LinkDocument = require("../linkedRows/LinkDocument")
+const { inventoryImport } = require("./inventoryImport")
+const { employeeImport } = require("./employeeImport")
+const { jobsImport } = require("./jobsImport")
+const { expensesImport } = require("./expensesImport")
+const { db: dbCore } = require("@budibase/backend-core")
+
+exports.DEFAULT_JOBS_TABLE_ID = "ta_bb_jobs"
+exports.DEFAULT_INVENTORY_TABLE_ID = "ta_bb_inventory"
+exports.DEFAULT_EXPENSES_TABLE_ID = "ta_bb_expenses"
+exports.DEFAULT_EMPLOYEE_TABLE_ID = "ta_bb_employee"
+exports.DEFAULT_BB_DATASOURCE_ID = "datasource_internal_bb_default"
+exports.DEFAULT_BB_DATASOURCE = {
+ _id: this.DEFAULT_BB_DATASOURCE_ID,
+ type: dbCore.BUDIBASE_DATASOURCE_TYPE,
+ name: "Sample Data",
+ source: "BUDIBASE",
+ config: {},
+}
+
+const syncLastIds = (table, rowCount) => {
+ Object.keys(table.schema).forEach(key => {
+ const entry = table.schema[key]
+ if (entry.autocolumn && entry.subtype == "autoID") {
+ entry.lastID = rowCount
+ }
+ })
+}
+
+const tableImport = (table, data) => {
+ const cloneTable = cloneDeep(table)
+ const rowDocs = importToRows(data, cloneTable)
+ syncLastIds(cloneTable, rowDocs.length)
+ return { rows: rowDocs, table: cloneTable }
+}
+
+// AUTO COLUMNS
+const AUTO_COLUMNS = {
+ "Created At": {
+ name: "Created At",
+ type: FieldTypes.DATETIME,
+ subtype: AutoFieldSubTypes.CREATED_AT,
+ icon: "ri-magic-line",
+ autocolumn: true,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ },
+ "Updated At": {
+ name: "Updated At",
+ type: FieldTypes.DATETIME,
+ subtype: AutoFieldSubTypes.UPDATED_AT,
+ icon: "ri-magic-line",
+ autocolumn: true,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ },
+}
+
+exports.DEFAULT_INVENTORY_TABLE_SCHEMA = {
+ _id: this.DEFAULT_INVENTORY_TABLE_ID,
+ type: "internal",
+ views: {},
+ sourceId: exports.DEFAULT_BB_DATASOURCE_ID,
+ primaryDisplay: "Item Name",
+ name: "Inventory",
+ schema: {
+ "Item ID": {
+ name: "Item ID",
+ type: FieldTypes.NUMBER,
+ subtype: AutoFieldSubTypes.AUTO_ID,
+ icon: "ri-magic-line",
+ autocolumn: true,
+ constraints: {
+ type: FieldTypes.NUMBER,
+ presence: false,
+ numericality: {
+ greaterThanOrEqualTo: "",
+ lessThanOrEqualTo: "",
+ },
+ },
+ },
+ "Item Name": {
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {
+ maximum: null,
+ },
+ presence: {
+ allowEmpty: false,
+ },
+ },
+ name: "Item Name",
+ },
+ "Item Tags": {
+ type: FieldTypes.ARRAY,
+ constraints: {
+ type: FieldTypes.ARRAY,
+ presence: {
+ allowEmpty: false,
+ },
+ inclusion: ["Electrical", "Material", "Vehicle", "Office", "Tools"],
+ },
+ name: "Item Tags",
+ sortable: false,
+ },
+ Notes: {
+ type: FieldTypes.LONGFORM,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ name: "Notes",
+ useRichText: null,
+ },
+ Status: {
+ type: FieldTypes.ARRAY,
+ constraints: {
+ type: FieldTypes.ARRAY,
+ presence: {
+ allowEmpty: false,
+ },
+ inclusion: ["Available", "Repair", "Broken"],
+ },
+ name: "Status",
+ sortable: false,
+ },
+ SKU: {
+ type: FieldTypes.BARCODEQR,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ name: "SKU",
+ },
+ "Purchase Date": {
+ type: FieldTypes.DATETIME,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "Purchase Date",
+ ignoreTimezones: true,
+ },
+ "Purchase Price": {
+ type: FieldTypes.NUMBER,
+ constraints: {
+ type: FieldTypes.NUMBER,
+ presence: false,
+ numericality: {
+ greaterThanOrEqualTo: null,
+ lessThanOrEqualTo: "",
+ },
+ },
+ name: "Purchase Price",
+ },
+ ...AUTO_COLUMNS,
+ },
+}
+
+exports.DEFAULT_EMPLOYEE_TABLE_SCHEMA = {
+ _id: this.DEFAULT_EMPLOYEE_TABLE_ID,
+ type: "internal",
+ views: {},
+ name: "Employees",
+ sourceId: exports.DEFAULT_BB_DATASOURCE_ID,
+ primaryDisplay: "First Name",
+ schema: {
+ "First Name": {
+ name: "First Name",
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ },
+ "Last Name": {
+ name: "Last Name",
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ },
+ Email: {
+ name: "Email",
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ },
+ Address: {
+ name: "Address",
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ },
+ City: {
+ name: "City",
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ },
+ Postcode: {
+ name: "Postcode",
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ },
+ Phone: {
+ name: "Phone",
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ },
+ "EMPLOYEE ID": {
+ name: "EMPLOYEE ID",
+ type: FieldTypes.NUMBER,
+ subtype: AutoFieldSubTypes.AUTO_ID,
+ icon: "ri-magic-line",
+ autocolumn: true,
+ constraints: {
+ type: FieldTypes.NUMBER,
+ presence: false,
+ numericality: {
+ greaterThanOrEqualTo: "",
+ lessThanOrEqualTo: "",
+ },
+ },
+ },
+ "Employee Level": {
+ type: FieldTypes.ARRAY,
+ constraints: {
+ type: FieldTypes.ARRAY,
+ presence: false,
+ inclusion: ["Manager", "Junior", "Senior", "Apprentice", "Contractor"],
+ },
+ name: "Employee Level",
+ sortable: false,
+ },
+ "Badge Photo": {
+ type: "attachment",
+ constraints: {
+ type: FieldTypes.ARRAY,
+ presence: false,
+ },
+ name: "Badge Photo",
+ sortable: false,
+ },
+ Jobs: {
+ type: FieldTypes.LINK,
+ constraints: {
+ type: FieldTypes.ARRAY,
+ presence: false,
+ },
+ fieldName: "Assigned",
+ name: "Jobs",
+ relationshipType: RelationshipTypes.MANY_TO_MANY,
+ tableId: this.DEFAULT_JOBS_TABLE_ID,
+ },
+ "Start Date": {
+ type: FieldTypes.DATETIME,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "Start Date",
+ ignoreTimezones: true,
+ },
+ "End Date": {
+ type: FieldTypes.DATETIME,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "End Date",
+ ignoreTimezones: true,
+ },
+ ...AUTO_COLUMNS,
+ },
+}
+
+exports.DEFAULT_JOBS_TABLE_SCHEMA = {
+ _id: this.DEFAULT_JOBS_TABLE_ID,
+ type: "internal",
+ name: "Jobs",
+ sourceId: exports.DEFAULT_BB_DATASOURCE_ID,
+ primaryDisplay: "Job ID",
+ schema: {
+ "Job ID": {
+ name: "Job ID",
+ type: FieldTypes.NUMBER,
+ subtype: AutoFieldSubTypes.AUTO_ID,
+ icon: "ri-magic-line",
+ autocolumn: true,
+ constraints: {
+ type: FieldTypes.NUMBER,
+ presence: false,
+ numericality: {
+ greaterThanOrEqualTo: "",
+ lessThanOrEqualTo: "",
+ },
+ },
+ },
+ "Quote Date": {
+ type: FieldTypes.DATETIME,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: {
+ allowEmpty: false,
+ },
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "Quote Date",
+ ignoreTimezones: true,
+ },
+ "Quote Price": {
+ type: FieldTypes.NUMBER,
+ constraints: {
+ type: FieldTypes.NUMBER,
+ presence: {
+ allowEmpty: false,
+ },
+ numericality: {
+ greaterThanOrEqualTo: "",
+ lessThanOrEqualTo: "",
+ },
+ },
+ name: "Quote Price",
+ },
+ "Works Start": {
+ type: FieldTypes.DATETIME,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "Works Start",
+ ignoreTimezones: true,
+ },
+ Address: {
+ type: FieldTypes.LONGFORM,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ name: "Address",
+ useRichText: null,
+ },
+ "Customer Name": {
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {
+ maximum: null,
+ },
+ presence: false,
+ },
+ name: "Customer Name",
+ },
+ Notes: {
+ type: FieldTypes.LONGFORM,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ name: "Notes",
+ useRichText: null,
+ },
+ "Customer Phone": {
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {
+ maximum: null,
+ },
+ presence: false,
+ },
+ name: "Customer Phone",
+ },
+ "Customer Email": {
+ type: FieldTypes.STRING,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {
+ maximum: null,
+ },
+ presence: false,
+ },
+ name: "Customer Email",
+ },
+ Assigned: {
+ name: "Assigned",
+ type: FieldTypes.LINK,
+ tableId: this.DEFAULT_EMPLOYEE_TABLE_ID,
+ fieldName: "Jobs",
+ relationshipType: RelationshipTypes.MANY_TO_MANY,
+ // sortable: true,
+ },
+ "Works End": {
+ type: "datetime",
+ constraints: {
+ type: "string",
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "Works End",
+ ignoreTimezones: true,
+ },
+ "Updated Price": {
+ type: "number",
+ constraints: {
+ type: "number",
+ presence: false,
+ numericality: {
+ greaterThanOrEqualTo: "",
+ lessThanOrEqualTo: "",
+ },
+ },
+ name: "Updated Price",
+ },
+ ...AUTO_COLUMNS,
+ },
+}
+
+exports.DEFAULT_EXPENSES_TABLE_SCHEMA = {
+ _id: this.DEFAULT_EXPENSES_TABLE_ID,
+ type: "internal",
+ views: {},
+ name: "Expenses",
+ sourceId: exports.DEFAULT_BB_DATASOURCE_ID,
+ primaryDisplay: "Expense ID",
+ schema: {
+ "Expense ID": {
+ name: "Expense ID",
+ type: FieldTypes.NUMBER,
+ subtype: AutoFieldSubTypes.AUTO_ID,
+ icon: "ri-magic-line",
+ autocolumn: true,
+ constraints: {
+ type: FieldTypes.NUMBER,
+ presence: false,
+ numericality: {
+ greaterThanOrEqualTo: "",
+ lessThanOrEqualTo: "",
+ },
+ },
+ },
+ "Expense Tags": {
+ type: FieldTypes.ARRAY,
+ constraints: {
+ type: FieldTypes.ARRAY,
+ presence: {
+ allowEmpty: false,
+ },
+ inclusion: [
+ "Fuel",
+ "Food",
+ "Materials",
+ "Repair",
+ "Equipment",
+ "Fees",
+ "Service",
+ "Office",
+ "Other",
+ ],
+ },
+ name: "Expense Tags",
+ sortable: false,
+ },
+ Cost: {
+ type: FieldTypes.NUMBER,
+ constraints: {
+ type: FieldTypes.NUMBER,
+ presence: {
+ allowEmpty: false,
+ },
+ numericality: {
+ greaterThanOrEqualTo: "",
+ lessThanOrEqualTo: "",
+ },
+ },
+ name: "Cost",
+ },
+ Notes: {
+ type: FieldTypes.LONGFORM,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ },
+ name: "Notes",
+ useRichText: null,
+ },
+ "Payment Due": {
+ type: FieldTypes.DATETIME,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "Payment Due",
+ ignoreTimezones: true,
+ },
+ "Date Paid": {
+ type: FieldTypes.DATETIME,
+ constraints: {
+ type: FieldTypes.STRING,
+ length: {},
+ presence: false,
+ datetime: {
+ latest: "",
+ earliest: "",
+ },
+ },
+ name: "Date Paid",
+ ignoreTimezones: true,
+ },
+ Attachment: {
+ type: FieldTypes.ATTACHMENT,
+ constraints: {
+ type: FieldTypes.ARRAY,
+ presence: false,
+ },
+ name: "Attachment",
+ sortable: false,
+ },
+ ...AUTO_COLUMNS,
+ },
+}
+
+exports.buildDefaultDocs = () => {
+ const inventoryData = tableImport(
+ this.DEFAULT_INVENTORY_TABLE_SCHEMA,
+ inventoryImport
+ )
+
+ const employeeData = tableImport(
+ this.DEFAULT_EMPLOYEE_TABLE_SCHEMA,
+ employeeImport
+ )
+
+ const jobData = tableImport(this.DEFAULT_JOBS_TABLE_SCHEMA, jobsImport)
+
+ const expensesData = tableImport(
+ this.DEFAULT_EXPENSES_TABLE_SCHEMA,
+ expensesImport
+ )
+
+ // Build one link doc for each employee/job
+ const jobEmployeeLinks = employeeData.rows.map((employee, index) => {
+ return new LinkDocument(
+ employeeData.table._id,
+ "Jobs",
+ employeeData.rows[index]._id,
+ jobData.table._id,
+ "Assigned",
+ jobData.rows[index]._id
+ )
+ })
+
+ return [
+ this.DEFAULT_BB_DATASOURCE,
+ inventoryData.table,
+ employeeData.table,
+ jobData.table,
+ expensesData.table,
+ ...inventoryData.rows,
+ ...employeeData.rows,
+ ...jobData.rows,
+ ...expensesData.rows,
+ ...jobEmployeeLinks,
+ ]
+}
diff --git a/packages/server/src/db/defaultData/employeeImport.js b/packages/server/src/db/defaultData/employeeImport.js
new file mode 100644
index 0000000000..eae43e182a
--- /dev/null
+++ b/packages/server/src/db/defaultData/employeeImport.js
@@ -0,0 +1,152 @@
+exports.employeeImport = [
+ {
+ "First Name": "Julie",
+ "Last Name": "Jimenez",
+ Email: "julie.jimenez@example.com",
+ Address: "4250 New Street",
+ City: "Stevenage",
+ Postcode: "EE32 3SE",
+ Phone: "01754 13523",
+ "Created At": "2022-11-10T17:56:18.353Z",
+ "Updated At": "2022-11-10T18:32:15.298Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Senior"],
+ "Start Date": "2015-02-12T12:00:00.000",
+ },
+ {
+ "First Name": "Mandy",
+ "Last Name": "Clark",
+ Email: "mandy.clark@example.com",
+ Address: "8632 North Street",
+ City: "Hereford",
+ Postcode: "GT81 7DG",
+ Phone: "016973 32814",
+ "Created At": "2022-11-10T17:56:18.353Z",
+ "Updated At": "2022-11-10T18:31:44.928Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Senior"],
+ "Start Date": "2017-09-10T12:00:00.000",
+ },
+ {
+ "First Name": "Holly",
+ "Last Name": "Carroll",
+ Email: "holly.carroll@example.com",
+ Address: "5976 Springfield Road",
+ City: "Edinburgh",
+ Postcode: "Y4 2LH",
+ Phone: "016977 73053",
+ "Created At": "2022-11-10T17:56:18.356Z",
+ "Updated At": "2022-11-10T18:31:32.086Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Senior"],
+ "Start Date": "2022-02-12T12:00:00.000",
+ },
+ {
+ "First Name": "Francis",
+ "Last Name": "Castro",
+ Email: "francis.castro@example.com",
+ Address: "3970 High Street",
+ City: "Wells",
+ Postcode: "X12 6QA",
+ Phone: "017684 23551",
+ "Created At": "2022-11-10T17:56:18.357Z",
+ "Updated At": "2022-11-10T18:31:16.976Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Apprentice"],
+ "Start Date": "2021-03-10T12:00:00.000",
+ },
+ {
+ "First Name": "Richard",
+ "Last Name": "Kelley",
+ Email: "richard.kelley@example.com",
+ Address: "2346 York Road",
+ City: "Leicester",
+ Postcode: "H7S 1AH",
+ Phone: "013873 65167",
+ "Created At": "2022-11-10T17:56:18.353Z",
+ "Updated At": "2022-11-10T18:32:23.314Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Apprentice"],
+ "Start Date": "2020-07-09T12:00:00.000",
+ },
+ {
+ "First Name": "Donald",
+ "Last Name": "Lynch",
+ Email: "donald.lynch@example.com",
+ Address: "9642 New Road",
+ City: "St Albans",
+ Postcode: "V9A 1NP",
+ Phone: "015242 46760",
+ "Created At": "2022-11-10T17:56:18.352Z",
+ "Updated At": "2022-11-10T18:30:38.439Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Junior"],
+ "Start Date": "2018-04-13T12:00:00.000",
+ },
+ {
+ "First Name": "Maria",
+ "Last Name": "Torres",
+ Email: "maria.torres@example.com",
+ Address: "9998 New Road",
+ City: "Aberdeen",
+ Postcode: "LP7 8JQ",
+ Phone: "0101 472 3365",
+ "Created At": "2022-11-10T17:56:18.353Z",
+ "Updated At": "2022-11-10T18:31:37.748Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Manager"],
+ "Start Date": "2016-05-22T12:00:00.000",
+ },
+ {
+ "First Name": "Suzy",
+ "Last Name": "Ruiz",
+ Email: "suzy.ruiz@example.com",
+ Address: "4641 Victoria Street",
+ City: "Armagh",
+ Postcode: "MO4X 8BP",
+ Phone: "015242 79977",
+ "Created At": "2022-11-10T17:56:18.354Z",
+ "Updated At": "2022-11-10T18:58:54.632Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Senior", "Manager"],
+ "Start Date": "2019-05-01T12:00:00.000",
+ },
+ {
+ "First Name": "Patrick",
+ "Last Name": "Garcia",
+ Email: "patrick.garcia@example.com",
+ Address: "7818 The Crescent",
+ City: "Bath",
+ Postcode: "OH5 3HE",
+ Phone: "017683 02608",
+ "Created At": "2022-11-10T17:56:18.353Z",
+ "Updated At": "2022-11-10T18:31:06.820Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Apprentice"],
+ "Start Date": "2014-08-30T12:00:00.000",
+ },
+ {
+ "First Name": "Brayden",
+ "Last Name": "Carpenter",
+ Email: "brayden.carpenter@example.com",
+ Address: "8755 The Drive",
+ City: "Bradford",
+ Postcode: "YH5 8RY",
+ Phone: "015395 12426",
+ "Created At": "2022-11-10T17:56:18.354Z",
+ "Updated At": "2022-11-10T20:41:26.977Z",
+ tableId: "ta_bb_employees",
+ type: "row",
+ "Employee Level": ["Contractor"],
+ "Start Date": "2022-11-09T12:00:00.000",
+ },
+]
diff --git a/packages/server/src/db/defaultData/expensesImport.js b/packages/server/src/db/defaultData/expensesImport.js
new file mode 100644
index 0000000000..2afa147321
--- /dev/null
+++ b/packages/server/src/db/defaultData/expensesImport.js
@@ -0,0 +1,114 @@
+exports.expensesImport = [
+ {
+ "Date Paid": "2022-11-12T12:00:00.000",
+ "Payment Due": "2022-11-01T12:00:00.000",
+ Cost: 117.4,
+ Notes: "Two vans needed a top up",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T19:07:14.714Z",
+ "Updated At": "2022-11-10T20:02:14.440Z",
+ type: "row",
+ "Expense Tags": ["Fuel", "Equipment"],
+ },
+ {
+ "Date Paid": "2022-11-11T12:00:00.000",
+ Cost: 217,
+ Notes: "3 branded work bags and safety equipment for the new hires",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T19:10:35.459Z",
+ "Updated At": "2022-11-10T19:10:35.459Z",
+ type: "row",
+ "Expense Tags": ["Materials"],
+ },
+ {
+ "Date Paid": "2022-11-25T12:00:00.000",
+ Cost: 420.68,
+ Notes: "Monthly games night",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T19:20:08.264Z",
+ "Updated At": "2022-11-10T19:27:14.141Z",
+ type: "row",
+ "Expense Tags": ["Food"],
+ },
+ {
+ "Date Paid": "2022-11-24T12:00:00.000",
+ "Payment Due": "2022-11-24T12:00:00.000",
+ Cost: 45,
+ Notes: "Work van",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T18:20:16.709Z",
+ "Updated At": "2022-11-10T20:02:05.293Z",
+ type: "row",
+ "Expense Tags": ["Fuel", "Equipment"],
+ },
+ {
+ "Payment Due": "2022-11-25T12:00:00.000",
+ Cost: 200,
+ Notes: "Accountant payroll management",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T19:06:16.014Z",
+ "Updated At": "2022-11-10T19:06:16.014Z",
+ type: "row",
+ "Expense Tags": ["Fees", "Service"],
+ },
+ {
+ "Payment Due": "2022-11-26T12:00:00.000",
+ Cost: 28,
+ Notes: "Circular saw needed a new plug",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T20:03:18.051Z",
+ "Updated At": "2022-11-10T20:03:18.051Z",
+ type: "row",
+ "Expense Tags": ["Equipment", "Repair"],
+ },
+ {
+ "Payment Due": "2022-11-11T12:00:00.000",
+ Cost: 131.75,
+ Notes: "Solicitor contract reviews for employees",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T18:56:16.111Z",
+ "Updated At": "2022-11-10T19:20:58.681Z",
+ type: "row",
+ "Expense Tags": ["Fees", "Service"],
+ },
+ {
+ Cost: 2500,
+ Notes: "New Laptop for the office. ",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T18:04:11.401Z",
+ "Updated At": "2022-11-10T20:08:16.459Z",
+ type: "row",
+ "Date Paid": "2022-11-09T12:00:00.000",
+ "Expense Tags": ["Equipment"],
+ },
+ {
+ "Date Paid": "2022-10-25T12:00:00.000",
+ Cost: 275,
+ Notes: "Accountant payroll. Added new hire",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T20:01:31.783Z",
+ "Updated At": "2022-11-10T20:01:31.783Z",
+ type: "row",
+ "Expense Tags": ["Fees", "Service"],
+ },
+ {
+ "Payment Due": "2022-11-19T12:00:00.000",
+ Cost: 250,
+ Notes: "200 new branded pens and 40 beanie hats. ",
+ Attachment: [],
+ tableId: "ta_bb_expenses",
+ "Created At": "2022-11-10T19:09:08.074Z",
+ "Updated At": "2022-11-10T19:09:08.074Z",
+ type: "row",
+ "Expense Tags": ["Service"],
+ },
+]
diff --git a/packages/server/src/db/defaultData/inventoryImport.js b/packages/server/src/db/defaultData/inventoryImport.js
new file mode 100644
index 0000000000..3d4cf98ee4
--- /dev/null
+++ b/packages/server/src/db/defaultData/inventoryImport.js
@@ -0,0 +1,106 @@
+exports.inventoryImport = [
+ {
+ Status: ["Available"],
+ "Item Name": "Little Blue Van",
+ SKU: "",
+ Notes: "MAX PAYLOAD 595 kg \nMAX LOAD LENGTH 1620 mm",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T19:11:40.141Z",
+ "Updated At": "2022-11-10T20:05:04.608Z",
+ type: "row",
+ "Purchase Date": "2022-10-10T12:00:00.000",
+ "Purchase Price": 39995,
+ "Item Tags": ["Vehicle"],
+ },
+ {
+ Status: ["Available"],
+ "Item Name": "Masonry Drill",
+ SKU: "ABC-123",
+ Notes: "Making a burning smell",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T18:46:10.820Z",
+ "Updated At": "2022-11-10T20:11:23.766Z",
+ type: "row",
+ "Purchase Date": "1992-11-19T12:00:00.000",
+ "Item Tags": ["Electrical", "Tools"],
+ "Purchase Price": 250,
+ },
+ {
+ Status: ["Repair"],
+ "Item Name": "Circular saw",
+ SKU: "AB2-100",
+ Notes: "",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T19:04:38.805Z",
+ "Updated At": "2022-11-10T20:20:24.000Z",
+ type: "row",
+ "Purchase Date": "2012-11-15T12:00:00.000",
+ "Item Tags": ["Electrical"],
+ "Purchase Price": 300,
+ },
+ {
+ "Item Tags": ["Electrical"],
+ "Purchase Price": 210,
+ "Purchase Date": "2022-10-17T12:00:00.000",
+ Status: ["Available"],
+ "Item Name": "Tablet Device (5g)",
+ SKU: "PH-001",
+ Notes: "Android tablet for use on site",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T20:21:56.332Z",
+ "Updated At": "2022-11-10T20:21:56.332Z",
+ type: "row",
+ },
+ {
+ "Item Tags": ["Tools", "Electrical"],
+ "Purchase Price": 200,
+ "Purchase Date": "2022-10-12T12:00:00.000",
+ Status: ["Available"],
+ "Item Name": "Power Screwdriver",
+ SKU: "TKIT-002-A",
+ Notes: "",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T20:10:51.129Z",
+ "Updated At": "2022-11-10T20:13:37.821Z",
+ type: "row",
+ },
+ {
+ Status: ["Available"],
+ "Item Name": "Large Blue Van",
+ SKU: "",
+ Notes: "MAX LOAD LENGTH 4256 mm",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T19:03:41.698Z",
+ "Updated At": "2022-11-10T20:04:57.932Z",
+ type: "row",
+ "Purchase Date": "2022-10-10T12:00:00.000",
+ "Purchase Price": 65995,
+ "Item Tags": ["Vehicle"],
+ },
+ {
+ "Purchase Price": 2500,
+ "Purchase Date": "2022-11-09T12:00:00.000",
+ Status: ["Available"],
+ "Item Name": "Office Laptop",
+ SKU: "PC-123-ABC",
+ Notes: "Office Laptop \n",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T20:06:14.463Z",
+ "Updated At": "2022-11-10T20:07:02.532Z",
+ type: "row",
+ "Item Tags": ["Electrical", "Office"],
+ },
+ {
+ Status: ["Available"],
+ "Item Name": "Little Red Van",
+ SKU: "",
+ Notes: "MAX PAYLOAD 595 kg \nMAX LOAD LENGTH 1620 mm",
+ tableId: "ta_bb_inventory",
+ "Created At": "2022-11-10T19:55:02.367Z",
+ "Updated At": "2022-11-10T20:05:13.504Z",
+ type: "row",
+ "Purchase Date": "2022-07-17T12:00:00.000",
+ "Purchase Price": 39995,
+ "Item Tags": ["Vehicle"],
+ },
+]
diff --git a/packages/server/src/db/defaultData/jobsImport.js b/packages/server/src/db/defaultData/jobsImport.js
new file mode 100644
index 0000000000..537cc2a006
--- /dev/null
+++ b/packages/server/src/db/defaultData/jobsImport.js
@@ -0,0 +1,158 @@
+exports.jobsImport = [
+ {
+ "Works End": "2023-01-28T12:00:00.000",
+ "Customer Email": "susie.peterson@example.com",
+ "Customer Phone": "016973 88386",
+ Notes:
+ "Bring the large van as recycling has been requested. \nAlso, they have a large dog.",
+ "Customer Name": "Susie Peterson",
+ Address: "5452 The Crescent\nBrighton and Hove\nAI7G 7BN",
+ "Works Start": "2023-01-26T12:00:00.000",
+ "Quote Price": 4200,
+ "Quote Date": "2022-11-11T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T18:00:29.510Z",
+ "Updated At": "2022-11-10T20:37:45.120Z",
+ type: "row",
+ },
+ {
+ "Updated Price": 307,
+ "Works End": "2022-11-19T12:00:00.000",
+ "Customer Email": "micheal.murphy@example.co",
+ "Customer Phone": "07344 867816",
+ Notes:
+ "Adding new utils and tearing down the dividing walls. Bring large blue van.\n\nThe customer can be difficult. Avoid",
+ "Customer Name": "Micheal Murphy",
+ Address: "5266 York Road\nOxford\nG2 8EP",
+ "Works Start": "2022-11-10T12:00:00.000",
+ "Quote Price": 1231,
+ "Quote Date": "2022-10-04T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T20:53:39.882Z",
+ "Updated At": "2022-11-10T20:59:49.435Z",
+ type: "row",
+ },
+ {
+ "Customer Email": "",
+ "Customer Phone": "07374 594595",
+ Notes:
+ "Removal and recycle requested of all units.\n\nStill awaiting feedback. If this is still around after next wednesday, just delete it.",
+ "Customer Name": "Charlotte Carpenter",
+ Address: "7780 Mill Lane\nGreater Manchester\nDU57 3GA",
+ "Quote Price": 500,
+ "Quote Date": "2022-11-08T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T21:03:11.782Z",
+ "Updated At": "2022-11-10T21:03:11.782Z",
+ type: "row",
+ },
+ {
+ "Updated Price": 2001,
+ "Works End": "2022-11-16T12:00:00.000",
+ "Customer Email": "leah.freeman@example.com",
+ "Customer Phone": "07844 42134",
+ Notes:
+ "Original quote too high. Material costs dropped.\nFull system installation.",
+ "Customer Name": "Leah Freeman",
+ Address: "4252 Fairview Road\nChester\nW62 7JH",
+ "Works Start": "2022-11-09T12:00:00.000",
+ "Quote Price": 3000,
+ "Quote Date": "2022-10-04T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T20:25:44.284Z",
+ "Updated At": "2022-11-10T20:54:21.655Z",
+ type: "row",
+ },
+ {
+ "Works End": "2022-11-13T12:00:00.000",
+ "Customer Email": "scarlett.gibson@example.co",
+ "Customer Phone": "07572 745859",
+ Notes:
+ "This address has a service dog.\n\nQuote didn't account for a sinkhole at the property. Amended",
+ "Customer Name": "Scarlett Gibson",
+ Address: "5624 The Drive\nArmagh\nNU0 5DW",
+ "Works Start": "2022-11-12T12:00:00.000",
+ "Quote Price": 120,
+ "Quote Date": "2022-11-11T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T19:50:55.215Z",
+ "Updated At": "2022-11-10T20:44:12.004Z",
+ type: "row",
+ "Updated Price": 175,
+ },
+ {
+ "Customer Email": "lester.rose@example.com",
+ "Customer Phone": "07103 009138",
+ Notes: "4 Radiators Removed\nMany cats in the house",
+ "Customer Name": "Lester Rose",
+ Address: "8543 Albert Road\nNewport\nLancashire\nUnited Kingdom\nS58 5YW",
+ "Quote Price": 3543,
+ "Quote Date": "2022-11-10T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T18:43:21.110Z",
+ "Updated At": "2022-11-10T20:40:48.241Z",
+ type: "row",
+ },
+ {
+ "Works End": "2022-11-24T12:00:00.000",
+ "Customer Email": "joel.owens@example.com",
+ "Customer Phone": "07216 548317",
+ Notes:
+ "Full retrofit of current installation. Will need big blue van. \n\nThere's a decent coffee place nearby. Ensure you buy enough for everyone.",
+ "Customer Name": "Joel Owens",
+ Address: "5516 Oaks Cross\nNewry\nT6V 9SL",
+ "Works Start": "2022-11-24T12:00:00.000",
+ "Quote Price": 789,
+ "Quote Date": "2022-11-10T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T21:07:28.365Z",
+ "Updated At": "2022-11-10T21:08:18.661Z",
+ type: "row",
+ },
+ {
+ "Customer Email": "freddie.franklin@example.com",
+ "Customer Phone": "016977 48298",
+ Notes:
+ "Equipment updates and some general maintenance.\n\nHouse has 3 walls.",
+ "Customer Name": "Freddie Franklin",
+ Address: "2035 Brick Kiln Road\nCoventry\nTS81 7AW",
+ "Quote Price": 302,
+ "Quote Date": "2022-11-10T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T18:33:57.850Z",
+ "Updated At": "2022-11-10T20:57:54.015Z",
+ type: "row",
+ },
+ {
+ "Works End": "2022-11-12T12:00:00.000",
+ "Customer Email": "diane.henry@example.com",
+ "Customer Phone": "07635 514491",
+ Notes: "Large van required, recycling requested. \nNew customer",
+ "Customer Name": "Diane Henry",
+ Address:
+ "3518 Station Road\nSunderland\nCounty Down\nUnited Kingdom\nXC67 8ES",
+ "Works Start": "2022-11-11T12:00:00.000",
+ "Quote Price": 2039,
+ "Quote Date": "2022-11-10T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T19:23:08.036Z",
+ "Updated At": "2022-11-10T20:45:40.523Z",
+ type: "row",
+ },
+ {
+ "Works End": "2022-09-23T12:00:00.000",
+ "Customer Email": "warren.alvarez@example.com",
+ "Customer Phone": "07768 90794",
+ Notes:
+ "System restoration and upgrades. \nCustomer is a smoker, bring cleaning equipment",
+ "Customer Name": "Warren Alvarez",
+ Address: "867 High Street\nBath\nKF8 6ZS",
+ "Works Start": "2022-09-23T12:00:00.000",
+ "Quote Price": 1412,
+ "Quote Date": "2022-09-20T12:00:00.000",
+ tableId: "ta_bb_jobs",
+ "Created At": "2022-11-10T20:57:00.124Z",
+ "Updated At": "2022-11-10T21:08:00.446Z",
+ type: "row",
+ },
+]
diff --git a/packages/server/src/db/linkedRows/LinkController.js b/packages/server/src/db/linkedRows/LinkController.js
index 32782df162..e7c338f709 100644
--- a/packages/server/src/db/linkedRows/LinkController.js
+++ b/packages/server/src/db/linkedRows/LinkController.js
@@ -1,55 +1,9 @@
const { IncludeDocs, getLinkDocuments } = require("./linkUtils")
-const {
- generateLinkID,
- InternalTables,
- getUserMetadataParams,
-} = require("../utils")
+const { InternalTables, getUserMetadataParams } = require("../utils")
const Sentry = require("@sentry/node")
const { FieldTypes, RelationshipTypes } = require("../../constants")
const { getAppDB } = require("@budibase/backend-core/context")
-
-/**
- * Creates a new link document structure which can be put to the database. It is important to
- * note that while this talks about linker/linked the link is bi-directional and for all intent
- * and purposes it does not matter from which direction the link was initiated.
- * @param {string} tableId1 The ID of the first table (the linker).
- * @param {string} tableId2 The ID of the second table (the linked).
- * @param {string} fieldName1 The name of the field in the linker table.
- * @param {string} fieldName2 The name of the field in the linked table.
- * @param {string} rowId1 The ID of the row which is acting as the linker.
- * @param {string} rowId2 The ID of the row which is acting as the linked.
- * @constructor
- */
-function LinkDocument(
- tableId1,
- fieldName1,
- rowId1,
- tableId2,
- fieldName2,
- rowId2
-) {
- // build the ID out of unique references to this link document
- this._id = generateLinkID(
- tableId1,
- tableId2,
- rowId1,
- rowId2,
- fieldName1,
- fieldName2
- )
- // required for referencing in view
- this.type = FieldTypes.LINK
- this.doc1 = {
- tableId: tableId1,
- fieldName: fieldName1,
- rowId: rowId1,
- }
- this.doc2 = {
- tableId: tableId2,
- fieldName: fieldName2,
- rowId: rowId2,
- }
-}
+const LinkDocument = require("./LinkDocument")
class LinkController {
constructor({ tableId, row, table, oldTable }) {
diff --git a/packages/server/src/db/linkedRows/LinkDocument.js b/packages/server/src/db/linkedRows/LinkDocument.js
new file mode 100644
index 0000000000..58aa630adc
--- /dev/null
+++ b/packages/server/src/db/linkedRows/LinkDocument.js
@@ -0,0 +1,47 @@
+const { generateLinkID } = require("../utils")
+const { FieldTypes } = require("../../constants")
+
+/**
+ * Creates a new link document structure which can be put to the database. It is important to
+ * note that while this talks about linker/linked the link is bi-directional and for all intent
+ * and purposes it does not matter from which direction the link was initiated.
+ * @param {string} tableId1 The ID of the first table (the linker).
+ * @param {string} tableId2 The ID of the second table (the linked).
+ * @param {string} fieldName1 The name of the field in the linker table.
+ * @param {string} fieldName2 The name of the field in the linked table.
+ * @param {string} rowId1 The ID of the row which is acting as the linker.
+ * @param {string} rowId2 The ID of the row which is acting as the linked.
+ * @constructor
+ */
+function LinkDocument(
+ tableId1,
+ fieldName1,
+ rowId1,
+ tableId2,
+ fieldName2,
+ rowId2
+) {
+ // build the ID out of unique references to this link document
+ this._id = generateLinkID(
+ tableId1,
+ tableId2,
+ rowId1,
+ rowId2,
+ fieldName1,
+ fieldName2
+ )
+ // required for referencing in view
+ this.type = FieldTypes.LINK
+ this.doc1 = {
+ tableId: tableId1,
+ fieldName: fieldName1,
+ rowId: rowId1,
+ }
+ this.doc2 = {
+ tableId: tableId2,
+ fieldName: fieldName2,
+ rowId: rowId2,
+ }
+}
+
+module.exports = LinkDocument
diff --git a/packages/server/src/db/utils.ts b/packages/server/src/db/utils.ts
index 58ea76c5ae..13bf6eb3b5 100644
--- a/packages/server/src/db/utils.ts
+++ b/packages/server/src/db/utils.ts
@@ -15,7 +15,7 @@ export const SearchIndexes = {
export const BudibaseInternalDB = {
_id: "bb_internal",
- type: "budibase",
+ type: dbCore.BUDIBASE_DATASOURCE_TYPE,
name: "Budibase DB",
source: "BUDIBASE",
config: {},
diff --git a/packages/server/src/sdk/app/tables/index.ts b/packages/server/src/sdk/app/tables/index.ts
index 15bf02cf62..98c7fc6a8b 100644
--- a/packages/server/src/sdk/app/tables/index.ts
+++ b/packages/server/src/sdk/app/tables/index.ts
@@ -19,7 +19,7 @@ async function getAllInternalTables(db?: Database): Promise
{
return internalTables.rows.map((tableDoc: any) => ({
...tableDoc.doc,
type: "internal",
- sourceId: BudibaseInternalDB._id,
+ sourceId: tableDoc.doc.sourceId || BudibaseInternalDB._id,
}))
}
diff --git a/packages/worker/src/api/routes/global/configs.js b/packages/worker/src/api/routes/global/configs.js
index bcbaa5caa2..fe8b1f97af 100644
--- a/packages/worker/src/api/routes/global/configs.js
+++ b/packages/worker/src/api/routes/global/configs.js
@@ -3,7 +3,7 @@ const controller = require("../../controllers/global/configs")
const { joiValidator } = require("@budibase/backend-core/auth")
const { adminOnly } = require("@budibase/backend-core/auth")
const Joi = require("joi")
-const { Config } = require("../../../constants")
+const { Config } = require("@budibase/backend-core/constants")
const router = new Router()