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