Move a user profile and password modals to frontend-core to allow sharing
This commit is contained in:
parent
b390f92019
commit
3c44c94442
|
@ -5,8 +5,8 @@
|
||||||
import { appsStore } from "@/stores/portal"
|
import { appsStore } from "@/stores/portal"
|
||||||
import { API } from "@/api"
|
import { API } from "@/api"
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { createValidationStore } from "@/helpers/validation/yup"
|
import { createValidationStore } from "@budibase/frontend-core/src/utils/validation/yup"
|
||||||
import * as appValidation from "@/helpers/validation/yup/app"
|
import * as appValidation from "@budibase/frontend-core/src/utils/validation/yup/app"
|
||||||
import EditableIcon from "@/components/common/EditableIcon.svelte"
|
import EditableIcon from "@/components/common/EditableIcon.svelte"
|
||||||
import { isEqual } from "lodash"
|
import { isEqual } from "lodash"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
import { appsStore, admin, auth } from "@/stores/portal"
|
import { appsStore, admin, auth } from "@/stores/portal"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { createValidationStore } from "@/helpers/validation/yup"
|
import { createValidationStore } from "@budibase/frontend-core/src/utils/validation/yup"
|
||||||
import * as appValidation from "@/helpers/validation/yup/app"
|
import * as appValidation from "@budibase/frontend-core/src/utils/validation/yup/app"
|
||||||
import TemplateCard from "@/components/common/TemplateCard.svelte"
|
import TemplateCard from "@/components/common/TemplateCard.svelte"
|
||||||
import { lowercase } from "@/helpers"
|
import { lowercase } from "@/helpers"
|
||||||
import { sdk } from "@budibase/shared-core"
|
import { sdk } from "@budibase/shared-core"
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
Layout,
|
Layout,
|
||||||
keepOpen,
|
keepOpen,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { createValidationStore } from "@/helpers/validation/yup"
|
import { createValidationStore } from "@budibase/frontend-core/src/utils/validation/yup"
|
||||||
import { writable, get } from "svelte/store"
|
import { writable, get } from "svelte/store"
|
||||||
import * as appValidation from "@/helpers/validation/yup/app"
|
import * as appValidation from "@budibase/frontend-core/src/utils/validation/yup/app"
|
||||||
import { appsStore, auth } from "@/stores/portal"
|
import { appsStore, auth } from "@/stores/portal"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { API } from "@/api"
|
import { API } from "@/api"
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
notifications,
|
notifications,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { downloadFile } from "@budibase/frontend-core"
|
import { downloadFile } from "@budibase/frontend-core"
|
||||||
import { createValidationStore } from "@/helpers/validation/yup"
|
import { createValidationStore } from "@budibase/frontend-core/src/utils/validation/yup"
|
||||||
|
|
||||||
export let app
|
export let app
|
||||||
export let published
|
export let published
|
||||||
|
|
|
@ -41,11 +41,6 @@ export const LAYOUT_NAMES = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// one or more word characters and whitespace
|
|
||||||
export const APP_NAME_REGEX = /^[\w\s]+$/
|
|
||||||
// zero or more non-whitespace characters
|
|
||||||
export const APP_URL_REGEX = /^[0-9a-zA-Z-_]+$/
|
|
||||||
|
|
||||||
export const DefaultAppTheme = {
|
export const DefaultAppTheme = {
|
||||||
primaryColor: "var(--spectrum-global-color-blue-600)",
|
primaryColor: "var(--spectrum-global-color-blue-600)",
|
||||||
primaryColorHover: "var(--spectrum-global-color-blue-500)",
|
primaryColorHover: "var(--spectrum-global-color-blue-500)",
|
||||||
|
|
|
@ -28,13 +28,13 @@
|
||||||
Constants,
|
Constants,
|
||||||
Utils,
|
Utils,
|
||||||
RoleUtils,
|
RoleUtils,
|
||||||
|
emailValidator,
|
||||||
} from "@budibase/frontend-core"
|
} from "@budibase/frontend-core"
|
||||||
import { sdk } from "@budibase/shared-core"
|
import { sdk } from "@budibase/shared-core"
|
||||||
import { API } from "@/api"
|
import { API } from "@/api"
|
||||||
import GroupIcon from "../../../portal/users/groups/_components/GroupIcon.svelte"
|
import GroupIcon from "../../../portal/users/groups/_components/GroupIcon.svelte"
|
||||||
import RoleSelect from "@/components/common/RoleSelect.svelte"
|
import RoleSelect from "@/components/common/RoleSelect.svelte"
|
||||||
import UpgradeModal from "@/components/common/users/UpgradeModal.svelte"
|
import UpgradeModal from "@/components/common/users/UpgradeModal.svelte"
|
||||||
import { emailValidator } from "@/helpers/validation"
|
|
||||||
import { fly } from "svelte/transition"
|
import { fly } from "svelte/transition"
|
||||||
import InfoDisplay from "../design/[screenId]/[componentId]/_components/Component/InfoDisplay.svelte"
|
import InfoDisplay from "../design/[screenId]/[componentId]/_components/Component/InfoDisplay.svelte"
|
||||||
import BuilderGroupPopover from "./BuilderGroupPopover.svelte"
|
import BuilderGroupPopover from "./BuilderGroupPopover.svelte"
|
||||||
|
|
|
@ -24,13 +24,13 @@
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { AppStatus } from "@/constants"
|
import { AppStatus } from "@/constants"
|
||||||
import { gradient } from "@/actions"
|
import { gradient } from "@/actions"
|
||||||
import ProfileModal from "@/components/settings/ProfileModal.svelte"
|
import { ProfileModal, ChangePasswordModal } from "@budibase/frontend-core"
|
||||||
import ChangePasswordModal from "@/components/settings/ChangePasswordModal.svelte"
|
|
||||||
import { processStringSync } from "@budibase/string-templates"
|
import { processStringSync } from "@budibase/string-templates"
|
||||||
import Spaceman from "assets/bb-space-man.svg"
|
import Spaceman from "assets/bb-space-man.svg"
|
||||||
import Logo from "assets/bb-emblem.svg"
|
import Logo from "assets/bb-emblem.svg"
|
||||||
import { UserAvatar } from "@budibase/frontend-core"
|
import { UserAvatar } from "@budibase/frontend-core"
|
||||||
import { helpers, sdk } from "@budibase/shared-core"
|
import { helpers, sdk } from "@budibase/shared-core"
|
||||||
|
import { API } from "@/api"
|
||||||
|
|
||||||
let loaded = false
|
let loaded = false
|
||||||
let userInfoModal
|
let userInfoModal
|
||||||
|
@ -201,10 +201,10 @@
|
||||||
</Page>
|
</Page>
|
||||||
</div>
|
</div>
|
||||||
<Modal bind:this={userInfoModal}>
|
<Modal bind:this={userInfoModal}>
|
||||||
<ProfileModal />
|
<ProfileModal {API} user={$auth.user} on:save={() => auth.getSelf()} />
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal bind:this={changePasswordModal}>
|
<Modal bind:this={changePasswordModal}>
|
||||||
<ChangePasswordModal />
|
<ChangePasswordModal {API} on:save={() => auth.getSelf()} />
|
||||||
</Modal>
|
</Modal>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
import Logo from "assets/bb-emblem.svg"
|
import Logo from "assets/bb-emblem.svg"
|
||||||
import { TestimonialPage } from "@budibase/frontend-core/src/components"
|
import { TestimonialPage } from "@budibase/frontend-core/src/components"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import PasswordRepeatInput from "../../../components/common/users/PasswordRepeatInput.svelte"
|
import PasswordRepeatInput from "@budibase/frontend-core/src/components/PasswordRepeatInput.svelte"
|
||||||
|
|
||||||
const resetCode = $params["?code"]
|
const resetCode = $params["?code"]
|
||||||
let form
|
let form
|
||||||
|
@ -79,11 +79,7 @@
|
||||||
<Layout gap="S" noPadding>
|
<Layout gap="S" noPadding>
|
||||||
<Heading size="M">Reset your password</Heading>
|
<Heading size="M">Reset your password</Heading>
|
||||||
<Body size="M">Must contain at least 12 characters</Body>
|
<Body size="M">Must contain at least 12 characters</Body>
|
||||||
<PasswordRepeatInput
|
<PasswordRepeatInput bind:password bind:error={passwordError} />
|
||||||
bind:passwordForm={form}
|
|
||||||
bind:password
|
|
||||||
bind:error={passwordError}
|
|
||||||
/>
|
|
||||||
<Button secondary cta on:click={reset}>
|
<Button secondary cta on:click={reset}>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<ProgressCircle overBackground={true} size="S" />
|
<ProgressCircle overBackground={true} size="S" />
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
import { admin, auth } from "@/stores/portal"
|
import { admin, auth } from "@/stores/portal"
|
||||||
import { ActionMenu, MenuItem, Icon, Modal } from "@budibase/bbui"
|
import { ActionMenu, MenuItem, Icon, Modal } from "@budibase/bbui"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import ProfileModal from "@/components/settings/ProfileModal.svelte"
|
import ProfileModal from "@budibase/frontend-core/src/components/ProfileModal.svelte"
|
||||||
import ChangePasswordModal from "@/components/settings/ChangePasswordModal.svelte"
|
import ChangePasswordModal from "@budibase/frontend-core/src/components/ChangePasswordModal.svelte"
|
||||||
import ThemeModal from "@/components/settings/ThemeModal.svelte"
|
import ThemeModal from "@/components/settings/ThemeModal.svelte"
|
||||||
import APIKeyModal from "@/components/settings/APIKeyModal.svelte"
|
import APIKeyModal from "@/components/settings/APIKeyModal.svelte"
|
||||||
import { UserAvatar } from "@budibase/frontend-core"
|
import { UserAvatar } from "@budibase/frontend-core"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, FancyForm, FancyInput } from "@budibase/bbui"
|
import { Button, FancyForm, FancyInput } from "@budibase/bbui"
|
||||||
import PanelHeader from "./PanelHeader.svelte"
|
import PanelHeader from "./PanelHeader.svelte"
|
||||||
import { APP_URL_REGEX } from "@/constants"
|
import { Constants } from "@budibase/frontend-core"
|
||||||
|
|
||||||
export let disabled
|
export let disabled
|
||||||
export let name = ""
|
export let name = ""
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
return "URL must be provided"
|
return "URL must be provided"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!APP_URL_REGEX.test(url)) {
|
if (!Constants.APP_URL_REGEX.test(url)) {
|
||||||
return "Invalid URL"
|
return "Invalid URL"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
Icon,
|
Icon,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { groups, licensing } from "@/stores/portal"
|
import { groups, licensing } from "@/stores/portal"
|
||||||
import { Constants } from "@budibase/frontend-core"
|
import { Constants, emailValidator } from "@budibase/frontend-core"
|
||||||
import { emailValidator } from "@/helpers/validation"
|
|
||||||
import { capitalise } from "@/helpers"
|
import { capitalise } from "@/helpers"
|
||||||
|
|
||||||
export let showOnboardingTypeModal
|
export let showOnboardingTypeModal
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
Icon,
|
Icon,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { groups, licensing, admin } from "@/stores/portal"
|
import { groups, licensing, admin } from "@/stores/portal"
|
||||||
import { emailValidator } from "@/helpers/validation"
|
import { emailValidator, Constants } from "@budibase/frontend-core"
|
||||||
import { Constants } from "@budibase/frontend-core"
|
|
||||||
import { capitalise } from "@/helpers"
|
import { capitalise } from "@/helpers"
|
||||||
|
|
||||||
const BYTES_IN_MB = 1000000
|
const BYTES_IN_MB = 1000000
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { ModalContent, Body, notifications } from "@budibase/bbui"
|
import { ModalContent, Body, notifications } from "@budibase/bbui"
|
||||||
import PasswordRepeatInput from "@/components/common/users/PasswordRepeatInput.svelte"
|
import PasswordRepeatInput from "./PasswordRepeatInput.svelte"
|
||||||
import { auth } from "@/stores/portal"
|
import type { APIClient } from "@budibase/frontend-core"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
let password
|
export let API: APIClient
|
||||||
let error
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
let password: string = ""
|
||||||
|
let error: string = ""
|
||||||
|
|
||||||
const updatePassword = async () => {
|
const updatePassword = async () => {
|
||||||
try {
|
try {
|
||||||
await auth.updateSelf({ password })
|
await API.updateSelf({ password })
|
||||||
|
dispatch("save")
|
||||||
notifications.success("Password changed successfully")
|
notifications.success("Password changed successfully")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Failed to update password")
|
notifications.error("Failed to update password")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeydown = evt => {
|
const handleKeydown = (evt: KeyboardEvent) => {
|
||||||
if (evt.key === "Enter" && !error && password) {
|
if (evt.key === "Enter" && !error && password) {
|
||||||
updatePassword()
|
updatePassword()
|
||||||
}
|
}
|
||||||
|
@ -27,7 +33,7 @@
|
||||||
title="Update password"
|
title="Update password"
|
||||||
confirmText="Update password"
|
confirmText="Update password"
|
||||||
onConfirm={updatePassword}
|
onConfirm={updatePassword}
|
||||||
disabled={error || !password}
|
disabled={!!error || !password}
|
||||||
>
|
>
|
||||||
<Body size="S">Enter your new password below.</Body>
|
<Body size="S">Enter your new password below.</Body>
|
||||||
<PasswordRepeatInput bind:password bind:error />
|
<PasswordRepeatInput bind:password bind:error />
|
|
@ -1,20 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import { FancyForm, FancyInput } from "@budibase/bbui"
|
import { FancyForm, FancyInput } from "@budibase/bbui"
|
||||||
import {
|
import { createValidationStore, requiredValidator } from "../utils/validation"
|
||||||
createValidationStore,
|
|
||||||
requiredValidator,
|
|
||||||
} from "@/helpers/validation"
|
|
||||||
import { admin } from "@/stores/portal"
|
|
||||||
|
|
||||||
export let password
|
export let password
|
||||||
export let passwordForm
|
|
||||||
export let error
|
export let error
|
||||||
|
export let minLength = 12
|
||||||
$: passwordMinLength = $admin.passwordMinLength ?? 12
|
|
||||||
|
|
||||||
const validatePassword = value => {
|
const validatePassword = value => {
|
||||||
if (!value || value.length < passwordMinLength) {
|
if (!value || value.length < minLength) {
|
||||||
return `Please enter at least ${passwordMinLength} characters. We recommend using machine generated or random passwords.`
|
return `Please enter at least ${minLength} characters. We recommend using machine generated or random passwords.`
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -41,7 +35,7 @@
|
||||||
firstPasswordError
|
firstPasswordError
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FancyForm bind:this={passwordForm}>
|
<FancyForm>
|
||||||
<FancyInput
|
<FancyInput
|
||||||
label="Password"
|
label="Password"
|
||||||
type="password"
|
type="password"
|
|
@ -1,16 +1,26 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { ModalContent, Body, Input, notifications } from "@budibase/bbui"
|
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { auth } from "@/stores/portal"
|
import { ModalContent, Body, Input, notifications } from "@budibase/bbui"
|
||||||
|
import type { User, ContextUser } from "@budibase/types"
|
||||||
|
import type { APIClient } from "@budibase/frontend-core"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
|
export let user: User | ContextUser | undefined = undefined
|
||||||
|
export let API: APIClient
|
||||||
|
|
||||||
|
$: console.log(user)
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
const values = writable({
|
const values = writable({
|
||||||
firstName: $auth.user.firstName,
|
firstName: user?.firstName,
|
||||||
lastName: $auth.user.lastName,
|
lastName: user?.lastName,
|
||||||
})
|
})
|
||||||
|
|
||||||
const updateInfo = async () => {
|
const updateInfo = async () => {
|
||||||
try {
|
try {
|
||||||
await auth.updateSelf($values)
|
await API.updateSelf($values)
|
||||||
|
dispatch("save")
|
||||||
notifications.success("Information updated successfully")
|
notifications.success("Information updated successfully")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
@ -23,7 +33,7 @@
|
||||||
<Body size="S">
|
<Body size="S">
|
||||||
Personalise the platform by adding your first name and last name.
|
Personalise the platform by adding your first name and last name.
|
||||||
</Body>
|
</Body>
|
||||||
<Input disabled bind:value={$auth.user.email} label="Email" />
|
<Input disabled value={user?.email || ""} label="Email" />
|
||||||
<Input bind:value={$values.firstName} label="First name" />
|
<Input bind:value={$values.firstName} label="First name" />
|
||||||
<Input bind:value={$values.lastName} label="Last name" />
|
<Input bind:value={$values.lastName} label="Last name" />
|
||||||
</ModalContent>
|
</ModalContent>
|
|
@ -9,3 +9,5 @@ export { Grid } from "./grid"
|
||||||
export { default as ClientAppSkeleton } from "./ClientAppSkeleton.svelte"
|
export { default as ClientAppSkeleton } from "./ClientAppSkeleton.svelte"
|
||||||
export { default as CoreFilterBuilder } from "./CoreFilterBuilder.svelte"
|
export { default as CoreFilterBuilder } from "./CoreFilterBuilder.svelte"
|
||||||
export { default as FilterUsers } from "./FilterUsers.svelte"
|
export { default as FilterUsers } from "./FilterUsers.svelte"
|
||||||
|
export { default as ChangePasswordModal } from "./ChangePasswordModal.svelte"
|
||||||
|
export { default as ProfileModal } from "./ProfileModal.svelte"
|
||||||
|
|
|
@ -166,3 +166,9 @@ export const FieldPermissions = {
|
||||||
READONLY: "readonly",
|
READONLY: "readonly",
|
||||||
HIDDEN: "hidden",
|
HIDDEN: "hidden",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// one or more word characters and whitespace
|
||||||
|
export const APP_NAME_REGEX = /^[\w\s]+$/
|
||||||
|
|
||||||
|
// zero or more non-whitespace characters
|
||||||
|
export const APP_URL_REGEX = /^[0-9a-zA-Z-_]+$/
|
||||||
|
|
|
@ -14,3 +14,4 @@ export * from "./settings"
|
||||||
export * from "./relatedColumns"
|
export * from "./relatedColumns"
|
||||||
export * from "./table"
|
export * from "./table"
|
||||||
export * from "./components"
|
export * from "./components"
|
||||||
|
export * from "./validation"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { string, mixed } from "yup"
|
import { string, mixed } from "yup"
|
||||||
import { APP_NAME_REGEX, APP_URL_REGEX } from "@/constants"
|
import { APP_NAME_REGEX, APP_URL_REGEX } from "../../../constants"
|
||||||
|
|
||||||
export const name = (validation, { apps, currentApp } = { apps: [] }) => {
|
export const name = (validation, { apps, currentApp } = { apps: [] }) => {
|
||||||
validation.addValidator(
|
validation.addValidator(
|
|
@ -1,7 +1,6 @@
|
||||||
import { capitalise } from "@/helpers"
|
|
||||||
import { object, string, number } from "yup"
|
import { object, string, number } from "yup"
|
||||||
import { writable, get } from "svelte/store"
|
import { writable, get } from "svelte/store"
|
||||||
import { notifications } from "@budibase/bbui"
|
import { Helpers, notifications } from "@budibase/bbui"
|
||||||
|
|
||||||
export const createValidationStore = () => {
|
export const createValidationStore = () => {
|
||||||
const DEFAULT = {
|
const DEFAULT = {
|
||||||
|
@ -77,7 +76,7 @@ export const createValidationStore = () => {
|
||||||
const [fieldError] = error.errors
|
const [fieldError] = error.errors
|
||||||
if (fieldError) {
|
if (fieldError) {
|
||||||
validation.update(store => {
|
validation.update(store => {
|
||||||
store.errors[propertyName] = capitalise(fieldError)
|
store.errors[propertyName] = Helpers.capitalise(fieldError)
|
||||||
store.valid = false
|
store.valid = false
|
||||||
return store
|
return store
|
||||||
})
|
})
|
||||||
|
@ -120,7 +119,7 @@ export const createValidationStore = () => {
|
||||||
} else {
|
} else {
|
||||||
error.inner.forEach(err => {
|
error.inner.forEach(err => {
|
||||||
validation.update(store => {
|
validation.update(store => {
|
||||||
store.errors[err.path] = capitalise(err.message)
|
store.errors[err.path] = Helpers.capitalise(err.message)
|
||||||
return store
|
return store
|
||||||
})
|
})
|
||||||
})
|
})
|
Loading…
Reference in New Issue