Merge branch 'develop' into Cypress
This commit is contained in:
commit
ad0bba5fc2
41 changed files with 3629 additions and 1637 deletions
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/backend-core",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Budibase backend core libraries used in server and worker",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
|
@ -23,7 +23,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@budibase/nano": "10.1.1",
|
||||
"@budibase/types": "2.2.12-alpha.50",
|
||||
"@budibase/types": "2.2.12-alpha.52",
|
||||
"@shopify/jest-koa-mocks": "5.0.1",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
"aws-cloudfront-sign": "2.2.0",
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
UserPermissionAssignedEvent,
|
||||
UserPermissionRemovedEvent,
|
||||
UserUpdatedEvent,
|
||||
UserOnboardingEvent,
|
||||
} from "@budibase/types"
|
||||
|
||||
async function created(user: User, timestamp?: number) {
|
||||
|
@ -36,6 +37,13 @@ async function deleted(user: User) {
|
|||
await publishEvent(Event.USER_DELETED, properties)
|
||||
}
|
||||
|
||||
export async function onboardingComplete(user: User) {
|
||||
const properties: UserOnboardingEvent = {
|
||||
userId: user._id as string,
|
||||
}
|
||||
await publishEvent(Event.USER_ONBOARDING_COMPLETE, properties)
|
||||
}
|
||||
|
||||
// PERMISSIONS
|
||||
|
||||
async function permissionAdminAssigned(user: User, timestamp?: number) {
|
||||
|
@ -126,6 +134,7 @@ export default {
|
|||
permissionAdminRemoved,
|
||||
permissionBuilderAssigned,
|
||||
permissionBuilderRemoved,
|
||||
onboardingComplete,
|
||||
invited,
|
||||
inviteAccepted,
|
||||
passwordForceReset,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/bbui",
|
||||
"description": "A UI solution used in the different Budibase projects.",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"module": "dist/bbui.es.js",
|
||||
|
@ -38,7 +38,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
||||
"@budibase/string-templates": "2.2.12-alpha.50",
|
||||
"@budibase/string-templates": "2.2.12-alpha.52",
|
||||
"@spectrum-css/accordion": "3.0.24",
|
||||
"@spectrum-css/actionbutton": "1.0.1",
|
||||
"@spectrum-css/actiongroup": "1.0.1",
|
||||
|
|
|
@ -3,6 +3,9 @@ export default function positionDropdown(
|
|||
{ anchor, align, maxWidth, useAnchorWidth }
|
||||
) {
|
||||
const update = () => {
|
||||
if (!anchor) {
|
||||
return
|
||||
}
|
||||
const anchorBounds = anchor.getBoundingClientRect()
|
||||
const elementBounds = element.getBoundingClientRect()
|
||||
let styles = {
|
||||
|
@ -13,6 +16,8 @@ export default function positionDropdown(
|
|||
top: null,
|
||||
}
|
||||
|
||||
let popoverLeftPad = 20
|
||||
|
||||
// Determine vertical styles
|
||||
if (window.innerHeight - anchorBounds.bottom < 100) {
|
||||
styles.top = anchorBounds.top - elementBounds.height - 5
|
||||
|
@ -29,7 +34,13 @@ export default function positionDropdown(
|
|||
styles.minWidth = anchorBounds.width
|
||||
}
|
||||
if (align === "right") {
|
||||
styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
|
||||
let left =
|
||||
anchorBounds.left + anchorBounds.width / 2 - elementBounds.width
|
||||
// Accommodate margin on popover: 1.25rem; ~20px
|
||||
if (left + elementBounds.width + popoverLeftPad > window.innerWidth) {
|
||||
left -= 20
|
||||
}
|
||||
styles.left = left
|
||||
} else if (align === "right-side") {
|
||||
styles.left = anchorBounds.left + anchorBounds.width
|
||||
} else {
|
||||
|
@ -54,8 +65,11 @@ export default function positionDropdown(
|
|||
const resizeObserver = new ResizeObserver(entries => {
|
||||
entries.forEach(update)
|
||||
})
|
||||
if (anchor) {
|
||||
resizeObserver.observe(anchor)
|
||||
}
|
||||
resizeObserver.observe(element)
|
||||
resizeObserver.observe(document.body)
|
||||
|
||||
document.addEventListener("scroll", update, true)
|
||||
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
export let tooltip = undefined
|
||||
export let dataCy
|
||||
export let newStyles = true
|
||||
export let id
|
||||
|
||||
let showTooltip = false
|
||||
</script>
|
||||
|
||||
<button
|
||||
{id}
|
||||
class:spectrum-Button--cta={cta}
|
||||
class:spectrum-Button--primary={primary}
|
||||
class:spectrum-Button--secondary={secondary}
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
export let showTip = false
|
||||
export let open = false
|
||||
export let useAnchorWidth = false
|
||||
|
||||
let tipSvg =
|
||||
'<svg xmlns="http://www.w3.org/svg/2000" width="23" height="12" class="spectrum-Popover-tip" > <path class="spectrum-Popover-tip-triangle" d="M 0.7071067811865476 0 L 11.414213562373096 10.707106781186548 L 22.121320343559645 0" /> </svg>'
|
||||
export let dismissible = true
|
||||
|
||||
$: tooltipClasses = showTip
|
||||
? `spectrum-Popover--withTip spectrum-Popover--${direction}`
|
||||
|
@ -67,9 +65,15 @@
|
|||
<Portal {target}>
|
||||
<div
|
||||
tabindex="0"
|
||||
use:positionDropdown={{ anchor, align, maxWidth, useAnchorWidth }}
|
||||
use:positionDropdown={{
|
||||
anchor,
|
||||
align,
|
||||
maxWidth,
|
||||
useAnchorWidth,
|
||||
showTip: false,
|
||||
}}
|
||||
use:clickOutside={{
|
||||
callback: handleOutsideClick,
|
||||
callback: dismissible ? handleOutsideClick : () => {},
|
||||
anchor,
|
||||
}}
|
||||
on:keydown={handleEscape}
|
||||
|
@ -78,10 +82,6 @@
|
|||
data-cy={dataCy}
|
||||
transition:fly|local={{ y: -20, duration: 200 }}
|
||||
>
|
||||
{#if showTip}
|
||||
{@html tipSvg}
|
||||
{/if}
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</Portal>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import Portal from "svelte-portal"
|
||||
export let title
|
||||
export let icon = ""
|
||||
export let id
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let selected = getContext("tab")
|
||||
|
@ -31,10 +32,7 @@
|
|||
$: {
|
||||
if ($selected.title === title && tab_internal) {
|
||||
if ($selected.info?.left !== tab_internal.getBoundingClientRect().left) {
|
||||
$selected = {
|
||||
...$selected,
|
||||
info: tab_internal.getBoundingClientRect(),
|
||||
}
|
||||
setTabInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +48,7 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
{id}
|
||||
bind:this={tab_internal}
|
||||
on:click={onClick}
|
||||
class:is-selected={$selected.title === title}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/builder",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -58,10 +58,13 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "2.2.12-alpha.50",
|
||||
"@budibase/client": "2.2.12-alpha.50",
|
||||
"@budibase/frontend-core": "2.2.12-alpha.50",
|
||||
"@budibase/string-templates": "2.2.12-alpha.50",
|
||||
"@budibase/bbui": "2.2.12-alpha.52",
|
||||
"@budibase/client": "2.2.12-alpha.52",
|
||||
"@budibase/frontend-core": "2.2.12-alpha.52",
|
||||
"@budibase/string-templates": "2.2.12-alpha.52",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||
"@sentry/browser": "5.19.1",
|
||||
"@spectrum-css/accordion": "^3.0.24",
|
||||
"@spectrum-css/page": "^3.0.1",
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import { routes } from "../.routify/routes"
|
||||
import { NotificationDisplay, BannerDisplay } from "@budibase/bbui"
|
||||
import { parse, stringify } from "qs"
|
||||
import HelpIcon from "components/common/HelpIcon.svelte"
|
||||
import LicensingOverlays from "components/portal/licensing/LicensingOverlays.svelte"
|
||||
|
||||
const queryHandler = { parse, stringify }
|
||||
|
@ -15,7 +14,6 @@
|
|||
<LicensingOverlays />
|
||||
<Router {routes} config={{ queryHandler }} />
|
||||
<div class="modal-container" />
|
||||
<HelpIcon />
|
||||
|
||||
<style>
|
||||
.modal-container {
|
||||
|
|
|
@ -63,6 +63,10 @@ const INITIAL_FRONTEND_STATE = {
|
|||
selectedScreenId: null,
|
||||
selectedComponentId: null,
|
||||
selectedLayoutId: null,
|
||||
|
||||
// onboarding
|
||||
onboarding: false,
|
||||
tourNodes: null,
|
||||
}
|
||||
|
||||
export const getFrontendStore = () => {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<script context="module">
|
||||
import { dom, library } from "@fortawesome/fontawesome-svg-core"
|
||||
import {
|
||||
faEnvelope,
|
||||
faXmark,
|
||||
faBook,
|
||||
faPlay,
|
||||
faLock,
|
||||
} from "@fortawesome/free-solid-svg-icons"
|
||||
import { faGithub, faDiscord } from "@fortawesome/free-brands-svg-icons"
|
||||
|
||||
library.add(faXmark, faBook, faPlay, faLock, faGithub, faDiscord, faEnvelope)
|
||||
dom.watch()
|
||||
</script>
|
||||
|
||||
<script>
|
||||
export let name
|
||||
</script>
|
||||
|
||||
<span>
|
||||
<i class={name} />
|
||||
</span>
|
||||
|
||||
<style>
|
||||
span {
|
||||
display: contents;
|
||||
}
|
||||
.svg-inline--fa {
|
||||
color: var(--spectrum-body-m-text-color, var(--spectrum-alias-text-color));
|
||||
}
|
||||
</style>
|
|
@ -1,42 +0,0 @@
|
|||
<script>
|
||||
import { Icon, Body } from "@budibase/bbui"
|
||||
</script>
|
||||
|
||||
<a target="_blank" href="https://github.com/Budibase/budibase/discussions">
|
||||
<div class="inner hoverable">
|
||||
<div class="hidden hoverable">
|
||||
<Body size="S">Need help? Go to our forums</Body>
|
||||
</div>
|
||||
<Icon name="Help" size="XXL" />
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
.inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-s);
|
||||
}
|
||||
.inner :global(*) {
|
||||
pointer-events: all;
|
||||
transition: color var(--spectrum-global-animation-duration-100, 130ms);
|
||||
}
|
||||
.inner:hover :global(*) {
|
||||
color: var(--spectrum-alias-icon-color-selected-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
position: absolute;
|
||||
bottom: var(--spacing-m);
|
||||
right: var(--spacing-m);
|
||||
border-radius: 55%;
|
||||
z-index: 99999;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.inner:hover .hidden {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
182
packages/builder/src/components/common/HelpMenu.svelte
Normal file
182
packages/builder/src/components/common/HelpMenu.svelte
Normal file
|
@ -0,0 +1,182 @@
|
|||
<script>
|
||||
import FontAwesomeIcon from "./FontAwesomeIcon.svelte"
|
||||
import { Popover, Heading, Body } from "@budibase/bbui"
|
||||
import { licensing } from "stores/portal"
|
||||
import { isEnabled, TENANT_FEATURE_FLAGS } from "helpers/featureFlags"
|
||||
|
||||
$: isPremiumUser = $licensing.license && !$licensing.isFreePlan
|
||||
|
||||
let show
|
||||
let hide
|
||||
let popoverAnchor
|
||||
</script>
|
||||
|
||||
<div bind:this={popoverAnchor} class="help">
|
||||
<button class="openMenu" on:click={show}>Help</button>
|
||||
<Popover
|
||||
class="helpMenuPopoverOverride"
|
||||
bind:show
|
||||
bind:hide
|
||||
anchor={popoverAnchor}
|
||||
>
|
||||
<nav class="helpMenu">
|
||||
<div class="header">
|
||||
<Heading size="XS">Help resources</Heading>
|
||||
<button on:click={hide} class="closeButton">
|
||||
<FontAwesomeIcon name="fa-solid fa-xmark" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="divider" />
|
||||
<a target="_blank" href="https://docs.budibase.com/docs">
|
||||
<div class="icon">
|
||||
<FontAwesomeIcon name="fa-solid fa-book" />
|
||||
</div>
|
||||
<Body size="S">Help docs</Body>
|
||||
</a>
|
||||
<div class="divider" />
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/Budibase/budibase/discussions"
|
||||
>
|
||||
<div class="icon">
|
||||
<FontAwesomeIcon name="fa-brands fa-github" />
|
||||
</div>
|
||||
<Body size="S">Discussions</Body>
|
||||
</a>
|
||||
<div class="divider" />
|
||||
<a target="_blank" href="https://discord.com/invite/ZepTmGbtfF">
|
||||
<div class="icon">
|
||||
<FontAwesomeIcon name="fa-brands fa-discord" />
|
||||
</div>
|
||||
<Body size="S">Discord</Body>
|
||||
</a>
|
||||
<div class="divider" />
|
||||
<a target="_blank" href="https://vimeo.com/showcase/budibase-university">
|
||||
<div class="icon">
|
||||
<FontAwesomeIcon name="fa-solid fa-play" />
|
||||
</div>
|
||||
<Body size="S">Budibase University</Body>
|
||||
</a>
|
||||
<div class="divider" />
|
||||
{#if isEnabled(TENANT_FEATURE_FLAGS.LICENSING)}
|
||||
<a
|
||||
href={isPremiumUser
|
||||
? "mailto:support@budibase.com"
|
||||
: "/builder/portal/account/usage"}
|
||||
>
|
||||
<div class="premiumLinkContent" class:disabled={!isPremiumUser}>
|
||||
<div class="icon">
|
||||
<FontAwesomeIcon name="fa-solid fa-envelope" />
|
||||
</div>
|
||||
<Body size="S">Email support</Body>
|
||||
</div>
|
||||
{#if !isPremiumUser}
|
||||
<div class="premiumBadge">
|
||||
<div class="icon">
|
||||
<FontAwesomeIcon name="fa-solid fa-lock" />
|
||||
</div>
|
||||
<Body size="XS">Premium</Body>
|
||||
</div>
|
||||
{/if}
|
||||
</a>
|
||||
{/if}
|
||||
</nav>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.help {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
bottom: var(--spacing-xl);
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
.openMenu {
|
||||
cursor: pointer;
|
||||
background-color: #6a1dc8;
|
||||
border-radius: 100px;
|
||||
color: white;
|
||||
border: none;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
padding: 10px 18px;
|
||||
}
|
||||
|
||||
.helpMenu {
|
||||
background-color: var(--background-alt);
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
nav {
|
||||
min-width: 280px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
border-bottom: 1px solid var(--spectrum-global-color-gray-300);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 0 0 16px;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
color: var(--grey-6);
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 18px 16px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.closeButton:hover {
|
||||
color: var(--grey-8);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
display: flex;
|
||||
padding: 12px;
|
||||
align-items: center;
|
||||
transition: filter 0.5s;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: var(--spectrum-global-color-gray-300);
|
||||
}
|
||||
|
||||
a:last-child {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 13px;
|
||||
margin-right: 7px;
|
||||
min-width: 18px;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.premiumLinkContent {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 70%;
|
||||
}
|
||||
|
||||
.premiumBadge {
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
border: var(--border-light);
|
||||
border-radius: 4px;
|
||||
padding: 4px 7px 5px 8px;
|
||||
}
|
||||
</style>
|
|
@ -11,6 +11,8 @@
|
|||
import { store } from "builderStore"
|
||||
import { ProgressCircle } from "@budibase/bbui"
|
||||
import CopyInput from "components/common/inputs/CopyInput.svelte"
|
||||
import TourWrap from "../portal/onboarding/TourWrap.svelte"
|
||||
import { TOUR_STEP_KEYS } from "../portal/onboarding/tours.js"
|
||||
|
||||
let publishModal
|
||||
let asyncModal
|
||||
|
@ -54,7 +56,11 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Button cta on:click={publishModal.show}>Publish</Button>
|
||||
<TourWrap tourStepKey={TOUR_STEP_KEYS.BUILDER_APP_PUBLISH}>
|
||||
<Button cta on:click={publishModal.show} id={"builder-app-publish-button"}>
|
||||
Publish
|
||||
</Button>
|
||||
</TourWrap>
|
||||
<Modal bind:this={publishModal}>
|
||||
<ModalContent
|
||||
title="Publish to production"
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
<script>
|
||||
import { Popover, Layout, Heading, Body, Button } from "@budibase/bbui"
|
||||
import { store } from "builderStore"
|
||||
import { TOURS } from "./tours.js"
|
||||
import { goto, layout, isActive } from "@roxi/routify"
|
||||
|
||||
let popoverAnchor
|
||||
let popover
|
||||
let tourSteps = null
|
||||
let tourStep
|
||||
let tourStepIdx
|
||||
let lastStep
|
||||
|
||||
$: tourNodes = { ...$store.tourNodes }
|
||||
$: tourKey = $store.tourKey
|
||||
$: tourStepKey = $store.tourStepKey
|
||||
|
||||
const initTour = targetKey => {
|
||||
if (!targetKey) {
|
||||
return
|
||||
}
|
||||
tourSteps = [...TOURS[targetKey]]
|
||||
tourStepIdx = 0
|
||||
tourStep = { ...tourSteps[tourStepIdx] }
|
||||
}
|
||||
|
||||
$: initTour(tourKey)
|
||||
|
||||
const updateTourStep = targetStepKey => {
|
||||
if (!tourSteps?.length) {
|
||||
return
|
||||
}
|
||||
tourStepIdx = getCurrentStepIdx(tourSteps, targetStepKey)
|
||||
lastStep = tourStepIdx + 1 == tourSteps.length
|
||||
tourStep = { ...tourSteps[tourStepIdx] }
|
||||
tourStep.onLoad()
|
||||
}
|
||||
|
||||
$: updateTourStep(tourStepKey)
|
||||
|
||||
const showPopover = (tourStep, tourNodes, popover) => {
|
||||
if (!tourStep) {
|
||||
return
|
||||
}
|
||||
popoverAnchor = tourNodes[tourStep.id]
|
||||
popover?.show()
|
||||
}
|
||||
|
||||
$: showPopover(tourStep, tourNodes, popover)
|
||||
|
||||
const navigateStep = step => {
|
||||
if (step.route) {
|
||||
const activeNav = $layout.children.find(c => $isActive(c.path))
|
||||
if (activeNav) {
|
||||
store.update(state => {
|
||||
if (!state.previousTopNavPath) state.previousTopNavPath = {}
|
||||
state.previousTopNavPath[activeNav.path] = window.location.pathname
|
||||
$goto(state.previousTopNavPath[step.route] || step.route)
|
||||
return state
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const nextStep = async () => {
|
||||
if (!lastStep === true) {
|
||||
let target = tourSteps[tourStepIdx + 1]
|
||||
if (target) {
|
||||
store.update(state => ({
|
||||
...state,
|
||||
tourStepKey: target.id,
|
||||
}))
|
||||
navigateStep(target)
|
||||
} else {
|
||||
console.log("Could not retrieve step")
|
||||
}
|
||||
} else {
|
||||
if (typeof tourStep.onComplete === "function") {
|
||||
tourStep.onComplete()
|
||||
}
|
||||
popover.hide()
|
||||
}
|
||||
}
|
||||
|
||||
const previousStep = async () => {
|
||||
if (tourStepIdx > 0) {
|
||||
let target = tourSteps[tourStepIdx - 1]
|
||||
if (target) {
|
||||
store.update(state => ({
|
||||
...state,
|
||||
tourStepKey: target.id,
|
||||
}))
|
||||
navigateStep(target)
|
||||
} else {
|
||||
console.log("Could not retrieve step")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getCurrentStepIdx = (steps, tourStepKey) => {
|
||||
if (!steps?.length) {
|
||||
return
|
||||
}
|
||||
if (steps?.length && !tourStepKey) {
|
||||
return 0
|
||||
}
|
||||
return steps.findIndex(step => step.id === tourStepKey)
|
||||
}
|
||||
</script>
|
||||
|
||||
{#key tourStepKey}
|
||||
<Popover
|
||||
align={tourStep?.align}
|
||||
bind:this={popover}
|
||||
anchor={popoverAnchor}
|
||||
dataCy="tour-popover-menu"
|
||||
maxWidth={300}
|
||||
dismissible={false}
|
||||
>
|
||||
<Layout gap="M">
|
||||
<div class="tour-header">
|
||||
<Heading size="XS">{tourStep?.title || "-"}</Heading>
|
||||
<div>{`${tourStepIdx + 1}/${tourSteps?.length}`}</div>
|
||||
</div>
|
||||
<Body size="S">
|
||||
<span class="tour-body">
|
||||
{#if tourStep.layout}
|
||||
<svelte:component this={tourStep.layout} />
|
||||
{:else}
|
||||
{tourStep?.body || ""}
|
||||
{/if}
|
||||
</span>
|
||||
</Body>
|
||||
<div class="tour-footer">
|
||||
<div class="tour-navigation">
|
||||
{#if tourStepIdx > 0}
|
||||
<Button
|
||||
secondary
|
||||
on:click={previousStep}
|
||||
disabled={tourStepIdx == 0}
|
||||
>
|
||||
<div>Back</div>
|
||||
</Button>
|
||||
{/if}
|
||||
<Button cta on:click={nextStep}>
|
||||
<div>{lastStep ? "Finish" : "Next"}</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</Popover>
|
||||
{/key}
|
||||
|
||||
<style>
|
||||
.tour-navigation {
|
||||
grid-gap: var(--spectrum-alias-grid-baseline);
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
:global([data-cy="tour-popover-menu"]) {
|
||||
padding: 10px;
|
||||
margin-top: var(--spacing-l);
|
||||
}
|
||||
.tour-body :global(.feature-list) {
|
||||
margin-bottom: 0px;
|
||||
padding-left: var(--spacing-xl);
|
||||
}
|
||||
.tour-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<script>
|
||||
import { tourHandler } from "./tourHandler"
|
||||
import { TOURS } from "./tours"
|
||||
import { onMount, onDestroy } from "svelte"
|
||||
import { store } from "builderStore"
|
||||
|
||||
export let tourStepKey
|
||||
|
||||
let currentTour
|
||||
let ready = false
|
||||
let handler
|
||||
|
||||
onMount(() => {
|
||||
if (!$store.tourKey) return
|
||||
|
||||
currentTour = TOURS[$store.tourKey].find(step => step.id === tourStepKey)
|
||||
|
||||
const elem = document.querySelector(currentTour.query)
|
||||
handler = tourHandler(elem, tourStepKey)
|
||||
ready = true
|
||||
})
|
||||
onDestroy(() => {
|
||||
if (handler) {
|
||||
handler.destroy()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<slot />
|
|
@ -0,0 +1,10 @@
|
|||
<div>
|
||||
In this section you can mange the data for your app:
|
||||
<ul class="feature-list">
|
||||
<li>Connect data sources</li>
|
||||
<li>Edit data</li>
|
||||
<li>Manage read & write access</li>
|
||||
<li>Create views</li>
|
||||
<li>Add bindings</li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,10 @@
|
|||
<div>
|
||||
After setting up your data, Design is where you build the screens for your
|
||||
app:
|
||||
<ul class="feature-list">
|
||||
<li>Add screens</li>
|
||||
<li>Add components</li>
|
||||
<li>Choose your theme</li>
|
||||
<li>Edit navigation</li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
<div>
|
||||
Once you’re happy with your app you can publish it to production!
|
||||
<p>
|
||||
After publishing, any changes you make will not take affect until you next
|
||||
publish.
|
||||
</p>
|
||||
</div>
|
|
@ -0,0 +1,3 @@
|
|||
export { default as OnboardingData } from "./OnboardingData.svelte"
|
||||
export { default as OnboardingDesign } from "./OnboardingDesign.svelte"
|
||||
export { default as OnboardingPublish } from "./OnboardingPublish.svelte"
|
|
@ -0,0 +1,47 @@
|
|||
import { store } from "builderStore/index"
|
||||
import { get } from "svelte/store"
|
||||
|
||||
const registerNode = async (node, tourStepKey) => {
|
||||
if (!node) {
|
||||
console.log("Tour Handler - an anchor node is required")
|
||||
}
|
||||
|
||||
if (!get(store).tourKey) {
|
||||
console.log("Tour Handler - No active tour ", tourStepKey, node)
|
||||
return
|
||||
}
|
||||
|
||||
store.update(state => {
|
||||
const update = {
|
||||
...state,
|
||||
tourNodes: {
|
||||
...state.tourNodes,
|
||||
[tourStepKey]: node,
|
||||
},
|
||||
}
|
||||
return update
|
||||
})
|
||||
}
|
||||
|
||||
export function tourHandler(node, tourStepKey) {
|
||||
if (node && tourStepKey) {
|
||||
registerNode(node, tourStepKey)
|
||||
}
|
||||
return {
|
||||
destroy: () => {
|
||||
const updatedTourNodes = get(store).tourNodes
|
||||
if (updatedTourNodes && updatedTourNodes[tourStepKey]) {
|
||||
delete updatedTourNodes[tourStepKey]
|
||||
store.update(state => {
|
||||
const update = {
|
||||
...state,
|
||||
tourNodes: {
|
||||
...updatedTourNodes,
|
||||
},
|
||||
}
|
||||
return update
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
95
packages/builder/src/components/portal/onboarding/tours.js
Normal file
95
packages/builder/src/components/portal/onboarding/tours.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
import { get } from "svelte/store"
|
||||
import { store } from "builderStore"
|
||||
import { users, auth } from "stores/portal"
|
||||
import analytics from "analytics"
|
||||
import { OnboardingData, OnboardingDesign, OnboardingPublish } from "./steps"
|
||||
const ONBOARDING_EVENT_PREFIX = "onboarding"
|
||||
|
||||
export const TOUR_STEP_KEYS = {
|
||||
BUILDER_APP_PUBLISH: "builder-app-publish",
|
||||
BUILDER_DATA_SECTION: "builder-data-section",
|
||||
BUILDER_DESIGN_SECTION: "builder-design-section",
|
||||
BUILDER_AUTOMATE_SECTION: "builder-automate-section",
|
||||
}
|
||||
|
||||
export const TOUR_KEYS = {
|
||||
TOUR_BUILDER_ONBOARDING: "builder-onboarding",
|
||||
}
|
||||
|
||||
const tourEvent = eventKey => {
|
||||
analytics.captureEvent(`${ONBOARDING_EVENT_PREFIX}:${eventKey}`, {
|
||||
eventSource: EventSource.PORTAL,
|
||||
})
|
||||
}
|
||||
|
||||
const getTours = () => {
|
||||
return {
|
||||
[TOUR_KEYS.TOUR_BUILDER_ONBOARDING]: [
|
||||
{
|
||||
id: TOUR_STEP_KEYS.BUILDER_DATA_SECTION,
|
||||
title: "Data",
|
||||
route: "/builder/app/:application/data",
|
||||
layout: OnboardingData,
|
||||
query: ".topcenternav .spectrum-Tabs-item#builder-data-tab",
|
||||
onLoad: async () => {
|
||||
tourEvent(TOUR_STEP_KEYS.BUILDER_DATA_SECTION)
|
||||
},
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
id: TOUR_STEP_KEYS.BUILDER_DESIGN_SECTION,
|
||||
title: "Design",
|
||||
route: "/builder/app/:application/design",
|
||||
layout: OnboardingDesign,
|
||||
query: ".topcenternav .spectrum-Tabs-item#builder-design-tab",
|
||||
onLoad: () => {
|
||||
tourEvent(TOUR_STEP_KEYS.BUILDER_DESIGN_SECTION)
|
||||
},
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
id: TOUR_STEP_KEYS.BUILDER_AUTOMATE_SECTION,
|
||||
title: "Automations",
|
||||
route: "/builder/app/:application/automate",
|
||||
query: ".topcenternav .spectrum-Tabs-item#builder-automate-tab",
|
||||
body: "Once you have your app screens made, you can set up automations to fit in with your current workflow",
|
||||
onLoad: () => {
|
||||
tourEvent(TOUR_STEP_KEYS.BUILDER_AUTOMATE_SECTION)
|
||||
},
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
id: TOUR_STEP_KEYS.BUILDER_APP_PUBLISH,
|
||||
title: "Publish",
|
||||
layout: OnboardingPublish,
|
||||
query: ".toprightnav #builder-app-publish-button",
|
||||
onLoad: () => {
|
||||
tourEvent(TOUR_STEP_KEYS.BUILDER_APP_PUBLISH)
|
||||
},
|
||||
onComplete: async () => {
|
||||
// Mark the users onboarding as complete
|
||||
// Clear all tour related state
|
||||
if (get(auth).user) {
|
||||
await users.save({
|
||||
...get(auth).user,
|
||||
onboardedAt: new Date().toISOString(),
|
||||
})
|
||||
|
||||
// Update the cached user
|
||||
await auth.getSelf()
|
||||
|
||||
store.update(state => ({
|
||||
...state,
|
||||
tourNodes: undefined,
|
||||
tourKey: undefined,
|
||||
tourKeyStep: undefined,
|
||||
onboarding: false,
|
||||
}))
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
export const TOURS = getTours()
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { store, automationStore } from "builderStore"
|
||||
import { roles, flags } from "stores/backend"
|
||||
import { auth } from "stores/portal"
|
||||
import {
|
||||
ActionMenu,
|
||||
MenuItem,
|
||||
|
@ -10,6 +11,7 @@
|
|||
Heading,
|
||||
notifications,
|
||||
} from "@budibase/bbui"
|
||||
|
||||
import RevertModal from "components/deploy/RevertModal.svelte"
|
||||
import VersionModal from "components/deploy/VersionModal.svelte"
|
||||
import DeployNavigation from "components/deploy/DeployNavigation.svelte"
|
||||
|
@ -17,6 +19,9 @@
|
|||
import { isActive, goto, layout, redirect } from "@roxi/routify"
|
||||
import { capitalise } from "helpers"
|
||||
import { onMount, onDestroy } from "svelte"
|
||||
import TourWrap from "components/portal/onboarding/TourWrap.svelte"
|
||||
import TourPopover from "components/portal/onboarding/TourPopover.svelte"
|
||||
import { TOUR_KEYS, TOURS } from "components/portal/onboarding/tours.js"
|
||||
|
||||
export let application
|
||||
|
||||
|
@ -62,6 +67,23 @@
|
|||
})
|
||||
}
|
||||
|
||||
const initTour = async () => {
|
||||
if (!$auth.user?.onboardedAt) {
|
||||
// Determine the correct step
|
||||
const activeNav = $layout.children.find(c => $isActive(c.path))
|
||||
const onboardingTour = TOURS[TOUR_KEYS.TOUR_BUILDER_ONBOARDING]
|
||||
const targetStep = activeNav
|
||||
? onboardingTour.find(step => step.route === activeNav?.path)
|
||||
: null
|
||||
await store.update(state => ({
|
||||
...state,
|
||||
onboarding: true,
|
||||
tourKey: TOUR_KEYS.TOUR_BUILDER_ONBOARDING,
|
||||
tourStepKey: targetStep?.id,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (!hasSynced && application) {
|
||||
try {
|
||||
|
@ -69,6 +91,7 @@
|
|||
// check if user has beta access
|
||||
// const betaResponse = await API.checkBetaAccess($auth?.user?.email)
|
||||
// betaAccess = betaResponse.access
|
||||
initTour()
|
||||
} catch (error) {
|
||||
notifications.error("Failed to sync with production database")
|
||||
}
|
||||
|
@ -88,6 +111,7 @@
|
|||
<!-- This should probably be some kind of loading state? -->
|
||||
<div class="loading" />
|
||||
{:then _}
|
||||
<TourPopover />
|
||||
<div class="root">
|
||||
<div class="top-nav">
|
||||
<div class="topleftnav">
|
||||
|
@ -140,12 +164,15 @@
|
|||
<div class="topcenternav">
|
||||
<Tabs {selected} size="M">
|
||||
{#each $layout.children as { path, title }}
|
||||
<TourWrap tourStepKey={`builder-${title}-section`}>
|
||||
<Tab
|
||||
quiet
|
||||
selected={$isActive(path)}
|
||||
on:click={topItemNavigate(path)}
|
||||
title={capitalise(title)}
|
||||
id={`builder-${title}-tab`}
|
||||
/>
|
||||
</TourWrap>
|
||||
{/each}
|
||||
</Tabs>
|
||||
</div>
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
import { Button } from "@budibase/bbui"
|
||||
import { goto } from "@roxi/routify"
|
||||
import { auth, admin } from "stores/portal"
|
||||
import { isEnabled, TENANT_FEATURE_FLAGS } from "helpers/featureFlags"
|
||||
</script>
|
||||
|
||||
{#if isEnabled(TENANT_FEATURE_FLAGS.LICENSING)}
|
||||
{#if $admin.cloud && $auth?.user?.accountPortalAccess}
|
||||
<Button
|
||||
cta
|
||||
|
@ -25,3 +27,4 @@
|
|||
Upgrade
|
||||
</Button>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import MobileMenu from "./_components/MobileMenu.svelte"
|
||||
import Logo from "./_components/Logo.svelte"
|
||||
import UserDropdown from "./_components/UserDropdown.svelte"
|
||||
import HelpMenu from "components/common/HelpMenu.svelte"
|
||||
|
||||
let loaded = false
|
||||
let mobileMenuVisible = false
|
||||
|
@ -46,6 +47,7 @@
|
|||
</script>
|
||||
|
||||
{#if $auth.user && loaded}
|
||||
<HelpMenu />
|
||||
<div class="container">
|
||||
<div class="nav">
|
||||
<div class="branding">
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/cli",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||
"main": "src/index.js",
|
||||
"bin": {
|
||||
|
@ -26,9 +26,9 @@
|
|||
"outputPath": "build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/backend-core": "2.2.12-alpha.50",
|
||||
"@budibase/string-templates": "2.2.12-alpha.50",
|
||||
"@budibase/types": "2.2.12-alpha.50",
|
||||
"@budibase/backend-core": "2.2.12-alpha.52",
|
||||
"@budibase/string-templates": "2.2.12-alpha.52",
|
||||
"@budibase/types": "2.2.12-alpha.52",
|
||||
"axios": "0.21.2",
|
||||
"chalk": "4.1.0",
|
||||
"cli-progress": "3.11.2",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/client",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"license": "MPL-2.0",
|
||||
"module": "dist/budibase-client.js",
|
||||
"main": "dist/budibase-client.js",
|
||||
|
@ -19,9 +19,9 @@
|
|||
"dev:builder": "rollup -cw"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "2.2.12-alpha.50",
|
||||
"@budibase/frontend-core": "2.2.12-alpha.50",
|
||||
"@budibase/string-templates": "2.2.12-alpha.50",
|
||||
"@budibase/bbui": "2.2.12-alpha.52",
|
||||
"@budibase/frontend-core": "2.2.12-alpha.52",
|
||||
"@budibase/string-templates": "2.2.12-alpha.52",
|
||||
"@spectrum-css/button": "^3.0.3",
|
||||
"@spectrum-css/card": "^3.0.3",
|
||||
"@spectrum-css/divider": "^1.0.3",
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@budibase/frontend-core",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Budibase frontend core libraries used in builder and client",
|
||||
"author": "Budibase",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "2.2.12-alpha.50",
|
||||
"@budibase/bbui": "2.2.12-alpha.52",
|
||||
"lodash": "^4.17.21",
|
||||
"svelte": "^3.46.2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/sdk",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Budibase Public API SDK",
|
||||
"author": "Budibase",
|
||||
"license": "MPL-2.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/server",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Budibase Web Server",
|
||||
"main": "src/index.ts",
|
||||
"repository": {
|
||||
|
@ -43,11 +43,11 @@
|
|||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "10.0.3",
|
||||
"@budibase/backend-core": "2.2.12-alpha.50",
|
||||
"@budibase/client": "2.2.12-alpha.50",
|
||||
"@budibase/pro": "2.2.12-alpha.50",
|
||||
"@budibase/string-templates": "2.2.12-alpha.50",
|
||||
"@budibase/types": "2.2.12-alpha.50",
|
||||
"@budibase/backend-core": "2.2.12-alpha.52",
|
||||
"@budibase/client": "2.2.12-alpha.52",
|
||||
"@budibase/pro": "2.2.12-alpha.52",
|
||||
"@budibase/string-templates": "2.2.12-alpha.52",
|
||||
"@budibase/types": "2.2.12-alpha.52",
|
||||
"@bull-board/api": "3.7.0",
|
||||
"@bull-board/koa": "3.9.4",
|
||||
"@elastic/elasticsearch": "7.10.0",
|
||||
|
|
|
@ -1273,13 +1273,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/backend-core@2.2.12-alpha.50":
|
||||
version "2.2.12-alpha.50"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.50.tgz#39f228904cf39de2dbb51900df4494267ac72381"
|
||||
integrity sha512-ysVJ6Eul7o+LZRoilFr7bk1/gkoxSqM30yBbRhKxIhH2IOk0qd9LAaNQiTnwn4ZzU+tJWSkyAsJAQdTnX8/i9g==
|
||||
"@budibase/backend-core@2.2.12-alpha.52":
|
||||
version "2.2.12-alpha.52"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.52.tgz#b1f7457f5aae71eaed4e4fb7ab3c2d760ea3d74a"
|
||||
integrity sha512-JUpwI6U0b+n5CyatdUUDzYkVneJQWUbjkGHZiWZrP0TncrHeKi4HmBKPswYoEydzOQQOfpDOa7ZoK9ffEldf/A==
|
||||
dependencies:
|
||||
"@budibase/nano" "10.1.1"
|
||||
"@budibase/types" "2.2.12-alpha.50"
|
||||
"@budibase/types" "2.2.12-alpha.52"
|
||||
"@shopify/jest-koa-mocks" "5.0.1"
|
||||
"@techpass/passport-openidconnect" "0.3.2"
|
||||
aws-cloudfront-sign "2.2.0"
|
||||
|
@ -1374,13 +1374,13 @@
|
|||
qs "^6.11.0"
|
||||
tough-cookie "^4.1.2"
|
||||
|
||||
"@budibase/pro@2.2.12-alpha.50":
|
||||
version "2.2.12-alpha.50"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.50.tgz#599edc75363b323f613a0d56e5173150582b13bb"
|
||||
integrity sha512-eeKY9P4Zi81AlU6vYWVcffMwkyUrNv6PcNjdKZZNBuIgNfOVejy9vmpIukx43LpHUOsk6FKxHFNVDN1txnYRkg==
|
||||
"@budibase/pro@2.2.12-alpha.52":
|
||||
version "2.2.12-alpha.52"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.52.tgz#37df13f60fbe873537e901f9183205100ddb8d98"
|
||||
integrity sha512-Y5luiKVvkOtWEnfZ0lrqfNfclSyQrhFJnP9P7BgEBKUcqBguslaAObPZtHfcP1GXiR/I6hoZKXMCCSvHDRXFbg==
|
||||
dependencies:
|
||||
"@budibase/backend-core" "2.2.12-alpha.50"
|
||||
"@budibase/types" "2.2.12-alpha.50"
|
||||
"@budibase/backend-core" "2.2.12-alpha.52"
|
||||
"@budibase/types" "2.2.12-alpha.52"
|
||||
"@koa/router" "8.0.8"
|
||||
bull "4.10.1"
|
||||
joi "17.6.0"
|
||||
|
@ -1406,10 +1406,10 @@
|
|||
svelte-apexcharts "^1.0.2"
|
||||
svelte-flatpickr "^3.1.0"
|
||||
|
||||
"@budibase/types@2.2.12-alpha.50":
|
||||
version "2.2.12-alpha.50"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.50.tgz#ef07d4593c1ea0da6a6b75004d1319d7621cd910"
|
||||
integrity sha512-LU+G7gQffBvnLvWfzpxUNcrCZFP/ZNQqAjB2KJxgq9pfeynU3MWAwut1tjKpp8eduuu7GnfBT1uvet9jM87FKA==
|
||||
"@budibase/types@2.2.12-alpha.52":
|
||||
version "2.2.12-alpha.52"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.52.tgz#184c2c74a1705e0fad49ad14608b618db99ecabd"
|
||||
integrity sha512-yQSxExP1l/kqy1grHB58STHDfs8UBwEozfRRs090kif3a69DfhAzur500EECW8otKahQKL+DUHedG0b/ilAVtw==
|
||||
|
||||
"@bull-board/api@3.7.0":
|
||||
version "3.7.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/string-templates",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Handlebars wrapper for Budibase templating.",
|
||||
"main": "src/index.cjs",
|
||||
"module": "dist/bundle.mjs",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/types",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Budibase types",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
|
@ -47,6 +47,7 @@ export interface User extends ThirdPartyUser {
|
|||
account?: {
|
||||
authType: string
|
||||
}
|
||||
onboardedAt?: string
|
||||
}
|
||||
|
||||
export interface UserRoles {
|
||||
|
|
|
@ -6,6 +6,9 @@ export enum Event {
|
|||
USER_UPDATED = "user:updated",
|
||||
USER_DELETED = "user:deleted",
|
||||
|
||||
// USER / ONBOARDING
|
||||
USER_ONBOARDING_COMPLETE = "user:onboarding:complete",
|
||||
|
||||
// USER / PERMISSIONS
|
||||
USER_PERMISSION_ADMIN_ASSIGNED = "user:admin:assigned",
|
||||
USER_PERMISSION_ADMIN_REMOVED = "user:admin:removed",
|
||||
|
|
|
@ -12,6 +12,11 @@ export interface UserDeletedEvent extends BaseEvent {
|
|||
userId: string
|
||||
}
|
||||
|
||||
export interface UserOnboardingEvent extends BaseEvent {
|
||||
userId: string
|
||||
step?: string
|
||||
}
|
||||
|
||||
export interface UserPermissionAssignedEvent extends BaseEvent {
|
||||
userId: string
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/worker",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "2.2.12-alpha.50",
|
||||
"version": "2.2.12-alpha.52",
|
||||
"description": "Budibase background service",
|
||||
"main": "src/index.ts",
|
||||
"repository": {
|
||||
|
@ -36,10 +36,10 @@
|
|||
"author": "Budibase",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@budibase/backend-core": "2.2.12-alpha.50",
|
||||
"@budibase/pro": "2.2.12-alpha.50",
|
||||
"@budibase/string-templates": "2.2.12-alpha.50",
|
||||
"@budibase/types": "2.2.12-alpha.50",
|
||||
"@budibase/backend-core": "2.2.12-alpha.52",
|
||||
"@budibase/pro": "2.2.12-alpha.52",
|
||||
"@budibase/string-templates": "2.2.12-alpha.52",
|
||||
"@budibase/types": "2.2.12-alpha.52",
|
||||
"@koa/router": "8.0.8",
|
||||
"@sentry/node": "6.17.7",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
|
|
|
@ -73,6 +73,10 @@ export const handleSaveEvents = async (
|
|||
await events.user.permissionAdminRemoved(user)
|
||||
}
|
||||
|
||||
if (isOnboardingComplete(user, existingUser)) {
|
||||
await events.user.onboardingComplete(user)
|
||||
}
|
||||
|
||||
if (
|
||||
!existingUser.forceResetPassword &&
|
||||
user.forceResetPassword &&
|
||||
|
@ -114,6 +118,10 @@ const isRemovingAdmin = (user: any, existingUser: any) => {
|
|||
return isRemovingPermission(user, existingUser, isAdmin)
|
||||
}
|
||||
|
||||
const isOnboardingComplete = (user: any, existingUser: any) => {
|
||||
return !existingUser?.onboardedAt && typeof user.onboardedAt === "string"
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a permission is being added to a new or existing user.
|
||||
*/
|
||||
|
|
|
@ -470,13 +470,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/backend-core@2.2.12-alpha.50":
|
||||
version "2.2.12-alpha.50"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.50.tgz#39f228904cf39de2dbb51900df4494267ac72381"
|
||||
integrity sha512-ysVJ6Eul7o+LZRoilFr7bk1/gkoxSqM30yBbRhKxIhH2IOk0qd9LAaNQiTnwn4ZzU+tJWSkyAsJAQdTnX8/i9g==
|
||||
"@budibase/backend-core@2.2.12-alpha.52":
|
||||
version "2.2.12-alpha.52"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.52.tgz#b1f7457f5aae71eaed4e4fb7ab3c2d760ea3d74a"
|
||||
integrity sha512-JUpwI6U0b+n5CyatdUUDzYkVneJQWUbjkGHZiWZrP0TncrHeKi4HmBKPswYoEydzOQQOfpDOa7ZoK9ffEldf/A==
|
||||
dependencies:
|
||||
"@budibase/nano" "10.1.1"
|
||||
"@budibase/types" "2.2.12-alpha.50"
|
||||
"@budibase/types" "2.2.12-alpha.52"
|
||||
"@shopify/jest-koa-mocks" "5.0.1"
|
||||
"@techpass/passport-openidconnect" "0.3.2"
|
||||
aws-cloudfront-sign "2.2.0"
|
||||
|
@ -521,13 +521,13 @@
|
|||
qs "^6.11.0"
|
||||
tough-cookie "^4.1.2"
|
||||
|
||||
"@budibase/pro@2.2.12-alpha.50":
|
||||
version "2.2.12-alpha.50"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.50.tgz#599edc75363b323f613a0d56e5173150582b13bb"
|
||||
integrity sha512-eeKY9P4Zi81AlU6vYWVcffMwkyUrNv6PcNjdKZZNBuIgNfOVejy9vmpIukx43LpHUOsk6FKxHFNVDN1txnYRkg==
|
||||
"@budibase/pro@2.2.12-alpha.52":
|
||||
version "2.2.12-alpha.52"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.52.tgz#37df13f60fbe873537e901f9183205100ddb8d98"
|
||||
integrity sha512-Y5luiKVvkOtWEnfZ0lrqfNfclSyQrhFJnP9P7BgEBKUcqBguslaAObPZtHfcP1GXiR/I6hoZKXMCCSvHDRXFbg==
|
||||
dependencies:
|
||||
"@budibase/backend-core" "2.2.12-alpha.50"
|
||||
"@budibase/types" "2.2.12-alpha.50"
|
||||
"@budibase/backend-core" "2.2.12-alpha.52"
|
||||
"@budibase/types" "2.2.12-alpha.52"
|
||||
"@koa/router" "8.0.8"
|
||||
bull "4.10.1"
|
||||
joi "17.6.0"
|
||||
|
@ -535,10 +535,10 @@
|
|||
lru-cache "^7.14.1"
|
||||
node-fetch "^2.6.1"
|
||||
|
||||
"@budibase/types@2.2.12-alpha.50":
|
||||
version "2.2.12-alpha.50"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.50.tgz#ef07d4593c1ea0da6a6b75004d1319d7621cd910"
|
||||
integrity sha512-LU+G7gQffBvnLvWfzpxUNcrCZFP/ZNQqAjB2KJxgq9pfeynU3MWAwut1tjKpp8eduuu7GnfBT1uvet9jM87FKA==
|
||||
"@budibase/types@2.2.12-alpha.52":
|
||||
version "2.2.12-alpha.52"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.52.tgz#184c2c74a1705e0fad49ad14608b618db99ecabd"
|
||||
integrity sha512-yQSxExP1l/kqy1grHB58STHDfs8UBwEozfRRs090kif3a69DfhAzur500EECW8otKahQKL+DUHedG0b/ilAVtw==
|
||||
|
||||
"@cspotcode/source-map-support@^0.8.0":
|
||||
version "0.8.1"
|
||||
|
|
Loading…
Reference in a new issue