overview card updates
This commit is contained in:
parent
f980d55af3
commit
545f3d62b7
|
@ -148,28 +148,6 @@ export function getTemplateParams(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new user group ID
|
||||
* @returns {string} The new user group ID which info can be stored under.
|
||||
*/
|
||||
exports.generateUserGroupID = () => {
|
||||
return `${DocumentTypes.GROUP}${SEPARATOR}${newid()}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameters for retrieving groups.
|
||||
*/
|
||||
exports.getUserGroupsParams = (groupId: any, otherProps = {}) => {
|
||||
if (!groupId) {
|
||||
groupId = ""
|
||||
}
|
||||
return {
|
||||
...otherProps,
|
||||
startkey: `${DocumentTypes.GROUP}${SEPARATOR}${groupId}`,
|
||||
endkey: `${DocumentTypes.GROUP}${SEPARATOR}${groupId}${UNICODE_MAX}`,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new role ID.
|
||||
* @returns {string} The new role ID which the role doc can be stored under.
|
||||
|
|
|
@ -23,10 +23,13 @@
|
|||
let assignmentModal
|
||||
let appGroups = []
|
||||
let appUsers = []
|
||||
let prevSearch = undefined,
|
||||
search = undefined
|
||||
let pageInfo = createPaginationStore()
|
||||
|
||||
$: page = $pageInfo.page
|
||||
$: fetchUsers(page)
|
||||
$: console.log(page)
|
||||
$: fetchUsers(page, search)
|
||||
|
||||
$: isProPlan = $auth.user?.license.plan.type === Constants.PlanType.FREE
|
||||
|
||||
|
@ -43,19 +46,6 @@
|
|||
})
|
||||
})
|
||||
|
||||
$: filteredUsers =
|
||||
$users.data?.filter(x => {
|
||||
return !Object.keys(x.roles).find(y => {
|
||||
return extractAppId(y) === extractAppId(app.appId)
|
||||
})
|
||||
}) || []
|
||||
|
||||
$: filteredGroups = $groups.filter(element => {
|
||||
return !element.apps.find(y => {
|
||||
return y.appId === app.appId
|
||||
})
|
||||
})
|
||||
|
||||
function extractAppId(id) {
|
||||
const split = id?.split("_") || []
|
||||
return split.length ? split[split.length - 1] : null
|
||||
|
@ -99,10 +89,16 @@
|
|||
groups.actions.save(group)
|
||||
}
|
||||
|
||||
async function fetchUsers(page) {
|
||||
async function fetchUsers(page, search) {
|
||||
if ($pageInfo.loading) {
|
||||
return
|
||||
}
|
||||
// need to remove the page if they've started searching
|
||||
if (search && !prevSearch) {
|
||||
pageInfo.reset()
|
||||
page = undefined
|
||||
}
|
||||
prevSearch = search
|
||||
try {
|
||||
pageInfo.loading()
|
||||
await users.search({ page, appId: app.appId })
|
||||
|
@ -136,7 +132,7 @@
|
|||
>
|
||||
</div>
|
||||
</div>
|
||||
{#if isProPlan}
|
||||
{#if isProPlan && appGroups.length}
|
||||
<List title="User Groups">
|
||||
{#each appGroups as group}
|
||||
<ListItem
|
||||
|
@ -154,31 +150,33 @@
|
|||
{/each}
|
||||
</List>
|
||||
{/if}
|
||||
<List title="Users">
|
||||
{#each appUsers as user}
|
||||
<ListItem title={user.email} avatar>
|
||||
<RoleSelect
|
||||
on:change={e => updateUserRole(e.detail, user)}
|
||||
autoWidth
|
||||
quiet
|
||||
value={user.roles[
|
||||
Object.keys(user.roles).find(
|
||||
x => extractAppId(x) === extractAppId(app.appId)
|
||||
)
|
||||
]}
|
||||
/>
|
||||
</ListItem>
|
||||
{/each}
|
||||
</List>
|
||||
<div class="pagination">
|
||||
<Pagination
|
||||
page={$pageInfo.pageNumber}
|
||||
hasPrevPage={$pageInfo.loading ? false : $pageInfo.hasPrevPage}
|
||||
hasNextPage={$pageInfo.loading ? false : $pageInfo.hasNextPage}
|
||||
goToPrevPage={pageInfo.prevPage}
|
||||
goToNextPage={pageInfo.nextPage}
|
||||
/>
|
||||
</div>
|
||||
{#if appUsers.length}
|
||||
<List title="Users">
|
||||
{#each appUsers as user}
|
||||
<ListItem title={user.email} avatar>
|
||||
<RoleSelect
|
||||
on:change={e => updateUserRole(e.detail, user)}
|
||||
autoWidth
|
||||
quiet
|
||||
value={user.roles[
|
||||
Object.keys(user.roles).find(
|
||||
x => extractAppId(x) === extractAppId(app.appId)
|
||||
)
|
||||
]}
|
||||
/>
|
||||
</ListItem>
|
||||
{/each}
|
||||
</List>
|
||||
<div class="pagination">
|
||||
<Pagination
|
||||
page={$pageInfo.pageNumber}
|
||||
hasPrevPage={$pageInfo.loading ? false : $pageInfo.hasPrevPage}
|
||||
hasNextPage={$pageInfo.loading ? false : $pageInfo.hasNextPage}
|
||||
goToPrevPage={pageInfo.prevPage}
|
||||
goToNextPage={pageInfo.nextPage}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="align">
|
||||
<Layout gap="S">
|
||||
|
@ -200,11 +198,7 @@
|
|||
</div>
|
||||
|
||||
<Modal bind:this={assignmentModal}>
|
||||
<AssignmentModal
|
||||
userData={filteredUsers.length ? filteredUsers : $users.data}
|
||||
groups={isProPlan ? filteredGroups : []}
|
||||
{addData}
|
||||
/>
|
||||
<AssignmentModal {app} {appUsers} {addData} />
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,16 +1,54 @@
|
|||
<script>
|
||||
import { ModalContent, PickerDropdown, ActionButton } from "@budibase/bbui"
|
||||
import {
|
||||
ModalContent,
|
||||
PickerDropdown,
|
||||
ActionButton,
|
||||
notifications,
|
||||
} from "@budibase/bbui"
|
||||
import { roles } from "stores/backend"
|
||||
import { groups, users } from "stores/portal"
|
||||
import { RoleUtils } from "@budibase/frontend-core"
|
||||
import { createPaginationStore } from "helpers/pagination"
|
||||
|
||||
export let app
|
||||
export let addData
|
||||
export let userData = []
|
||||
export let groups = []
|
||||
export let appUsers = []
|
||||
|
||||
let prevSearch = undefined,
|
||||
search = undefined
|
||||
let pageInfo = createPaginationStore()
|
||||
|
||||
$: page = $pageInfo.page
|
||||
$: fetchUsers(page, search)
|
||||
async function fetchUsers(page, search) {
|
||||
if ($pageInfo.loading) {
|
||||
return
|
||||
}
|
||||
// need to remove the page if they've started searching
|
||||
if (search && !prevSearch) {
|
||||
pageInfo.reset()
|
||||
page = undefined
|
||||
}
|
||||
prevSearch = search
|
||||
try {
|
||||
pageInfo.loading()
|
||||
await users.search({ page, search })
|
||||
pageInfo.fetched($users.hasNextPage, $users.nextPage)
|
||||
} catch (error) {
|
||||
notifications.error("Error getting user list")
|
||||
}
|
||||
}
|
||||
|
||||
$: filteredGroups = $groups.filter(element => {
|
||||
return !element.apps.find(y => {
|
||||
return y.appId === app.appId
|
||||
})
|
||||
})
|
||||
|
||||
$: optionSections = {
|
||||
...(groups.length && {
|
||||
...(filteredGroups.length && {
|
||||
groups: {
|
||||
data: groups,
|
||||
data: filteredGroups,
|
||||
getLabel: group => group.name,
|
||||
getValue: group => group._id,
|
||||
getIcon: group => group.icon,
|
||||
|
@ -18,7 +56,7 @@
|
|||
},
|
||||
}),
|
||||
users: {
|
||||
data: userData,
|
||||
data: $users.data.filter(u => !appUsers.find(x => x._id === u._id)),
|
||||
getLabel: user => user.email,
|
||||
getValue: user => user._id,
|
||||
getIcon: user => user.icon,
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
<script>
|
||||
import DashCard from "components/common/DashCard.svelte"
|
||||
import { AppStatus } from "constants"
|
||||
import { Icon, Heading, Link, Avatar, Layout } from "@budibase/bbui"
|
||||
import { Icon, Heading, Link, Avatar, Layout, Body } from "@budibase/bbui"
|
||||
import { store } from "builderStore"
|
||||
import clientPackage from "@budibase/client/package.json"
|
||||
import { processStringSync } from "@budibase/string-templates"
|
||||
import { users, auth } from "stores/portal"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { createEventDispatcher, onMount } from "svelte"
|
||||
|
||||
export let app
|
||||
export let deployments
|
||||
export let navigateTab
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const unpublishApp = () => {
|
||||
|
@ -18,7 +19,7 @@
|
|||
}
|
||||
|
||||
let appEditor, appEditorPromise
|
||||
|
||||
$: console.log($users.data)
|
||||
$: updateAvailable = clientPackage.version !== $store.version
|
||||
$: isPublished = app && app?.status === AppStatus.DEPLOYED
|
||||
$: appEditorId = !app?.updatedBy ? $auth.user._id : app?.updatedBy
|
||||
|
@ -37,6 +38,10 @@
|
|||
|
||||
return initials == "" ? user.email[0] : initials
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
await users.search({ page: undefined, appId: app.appId })
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="overview-tab">
|
||||
|
@ -132,6 +137,37 @@
|
|||
{/if}
|
||||
</div>
|
||||
</DashCard>
|
||||
<DashCard
|
||||
title={"Access"}
|
||||
showIcon={true}
|
||||
action={() => {
|
||||
navigateTab("Access")
|
||||
}}
|
||||
dataCy={"access"}
|
||||
>
|
||||
<div class="last-edited-content">
|
||||
{#if $users?.data?.length}
|
||||
<Layout noPadding gap="S">
|
||||
<div class="users-tab">
|
||||
{#each $users?.data as user}
|
||||
<Avatar size="M" initials={getInitials(user)} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="users-text">
|
||||
{$users?.data.length} users have access to this app
|
||||
</div>
|
||||
</Layout>
|
||||
{:else}
|
||||
<Layout noPadding gap="S">
|
||||
<Body>No users</Body>
|
||||
<div class="users-text">
|
||||
No users have been assigned to this app
|
||||
</div>
|
||||
</Layout>
|
||||
{/if}
|
||||
</div>
|
||||
</DashCard>
|
||||
</div>
|
||||
{#if false}
|
||||
<div class="bottom">
|
||||
|
@ -186,6 +222,14 @@
|
|||
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
|
||||
}
|
||||
|
||||
.users-tab {
|
||||
display: flex;
|
||||
gap: var(--spacing-m);
|
||||
}
|
||||
|
||||
.users-text {
|
||||
color: var(--spectrum-global-color-gray-600);
|
||||
}
|
||||
.overview-tab .bottom,
|
||||
.automation-metrics {
|
||||
display: grid;
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
const {
|
||||
generateUserGroupID,
|
||||
getUserGroupsParams,
|
||||
} = require("@budibase/backend-core/db")
|
||||
const { Configs } = require("../../../constants")
|
||||
const email = require("../../../utilities/email")
|
||||
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
||||
|
@ -11,13 +7,14 @@ const {
|
|||
CacheKeys,
|
||||
bustCache,
|
||||
} = require("@budibase/backend-core/cache")
|
||||
const { groups } = require("@budibase/pro")
|
||||
|
||||
exports.save = async function (ctx: any) {
|
||||
const db = getGlobalDB()
|
||||
|
||||
// Config does not exist yet
|
||||
if (!ctx.request.body._id) {
|
||||
ctx.request.body._id = generateUserGroupID(ctx.request.body.name)
|
||||
ctx.request.body._id = groups.generateUserGroupID(ctx.request.body.name)
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -34,7 +31,7 @@ exports.save = async function (ctx: any) {
|
|||
exports.fetch = async function (ctx: any) {
|
||||
const db = getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
getUserGroupsParams(null, {
|
||||
groups.getUserGroupsParams(null, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue