Convert portal groups store to TS

This commit is contained in:
Andrew Kingston 2025-01-03 12:07:04 +00:00
parent cf4122e204
commit a286685900
No known key found for this signature in database
12 changed files with 125 additions and 132 deletions

View File

@ -236,13 +236,13 @@
} }
if (!role) { if (!role) {
await groups.actions.removeApp(target._id, prodAppId) await groups.removeApp(target._id, prodAppId)
} else { } else {
await groups.actions.addApp(target._id, prodAppId, role) await groups.addApp(target._id, prodAppId, role)
} }
await usersFetch.refresh() await usersFetch.refresh()
await groups.actions.init() await groups.init()
} }
const onUpdateGroup = async (group, role) => { const onUpdateGroup = async (group, role) => {
@ -268,7 +268,7 @@
if (!group.roles) { if (!group.roles) {
return false return false
} }
return groups.actions.getGroupAppIds(group).includes(appId) return groups.getGroupAppIds(group).includes(appId)
}) })
} }
@ -299,7 +299,7 @@
role: group?.builder?.apps.includes(prodAppId) role: group?.builder?.apps.includes(prodAppId)
? Constants.Roles.CREATOR ? Constants.Roles.CREATOR
: group.roles?.[ : group.roles?.[
groups.actions.getGroupAppIds(group).find(x => x === prodAppId) groups.getGroupAppIds(group).find(x => x === prodAppId)
], ],
} }
} }
@ -485,12 +485,12 @@
} }
const removeGroupAppBuilder = async groupId => { const removeGroupAppBuilder = async groupId => {
await groups.actions.removeGroupAppBuilder(groupId, prodAppId) await groups.removeGroupAppBuilder(groupId, prodAppId)
} }
const initSidePanel = async sidePaneOpen => { const initSidePanel = async sidePaneOpen => {
if (sidePaneOpen === true) { if (sidePaneOpen === true) {
await groups.actions.init() await groups.init()
} }
loaded = true loaded = true
} }

View File

@ -53,7 +53,7 @@
} }
if (!Object.keys(user?.roles).length && user?.userGroups) { if (!Object.keys(user?.roles).length && user?.userGroups) {
return userGroups.find(group => { return userGroups.find(group => {
return groups.actions return groups
.getGroupAppIds(group) .getGroupAppIds(group)
.map(role => appsStore.extractAppId(role)) .map(role => appsStore.extractAppId(role))
.includes(app.appId) .includes(app.appId)
@ -86,7 +86,7 @@
try { try {
await organisation.init() await organisation.init()
await appsStore.load() await appsStore.load()
await groups.actions.init() await groups.init()
} catch (error) { } catch (error) {
notifications.error("Error loading apps") notifications.error("Error loading apps")
} }

View File

@ -24,7 +24,7 @@
promises.push(templates.load()) promises.push(templates.load())
} }
promises.push(groups.actions.init()) promises.push(groups.init())
// Always load latest // Always load latest
await Promise.all(promises) await Promise.all(promises)

View File

@ -53,9 +53,7 @@
$: readonly = !isAdmin || isScimGroup $: readonly = !isAdmin || isScimGroup
$: groupApps = $appsStore.apps $: groupApps = $appsStore.apps
.filter(app => .filter(app =>
groups.actions groups.getGroupAppIds(group).includes(appsStore.getProdAppID(app.devId))
.getGroupAppIds(group)
.includes(appsStore.getProdAppID(app.devId))
) )
.map(app => ({ .map(app => ({
...app, ...app,
@ -72,7 +70,7 @@
async function deleteGroup() { async function deleteGroup() {
try { try {
await groups.actions.delete(group) await groups.delete(group)
notifications.success("User group deleted successfully") notifications.success("User group deleted successfully")
$goto("./") $goto("./")
} catch (error) { } catch (error) {
@ -82,7 +80,7 @@
async function saveGroup(group) { async function saveGroup(group) {
try { try {
await groups.actions.save(group) await groups.save(group)
} catch (error) { } catch (error) {
if (error.message) { if (error.message) {
notifications.error(error.message) notifications.error(error.message)
@ -93,7 +91,7 @@
} }
const removeApp = async app => { const removeApp = async app => {
await groups.actions.removeApp(groupId, appsStore.getProdAppID(app.devId)) await groups.removeApp(groupId, appsStore.getProdAppID(app.devId))
} }
setContext("roles", { setContext("roles", {
updateRole: () => {}, updateRole: () => {},
@ -102,7 +100,7 @@
onMount(async () => { onMount(async () => {
try { try {
await Promise.all([groups.actions.init(), roles.fetch()]) await Promise.all([groups.init(), roles.fetch()])
loaded = true loaded = true
} catch (error) { } catch (error) {
notifications.error("Error fetching user group data") notifications.error("Error fetching user group data")

View File

@ -23,7 +23,7 @@
return keepOpen return keepOpen
} else { } else {
await groups.actions.addApp(group._id, prodAppId, selectedRoleId) await groups.addApp(group._id, prodAppId, selectedRoleId)
} }
} }
</script> </script>

View File

@ -50,11 +50,11 @@
selected={group.users?.map(user => user._id)} selected={group.users?.map(user => user._id)}
list={$users.data} list={$users.data}
on:select={async e => { on:select={async e => {
await groups.actions.addUser(groupId, e.detail) await groups.addUser(groupId, e.detail)
onUsersUpdated() onUsersUpdated()
}} }}
on:deselect={async e => { on:deselect={async e => {
await groups.actions.removeUser(groupId, e.detail) await groups.removeUser(groupId, e.detail)
onUsersUpdated() onUsersUpdated()
}} }}
/> />

View File

@ -60,7 +60,7 @@
async function saveGroup(group) { async function saveGroup(group) {
try { try {
group = await groups.actions.save(group) group = await groups.save(group)
$goto(`./${group._id}`) $goto(`./${group._id}`)
notifications.success(`User group created successfully`) notifications.success(`User group created successfully`)
} catch (error) { } catch (error) {
@ -83,7 +83,7 @@
try { try {
// always load latest // always load latest
await licensing.init() await licensing.init()
await groups.actions.init() await groups.init()
} catch (error) { } catch (error) {
notifications.error("Error getting user groups") notifications.error("Error getting user groups")
} }

View File

@ -219,12 +219,12 @@
} }
const addGroup = async groupId => { const addGroup = async groupId => {
await groups.actions.addUser(groupId, userId) await groups.addUser(groupId, userId)
await fetchUser() await fetchUser()
} }
const removeGroup = async groupId => { const removeGroup = async groupId => {
await groups.actions.removeUser(groupId, userId) await groups.removeUser(groupId, userId)
await fetchUser() await fetchUser()
} }
@ -234,7 +234,7 @@
onMount(async () => { onMount(async () => {
try { try {
await Promise.all([fetchUser(), groups.actions.init(), roles.fetch()]) await Promise.all([fetchUser(), groups.init(), roles.fetch()])
loaded = true loaded = true
} catch (error) { } catch (error) {
notifications.error("Error getting user groups") notifications.error("Error getting user groups")

View File

@ -247,7 +247,7 @@
try { try {
bulkSaveResponse = await users.create(await removingDuplicities(userData)) bulkSaveResponse = await users.create(await removingDuplicities(userData))
notifications.success("Successfully created user") notifications.success("Successfully created user")
await groups.actions.init() await groups.init()
passwordModal.show() passwordModal.show()
await fetch.refresh() await fetch.refresh()
} catch (error) { } catch (error) {
@ -317,7 +317,7 @@
onMount(async () => { onMount(async () => {
try { try {
await groups.actions.init() await groups.init()
groupsLoaded = true groupsLoaded = true
} catch (error) { } catch (error) {
notifications.error("Error fetching user group data") notifications.error("Error fetching user group data")

View File

@ -1,103 +0,0 @@
import { writable, get } from "svelte/store"
import { API } from "@/api"
import { licensing } from "@/stores/portal"
export function createGroupsStore() {
const store = writable([])
const updateStore = group => {
store.update(state => {
const currentIdx = state.findIndex(gr => gr._id === group._id)
if (currentIdx >= 0) {
state.splice(currentIdx, 1, group)
} else {
state.push(group)
}
return state
})
}
const getGroup = async groupId => {
const group = await API.getGroup(groupId)
updateStore(group)
}
const actions = {
init: async () => {
// only init if there is a groups license, just to be sure but the feature will be blocked
// on the backend anyway
if (get(licensing).groupsEnabled) {
const groups = await API.getGroups()
store.set(groups.data)
}
},
get: getGroup,
save: async group => {
const { ...dataToSave } = group
delete dataToSave.scimInfo
delete dataToSave.userGroups
const response = await API.saveGroup(dataToSave)
group._id = response._id
group._rev = response._rev
updateStore(group)
return group
},
delete: async group => {
await API.deleteGroup(group._id, group._rev)
store.update(state => {
state = state.filter(state => state._id !== group._id)
return state
})
},
addUser: async (groupId, userId) => {
await API.addUsersToGroup(groupId, userId)
// refresh the group enrichment
await getGroup(groupId)
},
removeUser: async (groupId, userId) => {
await API.removeUsersFromGroup(groupId, userId)
// refresh the group enrichment
await getGroup(groupId)
},
addApp: async (groupId, appId, roleId) => {
await API.addAppsToGroup(groupId, [{ appId, roleId }])
// refresh the group roles
await getGroup(groupId)
},
removeApp: async (groupId, appId) => {
await API.removeAppsFromGroup(groupId, [{ appId }])
// refresh the group roles
await getGroup(groupId)
},
getGroupAppIds: group => {
let groupAppIds = Object.keys(group?.roles || {})
if (group?.builder?.apps) {
groupAppIds = groupAppIds.concat(group.builder.apps)
}
return groupAppIds
},
addGroupAppBuilder: async (groupId, appId) => {
return await API.addGroupAppBuilder(groupId, appId)
},
removeGroupAppBuilder: async (groupId, appId) => {
return await API.removeGroupAppBuilder(groupId, appId)
},
}
return {
subscribe: store.subscribe,
actions,
}
}
export const groups = createGroupsStore()

View File

@ -0,0 +1,93 @@
import { get } from "svelte/store"
import { API } from "@/api"
import { licensing } from "@/stores/portal"
import { UserGroup } from "@budibase/types"
import { BudiStore } from "../BudiStore"
class GroupStore extends BudiStore<UserGroup[]> {
constructor() {
super([])
}
updateStore = (group: UserGroup) => {
this.update(state => {
const currentIdx = state.findIndex(gr => gr._id === group._id)
if (currentIdx >= 0) {
state.splice(currentIdx, 1, group)
} else {
state.push(group)
}
return state
})
}
async init() {
// Only init if there is a groups license, just to be sure but the feature will be blocked
// on the backend anyway
if (get(licensing).groupsEnabled) {
const groups = await API.getGroups()
this.set(groups)
}
}
private async refreshGroup(groupId: string) {
const group = await API.getGroup(groupId)
this.updateStore(group)
}
async save(group: UserGroup) {
const { ...dataToSave } = group
delete dataToSave.scimInfo
const response = await API.saveGroup(dataToSave)
group._id = response._id
group._rev = response._rev
this.updateStore(group)
return group
}
async delete(group: UserGroup) {
await API.deleteGroup(group._id!, group._rev!)
this.update(state => {
state = state.filter(state => state._id !== group._id)
return state
})
}
async addUser(groupId: string, userId: string) {
await API.addUsersToGroup(groupId, [userId])
await this.refreshGroup(groupId)
}
async removeUser(groupId: string, userId: string) {
await API.removeUsersFromGroup(groupId, [userId])
await this.refreshGroup(groupId)
}
async addApp(groupId: string, appId: string, roleId: string) {
await API.addAppsToGroup(groupId, [{ appId, roleId }])
await this.refreshGroup(groupId)
}
async removeApp(groupId: string, appId: string) {
await API.removeAppsFromGroup(groupId, [{ appId }])
await this.refreshGroup(groupId)
}
getGroupAppIds(group: UserGroup) {
let groupAppIds = Object.keys(group?.roles || {})
if (group?.builder?.apps) {
groupAppIds = groupAppIds.concat(group.builder.apps)
}
return groupAppIds
}
async addGroupAppBuilder(groupId: string, appId: string) {
return await API.addGroupAppBuilder(groupId, appId)
}
async removeGroupAppBuilder(groupId: string, appId: string) {
return await API.removeGroupAppBuilder(groupId, appId)
}
}
export const groups = new GroupStore()

View File

@ -1,4 +1,8 @@
import { SearchUserGroupResponse, UserGroup } from "@budibase/types" import {
SearchGroupResponse,
SearchUserGroupResponse,
UserGroup,
} from "@budibase/types"
import { BaseAPIClient } from "./types" import { BaseAPIClient } from "./types"
export interface GroupEndpoints { export interface GroupEndpoints {
@ -64,9 +68,10 @@ export const buildGroupsEndpoints = (API: BaseAPIClient): GroupEndpoints => {
* Gets all the user groups * Gets all the user groups
*/ */
getGroups: async () => { getGroups: async () => {
return await API.get({ const res = await API.get<SearchGroupResponse>({
url: "/api/global/groups", url: "/api/global/groups",
}) })
return res.data
}, },
/** /**