@nymphjs/tilmeld-setup 1.0.0-beta.121 → 1.0.0-beta.123
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +4 -2
- package/app/src/App.svelte +32 -66
- package/app/src/routes/GroupEdit.svelte +465 -42
- package/app/src/routes/Groups.svelte +24 -22
- package/app/src/routes/UserEdit.svelte +35 -44
- package/app/src/routes/Users.svelte +24 -22
- package/dist/app/index.js +6201 -1272
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/package.json +16 -13
- package/src/index.ts +3 -2
|
@@ -6,10 +6,7 @@
|
|
|
6
6
|
</section>
|
|
7
7
|
{:else}
|
|
8
8
|
<div style="display: flex; align-items: center; padding: 12px;">
|
|
9
|
-
<IconButton
|
|
10
|
-
title="Back"
|
|
11
|
-
onclick={() => router.navigate('', { historyAPIMethod: 'back' })}
|
|
12
|
-
>
|
|
9
|
+
<IconButton title="Back" onclick={() => pop()}>
|
|
13
10
|
<Icon tag="svg" viewBox="0 0 24 24">
|
|
14
11
|
<path fill="currentColor" d={mdiArrowLeft} />
|
|
15
12
|
</Icon>
|
|
@@ -23,7 +20,8 @@
|
|
|
23
20
|
{#await $entity.user.$wake() then _user}
|
|
24
21
|
<div style="padding: 12px;" class="mdc-typography--subtitle1">
|
|
25
22
|
Generated primary group for <a
|
|
26
|
-
href="
|
|
23
|
+
href="/users/edit/{encodeURIComponent($entity.user.guid || '')}"
|
|
24
|
+
use:link
|
|
27
25
|
>{$clientConfig.userFields.includes('name')
|
|
28
26
|
? $entity.user.name + ' (' + $entity.user.username + ')'
|
|
29
27
|
: $entity.user.username}</a
|
|
@@ -32,7 +30,10 @@
|
|
|
32
30
|
{/await}
|
|
33
31
|
{/if}
|
|
34
32
|
|
|
35
|
-
<TabBar
|
|
33
|
+
<TabBar
|
|
34
|
+
tabs={['General', 'Parent', 'Children', 'Abilities', 'Users']}
|
|
35
|
+
bind:active={activeTab}
|
|
36
|
+
>
|
|
36
37
|
{#snippet tab(tab)}
|
|
37
38
|
<Tab {tab}>
|
|
38
39
|
<Label>{tab}</Label>
|
|
@@ -194,7 +195,8 @@
|
|
|
194
195
|
No parent
|
|
195
196
|
{:else}
|
|
196
197
|
<a
|
|
197
|
-
href="
|
|
198
|
+
href="/groups/edit/{encodeURIComponent($entity.parent.guid || '')}"
|
|
199
|
+
use:link
|
|
198
200
|
>{$clientConfig.userFields.includes('name')
|
|
199
201
|
? $entity.parent.name + ' (' + $entity.parent.groupname + ')'
|
|
200
202
|
: $entity.parent.groupname}</a
|
|
@@ -285,6 +287,144 @@
|
|
|
285
287
|
{/if}
|
|
286
288
|
{/if}
|
|
287
289
|
|
|
290
|
+
{#if activeTab === 'Children'}
|
|
291
|
+
<h5 style="margin-top: 0;">Children</h5>
|
|
292
|
+
|
|
293
|
+
<DataTable
|
|
294
|
+
sortable
|
|
295
|
+
bind:sort={childrenSort}
|
|
296
|
+
bind:sortDirection={childrenSortDirection}
|
|
297
|
+
onSMUIDataTableSorted={handleChildrenSort}
|
|
298
|
+
table$aria-label="Children list"
|
|
299
|
+
style="width: 100%;"
|
|
300
|
+
>
|
|
301
|
+
<Head>
|
|
302
|
+
<Row>
|
|
303
|
+
{#if !$clientConfig.emailUsernames}
|
|
304
|
+
<Cell columnId="child-groupname">
|
|
305
|
+
<Label>Groupname</Label>
|
|
306
|
+
<IconButton>
|
|
307
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
308
|
+
</IconButton>
|
|
309
|
+
</Cell>
|
|
310
|
+
{/if}
|
|
311
|
+
{#if $clientConfig.userFields.includes('name')}
|
|
312
|
+
<Cell columnId="child-name">
|
|
313
|
+
<Label>Name</Label>
|
|
314
|
+
<IconButton>
|
|
315
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
316
|
+
</IconButton>
|
|
317
|
+
</Cell>
|
|
318
|
+
{/if}
|
|
319
|
+
{#if $clientConfig.userFields.includes('email')}
|
|
320
|
+
<Cell columnId="child-email">
|
|
321
|
+
<Label>Email</Label>
|
|
322
|
+
<IconButton>
|
|
323
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
324
|
+
</IconButton>
|
|
325
|
+
</Cell>
|
|
326
|
+
{/if}
|
|
327
|
+
<Cell columnId="child-enabled">
|
|
328
|
+
<Label>Enabled</Label>
|
|
329
|
+
<IconButton>
|
|
330
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
331
|
+
</IconButton>
|
|
332
|
+
</Cell>
|
|
333
|
+
</Row>
|
|
334
|
+
</Head>
|
|
335
|
+
<Body>
|
|
336
|
+
{#each $children as group (group.guid)}
|
|
337
|
+
<Row>
|
|
338
|
+
{#if !$clientConfig.emailUsernames}
|
|
339
|
+
<Cell
|
|
340
|
+
><a
|
|
341
|
+
href="/groups/edit/{encodeURIComponent(group.guid || '')}"
|
|
342
|
+
use:link>{group.groupname}</a
|
|
343
|
+
></Cell
|
|
344
|
+
>
|
|
345
|
+
{/if}
|
|
346
|
+
{#if $clientConfig.userFields.includes('name')}
|
|
347
|
+
<Cell
|
|
348
|
+
><a
|
|
349
|
+
href="/groups/edit/{encodeURIComponent(group.guid || '')}"
|
|
350
|
+
use:link>{group.name}</a
|
|
351
|
+
></Cell
|
|
352
|
+
>
|
|
353
|
+
{/if}
|
|
354
|
+
{#if $clientConfig.userFields.includes('email')}
|
|
355
|
+
<Cell
|
|
356
|
+
><a
|
|
357
|
+
href="/groups/edit/{encodeURIComponent(group.guid || '')}"
|
|
358
|
+
use:link>{group.email}</a
|
|
359
|
+
></Cell
|
|
360
|
+
>
|
|
361
|
+
{/if}
|
|
362
|
+
<Cell>{group.enabled ? 'Yes' : 'No'}</Cell>
|
|
363
|
+
</Row>
|
|
364
|
+
{:else}
|
|
365
|
+
{null}
|
|
366
|
+
{/each}
|
|
367
|
+
</Body>
|
|
368
|
+
|
|
369
|
+
{#snippet progress()}
|
|
370
|
+
<LinearProgress
|
|
371
|
+
indeterminate
|
|
372
|
+
closed={childrenLoaded}
|
|
373
|
+
aria-label="Data is being loaded..."
|
|
374
|
+
/>
|
|
375
|
+
{/snippet}
|
|
376
|
+
|
|
377
|
+
{#snippet paginate()}
|
|
378
|
+
<Pagination>
|
|
379
|
+
{#snippet rowsPerPage()}
|
|
380
|
+
<Label>Rows Per Page</Label>
|
|
381
|
+
<Select variant="outlined" bind:value={childrenPerPage} noLabel>
|
|
382
|
+
<Option value={10}>10</Option>
|
|
383
|
+
<Option value={25}>25</Option>
|
|
384
|
+
<Option value={100}>100</Option>
|
|
385
|
+
</Select>
|
|
386
|
+
{/snippet}
|
|
387
|
+
{#snippet total()}
|
|
388
|
+
{childrenStart + 1}-{childrenEnd} of {childrenLength}
|
|
389
|
+
{/snippet}
|
|
390
|
+
|
|
391
|
+
<IconButton
|
|
392
|
+
action="first-page"
|
|
393
|
+
title="First page"
|
|
394
|
+
onclick={() => (childrenCurrentPage = 0)}
|
|
395
|
+
disabled={childrenCurrentPage === 0}
|
|
396
|
+
>
|
|
397
|
+
<Icon class="material-icons">first_page</Icon>
|
|
398
|
+
</IconButton>
|
|
399
|
+
<IconButton
|
|
400
|
+
action="prev-page"
|
|
401
|
+
title="Prev page"
|
|
402
|
+
onclick={() => childrenCurrentPage--}
|
|
403
|
+
disabled={childrenCurrentPage === 0}
|
|
404
|
+
>
|
|
405
|
+
<Icon class="material-icons">chevron_left</Icon>
|
|
406
|
+
</IconButton>
|
|
407
|
+
<IconButton
|
|
408
|
+
action="next-page"
|
|
409
|
+
title="Next page"
|
|
410
|
+
onclick={() => childrenCurrentPage++}
|
|
411
|
+
disabled={childrenCurrentPage === childrenLastPage}
|
|
412
|
+
>
|
|
413
|
+
<Icon class="material-icons">chevron_right</Icon>
|
|
414
|
+
</IconButton>
|
|
415
|
+
<IconButton
|
|
416
|
+
action="last-page"
|
|
417
|
+
title="Last page"
|
|
418
|
+
onclick={() => (childrenCurrentPage = childrenLastPage)}
|
|
419
|
+
disabled={childrenCurrentPage === childrenLastPage}
|
|
420
|
+
>
|
|
421
|
+
<Icon class="material-icons">last_page</Icon>
|
|
422
|
+
</IconButton>
|
|
423
|
+
</Pagination>
|
|
424
|
+
{/snippet}
|
|
425
|
+
</DataTable>
|
|
426
|
+
{/if}
|
|
427
|
+
|
|
288
428
|
{#if activeTab === 'Abilities'}
|
|
289
429
|
<h5 style="margin-top: 0;">Abilities</h5>
|
|
290
430
|
|
|
@@ -332,6 +472,148 @@
|
|
|
332
472
|
</div>
|
|
333
473
|
{/if}
|
|
334
474
|
|
|
475
|
+
{#if activeTab === 'Users'}
|
|
476
|
+
<h5 style="margin-top: 0;">Users</h5>
|
|
477
|
+
|
|
478
|
+
<DataTable
|
|
479
|
+
sortable
|
|
480
|
+
bind:sort={usersSort}
|
|
481
|
+
bind:sortDirection={usersSortDirection}
|
|
482
|
+
onSMUIDataTableSorted={handleUsersSort}
|
|
483
|
+
table$aria-label="User list"
|
|
484
|
+
style="width: 100%;"
|
|
485
|
+
>
|
|
486
|
+
<Head>
|
|
487
|
+
<Row>
|
|
488
|
+
{#if !$clientConfig.emailUsernames}
|
|
489
|
+
<Cell columnId="user-username">
|
|
490
|
+
<Label>Username</Label>
|
|
491
|
+
<IconButton>
|
|
492
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
493
|
+
</IconButton>
|
|
494
|
+
</Cell>
|
|
495
|
+
{/if}
|
|
496
|
+
{#if $clientConfig.userFields.includes('name')}
|
|
497
|
+
<Cell columnId="user-name">
|
|
498
|
+
<Label>Name</Label>
|
|
499
|
+
<IconButton>
|
|
500
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
501
|
+
</IconButton>
|
|
502
|
+
</Cell>
|
|
503
|
+
{/if}
|
|
504
|
+
{#if $clientConfig.userFields.includes('email')}
|
|
505
|
+
<Cell columnId="user-email">
|
|
506
|
+
<Label>Email</Label>
|
|
507
|
+
<IconButton>
|
|
508
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
509
|
+
</IconButton>
|
|
510
|
+
</Cell>
|
|
511
|
+
{/if}
|
|
512
|
+
<Cell columnId="user-enabled">
|
|
513
|
+
<Label>Enabled</Label>
|
|
514
|
+
<IconButton>
|
|
515
|
+
<Icon class="material-icons">arrow_upward</Icon>
|
|
516
|
+
</IconButton>
|
|
517
|
+
</Cell>
|
|
518
|
+
<Cell columnId="user-primary" sortable={false}>
|
|
519
|
+
<Label>Primary</Label>
|
|
520
|
+
</Cell>
|
|
521
|
+
</Row>
|
|
522
|
+
</Head>
|
|
523
|
+
<Body>
|
|
524
|
+
{#each $users as user (user.guid)}
|
|
525
|
+
<Row>
|
|
526
|
+
{#if !$clientConfig.emailUsernames}
|
|
527
|
+
<Cell
|
|
528
|
+
><a
|
|
529
|
+
href="/users/edit/{encodeURIComponent(user.guid || '')}"
|
|
530
|
+
use:link>{user.username}</a
|
|
531
|
+
></Cell
|
|
532
|
+
>
|
|
533
|
+
{/if}
|
|
534
|
+
{#if $clientConfig.userFields.includes('name')}
|
|
535
|
+
<Cell
|
|
536
|
+
><a
|
|
537
|
+
href="/users/edit/{encodeURIComponent(user.guid || '')}"
|
|
538
|
+
use:link>{user.name}</a
|
|
539
|
+
></Cell
|
|
540
|
+
>
|
|
541
|
+
{/if}
|
|
542
|
+
{#if $clientConfig.userFields.includes('email')}
|
|
543
|
+
<Cell
|
|
544
|
+
><a
|
|
545
|
+
href="/users/edit/{encodeURIComponent(user.guid || '')}"
|
|
546
|
+
use:link>{user.email}</a
|
|
547
|
+
></Cell
|
|
548
|
+
>
|
|
549
|
+
{/if}
|
|
550
|
+
<Cell>{user.enabled ? 'Yes' : 'No'}</Cell>
|
|
551
|
+
<Cell>{$entity.$is(user.group) ? 'Yes' : 'No'}</Cell>
|
|
552
|
+
</Row>
|
|
553
|
+
{:else}
|
|
554
|
+
{null}
|
|
555
|
+
{/each}
|
|
556
|
+
</Body>
|
|
557
|
+
|
|
558
|
+
{#snippet progress()}
|
|
559
|
+
<LinearProgress
|
|
560
|
+
indeterminate
|
|
561
|
+
closed={usersLoaded}
|
|
562
|
+
aria-label="Data is being loaded..."
|
|
563
|
+
/>
|
|
564
|
+
{/snippet}
|
|
565
|
+
|
|
566
|
+
{#snippet paginate()}
|
|
567
|
+
<Pagination>
|
|
568
|
+
{#snippet rowsPerPage()}
|
|
569
|
+
<Label>Rows Per Page</Label>
|
|
570
|
+
<Select variant="outlined" bind:value={usersPerPage} noLabel>
|
|
571
|
+
<Option value={10}>10</Option>
|
|
572
|
+
<Option value={25}>25</Option>
|
|
573
|
+
<Option value={100}>100</Option>
|
|
574
|
+
</Select>
|
|
575
|
+
{/snippet}
|
|
576
|
+
{#snippet total()}
|
|
577
|
+
{usersStart + 1}-{usersEnd} of {usersLength}
|
|
578
|
+
{/snippet}
|
|
579
|
+
|
|
580
|
+
<IconButton
|
|
581
|
+
action="first-page"
|
|
582
|
+
title="First page"
|
|
583
|
+
onclick={() => (usersCurrentPage = 0)}
|
|
584
|
+
disabled={usersCurrentPage === 0}
|
|
585
|
+
>
|
|
586
|
+
<Icon class="material-icons">first_page</Icon>
|
|
587
|
+
</IconButton>
|
|
588
|
+
<IconButton
|
|
589
|
+
action="prev-page"
|
|
590
|
+
title="Prev page"
|
|
591
|
+
onclick={() => usersCurrentPage--}
|
|
592
|
+
disabled={usersCurrentPage === 0}
|
|
593
|
+
>
|
|
594
|
+
<Icon class="material-icons">chevron_left</Icon>
|
|
595
|
+
</IconButton>
|
|
596
|
+
<IconButton
|
|
597
|
+
action="next-page"
|
|
598
|
+
title="Next page"
|
|
599
|
+
onclick={() => usersCurrentPage++}
|
|
600
|
+
disabled={usersCurrentPage === usersLastPage}
|
|
601
|
+
>
|
|
602
|
+
<Icon class="material-icons">chevron_right</Icon>
|
|
603
|
+
</IconButton>
|
|
604
|
+
<IconButton
|
|
605
|
+
action="last-page"
|
|
606
|
+
title="Last page"
|
|
607
|
+
onclick={() => (usersCurrentPage = usersLastPage)}
|
|
608
|
+
disabled={usersCurrentPage === usersLastPage}
|
|
609
|
+
>
|
|
610
|
+
<Icon class="material-icons">last_page</Icon>
|
|
611
|
+
</IconButton>
|
|
612
|
+
</Pagination>
|
|
613
|
+
{/snippet}
|
|
614
|
+
</DataTable>
|
|
615
|
+
{/if}
|
|
616
|
+
|
|
335
617
|
{#if failureMessage}
|
|
336
618
|
<div class="tilmeld-failure">
|
|
337
619
|
{failureMessage}
|
|
@@ -357,7 +639,8 @@
|
|
|
357
639
|
<script lang="ts">
|
|
358
640
|
import type { Writable } from 'svelte/store';
|
|
359
641
|
import { writable } from 'svelte/store';
|
|
360
|
-
import
|
|
642
|
+
import { getContext } from 'svelte';
|
|
643
|
+
import { link, pop, replace } from 'svelte-spa-router';
|
|
361
644
|
import type {
|
|
362
645
|
AdminGroupData,
|
|
363
646
|
ClientConfig,
|
|
@@ -366,6 +649,7 @@
|
|
|
366
649
|
import type {
|
|
367
650
|
Group as GroupClass,
|
|
368
651
|
User as UserClass,
|
|
652
|
+
AdminUserData,
|
|
369
653
|
} from '@nymphjs/tilmeld-client';
|
|
370
654
|
import queryParser from '@nymphjs/query-parser';
|
|
371
655
|
import {
|
|
@@ -383,31 +667,31 @@
|
|
|
383
667
|
import Checkbox from '@smui/checkbox';
|
|
384
668
|
import List, { Item, Text, Meta } from '@smui/list';
|
|
385
669
|
import Paper from '@smui/paper';
|
|
386
|
-
import DataTable, {
|
|
670
|
+
import DataTable, {
|
|
671
|
+
Head,
|
|
672
|
+
Body,
|
|
673
|
+
Row,
|
|
674
|
+
Cell,
|
|
675
|
+
Pagination,
|
|
676
|
+
SortValue,
|
|
677
|
+
} from '@smui/data-table';
|
|
678
|
+
import Select, { Option } from '@smui/select';
|
|
387
679
|
import Textfield, { Input } from '@smui/textfield';
|
|
388
680
|
import HelperText from '@smui/textfield/helper-text';
|
|
389
681
|
import IconButton from '@smui/icon-button';
|
|
390
682
|
import Button from '@smui/button';
|
|
683
|
+
import LinearProgress from '@smui/linear-progress';
|
|
391
684
|
import { Icon, Label } from '@smui/common';
|
|
392
685
|
|
|
393
|
-
import { nymph, Group, User } from '../nymph';
|
|
686
|
+
import { nymph, Group, User } from '../nymph.js';
|
|
394
687
|
|
|
395
|
-
let {
|
|
396
|
-
router,
|
|
397
|
-
params,
|
|
398
|
-
clientConfig,
|
|
399
|
-
user,
|
|
400
|
-
}: {
|
|
401
|
-
router: Navigo;
|
|
402
|
-
params: { guid: string };
|
|
403
|
-
clientConfig: Writable<ClientConfig | undefined>;
|
|
404
|
-
user: Writable<(UserClass & CurrentUserData) | null | undefined>;
|
|
405
|
-
} = $props();
|
|
688
|
+
let { params }: { params: { guid: string } } = $props();
|
|
406
689
|
|
|
407
690
|
let entity: Writable<GroupClass & AdminGroupData> = writable(
|
|
408
691
|
Group.factorySync(),
|
|
409
692
|
);
|
|
410
|
-
let activeTab: 'General' | 'Parent' | 'Abilities'
|
|
693
|
+
let activeTab: 'General' | 'Parent' | 'Children' | 'Abilities' | 'Users' =
|
|
694
|
+
$state('General');
|
|
411
695
|
let parentSearch = $state('');
|
|
412
696
|
let ability = $state('');
|
|
413
697
|
let avatar = $state('https://secure.gravatar.com/avatar/?d=mm&s=40');
|
|
@@ -418,16 +702,63 @@
|
|
|
418
702
|
let emailTimer: number | undefined = undefined;
|
|
419
703
|
let emailVerified: boolean | undefined = $state();
|
|
420
704
|
let emailVerifiedMessage: string | undefined = $state();
|
|
705
|
+
let children: Writable<(GroupClass & AdminGroupData)[]> = $state(
|
|
706
|
+
writable([]),
|
|
707
|
+
);
|
|
708
|
+
let childrenSort: `child-${keyof AdminGroupData}` = $state('child-groupname');
|
|
709
|
+
let childrenSortDirection: Lowercase<SortValue> = $state('ascending');
|
|
710
|
+
let childrenPerPage = $state(10);
|
|
711
|
+
let childrenCurrentPage = $state(0);
|
|
712
|
+
let childrenLength = $state(0);
|
|
713
|
+
const childrenStart = $derived(childrenCurrentPage * childrenPerPage);
|
|
714
|
+
const childrenEnd = $derived(
|
|
715
|
+
Math.min(childrenStart + childrenPerPage, childrenLength),
|
|
716
|
+
);
|
|
717
|
+
const childrenLastPage = $derived(
|
|
718
|
+
Math.max(Math.ceil(childrenLength / childrenPerPage) - 1, 0),
|
|
719
|
+
);
|
|
720
|
+
let childrenLoaded = $state(false);
|
|
721
|
+
let users: Writable<(UserClass & AdminUserData)[]> = $state(writable([]));
|
|
722
|
+
let usersSort: `user-${keyof AdminUserData}` = $state('user-username');
|
|
723
|
+
let usersSortDirection: Lowercase<SortValue> = $state('ascending');
|
|
724
|
+
let usersPerPage = $state(10);
|
|
725
|
+
let usersCurrentPage = $state(0);
|
|
726
|
+
let usersLength = $state(0);
|
|
727
|
+
const usersStart = $derived(usersCurrentPage * usersPerPage);
|
|
728
|
+
const usersEnd = $derived(Math.min(usersStart + usersPerPage, usersLength));
|
|
729
|
+
const usersLastPage = $derived(
|
|
730
|
+
Math.max(Math.ceil(usersLength / usersPerPage) - 1, 0),
|
|
731
|
+
);
|
|
732
|
+
let usersLoaded = $state(false);
|
|
421
733
|
let saving = $state(false);
|
|
422
734
|
let success: boolean | undefined = $state();
|
|
423
735
|
let loading = $state(true);
|
|
424
736
|
|
|
737
|
+
const clientConfig =
|
|
738
|
+
getContext<Writable<ClientConfig | undefined>>('clientConfigStore');
|
|
739
|
+
const user =
|
|
740
|
+
getContext<Writable<(UserClass & CurrentUserData) | null | undefined>>(
|
|
741
|
+
'userStore',
|
|
742
|
+
);
|
|
743
|
+
|
|
425
744
|
$effect(() => {
|
|
426
745
|
if (params) {
|
|
427
746
|
handleGuidParam();
|
|
428
747
|
}
|
|
429
748
|
});
|
|
430
749
|
|
|
750
|
+
$effect(() => {
|
|
751
|
+
if (usersCurrentPage >= 0 && usersPerPage >= 0) {
|
|
752
|
+
fillUsers();
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
$effect(() => {
|
|
757
|
+
if (childrenCurrentPage >= 0 && childrenPerPage >= 0) {
|
|
758
|
+
fillChildren();
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
|
|
431
762
|
async function handleGuidParam() {
|
|
432
763
|
loading = true;
|
|
433
764
|
failureMessage = undefined;
|
|
@@ -477,6 +808,9 @@
|
|
|
477
808
|
avatar = await $entity.$getAvatar();
|
|
478
809
|
await $entity.$wakeAll(1);
|
|
479
810
|
$entity = $entity;
|
|
811
|
+
|
|
812
|
+
await fillUsers();
|
|
813
|
+
await fillChildren();
|
|
480
814
|
}
|
|
481
815
|
|
|
482
816
|
let parentsSearching = $state(false);
|
|
@@ -592,26 +926,114 @@
|
|
|
592
926
|
if (event.key === 'Enter') addAbility();
|
|
593
927
|
}
|
|
594
928
|
|
|
929
|
+
async function handleChildrenSort() {
|
|
930
|
+
await fillChildren();
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
async function fillChildren() {
|
|
934
|
+
childrenLoaded = false;
|
|
935
|
+
try {
|
|
936
|
+
if ($entity.guid == null) {
|
|
937
|
+
$children = [];
|
|
938
|
+
childrenLength = 0;
|
|
939
|
+
} else {
|
|
940
|
+
$children = await nymph.getEntities(
|
|
941
|
+
{
|
|
942
|
+
class: Group,
|
|
943
|
+
sort: childrenSort.slice('child-'.length),
|
|
944
|
+
reverse: childrenSortDirection === 'descending',
|
|
945
|
+
limit: childrenPerPage,
|
|
946
|
+
offset: childrenPerPage * childrenCurrentPage,
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
type: '&',
|
|
950
|
+
ref: ['parent', $entity],
|
|
951
|
+
},
|
|
952
|
+
);
|
|
953
|
+
|
|
954
|
+
if (childrenLength === 0) {
|
|
955
|
+
childrenLength = await nymph.getEntities(
|
|
956
|
+
{
|
|
957
|
+
class: Group,
|
|
958
|
+
return: 'count',
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
type: '&',
|
|
962
|
+
ref: ['parent', $entity],
|
|
963
|
+
},
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
} catch (e: any) {
|
|
968
|
+
failureMessage = e.message;
|
|
969
|
+
}
|
|
970
|
+
childrenLoaded = true;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
async function handleUsersSort() {
|
|
974
|
+
await fillUsers();
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
async function fillUsers() {
|
|
978
|
+
usersLoaded = false;
|
|
979
|
+
try {
|
|
980
|
+
if ($entity.guid == null) {
|
|
981
|
+
$users = [];
|
|
982
|
+
usersLength = 0;
|
|
983
|
+
} else {
|
|
984
|
+
$users = await nymph.getEntities(
|
|
985
|
+
{
|
|
986
|
+
class: User,
|
|
987
|
+
sort: usersSort.slice('user-'.length),
|
|
988
|
+
reverse: usersSortDirection === 'descending',
|
|
989
|
+
limit: usersPerPage,
|
|
990
|
+
offset: usersPerPage * usersCurrentPage,
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
type: '|',
|
|
994
|
+
ref: [
|
|
995
|
+
['group', $entity],
|
|
996
|
+
['groups', $entity],
|
|
997
|
+
],
|
|
998
|
+
},
|
|
999
|
+
);
|
|
1000
|
+
|
|
1001
|
+
if (usersLength === 0) {
|
|
1002
|
+
usersLength = await nymph.getEntities(
|
|
1003
|
+
{
|
|
1004
|
+
class: User,
|
|
1005
|
+
return: 'count',
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
type: '|',
|
|
1009
|
+
ref: [
|
|
1010
|
+
['group', $entity],
|
|
1011
|
+
['groups', $entity],
|
|
1012
|
+
],
|
|
1013
|
+
},
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
} catch (e: any) {
|
|
1018
|
+
failureMessage = e.message;
|
|
1019
|
+
}
|
|
1020
|
+
usersLoaded = true;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
595
1023
|
async function saveEntity() {
|
|
596
1024
|
saving = true;
|
|
597
1025
|
failureMessage = undefined;
|
|
598
1026
|
const newEntity = $entity.guid == null;
|
|
599
1027
|
try {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
`/groups/edit/${encodeURIComponent($entity.guid || '')}`,
|
|
606
|
-
{ historyAPIMethod: 'replaceState' },
|
|
607
|
-
);
|
|
608
|
-
}
|
|
609
|
-
setTimeout(() => {
|
|
610
|
-
success = undefined;
|
|
611
|
-
}, 1000);
|
|
612
|
-
} else {
|
|
613
|
-
failureMessage = 'Error saving group.';
|
|
1028
|
+
await $entity.$save();
|
|
1029
|
+
await readyEntity();
|
|
1030
|
+
success = true;
|
|
1031
|
+
if (newEntity) {
|
|
1032
|
+
replace(`/groups/edit/${encodeURIComponent($entity.guid || '')}`);
|
|
614
1033
|
}
|
|
1034
|
+
setTimeout(() => {
|
|
1035
|
+
success = undefined;
|
|
1036
|
+
}, 1000);
|
|
615
1037
|
} catch (e: any) {
|
|
616
1038
|
console.log('error:', e);
|
|
617
1039
|
failureMessage = e?.message;
|
|
@@ -621,14 +1043,15 @@
|
|
|
621
1043
|
|
|
622
1044
|
async function deleteEntity() {
|
|
623
1045
|
failureMessage = undefined;
|
|
624
|
-
if (
|
|
1046
|
+
if (
|
|
1047
|
+
confirm(
|
|
1048
|
+
'Are you sure you want to delete this? All descendant groups will be deleted too, and users will be removed.',
|
|
1049
|
+
)
|
|
1050
|
+
) {
|
|
625
1051
|
saving = true;
|
|
626
1052
|
try {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
} else {
|
|
630
|
-
failureMessage = 'An error occurred.';
|
|
631
|
-
}
|
|
1053
|
+
await $entity.$delete();
|
|
1054
|
+
pop();
|
|
632
1055
|
} catch (e: any) {
|
|
633
1056
|
failureMessage = e?.message;
|
|
634
1057
|
}
|