Merge pull request #7981 from Budibase/feature/group-app-add
Add apps to a group from within groups interface
This commit is contained in:
commit
190c54fb86
|
@ -36,6 +36,7 @@ exports.getDevelopmentAppID = appId => {
|
||||||
const rest = split.join(APP_PREFIX)
|
const rest = split.join(APP_PREFIX)
|
||||||
return `${APP_DEV_PREFIX}${rest}`
|
return `${APP_DEV_PREFIX}${rest}`
|
||||||
}
|
}
|
||||||
|
exports.getDevAppID = exports.getDevelopmentAppID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a development app ID to a deployed app ID.
|
* Convert a development app ID to a deployed app ID.
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
{
|
{
|
||||||
title: "Plugins",
|
title: "Plugins",
|
||||||
href: "/builder/portal/manage/plugins",
|
href: "/builder/portal/manage/plugins",
|
||||||
badge: "Beta",
|
badge: "New",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
import CreateEditGroupModal from "./_components/CreateEditGroupModal.svelte"
|
import CreateEditGroupModal from "./_components/CreateEditGroupModal.svelte"
|
||||||
import GroupIcon from "./_components/GroupIcon.svelte"
|
import GroupIcon from "./_components/GroupIcon.svelte"
|
||||||
|
import AppAddModal from "./_components/AppAddModal.svelte"
|
||||||
|
|
||||||
export let groupId
|
export let groupId
|
||||||
|
|
||||||
|
@ -34,8 +35,7 @@
|
||||||
let prevSearch = undefined
|
let prevSearch = undefined
|
||||||
let pageInfo = createPaginationStore()
|
let pageInfo = createPaginationStore()
|
||||||
let loaded = false
|
let loaded = false
|
||||||
let editModal
|
let editModal, deleteModal, appAddModal
|
||||||
let deleteModal
|
|
||||||
|
|
||||||
$: page = $pageInfo.page
|
$: page = $pageInfo.page
|
||||||
$: fetchUsers(page, searchTerm)
|
$: fetchUsers(page, searchTerm)
|
||||||
|
@ -182,7 +182,14 @@
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<Layout noPadding gap="S">
|
<Layout noPadding gap="S">
|
||||||
|
<div class="header">
|
||||||
<Heading size="S">Apps</Heading>
|
<Heading size="S">Apps</Heading>
|
||||||
|
<div>
|
||||||
|
<Button on:click={appAddModal.show()} icon="ExperienceAdd" cta>
|
||||||
|
Add app
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<List>
|
<List>
|
||||||
{#if groupApps.length}
|
{#if groupApps.length}
|
||||||
{#each groupApps as app}
|
{#each groupApps as app}
|
||||||
|
@ -203,6 +210,18 @@
|
||||||
{getRoleLabel(app.appId)}
|
{getRoleLabel(app.appId)}
|
||||||
</StatusLight>
|
</StatusLight>
|
||||||
</div>
|
</div>
|
||||||
|
<Icon
|
||||||
|
on:click={e => {
|
||||||
|
groups.actions.removeApp(
|
||||||
|
groupId,
|
||||||
|
apps.getProdAppID(app.appId)
|
||||||
|
)
|
||||||
|
e.stopPropagation()
|
||||||
|
}}
|
||||||
|
hoverable
|
||||||
|
size="S"
|
||||||
|
name="Close"
|
||||||
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -216,6 +235,11 @@
|
||||||
<Modal bind:this={editModal}>
|
<Modal bind:this={editModal}>
|
||||||
<CreateEditGroupModal {group} {saveGroup} />
|
<CreateEditGroupModal {group} {saveGroup} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<Modal bind:this={appAddModal}>
|
||||||
|
<AppAddModal {group} />
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
bind:this={deleteModal}
|
bind:this={deleteModal}
|
||||||
title="Delete user group"
|
title="Delete user group"
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<script>
|
||||||
|
import { Body, ModalContent, Select } from "@budibase/bbui"
|
||||||
|
import { apps, groups } from "stores/portal"
|
||||||
|
import { roles } from "stores/backend"
|
||||||
|
import RoleSelect from "components/common/RoleSelect.svelte"
|
||||||
|
|
||||||
|
export let group
|
||||||
|
|
||||||
|
$: appOptions = $apps.map(app => ({
|
||||||
|
label: app.name,
|
||||||
|
value: app,
|
||||||
|
}))
|
||||||
|
$: prodAppId = selectedApp ? apps.getProdAppID(selectedApp.appId) : ""
|
||||||
|
$: confirmDisabled =
|
||||||
|
(!selectingRole && !selectedApp) || (selectingRole && !selectedRoleId)
|
||||||
|
let selectedApp, selectedRoleId
|
||||||
|
let selectingRole = false
|
||||||
|
|
||||||
|
async function appSelected() {
|
||||||
|
if (!selectingRole) {
|
||||||
|
selectingRole = true
|
||||||
|
await roles.fetchByAppId(prodAppId)
|
||||||
|
// return false to stop closing modal
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
await groups.actions.addApp(group._id, prodAppId, selectedRoleId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ModalContent
|
||||||
|
onConfirm={appSelected}
|
||||||
|
size="M"
|
||||||
|
title="Add app to group"
|
||||||
|
confirmText={selectingRole ? "Confirm" : "Next"}
|
||||||
|
showSecondaryButton={selectingRole}
|
||||||
|
secondaryButtonText="Back"
|
||||||
|
secondaryAction={() => (selectingRole = false)}
|
||||||
|
disabled={confirmDisabled}
|
||||||
|
>
|
||||||
|
{#if !selectingRole}
|
||||||
|
<Body
|
||||||
|
>Select an app to assign roles for members of <i>"{group.name}"</i></Body
|
||||||
|
>
|
||||||
|
<Select bind:value={selectedApp} options={appOptions} />
|
||||||
|
{:else}
|
||||||
|
<Body
|
||||||
|
>Select the role that all members of "<i>{group.name}</i>" will have for
|
||||||
|
<i>"{selectedApp.name}"</i></Body
|
||||||
|
>
|
||||||
|
<RoleSelect allowPublic={false} bind:value={selectedRoleId} />
|
||||||
|
{/if}
|
||||||
|
</ModalContent>
|
|
@ -5,9 +5,7 @@ import { RoleUtils } from "@budibase/frontend-core"
|
||||||
export function createRolesStore() {
|
export function createRolesStore() {
|
||||||
const { subscribe, update, set } = writable([])
|
const { subscribe, update, set } = writable([])
|
||||||
|
|
||||||
const actions = {
|
function setRoles(roles) {
|
||||||
fetch: async () => {
|
|
||||||
const roles = await API.getRoles()
|
|
||||||
set(
|
set(
|
||||||
roles.sort((a, b) => {
|
roles.sort((a, b) => {
|
||||||
const priorityA = RoleUtils.getRolePriority(a._id)
|
const priorityA = RoleUtils.getRolePriority(a._id)
|
||||||
|
@ -15,6 +13,16 @@ export function createRolesStore() {
|
||||||
return priorityA > priorityB ? -1 : 1
|
return priorityA > priorityB ? -1 : 1
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
fetch: async () => {
|
||||||
|
const roles = await API.getRoles()
|
||||||
|
setRoles(roles)
|
||||||
|
},
|
||||||
|
fetchByAppId: async appId => {
|
||||||
|
const { roles } = await API.getRolesForApp(appId)
|
||||||
|
setRoles(roles)
|
||||||
},
|
},
|
||||||
delete: async role => {
|
delete: async role => {
|
||||||
await API.deleteRole({
|
await API.deleteRole({
|
||||||
|
|
|
@ -29,4 +29,13 @@ export const buildRoleEndpoints = API => ({
|
||||||
url: "/api/roles",
|
url: "/api/roles",
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of roles within a specified app.
|
||||||
|
*/
|
||||||
|
getRolesForApp: async appId => {
|
||||||
|
return await API.get({
|
||||||
|
url: `/api/global/roles/${appId}`,
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,6 +2,7 @@ const { getAllRoles } = require("@budibase/backend-core/roles")
|
||||||
const {
|
const {
|
||||||
getAllApps,
|
getAllApps,
|
||||||
getProdAppID,
|
getProdAppID,
|
||||||
|
getDevAppID,
|
||||||
DocumentType,
|
DocumentType,
|
||||||
} = require("@budibase/backend-core/db")
|
} = require("@budibase/backend-core/db")
|
||||||
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
||||||
|
@ -34,7 +35,7 @@ exports.fetch = async ctx => {
|
||||||
|
|
||||||
exports.find = async ctx => {
|
exports.find = async ctx => {
|
||||||
const appId = ctx.params.appId
|
const appId = ctx.params.appId
|
||||||
await doInAppContext(appId, async () => {
|
await doInAppContext(getDevAppID(appId), async () => {
|
||||||
const db = getAppDB()
|
const db = getAppDB()
|
||||||
const app = await db.get(DocumentType.APP_METADATA)
|
const app = await db.get(DocumentType.APP_METADATA)
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
|
|
Loading…
Reference in New Issue