Merge pull request #2703 from Budibase/feature/analytics
Feature/analytics
This commit is contained in:
commit
4e9d123a9e
|
@ -7,6 +7,7 @@ on:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
||||||
|
INTERCOM_TOKEN: ${{ secrets.INTERCOM_TOKEN }}
|
||||||
POSTHOG_URL: ${{ secrets.POSTHOG_URL }}
|
POSTHOG_URL: ${{ secrets.POSTHOG_URL }}
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ on:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
||||||
|
INTERCOM_TOKEN: ${{ secrets.INTERCOM_TOKEN }}
|
||||||
POSTHOG_URL: ${{ secrets.POSTHOG_URL }}
|
POSTHOG_URL: ${{ secrets.POSTHOG_URL }}
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
|
||||||
import { Router } from "@roxi/routify"
|
import { Router } from "@roxi/routify"
|
||||||
import { routes } from "../.routify/routes"
|
import { routes } from "../.routify/routes"
|
||||||
import { initialise } from "builderStore"
|
|
||||||
import { NotificationDisplay } from "@budibase/bbui"
|
import { NotificationDisplay } from "@budibase/bbui"
|
||||||
import { parse, stringify } from "qs"
|
import { parse, stringify } from "qs"
|
||||||
import HelpIcon from "components/common/HelpIcon.svelte"
|
import HelpIcon from "components/common/HelpIcon.svelte"
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
await initialise()
|
|
||||||
})
|
|
||||||
|
|
||||||
const queryHandler = { parse, stringify }
|
const queryHandler = { parse, stringify }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
import * as Sentry from "@sentry/browser"
|
|
||||||
import posthog from "posthog-js"
|
|
||||||
import api from "builderStore/api"
|
|
||||||
|
|
||||||
let analyticsEnabled
|
|
||||||
const posthogConfigured = process.env.POSTHOG_TOKEN && process.env.POSTHOG_URL
|
|
||||||
const sentryConfigured = process.env.SENTRY_DSN
|
|
||||||
|
|
||||||
const FEEDBACK_SUBMITTED_KEY = "budibase:feedback_submitted"
|
|
||||||
const APP_FIRST_STARTED_KEY = "budibase:first_run"
|
|
||||||
const feedbackHours = 12
|
|
||||||
|
|
||||||
async function activate() {
|
|
||||||
if (analyticsEnabled === undefined) {
|
|
||||||
// only the server knows the true NODE_ENV
|
|
||||||
// this was an issue as NODE_ENV = 'cypress' on the server,
|
|
||||||
// but 'production' on the client
|
|
||||||
const response = await api.get("/api/analytics")
|
|
||||||
analyticsEnabled = (await response.json()).enabled === true
|
|
||||||
}
|
|
||||||
if (!analyticsEnabled) return
|
|
||||||
if (sentryConfigured) Sentry.init({ dsn: process.env.SENTRY_DSN })
|
|
||||||
if (posthogConfigured) {
|
|
||||||
posthog.init(process.env.POSTHOG_TOKEN, {
|
|
||||||
autocapture: false,
|
|
||||||
capture_pageview: false,
|
|
||||||
api_host: process.env.POSTHOG_URL,
|
|
||||||
})
|
|
||||||
posthog.set_config({ persistence: "cookie" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function identify(id) {
|
|
||||||
if (!analyticsEnabled || !id) return
|
|
||||||
if (posthogConfigured) posthog.identify(id)
|
|
||||||
if (sentryConfigured)
|
|
||||||
Sentry.configureScope(scope => {
|
|
||||||
scope.setUser({ id: id })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function identifyByApiKey(apiKey) {
|
|
||||||
if (!analyticsEnabled) return true
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`https://03gaine137.execute-api.eu-west-1.amazonaws.com/prod/account/id?api_key=${apiKey.trim()}`
|
|
||||||
)
|
|
||||||
if (response.status === 200) {
|
|
||||||
const id = await response.json()
|
|
||||||
|
|
||||||
await api.put("/api/keys/userId", { value: id })
|
|
||||||
identify(id)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function captureException(err) {
|
|
||||||
if (!analyticsEnabled) return
|
|
||||||
Sentry.captureException(err)
|
|
||||||
captureEvent("Error", { error: err.message ? err.message : err })
|
|
||||||
}
|
|
||||||
|
|
||||||
function captureEvent(eventName, props = {}) {
|
|
||||||
if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return
|
|
||||||
props.sourceApp = "builder"
|
|
||||||
posthog.capture(eventName, props)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!localStorage.getItem(APP_FIRST_STARTED_KEY)) {
|
|
||||||
localStorage.setItem(APP_FIRST_STARTED_KEY, Date.now())
|
|
||||||
}
|
|
||||||
|
|
||||||
const isFeedbackTimeElapsed = sinceDateStr => {
|
|
||||||
const sinceDate = parseFloat(sinceDateStr)
|
|
||||||
const feedbackMilliseconds = feedbackHours * 60 * 60 * 1000
|
|
||||||
return Date.now() > sinceDate + feedbackMilliseconds
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitFeedback(values) {
|
|
||||||
if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return
|
|
||||||
localStorage.setItem(FEEDBACK_SUBMITTED_KEY, Date.now())
|
|
||||||
|
|
||||||
const prefixedValues = Object.entries(values).reduce((obj, [key, value]) => {
|
|
||||||
obj[`feedback_${key}`] = value
|
|
||||||
return obj
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
posthog.capture("Feedback Submitted", prefixedValues)
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestFeedbackOnDeploy() {
|
|
||||||
if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return false
|
|
||||||
const lastSubmittedStr = localStorage.getItem(FEEDBACK_SUBMITTED_KEY)
|
|
||||||
if (!lastSubmittedStr) return true
|
|
||||||
return isFeedbackTimeElapsed(lastSubmittedStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
function highlightFeedbackIcon() {
|
|
||||||
if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return false
|
|
||||||
const lastSubmittedStr = localStorage.getItem(FEEDBACK_SUBMITTED_KEY)
|
|
||||||
if (lastSubmittedStr) return isFeedbackTimeElapsed(lastSubmittedStr)
|
|
||||||
const firstRunStr = localStorage.getItem(APP_FIRST_STARTED_KEY)
|
|
||||||
if (!firstRunStr) return false
|
|
||||||
return isFeedbackTimeElapsed(firstRunStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opt In/Out
|
|
||||||
const ifAnalyticsEnabled = func => () => {
|
|
||||||
if (analyticsEnabled && process.env.POSTHOG_TOKEN) {
|
|
||||||
return func()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const disabled = () => posthog.has_opted_out_capturing()
|
|
||||||
const optIn = () => posthog.opt_in_capturing()
|
|
||||||
const optOut = () => posthog.opt_out_capturing()
|
|
||||||
|
|
||||||
export default {
|
|
||||||
activate,
|
|
||||||
identify,
|
|
||||||
identifyByApiKey,
|
|
||||||
captureException,
|
|
||||||
captureEvent,
|
|
||||||
requestFeedbackOnDeploy,
|
|
||||||
submitFeedback,
|
|
||||||
highlightFeedbackIcon,
|
|
||||||
disabled: () => {
|
|
||||||
if (analyticsEnabled == null) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return ifAnalyticsEnabled(disabled)
|
|
||||||
},
|
|
||||||
optIn: ifAnalyticsEnabled(optIn),
|
|
||||||
optOut: ifAnalyticsEnabled(optOut),
|
|
||||||
}
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
export default class IntercomClient {
|
||||||
|
constructor(token) {
|
||||||
|
this.token = token
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate intercom using their provided script.
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
if (!this.token) return
|
||||||
|
|
||||||
|
const token = this.token
|
||||||
|
|
||||||
|
var w = window
|
||||||
|
var ic = w.Intercom
|
||||||
|
if (typeof ic === "function") {
|
||||||
|
ic("reattach_activator")
|
||||||
|
ic("update", w.intercomSettings)
|
||||||
|
} else {
|
||||||
|
var d = document
|
||||||
|
var i = function () {
|
||||||
|
i.c(arguments)
|
||||||
|
}
|
||||||
|
i.q = []
|
||||||
|
i.c = function (args) {
|
||||||
|
i.q.push(args)
|
||||||
|
}
|
||||||
|
w.Intercom = i
|
||||||
|
var l = function () {
|
||||||
|
var s = d.createElement("script")
|
||||||
|
s.type = "text/javascript"
|
||||||
|
s.async = true
|
||||||
|
s.src = "https://widget.intercom.io/widget/" + token
|
||||||
|
var x = d.getElementsByTagName("script")[0]
|
||||||
|
x.parentNode.insertBefore(s, x)
|
||||||
|
}
|
||||||
|
if (document.readyState === "complete") {
|
||||||
|
l()
|
||||||
|
} else if (w.attachEvent) {
|
||||||
|
w.attachEvent("onload", l)
|
||||||
|
} else {
|
||||||
|
w.addEventListener("load", l, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialised = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the intercom chat bubble.
|
||||||
|
* @param {Object} user - user to identify
|
||||||
|
* @returns Intercom global object
|
||||||
|
*/
|
||||||
|
show(user = {}) {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
return window.Intercom("boot", {
|
||||||
|
app_id: this.token,
|
||||||
|
...user,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update intercom user details and messages.
|
||||||
|
* @returns Intercom global object
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
return window.Intercom("update")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture analytics events and send them to intercom.
|
||||||
|
* @param {String} event - event identifier
|
||||||
|
* @param {Object} props - properties for the event
|
||||||
|
* @returns Intercom global object
|
||||||
|
*/
|
||||||
|
captureEvent(event, props = {}) {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
return window.Intercom("trackEvent", event, props)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disassociate the user from the current session.
|
||||||
|
* @returns Intercom global object
|
||||||
|
*/
|
||||||
|
logout() {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
return window.Intercom("shutdown")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
import posthog from "posthog-js"
|
||||||
|
import { Events } from "./constants"
|
||||||
|
|
||||||
|
export default class PosthogClient {
|
||||||
|
constructor(token, url) {
|
||||||
|
this.token = token
|
||||||
|
this.url = url
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
if (!this.token || !this.url) return
|
||||||
|
|
||||||
|
posthog.init(this.token, {
|
||||||
|
autocapture: false,
|
||||||
|
capture_pageview: false,
|
||||||
|
api_host: this.url,
|
||||||
|
})
|
||||||
|
posthog.set_config({ persistence: "cookie" })
|
||||||
|
|
||||||
|
this.initialised = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the posthog context to the current user
|
||||||
|
* @param {String} id - unique user id
|
||||||
|
*/
|
||||||
|
identify(id) {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
posthog.identify(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update user metadata associated with current user in posthog
|
||||||
|
* @param {Object} meta - user fields
|
||||||
|
*/
|
||||||
|
updateUser(meta) {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
posthog.people.set(meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture analytics events and send them to posthog.
|
||||||
|
* @param {String} event - event identifier
|
||||||
|
* @param {Object} props - properties for the event
|
||||||
|
*/
|
||||||
|
captureEvent(eventName, props) {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
props.sourceApp = "builder"
|
||||||
|
posthog.capture(eventName, props)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit NPS feedback to posthog.
|
||||||
|
* @param {Object} values - NPS Values
|
||||||
|
*/
|
||||||
|
npsFeedback(values) {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
localStorage.setItem(Events.NPS.SUBMITTED, Date.now())
|
||||||
|
|
||||||
|
const prefixedFeedback = {}
|
||||||
|
for (let key in values) {
|
||||||
|
prefixedFeedback[`feedback_${key}`] = values[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
posthog.capture(Events.NPS.SUBMITTED, prefixedFeedback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset posthog user back to initial state on logout.
|
||||||
|
*/
|
||||||
|
logout() {
|
||||||
|
if (!this.initialised) return
|
||||||
|
|
||||||
|
posthog.reset()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import * as Sentry from "@sentry/browser"
|
||||||
|
|
||||||
|
export default class SentryClient {
|
||||||
|
constructor(dsn) {
|
||||||
|
this.dsn = dsn
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
if (this.dsn) {
|
||||||
|
Sentry.init({ dsn: this.dsn })
|
||||||
|
|
||||||
|
this.initalised = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture an exception and send it to sentry.
|
||||||
|
* @param {Error} err - JS error object
|
||||||
|
*/
|
||||||
|
captureException(err) {
|
||||||
|
if (!this.initalised) return
|
||||||
|
|
||||||
|
Sentry.captureException(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify user in sentry.
|
||||||
|
* @param {String} id - Unique user id
|
||||||
|
*/
|
||||||
|
identify(id) {
|
||||||
|
if (!this.initalised) return
|
||||||
|
|
||||||
|
Sentry.configureScope(scope => {
|
||||||
|
scope.setUser({ id })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
export const Events = {
|
||||||
|
BUILDER: {
|
||||||
|
STARTED: "Builder Started",
|
||||||
|
},
|
||||||
|
COMPONENT: {
|
||||||
|
CREATED: "Added Component",
|
||||||
|
},
|
||||||
|
DATASOURCE: {
|
||||||
|
CREATED: "Datasource Created",
|
||||||
|
UPDATED: "Datasource Updated",
|
||||||
|
},
|
||||||
|
TABLE: {
|
||||||
|
CREATED: "Table Created",
|
||||||
|
},
|
||||||
|
VIEW: {
|
||||||
|
CREATED: "View Created",
|
||||||
|
ADDED_FILTER: "Added View Filter",
|
||||||
|
ADDED_CALCULATE: "Added View Calculate",
|
||||||
|
},
|
||||||
|
SCREEN: {
|
||||||
|
CREATED: "Screen Created",
|
||||||
|
},
|
||||||
|
AUTOMATION: {
|
||||||
|
CREATED: "Automation Created",
|
||||||
|
SAVED: "Automation Saved",
|
||||||
|
BLOCK_ADDED: "Added Automation Block",
|
||||||
|
},
|
||||||
|
NPS: {
|
||||||
|
SUBMITTED: "budibase:feedback_submitted",
|
||||||
|
},
|
||||||
|
APP: {
|
||||||
|
CREATED: "budibase:app_created",
|
||||||
|
PUBLISHED: "budibase:app_published",
|
||||||
|
UNPUBLISHED: "budibase:app_unpublished",
|
||||||
|
},
|
||||||
|
ANALYTICS: {
|
||||||
|
OPT_IN: "budibase:analytics_opt_in",
|
||||||
|
OPT_OUT: "budibase:analytics_opt_out",
|
||||||
|
},
|
||||||
|
USER: {
|
||||||
|
INVITE: "budibase:portal_user_invite",
|
||||||
|
},
|
||||||
|
SMTP: {
|
||||||
|
SAVED: "budibase:smtp_saved",
|
||||||
|
},
|
||||||
|
SSO: {
|
||||||
|
SAVED: "budibase:sso_saved",
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
import api from "builderStore/api"
|
||||||
|
import PosthogClient from "./PosthogClient"
|
||||||
|
import IntercomClient from "./IntercomClient"
|
||||||
|
import SentryClient from "./SentryClient"
|
||||||
|
import { Events } from "./constants"
|
||||||
|
import { auth } from "stores/portal"
|
||||||
|
import { get } from "svelte/store"
|
||||||
|
|
||||||
|
const posthog = new PosthogClient(
|
||||||
|
process.env.POSTHOG_TOKEN,
|
||||||
|
process.env.POSTHOG_URL
|
||||||
|
)
|
||||||
|
const sentry = new SentryClient(process.env.SENTRY_DSN)
|
||||||
|
const intercom = new IntercomClient(process.env.INTERCOM_TOKEN)
|
||||||
|
|
||||||
|
class AnalyticsHub {
|
||||||
|
constructor() {
|
||||||
|
this.clients = [posthog, sentry, intercom]
|
||||||
|
}
|
||||||
|
|
||||||
|
async activate() {
|
||||||
|
// Setting the analytics env var off in the backend overrides org/tenant settings
|
||||||
|
const analyticsStatus = await api.get("/api/analytics")
|
||||||
|
const json = await analyticsStatus.json()
|
||||||
|
|
||||||
|
// Multitenancy disabled on the backend
|
||||||
|
if (!json.enabled) return
|
||||||
|
|
||||||
|
const tenantId = get(auth).tenantId
|
||||||
|
|
||||||
|
if (tenantId) {
|
||||||
|
const res = await api.get(
|
||||||
|
`/api/global/configs/public?tenantId=${tenantId}`
|
||||||
|
)
|
||||||
|
const orgJson = await res.json()
|
||||||
|
|
||||||
|
// analytics opted out for the tenant
|
||||||
|
if (orgJson.config?.analytics === false) return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.clients.forEach(client => client.init())
|
||||||
|
this.enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
identify(id, metadata) {
|
||||||
|
posthog.identify(id)
|
||||||
|
if (metadata) {
|
||||||
|
posthog.updateUser(metadata)
|
||||||
|
}
|
||||||
|
sentry.identify(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
captureException(err) {
|
||||||
|
sentry.captureException(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
captureEvent(eventName, props = {}) {
|
||||||
|
posthog.captureEvent(eventName, props)
|
||||||
|
intercom.captureEvent(eventName, props)
|
||||||
|
}
|
||||||
|
|
||||||
|
showChat(user) {
|
||||||
|
intercom.show(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
submitFeedback(values) {
|
||||||
|
posthog.npsFeedback(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
async logout() {
|
||||||
|
posthog.logout()
|
||||||
|
intercom.logout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const analytics = new AnalyticsHub()
|
||||||
|
|
||||||
|
export { Events }
|
||||||
|
export default analytics
|
|
@ -3,7 +3,6 @@ import { getAutomationStore } from "./store/automation"
|
||||||
import { getHostingStore } from "./store/hosting"
|
import { getHostingStore } from "./store/hosting"
|
||||||
import { getThemeStore } from "./store/theme"
|
import { getThemeStore } from "./store/theme"
|
||||||
import { derived, writable } from "svelte/store"
|
import { derived, writable } from "svelte/store"
|
||||||
import analytics from "analytics"
|
|
||||||
import { FrontendTypes, LAYOUT_NAMES } from "../constants"
|
import { FrontendTypes, LAYOUT_NAMES } from "../constants"
|
||||||
import { findComponent } from "./storeUtils"
|
import { findComponent } from "./storeUtils"
|
||||||
|
|
||||||
|
@ -55,13 +54,4 @@ export const mainLayout = derived(store, $store => {
|
||||||
|
|
||||||
export const selectedAccessRole = writable("BASIC")
|
export const selectedAccessRole = writable("BASIC")
|
||||||
|
|
||||||
export const initialise = async () => {
|
|
||||||
try {
|
|
||||||
await analytics.activate()
|
|
||||||
analytics.captureEvent("Builder Started")
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const screenSearchString = writable(null)
|
export const screenSearchString = writable(null)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { writable } from "svelte/store"
|
||||||
import api from "../../api"
|
import api from "../../api"
|
||||||
import Automation from "./Automation"
|
import Automation from "./Automation"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
const automationActions = store => ({
|
const automationActions = store => ({
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
|
@ -110,7 +110,7 @@ const automationActions = store => ({
|
||||||
state.selectedBlock = newBlock
|
state.selectedBlock = newBlock
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
analytics.captureEvent("Added Automation Block", {
|
analytics.captureEvent(Events.AUTOMATION.BLOCK_ADDED, {
|
||||||
name: block.name,
|
name: block.name,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
import { fetchComponentLibDefinitions } from "../loadComponentLibraries"
|
import { fetchComponentLibDefinitions } from "../loadComponentLibraries"
|
||||||
import api from "../api"
|
import api from "../api"
|
||||||
import { FrontendTypes } from "constants"
|
import { FrontendTypes } from "constants"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
import {
|
import {
|
||||||
findComponentType,
|
findComponentType,
|
||||||
findComponentParent,
|
findComponentParent,
|
||||||
|
@ -443,7 +443,7 @@ export const getFrontendStore = () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Log event
|
// Log event
|
||||||
analytics.captureEvent("Added Component", {
|
analytics.captureEvent(Events.COMPONENT.CREATED, {
|
||||||
name: componentInstance._component,
|
name: componentInstance._component,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
import { notifications } from "@budibase/bbui"
|
import { notifications } from "@budibase/bbui"
|
||||||
import { Input, ModalContent, Layout, Body, Icon } from "@budibase/bbui"
|
import { Input, ModalContent, Layout, Body, Icon } from "@budibase/bbui"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
let name
|
let name
|
||||||
let selectedTrigger
|
let selectedTrigger
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
notifications.success(`Automation ${name} created.`)
|
notifications.success(`Automation ${name} created.`)
|
||||||
|
|
||||||
$goto(`./${$automationStore.selectedAutomation.automation._id}`)
|
$goto(`./${$automationStore.selectedAutomation.automation._id}`)
|
||||||
analytics.captureEvent("Automation Created", { name })
|
analytics.captureEvent(Events.AUTOMATION.CREATED, { name })
|
||||||
}
|
}
|
||||||
$: triggers = Object.entries($automationStore.blockDefinitions.TRIGGER)
|
$: triggers = Object.entries($automationStore.blockDefinitions.TRIGGER)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
import { notifications } from "@budibase/bbui"
|
import { notifications } from "@budibase/bbui"
|
||||||
import { Icon, Input, ModalContent, Modal } from "@budibase/bbui"
|
import { Icon, Input, ModalContent, Modal } from "@budibase/bbui"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
let name
|
let name
|
||||||
let error = ""
|
let error = ""
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
}
|
}
|
||||||
await automationStore.actions.save(updatedAutomation)
|
await automationStore.actions.save(updatedAutomation)
|
||||||
notifications.success(`Automation ${name} updated successfully.`)
|
notifications.success(`Automation ${name} updated successfully.`)
|
||||||
analytics.captureEvent("Automation Saved", { name })
|
analytics.captureEvent(Events.AUTOMATION.SAVED, { name })
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { Select, Label, notifications, ModalContent } from "@budibase/bbui"
|
import { Select, Label, notifications, ModalContent } from "@budibase/bbui"
|
||||||
import { tables, views } from "stores/backend"
|
import { tables, views } from "stores/backend"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
import { FIELDS } from "constants/backend"
|
import { FIELDS } from "constants/backend"
|
||||||
|
|
||||||
const CALCULATIONS = [
|
const CALCULATIONS = [
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
function saveView() {
|
function saveView() {
|
||||||
views.save(view)
|
views.save(view)
|
||||||
notifications.success(`View ${view.name} saved.`)
|
notifications.success(`View ${view.name} saved.`)
|
||||||
analytics.captureEvent("Added View Calculate", { field: view.field })
|
analytics.captureEvent(Events.VIEW.ADDED_CALCULATE, { field: view.field })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { views as viewsStore } from "stores/backend"
|
import { views as viewsStore } from "stores/backend"
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
let name
|
let name
|
||||||
let field
|
let field
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
field,
|
field,
|
||||||
})
|
})
|
||||||
notifications.success(`View ${name} created`)
|
notifications.success(`View ${name} created`)
|
||||||
analytics.captureEvent("View Created", { name })
|
analytics.captureEvent(Events.VIEW.CREATED, { name })
|
||||||
$goto(`../../view/${name}`)
|
$goto(`../../view/${name}`)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
Icon,
|
Icon,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { tables, views } from "stores/backend"
|
import { tables, views } from "stores/backend"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
const CONDITIONS = [
|
const CONDITIONS = [
|
||||||
{
|
{
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
function saveView() {
|
function saveView() {
|
||||||
views.save(view)
|
views.save(view)
|
||||||
notifications.success(`View ${view.name} saved.`)
|
notifications.success(`View ${view.name} saved.`)
|
||||||
analytics.captureEvent("Added View Filter", {
|
analytics.captureEvent(Events.VIEW.ADDED_FILTER, {
|
||||||
filters: JSON.stringify(view.filters),
|
filters: JSON.stringify(view.filters),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import { Input, Label, ModalContent, Modal, Context } from "@budibase/bbui"
|
import { Input, Label, ModalContent, Modal, Context } from "@budibase/bbui"
|
||||||
import TableIntegrationMenu from "../TableIntegrationMenu/index.svelte"
|
import TableIntegrationMenu from "../TableIntegrationMenu/index.svelte"
|
||||||
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte"
|
import CreateTableModal from "components/backend/TableNavigator/modals/CreateTableModal.svelte"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
const modalContext = getContext(Context.Modal)
|
const modalContext = getContext(Context.Modal)
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
plus,
|
plus,
|
||||||
})
|
})
|
||||||
notifications.success(`Datasource ${name} created successfully.`)
|
notifications.success(`Datasource ${name} created successfully.`)
|
||||||
analytics.captureEvent("Datasource Created", { name, type })
|
analytics.captureEvent(Events.DATASOURCE.CREATED, { name, type })
|
||||||
|
|
||||||
// Navigate to new datasource
|
// Navigate to new datasource
|
||||||
$goto(`./datasource/${response._id}`)
|
$goto(`./datasource/${response._id}`)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { datasources } from "stores/backend"
|
import { datasources } from "stores/backend"
|
||||||
import { notifications } from "@budibase/bbui"
|
import { notifications } from "@budibase/bbui"
|
||||||
import { Input, ModalContent, Modal } from "@budibase/bbui"
|
import { Input, ModalContent, Modal } from "@budibase/bbui"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
let error = ""
|
let error = ""
|
||||||
let modal
|
let modal
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
}
|
}
|
||||||
await datasources.save(updatedDatasource)
|
await datasources.save(updatedDatasource)
|
||||||
notifications.success(`Datasource ${name} updated successfully.`)
|
notifications.success(`Datasource ${name} updated successfully.`)
|
||||||
analytics.captureEvent("Datasource Updated", updatedDatasource)
|
analytics.captureEvent(Events.DATASOURCE.UPDATED, updatedDatasource)
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
Layout,
|
Layout,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import TableDataImport from "../TableDataImport.svelte"
|
import TableDataImport from "../TableDataImport.svelte"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
import screenTemplates from "builderStore/store/screenTemplates"
|
import screenTemplates from "builderStore/store/screenTemplates"
|
||||||
import { buildAutoColumn, getAutoColumnInformation } from "builderStore/utils"
|
import { buildAutoColumn, getAutoColumnInformation } from "builderStore/utils"
|
||||||
import { NEW_ROW_TEMPLATE } from "builderStore/store/screenTemplates/newRowScreen"
|
import { NEW_ROW_TEMPLATE } from "builderStore/store/screenTemplates/newRowScreen"
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
// Create table
|
// Create table
|
||||||
const table = await tables.save(newTable)
|
const table = await tables.save(newTable)
|
||||||
notifications.success(`Table ${name} created successfully.`)
|
notifications.success(`Table ${name} created successfully.`)
|
||||||
analytics.captureEvent("Table Created", { name })
|
analytics.captureEvent(Events.TABLE.CREATED, { name })
|
||||||
|
|
||||||
// Create auto screens
|
// Create auto screens
|
||||||
if (createAutoscreens) {
|
if (createAutoscreens) {
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
import { onMount, onDestroy } from "svelte"
|
import { onMount, onDestroy } from "svelte"
|
||||||
import { Button, Modal, notifications, ModalContent } from "@budibase/bbui"
|
import { Button, Modal, notifications, ModalContent } from "@budibase/bbui"
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
|
||||||
const DeploymentStatus = {
|
const DeploymentStatus = {
|
||||||
SUCCESS: "SUCCESS",
|
SUCCESS: "SUCCESS",
|
||||||
|
@ -23,6 +24,9 @@
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
throw new Error(`status ${response.status}`)
|
throw new Error(`status ${response.status}`)
|
||||||
} else {
|
} else {
|
||||||
|
analytics.captureEvent(Events.APP.PUBLISHED, {
|
||||||
|
appId: $store.appId,
|
||||||
|
})
|
||||||
notifications.success(`Application published successfully`)
|
notifications.success(`Application published successfully`)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import { roles } from "stores/backend"
|
import { roles } from "stores/backend"
|
||||||
import { Input, Select, ModalContent, Toggle } from "@budibase/bbui"
|
import { Input, Select, ModalContent, Toggle } from "@budibase/bbui"
|
||||||
import getTemplates from "builderStore/store/screenTemplates"
|
import getTemplates from "builderStore/store/screenTemplates"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
const CONTAINER = "@budibase/standard-components/container"
|
const CONTAINER = "@budibase/standard-components/container"
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
if (templateIndex !== undefined) {
|
if (templateIndex !== undefined) {
|
||||||
const template = templates[templateIndex]
|
const template = templates[templateIndex]
|
||||||
analytics.captureEvent("Screen Created", {
|
analytics.captureEvent(Events.SCREEN.CREATED, {
|
||||||
template: template.id || template.name,
|
template: template.id || template.name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
import { admin } from "stores/portal"
|
import { admin } from "stores/portal"
|
||||||
import { string, mixed, object } from "yup"
|
import { string, mixed, object } from "yup"
|
||||||
import api, { get, post } from "builderStore/api"
|
import api, { get, post } from "builderStore/api"
|
||||||
import analytics from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { capitalise } from "helpers"
|
import { capitalise } from "helpers"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
|
@ -98,9 +98,9 @@
|
||||||
throw new Error(appJson.message)
|
throw new Error(appJson.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
analytics.captureEvent("App Created", {
|
analytics.captureEvent(Events.APP.CREATED, {
|
||||||
name: $values.name,
|
name: $values.name,
|
||||||
appId: appJson._id,
|
appId: appJson.instance._id,
|
||||||
template,
|
template,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
})
|
})
|
||||||
|
|
||||||
if ($auth?.user?.forceResetPassword) {
|
if ($auth?.user?.forceResetPassword) {
|
||||||
$goto("./reset")
|
$goto("./reset")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
||||||
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
||||||
import api, { del } from "builderStore/api"
|
import { del } from "builderStore/api"
|
||||||
import analytics from "analytics"
|
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { apps, auth, admin } from "stores/portal"
|
import { apps, auth, admin } from "stores/portal"
|
||||||
import download from "downloadjs"
|
import download from "downloadjs"
|
||||||
|
@ -66,14 +65,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkKeys = async () => {
|
|
||||||
const response = await api.get(`/api/keys/`)
|
|
||||||
const keys = await response.json()
|
|
||||||
if (keys.userId) {
|
|
||||||
analytics.identify(keys.userId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const initiateAppCreation = () => {
|
const initiateAppCreation = () => {
|
||||||
creationModal.show()
|
creationModal.show()
|
||||||
creatingApp = true
|
creatingApp = true
|
||||||
|
@ -188,7 +179,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
checkKeys()
|
|
||||||
await apps.load()
|
await apps.load()
|
||||||
loaded = true
|
loaded = true
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { organisation, auth, admin } from "stores/portal"
|
import { organisation, auth, admin } from "stores/portal"
|
||||||
import { uuid } from "builderStore/uuid"
|
import { uuid } from "builderStore/uuid"
|
||||||
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
$: tenantId = $auth.tenantId
|
$: tenantId = $auth.tenantId
|
||||||
$: multiTenancyEnabled = $admin.multiTenancy
|
$: multiTenancyEnabled = $admin.multiTenancy
|
||||||
|
@ -209,6 +210,7 @@
|
||||||
providers[res.type]._id = res._id
|
providers[res.type]._id = res._id
|
||||||
})
|
})
|
||||||
notifications.success(`Settings saved.`)
|
notifications.success(`Settings saved.`)
|
||||||
|
analytics.captureEvent(Events.SSO.SAVED)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
notifications.error(`Failed to update auth settings. ${err}`)
|
notifications.error(`Failed to update auth settings. ${err}`)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import { email } from "stores/portal"
|
import { email } from "stores/portal"
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
const ConfigTypes = {
|
const ConfigTypes = {
|
||||||
SMTP: "smtp",
|
SMTP: "smtp",
|
||||||
|
@ -69,6 +70,7 @@
|
||||||
smtpConfig._rev = json._rev
|
smtpConfig._rev = json._rev
|
||||||
smtpConfig._id = json._id
|
smtpConfig._id = json._id
|
||||||
notifications.success(`Settings saved.`)
|
notifications.success(`Settings saved.`)
|
||||||
|
analytics.captureEvent(Events.SMTP.SAVED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { createValidationStore, emailValidator } from "helpers/validation"
|
import { createValidationStore, emailValidator } from "helpers/validation"
|
||||||
import { users } from "stores/portal"
|
import { users } from "stores/portal"
|
||||||
|
import analytics, { Events } from "analytics"
|
||||||
|
|
||||||
export let disabled
|
export let disabled
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
notifications.error(res.message)
|
notifications.error(res.message)
|
||||||
} else {
|
} else {
|
||||||
notifications.success(res.message)
|
notifications.success(res.message)
|
||||||
|
analytics.captureEvent(Events.USER.INVITE, { type: selected })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const values = writable({
|
const values = writable({
|
||||||
analytics: !analytics.disabled(),
|
analytics: analytics.enabled,
|
||||||
company: $organisation.company,
|
company: $organisation.company,
|
||||||
platformUrl: $organisation.platformUrl,
|
platformUrl: $organisation.platformUrl,
|
||||||
logo: $organisation.logoUrl
|
logo: $organisation.logoUrl
|
||||||
|
@ -48,13 +48,6 @@
|
||||||
async function saveConfig() {
|
async function saveConfig() {
|
||||||
loading = true
|
loading = true
|
||||||
|
|
||||||
// Set analytics preference
|
|
||||||
if ($values.analytics) {
|
|
||||||
analytics.optIn()
|
|
||||||
} else {
|
|
||||||
analytics.optOut()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload logo if required
|
// Upload logo if required
|
||||||
if ($values.logo && !$values.logo.url) {
|
if ($values.logo && !$values.logo.url) {
|
||||||
await uploadLogo($values.logo)
|
await uploadLogo($values.logo)
|
||||||
|
@ -64,6 +57,7 @@
|
||||||
const config = {
|
const config = {
|
||||||
company: $values.company ?? "",
|
company: $values.company ?? "",
|
||||||
platformUrl: $values.platformUrl ?? "",
|
platformUrl: $values.platformUrl ?? "",
|
||||||
|
analytics: $values.analytics,
|
||||||
}
|
}
|
||||||
// remove logo if required
|
// remove logo if required
|
||||||
if (!$values.logo) {
|
if (!$values.logo) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { derived, writable, get } from "svelte/store"
|
import { derived, writable, get } from "svelte/store"
|
||||||
import api from "../../builderStore/api"
|
import api from "../../builderStore/api"
|
||||||
import { admin } from "stores/portal"
|
import { admin } from "stores/portal"
|
||||||
|
import analytics from "analytics"
|
||||||
|
|
||||||
export function createAuthStore() {
|
export function createAuthStore() {
|
||||||
const auth = writable({
|
const auth = writable({
|
||||||
|
@ -49,6 +50,21 @@ export function createAuthStore() {
|
||||||
}
|
}
|
||||||
return store
|
return store
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
analytics.activate().then(() => {
|
||||||
|
analytics.identify(user._id, user)
|
||||||
|
if (user.size === "100+" || user.size === "10000+") {
|
||||||
|
analytics.showChat({
|
||||||
|
email: user.email,
|
||||||
|
created_at: user.createdAt || Date.now(),
|
||||||
|
name: user.name,
|
||||||
|
user_id: user._id,
|
||||||
|
tenant: user.tenantId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setOrganisation(tenantId) {
|
async function setOrganisation(tenantId) {
|
||||||
|
|
|
@ -22,6 +22,9 @@ export default ({ mode }) => {
|
||||||
isProduction ? "production" : "development"
|
isProduction ? "production" : "development"
|
||||||
),
|
),
|
||||||
"process.env.POSTHOG_TOKEN": JSON.stringify(process.env.POSTHOG_TOKEN),
|
"process.env.POSTHOG_TOKEN": JSON.stringify(process.env.POSTHOG_TOKEN),
|
||||||
|
"process.env.INTERCOM_TOKEN": JSON.stringify(
|
||||||
|
process.env.INTERCOM_TOKEN
|
||||||
|
),
|
||||||
"process.env.POSTHOG_URL": JSON.stringify(process.env.POSTHOG_URL),
|
"process.env.POSTHOG_URL": JSON.stringify(process.env.POSTHOG_URL),
|
||||||
"process.env.SENTRY_DSN": JSON.stringify(process.env.SENTRY_DSN),
|
"process.env.SENTRY_DSN": JSON.stringify(process.env.SENTRY_DSN),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"postbuild": "copyfiles -u 1 src/**/*.svelte dist/ && copyfiles -u 1 src/**/*.hbs dist/ && copyfiles -u 1 src/**/*.json dist/",
|
"postbuild": "copyfiles -u 1 src/**/*.svelte dist/ && copyfiles -u 1 src/**/*.hbs dist/ && copyfiles -u 1 src/**/*.json dist/",
|
||||||
"test": "jest --coverage --maxWorkers=2",
|
"test": "jest --coverage --maxWorkers=2",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"predocker": "copyfiles -f ../client/dist/budibase-client.js ../client/manifest.json client",
|
"predocker": "copyfiles -f ../client/dist/budibase-client.js ../standard-components/manifest.json client",
|
||||||
"build:docker": "yarn run predocker && docker build . -t app-service",
|
"build:docker": "yarn run predocker && docker build . -t app-service",
|
||||||
"run:docker": "node dist/index.js",
|
"run:docker": "node dist/index.js",
|
||||||
"dev:stack:up": "node scripts/dev/manage.js up",
|
"dev:stack:up": "node scripts/dev/manage.js up",
|
||||||
|
@ -23,10 +23,9 @@
|
||||||
"format": "prettier --config ../../.prettierrc.json 'src/**/*.ts' --write",
|
"format": "prettier --config ../../.prettierrc.json 'src/**/*.ts' --write",
|
||||||
"lint": "eslint --fix src/",
|
"lint": "eslint --fix src/",
|
||||||
"lint:fix": "yarn run format && yarn run lint",
|
"lint:fix": "yarn run format && yarn run lint",
|
||||||
|
"initialise": "node scripts/initialise.js",
|
||||||
"multi:enable": "node scripts/multiTenancy.js enable",
|
"multi:enable": "node scripts/multiTenancy.js enable",
|
||||||
"multi:disable": "node scripts/multiTenancy.js disable",
|
"multi:disable": "node scripts/multiTenancy.js disable"
|
||||||
"selfhost:enable": "node scripts/selfhost.js enable",
|
|
||||||
"selfhost:disable": "node scripts/selfhost.js disable"
|
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"preset": "ts-jest",
|
"preset": "ts-jest",
|
||||||
|
@ -49,8 +48,7 @@
|
||||||
"!src/automations/tests/**/*",
|
"!src/automations/tests/**/*",
|
||||||
"!src/utilities/fileProcessor.js",
|
"!src/utilities/fileProcessor.js",
|
||||||
"!src/utilities/fileSystem/**/*",
|
"!src/utilities/fileSystem/**/*",
|
||||||
"!src/utilities/redis.js",
|
"!src/utilities/redis.js"
|
||||||
"!src/api/controllers/row/internalSearch.js"
|
|
||||||
],
|
],
|
||||||
"coverageReporters": [
|
"coverageReporters": [
|
||||||
"lcov",
|
"lcov",
|
||||||
|
@ -98,7 +96,7 @@
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"mongodb": "3.6.3",
|
"mongodb": "3.6.3",
|
||||||
"mssql": "6.2.3",
|
"mssql": "6.2.3",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "2.18.1",
|
||||||
"node-fetch": "2.6.0",
|
"node-fetch": "2.6.0",
|
||||||
"open": "7.3.0",
|
"open": "7.3.0",
|
||||||
"pg": "8.5.1",
|
"pg": "8.5.1",
|
||||||
|
|
|
@ -2,6 +2,6 @@ const env = require("../../environment")
|
||||||
|
|
||||||
exports.isEnabled = async function (ctx) {
|
exports.isEnabled = async function (ctx) {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
enabled: env.ENABLE_ANALYTICS === "true",
|
enabled: !env.SELF_HOSTED && env.ENABLE_ANALYTICS === "true",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ async function saveUser(
|
||||||
|
|
||||||
_id = _id || generateGlobalUserID()
|
_id = _id || generateGlobalUserID()
|
||||||
user = {
|
user = {
|
||||||
|
createdAt: Date.now(),
|
||||||
...dbUser,
|
...dbUser,
|
||||||
...user,
|
...user,
|
||||||
_id,
|
_id,
|
||||||
|
@ -148,6 +149,7 @@ exports.adminUser = async ctx => {
|
||||||
const user = {
|
const user = {
|
||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
|
createdAt: Date.now(),
|
||||||
roles: {},
|
roles: {},
|
||||||
builder: {
|
builder: {
|
||||||
global: true,
|
global: true,
|
||||||
|
|
Loading…
Reference in New Issue