lint:fix
This commit is contained in:
parent
27ce375f17
commit
0afbf1649e
|
@ -1,9 +1,9 @@
|
||||||
let Pouch
|
let Pouch
|
||||||
|
|
||||||
module.exports.setDB = pouch => {
|
module.exports.setDB = (pouch) => {
|
||||||
Pouch = pouch
|
Pouch = pouch
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getDB = dbName => {
|
module.exports.getDB = (dbName) => {
|
||||||
return new Pouch(dbName)
|
return new Pouch(dbName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ exports.getGroupParams = (id = "", otherProps = {}) => {
|
||||||
* Generates a new global user ID.
|
* Generates a new global user ID.
|
||||||
* @returns {string} The new user ID which the user doc can be stored under.
|
* @returns {string} The new user ID which the user doc can be stored under.
|
||||||
*/
|
*/
|
||||||
exports.generateGlobalUserID = id => {
|
exports.generateGlobalUserID = (id) => {
|
||||||
return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}`
|
return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ exports.getGlobalUserParams = (globalId, otherProps = {}) => {
|
||||||
* Generates a template ID.
|
* Generates a template ID.
|
||||||
* @param ownerId The owner/user of the template, this could be global or a group level.
|
* @param ownerId The owner/user of the template, this could be global or a group level.
|
||||||
*/
|
*/
|
||||||
exports.generateTemplateID = ownerId => {
|
exports.generateTemplateID = (ownerId) => {
|
||||||
return `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${newid()}`
|
return `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${newid()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ const determineScopedConfig = async function(db, { type, user, group }) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const configs = response.rows.map(row => {
|
const configs = response.rows.map((row) => {
|
||||||
const config = row.doc
|
const config = row.doc
|
||||||
|
|
||||||
// Config is specific to a user and a group
|
// Config is specific to a user and a group
|
||||||
|
|
|
@ -4,7 +4,7 @@ const { v4 } = require("uuid")
|
||||||
|
|
||||||
const SALT_ROUNDS = env.SALT_ROUNDS || 10
|
const SALT_ROUNDS = env.SALT_ROUNDS || 10
|
||||||
|
|
||||||
exports.hash = async data => {
|
exports.hash = async (data) => {
|
||||||
const salt = await bcrypt.genSalt(SALT_ROUNDS)
|
const salt = await bcrypt.genSalt(SALT_ROUNDS)
|
||||||
return bcrypt.hash(data, salt)
|
return bcrypt.hash(data, salt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ function confirmAppId(possibleAppId) {
|
||||||
* @param {object} ctx The main request body to look through.
|
* @param {object} ctx The main request body to look through.
|
||||||
* @returns {string|undefined} If an appId was found it will be returned.
|
* @returns {string|undefined} If an appId was found it will be returned.
|
||||||
*/
|
*/
|
||||||
exports.getAppId = ctx => {
|
exports.getAppId = (ctx) => {
|
||||||
const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId]
|
const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId]
|
||||||
if (ctx.subdomains) {
|
if (ctx.subdomains) {
|
||||||
options.push(ctx.subdomains[1])
|
options.push(ctx.subdomains[1])
|
||||||
|
@ -41,7 +41,7 @@ exports.getAppId = ctx => {
|
||||||
}
|
}
|
||||||
let appPath =
|
let appPath =
|
||||||
ctx.request.headers.referrer ||
|
ctx.request.headers.referrer ||
|
||||||
ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX))
|
ctx.path.split("/").filter((subPath) => subPath.startsWith(APP_PREFIX))
|
||||||
if (!appId && appPath.length !== 0) {
|
if (!appId && appPath.length !== 0) {
|
||||||
appId = confirmAppId(appPath[0])
|
appId = confirmAppId(appPath[0])
|
||||||
}
|
}
|
||||||
|
@ -101,11 +101,11 @@ exports.clearCookie = (ctx, name) => {
|
||||||
* @param {object} ctx The koa context object to be tested.
|
* @param {object} ctx The koa context object to be tested.
|
||||||
* @return {boolean} returns true if the call is from the client lib (a built app rather than the builder).
|
* @return {boolean} returns true if the call is from the client lib (a built app rather than the builder).
|
||||||
*/
|
*/
|
||||||
exports.isClient = ctx => {
|
exports.isClient = (ctx) => {
|
||||||
return ctx.headers["x-budibase-type"] === "client"
|
return ctx.headers["x-budibase-type"] === "client"
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getGlobalUserByEmail = async email => {
|
exports.getGlobalUserByEmail = async (email) => {
|
||||||
const db = getDB(StaticDatabases.GLOBAL.name)
|
const db = getDB(StaticDatabases.GLOBAL.name)
|
||||||
try {
|
try {
|
||||||
let users = (
|
let users = (
|
||||||
|
@ -114,7 +114,7 @@ exports.getGlobalUserByEmail = async email => {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
).rows
|
).rows
|
||||||
users = users.map(user => user.doc)
|
users = users.map((user) => user.doc)
|
||||||
return users.length <= 1 ? users[0] : users
|
return users.length <= 1 ? users[0] : users
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err != null && err.name === "not_found") {
|
if (err != null && err.name === "not_found") {
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default function positionDropdown(element, { anchor, align }) {
|
||||||
element.style[positionSide] = `${dimensions[positionSide]}px`
|
element.style[positionSide] = `${dimensions[positionSide]}px`
|
||||||
element.style.left = `${calcLeftPosition(dimensions).toFixed(0)}px`
|
element.style.left = `${calcLeftPosition(dimensions).toFixed(0)}px`
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver(entries => {
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
entries.forEach(() => {
|
entries.forEach(() => {
|
||||||
dimensions = getDimensions()
|
dimensions = getDimensions()
|
||||||
element.style[positionSide] = `${dimensions[positionSide]}px`
|
element.style[positionSide] = `${dimensions[positionSide]}px`
|
||||||
|
|
|
@ -7,7 +7,7 @@ export const createNotificationStore = () => {
|
||||||
const _notifications = writable([], () => {
|
const _notifications = writable([], () => {
|
||||||
return () => {
|
return () => {
|
||||||
// clear all the timers
|
// clear all the timers
|
||||||
timeoutIds.forEach(timeoutId => {
|
timeoutIds.forEach((timeoutId) => {
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
})
|
})
|
||||||
_notifications.set([])
|
_notifications.set([])
|
||||||
|
@ -25,11 +25,11 @@ export const createNotificationStore = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let _id = id()
|
let _id = id()
|
||||||
_notifications.update(state => {
|
_notifications.update((state) => {
|
||||||
return [...state, { id: _id, type, message, icon }]
|
return [...state, { id: _id, type, message, icon }]
|
||||||
})
|
})
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
_notifications.update(state => {
|
_notifications.update((state) => {
|
||||||
return state.filter(({ id }) => id !== _id)
|
return state.filter(({ id }) => id !== _id)
|
||||||
})
|
})
|
||||||
}, NOTIFICATION_TIMEOUT)
|
}, NOTIFICATION_TIMEOUT)
|
||||||
|
@ -41,21 +41,16 @@ export const createNotificationStore = () => {
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
send,
|
send,
|
||||||
info: msg => send(msg, "info", "Info"),
|
info: (msg) => send(msg, "info", "Info"),
|
||||||
error: msg => send(msg, "error", "Alert"),
|
error: (msg) => send(msg, "error", "Alert"),
|
||||||
warning: msg => send(msg, "warning", "Alert"),
|
warning: (msg) => send(msg, "warning", "Alert"),
|
||||||
success: msg => send(msg, "success", "CheckmarkCircle"),
|
success: (msg) => send(msg, "success", "CheckmarkCircle"),
|
||||||
blockNotifications,
|
blockNotifications,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function id() {
|
function id() {
|
||||||
return (
|
return "_" + Math.random().toString(36).substr(2, 9)
|
||||||
"_" +
|
|
||||||
Math.random()
|
|
||||||
.toString(36)
|
|
||||||
.substr(2, 9)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const notifications = createNotificationStore()
|
export const notifications = createNotificationStore()
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
export const generateID = () => {
|
export const generateID = () => {
|
||||||
const rand = Math.random()
|
const rand = Math.random().toString(32).substring(2)
|
||||||
.toString(32)
|
|
||||||
.substring(2)
|
|
||||||
|
|
||||||
// Starts with a letter so that its a valid DOM ID
|
// Starts with a letter so that its a valid DOM ID
|
||||||
return `A${rand}`
|
return `A${rand}`
|
||||||
|
|
|
@ -6,15 +6,13 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
Cypress.Commands.add("login", () => {
|
Cypress.Commands.add("login", () => {
|
||||||
cy.getCookie("budibase:auth").then(cookie => {
|
cy.getCookie("budibase:auth").then((cookie) => {
|
||||||
// Already logged in
|
// Already logged in
|
||||||
if (cookie) return
|
if (cookie) return
|
||||||
|
|
||||||
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
||||||
cy.contains("Create Test User").click()
|
cy.contains("Create Test User").click()
|
||||||
cy.get("input")
|
cy.get("input").first().type("test@test.com")
|
||||||
.first()
|
|
||||||
.type("test@test.com")
|
|
||||||
|
|
||||||
cy.get('input[type="password"]').type("test")
|
cy.get('input[type="password"]').type("test")
|
||||||
|
|
||||||
|
@ -22,38 +20,26 @@ Cypress.Commands.add("login", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("createApp", name => {
|
Cypress.Commands.add("createApp", (name) => {
|
||||||
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
||||||
// wait for init API calls on visit
|
// wait for init API calls on visit
|
||||||
cy.wait(100)
|
cy.wait(100)
|
||||||
cy.contains("Create New Web App").click()
|
cy.contains("Create New Web App").click()
|
||||||
cy.get("body")
|
cy.get("body")
|
||||||
.then($body => {
|
.then(($body) => {
|
||||||
if ($body.find("input[name=apiKey]").length) {
|
if ($body.find("input[name=apiKey]").length) {
|
||||||
// input was found, do something else here
|
// input was found, do something else here
|
||||||
cy.get("input[name=apiKey]")
|
cy.get("input[name=apiKey]").type(name).should("have.value", name)
|
||||||
.type(name)
|
|
||||||
.should("have.value", name)
|
|
||||||
cy.contains("Next").click()
|
cy.contains("Next").click()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
cy.get(".spectrum-Modal")
|
cy.get(".spectrum-Modal")
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get("input")
|
cy.get("input").eq(0).type(name).should("have.value", name).blur()
|
||||||
.eq(0)
|
|
||||||
.type(name)
|
|
||||||
.should("have.value", name)
|
|
||||||
.blur()
|
|
||||||
cy.contains("Next").click()
|
cy.contains("Next").click()
|
||||||
cy.get("input")
|
cy.get("input").eq(1).type("test@test.com").blur()
|
||||||
.eq(1)
|
cy.get("input").eq(2).type("test").blur()
|
||||||
.type("test@test.com")
|
|
||||||
.blur()
|
|
||||||
cy.get("input")
|
|
||||||
.eq(2)
|
|
||||||
.type("test")
|
|
||||||
.blur()
|
|
||||||
cy.contains("Submit").click()
|
cy.contains("Submit").click()
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -64,20 +50,16 @@ Cypress.Commands.add("createApp", name => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("deleteApp", name => {
|
Cypress.Commands.add("deleteApp", (name) => {
|
||||||
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
|
||||||
cy.get(".apps").then($apps => {
|
cy.get(".apps").then(($apps) => {
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
if ($apps.find(`[data-cy="app-${name}"]`).length) {
|
if ($apps.find(`[data-cy="app-${name}"]`).length) {
|
||||||
cy.get(`[data-cy="app-${name}"]`)
|
cy.get(`[data-cy="app-${name}"]`).contains("Open").click()
|
||||||
.contains("Open")
|
|
||||||
.click()
|
|
||||||
cy.get("[data-cy=settings-icon]").click()
|
cy.get("[data-cy=settings-icon]").click()
|
||||||
cy.get(".spectrum-Dialog").within(() => {
|
cy.get(".spectrum-Dialog").within(() => {
|
||||||
cy.contains("Danger Zone").click()
|
cy.contains("Danger Zone").click()
|
||||||
cy.get("input")
|
cy.get("input").type("DELETE").blur()
|
||||||
.type("DELETE")
|
|
||||||
.blur()
|
|
||||||
cy.contains("Delete Entire App").click()
|
cy.contains("Delete Entire App").click()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -96,17 +78,12 @@ Cypress.Commands.add("createTestTableWithData", () => {
|
||||||
cy.addColumn("dog", "age", "Number")
|
cy.addColumn("dog", "age", "Number")
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("createTable", tableName => {
|
Cypress.Commands.add("createTable", (tableName) => {
|
||||||
// Enter table name
|
// Enter table name
|
||||||
cy.get("[data-cy=new-table]").click()
|
cy.get("[data-cy=new-table]").click()
|
||||||
cy.get(".spectrum-Modal").within(() => {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
cy.get("input")
|
cy.get("input").first().type(tableName).blur()
|
||||||
.first()
|
cy.get(".spectrum-ButtonGroup").contains("Create").click()
|
||||||
.type(tableName)
|
|
||||||
.blur()
|
|
||||||
cy.get(".spectrum-ButtonGroup")
|
|
||||||
.contains("Create")
|
|
||||||
.click()
|
|
||||||
})
|
})
|
||||||
cy.contains(tableName).should("be.visible")
|
cy.contains(tableName).should("be.visible")
|
||||||
})
|
})
|
||||||
|
@ -118,10 +95,7 @@ Cypress.Commands.add("addColumn", (tableName, columnName, type) => {
|
||||||
|
|
||||||
// Configure column
|
// Configure column
|
||||||
cy.get(".spectrum-Modal").within(() => {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
cy.get("input")
|
cy.get("input").first().type(columnName).blur()
|
||||||
.first()
|
|
||||||
.type(columnName)
|
|
||||||
.blur()
|
|
||||||
|
|
||||||
// Unset table display column
|
// Unset table display column
|
||||||
cy.contains("display column").click({ force: true })
|
cy.contains("display column").click({ force: true })
|
||||||
|
@ -130,18 +104,13 @@ Cypress.Commands.add("addColumn", (tableName, columnName, type) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("addRow", values => {
|
Cypress.Commands.add("addRow", (values) => {
|
||||||
cy.contains("Create row").click()
|
cy.contains("Create row").click()
|
||||||
cy.get(".spectrum-Modal").within(() => {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
for (let i = 0; i < values.length; i++) {
|
for (let i = 0; i < values.length; i++) {
|
||||||
cy.get("input")
|
cy.get("input").eq(i).type(values[i]).blur()
|
||||||
.eq(i)
|
|
||||||
.type(values[i])
|
|
||||||
.blur()
|
|
||||||
}
|
}
|
||||||
cy.get(".spectrum-ButtonGroup")
|
cy.get(".spectrum-ButtonGroup").contains("Create").click()
|
||||||
.contains("Create")
|
|
||||||
.click()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -150,22 +119,12 @@ Cypress.Commands.add("createUser", (email, password, role) => {
|
||||||
cy.contains("Users").click()
|
cy.contains("Users").click()
|
||||||
cy.contains("Create user").click()
|
cy.contains("Create user").click()
|
||||||
cy.get(".spectrum-Modal").within(() => {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
cy.get("input")
|
cy.get("input").first().type(email).blur()
|
||||||
.first()
|
cy.get("input").eq(1).type(password).blur()
|
||||||
.type(email)
|
cy.get("select").first().select(role)
|
||||||
.blur()
|
|
||||||
cy.get("input")
|
|
||||||
.eq(1)
|
|
||||||
.type(password)
|
|
||||||
.blur()
|
|
||||||
cy.get("select")
|
|
||||||
.first()
|
|
||||||
.select(role)
|
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
cy.get(".spectrum-ButtonGroup")
|
cy.get(".spectrum-ButtonGroup").contains("Create User").click()
|
||||||
.contains("Create User")
|
|
||||||
.click()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -175,7 +134,7 @@ Cypress.Commands.add("addComponent", (category, component) => {
|
||||||
}
|
}
|
||||||
cy.get(`[data-cy="component-${component}"]`).click()
|
cy.get(`[data-cy="component-${component}"]`).click()
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.location().then(loc => {
|
cy.location().then((loc) => {
|
||||||
const params = loc.pathname.split("/")
|
const params = loc.pathname.split("/")
|
||||||
const componentId = params[params.length - 1]
|
const componentId = params[params.length - 1]
|
||||||
cy.getComponent(componentId).should("exist")
|
cy.getComponent(componentId).should("exist")
|
||||||
|
@ -183,7 +142,7 @@ Cypress.Commands.add("addComponent", (category, component) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("getComponent", componentId => {
|
Cypress.Commands.add("getComponent", (componentId) => {
|
||||||
return cy
|
return cy
|
||||||
.get("iframe")
|
.get("iframe")
|
||||||
.its("0.contentDocument")
|
.its("0.contentDocument")
|
||||||
|
@ -201,15 +160,9 @@ Cypress.Commands.add("navigateToFrontend", () => {
|
||||||
Cypress.Commands.add("createScreen", (screenName, route) => {
|
Cypress.Commands.add("createScreen", (screenName, route) => {
|
||||||
cy.get("[data-cy=new-screen]").click()
|
cy.get("[data-cy=new-screen]").click()
|
||||||
cy.get(".spectrum-Modal").within(() => {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
cy.get("input")
|
cy.get("input").eq(0).type(screenName).blur()
|
||||||
.eq(0)
|
|
||||||
.type(screenName)
|
|
||||||
.blur()
|
|
||||||
if (route) {
|
if (route) {
|
||||||
cy.get("input")
|
cy.get("input").eq(1).type(route).blur()
|
||||||
.eq(1)
|
|
||||||
.type(route)
|
|
||||||
.blur()
|
|
||||||
}
|
}
|
||||||
cy.contains("Create Screen").click()
|
cy.contains("Create Screen").click()
|
||||||
})
|
})
|
||||||
|
|
|
@ -32,7 +32,7 @@ function identify(id) {
|
||||||
if (!analyticsEnabled || !id) return
|
if (!analyticsEnabled || !id) return
|
||||||
if (posthogConfigured) posthog.identify(id)
|
if (posthogConfigured) posthog.identify(id)
|
||||||
if (sentryConfigured)
|
if (sentryConfigured)
|
||||||
Sentry.configureScope(scope => {
|
Sentry.configureScope((scope) => {
|
||||||
scope.setUser({ id: id })
|
scope.setUser({ id: id })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ if (!localStorage.getItem(APP_FIRST_STARTED_KEY)) {
|
||||||
localStorage.setItem(APP_FIRST_STARTED_KEY, Date.now())
|
localStorage.setItem(APP_FIRST_STARTED_KEY, Date.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
const isFeedbackTimeElapsed = sinceDateStr => {
|
const isFeedbackTimeElapsed = (sinceDateStr) => {
|
||||||
const sinceDate = parseFloat(sinceDateStr)
|
const sinceDate = parseFloat(sinceDateStr)
|
||||||
const feedbackMilliseconds = feedbackHours * 60 * 60 * 1000
|
const feedbackMilliseconds = feedbackHours * 60 * 60 * 1000
|
||||||
return Date.now() > sinceDate + feedbackMilliseconds
|
return Date.now() > sinceDate + feedbackMilliseconds
|
||||||
|
@ -107,7 +107,7 @@ function highlightFeedbackIcon() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opt In/Out
|
// Opt In/Out
|
||||||
const ifAnalyticsEnabled = func => () => {
|
const ifAnalyticsEnabled = (func) => () => {
|
||||||
if (analyticsEnabled && process.env.POSTHOG_TOKEN) {
|
if (analyticsEnabled && process.env.POSTHOG_TOKEN) {
|
||||||
return func()
|
return func()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { store } from "./index"
|
||||||
import { get as svelteGet } from "svelte/store"
|
import { get as svelteGet } from "svelte/store"
|
||||||
import { removeCookie, Cookies } from "./cookies"
|
import { removeCookie, Cookies } from "./cookies"
|
||||||
|
|
||||||
const apiCall = method => async (
|
const apiCall = (method) => async (
|
||||||
url,
|
url,
|
||||||
body,
|
body,
|
||||||
headers = { "Content-Type": "application/json" }
|
headers = { "Content-Type": "application/json" }
|
||||||
|
|
|
@ -4,7 +4,7 @@ export const Cookies = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCookie(cookieName) {
|
export function getCookie(cookieName) {
|
||||||
return document.cookie.split(";").some(cookie => {
|
return document.cookie.split(";").some((cookie) => {
|
||||||
return cookie.trim().startsWith(`${cookieName}=`)
|
return cookie.trim().startsWith(`${cookieName}=`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const getDataProviderComponents = (asset, componentId) => {
|
||||||
path.pop()
|
path.pop()
|
||||||
|
|
||||||
// Filter by only data provider components
|
// Filter by only data provider components
|
||||||
return path.filter(component => {
|
return path.filter((component) => {
|
||||||
const def = store.actions.components.getDefinition(component._component)
|
const def = store.actions.components.getDefinition(component._component)
|
||||||
return def?.context != null
|
return def?.context != null
|
||||||
})
|
})
|
||||||
|
@ -54,7 +54,7 @@ export const getActionProviderComponents = (asset, componentId, actionType) => {
|
||||||
path.pop()
|
path.pop()
|
||||||
|
|
||||||
// Filter by only data provider components
|
// Filter by only data provider components
|
||||||
return path.filter(component => {
|
return path.filter((component) => {
|
||||||
const def = store.actions.components.getDefinition(component._component)
|
const def = store.actions.components.getDefinition(component._component)
|
||||||
return def?.actions?.includes(actionType)
|
return def?.actions?.includes(actionType)
|
||||||
})
|
})
|
||||||
|
@ -70,7 +70,7 @@ export const getDatasourceForProvider = (asset, component) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this component has a dataProvider setting, go up the stack and use it
|
// If this component has a dataProvider setting, go up the stack and use it
|
||||||
const dataProviderSetting = def.settings.find(setting => {
|
const dataProviderSetting = def.settings.find((setting) => {
|
||||||
return setting.type === "dataProvider"
|
return setting.type === "dataProvider"
|
||||||
})
|
})
|
||||||
if (dataProviderSetting) {
|
if (dataProviderSetting) {
|
||||||
|
@ -82,7 +82,7 @@ export const getDatasourceForProvider = (asset, component) => {
|
||||||
|
|
||||||
// Extract datasource from component instance
|
// Extract datasource from component instance
|
||||||
const validSettingTypes = ["dataSource", "table", "schema"]
|
const validSettingTypes = ["dataSource", "table", "schema"]
|
||||||
const datasourceSetting = def.settings.find(setting => {
|
const datasourceSetting = def.settings.find((setting) => {
|
||||||
return validSettingTypes.includes(setting.type)
|
return validSettingTypes.includes(setting.type)
|
||||||
})
|
})
|
||||||
if (!datasourceSetting) {
|
if (!datasourceSetting) {
|
||||||
|
@ -112,7 +112,7 @@ const getContextBindings = (asset, componentId) => {
|
||||||
let bindings = []
|
let bindings = []
|
||||||
|
|
||||||
// Create bindings for each data provider
|
// Create bindings for each data provider
|
||||||
dataProviders.forEach(component => {
|
dataProviders.forEach((component) => {
|
||||||
const def = store.actions.components.getDefinition(component._component)
|
const def = store.actions.components.getDefinition(component._component)
|
||||||
const contextDefinition = def.context
|
const contextDefinition = def.context
|
||||||
let schema
|
let schema
|
||||||
|
@ -127,7 +127,7 @@ const getContextBindings = (asset, componentId) => {
|
||||||
// Static contexts are fully defined by the components
|
// Static contexts are fully defined by the components
|
||||||
schema = {}
|
schema = {}
|
||||||
const values = contextDefinition.values || []
|
const values = contextDefinition.values || []
|
||||||
values.forEach(value => {
|
values.forEach((value) => {
|
||||||
schema[value.key] = { name: value.label, type: "string" }
|
schema[value.key] = { name: value.label, type: "string" }
|
||||||
})
|
})
|
||||||
} else if (contextDefinition.type === "schema") {
|
} else if (contextDefinition.type === "schema") {
|
||||||
|
@ -148,7 +148,7 @@ const getContextBindings = (asset, componentId) => {
|
||||||
|
|
||||||
// Create bindable properties for each schema field
|
// Create bindable properties for each schema field
|
||||||
const safeComponentId = makePropSafe(component._id)
|
const safeComponentId = makePropSafe(component._id)
|
||||||
keys.forEach(key => {
|
keys.forEach((key) => {
|
||||||
const fieldSchema = schema[key]
|
const fieldSchema = schema[key]
|
||||||
|
|
||||||
// Make safe runtime binding and replace certain bindings with a
|
// Make safe runtime binding and replace certain bindings with a
|
||||||
|
@ -197,7 +197,7 @@ const getUserBindings = () => {
|
||||||
})
|
})
|
||||||
const keys = Object.keys(schema).sort()
|
const keys = Object.keys(schema).sort()
|
||||||
const safeUser = makePropSafe("user")
|
const safeUser = makePropSafe("user")
|
||||||
keys.forEach(key => {
|
keys.forEach((key) => {
|
||||||
const fieldSchema = schema[key]
|
const fieldSchema = schema[key]
|
||||||
// Replace certain bindings with a new property to help display components
|
// Replace certain bindings with a new property to help display components
|
||||||
let runtimeBoundKey = key
|
let runtimeBoundKey = key
|
||||||
|
@ -224,17 +224,17 @@ const getUserBindings = () => {
|
||||||
/**
|
/**
|
||||||
* Gets all bindable properties from URL parameters.
|
* Gets all bindable properties from URL parameters.
|
||||||
*/
|
*/
|
||||||
const getUrlBindings = asset => {
|
const getUrlBindings = (asset) => {
|
||||||
const url = asset?.routing?.route ?? ""
|
const url = asset?.routing?.route ?? ""
|
||||||
const split = url.split("/")
|
const split = url.split("/")
|
||||||
let params = []
|
let params = []
|
||||||
split.forEach(part => {
|
split.forEach((part) => {
|
||||||
if (part.startsWith(":") && part.length > 1) {
|
if (part.startsWith(":") && part.length > 1) {
|
||||||
params.push(part.replace(/:/g, "").replace(/\?/g, ""))
|
params.push(part.replace(/:/g, "").replace(/\?/g, ""))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const safeURL = makePropSafe("url")
|
const safeURL = makePropSafe("url")
|
||||||
return params.map(param => ({
|
return params.map((param) => ({
|
||||||
type: "context",
|
type: "context",
|
||||||
runtimeBinding: `${safeURL}.${makePropSafe(param)}`,
|
runtimeBinding: `${safeURL}.${makePropSafe(param)}`,
|
||||||
readableBinding: `URL.${param}`,
|
readableBinding: `URL.${param}`,
|
||||||
|
@ -250,10 +250,10 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
|
||||||
const { type } = datasource
|
const { type } = datasource
|
||||||
if (type === "query") {
|
if (type === "query") {
|
||||||
const queries = get(queriesStores).list
|
const queries = get(queriesStores).list
|
||||||
table = queries.find(query => query._id === datasource._id)
|
table = queries.find((query) => query._id === datasource._id)
|
||||||
} else {
|
} else {
|
||||||
const tables = get(tablesStore).list
|
const tables = get(tablesStore).list
|
||||||
table = tables.find(table => table._id === datasource.tableId)
|
table = tables.find((table) => table._id === datasource.tableId)
|
||||||
}
|
}
|
||||||
if (table) {
|
if (table) {
|
||||||
if (type === "view") {
|
if (type === "view") {
|
||||||
|
@ -261,7 +261,7 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
|
||||||
} else if (type === "query" && isForm) {
|
} else if (type === "query" && isForm) {
|
||||||
schema = {}
|
schema = {}
|
||||||
const params = table.parameters || []
|
const params = table.parameters || []
|
||||||
params.forEach(param => {
|
params.forEach((param) => {
|
||||||
if (param?.name) {
|
if (param?.name) {
|
||||||
schema[param.name] = { ...param, type: "string" }
|
schema[param.name] = { ...param, type: "string" }
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,7 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
|
||||||
|
|
||||||
// Ensure there are "name" properties for all fields
|
// Ensure there are "name" properties for all fields
|
||||||
if (schema) {
|
if (schema) {
|
||||||
Object.keys(schema).forEach(field => {
|
Object.keys(schema).forEach((field) => {
|
||||||
if (!schema[field].name) {
|
if (!schema[field].name) {
|
||||||
schema[field].name = field
|
schema[field].name = field
|
||||||
}
|
}
|
||||||
|
@ -293,14 +293,14 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
|
||||||
* Builds a form schema given a form component.
|
* Builds a form schema given a form component.
|
||||||
* A form schema is a schema of all the fields nested anywhere within a form.
|
* A form schema is a schema of all the fields nested anywhere within a form.
|
||||||
*/
|
*/
|
||||||
const buildFormSchema = component => {
|
const buildFormSchema = (component) => {
|
||||||
let schema = {}
|
let schema = {}
|
||||||
if (!component) {
|
if (!component) {
|
||||||
return schema
|
return schema
|
||||||
}
|
}
|
||||||
const def = store.actions.components.getDefinition(component._component)
|
const def = store.actions.components.getDefinition(component._component)
|
||||||
const fieldSetting = def?.settings?.find(
|
const fieldSetting = def?.settings?.find(
|
||||||
setting => setting.key === "field" && setting.type.startsWith("field/")
|
(setting) => setting.key === "field" && setting.type.startsWith("field/")
|
||||||
)
|
)
|
||||||
if (fieldSetting && component.field) {
|
if (fieldSetting && component.field) {
|
||||||
const type = fieldSetting.type.split("field/")[1]
|
const type = fieldSetting.type.split("field/")[1]
|
||||||
|
@ -308,7 +308,7 @@ const buildFormSchema = component => {
|
||||||
schema[component.field] = { type }
|
schema[component.field] = { type }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component._children?.forEach(child => {
|
component._children?.forEach((child) => {
|
||||||
const childSchema = buildFormSchema(child)
|
const childSchema = buildFormSchema(child)
|
||||||
schema = { ...schema, ...childSchema }
|
schema = { ...schema, ...childSchema }
|
||||||
})
|
})
|
||||||
|
@ -339,7 +339,7 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) {
|
||||||
return textWithBindings
|
return textWithBindings
|
||||||
}
|
}
|
||||||
const convertFromProps = bindableProperties
|
const convertFromProps = bindableProperties
|
||||||
.map(el => el[convertFrom])
|
.map((el) => el[convertFrom])
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return b.length - a.length
|
return b.length - a.length
|
||||||
})
|
})
|
||||||
|
@ -349,7 +349,9 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) {
|
||||||
let newBoundValue = boundValue
|
let newBoundValue = boundValue
|
||||||
for (let from of convertFromProps) {
|
for (let from of convertFromProps) {
|
||||||
if (newBoundValue.includes(from)) {
|
if (newBoundValue.includes(from)) {
|
||||||
const binding = bindableProperties.find(el => el[convertFrom] === from)
|
const binding = bindableProperties.find(
|
||||||
|
(el) => el[convertFrom] === from
|
||||||
|
)
|
||||||
newBoundValue = newBoundValue.replace(from, binding[convertTo])
|
newBoundValue = newBoundValue.replace(from, binding[convertTo])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,16 @@ export const automationStore = getAutomationStore()
|
||||||
export const themeStore = getThemeStore()
|
export const themeStore = getThemeStore()
|
||||||
export const hostingStore = getHostingStore()
|
export const hostingStore = getHostingStore()
|
||||||
|
|
||||||
export const currentAsset = derived(store, $store => {
|
export const currentAsset = derived(store, ($store) => {
|
||||||
const type = $store.currentFrontEndType
|
const type = $store.currentFrontEndType
|
||||||
if (type === FrontendTypes.SCREEN) {
|
if (type === FrontendTypes.SCREEN) {
|
||||||
return $store.screens.find(screen => screen._id === $store.selectedScreenId)
|
return $store.screens.find(
|
||||||
|
(screen) => screen._id === $store.selectedScreenId
|
||||||
|
)
|
||||||
} else if (type === FrontendTypes.LAYOUT) {
|
} else if (type === FrontendTypes.LAYOUT) {
|
||||||
return $store.layouts.find(layout => layout._id === $store.selectedLayoutId)
|
return $store.layouts.find(
|
||||||
|
(layout) => layout._id === $store.selectedLayoutId
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
@ -32,24 +36,24 @@ export const selectedComponent = derived(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
export const currentAssetId = derived(store, $store => {
|
export const currentAssetId = derived(store, ($store) => {
|
||||||
return $store.currentFrontEndType === FrontendTypes.SCREEN
|
return $store.currentFrontEndType === FrontendTypes.SCREEN
|
||||||
? $store.selectedScreenId
|
? $store.selectedScreenId
|
||||||
: $store.selectedLayoutId
|
: $store.selectedLayoutId
|
||||||
})
|
})
|
||||||
|
|
||||||
export const currentAssetName = derived(currentAsset, $currentAsset => {
|
export const currentAssetName = derived(currentAsset, ($currentAsset) => {
|
||||||
return $currentAsset?.name
|
return $currentAsset?.name
|
||||||
})
|
})
|
||||||
|
|
||||||
// leave this as before for consistency
|
// leave this as before for consistency
|
||||||
export const allScreens = derived(store, $store => {
|
export const allScreens = derived(store, ($store) => {
|
||||||
return $store.screens
|
return $store.screens
|
||||||
})
|
})
|
||||||
|
|
||||||
export const mainLayout = derived(store, $store => {
|
export const mainLayout = derived(store, ($store) => {
|
||||||
return $store.layouts?.find(
|
return $store.layouts?.find(
|
||||||
layout => layout._id === LAYOUT_NAMES.MASTER.PRIVATE
|
(layout) => layout._id === LAYOUT_NAMES.MASTER.PRIVATE
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { get } from "builderStore/api"
|
||||||
* their props and other metadata from components.json.
|
* their props and other metadata from components.json.
|
||||||
* @param {string} appId - ID of the currently running app
|
* @param {string} appId - ID of the currently running app
|
||||||
*/
|
*/
|
||||||
export const fetchComponentLibDefinitions = async appId => {
|
export const fetchComponentLibDefinitions = async (appId) => {
|
||||||
const LIB_DEFINITION_URL = `/api/${appId}/components/definitions`
|
const LIB_DEFINITION_URL = `/api/${appId}/components/definitions`
|
||||||
try {
|
try {
|
||||||
const libDefinitionResponse = await get(LIB_DEFINITION_URL)
|
const libDefinitionResponse = await get(LIB_DEFINITION_URL)
|
||||||
|
|
|
@ -37,7 +37,7 @@ export default class Automation {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const stepIdx = steps.findIndex(step => step.id === id)
|
const stepIdx = steps.findIndex((step) => step.id === id)
|
||||||
if (stepIdx < 0) throw new Error("Block not found.")
|
if (stepIdx < 0) throw new Error("Block not found.")
|
||||||
steps.splice(stepIdx, 1, updatedBlock)
|
steps.splice(stepIdx, 1, updatedBlock)
|
||||||
this.automation.definition.steps = steps
|
this.automation.definition.steps = steps
|
||||||
|
@ -51,7 +51,7 @@ export default class Automation {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const stepIdx = steps.findIndex(step => step.id === id)
|
const stepIdx = steps.findIndex((step) => step.id === id)
|
||||||
if (stepIdx < 0) throw new Error("Block not found.")
|
if (stepIdx < 0) throw new Error("Block not found.")
|
||||||
steps.splice(stepIdx, 1)
|
steps.splice(stepIdx, 1)
|
||||||
this.automation.definition.steps = steps
|
this.automation.definition.steps = steps
|
||||||
|
|
|
@ -4,14 +4,14 @@ import Automation from "./Automation"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
|
||||||
const automationActions = store => ({
|
const automationActions = (store) => ({
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
const responses = await Promise.all([
|
const responses = await Promise.all([
|
||||||
api.get(`/api/automations`),
|
api.get(`/api/automations`),
|
||||||
api.get(`/api/automations/definitions/list`),
|
api.get(`/api/automations/definitions/list`),
|
||||||
])
|
])
|
||||||
const jsonResponses = await Promise.all(responses.map(x => x.json()))
|
const jsonResponses = await Promise.all(responses.map((x) => x.json()))
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
let selected = state.selectedAutomation?.automation
|
let selected = state.selectedAutomation?.automation
|
||||||
state.automations = jsonResponses[0]
|
state.automations = jsonResponses[0]
|
||||||
state.blockDefinitions = {
|
state.blockDefinitions = {
|
||||||
|
@ -22,7 +22,7 @@ const automationActions = store => ({
|
||||||
// if previously selected find the new obj and select it
|
// if previously selected find the new obj and select it
|
||||||
if (selected) {
|
if (selected) {
|
||||||
selected = jsonResponses[0].filter(
|
selected = jsonResponses[0].filter(
|
||||||
automation => automation._id === selected._id
|
(automation) => automation._id === selected._id
|
||||||
)
|
)
|
||||||
state.selectedAutomation = new Automation(selected[0])
|
state.selectedAutomation = new Automation(selected[0])
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ const automationActions = store => ({
|
||||||
const CREATE_AUTOMATION_URL = `/api/automations`
|
const CREATE_AUTOMATION_URL = `/api/automations`
|
||||||
const response = await api.post(CREATE_AUTOMATION_URL, automation)
|
const response = await api.post(CREATE_AUTOMATION_URL, automation)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.automations = [...state.automations, json.automation]
|
state.automations = [...state.automations, json.automation]
|
||||||
store.actions.select(json.automation)
|
store.actions.select(json.automation)
|
||||||
return state
|
return state
|
||||||
|
@ -50,9 +50,9 @@ const automationActions = store => ({
|
||||||
const UPDATE_AUTOMATION_URL = `/api/automations`
|
const UPDATE_AUTOMATION_URL = `/api/automations`
|
||||||
const response = await api.put(UPDATE_AUTOMATION_URL, automation)
|
const response = await api.put(UPDATE_AUTOMATION_URL, automation)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
const existingIdx = state.automations.findIndex(
|
const existingIdx = state.automations.findIndex(
|
||||||
existing => existing._id === automation._id
|
(existing) => existing._id === automation._id
|
||||||
)
|
)
|
||||||
state.automations.splice(existingIdx, 1, json.automation)
|
state.automations.splice(existingIdx, 1, json.automation)
|
||||||
state.automations = state.automations
|
state.automations = state.automations
|
||||||
|
@ -65,9 +65,9 @@ const automationActions = store => ({
|
||||||
const DELETE_AUTOMATION_URL = `/api/automations/${_id}/${_rev}`
|
const DELETE_AUTOMATION_URL = `/api/automations/${_id}/${_rev}`
|
||||||
await api.delete(DELETE_AUTOMATION_URL)
|
await api.delete(DELETE_AUTOMATION_URL)
|
||||||
|
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
const existingIdx = state.automations.findIndex(
|
const existingIdx = state.automations.findIndex(
|
||||||
existing => existing._id === _id
|
(existing) => existing._id === _id
|
||||||
)
|
)
|
||||||
state.automations.splice(existingIdx, 1)
|
state.automations.splice(existingIdx, 1)
|
||||||
state.automations = state.automations
|
state.automations = state.automations
|
||||||
|
@ -81,15 +81,15 @@ const automationActions = store => ({
|
||||||
const TRIGGER_AUTOMATION_URL = `/api/automations/${_id}/trigger`
|
const TRIGGER_AUTOMATION_URL = `/api/automations/${_id}/trigger`
|
||||||
return await api.post(TRIGGER_AUTOMATION_URL)
|
return await api.post(TRIGGER_AUTOMATION_URL)
|
||||||
},
|
},
|
||||||
select: automation => {
|
select: (automation) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.selectedAutomation = new Automation(cloneDeep(automation))
|
state.selectedAutomation = new Automation(cloneDeep(automation))
|
||||||
state.selectedBlock = null
|
state.selectedBlock = null
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
addBlockToAutomation: block => {
|
addBlockToAutomation: (block) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
const newBlock = state.selectedAutomation.addBlock(cloneDeep(block))
|
const newBlock = state.selectedAutomation.addBlock(cloneDeep(block))
|
||||||
state.selectedBlock = newBlock
|
state.selectedBlock = newBlock
|
||||||
return state
|
return state
|
||||||
|
@ -98,10 +98,10 @@ const automationActions = store => ({
|
||||||
name: block.name,
|
name: block.name,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteAutomationBlock: block => {
|
deleteAutomationBlock: (block) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
const idx = state.selectedAutomation.automation.definition.steps.findIndex(
|
const idx = state.selectedAutomation.automation.definition.steps.findIndex(
|
||||||
x => x.id === block.id
|
(x) => x.id === block.id
|
||||||
)
|
)
|
||||||
state.selectedAutomation.deleteBlock(block.id)
|
state.selectedAutomation.deleteBlock(block.id)
|
||||||
|
|
||||||
|
|
|
@ -49,10 +49,10 @@ export const getFrontendStore = () => {
|
||||||
const store = writable({ ...INITIAL_FRONTEND_STATE })
|
const store = writable({ ...INITIAL_FRONTEND_STATE })
|
||||||
|
|
||||||
store.actions = {
|
store.actions = {
|
||||||
initialise: async pkg => {
|
initialise: async (pkg) => {
|
||||||
const { layouts, screens, application, clientLibPath } = pkg
|
const { layouts, screens, application, clientLibPath } = pkg
|
||||||
const components = await fetchComponentLibDefinitions(application._id)
|
const components = await fetchComponentLibDefinitions(application._id)
|
||||||
store.update(state => ({
|
store.update((state) => ({
|
||||||
...state,
|
...state,
|
||||||
libraries: application.componentLibraries,
|
libraries: application.componentLibraries,
|
||||||
components,
|
components,
|
||||||
|
@ -70,7 +70,7 @@ export const getFrontendStore = () => {
|
||||||
|
|
||||||
// Initialise backend stores
|
// Initialise backend stores
|
||||||
const [_integrations] = await Promise.all([
|
const [_integrations] = await Promise.all([
|
||||||
api.get("/api/integrations").then(r => r.json()),
|
api.get("/api/integrations").then((r) => r.json()),
|
||||||
])
|
])
|
||||||
datasources.init()
|
datasources.init()
|
||||||
integrations.set(_integrations)
|
integrations.set(_integrations)
|
||||||
|
@ -82,18 +82,18 @@ export const getFrontendStore = () => {
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
const response = await api.get("/api/routing")
|
const response = await api.get("/api/routing")
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.routes = json.routes
|
state.routes = json.routes
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
screens: {
|
screens: {
|
||||||
select: screenId => {
|
select: (screenId) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
let screens = get(allScreens)
|
let screens = get(allScreens)
|
||||||
let screen =
|
let screen =
|
||||||
screens.find(screen => screen._id === screenId) || screens[0]
|
screens.find((screen) => screen._id === screenId) || screens[0]
|
||||||
if (!screen) return state
|
if (!screen) return state
|
||||||
|
|
||||||
// Update role to the screen's role setting so that it will always
|
// Update role to the screen's role setting so that it will always
|
||||||
|
@ -107,9 +107,9 @@ export const getFrontendStore = () => {
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
create: async screen => {
|
create: async (screen) => {
|
||||||
screen = await store.actions.screens.save(screen)
|
screen = await store.actions.screens.save(screen)
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.selectedScreenId = screen._id
|
state.selectedScreenId = screen._id
|
||||||
state.selectedComponentId = screen.props._id
|
state.selectedComponentId = screen.props._id
|
||||||
state.currentFrontEndType = FrontendTypes.SCREEN
|
state.currentFrontEndType = FrontendTypes.SCREEN
|
||||||
|
@ -118,15 +118,15 @@ export const getFrontendStore = () => {
|
||||||
})
|
})
|
||||||
return screen
|
return screen
|
||||||
},
|
},
|
||||||
save: async screen => {
|
save: async (screen) => {
|
||||||
const creatingNewScreen = screen._id === undefined
|
const creatingNewScreen = screen._id === undefined
|
||||||
const response = await api.post(`/api/screens`, screen)
|
const response = await api.post(`/api/screens`, screen)
|
||||||
screen = await response.json()
|
screen = await response.json()
|
||||||
await store.actions.routing.fetch()
|
await store.actions.routing.fetch()
|
||||||
|
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
const foundScreen = state.screens.findIndex(
|
const foundScreen = state.screens.findIndex(
|
||||||
el => el._id === screen._id
|
(el) => el._id === screen._id
|
||||||
)
|
)
|
||||||
if (foundScreen !== -1) {
|
if (foundScreen !== -1) {
|
||||||
state.screens.splice(foundScreen, 1)
|
state.screens.splice(foundScreen, 1)
|
||||||
|
@ -141,14 +141,14 @@ export const getFrontendStore = () => {
|
||||||
|
|
||||||
return screen
|
return screen
|
||||||
},
|
},
|
||||||
delete: async screens => {
|
delete: async (screens) => {
|
||||||
const screensToDelete = Array.isArray(screens) ? screens : [screens]
|
const screensToDelete = Array.isArray(screens) ? screens : [screens]
|
||||||
|
|
||||||
const screenDeletePromises = []
|
const screenDeletePromises = []
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
for (let screenToDelete of screensToDelete) {
|
for (let screenToDelete of screensToDelete) {
|
||||||
state.screens = state.screens.filter(
|
state.screens = state.screens.filter(
|
||||||
screen => screen._id !== screenToDelete._id
|
(screen) => screen._id !== screenToDelete._id
|
||||||
)
|
)
|
||||||
screenDeletePromises.push(
|
screenDeletePromises.push(
|
||||||
api.delete(
|
api.delete(
|
||||||
|
@ -177,8 +177,8 @@ export const getFrontendStore = () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
layouts: {
|
layouts: {
|
||||||
select: layoutId => {
|
select: (layoutId) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
const layout =
|
const layout =
|
||||||
store.actions.layouts.find(layoutId) || get(store).layouts[0]
|
store.actions.layouts.find(layoutId) || get(store).layouts[0]
|
||||||
if (!layout) return
|
if (!layout) return
|
||||||
|
@ -189,15 +189,15 @@ export const getFrontendStore = () => {
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
save: async layout => {
|
save: async (layout) => {
|
||||||
const layoutToSave = cloneDeep(layout)
|
const layoutToSave = cloneDeep(layout)
|
||||||
const creatingNewLayout = layoutToSave._id === undefined
|
const creatingNewLayout = layoutToSave._id === undefined
|
||||||
const response = await api.post(`/api/layouts`, layoutToSave)
|
const response = await api.post(`/api/layouts`, layoutToSave)
|
||||||
const savedLayout = await response.json()
|
const savedLayout = await response.json()
|
||||||
|
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
const layoutIdx = state.layouts.findIndex(
|
const layoutIdx = state.layouts.findIndex(
|
||||||
stateLayout => stateLayout._id === savedLayout._id
|
(stateLayout) => stateLayout._id === savedLayout._id
|
||||||
)
|
)
|
||||||
if (layoutIdx >= 0) {
|
if (layoutIdx >= 0) {
|
||||||
// update existing layout
|
// update existing layout
|
||||||
|
@ -216,14 +216,14 @@ export const getFrontendStore = () => {
|
||||||
|
|
||||||
return savedLayout
|
return savedLayout
|
||||||
},
|
},
|
||||||
find: layoutId => {
|
find: (layoutId) => {
|
||||||
if (!layoutId) {
|
if (!layoutId) {
|
||||||
return get(mainLayout)
|
return get(mainLayout)
|
||||||
}
|
}
|
||||||
const storeContents = get(store)
|
const storeContents = get(store)
|
||||||
return storeContents.layouts.find(layout => layout._id === layoutId)
|
return storeContents.layouts.find((layout) => layout._id === layoutId)
|
||||||
},
|
},
|
||||||
delete: async layoutToDelete => {
|
delete: async (layoutToDelete) => {
|
||||||
const response = await api.delete(
|
const response = await api.delete(
|
||||||
`/api/layouts/${layoutToDelete._id}/${layoutToDelete._rev}`
|
`/api/layouts/${layoutToDelete._id}/${layoutToDelete._rev}`
|
||||||
)
|
)
|
||||||
|
@ -231,9 +231,9 @@ export const getFrontendStore = () => {
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
throw new Error(json.message)
|
throw new Error(json.message)
|
||||||
}
|
}
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.layouts = state.layouts.filter(
|
state.layouts = state.layouts.filter(
|
||||||
layout => layout._id !== layoutToDelete._id
|
(layout) => layout._id !== layoutToDelete._id
|
||||||
)
|
)
|
||||||
if (layoutToDelete._id === state.selectedLayoutId) {
|
if (layoutToDelete._id === state.selectedLayoutId) {
|
||||||
state.selectedLayoutId = get(mainLayout)._id
|
state.selectedLayoutId = get(mainLayout)._id
|
||||||
|
@ -243,7 +243,7 @@ export const getFrontendStore = () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
select: component => {
|
select: (component) => {
|
||||||
if (!component) {
|
if (!component) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -263,13 +263,13 @@ export const getFrontendStore = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise select the component
|
// Otherwise select the component
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.selectedComponentId = component._id
|
state.selectedComponentId = component._id
|
||||||
state.currentView = "component"
|
state.currentView = "component"
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getDefinition: componentName => {
|
getDefinition: (componentName) => {
|
||||||
if (!componentName) {
|
if (!componentName) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ export const getFrontendStore = () => {
|
||||||
// Generate default props
|
// Generate default props
|
||||||
let props = { ...presetProps }
|
let props = { ...presetProps }
|
||||||
if (definition.settings) {
|
if (definition.settings) {
|
||||||
definition.settings.forEach(setting => {
|
definition.settings.forEach((setting) => {
|
||||||
if (setting.defaultValue !== undefined) {
|
if (setting.defaultValue !== undefined) {
|
||||||
props[setting.key] = setting.defaultValue
|
props[setting.key] = setting.defaultValue
|
||||||
}
|
}
|
||||||
|
@ -367,7 +367,7 @@ export const getFrontendStore = () => {
|
||||||
|
|
||||||
// Save components and update UI
|
// Save components and update UI
|
||||||
await store.actions.preview.saveSelected()
|
await store.actions.preview.saveSelected()
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.currentView = "component"
|
state.currentView = "component"
|
||||||
state.selectedComponentId = componentInstance._id
|
state.selectedComponentId = componentInstance._id
|
||||||
return state
|
return state
|
||||||
|
@ -380,7 +380,7 @@ export const getFrontendStore = () => {
|
||||||
|
|
||||||
return componentInstance
|
return componentInstance
|
||||||
},
|
},
|
||||||
delete: async component => {
|
delete: async (component) => {
|
||||||
if (!component) {
|
if (!component) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ export const getFrontendStore = () => {
|
||||||
const parent = findComponentParent(asset.props, component._id)
|
const parent = findComponentParent(asset.props, component._id)
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent._children = parent._children.filter(
|
parent._children = parent._children.filter(
|
||||||
child => child._id !== component._id
|
(child) => child._id !== component._id
|
||||||
)
|
)
|
||||||
store.actions.components.select(parent)
|
store.actions.components.select(parent)
|
||||||
}
|
}
|
||||||
|
@ -404,7 +404,7 @@ export const getFrontendStore = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update store with copied component
|
// Update store with copied component
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.componentToPaste = cloneDeep(component)
|
state.componentToPaste = cloneDeep(component)
|
||||||
state.componentToPaste.isCut = cut
|
state.componentToPaste.isCut = cut
|
||||||
return state
|
return state
|
||||||
|
@ -415,7 +415,7 @@ export const getFrontendStore = () => {
|
||||||
const parent = findComponentParent(selectedAsset.props, component._id)
|
const parent = findComponentParent(selectedAsset.props, component._id)
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent._children = parent._children.filter(
|
parent._children = parent._children.filter(
|
||||||
child => child._id !== component._id
|
(child) => child._id !== component._id
|
||||||
)
|
)
|
||||||
store.actions.components.select(parent)
|
store.actions.components.select(parent)
|
||||||
}
|
}
|
||||||
|
@ -423,7 +423,7 @@ export const getFrontendStore = () => {
|
||||||
},
|
},
|
||||||
paste: async (targetComponent, mode) => {
|
paste: async (targetComponent, mode) => {
|
||||||
let promises = []
|
let promises = []
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
// Stop if we have nothing to paste
|
// Stop if we have nothing to paste
|
||||||
if (!state.componentToPaste) {
|
if (!state.componentToPaste) {
|
||||||
return state
|
return state
|
||||||
|
@ -444,7 +444,7 @@ export const getFrontendStore = () => {
|
||||||
if (cut) {
|
if (cut) {
|
||||||
state.componentToPaste = null
|
state.componentToPaste = null
|
||||||
} else {
|
} else {
|
||||||
const randomizeIds = component => {
|
const randomizeIds = (component) => {
|
||||||
if (!component) {
|
if (!component) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,7 @@ export const getFrontendStore = () => {
|
||||||
}
|
}
|
||||||
await store.actions.preview.saveSelected()
|
await store.actions.preview.saveSelected()
|
||||||
},
|
},
|
||||||
updateCustomStyle: async style => {
|
updateCustomStyle: async (style) => {
|
||||||
const selected = get(selectedComponent)
|
const selected = get(selectedComponent)
|
||||||
selected._styles.custom = style
|
selected._styles.custom = style
|
||||||
await store.actions.preview.saveSelected()
|
await store.actions.preview.saveSelected()
|
||||||
|
@ -507,7 +507,7 @@ export const getFrontendStore = () => {
|
||||||
selected._styles = { normal: {}, hover: {}, active: {} }
|
selected._styles = { normal: {}, hover: {}, active: {} }
|
||||||
await store.actions.preview.saveSelected()
|
await store.actions.preview.saveSelected()
|
||||||
},
|
},
|
||||||
updateTransition: async transition => {
|
updateTransition: async (transition) => {
|
||||||
const selected = get(selectedComponent)
|
const selected = get(selectedComponent)
|
||||||
if (transition == null || transition === "") {
|
if (transition == null || transition === "") {
|
||||||
selected._transition = ""
|
selected._transition = ""
|
||||||
|
@ -522,7 +522,7 @@ export const getFrontendStore = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
component[name] = value
|
component[name] = value
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.selectedComponentId = component._id
|
state.selectedComponentId = component._id
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,18 +17,20 @@ export const getHostingStore = () => {
|
||||||
api.get("/api/hosting/"),
|
api.get("/api/hosting/"),
|
||||||
api.get("/api/hosting/urls"),
|
api.get("/api/hosting/urls"),
|
||||||
])
|
])
|
||||||
const [info, urls] = await Promise.all(responses.map(resp => resp.json()))
|
const [info, urls] = await Promise.all(
|
||||||
store.update(state => {
|
responses.map((resp) => resp.json())
|
||||||
|
)
|
||||||
|
store.update((state) => {
|
||||||
state.hostingInfo = info
|
state.hostingInfo = info
|
||||||
state.appUrl = urls.app
|
state.appUrl = urls.app
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
return info
|
return info
|
||||||
},
|
},
|
||||||
save: async hostingInfo => {
|
save: async (hostingInfo) => {
|
||||||
const response = await api.post("/api/hosting", hostingInfo)
|
const response = await api.post("/api/hosting", hostingInfo)
|
||||||
const revision = (await response.json()).rev
|
const revision = (await response.json()).rev
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.hostingInfo = {
|
state.hostingInfo = {
|
||||||
...hostingInfo,
|
...hostingInfo,
|
||||||
_rev: revision,
|
_rev: revision,
|
||||||
|
@ -38,10 +40,12 @@ export const getHostingStore = () => {
|
||||||
},
|
},
|
||||||
fetchDeployedApps: async () => {
|
fetchDeployedApps: async () => {
|
||||||
let deployments = await (await get("/api/hosting/apps")).json()
|
let deployments = await (await get("/api/hosting/apps")).json()
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.deployedApps = deployments
|
state.deployedApps = deployments
|
||||||
state.deployedAppNames = Object.values(deployments).map(app => app.name)
|
state.deployedAppNames = Object.values(deployments).map(
|
||||||
state.deployedAppUrls = Object.values(deployments).map(app => app.url)
|
(app) => app.name
|
||||||
|
)
|
||||||
|
state.deployedAppUrls = Object.values(deployments).map((app) => app.url)
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
return deployments
|
return deployments
|
||||||
|
|
|
@ -12,13 +12,13 @@ export const localStorageStore = (localStorageKey, initialValue) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// New store setter which updates the store and localstorage
|
// New store setter which updates the store and localstorage
|
||||||
const set = value => {
|
const set = (value) => {
|
||||||
store.set(value)
|
store.set(value)
|
||||||
localStorage.setItem(localStorageKey, JSON.stringify(value))
|
localStorage.setItem(localStorageKey, JSON.stringify(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// New store updater which updates the store and localstorage
|
// New store updater which updates the store and localstorage
|
||||||
const update = updaterFn => set(updaterFn(get(store)))
|
const update = (updaterFn) => set(updaterFn(get(store)))
|
||||||
|
|
||||||
// Hydrates the store from localstorage
|
// Hydrates the store from localstorage
|
||||||
const hydrate = () => {
|
const hydrate = () => {
|
||||||
|
|
|
@ -6,7 +6,7 @@ export const notificationStore = writable({
|
||||||
})
|
})
|
||||||
|
|
||||||
export function send(message, type = "default") {
|
export function send(message, type = "default") {
|
||||||
notificationStore.update(state => {
|
notificationStore.update((state) => {
|
||||||
state.notifications = [
|
state.notifications = [
|
||||||
...state.notifications,
|
...state.notifications,
|
||||||
{ id: generate(), type, message },
|
{ id: generate(), type, message },
|
||||||
|
@ -16,8 +16,8 @@ export function send(message, type = "default") {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const notifier = {
|
export const notifier = {
|
||||||
danger: msg => send(msg, "danger"),
|
danger: (msg) => send(msg, "danger"),
|
||||||
warning: msg => send(msg, "warning"),
|
warning: (msg) => send(msg, "warning"),
|
||||||
info: msg => send(msg, "info"),
|
info: (msg) => send(msg, "info"),
|
||||||
success: msg => send(msg, "success"),
|
success: (msg) => send(msg, "success"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import rowDetailScreen from "./rowDetailScreen"
|
||||||
import rowListScreen from "./rowListScreen"
|
import rowListScreen from "./rowListScreen"
|
||||||
import createFromScratchScreen from "./createFromScratchScreen"
|
import createFromScratchScreen from "./createFromScratchScreen"
|
||||||
|
|
||||||
const allTemplates = tables => [
|
const allTemplates = (tables) => [
|
||||||
...newRowScreen(tables),
|
...newRowScreen(tables),
|
||||||
...rowDetailScreen(tables),
|
...rowDetailScreen(tables),
|
||||||
...rowListScreen(tables),
|
...rowListScreen(tables),
|
||||||
|
@ -18,7 +18,7 @@ const createTemplateOverride = (frontendState, create) => () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (frontendState, tables) => {
|
export default (frontendState, tables) => {
|
||||||
const enrichTemplate = template => ({
|
const enrichTemplate = (template) => ({
|
||||||
...template,
|
...template,
|
||||||
create: createTemplateOverride(frontendState, template.create),
|
create: createTemplateOverride(frontendState, template.create),
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from "./utils/commonComponents"
|
} from "./utils/commonComponents"
|
||||||
|
|
||||||
export default function (tables) {
|
export default function (tables) {
|
||||||
return tables.map(table => {
|
return tables.map((table) => {
|
||||||
return {
|
return {
|
||||||
name: `${table.name} - New`,
|
name: `${table.name} - New`,
|
||||||
create: () => createScreen(table),
|
create: () => createScreen(table),
|
||||||
|
@ -19,14 +19,14 @@ export default function(tables) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const newRowUrl = table => sanitizeUrl(`/${table.name}/new/row`)
|
export const newRowUrl = (table) => sanitizeUrl(`/${table.name}/new/row`)
|
||||||
export const NEW_ROW_TEMPLATE = "NEW_ROW_TEMPLATE"
|
export const NEW_ROW_TEMPLATE = "NEW_ROW_TEMPLATE"
|
||||||
|
|
||||||
function generateTitleContainer(table, formId) {
|
function generateTitleContainer(table, formId) {
|
||||||
return makeTitleContainer("New Row").addChild(makeSaveButton(table, formId))
|
return makeTitleContainer("New Row").addChild(makeSaveButton(table, formId))
|
||||||
}
|
}
|
||||||
|
|
||||||
const createScreen = table => {
|
const createScreen = (table) => {
|
||||||
const screen = new Screen()
|
const screen = new Screen()
|
||||||
.component("@budibase/standard-components/container")
|
.component("@budibase/standard-components/container")
|
||||||
.instanceName(`${table.name} - New`)
|
.instanceName(`${table.name} - New`)
|
||||||
|
@ -52,7 +52,7 @@ const createScreen = table => {
|
||||||
|
|
||||||
// Add all form fields from this schema to the field group
|
// Add all form fields from this schema to the field group
|
||||||
const datasource = { type: "table", tableId: table._id }
|
const datasource = { type: "table", tableId: table._id }
|
||||||
makeDatasourceFormComponents(datasource).forEach(component => {
|
makeDatasourceFormComponents(datasource).forEach((component) => {
|
||||||
fieldGroup.addChild(component)
|
fieldGroup.addChild(component)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
} from "./utils/commonComponents"
|
} from "./utils/commonComponents"
|
||||||
|
|
||||||
export default function (tables) {
|
export default function (tables) {
|
||||||
return tables.map(table => {
|
return tables.map((table) => {
|
||||||
return {
|
return {
|
||||||
name: `${table.name} - Detail`,
|
name: `${table.name} - Detail`,
|
||||||
create: () => createScreen(table),
|
create: () => createScreen(table),
|
||||||
|
@ -23,7 +23,7 @@ export default function(tables) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ROW_DETAIL_TEMPLATE = "ROW_DETAIL_TEMPLATE"
|
export const ROW_DETAIL_TEMPLATE = "ROW_DETAIL_TEMPLATE"
|
||||||
export const rowDetailUrl = table => sanitizeUrl(`/${table.name}/:id`)
|
export const rowDetailUrl = (table) => sanitizeUrl(`/${table.name}/:id`)
|
||||||
|
|
||||||
function generateTitleContainer(table, title, formId, repeaterId) {
|
function generateTitleContainer(table, title, formId, repeaterId) {
|
||||||
// have to override style for this, its missing margin
|
// have to override style for this, its missing margin
|
||||||
|
@ -77,12 +77,10 @@ function generateTitleContainer(table, title, formId, repeaterId) {
|
||||||
})
|
})
|
||||||
.instanceName("Delete Button")
|
.instanceName("Delete Button")
|
||||||
|
|
||||||
return makeTitleContainer(title)
|
return makeTitleContainer(title).addChild(deleteButton).addChild(saveButton)
|
||||||
.addChild(deleteButton)
|
|
||||||
.addChild(saveButton)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const createScreen = table => {
|
const createScreen = (table) => {
|
||||||
const provider = new Component("@budibase/standard-components/dataprovider")
|
const provider = new Component("@budibase/standard-components/dataprovider")
|
||||||
.instanceName(`Data Provider`)
|
.instanceName(`Data Provider`)
|
||||||
.customProps({
|
.customProps({
|
||||||
|
@ -124,7 +122,7 @@ const createScreen = table => {
|
||||||
|
|
||||||
// Add all form fields from this schema to the field group
|
// Add all form fields from this schema to the field group
|
||||||
const datasource = { type: "table", tableId: table._id }
|
const datasource = { type: "table", tableId: table._id }
|
||||||
makeDatasourceFormComponents(datasource).forEach(component => {
|
makeDatasourceFormComponents(datasource).forEach((component) => {
|
||||||
fieldGroup.addChild(component)
|
fieldGroup.addChild(component)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Component } from "./utils/Component"
|
||||||
import { makePropSafe } from "@budibase/string-templates"
|
import { makePropSafe } from "@budibase/string-templates"
|
||||||
|
|
||||||
export default function (tables) {
|
export default function (tables) {
|
||||||
return tables.map(table => {
|
return tables.map((table) => {
|
||||||
return {
|
return {
|
||||||
name: `${table.name} - List`,
|
name: `${table.name} - List`,
|
||||||
create: () => createScreen(table),
|
create: () => createScreen(table),
|
||||||
|
@ -15,7 +15,7 @@ export default function(tables) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE"
|
export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE"
|
||||||
export const rowListUrl = table => sanitizeUrl(`/${table.name}`)
|
export const rowListUrl = (table) => sanitizeUrl(`/${table.name}`)
|
||||||
|
|
||||||
function generateTitleContainer(table) {
|
function generateTitleContainer(table) {
|
||||||
const newButton = new Component("@budibase/standard-components/button")
|
const newButton = new Component("@budibase/standard-components/button")
|
||||||
|
@ -70,7 +70,7 @@ function generateTitleContainer(table) {
|
||||||
.addChild(newButton)
|
.addChild(newButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createScreen = table => {
|
const createScreen = (table) => {
|
||||||
const provider = new Component("@budibase/standard-components/dataprovider")
|
const provider = new Component("@budibase/standard-components/dataprovider")
|
||||||
.instanceName(`Data Provider`)
|
.instanceName(`Data Provider`)
|
||||||
.customProps({
|
.customProps({
|
||||||
|
|
|
@ -178,7 +178,7 @@ export function makeDatasourceFormComponents(datasource) {
|
||||||
const { schema } = getSchemaForDatasource(datasource, true)
|
const { schema } = getSchemaForDatasource(datasource, true)
|
||||||
let components = []
|
let components = []
|
||||||
let fields = Object.keys(schema || {})
|
let fields = Object.keys(schema || {})
|
||||||
fields.forEach(field => {
|
fields.forEach((field) => {
|
||||||
const fieldSchema = schema[field]
|
const fieldSchema = schema[field]
|
||||||
// skip autocolumns
|
// skip autocolumns
|
||||||
if (fieldSchema.autocolumn) {
|
if (fieldSchema.autocolumn) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export default function (url) {
|
export default function (url) {
|
||||||
return url
|
return url
|
||||||
.split("/")
|
.split("/")
|
||||||
.map(part => {
|
.map((part) => {
|
||||||
// if parameter, then use as is
|
// if parameter, then use as is
|
||||||
if (part.startsWith(":")) return part
|
if (part.startsWith(":")) return part
|
||||||
return encodeURIComponent(part.replace(/ /g, "-"))
|
return encodeURIComponent(part.replace(/ /g, "-"))
|
||||||
|
|
|
@ -9,14 +9,14 @@ export const getThemeStore = () => {
|
||||||
const store = localStorageStore("bb-theme", initialValue)
|
const store = localStorageStore("bb-theme", initialValue)
|
||||||
|
|
||||||
// Update theme class when store changes
|
// Update theme class when store changes
|
||||||
store.subscribe(state => {
|
store.subscribe((state) => {
|
||||||
// Handle any old local storage values - this can be removed after the update
|
// Handle any old local storage values - this can be removed after the update
|
||||||
if (state.darkMode !== undefined) {
|
if (state.darkMode !== undefined) {
|
||||||
store.set(initialValue)
|
store.set(initialValue)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
state.options.forEach(option => {
|
state.options.forEach((option) => {
|
||||||
themeElement.classList.toggle(
|
themeElement.classList.toggle(
|
||||||
`spectrum--${option}`,
|
`spectrum--${option}`,
|
||||||
option === state.theme
|
option === state.theme
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
* Recursively searches for a specific component ID
|
* Recursively searches for a specific component ID
|
||||||
*/
|
*/
|
||||||
export const findComponent = (rootComponent, id) => {
|
export const findComponent = (rootComponent, id) => {
|
||||||
return searchComponentTree(rootComponent, comp => comp._id === id)
|
return searchComponentTree(rootComponent, (comp) => comp._id === id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively searches for a specific component type
|
* Recursively searches for a specific component type
|
||||||
*/
|
*/
|
||||||
export const findComponentType = (rootComponent, type) => {
|
export const findComponentType = (rootComponent, type) => {
|
||||||
return searchComponentTree(rootComponent, comp => comp._component === type)
|
return searchComponentTree(rootComponent, (comp) => comp._component === type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,7 @@ export const findAllMatchingComponents = (rootComponent, selector) => {
|
||||||
}
|
}
|
||||||
let components = []
|
let components = []
|
||||||
if (rootComponent._children) {
|
if (rootComponent._children) {
|
||||||
rootComponent._children.forEach(child => {
|
rootComponent._children.forEach((child) => {
|
||||||
components = [
|
components = [
|
||||||
...components,
|
...components,
|
||||||
...findAllMatchingComponents(child, selector),
|
...findAllMatchingComponents(child, selector),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export function uuid() {
|
export function uuid() {
|
||||||
// always want to make this start with a letter, as this makes it
|
// always want to make this start with a letter, as this makes it
|
||||||
// easier to use with template string bindings in the client
|
// easier to use with template string bindings in the client
|
||||||
return "cxxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, c => {
|
return "cxxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||||||
const r = (Math.random() * 16) | 0,
|
const r = (Math.random() * 16) | 0,
|
||||||
v = c == "x" ? r : (r & 0x3) | 0x8
|
v = c == "x" ? r : (r & 0x3) | 0x8
|
||||||
return v.toString(16)
|
return v.toString(16)
|
||||||
|
|
|
@ -17,8 +17,8 @@ export default function() {
|
||||||
const store = writable({})
|
const store = writable({})
|
||||||
|
|
||||||
store.actions = {
|
store.actions = {
|
||||||
dragstart: component => {
|
dragstart: (component) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.dragged = component
|
state.dragged = component
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
@ -29,7 +29,7 @@ export default function() {
|
||||||
canHaveChildrenButIsEmpty,
|
canHaveChildrenButIsEmpty,
|
||||||
mousePosition,
|
mousePosition,
|
||||||
}) => {
|
}) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.targetComponent = component
|
state.targetComponent = component
|
||||||
// only allow dropping inside when container is empty
|
// only allow dropping inside when container is empty
|
||||||
// if container has children, drag over them
|
// if container has children, drag over them
|
||||||
|
@ -65,7 +65,7 @@ export default function() {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
reset: () => {
|
reset: () => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.dropPosition = ""
|
state.dropPosition = ""
|
||||||
state.targetComponent = null
|
state.targetComponent = null
|
||||||
state.dragged = null
|
state.dragged = null
|
||||||
|
@ -85,7 +85,7 @@ export default function() {
|
||||||
}
|
}
|
||||||
// Stop if the target is a child of source
|
// Stop if the target is a child of source
|
||||||
const path = findComponentPath(state.dragged, state.targetComponent._id)
|
const path = findComponentPath(state.dragged, state.targetComponent._id)
|
||||||
const ids = path.map(component => component._id)
|
const ids = path.map((component) => component._id)
|
||||||
if (ids.includes(state.targetComponent._id)) {
|
if (ids.includes(state.targetComponent._id)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { getManifest } from "@budibase/string-templates"
|
||||||
export function handlebarsCompletions() {
|
export function handlebarsCompletions() {
|
||||||
const manifest = getManifest()
|
const manifest = getManifest()
|
||||||
|
|
||||||
return Object.keys(manifest).flatMap(key =>
|
return Object.keys(manifest).flatMap((key) =>
|
||||||
Object.entries(manifest[key]).map(([helperName, helperConfig]) => ({
|
Object.entries(manifest[key]).map(([helperName, helperConfig]) => ({
|
||||||
text: helperName,
|
text: helperName,
|
||||||
path: helperName,
|
path: helperName,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { last, flow } from "lodash/fp"
|
import { last, flow } from "lodash/fp"
|
||||||
|
|
||||||
export const buildStyle = styles => {
|
export const buildStyle = (styles) => {
|
||||||
let str = ""
|
let str = ""
|
||||||
for (let s in styles) {
|
for (let s in styles) {
|
||||||
if (styles[s]) {
|
if (styles[s]) {
|
||||||
|
@ -11,14 +11,15 @@ export const buildStyle = styles => {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
export const convertCamel = str => {
|
export const convertCamel = (str) => {
|
||||||
return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)
|
return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pipe = (arg, funcs) => flow(funcs)(arg)
|
export const pipe = (arg, funcs) => flow(funcs)(arg)
|
||||||
|
|
||||||
export const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
|
export const capitalise = (s) =>
|
||||||
|
s.substring(0, 1).toUpperCase() + s.substring(1)
|
||||||
|
|
||||||
export const get_name = s => (!s ? "" : last(s.split("/")))
|
export const get_name = (s) => (!s ? "" : last(s.split("/")))
|
||||||
|
|
||||||
export const get_capitalised_name = name => pipe(name, [get_name, capitalise])
|
export const get_capitalised_name = (name) => pipe(name, [get_name, capitalise])
|
||||||
|
|
|
@ -13,12 +13,12 @@ export function createAuthStore() {
|
||||||
const { subscribe, set } = writable(null)
|
const { subscribe, set } = writable(null)
|
||||||
|
|
||||||
checkAuth()
|
checkAuth()
|
||||||
.then(user => set({ user }))
|
.then((user) => set({ user }))
|
||||||
.catch(() => set({ user: null }))
|
.catch(() => set({ user: null }))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
login: async creds => {
|
login: async (creds) => {
|
||||||
const response = await api.post(`/api/admin/auth`, creds)
|
const response = await api.post(`/api/admin/auth`, creds)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
|
@ -36,7 +36,7 @@ export function createAuthStore() {
|
||||||
await response.json()
|
await response.json()
|
||||||
set({ user: null })
|
set({ user: null })
|
||||||
},
|
},
|
||||||
createUser: async user => {
|
createUser: async (user) => {
|
||||||
const response = await api.post(`/api/admin/users`, user)
|
const response = await api.post(`/api/admin/users`, user)
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
throw "Unable to create user"
|
throw "Unable to create user"
|
||||||
|
|
|
@ -21,19 +21,19 @@ export function createDatasourcesStore() {
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
const response = await api.get(`/api/datasources`)
|
const response = await api.get(`/api/datasources`)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
update(state => ({ ...state, list: json }))
|
update((state) => ({ ...state, list: json }))
|
||||||
return json
|
return json
|
||||||
},
|
},
|
||||||
select: async datasourceId => {
|
select: async (datasourceId) => {
|
||||||
update(state => ({ ...state, selected: datasourceId }))
|
update((state) => ({ ...state, selected: datasourceId }))
|
||||||
queries.update(state => ({ ...state, selected: null }))
|
queries.update((state) => ({ ...state, selected: null }))
|
||||||
},
|
},
|
||||||
save: async datasource => {
|
save: async (datasource) => {
|
||||||
const response = await api.post("/api/datasources", datasource)
|
const response = await api.post("/api/datasources", datasource)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
|
|
||||||
update(state => {
|
update((state) => {
|
||||||
const currentIdx = state.list.findIndex(ds => ds._id === json._id)
|
const currentIdx = state.list.findIndex((ds) => ds._id === json._id)
|
||||||
|
|
||||||
const sources = state.list
|
const sources = state.list
|
||||||
|
|
||||||
|
@ -47,13 +47,13 @@ export function createDatasourcesStore() {
|
||||||
})
|
})
|
||||||
return json
|
return json
|
||||||
},
|
},
|
||||||
delete: async datasource => {
|
delete: async (datasource) => {
|
||||||
const response = await api.delete(
|
const response = await api.delete(
|
||||||
`/api/datasources/${datasource._id}/${datasource._rev}`
|
`/api/datasources/${datasource._id}/${datasource._rev}`
|
||||||
)
|
)
|
||||||
update(state => {
|
update((state) => {
|
||||||
const sources = state.list.filter(
|
const sources = state.list.filter(
|
||||||
existing => existing._id !== datasource._id
|
(existing) => existing._id !== datasource._id
|
||||||
)
|
)
|
||||||
return { list: sources, selected: null }
|
return { list: sources, selected: null }
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,7 +6,7 @@ export function createPermissionStore() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
forResource: async resourceId => {
|
forResource: async (resourceId) => {
|
||||||
const response = await api.get(`/api/permission/${resourceId}`)
|
const response = await api.get(`/api/permission/${resourceId}`)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
return json
|
return json
|
||||||
|
|
|
@ -17,13 +17,13 @@ export function createQueriesStore() {
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
const response = await api.get(`/api/queries`)
|
const response = await api.get(`/api/queries`)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
update(state => ({ ...state, list: json }))
|
update((state) => ({ ...state, list: json }))
|
||||||
return json
|
return json
|
||||||
},
|
},
|
||||||
save: async (datasourceId, query) => {
|
save: async (datasourceId, query) => {
|
||||||
const _integrations = get(integrations)
|
const _integrations = get(integrations)
|
||||||
const dataSource = get(datasources).list.filter(
|
const dataSource = get(datasources).list.filter(
|
||||||
ds => ds._id === datasourceId
|
(ds) => ds._id === datasourceId
|
||||||
)
|
)
|
||||||
// check if readable attribute is found
|
// check if readable attribute is found
|
||||||
if (dataSource.length !== 0) {
|
if (dataSource.length !== 0) {
|
||||||
|
@ -39,8 +39,10 @@ export function createQueriesStore() {
|
||||||
throw new Error("Failed saving query.")
|
throw new Error("Failed saving query.")
|
||||||
}
|
}
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
update(state => {
|
update((state) => {
|
||||||
const currentIdx = state.list.findIndex(query => query._id === json._id)
|
const currentIdx = state.list.findIndex(
|
||||||
|
(query) => query._id === json._id
|
||||||
|
)
|
||||||
|
|
||||||
const queries = state.list
|
const queries = state.list
|
||||||
|
|
||||||
|
@ -53,16 +55,19 @@ export function createQueriesStore() {
|
||||||
})
|
})
|
||||||
return json
|
return json
|
||||||
},
|
},
|
||||||
select: query => {
|
select: (query) => {
|
||||||
update(state => ({ ...state, selected: query._id }))
|
update((state) => ({ ...state, selected: query._id }))
|
||||||
datasources.update(state => ({ ...state, selected: query.datasourceId }))
|
datasources.update((state) => ({
|
||||||
|
...state,
|
||||||
|
selected: query.datasourceId,
|
||||||
|
}))
|
||||||
},
|
},
|
||||||
delete: async query => {
|
delete: async (query) => {
|
||||||
const response = await api.delete(
|
const response = await api.delete(
|
||||||
`/api/queries/${query._id}/${query._rev}`
|
`/api/queries/${query._id}/${query._rev}`
|
||||||
)
|
)
|
||||||
update(state => {
|
update((state) => {
|
||||||
state.list = state.list.filter(existing => existing._id !== query._id)
|
state.list = state.list.filter((existing) => existing._id !== query._id)
|
||||||
if (state.selected === query._id) {
|
if (state.selected === query._id) {
|
||||||
state.selected = null
|
state.selected = null
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@ export function createRolesStore() {
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
set(await getRoles())
|
set(await getRoles())
|
||||||
},
|
},
|
||||||
delete: async role => {
|
delete: async (role) => {
|
||||||
const response = await api.delete(`/api/roles/${role._id}/${role._rev}`)
|
const response = await api.delete(`/api/roles/${role._id}/${role._rev}`)
|
||||||
update(state => state.filter(existing => existing._id !== role._id))
|
update((state) => state.filter((existing) => existing._id !== role._id))
|
||||||
return response
|
return response
|
||||||
},
|
},
|
||||||
save: async role => {
|
save: async (role) => {
|
||||||
const response = await api.post("/api/roles", role)
|
const response = await api.post("/api/roles", role)
|
||||||
set(await getRoles())
|
set(await getRoles())
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -10,17 +10,17 @@ export function createTablesStore() {
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
const tablesResponse = await api.get(`/api/tables`)
|
const tablesResponse = await api.get(`/api/tables`)
|
||||||
const tables = await tablesResponse.json()
|
const tables = await tablesResponse.json()
|
||||||
update(state => ({ ...state, list: tables }))
|
update((state) => ({ ...state, list: tables }))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function select(table) {
|
async function select(table) {
|
||||||
if (!table) {
|
if (!table) {
|
||||||
update(state => ({
|
update((state) => ({
|
||||||
...state,
|
...state,
|
||||||
selected: {},
|
selected: {},
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
update(state => ({
|
update((state) => ({
|
||||||
...state,
|
...state,
|
||||||
selected: table,
|
selected: table,
|
||||||
draft: cloneDeep(table),
|
draft: cloneDeep(table),
|
||||||
|
@ -31,7 +31,7 @@ export function createTablesStore() {
|
||||||
|
|
||||||
async function save(table) {
|
async function save(table) {
|
||||||
const updatedTable = cloneDeep(table)
|
const updatedTable = cloneDeep(table)
|
||||||
const oldTable = get(store).list.filter(t => t._id === table._id)[0]
|
const oldTable = get(store).list.filter((t) => t._id === table._id)[0]
|
||||||
|
|
||||||
const fieldNames = []
|
const fieldNames = []
|
||||||
// update any renamed schema keys to reflect their names
|
// update any renamed schema keys to reflect their names
|
||||||
|
@ -78,16 +78,16 @@ export function createTablesStore() {
|
||||||
draft: {},
|
draft: {},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
delete: async table => {
|
delete: async (table) => {
|
||||||
await api.delete(`/api/tables/${table._id}/${table._rev}`)
|
await api.delete(`/api/tables/${table._id}/${table._rev}`)
|
||||||
update(state => ({
|
update((state) => ({
|
||||||
...state,
|
...state,
|
||||||
list: state.list.filter(existing => existing._id !== table._id),
|
list: state.list.filter((existing) => existing._id !== table._id),
|
||||||
selected: {},
|
selected: {},
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
saveField: ({ originalName, field, primaryDisplay = false, indexes }) => {
|
saveField: ({ originalName, field, primaryDisplay = false, indexes }) => {
|
||||||
update(state => {
|
update((state) => {
|
||||||
// delete the original if renaming
|
// delete the original if renaming
|
||||||
// need to handle if the column had no name, empty string
|
// need to handle if the column had no name, empty string
|
||||||
if (originalName || originalName === "") {
|
if (originalName || originalName === "") {
|
||||||
|
@ -115,8 +115,8 @@ export function createTablesStore() {
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteField: field => {
|
deleteField: (field) => {
|
||||||
update(state => {
|
update((state) => {
|
||||||
delete state.draft.schema[field.name]
|
delete state.draft.schema[field.name]
|
||||||
save(state.draft)
|
save(state.draft)
|
||||||
return state
|
return state
|
||||||
|
|
|
@ -10,17 +10,17 @@ export function createViewsStore() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
select: async view => {
|
select: async (view) => {
|
||||||
update(state => ({
|
update((state) => ({
|
||||||
...state,
|
...state,
|
||||||
selected: view,
|
selected: view,
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
delete: async view => {
|
delete: async (view) => {
|
||||||
await api.delete(`/api/views/${view}`)
|
await api.delete(`/api/views/${view}`)
|
||||||
await tables.fetch()
|
await tables.fetch()
|
||||||
},
|
},
|
||||||
save: async view => {
|
save: async (view) => {
|
||||||
const response = await api.post(`/api/views`, view)
|
const response = await api.post(`/api/views`, view)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
|
|
||||||
|
@ -30,14 +30,14 @@ export function createViewsStore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewTable = get(tables).list.find(
|
const viewTable = get(tables).list.find(
|
||||||
table => table._id === view.tableId
|
(table) => table._id === view.tableId
|
||||||
)
|
)
|
||||||
|
|
||||||
if (view.originalName) delete viewTable.views[view.originalName]
|
if (view.originalName) delete viewTable.views[view.originalName]
|
||||||
viewTable.views[view.name] = viewMeta
|
viewTable.views[view.name] = viewMeta
|
||||||
await tables.save(viewTable)
|
await tables.save(viewTable)
|
||||||
|
|
||||||
update(state => ({ ...state, selected: viewMeta }))
|
update((state) => ({ ...state, selected: viewMeta }))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ module.exports.make = async (inputs = {}) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.get = property => {
|
module.exports.get = (property) => {
|
||||||
const props = fs.readFileSync(FILE_PATH, "utf8").split(property)
|
const props = fs.readFileSync(FILE_PATH, "utf8").split(property)
|
||||||
if (props[0].charAt(0) === "=") {
|
if (props[0].charAt(0) === "=") {
|
||||||
property = props[0]
|
property = props[0]
|
||||||
|
|
|
@ -17,6 +17,6 @@ async function init() {
|
||||||
await program.parseAsync(process.argv)
|
await program.parseAsync(process.argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
init().catch(err => {
|
init().catch((err) => {
|
||||||
console.error(`Unexpected error - `, err)
|
console.error(`Unexpected error - `, err)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const inquirer = require("inquirer")
|
const inquirer = require("inquirer")
|
||||||
|
|
||||||
exports.confirmation = async question => {
|
exports.confirmation = async (question) => {
|
||||||
const config = {
|
const config = {
|
||||||
type: "confirm",
|
type: "confirm",
|
||||||
message: question,
|
message: question,
|
||||||
|
@ -27,7 +27,7 @@ exports.number = async (question, defaultNumber) => {
|
||||||
type: "input",
|
type: "input",
|
||||||
name: "number",
|
name: "number",
|
||||||
message: question,
|
message: question,
|
||||||
validate: value => {
|
validate: (value) => {
|
||||||
let valid = !isNaN(parseFloat(value))
|
let valid = !isNaN(parseFloat(value))
|
||||||
return valid || "Please enter a number"
|
return valid || "Please enter a number"
|
||||||
},
|
},
|
||||||
|
|
|
@ -34,7 +34,7 @@ class Command {
|
||||||
"--help",
|
"--help",
|
||||||
getSubHelpDescription(`Get help with ${this.command} options`)
|
getSubHelpDescription(`Get help with ${this.command} options`)
|
||||||
)
|
)
|
||||||
command.action(async options => {
|
command.action(async (options) => {
|
||||||
try {
|
try {
|
||||||
let executed = false
|
let executed = false
|
||||||
for (let opt of thisCmd.opts) {
|
for (let opt of thisCmd.opts) {
|
||||||
|
|
|
@ -21,23 +21,23 @@ exports.downloadFile = async (url, filePath) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getHelpDescription = string => {
|
exports.getHelpDescription = (string) => {
|
||||||
return chalk.cyan(string)
|
return chalk.cyan(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getSubHelpDescription = string => {
|
exports.getSubHelpDescription = (string) => {
|
||||||
return chalk.green(string)
|
return chalk.green(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.error = error => {
|
exports.error = (error) => {
|
||||||
return chalk.red(`Error - ${error}`)
|
return chalk.red(`Error - ${error}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.success = success => {
|
exports.success = (success) => {
|
||||||
return chalk.green(success)
|
return chalk.green(success)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.info = info => {
|
exports.info = (info) => {
|
||||||
return chalk.cyan(info)
|
return chalk.cyan(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ exports.logErrorToFile = (file, error) => {
|
||||||
fs.writeFileSync(path.resolve(`./${file}`), `Budibase Error\n${error}`)
|
fs.writeFileSync(path.resolve(`./${file}`), `Budibase Error\n${error}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.parseEnv = env => {
|
exports.parseEnv = (env) => {
|
||||||
const lines = env.toString().split("\n")
|
const lines = env.toString().split("\n")
|
||||||
let result = {}
|
let result = {}
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ let cache = {}
|
||||||
/**
|
/**
|
||||||
* Handler for API errors.
|
* Handler for API errors.
|
||||||
*/
|
*/
|
||||||
const handleError = error => {
|
const handleError = (error) => {
|
||||||
return { error }
|
return { error }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ const makeApiCall = async ({ method, url, body, json = true }) => {
|
||||||
* Future invocation for this URL will return the cached result instead of
|
* Future invocation for this URL will return the cached result instead of
|
||||||
* hitting the server again.
|
* hitting the server again.
|
||||||
*/
|
*/
|
||||||
const makeCachedApiCall = async params => {
|
const makeCachedApiCall = async (params) => {
|
||||||
const identifier = params.url
|
const identifier = params.url
|
||||||
if (!identifier) {
|
if (!identifier) {
|
||||||
return null
|
return null
|
||||||
|
@ -76,7 +76,7 @@ const makeCachedApiCall = async params => {
|
||||||
/**
|
/**
|
||||||
* Constructs an API call function for a particular HTTP method.
|
* Constructs an API call function for a particular HTTP method.
|
||||||
*/
|
*/
|
||||||
const requestApiCall = method => async params => {
|
const requestApiCall = (method) => async (params) => {
|
||||||
const { url, cache = false } = params
|
const { url, cache = false } = params
|
||||||
const fixedUrl = `/${url}`.replace("//", "/")
|
const fixedUrl = `/${url}`.replace("//", "/")
|
||||||
const enrichedParams = { ...params, method, url: fixedUrl }
|
const enrichedParams = { ...params, method, url: fixedUrl }
|
||||||
|
|
|
@ -3,7 +3,7 @@ import API from "./api"
|
||||||
/**
|
/**
|
||||||
* Fetches screen definition for an app.
|
* Fetches screen definition for an app.
|
||||||
*/
|
*/
|
||||||
export const fetchAppDefinition = async appId => {
|
export const fetchAppDefinition = async (appId) => {
|
||||||
return await API.get({
|
return await API.get({
|
||||||
url: `/api/applications/${appId}/definition`,
|
url: `/api/applications/${appId}/definition`,
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,7 +3,7 @@ import API from "./api"
|
||||||
/**
|
/**
|
||||||
* Uploads an attachment to the server.
|
* Uploads an attachment to the server.
|
||||||
*/
|
*/
|
||||||
export const uploadAttachment = async data => {
|
export const uploadAttachment = async (data) => {
|
||||||
return await API.post({
|
return await API.post({
|
||||||
url: "/api/attachments/upload",
|
url: "/api/attachments/upload",
|
||||||
body: data,
|
body: data,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { executeQuery } from "./queries"
|
||||||
/**
|
/**
|
||||||
* Fetches all rows for a particular Budibase data source.
|
* Fetches all rows for a particular Budibase data source.
|
||||||
*/
|
*/
|
||||||
export const fetchDatasource = async dataSource => {
|
export const fetchDatasource = async (dataSource) => {
|
||||||
if (!dataSource || !dataSource.type) {
|
if (!dataSource || !dataSource.type) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ export const fetchRow = async ({ tableId, rowId }) => {
|
||||||
/**
|
/**
|
||||||
* Creates a row in a table.
|
* Creates a row in a table.
|
||||||
*/
|
*/
|
||||||
export const saveRow = async row => {
|
export const saveRow = async (row) => {
|
||||||
if (!row?.tableId) {
|
if (!row?.tableId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ export const saveRow = async row => {
|
||||||
/**
|
/**
|
||||||
* Updates a row in a table.
|
* Updates a row in a table.
|
||||||
*/
|
*/
|
||||||
export const updateRow = async row => {
|
export const updateRow = async (row) => {
|
||||||
if (!row?.tableId || !row?._id) {
|
if (!row?.tableId || !row?._id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -115,15 +115,15 @@ export const enrichRows = async (rows, tableId) => {
|
||||||
const schema = tableDefinition && tableDefinition.schema
|
const schema = tableDefinition && tableDefinition.schema
|
||||||
if (schema) {
|
if (schema) {
|
||||||
const keys = Object.keys(schema)
|
const keys = Object.keys(schema)
|
||||||
rows.forEach(row => {
|
rows.forEach((row) => {
|
||||||
for (let key of keys) {
|
for (let key of keys) {
|
||||||
const type = schema[key].type
|
const type = schema[key].type
|
||||||
if (type === "link") {
|
if (type === "link") {
|
||||||
// Enrich row a string join of relationship fields
|
// Enrich row a string join of relationship fields
|
||||||
row[`${key}_text`] =
|
row[`${key}_text`] =
|
||||||
row[key]
|
row[key]
|
||||||
?.map(option => option?.primaryDisplay)
|
?.map((option) => option?.primaryDisplay)
|
||||||
.filter(option => !!option)
|
.filter((option) => !!option)
|
||||||
.join(", ") || ""
|
.join(", ") || ""
|
||||||
} else if (type === "attachment") {
|
} else if (type === "attachment") {
|
||||||
// Enrich row with the first image URL for any attachment fields
|
// Enrich row with the first image URL for any attachment fields
|
||||||
|
|
|
@ -5,14 +5,14 @@ import { enrichRows } from "./rows"
|
||||||
* Fetches a table definition.
|
* Fetches a table definition.
|
||||||
* Since definitions cannot change at runtime, the result is cached.
|
* Since definitions cannot change at runtime, the result is cached.
|
||||||
*/
|
*/
|
||||||
export const fetchTableDefinition = async tableId => {
|
export const fetchTableDefinition = async (tableId) => {
|
||||||
return await API.get({ url: `/api/tables/${tableId}`, cache: true })
|
return await API.get({ url: `/api/tables/${tableId}`, cache: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches all rows from a table.
|
* Fetches all rows from a table.
|
||||||
*/
|
*/
|
||||||
export const fetchTableData = async tableId => {
|
export const fetchTableData = async (tableId) => {
|
||||||
const rows = await API.get({ url: `/api/${tableId}/rows` })
|
const rows = await API.get({ url: `/api/${tableId}/rows` })
|
||||||
return await enrichRows(rows, tableId)
|
return await enrichRows(rows, tableId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ const createBuilderStore = () => {
|
||||||
}
|
}
|
||||||
const store = writable(initialState)
|
const store = writable(initialState)
|
||||||
const actions = {
|
const actions = {
|
||||||
selectComponent: id => {
|
selectComponent: (id) => {
|
||||||
if (id) {
|
if (id) {
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("bb-select-component", { detail: id })
|
new CustomEvent("bb-select-component", { detail: id })
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { writable, derived } from "svelte/store"
|
import { writable, derived } from "svelte/store"
|
||||||
|
|
||||||
export const createContextStore = oldContext => {
|
export const createContextStore = (oldContext) => {
|
||||||
const newContext = writable({})
|
const newContext = writable({})
|
||||||
const contexts = oldContext ? [oldContext, newContext] : [newContext]
|
const contexts = oldContext ? [oldContext, newContext] : [newContext]
|
||||||
const totalContext = derived(contexts, $contexts => {
|
const totalContext = derived(contexts, ($contexts) => {
|
||||||
return $contexts.reduce((total, context) => ({ ...total, ...context }), {})
|
return $contexts.reduce((total, context) => ({ ...total, ...context }), {})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ export const createContextStore = oldContext => {
|
||||||
if (!providerId || data === undefined) {
|
if (!providerId || data === undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newContext.update(state => {
|
newContext.update((state) => {
|
||||||
state[providerId] = data
|
state[providerId] = data
|
||||||
|
|
||||||
// Keep track of the closest component ID so we can later hydrate a "data" prop.
|
// Keep track of the closest component ID so we can later hydrate a "data" prop.
|
||||||
|
@ -29,7 +29,7 @@ export const createContextStore = oldContext => {
|
||||||
if (!providerId || !actionType) {
|
if (!providerId || !actionType) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newContext.update(state => {
|
newContext.update((state) => {
|
||||||
state[`${providerId}_${actionType}`] = callback
|
state[`${providerId}_${actionType}`] = callback
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
|
|
@ -40,8 +40,8 @@ export const createDataSourceStore = () => {
|
||||||
|
|
||||||
// Store configs for each relevant dataSource ID
|
// Store configs for each relevant dataSource ID
|
||||||
if (dataSourceIds.length) {
|
if (dataSourceIds.length) {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
dataSourceIds.forEach(id => {
|
dataSourceIds.forEach((id) => {
|
||||||
state.push({
|
state.push({
|
||||||
dataSourceId: id,
|
dataSourceId: id,
|
||||||
instanceId,
|
instanceId,
|
||||||
|
@ -55,22 +55,22 @@ export const createDataSourceStore = () => {
|
||||||
|
|
||||||
// Removes all registered dataSource instances belonging to a particular
|
// Removes all registered dataSource instances belonging to a particular
|
||||||
// instance ID
|
// instance ID
|
||||||
const unregisterInstance = instanceId => {
|
const unregisterInstance = (instanceId) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
return state.filter(instance => instance.instanceId !== instanceId)
|
return state.filter((instance) => instance.instanceId !== instanceId)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidates a specific dataSource ID by refreshing all instances
|
// Invalidates a specific dataSource ID by refreshing all instances
|
||||||
// which depend on data from that dataSource
|
// which depend on data from that dataSource
|
||||||
const invalidateDataSource = dataSourceId => {
|
const invalidateDataSource = (dataSourceId) => {
|
||||||
const relatedInstances = get(store).filter(instance => {
|
const relatedInstances = get(store).filter((instance) => {
|
||||||
return instance.dataSourceId === dataSourceId
|
return instance.dataSourceId === dataSourceId
|
||||||
})
|
})
|
||||||
if (relatedInstances?.length) {
|
if (relatedInstances?.length) {
|
||||||
notificationStore.blockNotifications(1000)
|
notificationStore.blockNotifications(1000)
|
||||||
}
|
}
|
||||||
relatedInstances?.forEach(instance => {
|
relatedInstances?.forEach((instance) => {
|
||||||
instance.refresh()
|
instance.refresh()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ const createNotificationStore = () => {
|
||||||
const _notifications = writable([], () => {
|
const _notifications = writable([], () => {
|
||||||
return () => {
|
return () => {
|
||||||
// clear all the timers
|
// clear all the timers
|
||||||
timeoutIds.forEach(timeoutId => {
|
timeoutIds.forEach((timeoutId) => {
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
})
|
})
|
||||||
_notifications.set([])
|
_notifications.set([])
|
||||||
|
@ -25,11 +25,11 @@ const createNotificationStore = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let _id = id()
|
let _id = id()
|
||||||
_notifications.update(state => {
|
_notifications.update((state) => {
|
||||||
return [...state, { id: _id, type, message }]
|
return [...state, { id: _id, type, message }]
|
||||||
})
|
})
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
_notifications.update(state => {
|
_notifications.update((state) => {
|
||||||
return state.filter(({ id }) => id !== _id)
|
return state.filter(({ id }) => id !== _id)
|
||||||
})
|
})
|
||||||
}, NOTIFICATION_TIMEOUT)
|
}, NOTIFICATION_TIMEOUT)
|
||||||
|
@ -41,21 +41,16 @@ const createNotificationStore = () => {
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
send,
|
send,
|
||||||
danger: msg => send(msg, "danger"),
|
danger: (msg) => send(msg, "danger"),
|
||||||
warning: msg => send(msg, "warning"),
|
warning: (msg) => send(msg, "warning"),
|
||||||
info: msg => send(msg, "info"),
|
info: (msg) => send(msg, "info"),
|
||||||
success: msg => send(msg, "success"),
|
success: (msg) => send(msg, "success"),
|
||||||
blockNotifications,
|
blockNotifications,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function id() {
|
function id() {
|
||||||
return (
|
return "_" + Math.random().toString(36).substr(2, 9)
|
||||||
"_" +
|
|
||||||
Math.random()
|
|
||||||
.toString(36)
|
|
||||||
.substr(2, 9)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const notificationStore = createNotificationStore()
|
export const notificationStore = createNotificationStore()
|
||||||
|
|
|
@ -14,7 +14,7 @@ const createRouteStore = () => {
|
||||||
const fetchRoutes = async () => {
|
const fetchRoutes = async () => {
|
||||||
const routeConfig = await API.fetchRoutes()
|
const routeConfig = await API.fetchRoutes()
|
||||||
let routes = []
|
let routes = []
|
||||||
Object.values(routeConfig.routes).forEach(route => {
|
Object.values(routeConfig.routes).forEach((route) => {
|
||||||
Object.entries(route.subpaths).forEach(([path, config]) => {
|
Object.entries(route.subpaths).forEach(([path, config]) => {
|
||||||
routes.push({
|
routes.push({
|
||||||
path,
|
path,
|
||||||
|
@ -28,21 +28,21 @@ const createRouteStore = () => {
|
||||||
return a.path > b.path ? -1 : 1
|
return a.path > b.path ? -1 : 1
|
||||||
})
|
})
|
||||||
|
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.routes = routes
|
state.routes = routes
|
||||||
state.routeSessionId = Math.random()
|
state.routeSessionId = Math.random()
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const setRouteParams = routeParams => {
|
const setRouteParams = (routeParams) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.routeParams = routeParams
|
state.routeParams = routeParams
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const setActiveRoute = route => {
|
const setActiveRoute = (route) => {
|
||||||
store.update(state => {
|
store.update((state) => {
|
||||||
state.activeRoute = state.routes.find(x => x.path === route)
|
state.activeRoute = state.routes.find((x) => x.path === route)
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ const createScreenStore = () => {
|
||||||
activeScreen = screens[0]
|
activeScreen = screens[0]
|
||||||
} else if ($routeStore.activeRoute) {
|
} else if ($routeStore.activeRoute) {
|
||||||
activeScreen = screens.find(
|
activeScreen = screens.find(
|
||||||
screen => screen._id === $routeStore.activeRoute.screenId
|
(screen) => screen._id === $routeStore.activeRoute.screenId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (activeScreen) {
|
if (activeScreen) {
|
||||||
activeLayout = layouts.find(
|
activeLayout = layouts.find(
|
||||||
layout => layout._id === activeScreen.layoutId
|
(layout) => layout._id === activeScreen.layoutId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,27 +16,27 @@ const saveRowHandler = async (action, context) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteRowHandler = async action => {
|
const deleteRowHandler = async (action) => {
|
||||||
const { tableId, revId, rowId } = action.parameters
|
const { tableId, revId, rowId } = action.parameters
|
||||||
if (tableId && revId && rowId) {
|
if (tableId && revId && rowId) {
|
||||||
await deleteRow({ tableId, rowId, revId })
|
await deleteRow({ tableId, rowId, revId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggerAutomationHandler = async action => {
|
const triggerAutomationHandler = async (action) => {
|
||||||
const { fields } = action.parameters
|
const { fields } = action.parameters
|
||||||
if (fields) {
|
if (fields) {
|
||||||
await triggerAutomation(action.parameters.automationId, fields)
|
await triggerAutomation(action.parameters.automationId, fields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigationHandler = action => {
|
const navigationHandler = (action) => {
|
||||||
if (action.parameters.url) {
|
if (action.parameters.url) {
|
||||||
routeStore.actions.navigate(action.parameters.url)
|
routeStore.actions.navigate(action.parameters.url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryExecutionHandler = async action => {
|
const queryExecutionHandler = async (action) => {
|
||||||
const { datasourceId, queryId, queryParams } = action.parameters
|
const { datasourceId, queryId, queryParams } = action.parameters
|
||||||
await executeQuery({
|
await executeQuery({
|
||||||
datasourceId,
|
datasourceId,
|
||||||
|
@ -68,7 +68,7 @@ const refreshDatasourceHandler = async (action, context) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const loginHandler = async action => {
|
const loginHandler = async (action) => {
|
||||||
const { email, password } = action.parameters
|
const { email, password } = action.parameters
|
||||||
await authStore.actions.logIn({ email, password })
|
await authStore.actions.logIn({ email, password })
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ export const enrichButtonActions = (actions, context) => {
|
||||||
if (get(builderStore).inBuilder) {
|
if (get(builderStore).inBuilder) {
|
||||||
return () => {}
|
return () => {}
|
||||||
}
|
}
|
||||||
const handlers = actions.map(def => handlerMap[def["##eventHandlerType"]])
|
const handlers = actions.map((def) => handlerMap[def["##eventHandlerType"]])
|
||||||
return async () => {
|
return async () => {
|
||||||
for (let i = 0; i < handlers.length; i++) {
|
for (let i = 0; i < handlers.length; i++) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export const hashString = str => {
|
export const hashString = (str) => {
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ export const styleable = (node, styles = {}) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applies a style string to a DOM node
|
// Applies a style string to a DOM node
|
||||||
const applyStyles = styleString => {
|
const applyStyles = (styleString) => {
|
||||||
node.style = addBuilderPreviewStyles(node, styleString, componentId)
|
node.style = addBuilderPreviewStyles(node, styleString, componentId)
|
||||||
node.dataset.componentId = componentId
|
node.dataset.componentId = componentId
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ export const styleable = (node, styles = {}) => {
|
||||||
|
|
||||||
// Handler to select a component in the builder when clicking it in the
|
// Handler to select a component in the builder when clicking it in the
|
||||||
// builder preview
|
// builder preview
|
||||||
selectComponent = event => {
|
selectComponent = (event) => {
|
||||||
builderStore.actions.selectComponent(componentId)
|
builderStore.actions.selectComponent(componentId)
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
@ -106,7 +106,7 @@ export const styleable = (node, styles = {}) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Clean up old listeners and apply new ones on update
|
// Clean up old listeners and apply new ones on update
|
||||||
update: newStyles => {
|
update: (newStyles) => {
|
||||||
removeListeners()
|
removeListeners()
|
||||||
setupStyles(newStyles)
|
setupStyles(newStyles)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const aws = {}
|
const aws = {}
|
||||||
|
|
||||||
const response = body => () => ({ promise: () => body })
|
const response = (body) => () => ({ promise: () => body })
|
||||||
|
|
||||||
function DocumentClient() {
|
function DocumentClient() {
|
||||||
this.put = jest.fn(response({}))
|
this.put = jest.fn(response({}))
|
||||||
|
|
|
@ -46,7 +46,7 @@ async function init() {
|
||||||
SELF_HOSTED: 1,
|
SELF_HOSTED: 1,
|
||||||
}
|
}
|
||||||
let envFile = ""
|
let envFile = ""
|
||||||
Object.keys(envFileJson).forEach(key => {
|
Object.keys(envFileJson).forEach((key) => {
|
||||||
envFile += `${key}=${envFileJson[key]}\n`
|
envFile += `${key}=${envFileJson[key]}\n`
|
||||||
})
|
})
|
||||||
fs.writeFileSync(envFilePath, envFile)
|
fs.writeFileSync(envFilePath, envFile)
|
||||||
|
@ -78,7 +78,7 @@ const managementCommand = process.argv.slice(2)[0]
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!managementCommand ||
|
!managementCommand ||
|
||||||
!Object.values(Commands).some(command => managementCommand === command)
|
!Object.values(Commands).some((command) => managementCommand === command)
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"You must supply either an 'up', 'down' or 'nuke' commmand to manage the budibase development environment."
|
"You must supply either an 'up', 'down' or 'nuke' commmand to manage the budibase development environment."
|
||||||
|
@ -104,7 +104,7 @@ command()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log("Done! 🎉")
|
console.log("Done! 🎉")
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
console.error(
|
console.error(
|
||||||
"Something went wrong while managing budibase dev environment:",
|
"Something went wrong while managing budibase dev environment:",
|
||||||
err.message
|
err.message
|
||||||
|
|
|
@ -25,7 +25,7 @@ yargs
|
||||||
type: "string",
|
type: "string",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async args => {
|
async (args) => {
|
||||||
if (!env.isDev()) {
|
if (!env.isDev()) {
|
||||||
throw "Only works in dev"
|
throw "Only works in dev"
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ console.log(`Replicating from ${appName} to ${remoteUrl}/${appName}`)
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
const allDbs = await CouchDB.allDbs()
|
const allDbs = await CouchDB.allDbs()
|
||||||
const appDbNames = allDbs.filter(dbName => dbName.startsWith("inst_app"))
|
const appDbNames = allDbs.filter((dbName) => dbName.startsWith("inst_app"))
|
||||||
let apps = []
|
let apps = []
|
||||||
for (let dbName of appDbNames) {
|
for (let dbName of appDbNames) {
|
||||||
const db = new CouchDB(dbName)
|
const db = new CouchDB(dbName)
|
||||||
|
@ -22,12 +22,12 @@ const run = async () => {
|
||||||
}
|
}
|
||||||
apps = await Promise.all(apps)
|
apps = await Promise.all(apps)
|
||||||
const app = apps.find(
|
const app = apps.find(
|
||||||
a => a.name === appName || a.name.toLowerCase() === appName
|
(a) => a.name === appName || a.name.toLowerCase() === appName
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!app) {
|
if (!app) {
|
||||||
console.log(
|
console.log(
|
||||||
`Could not find app... apps: ${apps.map(app => app.name).join(", ")}`
|
`Could not find app... apps: ${apps.map((app) => app.name).join(", ")}`
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ async function getLayouts(db) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).rows.map(row => row.doc)
|
).rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getScreens(db) {
|
async function getScreens(db) {
|
||||||
|
@ -53,7 +53,7 @@ async function getScreens(db) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).rows.map(row => row.doc)
|
).rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserRoleId(ctx) {
|
function getUserRoleId(ctx) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ const { outputProcessing } = require("../../utilities/rowProcessor")
|
||||||
const { InternalTables } = require("../../db/utils")
|
const { InternalTables } = require("../../db/utils")
|
||||||
const { getFullUser } = require("../../utilities/users")
|
const { getFullUser } = require("../../utilities/users")
|
||||||
|
|
||||||
exports.fetchSelf = async ctx => {
|
exports.fetchSelf = async (ctx) => {
|
||||||
if (!ctx.user) {
|
if (!ctx.user) {
|
||||||
ctx.throw(403, "No user logged in")
|
ctx.throw(403, "No user logged in")
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ exports.fetch = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
ctx.body = response.rows.map(row => row.doc)
|
ctx.body = response.rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.find = async function (ctx) {
|
exports.find = async function (ctx) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ exports.fetchAppComponentDefinitions = async function(ctx) {
|
||||||
const app = await db.get(appId)
|
const app = await db.get(appId)
|
||||||
|
|
||||||
let componentManifests = await Promise.all(
|
let componentManifests = await Promise.all(
|
||||||
app.componentLibraries.map(async library => {
|
app.componentLibraries.map(async (library) => {
|
||||||
let manifest = await getComponentLibraryManifest(appId, library)
|
let manifest = await getComponentLibraryManifest(appId, library)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -13,7 +13,7 @@ exports.fetch = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).rows.map(row => row.doc)
|
).rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.save = async function (ctx) {
|
exports.save = async function (ctx) {
|
||||||
|
@ -38,7 +38,7 @@ exports.destroy = async function(ctx) {
|
||||||
|
|
||||||
// Delete all queries for the datasource
|
// Delete all queries for the datasource
|
||||||
const rows = await db.allDocs(getQueryParams(ctx.params.datasourceId, null))
|
const rows = await db.allDocs(getQueryParams(ctx.params.datasourceId, null))
|
||||||
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
|
await db.bulkDocs(rows.rows.map((row) => ({ ...row.doc, _deleted: true })))
|
||||||
|
|
||||||
// delete the datasource
|
// delete the datasource
|
||||||
await db.remove(ctx.params.datasourceId, ctx.params.revId)
|
await db.remove(ctx.params.datasourceId, ctx.params.revId)
|
||||||
|
|
|
@ -131,6 +131,6 @@ exports.performReplication = (appId, session, dbUrl) => {
|
||||||
const replication = local.sync(remote)
|
const replication = local.sync(remote)
|
||||||
|
|
||||||
replication.on("complete", () => resolve())
|
replication.on("complete", () => resolve())
|
||||||
replication.on("error", err => reject(err))
|
replication.on("error", (err) => reject(err))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,14 @@ async function redirect(ctx, method) {
|
||||||
ctx.cookies
|
ctx.cookies
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.redirectGet = async ctx => {
|
exports.redirectGet = async (ctx) => {
|
||||||
await redirect(ctx, "GET")
|
await redirect(ctx, "GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.redirectPost = async ctx => {
|
exports.redirectPost = async (ctx) => {
|
||||||
await redirect(ctx, "POST")
|
await redirect(ctx, "POST")
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.redirectDelete = async ctx => {
|
exports.redirectDelete = async (ctx) => {
|
||||||
await redirect(ctx, "DELETE")
|
await redirect(ctx, "DELETE")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@ const {
|
||||||
} = require("../../utilities/builder/hosting")
|
} = require("../../utilities/builder/hosting")
|
||||||
const { StaticDatabases } = require("../../db/utils")
|
const { StaticDatabases } = require("../../db/utils")
|
||||||
|
|
||||||
exports.fetchInfo = async ctx => {
|
exports.fetchInfo = async (ctx) => {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
types: Object.values(HostingTypes),
|
types: Object.values(HostingTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.save = async ctx => {
|
exports.save = async (ctx) => {
|
||||||
const db = new CouchDB(StaticDatabases.BUILDER_HOSTING.name)
|
const db = new CouchDB(StaticDatabases.BUILDER_HOSTING.name)
|
||||||
const { type } = ctx.request.body
|
const { type } = ctx.request.body
|
||||||
if (type === HostingTypes.CLOUD && ctx.request.body._rev) {
|
if (type === HostingTypes.CLOUD && ctx.request.body._rev) {
|
||||||
|
@ -29,16 +29,16 @@ exports.save = async ctx => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetch = async ctx => {
|
exports.fetch = async (ctx) => {
|
||||||
ctx.body = await getHostingInfo()
|
ctx.body = await getHostingInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetchUrls = async ctx => {
|
exports.fetchUrls = async (ctx) => {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
app: await getAppUrl(ctx.appId),
|
app: await getAppUrl(ctx.appId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getDeployedApps = async ctx => {
|
exports.getDeployedApps = async (ctx) => {
|
||||||
ctx.body = await getDeployedApps(ctx)
|
ctx.body = await getDeployedApps(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ exports.destroy = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).rows.map(element => element.doc.layoutId)
|
).rows.map((element) => element.doc.layoutId)
|
||||||
if (layoutsUsedByScreens.includes(layoutId)) {
|
if (layoutsUsedByScreens.includes(layoutId)) {
|
||||||
ctx.throw(400, "Cannot delete a layout that's being used by a screen")
|
ctx.throw(400, "Cannot delete a layout that's being used by a screen")
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ async function getAllDBRoles(db) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
return body.rows.map(row => row.doc)
|
return body.rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updatePermissionOnRole(
|
async function updatePermissionOnRole(
|
||||||
|
@ -63,7 +63,7 @@ async function updatePermissionOnRole(
|
||||||
const docUpdates = []
|
const docUpdates = []
|
||||||
|
|
||||||
// the permission is for a built in, make sure it exists
|
// the permission is for a built in, make sure it exists
|
||||||
if (isABuiltin && !dbRoles.some(role => role._id === dbRoleId)) {
|
if (isABuiltin && !dbRoles.some((role) => role._id === dbRoleId)) {
|
||||||
const builtin = getBuiltinRoles()[roleId]
|
const builtin = getBuiltinRoles()[roleId]
|
||||||
builtin._id = getDBRoleID(builtin._id)
|
builtin._id = getDBRoleID(builtin._id)
|
||||||
dbRoles.push(builtin)
|
dbRoles.push(builtin)
|
||||||
|
@ -101,7 +101,7 @@ async function updatePermissionOnRole(
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await db.bulkDocs(docUpdates)
|
const response = await db.bulkDocs(docUpdates)
|
||||||
return response.map(resp => {
|
return response.map((resp) => {
|
||||||
resp._id = getExternalRoleID(resp.id)
|
resp._id = getExternalRoleID(resp.id)
|
||||||
delete resp.id
|
delete resp.id
|
||||||
return resp
|
return resp
|
||||||
|
@ -152,7 +152,7 @@ exports.getResourcePerms = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
const roles = body.rows.map(row => row.doc)
|
const roles = body.rows.map((row) => row.doc)
|
||||||
let permissions = {}
|
let permissions = {}
|
||||||
for (let level of SUPPORTED_LEVELS) {
|
for (let level of SUPPORTED_LEVELS) {
|
||||||
// update the various roleIds in the resource permissions
|
// update the various roleIds in the resource permissions
|
||||||
|
|
|
@ -35,7 +35,7 @@ exports.fetch = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
ctx.body = enrichQueries(body.rows.map(row => row.doc))
|
ctx.body = enrichQueries(body.rows.map((row) => row.doc))
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.save = async function (ctx) {
|
exports.save = async function (ctx) {
|
||||||
|
|
|
@ -57,20 +57,20 @@ exports.fetch = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
let roles = body.rows.map(row => row.doc)
|
let roles = body.rows.map((row) => row.doc)
|
||||||
const builtinRoles = getBuiltinRoles()
|
const builtinRoles = getBuiltinRoles()
|
||||||
|
|
||||||
// need to combine builtin with any DB record of them (for sake of permissions)
|
// need to combine builtin with any DB record of them (for sake of permissions)
|
||||||
for (let builtinRoleId of EXTERNAL_BUILTIN_ROLE_IDS) {
|
for (let builtinRoleId of EXTERNAL_BUILTIN_ROLE_IDS) {
|
||||||
const builtinRole = builtinRoles[builtinRoleId]
|
const builtinRole = builtinRoles[builtinRoleId]
|
||||||
const dbBuiltin = roles.filter(
|
const dbBuiltin = roles.filter(
|
||||||
dbRole => getExternalRoleID(dbRole._id) === builtinRoleId
|
(dbRole) => getExternalRoleID(dbRole._id) === builtinRoleId
|
||||||
)[0]
|
)[0]
|
||||||
if (dbBuiltin == null) {
|
if (dbBuiltin == null) {
|
||||||
roles.push(builtinRole)
|
roles.push(builtinRole)
|
||||||
} else {
|
} else {
|
||||||
// remove role and all back after combining with the builtin
|
// remove role and all back after combining with the builtin
|
||||||
roles = roles.filter(role => role._id !== dbBuiltin._id)
|
roles = roles.filter((role) => role._id !== dbBuiltin._id)
|
||||||
dbBuiltin._id = getExternalRoleID(dbBuiltin._id)
|
dbBuiltin._id = getExternalRoleID(dbBuiltin._id)
|
||||||
roles.push(Object.assign(builtinRole, dbBuiltin))
|
roles.push(Object.assign(builtinRole, dbBuiltin))
|
||||||
}
|
}
|
||||||
|
@ -116,8 +116,8 @@ exports.destroy = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).rows.map(row => row.doc)
|
).rows.map((row) => row.doc)
|
||||||
const usersWithRole = users.filter(user => user.roleId === roleId)
|
const usersWithRole = users.filter((user) => user.roleId === roleId)
|
||||||
if (usersWithRole.length !== 0) {
|
if (usersWithRole.length !== 0) {
|
||||||
ctx.throw(400, "Cannot delete role when it is in use.")
|
ctx.throw(400, "Cannot delete role when it is in use.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,11 @@ async function getRoutingStructure(appId) {
|
||||||
return { routes: routing.json }
|
return { routes: routing.json }
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetch = async ctx => {
|
exports.fetch = async (ctx) => {
|
||||||
ctx.body = await getRoutingStructure(ctx.appId)
|
ctx.body = await getRoutingStructure(ctx.appId)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.clientFetch = async ctx => {
|
exports.clientFetch = async (ctx) => {
|
||||||
const routing = await getRoutingStructure(ctx.appId)
|
const routing = await getRoutingStructure(ctx.appId)
|
||||||
let roleId = ctx.user.role._id
|
let roleId = ctx.user.role._id
|
||||||
// builder is a special case, always return the full routing structure
|
// builder is a special case, always return the full routing structure
|
||||||
|
|
|
@ -213,7 +213,7 @@ exports.fetchView = async function(ctx) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!calculation) {
|
if (!calculation) {
|
||||||
response.rows = response.rows.map(row => row.doc)
|
response.rows = response.rows.map((row) => row.doc)
|
||||||
let table
|
let table
|
||||||
try {
|
try {
|
||||||
table = await db.get(viewInfo.meta.tableId)
|
table = await db.get(viewInfo.meta.tableId)
|
||||||
|
@ -227,7 +227,7 @@ exports.fetchView = async function(ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculation === CALCULATION_TYPES.STATS) {
|
if (calculation === CALCULATION_TYPES.STATS) {
|
||||||
response.rows = response.rows.map(row => ({
|
response.rows = response.rows.map((row) => ({
|
||||||
group: row.key,
|
group: row.key,
|
||||||
field,
|
field,
|
||||||
...row.value,
|
...row.value,
|
||||||
|
@ -240,7 +240,7 @@ exports.fetchView = async function(ctx) {
|
||||||
calculation === CALCULATION_TYPES.COUNT ||
|
calculation === CALCULATION_TYPES.COUNT ||
|
||||||
calculation === CALCULATION_TYPES.SUM
|
calculation === CALCULATION_TYPES.SUM
|
||||||
) {
|
) {
|
||||||
ctx.body = response.rows.map(row => ({
|
ctx.body = response.rows.map((row) => ({
|
||||||
group: row.key,
|
group: row.key,
|
||||||
field,
|
field,
|
||||||
value: row.value,
|
value: row.value,
|
||||||
|
@ -303,7 +303,7 @@ exports.fetchTableRows = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
rows = response.rows.map(row => row.doc)
|
rows = response.rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
ctx.body = await outputProcessing(appId, table, rows)
|
ctx.body = await outputProcessing(appId, table, rows)
|
||||||
}
|
}
|
||||||
|
@ -399,13 +399,13 @@ exports.fetchEnrichedRow = async function(ctx) {
|
||||||
// look up the actual rows based on the ids
|
// look up the actual rows based on the ids
|
||||||
const response = await db.allDocs({
|
const response = await db.allDocs({
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
keys: linkVals.map(linkVal => linkVal.id),
|
keys: linkVals.map((linkVal) => linkVal.id),
|
||||||
})
|
})
|
||||||
// need to include the IDs in these rows for any links they may have
|
// need to include the IDs in these rows for any links they may have
|
||||||
let linkedRows = await outputProcessing(
|
let linkedRows = await outputProcessing(
|
||||||
appId,
|
appId,
|
||||||
table,
|
table,
|
||||||
response.rows.map(row => row.doc)
|
response.rows.map((row) => row.doc)
|
||||||
)
|
)
|
||||||
// insert the link rows in the correct place throughout the main row
|
// insert the link rows in the correct place throughout the main row
|
||||||
for (let fieldName of Object.keys(table.schema)) {
|
for (let fieldName of Object.keys(table.schema)) {
|
||||||
|
@ -413,8 +413,8 @@ exports.fetchEnrichedRow = async function(ctx) {
|
||||||
if (field.type === FieldTypes.LINK) {
|
if (field.type === FieldTypes.LINK) {
|
||||||
// find the links that pertain to this field, get their indexes
|
// find the links that pertain to this field, get their indexes
|
||||||
const linkIndexes = linkVals
|
const linkIndexes = linkVals
|
||||||
.filter(link => link.fieldName === fieldName)
|
.filter((link) => link.fieldName === fieldName)
|
||||||
.map(link => linkVals.indexOf(link))
|
.map((link) => linkVals.indexOf(link))
|
||||||
// find the rows that the links state are linked to this field
|
// find the rows that the links state are linked to this field
|
||||||
row[fieldName] = linkedRows.filter((linkRow, index) =>
|
row[fieldName] = linkedRows.filter((linkRow, index) =>
|
||||||
linkIndexes.includes(index)
|
linkIndexes.includes(index)
|
||||||
|
@ -430,7 +430,7 @@ async function bulkDelete(ctx) {
|
||||||
const { rows } = ctx.request.body
|
const { rows } = ctx.request.body
|
||||||
const db = new CouchDB(appId)
|
const db = new CouchDB(appId)
|
||||||
|
|
||||||
let updates = rows.map(row =>
|
let updates = rows.map((row) =>
|
||||||
linkRows.updateLinks({
|
linkRows.updateLinks({
|
||||||
appId,
|
appId,
|
||||||
eventType: linkRows.EventType.ROW_DELETE,
|
eventType: linkRows.EventType.ROW_DELETE,
|
||||||
|
@ -441,7 +441,7 @@ async function bulkDelete(ctx) {
|
||||||
// TODO remove special user case in future
|
// TODO remove special user case in future
|
||||||
if (ctx.params.tableId === InternalTables.USER_METADATA) {
|
if (ctx.params.tableId === InternalTables.USER_METADATA) {
|
||||||
updates = updates.concat(
|
updates = updates.concat(
|
||||||
rows.map(row => {
|
rows.map((row) => {
|
||||||
ctx.params = {
|
ctx.params = {
|
||||||
id: row._id,
|
id: row._id,
|
||||||
}
|
}
|
||||||
|
@ -449,11 +449,11 @@ async function bulkDelete(ctx) {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
await db.bulkDocs(rows.map(row => ({ ...row, _deleted: true })))
|
await db.bulkDocs(rows.map((row) => ({ ...row, _deleted: true })))
|
||||||
}
|
}
|
||||||
await Promise.all(updates)
|
await Promise.all(updates)
|
||||||
|
|
||||||
rows.forEach(row => {
|
rows.forEach((row) => {
|
||||||
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ const CouchDB = require("../../db")
|
||||||
const { getScreenParams, generateScreenID } = require("../../db/utils")
|
const { getScreenParams, generateScreenID } = require("../../db/utils")
|
||||||
const { AccessController } = require("../../utilities/security/roles")
|
const { AccessController } = require("../../utilities/security/roles")
|
||||||
|
|
||||||
exports.fetch = async ctx => {
|
exports.fetch = async (ctx) => {
|
||||||
const appId = ctx.appId
|
const appId = ctx.appId
|
||||||
const db = new CouchDB(appId)
|
const db = new CouchDB(appId)
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ exports.fetch = async ctx => {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).rows.map(element => element.doc)
|
).rows.map((element) => element.doc)
|
||||||
|
|
||||||
ctx.body = await new AccessController(appId).checkScreensAccess(
|
ctx.body = await new AccessController(appId).checkScreensAccess(
|
||||||
screens,
|
screens,
|
||||||
|
@ -20,7 +20,7 @@ exports.fetch = async ctx => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.save = async ctx => {
|
exports.save = async (ctx) => {
|
||||||
const appId = ctx.appId
|
const appId = ctx.appId
|
||||||
const db = new CouchDB(appId)
|
const db = new CouchDB(appId)
|
||||||
let screen = ctx.request.body
|
let screen = ctx.request.body
|
||||||
|
@ -38,7 +38,7 @@ exports.save = async ctx => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.destroy = async ctx => {
|
exports.destroy = async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
await db.remove(ctx.params.screenId, ctx.params.screenRev)
|
await db.remove(ctx.params.screenId, ctx.params.screenRev)
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const { QueryBuilder, buildSearchUrl, search } = require("./utils")
|
const { QueryBuilder, buildSearchUrl, search } = require("./utils")
|
||||||
|
|
||||||
exports.rowSearch = async ctx => {
|
exports.rowSearch = async (ctx) => {
|
||||||
const appId = ctx.appId
|
const appId = ctx.appId
|
||||||
const { tableId } = ctx.params
|
const { tableId } = ctx.params
|
||||||
const { bookmark, query, raw } = ctx.request.body
|
const { bookmark, query, raw } = ctx.request.body
|
||||||
|
|
|
@ -116,7 +116,7 @@ class QueryBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.search = async query => {
|
exports.search = async (query) => {
|
||||||
const response = await fetch(query, {
|
const response = await fetch(query, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
})
|
})
|
||||||
|
@ -125,7 +125,7 @@ exports.search = async query => {
|
||||||
rows: [],
|
rows: [],
|
||||||
}
|
}
|
||||||
if (json.rows != null && json.rows.length > 0) {
|
if (json.rows != null && json.rows.length > 0) {
|
||||||
output.rows = json.rows.map(row => row.doc)
|
output.rows = json.rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
if (json.bookmark) {
|
if (json.bookmark) {
|
||||||
output.bookmark = json.bookmark
|
output.bookmark = json.bookmark
|
||||||
|
|
|
@ -15,7 +15,7 @@ const {
|
||||||
TOP_LEVEL_PATH,
|
TOP_LEVEL_PATH,
|
||||||
} = require("../../../utilities/fileSystem")
|
} = require("../../../utilities/fileSystem")
|
||||||
const env = require("../../../environment")
|
const env = require("../../../environment")
|
||||||
const fileProcessor = require("../../../utilities/fileSystem/processor")
|
// const fileProcessor = require("../../../utilities/fileSystem/processor")
|
||||||
const { objectStoreUrl, clientLibraryPath } = require("../../../utilities")
|
const { objectStoreUrl, clientLibraryPath } = require("../../../utilities")
|
||||||
|
|
||||||
async function checkForSelfHostedURL(ctx) {
|
async function checkForSelfHostedURL(ctx) {
|
||||||
|
@ -43,7 +43,7 @@ exports.uploadFile = async function(ctx) {
|
||||||
? Array.from(ctx.request.files.file)
|
? Array.from(ctx.request.files.file)
|
||||||
: [ctx.request.files.file]
|
: [ctx.request.files.file]
|
||||||
|
|
||||||
const uploads = files.map(async file => {
|
const uploads = files.map(async (file) => {
|
||||||
const fileExtension = [...file.name.split(".")].pop()
|
const fileExtension = [...file.name.split(".")].pop()
|
||||||
// filenames converted to UUIDs so they are unique
|
// filenames converted to UUIDs so they are unique
|
||||||
const processedFileName = `${uuid.v4()}.${fileExtension}`
|
const processedFileName = `${uuid.v4()}.${fileExtension}`
|
||||||
|
|
|
@ -16,7 +16,7 @@ exports.fetch = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
ctx.body = body.rows.map(row => row.doc)
|
ctx.body = body.rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.find = async function (ctx) {
|
exports.find = async function (ctx) {
|
||||||
|
@ -137,7 +137,7 @@ exports.destroy = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
|
await db.bulkDocs(rows.rows.map((row) => ({ ...row.doc, _deleted: true })))
|
||||||
|
|
||||||
// update linked rows
|
// update linked rows
|
||||||
await linkRows.updateLinks({
|
await linkRows.updateLinks({
|
||||||
|
@ -152,7 +152,7 @@ exports.destroy = async function(ctx) {
|
||||||
// remove table search index
|
// remove table search index
|
||||||
const currentIndexes = await db.getIndexes()
|
const currentIndexes = await db.getIndexes()
|
||||||
const existingIndex = currentIndexes.indexes.find(
|
const existingIndex = currentIndexes.indexes.find(
|
||||||
existing => existing.name === `search:${ctx.params.tableId}`
|
(existing) => existing.name === `search:${ctx.params.tableId}`
|
||||||
)
|
)
|
||||||
if (existingIndex) {
|
if (existingIndex) {
|
||||||
await db.deleteIndex(existingIndex)
|
await db.deleteIndex(existingIndex)
|
||||||
|
|
|
@ -16,7 +16,7 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
|
||||||
let deletedColumns = []
|
let deletedColumns = []
|
||||||
if (oldTable && oldTable.schema && updatedTable.schema) {
|
if (oldTable && oldTable.schema && updatedTable.schema) {
|
||||||
deletedColumns = Object.keys(oldTable.schema).filter(
|
deletedColumns = Object.keys(oldTable.schema).filter(
|
||||||
colName => updatedTable.schema[colName] == null
|
(colName) => updatedTable.schema[colName] == null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// check for renaming of columns or deleted columns
|
// check for renaming of columns or deleted columns
|
||||||
|
@ -31,7 +31,7 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
|
||||||
doc[rename.updated] = doc[rename.old]
|
doc[rename.updated] = doc[rename.old]
|
||||||
delete doc[rename.old]
|
delete doc[rename.old]
|
||||||
} else if (deletedColumns.length !== 0) {
|
} else if (deletedColumns.length !== 0) {
|
||||||
deletedColumns.forEach(colName => delete doc[colName])
|
deletedColumns.forEach((colName) => delete doc[colName])
|
||||||
}
|
}
|
||||||
return doc
|
return doc
|
||||||
})
|
})
|
||||||
|
@ -102,12 +102,12 @@ exports.handleSearchIndexes = async (appId, table) => {
|
||||||
const indexName = `search:${table._id}`
|
const indexName = `search:${table._id}`
|
||||||
|
|
||||||
const existingIndex = currentIndexes.indexes.find(
|
const existingIndex = currentIndexes.indexes.find(
|
||||||
existing => existing.name === indexName
|
(existing) => existing.name === indexName
|
||||||
)
|
)
|
||||||
|
|
||||||
if (existingIndex) {
|
if (existingIndex) {
|
||||||
const currentFields = existingIndex.def.fields.map(
|
const currentFields = existingIndex.def.fields.map(
|
||||||
field => Object.keys(field)[0]
|
(field) => Object.keys(field)[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
// if index fields have changed, delete the original index
|
// if index fields have changed, delete the original index
|
||||||
|
@ -138,7 +138,7 @@ exports.handleSearchIndexes = async (appId, table) => {
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.checkStaticTables = table => {
|
exports.checkStaticTables = (table) => {
|
||||||
// check user schema has all required elements
|
// check user schema has all required elements
|
||||||
if (table._id === InternalTables.USER_METADATA) {
|
if (table._id === InternalTables.USER_METADATA) {
|
||||||
for (let [key, schema] of Object.entries(USERS_TABLE_SCHEMA.schema)) {
|
for (let [key, schema] of Object.entries(USERS_TABLE_SCHEMA.schema)) {
|
||||||
|
|
|
@ -22,11 +22,11 @@ exports.fetchMetadata = async function(ctx) {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).rows.map(row => row.doc)
|
).rows.map((row) => row.doc)
|
||||||
const users = []
|
const users = []
|
||||||
for (let user of global) {
|
for (let user of global) {
|
||||||
// find the metadata that matches up to the global ID
|
// find the metadata that matches up to the global ID
|
||||||
const info = metadata.find(meta => meta._id.includes(user._id))
|
const info = metadata.find((meta) => meta._id.includes(user._id))
|
||||||
// remove these props, not for the correct DB
|
// remove these props, not for the correct DB
|
||||||
users.push({
|
users.push({
|
||||||
...user,
|
...user,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
exports.csv = function (headers, rows) {
|
exports.csv = function (headers, rows) {
|
||||||
let csv = headers.map(key => `"${key}"`).join(",")
|
let csv = headers.map((key) => `"${key}"`).join(",")
|
||||||
|
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
csv = `${csv}\n${headers
|
csv = `${csv}\n${headers
|
||||||
.map(header => `"${row[header]}"`.trim())
|
.map((header) => `"${row[header]}"`.trim())
|
||||||
.join(",")}`
|
.join(",")}`
|
||||||
}
|
}
|
||||||
return csv
|
return csv
|
||||||
|
|
|
@ -6,7 +6,7 @@ const { fetchView } = require("../row")
|
||||||
const { ViewNames } = require("../../../db/utils")
|
const { ViewNames } = require("../../../db/utils")
|
||||||
|
|
||||||
const controller = {
|
const controller = {
|
||||||
fetch: async ctx => {
|
fetch: async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
const designDoc = await db.get("_design/database")
|
const designDoc = await db.get("_design/database")
|
||||||
const response = []
|
const response = []
|
||||||
|
@ -24,7 +24,7 @@ const controller = {
|
||||||
|
|
||||||
ctx.body = response
|
ctx.body = response
|
||||||
},
|
},
|
||||||
save: async ctx => {
|
save: async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
const { originalName, ...viewToSave } = ctx.request.body
|
const { originalName, ...viewToSave } = ctx.request.body
|
||||||
const designDoc = await db.get("_design/database")
|
const designDoc = await db.get("_design/database")
|
||||||
|
@ -65,7 +65,7 @@ const controller = {
|
||||||
name: viewToSave.name,
|
name: viewToSave.name,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroy: async ctx => {
|
destroy: async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
const designDoc = await db.get("_design/database")
|
const designDoc = await db.get("_design/database")
|
||||||
const viewName = decodeURI(ctx.params.viewName)
|
const viewName = decodeURI(ctx.params.viewName)
|
||||||
|
@ -80,7 +80,7 @@ const controller = {
|
||||||
|
|
||||||
ctx.body = view
|
ctx.body = view
|
||||||
},
|
},
|
||||||
exportView: async ctx => {
|
exportView: async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
const designDoc = await db.get("_design/database")
|
const designDoc = await db.get("_design/database")
|
||||||
const viewName = decodeURI(ctx.query.view)
|
const viewName = decodeURI(ctx.query.view)
|
||||||
|
|
|
@ -21,17 +21,17 @@ exports.WebhookType = {
|
||||||
AUTOMATION: "automation",
|
AUTOMATION: "automation",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetch = async ctx => {
|
exports.fetch = async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
const response = await db.allDocs(
|
const response = await db.allDocs(
|
||||||
getWebhookParams(null, {
|
getWebhookParams(null, {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
ctx.body = response.rows.map(row => row.doc)
|
ctx.body = response.rows.map((row) => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.save = async ctx => {
|
exports.save = async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
const webhook = ctx.request.body
|
const webhook = ctx.request.body
|
||||||
webhook.appId = ctx.appId
|
webhook.appId = ctx.appId
|
||||||
|
@ -50,12 +50,12 @@ exports.save = async ctx => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.destroy = async ctx => {
|
exports.destroy = async (ctx) => {
|
||||||
const db = new CouchDB(ctx.appId)
|
const db = new CouchDB(ctx.appId)
|
||||||
ctx.body = await db.remove(ctx.params.id, ctx.params.rev)
|
ctx.body = await db.remove(ctx.params.id, ctx.params.rev)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.buildSchema = async ctx => {
|
exports.buildSchema = async (ctx) => {
|
||||||
const db = new CouchDB(ctx.params.instance)
|
const db = new CouchDB(ctx.params.instance)
|
||||||
const webhook = await db.get(ctx.params.id)
|
const webhook = await db.get(ctx.params.id)
|
||||||
webhook.bodySchema = toJsonSchema(ctx.request.body)
|
webhook.bodySchema = toJsonSchema(ctx.request.body)
|
||||||
|
@ -75,7 +75,7 @@ exports.buildSchema = async ctx => {
|
||||||
ctx.body = await db.put(webhook)
|
ctx.body = await db.put(webhook)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.trigger = async ctx => {
|
exports.trigger = async (ctx) => {
|
||||||
const db = new CouchDB(ctx.params.instance)
|
const db = new CouchDB(ctx.params.instance)
|
||||||
const webhook = await db.get(ctx.params.id)
|
const webhook = await db.get(ctx.params.id)
|
||||||
// validate against the schema
|
// validate against the schema
|
||||||
|
|
|
@ -36,8 +36,8 @@ router
|
||||||
}
|
}
|
||||||
await next()
|
await next()
|
||||||
})
|
})
|
||||||
.use("/health", ctx => (ctx.status = 200))
|
.use("/health", (ctx) => (ctx.status = 200))
|
||||||
.use("/version", ctx => (ctx.body = pkg.version))
|
.use("/version", (ctx) => (ctx.body = pkg.version))
|
||||||
.use(buildAuthMiddleware(NO_AUTH_ENDPOINTS))
|
.use(buildAuthMiddleware(NO_AUTH_ENDPOINTS))
|
||||||
.use(currentApp)
|
.use(currentApp)
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ router.use(async (ctx, next) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get("/health", ctx => (ctx.status = 200))
|
router.get("/health", (ctx) => (ctx.status = 200))
|
||||||
|
|
||||||
// authenticated routes
|
// authenticated routes
|
||||||
for (let route of mainRoutes) {
|
for (let route of mainRoutes) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ function Request(appId, params) {
|
||||||
this.params = params
|
this.params = params
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getAllTableRows = async config => {
|
exports.getAllTableRows = async (config) => {
|
||||||
const req = new Request(config.appId, { tableId: config.table._id })
|
const req = new Request(config.appId, { tableId: config.table._id })
|
||||||
await rowController.fetchTableRows(req)
|
await rowController.fetchTableRows(req)
|
||||||
return req.body
|
return req.body
|
||||||
|
@ -26,7 +26,7 @@ exports.clearAllApps = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.clearAllAutomations = async config => {
|
exports.clearAllAutomations = async (config) => {
|
||||||
const automations = await config.getAllAutomations()
|
const automations = await config.getAllAutomations()
|
||||||
for (let auto of automations) {
|
for (let auto of automations) {
|
||||||
await config.deleteAutomation(auto)
|
await config.deleteAutomation(auto)
|
||||||
|
@ -88,6 +88,6 @@ exports.checkPermissionsEndpoint = async ({
|
||||||
.expect(403)
|
.expect(403)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getDB = config => {
|
exports.getDB = (config) => {
|
||||||
return new CouchDB(config.getAppId())
|
return new CouchDB(config.getAppId())
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ jest.mock("../../../../utilities/workerRequests", () => ({
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
exports.delay = ms => new Promise(resolve => setTimeout(resolve, ms))
|
exports.delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||||
|
|
||||||
let request, config
|
let request, config
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ exports.getConfig = () => {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.switchToSelfHosted = async func => {
|
exports.switchToSelfHosted = async (func) => {
|
||||||
// self hosted stops any attempts to Dynamo
|
// self hosted stops any attempts to Dynamo
|
||||||
env._set("NODE_ENV", "production")
|
env._set("NODE_ENV", "production")
|
||||||
env._set("SELF_HOSTED", true)
|
env._set("SELF_HOSTED", true)
|
||||||
|
|
|
@ -73,7 +73,7 @@ module.exports = server.listen(env.PORT || 0, async () => {
|
||||||
await automations.init()
|
await automations.init()
|
||||||
})
|
})
|
||||||
|
|
||||||
process.on("uncaughtException", err => {
|
process.on("uncaughtException", (err) => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
server.close()
|
server.close()
|
||||||
server.destroy()
|
server.destroy()
|
||||||
|
|
|
@ -9,7 +9,7 @@ let workers = workerFarm(require.resolve("./thread"))
|
||||||
|
|
||||||
function runWorker(job) {
|
function runWorker(job) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
workers(job, err => {
|
workers(job, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -32,7 +32,7 @@ async function updateQuota(automation) {
|
||||||
*/
|
*/
|
||||||
module.exports.init = async function () {
|
module.exports.init = async function () {
|
||||||
await actions.init()
|
await actions.init()
|
||||||
triggers.automationQueue.process(async job => {
|
triggers.automationQueue.process(async (job) => {
|
||||||
try {
|
try {
|
||||||
if (env.USE_QUOTAS) {
|
if (env.USE_QUOTAS) {
|
||||||
job.data.automation.apiKey = await updateQuota(job.data.automation)
|
job.data.automation.apiKey = await updateQuota(job.data.automation)
|
||||||
|
|
|
@ -17,7 +17,7 @@ exports.afterAll = () => {
|
||||||
config.end()
|
config.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.runInProd = async fn => {
|
exports.runInProd = async (fn) => {
|
||||||
env._set("NODE_ENV", "production")
|
env._set("NODE_ENV", "production")
|
||||||
env._set("USE_QUOTAS", 1)
|
env._set("USE_QUOTAS", 1)
|
||||||
let error
|
let error
|
||||||
|
@ -37,7 +37,7 @@ exports.runStep = async function runStep(stepId, inputs) {
|
||||||
let step
|
let step
|
||||||
if (
|
if (
|
||||||
Object.values(exports.actions)
|
Object.values(exports.actions)
|
||||||
.map(action => action.stepId)
|
.map((action) => action.stepId)
|
||||||
.includes(stepId)
|
.includes(stepId)
|
||||||
) {
|
) {
|
||||||
step = await actions.getAction(stepId)
|
step = await actions.getAction(stepId)
|
||||||
|
|
|
@ -204,8 +204,8 @@ async function queueRelevantRowAutomations(event, eventType) {
|
||||||
|
|
||||||
// filter down to the correct event type
|
// filter down to the correct event type
|
||||||
automations = automations.rows
|
automations = automations.rows
|
||||||
.map(automation => automation.doc)
|
.map((automation) => automation.doc)
|
||||||
.filter(automation => {
|
.filter((automation) => {
|
||||||
const trigger = automation.definition.trigger
|
const trigger = automation.definition.trigger
|
||||||
return trigger && trigger.event === eventType
|
return trigger && trigger.event === eventType
|
||||||
})
|
})
|
||||||
|
|
|
@ -50,7 +50,7 @@ exports.createHomeScreen = () => ({
|
||||||
name: "home-screen",
|
name: "home-screen",
|
||||||
})
|
})
|
||||||
|
|
||||||
exports.createLoginScreen = app => ({
|
exports.createLoginScreen = (app) => ({
|
||||||
description: "",
|
description: "",
|
||||||
url: "",
|
url: "",
|
||||||
layoutId: BASE_LAYOUT_PROP_IDS.PUBLIC,
|
layoutId: BASE_LAYOUT_PROP_IDS.PUBLIC,
|
||||||
|
|
|
@ -27,7 +27,7 @@ exports.getBuilderMainDoc = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setBuilderMainDoc = async doc => {
|
exports.setBuilderMainDoc = async (doc) => {
|
||||||
if (!env.SELF_HOSTED) {
|
if (!env.SELF_HOSTED) {
|
||||||
throw SELF_HOST_ERR
|
throw SELF_HOST_ERR
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ allDbs(Pouch)
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function replicateLocal() {
|
function replicateLocal() {
|
||||||
Pouch.allDbs().then(dbs => {
|
Pouch.allDbs().then((dbs) => {
|
||||||
for (let db of dbs) {
|
for (let db of dbs) {
|
||||||
new Pouch(db).sync(
|
new Pouch(db).sync(
|
||||||
new PouchDB(`http://127.0.0.1:5984/${db}`, { live: true })
|
new PouchDB(`http://127.0.0.1:5984/${db}`, { live: true })
|
||||||
|
|
|
@ -100,7 +100,7 @@ class Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.init = endpoint => {
|
exports.init = (endpoint) => {
|
||||||
let AWS = require("aws-sdk")
|
let AWS = require("aws-sdk")
|
||||||
AWS.config.update({
|
AWS.config.update({
|
||||||
region: AWS_REGION,
|
region: AWS_REGION,
|
||||||
|
|
|
@ -194,11 +194,11 @@ class LinkController {
|
||||||
if (field.type === FieldTypes.LINK && rowField != null) {
|
if (field.type === FieldTypes.LINK && rowField != null) {
|
||||||
// check which links actual pertain to the update in this row
|
// check which links actual pertain to the update in this row
|
||||||
const thisFieldLinkDocs = linkDocs.filter(
|
const thisFieldLinkDocs = linkDocs.filter(
|
||||||
linkDoc =>
|
(linkDoc) =>
|
||||||
linkDoc.doc1.fieldName === fieldName ||
|
linkDoc.doc1.fieldName === fieldName ||
|
||||||
linkDoc.doc2.fieldName === fieldName
|
linkDoc.doc2.fieldName === fieldName
|
||||||
)
|
)
|
||||||
const linkDocIds = thisFieldLinkDocs.map(linkDoc => {
|
const linkDocIds = thisFieldLinkDocs.map((linkDoc) => {
|
||||||
return linkDoc.doc1.rowId === row._id
|
return linkDoc.doc1.rowId === row._id
|
||||||
? linkDoc.doc2.rowId
|
? linkDoc.doc2.rowId
|
||||||
: linkDoc.doc1.rowId
|
: linkDoc.doc1.rowId
|
||||||
|
@ -218,7 +218,7 @@ class LinkController {
|
||||||
rowId: linkId,
|
rowId: linkId,
|
||||||
includeDocs: IncludeDocs.EXCLUDE,
|
includeDocs: IncludeDocs.EXCLUDE,
|
||||||
})
|
})
|
||||||
).filter(link => link.id !== row._id)
|
).filter((link) => link.id !== row._id)
|
||||||
|
|
||||||
// The 1 side of 1:N is already related to something else
|
// The 1 side of 1:N is already related to something else
|
||||||
// You must remove the existing relationship
|
// You must remove the existing relationship
|
||||||
|
@ -251,12 +251,12 @@ class LinkController {
|
||||||
}
|
}
|
||||||
// find the docs that need to be deleted
|
// find the docs that need to be deleted
|
||||||
let toDeleteDocs = thisFieldLinkDocs
|
let toDeleteDocs = thisFieldLinkDocs
|
||||||
.filter(doc => {
|
.filter((doc) => {
|
||||||
let correctDoc =
|
let correctDoc =
|
||||||
doc.doc1.fieldName === fieldName ? doc.doc2 : doc.doc1
|
doc.doc1.fieldName === fieldName ? doc.doc2 : doc.doc1
|
||||||
return rowField.indexOf(correctDoc.rowId) === -1
|
return rowField.indexOf(correctDoc.rowId) === -1
|
||||||
})
|
})
|
||||||
.map(doc => {
|
.map((doc) => {
|
||||||
return { ...doc, _deleted: true }
|
return { ...doc, _deleted: true }
|
||||||
})
|
})
|
||||||
// now add the docs to be deleted to the bulk operation
|
// now add the docs to be deleted to the bulk operation
|
||||||
|
@ -282,7 +282,7 @@ class LinkController {
|
||||||
if (linkDocs.length === 0) {
|
if (linkDocs.length === 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const toDelete = linkDocs.map(doc => {
|
const toDelete = linkDocs.map((doc) => {
|
||||||
return {
|
return {
|
||||||
...doc,
|
...doc,
|
||||||
_deleted: true,
|
_deleted: true,
|
||||||
|
@ -301,7 +301,7 @@ class LinkController {
|
||||||
let oldTable = this._oldTable
|
let oldTable = this._oldTable
|
||||||
let field = oldTable.schema[fieldName]
|
let field = oldTable.schema[fieldName]
|
||||||
const linkDocs = await this.getTableLinkDocs()
|
const linkDocs = await this.getTableLinkDocs()
|
||||||
let toDelete = linkDocs.filter(linkDoc => {
|
let toDelete = linkDocs.filter((linkDoc) => {
|
||||||
let correctFieldName =
|
let correctFieldName =
|
||||||
linkDoc.doc1.tableId === oldTable._id
|
linkDoc.doc1.tableId === oldTable._id
|
||||||
? linkDoc.doc1.fieldName
|
? linkDoc.doc1.fieldName
|
||||||
|
@ -309,7 +309,7 @@ class LinkController {
|
||||||
return correctFieldName === fieldName
|
return correctFieldName === fieldName
|
||||||
})
|
})
|
||||||
await this._db.bulkDocs(
|
await this._db.bulkDocs(
|
||||||
toDelete.map(doc => {
|
toDelete.map((doc) => {
|
||||||
return {
|
return {
|
||||||
...doc,
|
...doc,
|
||||||
_deleted: true,
|
_deleted: true,
|
||||||
|
@ -434,7 +434,7 @@ class LinkController {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// get link docs for this table and configure for deletion
|
// get link docs for this table and configure for deletion
|
||||||
const toDelete = linkDocs.map(doc => {
|
const toDelete = linkDocs.map((doc) => {
|
||||||
return {
|
return {
|
||||||
...doc,
|
...doc,
|
||||||
_deleted: true,
|
_deleted: true,
|
||||||
|
|
|
@ -33,11 +33,11 @@ exports.getLinkDocuments = getLinkDocuments
|
||||||
exports.createLinkView = createLinkView
|
exports.createLinkView = createLinkView
|
||||||
|
|
||||||
async function getLinksForRows(appId, rows) {
|
async function getLinksForRows(appId, rows) {
|
||||||
const tableIds = [...new Set(rows.map(el => el.tableId))]
|
const tableIds = [...new Set(rows.map((el) => el.tableId))]
|
||||||
// start by getting all the link values for performance reasons
|
// start by getting all the link values for performance reasons
|
||||||
const responses = flatten(
|
const responses = flatten(
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
tableIds.map(tableId =>
|
tableIds.map((tableId) =>
|
||||||
getLinkDocuments({
|
getLinkDocuments({
|
||||||
appId,
|
appId,
|
||||||
tableId: tableId,
|
tableId: tableId,
|
||||||
|
@ -51,7 +51,7 @@ async function getLinksForRows(appId, rows) {
|
||||||
return getUniqueByProp(
|
return getUniqueByProp(
|
||||||
responses
|
responses
|
||||||
// create a unique ID which we can use for getting only unique ones
|
// create a unique ID which we can use for getting only unique ones
|
||||||
.map(el => ({ ...el, unique: el.id + el.thisId + el.fieldName })),
|
.map((el) => ({ ...el, unique: el.id + el.thisId + el.fieldName })),
|
||||||
"unique"
|
"unique"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -127,8 +127,8 @@ exports.attachLinkIDs = async (appId, rows) => {
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
// find anything that matches the row's ID we are searching for and join it
|
// find anything that matches the row's ID we are searching for and join it
|
||||||
links
|
links
|
||||||
.filter(el => el.thisId === row._id)
|
.filter((el) => el.thisId === row._id)
|
||||||
.forEach(link => {
|
.forEach((link) => {
|
||||||
if (row[link.fieldName] == null) {
|
if (row[link.fieldName] == null) {
|
||||||
row[link.fieldName] = []
|
row[link.fieldName] = []
|
||||||
}
|
}
|
||||||
|
@ -154,21 +154,21 @@ exports.attachLinkedPrimaryDisplay = async (appId, table, rows) => {
|
||||||
return rows
|
return rows
|
||||||
}
|
}
|
||||||
const db = new CouchDB(appId)
|
const db = new CouchDB(appId)
|
||||||
const links = (await getLinksForRows(appId, rows)).filter(link =>
|
const links = (await getLinksForRows(appId, rows)).filter((link) =>
|
||||||
rows.some(row => row._id === link.thisId)
|
rows.some((row) => row._id === link.thisId)
|
||||||
)
|
)
|
||||||
const linkedRowIds = links.map(link => link.id)
|
const linkedRowIds = links.map((link) => link.id)
|
||||||
const linked = (await db.allDocs(getMultiIDParams(linkedRowIds))).rows.map(
|
const linked = (await db.allDocs(getMultiIDParams(linkedRowIds))).rows.map(
|
||||||
row => row.doc
|
(row) => row.doc
|
||||||
)
|
)
|
||||||
// will populate this as we find them
|
// will populate this as we find them
|
||||||
const linkedTables = []
|
const linkedTables = []
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
for (let link of links.filter(link => link.thisId === row._id)) {
|
for (let link of links.filter((link) => link.thisId === row._id)) {
|
||||||
if (row[link.fieldName] == null) {
|
if (row[link.fieldName] == null) {
|
||||||
row[link.fieldName] = []
|
row[link.fieldName] = []
|
||||||
}
|
}
|
||||||
const linkedRow = linked.find(row => row._id === link.id)
|
const linkedRow = linked.find((row) => row._id === link.id)
|
||||||
const linkedTableId =
|
const linkedTableId =
|
||||||
linkedRow.tableId || getRelatedTableForField(table, link.fieldName)
|
linkedRow.tableId || getRelatedTableForField(table, link.fieldName)
|
||||||
const linkedTable = await getLinkedTable(db, linkedTableId, linkedTables)
|
const linkedTable = await getLinkedTable(db, linkedTableId, linkedTables)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue