@humandialog/forms.svelte 0.6.2 → 1.1.1
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/components/checkbox.svelte +9 -2
- package/components/combo/combo.svelte +19 -7
- package/components/combo/combo.svelte.d.ts +1 -0
- package/components/contextmenu.svelte +13 -4
- package/components/input.text.svelte.d.ts +2 -2
- package/components/inputbox.ltop.svelte +18 -8
- package/components/inputbox.ltop.svelte.d.ts +12 -10
- package/components/list/internal/list.element.svelte +22 -4
- package/components/list/list.svelte +28 -26
- package/components/sidebar/sidebar.brand.svelte +5 -2
- package/components/sidebar/sidebar.brand.svelte.d.ts +2 -0
- package/components/simple.table.svelte.d.ts +2 -2
- package/components/table/_template.table.svelte.d.ts +2 -2
- package/components/textarea.ltop.svelte.d.ts +2 -2
- package/components/tile.title.svelte.d.ts +2 -2
- package/desk.svelte +113 -106
- package/horizontal.toolbar.svelte +44 -17
- package/package.json +2 -2
- package/page.svelte.d.ts +6 -6
- package/stores.d.ts +2 -0
- package/stores.js +8 -0
- package/tenant.members.svelte +395 -82
- package/tenant.members.svelte.d.ts +2 -2
- package/vertical.toolbar.svelte +148 -11
package/tenant.members.svelte
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { FaUserPlus,
|
|
3
3
|
FaUserMinus,
|
|
4
4
|
FaPen,
|
|
5
|
-
FaInfoCircle
|
|
5
|
+
FaInfoCircle,
|
|
6
|
+
FaChevronDown} from 'svelte-icons/fa'
|
|
6
7
|
|
|
7
8
|
import Page from './page.svelte'
|
|
8
9
|
import List from './components/list/list.svelte'
|
|
@@ -13,10 +14,14 @@
|
|
|
13
14
|
import ListStaticProperty from './components/list/list.static.svelte'
|
|
14
15
|
import Input from './components/inputbox.ltop.svelte';
|
|
15
16
|
import Icon from "./components/icon.svelte";
|
|
17
|
+
import Combo from './components/combo/combo.svelte'
|
|
16
18
|
import Modal from './modal.svelte'
|
|
17
19
|
import Checkbox from './components/checkbox.svelte';
|
|
18
|
-
import {Popover} from 'flowbite-svelte'
|
|
19
|
-
import { reef } from '@humandialog/auth.svelte';
|
|
20
|
+
import {Popover, Alert} from 'flowbite-svelte'
|
|
21
|
+
import { reef, session, signInHRef } from '@humandialog/auth.svelte';
|
|
22
|
+
import { ComboSource } from './';
|
|
23
|
+
import {removeAt} from './utils'
|
|
24
|
+
import {showMenu} from './components/menu'
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
// ==============================================================================
|
|
@@ -27,7 +32,7 @@
|
|
|
27
32
|
export let refAttrib = "$ref";
|
|
28
33
|
export let showFiles = false;
|
|
29
34
|
//export let show_admin = true;
|
|
30
|
-
export let
|
|
35
|
+
export let showAccessRoles = false;
|
|
31
36
|
|
|
32
37
|
// ===============================================================================
|
|
33
38
|
|
|
@@ -41,11 +46,34 @@
|
|
|
41
46
|
|
|
42
47
|
let reef_users = [];
|
|
43
48
|
let new_reef_user_id = 1;
|
|
49
|
+
let access_roles = [];
|
|
44
50
|
|
|
45
51
|
let fake_users;
|
|
46
52
|
|
|
53
|
+
const authAccessKinds = [
|
|
54
|
+
{ name: 'No auth access', key: 0 },
|
|
55
|
+
{ name: 'Read auth access', key: 1 },
|
|
56
|
+
{ name: 'Can invite others', key: 3 },
|
|
57
|
+
{ name: 'Full auth access', key: 7 },
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
const filesAccessKinds = [
|
|
61
|
+
{ name: 'Can read files', key: 0 },
|
|
62
|
+
{ name: 'Can write files', key: 1 },
|
|
63
|
+
{ name: 'Full files access', key: 3 },
|
|
64
|
+
]
|
|
65
|
+
|
|
47
66
|
async function init()
|
|
48
67
|
{
|
|
68
|
+
if(showAccessRoles)
|
|
69
|
+
{
|
|
70
|
+
let roles = await reef.get('/sys/list_access_roles')
|
|
71
|
+
access_roles = [];
|
|
72
|
+
if(roles)
|
|
73
|
+
roles.forEach( gname => access_roles.push({name: gname}));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
49
77
|
reef_users = [];
|
|
50
78
|
if(users && Array.isArray(users) && users.length > 0)
|
|
51
79
|
{
|
|
@@ -59,8 +87,8 @@
|
|
|
59
87
|
[refAttrib]: u[refAttrib],
|
|
60
88
|
auth_group: 0,
|
|
61
89
|
files_group :0,
|
|
62
|
-
|
|
63
|
-
other: "",
|
|
90
|
+
acc_role: "",
|
|
91
|
+
//other: "",
|
|
64
92
|
avatar_url : "",
|
|
65
93
|
invitation_not_accepted: false,
|
|
66
94
|
removed: false,
|
|
@@ -91,10 +119,12 @@
|
|
|
91
119
|
if(handled_no == reef_users.length)
|
|
92
120
|
{
|
|
93
121
|
//console.log('reload', reef_users)
|
|
122
|
+
//reef_users = [...reef_users]
|
|
94
123
|
|
|
95
124
|
list?.reload(reef_users);
|
|
96
125
|
}
|
|
97
126
|
} )
|
|
127
|
+
|
|
98
128
|
}
|
|
99
129
|
|
|
100
130
|
function set_user_info(user, info)
|
|
@@ -102,10 +132,11 @@
|
|
|
102
132
|
user.auth_group = info.auth_group ?? 0;
|
|
103
133
|
user.files_group = info.files_group ?? 0;
|
|
104
134
|
user.avatar_url = info.avatar_url ?? "";
|
|
105
|
-
user.
|
|
106
|
-
user.
|
|
135
|
+
user.access_details = info.access_details
|
|
136
|
+
user.acc_role = info.access_details?.role ?? '';
|
|
107
137
|
user.removed = info.removed ?? false;
|
|
108
138
|
user.invitation_not_accepted = info.invitation_not_accepted ?? false;
|
|
139
|
+
//console.log(info)
|
|
109
140
|
|
|
110
141
|
if(user.removed)
|
|
111
142
|
user.membership_tag = "Removed";
|
|
@@ -128,25 +159,14 @@
|
|
|
128
159
|
let new_user = {
|
|
129
160
|
name: '',
|
|
130
161
|
email: '',
|
|
131
|
-
|
|
162
|
+
auth_group: 0,
|
|
163
|
+
files_group: 0,
|
|
164
|
+
acc_role: ''
|
|
132
165
|
}
|
|
133
166
|
|
|
134
167
|
let name_input;
|
|
135
168
|
let email_input;
|
|
136
169
|
|
|
137
|
-
async function delete_user(user)
|
|
138
|
-
{
|
|
139
|
-
let email = user[emailAttrib];
|
|
140
|
-
|
|
141
|
-
let removed_user_details = await reef.get('/sys/kick_out_user?email=' + email);
|
|
142
|
-
if(removed_user_details)
|
|
143
|
-
{
|
|
144
|
-
//let removed_user = reef_users.find( u => u[emailAttrib] == user[emailAttrib])
|
|
145
|
-
set_user_info(user, removed_user_details);
|
|
146
|
-
list?.refresh();
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
170
|
async function on_name_changed(user, name, property)
|
|
151
171
|
{
|
|
152
172
|
user[property] = name;
|
|
@@ -166,36 +186,92 @@
|
|
|
166
186
|
if(user.auth_group != flags)
|
|
167
187
|
{
|
|
168
188
|
let email = user[emailAttrib];
|
|
169
|
-
|
|
170
|
-
if(
|
|
189
|
+
const res = await reef.fetch(`/json/anyv/sys/set_user_details?email=${email}&auth_group=${flags}`)
|
|
190
|
+
if(res.ok)
|
|
171
191
|
{
|
|
192
|
+
const response_string = await res.text();
|
|
193
|
+
const info = JSON.parse(response_string);
|
|
194
|
+
|
|
172
195
|
user.auth_group = flags;
|
|
173
196
|
|
|
174
197
|
set_user_info(user, info)
|
|
175
|
-
list?.
|
|
198
|
+
list?.rereder();
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
else
|
|
202
|
+
{
|
|
203
|
+
const err_msg = await res.text();
|
|
204
|
+
alerts.push(err_msg)
|
|
205
|
+
alerts = [...alerts];
|
|
206
|
+
return false;
|
|
176
207
|
}
|
|
177
208
|
}
|
|
209
|
+
return false;
|
|
178
210
|
}
|
|
179
211
|
|
|
180
212
|
async function on_change_files_access(user, flags, name)
|
|
181
213
|
{
|
|
182
214
|
if(user.files_group != flags)
|
|
183
215
|
{
|
|
184
|
-
user.files_group = flags;
|
|
185
|
-
|
|
186
216
|
let email = user[emailAttrib];
|
|
187
|
-
|
|
188
|
-
if(
|
|
217
|
+
const res = await reef.fetch(`/json/anyv/sys/set_user_details?email=${email}&files_group=${flags}`)
|
|
218
|
+
if(res.ok)
|
|
219
|
+
{
|
|
220
|
+
const response_string = await res.text();
|
|
221
|
+
const info = JSON.parse(response_string);
|
|
222
|
+
|
|
223
|
+
user.files_group = flags;
|
|
224
|
+
|
|
225
|
+
set_user_info(user, info)
|
|
226
|
+
list?.rereder();
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
else
|
|
230
|
+
{
|
|
231
|
+
const err_msg = await res.text();
|
|
232
|
+
alerts.push(err_msg)
|
|
233
|
+
alerts = [...alerts];
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function on_change_access_role(user, role, name)
|
|
241
|
+
{
|
|
242
|
+
if(user.access_details && user.access_details.role != role)
|
|
243
|
+
{
|
|
244
|
+
const email = user[emailAttrib];
|
|
245
|
+
const res = await reef.fetch(`/json/anyv/sys/set_user_role?email=${email}&role=${role}`)
|
|
246
|
+
if(res.ok)
|
|
189
247
|
{
|
|
248
|
+
const response_string = await res.text();
|
|
249
|
+
const info = JSON.parse(response_string);
|
|
250
|
+
|
|
251
|
+
user.access_details.role = role;
|
|
252
|
+
user.acc_role = role
|
|
253
|
+
|
|
190
254
|
set_user_info(user, info)
|
|
191
|
-
list?.
|
|
255
|
+
list?.rereder();
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
else
|
|
259
|
+
{
|
|
260
|
+
const err_msg = await res.text();
|
|
261
|
+
alerts = [err_msg, ...alerts];
|
|
262
|
+
return false;
|
|
192
263
|
}
|
|
193
264
|
}
|
|
265
|
+
return false;
|
|
194
266
|
}
|
|
195
267
|
|
|
196
268
|
function create_new_user()
|
|
197
269
|
{
|
|
270
|
+
if(showAccessRoles)
|
|
271
|
+
new_user.acc_role = access_roles[0].name
|
|
272
|
+
|
|
198
273
|
create_new_user_enabled = true;
|
|
274
|
+
|
|
199
275
|
}
|
|
200
276
|
|
|
201
277
|
let page_operations=[
|
|
@@ -214,14 +290,26 @@
|
|
|
214
290
|
action: (focused) => { list.edit(user, nameAttrib) }
|
|
215
291
|
},
|
|
216
292
|
{
|
|
217
|
-
caption: '
|
|
293
|
+
caption: 'Users management',
|
|
218
294
|
action: (focused) => { list.edit(user, 'Privileges') }
|
|
219
295
|
}];
|
|
220
296
|
|
|
297
|
+
if(showAccessRoles)
|
|
298
|
+
{
|
|
299
|
+
operations.push({
|
|
300
|
+
separator: true
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
operations.push({
|
|
304
|
+
caption: 'Access role',
|
|
305
|
+
action: (focused) => { list.edit(user, 'Access') }
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
221
309
|
if(showFiles)
|
|
222
310
|
{
|
|
223
311
|
operations.push({
|
|
224
|
-
caption: '
|
|
312
|
+
caption: 'External files',
|
|
225
313
|
action: (focused) => { list.edit(user, 'Files') }
|
|
226
314
|
});
|
|
227
315
|
}
|
|
@@ -232,6 +320,9 @@
|
|
|
232
320
|
let user_operations = (user) => {
|
|
233
321
|
|
|
234
322
|
let operations = [];
|
|
323
|
+
|
|
324
|
+
if(user.removed)
|
|
325
|
+
return [];
|
|
235
326
|
|
|
236
327
|
let edit_operations = get_edit_operations(user)
|
|
237
328
|
if(edit_operations.length == 1)
|
|
@@ -254,13 +345,16 @@
|
|
|
254
345
|
operations.push({
|
|
255
346
|
caption: '',
|
|
256
347
|
icon: FaUserMinus,
|
|
257
|
-
action: (focused) =>
|
|
348
|
+
action: (focused) => askToRemove(user)
|
|
258
349
|
});
|
|
259
350
|
|
|
260
351
|
return operations;
|
|
261
352
|
}
|
|
262
353
|
|
|
263
354
|
let user_context_menu = (user) => {
|
|
355
|
+
if(user.removed)
|
|
356
|
+
return [];
|
|
357
|
+
|
|
264
358
|
let edit_operations = get_edit_operations(user);
|
|
265
359
|
return {
|
|
266
360
|
grid: edit_operations
|
|
@@ -298,11 +392,7 @@
|
|
|
298
392
|
|
|
299
393
|
}
|
|
300
394
|
|
|
301
|
-
|
|
302
|
-
{
|
|
303
|
-
return !!s;
|
|
304
|
-
}
|
|
305
|
-
|
|
395
|
+
|
|
306
396
|
function add_fake_users(reef_users)
|
|
307
397
|
{
|
|
308
398
|
const names = [
|
|
@@ -379,37 +469,69 @@
|
|
|
379
469
|
if(!email_input?.validate())
|
|
380
470
|
return;
|
|
381
471
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
472
|
+
try {
|
|
473
|
+
const res = await reef.fetch('/json/anyv/sys/invite_user', {
|
|
474
|
+
method: 'POST',
|
|
475
|
+
body: JSON.stringify({
|
|
476
|
+
email: new_user.email,
|
|
477
|
+
auth_group: new_user.auth_group,
|
|
478
|
+
files_group: new_user.files_group,
|
|
479
|
+
role: new_user.acc_role,
|
|
480
|
+
client_id: $session.configuration.client_id,
|
|
481
|
+
redirect_uri: `${window.location.origin}/#/auth/cb`,
|
|
482
|
+
state: `${window.location.origin}/#/auth/signin`,
|
|
483
|
+
set:
|
|
484
|
+
{
|
|
485
|
+
[nameAttrib]: new_user.name,
|
|
486
|
+
[emailAttrib]: new_user.email
|
|
487
|
+
}
|
|
488
|
+
})
|
|
391
489
|
})
|
|
392
|
-
if(result)
|
|
393
|
-
{
|
|
394
|
-
let created_user = result.User;
|
|
395
|
-
let new_reef_user = {
|
|
396
|
-
[nameAttrib]: created_user[nameAttrib],
|
|
397
|
-
[emailAttrib]: created_user[emailAttrib],
|
|
398
|
-
[refAttrib]: created_user[refAttrib]
|
|
399
|
-
}
|
|
400
490
|
|
|
401
|
-
|
|
402
|
-
|
|
491
|
+
if(res.ok)
|
|
492
|
+
{
|
|
493
|
+
const result = await res.json();
|
|
494
|
+
let created_user = result.User;
|
|
495
|
+
let new_reef_user = {
|
|
496
|
+
[nameAttrib]: created_user[nameAttrib],
|
|
497
|
+
[emailAttrib]: created_user[emailAttrib],
|
|
498
|
+
[refAttrib]: created_user[refAttrib]
|
|
499
|
+
}
|
|
403
500
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
501
|
+
let details = await reef.get(`/sys/user_details?email=${new_reef_user[emailAttrib]}`)
|
|
502
|
+
set_user_info(new_reef_user, details);
|
|
407
503
|
|
|
504
|
+
let sameUserIdx = reef_users.findIndex(ru => ru[refAttrib] == new_reef_user[refAttrib])
|
|
505
|
+
if(sameUserIdx >= 0)
|
|
506
|
+
{
|
|
507
|
+
reef_users[sameUserIdx] = new_reef_user;
|
|
508
|
+
reef_users = [... reef_users];
|
|
509
|
+
}
|
|
510
|
+
else
|
|
511
|
+
{
|
|
512
|
+
reef_users = [...reef_users, new_reef_user]
|
|
513
|
+
}
|
|
408
514
|
|
|
515
|
+
|
|
516
|
+
list?.reload(reef_users);
|
|
517
|
+
}
|
|
518
|
+
else
|
|
519
|
+
{
|
|
520
|
+
const err_msg = await res.text();
|
|
521
|
+
alerts = [err_msg, ...alerts];
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
catch (err)
|
|
525
|
+
{
|
|
526
|
+
alerts = [err, ...alerts];
|
|
527
|
+
}
|
|
409
528
|
|
|
410
529
|
new_user.name = '';
|
|
411
530
|
new_user.email = '';
|
|
412
|
-
new_user.
|
|
531
|
+
new_user.auth_group = 0;
|
|
532
|
+
new_user.files_group = 0;
|
|
533
|
+
new_user.acc_role = ''
|
|
534
|
+
|
|
413
535
|
create_new_user_enabled = false;
|
|
414
536
|
}
|
|
415
537
|
|
|
@@ -417,10 +539,54 @@
|
|
|
417
539
|
{
|
|
418
540
|
new_user.name = '';
|
|
419
541
|
new_user.email = '';
|
|
420
|
-
new_user.
|
|
542
|
+
new_user.auth_group = 0;
|
|
543
|
+
new_user.files_group = 0;
|
|
544
|
+
new_user.acc_role = ''
|
|
545
|
+
|
|
421
546
|
create_new_user_enabled = false;
|
|
422
547
|
}
|
|
423
548
|
|
|
549
|
+
let alerts = []
|
|
550
|
+
|
|
551
|
+
let removeModal;
|
|
552
|
+
let userToRemove;
|
|
553
|
+
function askToRemove(user)
|
|
554
|
+
{
|
|
555
|
+
userToRemove = user;
|
|
556
|
+
removeModal.show()
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
async function removeUser()
|
|
560
|
+
{
|
|
561
|
+
if(!userToRemove)
|
|
562
|
+
return;
|
|
563
|
+
|
|
564
|
+
let email = userToRemove[emailAttrib];
|
|
565
|
+
try{
|
|
566
|
+
|
|
567
|
+
const res = await reef.fetch('/json/anyv/sys/kick_out_user?email=' + email)
|
|
568
|
+
removeModal.hide();
|
|
569
|
+
|
|
570
|
+
if(res.ok)
|
|
571
|
+
{
|
|
572
|
+
const removed_user_details = await res.json();
|
|
573
|
+
//let removed_user = reef_users.find( u => u[emailAttrib] == user[emailAttrib])
|
|
574
|
+
set_user_info(userToRemove, removed_user_details);
|
|
575
|
+
list?.rereder();
|
|
576
|
+
}
|
|
577
|
+
else
|
|
578
|
+
{
|
|
579
|
+
const err = await res.text()
|
|
580
|
+
alerts = [err, ...alerts];
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
catch(err)
|
|
584
|
+
{
|
|
585
|
+
alerts = [err, ...alerts];
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
|
|
424
590
|
</script>
|
|
425
591
|
|
|
426
592
|
<Page self={data_item}
|
|
@@ -429,6 +595,23 @@
|
|
|
429
595
|
clearsContext='props sel'>
|
|
430
596
|
<!--a href="/" class="underline text-sm font-semibold ml-3"> < Back to root</a-->
|
|
431
597
|
|
|
598
|
+
<!-- alerts -->
|
|
599
|
+
<section class="absolute left-2 sm:left-auto sm:right-2 bottom-2 flex flex-col gap-2">
|
|
600
|
+
{#each alerts as alert, idx}
|
|
601
|
+
<Alert class="bg-red-900/40 shadow-lg shadow-stone-400 dark:shadow-black flex flex-row">
|
|
602
|
+
<p>
|
|
603
|
+
{alert}
|
|
604
|
+
</p>
|
|
605
|
+
<button class="font-bold ml-auto"
|
|
606
|
+
on:click={() => {alerts = removeAt(alerts, idx)}}>
|
|
607
|
+
x
|
|
608
|
+
</button>
|
|
609
|
+
</Alert>
|
|
610
|
+
{/each}
|
|
611
|
+
</section>
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
432
615
|
{#if reef_users && reef_users.length > 0}
|
|
433
616
|
<List objects={reef_users}
|
|
434
617
|
title='Members'
|
|
@@ -441,25 +624,29 @@
|
|
|
441
624
|
<ListStaticProperty name="Membership" a="membership_tag"/>
|
|
442
625
|
|
|
443
626
|
<ListComboProperty name='Privileges' a='auth_group' onSelect={on_change_privileges}>
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
<ComboItem name='Can fully manage' key={7} />
|
|
627
|
+
{#each authAccessKinds as kind}
|
|
628
|
+
<ComboItem name={kind.name} key={kind.key} />
|
|
629
|
+
{/each}
|
|
448
630
|
</ListComboProperty>
|
|
449
631
|
|
|
632
|
+
{#if showAccessRoles}
|
|
633
|
+
<ListComboProperty name='Access' a='acc_role' onSelect={on_change_access_role}>
|
|
634
|
+
<ComboSource objects={access_roles} name='name' key='name'/>
|
|
635
|
+
</ListComboProperty>
|
|
636
|
+
{/if}
|
|
637
|
+
|
|
450
638
|
{#if showFiles}
|
|
451
639
|
<ListComboProperty name='Files' a='files_group' onSelect={on_change_files_access}>
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
<ComboItem name='Read&Write' key={3} />
|
|
640
|
+
{#each filesAccessKinds as kind}
|
|
641
|
+
<ComboItem name={kind.name} key={kind.key} />
|
|
642
|
+
{/each}
|
|
456
643
|
</ListComboProperty>
|
|
457
644
|
{/if}
|
|
458
645
|
|
|
459
646
|
|
|
460
647
|
</List>
|
|
461
648
|
{/if}
|
|
462
|
-
|
|
649
|
+
|
|
463
650
|
</Page>
|
|
464
651
|
|
|
465
652
|
<Modal bind:open={create_new_user_enabled}
|
|
@@ -468,28 +655,154 @@
|
|
|
468
655
|
onOkCallback={on_new_user_requested}
|
|
469
656
|
onCancelCallback={on_new_user_canceled}
|
|
470
657
|
icon={FaUserPlus}>
|
|
471
|
-
<Input label='Name'
|
|
472
|
-
placeholder=''
|
|
473
|
-
self={new_user}
|
|
474
|
-
a="name"
|
|
475
|
-
validateCb={is_valid_name}
|
|
476
|
-
bind:this={name_input}/>
|
|
477
658
|
|
|
478
659
|
<Input label='E-mail'
|
|
479
660
|
placeholder=''
|
|
480
661
|
self={new_user}
|
|
481
662
|
a="email"
|
|
482
|
-
|
|
663
|
+
validation={is_valid_email_address}
|
|
483
664
|
bind:this={email_input}/>
|
|
484
665
|
|
|
485
|
-
<
|
|
666
|
+
<Input label='Name'
|
|
667
|
+
placeholder='Optional'
|
|
668
|
+
self={new_user}
|
|
669
|
+
a="name"
|
|
670
|
+
bind:this={name_input}/>
|
|
671
|
+
|
|
672
|
+
<!--Checkbox class="mt-2 text-xs font-normal" self={new_user} a="maintainer">
|
|
486
673
|
<div class="flex flex-row items-center">
|
|
487
674
|
<span class="">Maintainer</span>
|
|
488
675
|
<Icon id="b1" size={4} component={FaInfoCircle} class="text-stone-400 ml-5 pt-0 mt-1"/>
|
|
489
|
-
<Popover class="w-64 text-sm font-light
|
|
490
|
-
Means that the invited user will be able to add
|
|
676
|
+
<Popover class="w-64 text-sm font-light text-stone-500 bg-white dark:bg-stone-800 dark:border-stone-600 dark:text-stone-400" triggeredBy="#b1" color="dropdown">
|
|
677
|
+
Means that the invited user will be able to add/remove others and manage permissions in this organization.
|
|
491
678
|
</Popover>
|
|
492
679
|
</div>
|
|
493
|
-
</Checkbox
|
|
680
|
+
</Checkbox-->
|
|
681
|
+
|
|
682
|
+
<!-- There is problem with dropdown/combo on dialogs (nested fixed stacks) -->
|
|
683
|
+
<!--Combo class="mt-2" label='Privileges' a='auth_group' self={new_user} >
|
|
684
|
+
<ComboItem name='No auth access' key={0} />
|
|
685
|
+
<ComboItem name='Read auth access' key={1} />
|
|
686
|
+
<ComboItem name='Can invite others' key={3} />
|
|
687
|
+
<ComboItem name='Full auth access' key={7} />
|
|
688
|
+
</Combo-->
|
|
689
|
+
|
|
690
|
+
<section class="mt-2 grid grid-cols-2 gap-2">
|
|
691
|
+
<div class="flex flex-col">
|
|
692
|
+
<label for="new_user_auth_group"
|
|
693
|
+
class="text-xs">
|
|
694
|
+
Auth access
|
|
695
|
+
</label>
|
|
696
|
+
<button id="new_user_auth_group"
|
|
697
|
+
class=" w-full mt-0.5
|
|
698
|
+
bg-stone-50 border border-stone-300 text-stone-900 text-base sm:text-sm rounded-lg
|
|
699
|
+
focus:ring-primary-600 focus:border-primary-600 pb-0.5 pt-0.5 px-2.5 dark:bg-stone-700
|
|
700
|
+
dark:border-stone-600 dark:placeholder-stone-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
|
|
701
|
+
on:click={(e) => {
|
|
702
|
+
let owner = e.target;
|
|
703
|
+
while(owner && owner.tagName != 'BUTTON')
|
|
704
|
+
owner = owner.parentElement
|
|
705
|
+
|
|
706
|
+
if(!owner)
|
|
707
|
+
return;
|
|
708
|
+
|
|
709
|
+
let options = [];
|
|
710
|
+
authAccessKinds.forEach(k => options.push({
|
|
711
|
+
caption: k.name,
|
|
712
|
+
action: (f) => { new_user.auth_group=k.key}
|
|
713
|
+
}));
|
|
714
|
+
|
|
715
|
+
let rect = owner.getBoundingClientRect();
|
|
716
|
+
let pt = new DOMPoint(rect.left, rect.bottom)
|
|
717
|
+
showMenu(pt, options);
|
|
718
|
+
}}>
|
|
719
|
+
{authAccessKinds.find(k => k.key == new_user.auth_group)?.name}
|
|
720
|
+
<span class="w-3 h-3 inline-block text-stone-700 dark:text-stone-300 ml-2 mt-2 sm:mt-1">
|
|
721
|
+
<FaChevronDown/>
|
|
722
|
+
</span>
|
|
723
|
+
</button>
|
|
724
|
+
</div>
|
|
725
|
+
|
|
726
|
+
{#if showFiles}
|
|
727
|
+
<div class="flex flex-col">
|
|
728
|
+
<label for="new_user_auth_group"
|
|
729
|
+
class="text-xs">
|
|
730
|
+
Files access
|
|
731
|
+
</label>
|
|
732
|
+
<button
|
|
733
|
+
class=" mt-0.5 w-full
|
|
734
|
+
bg-stone-50 border border-stone-300 text-stone-900 text-base sm:text-sm rounded-lg
|
|
735
|
+
focus:ring-primary-600 focus:border-primary-600 pb-0.5 pt-0.5 px-2.5 dark:bg-stone-700
|
|
736
|
+
dark:border-stone-600 dark:placeholder-stone-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
|
|
737
|
+
on:click={(e) => {
|
|
738
|
+
let owner = e.target;
|
|
739
|
+
while(owner && owner.tagName != 'BUTTON')
|
|
740
|
+
owner = owner.parentElement
|
|
741
|
+
|
|
742
|
+
if(!owner)
|
|
743
|
+
return;
|
|
744
|
+
|
|
745
|
+
let options = [];
|
|
746
|
+
filesAccessKinds.forEach(k => options.push({
|
|
747
|
+
caption: k.name,
|
|
748
|
+
action: (f) => { new_user.files_group=k.key}
|
|
749
|
+
}));
|
|
750
|
+
|
|
751
|
+
let rect = owner.getBoundingClientRect();
|
|
752
|
+
let pt = new DOMPoint(rect.left, rect.bottom)
|
|
753
|
+
showMenu(pt, options);
|
|
754
|
+
}}>
|
|
755
|
+
{filesAccessKinds.find(k => k.key == new_user.files_group)?.name}
|
|
756
|
+
<span class="w-3 h-3 inline-block text-stone-700 dark:text-stone-300 ml-2 mt-2 sm:mt-1">
|
|
757
|
+
<FaChevronDown/>
|
|
758
|
+
</span>
|
|
759
|
+
</button>
|
|
760
|
+
</div>
|
|
761
|
+
{/if}
|
|
762
|
+
|
|
763
|
+
{#if showAccessRoles}
|
|
764
|
+
<div class="flex flex-col">
|
|
765
|
+
<label for="new_user_auth_group"
|
|
766
|
+
class="text-xs">
|
|
767
|
+
App role
|
|
768
|
+
</label>
|
|
769
|
+
<button
|
|
770
|
+
class=" mt-0.5 w-full
|
|
771
|
+
bg-stone-50 border border-stone-300 text-stone-900 text-base sm:text-sm rounded-lg
|
|
772
|
+
focus:ring-primary-600 focus:border-primary-600 pb-0.5 pt-0.5 px-2.5 dark:bg-stone-700
|
|
773
|
+
dark:border-stone-600 dark:placeholder-stone-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
|
|
774
|
+
on:click={(e) => {
|
|
775
|
+
let owner = e.target;
|
|
776
|
+
while(owner && owner.tagName != 'BUTTON')
|
|
777
|
+
owner = owner.parentElement
|
|
778
|
+
|
|
779
|
+
if(!owner)
|
|
780
|
+
return;
|
|
781
|
+
|
|
782
|
+
let options = [];
|
|
783
|
+
access_roles.forEach(k => options.push({
|
|
784
|
+
caption: k.name,
|
|
785
|
+
action: (f) => { new_user.acc_role=k.name}
|
|
786
|
+
}));
|
|
787
|
+
|
|
788
|
+
let rect = owner.getBoundingClientRect();
|
|
789
|
+
let pt = new DOMPoint(rect.left, rect.bottom)
|
|
790
|
+
showMenu(pt, options);
|
|
791
|
+
}}>
|
|
792
|
+
{new_user.acc_role ? new_user.acc_role : '<none>'}
|
|
793
|
+
<span class="w-3 h-3 inline-block text-stone-700 dark:text-stone-300 ml-2 mt-2 sm:mt-1">
|
|
794
|
+
<FaChevronDown/>
|
|
795
|
+
</span>
|
|
796
|
+
</button>
|
|
797
|
+
</div>
|
|
798
|
+
{/if}
|
|
799
|
+
</section>
|
|
494
800
|
</Modal>
|
|
495
801
|
|
|
802
|
+
<Modal title="User removal"
|
|
803
|
+
content="Are you sure you want to remove {userToRemove ? userToRemove[nameAttrib] : 'user'} from the group?"
|
|
804
|
+
icon={FaUserMinus}
|
|
805
|
+
okCaption='Remove'
|
|
806
|
+
onOkCallback={removeUser}
|
|
807
|
+
bind:this={removeModal}
|
|
808
|
+
/>
|