This commit is contained in:
Ruben Fiszel
2022-12-16 09:53:17 +01:00
parent 3735171a0d
commit 3e7751f705
5 changed files with 221 additions and 115 deletions
@@ -0,0 +1,166 @@
<script lang="ts">
import { userStore, workspaceStore } from '$lib/stores'
import { type Group, GroupService, UserService, GranularAclService } from '$lib/gen'
import AutoComplete from 'simple-svelte-autocomplete'
import TableCustom from './TableCustom.svelte'
import { canWrite } from '$lib/utils'
import { Button, ToggleButton, ToggleButtonGroup } from './common'
import Skeleton from './common/skeleton/Skeleton.svelte'
import Tooltip from './Tooltip.svelte'
export let name: string
let can_write = false
type Role = 'viewer' | 'member' | 'manager' | 'member_manager'
let group: Group | undefined
let members: { name: string; role: Role }[] | undefined = undefined
let usernames: string[] | undefined = []
let username: string = ''
async function loadUsernames(): Promise<void> {
usernames = await UserService.listUsernames({ workspace: $workspaceStore! })
}
$: {
if ($workspaceStore && $userStore) {
load()
}
}
async function load() {
await loadGroup()
await loadUsernames()
}
async function addToGroup() {
await GroupService.addUserToGroup({
workspace: $workspaceStore ?? '',
name,
requestBody: { username }
})
loadGroup()
}
async function loadGroup(): Promise<void> {
group = await GroupService.getGroup({ workspace: $workspaceStore!, name })
can_write = canWrite(group.name!, group.extra_perms ?? {}, $userStore)
members = Object.keys(group?.extra_perms ?? {})
.concat(group?.members ?? [])
.map((x) => {
return {
name: x,
role: getRole(x)
}
})
}
function getRole(x: string): Role {
const writer = x in (group?.extra_perms ?? {}) && (group?.extra_perms ?? {})[name]
const member = group?.members?.includes(x)
if (writer && member) {
return 'member_manager'
} else if (writer) {
return 'manager'
} else if (member) {
return 'member'
}
return 'viewer'
}
</script>
<div class="flex flex-col gap-6">
<h2>Summary</h2>
{#if group}
<p>{group?.summary ?? 'No summary'}</p>
{:else}
<Skeleton layout={[[4]]} />
{/if}
<h2>Members</h2>
{#if can_write}
<div class="flex items-start">
<AutoComplete items={usernames} bind:selectedItem={username} />
<Button variant="contained" color="blue" size="sm" btnClasses="!ml-4" on:click={addToGroup}>
Add member
</Button>
</div>
{/if}
{#if members}
<TableCustom>
<tr slot="header-row">
<th>user</th>
<th />
<th />
</tr>
<tbody slot="body">
{#each members as { name, role }}<tr>
<td>{name}</td>
<td>
<ToggleButtonGroup
selected={role}
on:selected={async (e) => {
const group = e.detail
// const wasInGroup = (group?.members ?? []).includes(group)
// const inAcl = (
// group?.extra_perms ? Object.keys(group?.extra_perms) : []
// ).includes(group)
if (group == 'member') {
GroupService.addUserToGroup(group)
GranularAclService.removeGranularAcls({
workspace: $workspaceStore ?? '',
path: name,
kind: 'group_',
requestBody: $userStore.
})
}
loadGroup()
}}
>
<ToggleButton position="left" value="member" size="xs"
>Viewer <Tooltip
>A viewer can see who are the members and managers of a group</Tooltip
></ToggleButton
>
<ToggleButton position="left" value="member" size="xs"
>Member <Tooltip
>A Member of a group can see everything the group can see, write to everything
the group can write, and generally act on behalf of the group</Tooltip
></ToggleButton
>
<ToggleButton position="center" value="manager" size="xs"
>Manager <Tooltip
>A manager of a group can manage the group, adding and removing users and change
their roles. He is not necessarily a member of the group.</Tooltip
></ToggleButton
>
<ToggleButton position="right" value="member_manager" size="xs"
>Member & Manager</ToggleButton
>
</ToggleButtonGroup></td
>
<td>
{#if can_write}
<button
class="ml-2 text-red-500"
on:click={async () => {
await GroupService.removeUserToGroup({
workspace: $workspaceStore ?? '',
name: group?.name ?? '',
requestBody: { username: name }
})
loadGroup()
}}>remove</button
>
{/if}</td
>
</tr>{/each}
</tbody>
</TableCustom>
{:else}
<div class="flex flex-col">
{#each new Array(6) as _}
<Skeleton layout={[[2], 0.7]} />
{/each}
</div>
{/if}
</div>
@@ -1,105 +0,0 @@
<script lang="ts">
import { userStore, workspaceStore } from '$lib/stores'
import { type Group, GroupService, UserService } from '$lib/gen'
import AutoComplete from 'simple-svelte-autocomplete'
import TableCustom from './TableCustom.svelte'
import { canWrite } from '$lib/utils'
import { Button, Drawer } from './common'
import DrawerContent from './common/drawer/DrawerContent.svelte'
let name = ''
let drawer: Drawer
let can_write = false
let group: Group | undefined
let members: { name: string; isAdmin: boolean }[] = []
let usernames: string[] = []
let username: string = ''
async function loadUsernames(): Promise<void> {
usernames = await UserService.listUsernames({ workspace: $workspaceStore! })
}
$: {
if (group && $workspaceStore && userStore) {
members = (group.members ?? []).map((x) => {
return {
name: x,
isAdmin: x in (group?.extra_perms ?? {}) && (group?.extra_perms ?? {})[name]
}
})
}
}
export function openDrawer(newName: string): void {
name = newName
loadGroup()
loadUsernames()
drawer.openDrawer()
}
async function addToGroup() {
await GroupService.addUserToGroup({
workspace: $workspaceStore ?? '',
name,
requestBody: { username }
})
loadGroup()
}
async function loadGroup(): Promise<void> {
group = await GroupService.getGroup({ workspace: $workspaceStore!, name })
can_write = canWrite(group.name!, group.extra_perms ?? {}, $userStore)
}
</script>
<Drawer bind:this={drawer}>
<DrawerContent title="Group {name}" on:close={drawer.closeDrawer}>
<div class="flex flex-col gap-6">
<h2>Summary</h2>
<p>{group?.summary ?? 'No summary'}</p>
<h2>Members</h2>
{#if can_write}
<div class="flex items-start">
<AutoComplete items={usernames} bind:selectedItem={username} />
<Button
variant="contained"
color="blue"
size="sm"
btnClasses="!ml-4"
on:click={addToGroup}
>
Add member
</Button>
</div>
{/if}
<TableCustom>
<tr slot="header-row">
<th>user</th>
<th>admin of group</th>
<th />
</tr>
<tbody slot="body">
{#each members as { name, isAdmin }}<tr>
<td>{name}</td>
<td> {isAdmin ? 'admin' : ''} </td>
<td>
{#if can_write}
<button
class="ml-2 text-red-500"
on:click={async () => {
await GroupService.removeUserToGroup({
workspace: $workspaceStore ?? '',
name: group?.name ?? '',
requestBody: { username: name }
})
loadGroup()
}}>remove</button
>
{/if}</td
>
</tr>{/each}
</tbody>
</TableCustom>
</div>
</DrawerContent>
</Drawer>
+37 -1
View File
@@ -15,6 +15,9 @@
import { createEventDispatcher } from 'svelte'
import Required from './Required.svelte'
import Popover from './Popover.svelte'
import { Button, Drawer, DrawerContent } from './common'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import GroupEditor from './GroupEditor.svelte'
type PathKind = 'resource' | 'script' | 'variable' | 'flow' | 'schedule' | 'app'
let meta: Meta | undefined = undefined
@@ -155,8 +158,37 @@
path = initialPath
}
}
let newGroup: Drawer
let newGroupName: string
let groupCreated: string | undefined = undefined
async function addGroup() {
await GroupService.createGroup({
workspace: $workspaceStore ?? '',
requestBody: { name: newGroupName }
})
groupCreated = newGroupName
loadGroups()
}
</script>
<Drawer bind:this={newGroup}>
<DrawerContent title="New Group" on:close={newGroup.closeDrawer}>
<div class="flex flex-row">
<input class="mr-2" placeholder="New group name" bind:value={newGroupName} />
<Button size="md" startIcon={{ icon: faPlus }} disabled={!newGroupName} on:click={addGroup}>
New&nbsp;group
</Button>
</div>
{#if groupCreated}
<div class="mt-8" />
<GroupEditor name={groupCreated} />
{/if}
</DrawerContent>
</Drawer>
<div>
<div class="flex flex-col sm:grid sm:grid-cols-4 sm:gap-4 pb-0 mb-1">
{#if meta != undefined}
@@ -202,7 +234,11 @@
</label>
{:else}
<label class="block">
<span class="text-gray-700 text-sm">Owner</span>
<span class="text-gray-700 text-sm inline-flex justify-between w-full"
>Owner <button class=" text-xs text-blue-500" on:click={newGroup.openDrawer}
>+group</button
></span
>
<select {disabled} bind:value={meta.owner}>
{#each groups as g}
<option>{g.name}</option>
@@ -132,8 +132,10 @@
</div>
{/each}
{/if}
<InsertModuleButton on:new={(e) => insertNewModuleAtIndex(modules?.length ?? 0, e.detail)} />
<InsertModuleButton
trigger={modules?.length == 0}
on:new={(e) => insertNewModuleAtIndex(modules?.length ?? 0, e.detail)}
/>
</ul>
{#if root}
<div class="sticky bottom-0 bg-gray-50 flex-none px-4 py-1 pb-2 border-t">
+14 -7
View File
@@ -13,21 +13,21 @@
import CenteredPage from '$lib/components/CenteredPage.svelte'
import Dropdown from '$lib/components/Dropdown.svelte'
import GroupModal from '$lib/components/GroupModal.svelte'
import GroupEditor from '$lib/components/GroupEditor.svelte'
import PageHeader from '$lib/components/PageHeader.svelte'
import SharedBadge from '$lib/components/SharedBadge.svelte'
import ShareModal from '$lib/components/ShareModal.svelte'
import TableCustom from '$lib/components/TableCustom.svelte'
import { userStore, workspaceStore } from '$lib/stores'
import { faEdit, faPlus, faShare, faTrash } from '@fortawesome/free-solid-svg-icons'
import { Alert, Button } from '$lib/components/common'
import { Button, Drawer, DrawerContent } from '$lib/components/common'
type GroupW = Group & { canWrite: boolean }
let newGroupName: string = ''
let groups: GroupW[] = []
let shareModal: ShareModal
let groupModal: GroupModal
let groupDrawer: Drawer
async function loadGroups(): Promise<void> {
groups = (await GroupService.listGroups({ workspace: $workspaceStore! })).map((x) => {
@@ -55,6 +55,8 @@
loadGroups()
}
}
let editGroupName: string = ''
</script>
<ShareModal
@@ -65,7 +67,11 @@
}}
/>
<GroupModal bind:this={groupModal} />
<Drawer bind:this={groupDrawer}>
<DrawerContent title="Group {editGroupName}" on:close={groupDrawer.closeDrawer}>
<GroupEditor name={editGroupName} />
</DrawerContent>
</Drawer>
<CenteredPage>
<PageHeader
@@ -85,7 +91,6 @@
</div>
</PageHeader>
<div class="relative mb-20">
<TableCustom>
<tr slot="header-row">
@@ -100,7 +105,8 @@
<a
href="#{name}"
on:click={() => {
groupModal.openDrawer(name)
editGroupName = name
groupDrawer.openDrawer()
}}
>{name}
</a>
@@ -118,7 +124,8 @@
icon: faEdit,
disabled: !canWrite,
action: () => {
groupModal.openDrawer(name)
editGroupName = name
groupDrawer.openDrawer()
}
},
{