@nymphjs/tilmeld-setup 1.0.0-beta.12 → 1.0.0-beta.121
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 +478 -0
- package/README.md +6 -5
- package/app/index.ts +9 -3
- package/app/src/App.svelte +148 -77
- package/app/src/nymph.ts +1 -1
- package/app/src/routes/GroupEdit.svelte +638 -0
- package/app/src/routes/Groups.svelte +201 -0
- package/app/src/{Intro.svelte → routes/Intro.svelte} +14 -1
- package/app/src/routes/NotFound.svelte +9 -0
- package/app/src/routes/UserEdit.svelte +1202 -0
- package/app/src/routes/Users.svelte +201 -0
- package/app/theme/_smui-theme.scss +5 -5
- package/dist/app/index.css +105 -0
- package/dist/app/index.js +43615 -3
- package/dist/app/smui.css +1 -29
- package/dist/index.d.ts +5 -3
- package/dist/index.js +19 -20
- package/dist/index.js.map +1 -1
- package/jest.config.js +31 -5
- package/package.json +67 -59
- package/rollup.config.mjs +36 -0
- package/src/index.ts +26 -21
- package/static/index.html +4 -1
- package/test.mjs +13 -12
- package/tsconfig.json +13 -1
- package/tsconfig.server.json +6 -3
- package/typedoc.json +5 -0
- package/app/src/GroupEdit.svelte +0 -570
- package/app/src/Groups.svelte +0 -159
- package/app/src/UserEdit.svelte +0 -902
- package/app/src/Users.svelte +0 -159
- package/dist/app/index.js.LICENSE.txt +0 -114
- package/dist/app/index.js.map +0 -1
- package/webpack.config.js +0 -38
package/app/src/App.svelte
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<svelte:window
|
|
1
|
+
<svelte:window onresize={setMiniWindow} />
|
|
2
|
+
|
|
2
3
|
<TopAppBar variant="static" class="tilmeld-top-app-bar">
|
|
3
4
|
<Row>
|
|
4
5
|
<Section>
|
|
5
6
|
{#if miniWindow}
|
|
6
|
-
<IconButton
|
|
7
|
-
class="material-icons"
|
|
8
|
-
|
|
9
|
-
>
|
|
7
|
+
<IconButton onclick={() => (drawerOpen = !drawerOpen)}>
|
|
8
|
+
<Icon class="material-icons">menu</Icon>
|
|
9
|
+
</IconButton>
|
|
10
10
|
{/if}
|
|
11
11
|
<Title style={miniWindow ? 'padding-left: 0;' : ''}>
|
|
12
12
|
{miniWindow ? 'Tilmeld Setup' : 'Tilmeld Setup App'}
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
</Section>
|
|
15
15
|
<Section align="end" toolbar style="color: var(--mdc-on-surface, #000);">
|
|
16
16
|
<IconButton
|
|
17
|
-
href="https://
|
|
17
|
+
href="https://forge.sciactive.com/sciactive/nymphjs"
|
|
18
18
|
target="_blank"
|
|
19
19
|
rel="noreferrer"
|
|
20
|
-
title="Nymph/Tilmeld on
|
|
20
|
+
title="Nymph/Tilmeld on SciActive Forge"
|
|
21
21
|
>
|
|
22
|
-
<Icon
|
|
23
|
-
<path fill="currentColor" d={
|
|
22
|
+
<Icon tag="svg" viewBox="0 0 24 24">
|
|
23
|
+
<path fill="currentColor" d={mdiGit} />
|
|
24
24
|
</Icon>
|
|
25
25
|
</IconButton>
|
|
26
26
|
<IconButton
|
|
@@ -29,34 +29,24 @@
|
|
|
29
29
|
rel="noreferrer"
|
|
30
30
|
title="SciActive on Mastodon"
|
|
31
31
|
>
|
|
32
|
-
<Icon
|
|
32
|
+
<Icon tag="svg" viewBox="0 0 24 24">
|
|
33
33
|
<path fill="currentColor" d={mdiMastodon} />
|
|
34
34
|
</Icon>
|
|
35
35
|
</IconButton>
|
|
36
|
-
<IconButton
|
|
37
|
-
href="https://twitter.com/SciActive"
|
|
38
|
-
target="_blank"
|
|
39
|
-
rel="noreferrer"
|
|
40
|
-
title="SciActive on Twitter"
|
|
41
|
-
>
|
|
42
|
-
<Icon component={Svg} viewBox="0 0 24 24">
|
|
43
|
-
<path fill="currentColor" d={mdiTwitter} />
|
|
44
|
-
</Icon>
|
|
45
|
-
</IconButton>
|
|
46
36
|
<div>
|
|
47
37
|
<IconButton
|
|
48
38
|
title="Account"
|
|
49
|
-
|
|
39
|
+
onclick={() => $user != null && accountMenu.setOpen(true)}
|
|
50
40
|
>
|
|
51
41
|
<Icon tag="img" src={userAvatar} />
|
|
52
42
|
</IconButton>
|
|
53
43
|
<Menu bind:this={accountMenu} anchorCorner="BOTTOM_LEFT">
|
|
54
44
|
<List>
|
|
55
|
-
<Item
|
|
45
|
+
<Item onSMUIAction={() => (accountOpen = true)}>
|
|
56
46
|
<Text>Account Details</Text>
|
|
57
47
|
</Item>
|
|
58
48
|
<Separator />
|
|
59
|
-
<Item
|
|
49
|
+
<Item onSMUIAction={() => $user?.$logout()}>
|
|
60
50
|
<Text>Logout</Text>
|
|
61
51
|
</Item>
|
|
62
52
|
</List>
|
|
@@ -74,7 +64,7 @@
|
|
|
74
64
|
: 'hide-initial-small'}"
|
|
75
65
|
>
|
|
76
66
|
<Content>
|
|
77
|
-
<List>
|
|
67
|
+
<List tag="div">
|
|
78
68
|
{#if tilmeldAdmin}
|
|
79
69
|
{#each sections as section (section.name)}
|
|
80
70
|
{#if 'separator' in section}
|
|
@@ -82,13 +72,14 @@
|
|
|
82
72
|
{:else}
|
|
83
73
|
<Item
|
|
84
74
|
bind:this={section.component}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
75
|
+
tag="a"
|
|
76
|
+
nonInteractive={!('href' in section)}
|
|
77
|
+
href={'href' in section ? `#${section.href}` : undefined}
|
|
78
|
+
activated={section.absolute
|
|
79
|
+
? `${currentMatch.route.path}/` === section.href
|
|
80
|
+
: `${currentMatch.route.path}/`.startsWith(
|
|
81
|
+
section.href ?? '!',
|
|
82
|
+
)}
|
|
92
83
|
style={section.indent
|
|
93
84
|
? 'margin-left: ' + section.indent * 25 + 'px;'
|
|
94
85
|
: ''}
|
|
@@ -97,12 +88,12 @@
|
|
|
97
88
|
</Item>
|
|
98
89
|
{/if}
|
|
99
90
|
{/each}
|
|
100
|
-
{:else if user == null}
|
|
101
|
-
<Item
|
|
91
|
+
{:else if $user == null}
|
|
92
|
+
<Item tag="span" onclick={() => (drawerOpen = false)} activated>
|
|
102
93
|
<Text class="mdc-theme--on-secondary">Login</Text>
|
|
103
94
|
</Item>
|
|
104
95
|
{:else}
|
|
105
|
-
<Item
|
|
96
|
+
<Item tag="span" onclick={() => (drawerOpen = false)} activated>
|
|
106
97
|
<Text class="mdc-theme--on-secondary">Forbidden</Text>
|
|
107
98
|
</Item>
|
|
108
99
|
{/if}
|
|
@@ -116,83 +107,157 @@
|
|
|
116
107
|
<AppContent class="tilmeld-app-content">
|
|
117
108
|
<main class="tilmeld-main-content" bind:this={mainContent}>
|
|
118
109
|
{#if tilmeldAdmin}
|
|
119
|
-
{#if clientConfig}
|
|
120
|
-
<
|
|
110
|
+
{#if $clientConfig}
|
|
111
|
+
<CurrentRoute {router} {params} {clientConfig} {user} />
|
|
121
112
|
{:else}
|
|
122
113
|
Loading...
|
|
123
114
|
{/if}
|
|
124
|
-
{:else if user
|
|
115
|
+
{:else if $user === null}
|
|
125
116
|
<section style="display: flex; justify-content: center;">
|
|
126
|
-
<Login
|
|
117
|
+
<Login
|
|
118
|
+
{User}
|
|
119
|
+
{clientConfig}
|
|
120
|
+
showExistingUserToggle={allowRegistration}
|
|
121
|
+
/>
|
|
127
122
|
</section>
|
|
123
|
+
{:else if $user === undefined}
|
|
124
|
+
Loading...
|
|
128
125
|
{:else}
|
|
129
126
|
<section>You don't have permission to access this app.</section>
|
|
130
127
|
{/if}
|
|
131
|
-
<Account bind:open={accountOpen} {User} {clientConfig} />
|
|
128
|
+
<Account bind:open={accountOpen} {User} {user} {clientConfig} />
|
|
132
129
|
</main>
|
|
133
130
|
</AppContent>
|
|
134
131
|
</div>
|
|
135
132
|
|
|
136
133
|
<script lang="ts">
|
|
137
|
-
import {
|
|
134
|
+
import type { Component } from 'svelte';
|
|
135
|
+
import { onMount } from 'svelte';
|
|
136
|
+
import type { Writable } from 'svelte/store';
|
|
137
|
+
import { writable } from 'svelte/store';
|
|
138
|
+
import Navigo from 'navigo';
|
|
138
139
|
import type {
|
|
139
140
|
User as UserClass,
|
|
140
141
|
ClientConfig,
|
|
141
142
|
CurrentUserData,
|
|
142
143
|
} from '@nymphjs/tilmeld-client';
|
|
143
144
|
import { Login, Account } from '@nymphjs/tilmeld-components';
|
|
144
|
-
import {
|
|
145
|
+
import { mdiGit, mdiMastodon } from '@mdi/js';
|
|
145
146
|
import TopAppBar, { Row, Section, Title } from '@smui/top-app-bar';
|
|
146
147
|
import Drawer, { Content, Scrim, AppContent } from '@smui/drawer';
|
|
147
148
|
import IconButton from '@smui/icon-button';
|
|
148
149
|
import List, { Item, Text, Separator } from '@smui/list';
|
|
149
150
|
import Menu from '@smui/menu';
|
|
150
|
-
import { Icon
|
|
151
|
+
import { Icon } from '@smui/common';
|
|
151
152
|
|
|
152
153
|
import { User } from './nymph';
|
|
153
|
-
import Intro from './Intro.svelte';
|
|
154
|
-
import Users from './Users.svelte';
|
|
155
|
-
import
|
|
156
|
-
import
|
|
154
|
+
import Intro from './routes/Intro.svelte';
|
|
155
|
+
import Users from './routes/Users.svelte';
|
|
156
|
+
import UserEdit from './routes/UserEdit.svelte';
|
|
157
|
+
import Groups from './routes/Groups.svelte';
|
|
158
|
+
import GroupEdit from './routes/GroupEdit.svelte';
|
|
159
|
+
import NotFound from './routes/NotFound.svelte';
|
|
157
160
|
|
|
158
161
|
const DEFAULT_AVATAR = 'https://secure.gravatar.com/avatar/?d=mm&s=40';
|
|
162
|
+
const allowRegistration = (window as any).allowRegistration;
|
|
159
163
|
|
|
160
164
|
let mainContent: HTMLElement;
|
|
161
|
-
let miniWindow = false;
|
|
162
|
-
let drawerOpen = false;
|
|
165
|
+
let miniWindow = $state(false);
|
|
166
|
+
let drawerOpen = $state(false);
|
|
163
167
|
let accountMenu: any;
|
|
164
|
-
let
|
|
165
|
-
let
|
|
166
|
-
|
|
167
|
-
let userAvatar: string = DEFAULT_AVATAR;
|
|
168
|
-
let tilmeldAdmin: boolean | undefined =
|
|
169
|
-
let accountOpen = false;
|
|
170
|
-
|
|
171
|
-
$: if (active && mainContent) {
|
|
172
|
-
drawerOpen = false;
|
|
173
|
-
mainContent.scrollTop = 0;
|
|
174
|
-
}
|
|
168
|
+
let clientConfig: Writable<ClientConfig | undefined> = writable();
|
|
169
|
+
let user: Writable<(UserClass & CurrentUserData) | null | undefined> =
|
|
170
|
+
writable();
|
|
171
|
+
let userAvatar: string = $state(DEFAULT_AVATAR);
|
|
172
|
+
let tilmeldAdmin: boolean | undefined = $state();
|
|
173
|
+
let accountOpen = $state(false);
|
|
175
174
|
|
|
176
|
-
|
|
177
|
-
user
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
175
|
+
$effect(() => {
|
|
176
|
+
if ($user) {
|
|
177
|
+
$user
|
|
178
|
+
.$gatekeeper('tilmeld/admin')
|
|
179
|
+
.then((value) => (tilmeldAdmin = value));
|
|
180
|
+
$user.$getAvatar().then((value) => (userAvatar = value));
|
|
181
|
+
} else {
|
|
182
|
+
tilmeldAdmin = undefined;
|
|
183
|
+
userAvatar = DEFAULT_AVATAR;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const router = new Navigo('/', { hash: true });
|
|
188
|
+
let CurrentRoute: Component<any> = $state(Intro);
|
|
189
|
+
let params: any = $state({});
|
|
190
|
+
|
|
191
|
+
router.hooks({
|
|
192
|
+
before(done, match) {
|
|
193
|
+
if (mainContent) {
|
|
194
|
+
drawerOpen = false;
|
|
195
|
+
mainContent.scrollTop = 0;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
currentMatch = match;
|
|
199
|
+
|
|
200
|
+
done();
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
router.on({
|
|
205
|
+
'/': () => {
|
|
206
|
+
CurrentRoute = Intro;
|
|
207
|
+
params = {};
|
|
208
|
+
},
|
|
209
|
+
'/users/edit/:guid': ({ data }: any) => {
|
|
210
|
+
CurrentRoute = UserEdit;
|
|
211
|
+
params = data;
|
|
212
|
+
},
|
|
213
|
+
'/users/': () => {
|
|
214
|
+
CurrentRoute = Users;
|
|
215
|
+
params = {};
|
|
216
|
+
},
|
|
217
|
+
'/users/:query?': ({ data }: any) => {
|
|
218
|
+
CurrentRoute = Users;
|
|
219
|
+
params = data;
|
|
220
|
+
},
|
|
221
|
+
'/groups/edit/:guid': ({ data }: any) => {
|
|
222
|
+
CurrentRoute = GroupEdit;
|
|
223
|
+
params = data;
|
|
224
|
+
},
|
|
225
|
+
'/groups/': () => {
|
|
226
|
+
CurrentRoute = Groups;
|
|
227
|
+
params = {};
|
|
228
|
+
},
|
|
229
|
+
'/groups/:query?': ({ data }: any) => {
|
|
230
|
+
CurrentRoute = Groups;
|
|
231
|
+
params = data;
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
router.notFound(({ hashString }: any) => {
|
|
236
|
+
if (hashString === '') {
|
|
237
|
+
router.navigate('/', { historyAPIMethod: 'replaceState' });
|
|
238
|
+
} else {
|
|
239
|
+
CurrentRoute = NotFound;
|
|
240
|
+
params = {};
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
let currentMatch = $state(router.getCurrentLocation());
|
|
245
|
+
router.resolve();
|
|
183
246
|
|
|
184
247
|
const sections: (
|
|
185
248
|
| {
|
|
186
249
|
name: string;
|
|
187
250
|
indent: number;
|
|
188
|
-
|
|
189
|
-
|
|
251
|
+
href?: string;
|
|
252
|
+
absolute?: boolean;
|
|
253
|
+
component?: ReturnType<Component<any>>;
|
|
190
254
|
}
|
|
191
255
|
| { name: string; separator: true }
|
|
192
256
|
)[] = [
|
|
193
257
|
{
|
|
194
258
|
name: 'Introduction',
|
|
195
|
-
|
|
259
|
+
href: '/',
|
|
260
|
+
absolute: true,
|
|
196
261
|
indent: 0,
|
|
197
262
|
},
|
|
198
263
|
{
|
|
@@ -201,31 +266,37 @@
|
|
|
201
266
|
},
|
|
202
267
|
{
|
|
203
268
|
name: 'Users',
|
|
204
|
-
|
|
269
|
+
href: 'users/',
|
|
205
270
|
indent: 0,
|
|
206
271
|
},
|
|
207
272
|
{
|
|
208
273
|
name: 'Groups',
|
|
209
|
-
|
|
274
|
+
href: 'groups/',
|
|
210
275
|
indent: 0,
|
|
211
276
|
},
|
|
212
277
|
];
|
|
213
278
|
|
|
214
279
|
const onLogin = (currentUser: UserClass & CurrentUserData) => {
|
|
215
|
-
user = currentUser;
|
|
280
|
+
$user = currentUser;
|
|
281
|
+
// Helps with admin and debugging.
|
|
282
|
+
(window as any).user = currentUser;
|
|
216
283
|
};
|
|
217
284
|
const onLogout = () => {
|
|
218
|
-
user =
|
|
285
|
+
$user = null;
|
|
286
|
+
// Helps with admin and debugging.
|
|
287
|
+
(window as any).user = null;
|
|
219
288
|
};
|
|
220
289
|
|
|
221
290
|
onMount(setMiniWindow);
|
|
222
291
|
onMount(async () => {
|
|
223
292
|
User.on('login', onLogin);
|
|
224
293
|
User.on('logout', onLogout);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
294
|
+
|
|
295
|
+
$clientConfig = await User.getClientConfig();
|
|
296
|
+
|
|
297
|
+
$user = await User.current();
|
|
298
|
+
// Helps with admin and debugging.
|
|
299
|
+
(window as any).user = $user;
|
|
229
300
|
});
|
|
230
301
|
|
|
231
302
|
function setMiniWindow() {
|
package/app/src/nymph.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from '@nymphjs/tilmeld-client';
|
|
7
7
|
|
|
8
8
|
const nymph = new Nymph(
|
|
9
|
-
(window as unknown as { nymphOptions: NymphOptions }).nymphOptions
|
|
9
|
+
(window as unknown as { nymphOptions: NymphOptions }).nymphOptions,
|
|
10
10
|
);
|
|
11
11
|
const User = nymph.addEntityClass(UserClass);
|
|
12
12
|
const Group = nymph.addEntityClass(GroupClass);
|