Merge branch 'master' into test-speedup
This commit is contained in:
commit
5da775c2b8
|
@ -1,9 +1,12 @@
|
||||||
import posthog from "posthog-js"
|
import posthog from "posthog-js"
|
||||||
import { Events } from "./constants"
|
|
||||||
|
|
||||||
export default class PosthogClient {
|
export default class PosthogClient {
|
||||||
constructor(token) {
|
token: string
|
||||||
|
initialised: boolean
|
||||||
|
|
||||||
|
constructor(token: string) {
|
||||||
this.token = token
|
this.token = token
|
||||||
|
this.initialised = false
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
@ -12,6 +15,8 @@ export default class PosthogClient {
|
||||||
posthog.init(this.token, {
|
posthog.init(this.token, {
|
||||||
autocapture: false,
|
autocapture: false,
|
||||||
capture_pageview: false,
|
capture_pageview: false,
|
||||||
|
// disable by default
|
||||||
|
disable_session_recording: true,
|
||||||
})
|
})
|
||||||
posthog.set_config({ persistence: "cookie" })
|
posthog.set_config({ persistence: "cookie" })
|
||||||
|
|
||||||
|
@ -22,7 +27,7 @@ export default class PosthogClient {
|
||||||
* Set the posthog context to the current user
|
* Set the posthog context to the current user
|
||||||
* @param {String} id - unique user id
|
* @param {String} id - unique user id
|
||||||
*/
|
*/
|
||||||
identify(id) {
|
identify(id: string) {
|
||||||
if (!this.initialised) return
|
if (!this.initialised) return
|
||||||
|
|
||||||
posthog.identify(id)
|
posthog.identify(id)
|
||||||
|
@ -32,7 +37,7 @@ export default class PosthogClient {
|
||||||
* Update user metadata associated with current user in posthog
|
* Update user metadata associated with current user in posthog
|
||||||
* @param {Object} meta - user fields
|
* @param {Object} meta - user fields
|
||||||
*/
|
*/
|
||||||
updateUser(meta) {
|
updateUser(meta: Record<string, any>) {
|
||||||
if (!this.initialised) return
|
if (!this.initialised) return
|
||||||
|
|
||||||
posthog.people.set(meta)
|
posthog.people.set(meta)
|
||||||
|
@ -43,28 +48,22 @@ export default class PosthogClient {
|
||||||
* @param {String} event - event identifier
|
* @param {String} event - event identifier
|
||||||
* @param {Object} props - properties for the event
|
* @param {Object} props - properties for the event
|
||||||
*/
|
*/
|
||||||
captureEvent(eventName, props) {
|
captureEvent(event: string, props: Record<string, any>) {
|
||||||
if (!this.initialised) return
|
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)
|
props.sourceApp = "builder"
|
||||||
|
posthog.capture(event, props)
|
||||||
|
}
|
||||||
|
|
||||||
|
enableSessionRecording() {
|
||||||
|
if (!this.initialised) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
posthog.set_config({
|
||||||
|
disable_session_recording: false,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -31,6 +31,10 @@ class AnalyticsHub {
|
||||||
posthog.captureEvent(eventName, props)
|
posthog.captureEvent(eventName, props)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableSessionRecording() {
|
||||||
|
posthog.enableSessionRecording()
|
||||||
|
}
|
||||||
|
|
||||||
async logout() {
|
async logout() {
|
||||||
posthog.logout()
|
posthog.logout()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
SystemStatusResponse,
|
SystemStatusResponse,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { BudiStore } from "../BudiStore"
|
import { BudiStore } from "../BudiStore"
|
||||||
|
import Analytics from "../../analytics"
|
||||||
|
|
||||||
interface AdminState extends GetEnvironmentResponse {
|
interface AdminState extends GetEnvironmentResponse {
|
||||||
loaded: boolean
|
loaded: boolean
|
||||||
|
@ -33,6 +34,8 @@ export class AdminStore extends BudiStore<AdminState> {
|
||||||
await this.getEnvironment()
|
await this.getEnvironment()
|
||||||
// enable system status checks in the cloud
|
// enable system status checks in the cloud
|
||||||
if (get(this.store).cloud) {
|
if (get(this.store).cloud) {
|
||||||
|
// in cloud allow this
|
||||||
|
Analytics.enableSessionRecording()
|
||||||
await this.getSystemStatus()
|
await this.getSystemStatus()
|
||||||
this.checkStatus()
|
this.checkStatus()
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ export const HelperFunctionNames = {
|
||||||
ALL: "all",
|
ALL: "all",
|
||||||
LITERAL: "literal",
|
LITERAL: "literal",
|
||||||
JS: "js",
|
JS: "js",
|
||||||
|
DECODE_ID: "decodeId",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LITERAL_MARKER = "%LITERAL%"
|
export const LITERAL_MARKER = "%LITERAL%"
|
||||||
|
|
|
@ -25,13 +25,29 @@ function isObject(value: string | any[]) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const HELPERS = [
|
export const HELPERS = [
|
||||||
// external helpers
|
// external helpers
|
||||||
new Helper(HelperFunctionNames.OBJECT, (value: any) => {
|
new Helper(HelperFunctionNames.OBJECT, (value: any) => {
|
||||||
return new Handlebars.SafeString(JSON.stringify(value))
|
return new Handlebars.SafeString(JSON.stringify(value))
|
||||||
}),
|
}),
|
||||||
// javascript helper
|
// javascript helper
|
||||||
new Helper(HelperFunctionNames.JS, processJS, false),
|
new Helper(HelperFunctionNames.JS, processJS, false),
|
||||||
|
new Helper(HelperFunctionNames.DECODE_ID, (_id: string | { _id: string }) => {
|
||||||
|
if (!_id) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
// have to replace on the way back as we swapped out the double quotes
|
||||||
|
// when encoding, but JSON can't handle the single quotes
|
||||||
|
const id = typeof _id === "string" ? _id : _id._id
|
||||||
|
const decoded: string = decodeURIComponent(id).replace(/'/g, '"')
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(decoded)
|
||||||
|
return Array.isArray(parsed) ? parsed : [parsed]
|
||||||
|
} catch (err) {
|
||||||
|
// wasn't json - likely was handlebars for a many to many
|
||||||
|
return [_id]
|
||||||
|
}
|
||||||
|
}),
|
||||||
// this help is applied to all statements
|
// this help is applied to all statements
|
||||||
new Helper(
|
new Helper(
|
||||||
HelperFunctionNames.ALL,
|
HelperFunctionNames.ALL,
|
||||||
|
|
|
@ -517,3 +517,44 @@ describe("helper overlap", () => {
|
||||||
expect(output).toEqual("a")
|
expect(output).toEqual("a")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("Test the decodeId helper", () => {
|
||||||
|
it("should decode a valid encoded ID", async () => {
|
||||||
|
const encodedId = encodeURIComponent("[42]") // "%5B42%5D"
|
||||||
|
const output = await processString("{{ decodeId id }}", { id: encodedId })
|
||||||
|
expect(output).toBe("42")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should return an unchanged string if the string isn't encoded", async () => {
|
||||||
|
const unencodedId = "forty-two"
|
||||||
|
const output = await processString("{{ decodeId id }}", { id: unencodedId })
|
||||||
|
expect(output).toBe("forty-two")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should return a string of comma-separated IDs when passed multiple IDs in a URI encoded array", async () => {
|
||||||
|
const encodedIds = encodeURIComponent("[1,2,3]") // "%5B1%2C2%2C3%5D"
|
||||||
|
const output = await processString("{{ decodeId id }}", { id: encodedIds })
|
||||||
|
expect(output).toBe("1,2,3")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Handles empty array gracefully", async () => {
|
||||||
|
const output = await processString("{{ decodeId value }}", {
|
||||||
|
value: [],
|
||||||
|
})
|
||||||
|
expect(output).toBe("[[]]")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Handles undefined gracefully", async () => {
|
||||||
|
const output = await processString("{{ decodeId value }}", {
|
||||||
|
value: undefined,
|
||||||
|
})
|
||||||
|
expect(output).toBe("")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Handles null gracefully", async () => {
|
||||||
|
const output = await processString("{{ decodeId value }}", {
|
||||||
|
value: undefined,
|
||||||
|
})
|
||||||
|
expect(output).toBe("")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in New Issue