Merge pull request #15294 from Budibase/type-portal-group-store

Convert portal groups store to TS
This commit is contained in:
Andrew Kingston 2025-01-07 12:35:57 +00:00 committed by GitHub
commit 55685be081
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 128 additions and 132 deletions

View File

@ -236,13 +236,13 @@
}
if (!role) {
await groups.actions.removeApp(target._id, prodAppId)
await groups.removeApp(target._id, prodAppId)
} else {
await groups.actions.addApp(target._id, prodAppId, role)
await groups.addApp(target._id, prodAppId, role)
}
await usersFetch.refresh()
await groups.actions.init()
await groups.init()
}
const onUpdateGroup = async (group, role) => {
@ -268,7 +268,7 @@
if (!group.roles) {
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)
? Constants.Roles.CREATOR
: 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 => {
await groups.actions.removeGroupAppBuilder(groupId, prodAppId)
await groups.removeGroupAppBuilder(groupId, prodAppId)
}
const initSidePanel = async sidePaneOpen => {
if (sidePaneOpen === true) {
await groups.actions.init()
await groups.init()
}
loaded = true
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -247,7 +247,7 @@
try {
bulkSaveResponse = await users.create(await removingDuplicities(userData))
notifications.success("Successfully created user")
await groups.actions.init()
await groups.init()
passwordModal.show()
await fetch.refresh()
} catch (error) {
@ -317,7 +317,7 @@
onMount(async () => {
try {
await groups.actions.init()
await groups.init()
groupsLoaded = true
} catch (error) {
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,96 @@
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(groups => {
const index = groups.findIndex(g => g._id === group._id)
if (index !== -1) {
groups.splice(index, 1)
}
return groups
})
}
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"
export interface GroupEndpoints {
@ -64,9 +68,10 @@ export const buildGroupsEndpoints = (API: BaseAPIClient): GroupEndpoints => {
* Gets all the user groups
*/
getGroups: async () => {
return await API.get({
const res = await API.get<SearchGroupResponse>({
url: "/api/global/groups",
})
return res.data
},
/**