ichec-angular-core 0.0.13 → 0.1.0
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/fesm2022/ichec-angular-core.mjs +842 -202
- package/fesm2022/ichec-angular-core.mjs.map +1 -1
- package/index.d.ts +233 -84
- package/package.json +1 -1
- package/styles/styles.scss +1 -0
|
@@ -1,37 +1,70 @@
|
|
|
1
|
-
import { map, catchError, mergeMap, throwError, BehaviorSubject, mergeAll,
|
|
2
|
-
import {
|
|
1
|
+
import { map, catchError, tap, mergeMap, throwError, BehaviorSubject, mergeAll, merge, debounceTime, distinctUntilChanged, Subscription, of, finalize } from 'rxjs';
|
|
2
|
+
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { InjectionToken, inject, Injectable, input, signal, Component, computed, output
|
|
5
|
-
import { NgIf, Location,
|
|
6
|
-
import * as
|
|
4
|
+
import { InjectionToken, inject, Injectable, input, signal, Component, viewChild, computed, output } from '@angular/core';
|
|
5
|
+
import { NgIf, Location, NgTemplateOutlet, TitleCasePipe } from '@angular/common';
|
|
6
|
+
import * as i1 from '@angular/router';
|
|
7
7
|
import { RouterModule, RouterOutlet, Router, ActivatedRoute } from '@angular/router';
|
|
8
8
|
import * as i2 from '@angular/material/toolbar';
|
|
9
9
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
10
|
-
import * as i3
|
|
10
|
+
import * as i3 from '@angular/material/icon';
|
|
11
11
|
import { MatIconModule } from '@angular/material/icon';
|
|
12
12
|
import * as i2$1 from '@angular/material/button';
|
|
13
13
|
import { MatButtonModule } from '@angular/material/button';
|
|
14
14
|
import * as i5 from '@angular/material/menu';
|
|
15
15
|
import { MatMenuModule } from '@angular/material/menu';
|
|
16
|
-
import * as i1 from '@angular/material/sidenav';
|
|
17
|
-
import { MatSidenavModule } from '@angular/material/sidenav';
|
|
16
|
+
import * as i1$1 from '@angular/material/sidenav';
|
|
17
|
+
import { MatSidenavContent, MatSidenavModule } from '@angular/material/sidenav';
|
|
18
18
|
import * as i2$2 from '@angular/material/list';
|
|
19
19
|
import { MatListModule } from '@angular/material/list';
|
|
20
|
-
import * as i1$
|
|
21
|
-
import { FormsModule,
|
|
20
|
+
import * as i1$2 from '@angular/forms';
|
|
21
|
+
import { FormsModule, FormControl, ReactiveFormsModule, FormBuilder } from '@angular/forms';
|
|
22
22
|
import * as i3$2 from '@angular/material/input';
|
|
23
23
|
import { MatInputModule } from '@angular/material/input';
|
|
24
|
-
import * as
|
|
24
|
+
import * as i3$1 from '@angular/material/form-field';
|
|
25
25
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
26
|
-
import * as
|
|
26
|
+
import * as i1$3 from '@angular/material/card';
|
|
27
27
|
import { MatCardModule } from '@angular/material/card';
|
|
28
|
-
import * as i1$
|
|
28
|
+
import * as i1$4 from '@angular/material/table';
|
|
29
29
|
import { MatTable, MatTableModule } from '@angular/material/table';
|
|
30
|
-
import * as
|
|
30
|
+
import * as i6 from '@angular/material/select';
|
|
31
31
|
import { MatSelectModule } from '@angular/material/select';
|
|
32
|
+
import * as i6$1 from '@angular/material/autocomplete';
|
|
33
|
+
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
|
34
|
+
import * as i4 from '@angular/material/tooltip';
|
|
35
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
36
|
+
import * as i3$3 from '@angular/material/sort';
|
|
37
|
+
import { MatSort, MatSortModule } from '@angular/material/sort';
|
|
38
|
+
import * as i1$5 from '@angular/material/button-toggle';
|
|
39
|
+
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
40
|
+
import * as i2$5 from '@angular/material/progress-spinner';
|
|
41
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
42
|
+
import * as i2$3 from '@angular/material/paginator';
|
|
43
|
+
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
|
|
44
|
+
import * as i2$4 from '@angular/cdk/scrolling';
|
|
45
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
46
|
+
import { DataSource } from '@angular/cdk/collections';
|
|
32
47
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
33
48
|
|
|
49
|
+
class Paginated {
|
|
50
|
+
count = 0;
|
|
51
|
+
next = null;
|
|
52
|
+
previous = null;
|
|
53
|
+
results = [];
|
|
54
|
+
}
|
|
55
|
+
class Permission {
|
|
56
|
+
id = 0;
|
|
57
|
+
url = "";
|
|
58
|
+
codename = "";
|
|
59
|
+
static typename = "permission";
|
|
60
|
+
static plural = "permissions";
|
|
61
|
+
constructor(params = {}) {
|
|
62
|
+
Object.assign(this, params);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
34
65
|
class PortalMember {
|
|
66
|
+
static typename = "member";
|
|
67
|
+
static plural = "members";
|
|
35
68
|
id = 0;
|
|
36
69
|
url = "";
|
|
37
70
|
username = "";
|
|
@@ -41,30 +74,34 @@ class PortalMember {
|
|
|
41
74
|
phone = "";
|
|
42
75
|
organization = "";
|
|
43
76
|
profile_url = "";
|
|
77
|
+
all_permissions = [];
|
|
44
78
|
constructor(params = {}) {
|
|
45
79
|
Object.assign(this, params);
|
|
46
80
|
}
|
|
47
81
|
}
|
|
48
82
|
class Group {
|
|
83
|
+
static typename = "group";
|
|
84
|
+
static plural = "groups";
|
|
49
85
|
name = "";
|
|
50
86
|
url = "";
|
|
51
87
|
id = 0;
|
|
52
|
-
}
|
|
53
|
-
class Organization {
|
|
54
|
-
id = 0;
|
|
55
|
-
url = "";
|
|
56
|
-
name = "";
|
|
57
|
-
acronym = "";
|
|
58
|
-
description = "";
|
|
59
|
-
address = "";
|
|
60
|
-
website = "";
|
|
61
|
-
country = "";
|
|
62
|
-
members = [];
|
|
63
88
|
constructor(params = {}) {
|
|
64
89
|
Object.assign(this, params);
|
|
65
90
|
}
|
|
66
91
|
}
|
|
67
92
|
|
|
93
|
+
class ItemQuery {
|
|
94
|
+
queries = new Map();
|
|
95
|
+
page = 0;
|
|
96
|
+
page_size = 0;
|
|
97
|
+
sort_field = "";
|
|
98
|
+
sort_order = "";
|
|
99
|
+
filter_field = "";
|
|
100
|
+
filter = "";
|
|
101
|
+
constructor(params = {}) {
|
|
102
|
+
Object.assign(this, params);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
68
105
|
var ErrorCode;
|
|
69
106
|
(function (ErrorCode) {
|
|
70
107
|
ErrorCode[ErrorCode["UnknownError"] = 1] = "UnknownError";
|
|
@@ -76,22 +113,42 @@ class ApiError {
|
|
|
76
113
|
|
|
77
114
|
const ENDPOINT_URL = new InjectionToken("Default endpoint url");
|
|
78
115
|
class RestService {
|
|
79
|
-
_url;
|
|
80
|
-
_endpoint_url;
|
|
81
|
-
_http;
|
|
82
|
-
constructor(_url, _endpoint_url, _http) {
|
|
83
|
-
this._url = _url;
|
|
84
|
-
this._endpoint_url = _endpoint_url;
|
|
85
|
-
this._http = _http;
|
|
86
|
-
}
|
|
116
|
+
_url = "";
|
|
117
|
+
_endpoint_url = inject(ENDPOINT_URL);
|
|
118
|
+
_http = inject(HttpClient);
|
|
87
119
|
deleteItem(id) {
|
|
88
120
|
return this._http.delete(this.getBaseUrl() + id + "/", { headers: this.getHeaders() }).pipe(map(_response => { return void (0); }), catchError(this.handleError));
|
|
89
121
|
}
|
|
90
|
-
getForUser(user) {
|
|
91
|
-
|
|
122
|
+
getForUser(user, query = new ItemQuery()) {
|
|
123
|
+
query.queries.set('user', user.id.toString());
|
|
124
|
+
return this.get(query);
|
|
92
125
|
}
|
|
93
|
-
get(query =
|
|
94
|
-
|
|
126
|
+
get(query = new ItemQuery()) {
|
|
127
|
+
const params = query.queries;
|
|
128
|
+
if (query.page > 0) {
|
|
129
|
+
params.set('page', query.page.toString());
|
|
130
|
+
}
|
|
131
|
+
if (query.page_size > 0) {
|
|
132
|
+
params.set('page_size', query.page_size.toString());
|
|
133
|
+
}
|
|
134
|
+
if (query.sort_field) {
|
|
135
|
+
let sort_field = query.sort_field;
|
|
136
|
+
if (query.sort_order === "desc") {
|
|
137
|
+
sort_field = "-" + sort_field;
|
|
138
|
+
}
|
|
139
|
+
params.set('ordering', sort_field);
|
|
140
|
+
}
|
|
141
|
+
if (query.filter_field) {
|
|
142
|
+
params.set('search_field', query.filter_field);
|
|
143
|
+
}
|
|
144
|
+
if (query.filter) {
|
|
145
|
+
params.set('search', query.filter);
|
|
146
|
+
}
|
|
147
|
+
console.log(params);
|
|
148
|
+
return this._http.get(this.getBaseUrl(), {
|
|
149
|
+
headers: this.getHeaders(),
|
|
150
|
+
params: new HttpParams({ fromObject: Object.fromEntries(params) })
|
|
151
|
+
}).pipe(tap(response => console.log(response)), catchError(this.handleError));
|
|
95
152
|
}
|
|
96
153
|
getItem(id) {
|
|
97
154
|
return this._http.get(this.getBaseUrl() + id, { headers: this.getHeaders() }).pipe(catchError(this.handleError));
|
|
@@ -99,6 +156,9 @@ class RestService {
|
|
|
99
156
|
getUrl(url) {
|
|
100
157
|
return this._http.get(url, { headers: this.getHeaders() }).pipe(catchError(this.handleError));
|
|
101
158
|
}
|
|
159
|
+
getPaginatedUrl(url) {
|
|
160
|
+
return this._http.get(url, { headers: this.getHeaders() }).pipe(catchError(this.handleError));
|
|
161
|
+
}
|
|
102
162
|
getOptions() {
|
|
103
163
|
return this._http.options(this.getBaseUrl(), { headers: this.getHeaders() }).pipe(catchError(this.handleError));
|
|
104
164
|
}
|
|
@@ -165,12 +225,44 @@ class RestService {
|
|
|
165
225
|
}
|
|
166
226
|
}
|
|
167
227
|
|
|
168
|
-
class
|
|
169
|
-
|
|
228
|
+
class ItemService extends RestService {
|
|
229
|
+
itemType = "";
|
|
230
|
+
canEdit() {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
canCreate() {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
canDelete() {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
canView() {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
instantiateType(_) {
|
|
243
|
+
throw new Error('Not Implemented');
|
|
244
|
+
}
|
|
245
|
+
getItem(id) {
|
|
246
|
+
return super.getItem(id).pipe(map(x => this.instantiateType(x)));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
class ResolvedPermission {
|
|
251
|
+
canEdit = false;
|
|
252
|
+
canAdd = false;
|
|
253
|
+
canView = false;
|
|
254
|
+
canDelete = false;
|
|
255
|
+
}
|
|
256
|
+
class UserService extends ItemService {
|
|
257
|
+
/**
|
|
258
|
+
Service to handle IPortalMember via REST and also handle logins.
|
|
170
259
|
*/
|
|
171
260
|
loggedInUser = new BehaviorSubject(null);
|
|
172
|
-
|
|
173
|
-
|
|
261
|
+
_url = PortalMember.plural;
|
|
262
|
+
itemType = PortalMember.plural;
|
|
263
|
+
permissions = new Map();
|
|
264
|
+
instantiateType(item) {
|
|
265
|
+
return new PortalMember(item);
|
|
174
266
|
}
|
|
175
267
|
login(username, password) {
|
|
176
268
|
console.log("Attempting login");
|
|
@@ -181,6 +273,34 @@ class UserService extends RestService {
|
|
|
181
273
|
const api_auth_endpoint = this._endpoint_url + "/api-token-auth/";
|
|
182
274
|
return this._http.post(api_auth_endpoint, body.toString(), { headers: headers }).pipe(map(token => this.onLoginToken(token)), mergeAll(), catchError(this.handleError));
|
|
183
275
|
}
|
|
276
|
+
hasAddPermission(feature) {
|
|
277
|
+
const perm = this.permissions.get(feature);
|
|
278
|
+
if (!perm) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
return perm.canAdd;
|
|
282
|
+
}
|
|
283
|
+
hasDeletePermission(feature) {
|
|
284
|
+
const perm = this.permissions.get(feature);
|
|
285
|
+
if (!perm) {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
return perm.canDelete;
|
|
289
|
+
}
|
|
290
|
+
hasEditPermission(feature) {
|
|
291
|
+
const perm = this.permissions.get(feature);
|
|
292
|
+
if (!perm) {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
return perm.canEdit;
|
|
296
|
+
}
|
|
297
|
+
hasViewPermission(feature) {
|
|
298
|
+
const perm = this.permissions.get(feature);
|
|
299
|
+
if (!perm) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
return perm.canView;
|
|
303
|
+
}
|
|
184
304
|
logout() {
|
|
185
305
|
if (this.loggedInUser === null) {
|
|
186
306
|
return;
|
|
@@ -195,10 +315,39 @@ class UserService extends RestService {
|
|
|
195
315
|
return this.getItem(Number(token_response.user_id)).pipe(tap(user => this.onLoggedIn(user)), map(_response => { return void (0); }), catchError(this.handleError));
|
|
196
316
|
}
|
|
197
317
|
onLoggedIn(user) {
|
|
198
|
-
console.log("Log in
|
|
318
|
+
console.log("Log in successful for user: " + user.username);
|
|
199
319
|
this.loggedInUser.next(user);
|
|
320
|
+
this.processPermissions();
|
|
321
|
+
}
|
|
322
|
+
parsePermission(p) {
|
|
323
|
+
const split_module = p.split(".");
|
|
324
|
+
const split_cap = split_module[split_module.length - 1].split("_");
|
|
325
|
+
return { feature: split_cap[1], capability: split_cap[0] };
|
|
326
|
+
}
|
|
327
|
+
processPermissions() {
|
|
328
|
+
const user = this.loggedInUser.value;
|
|
329
|
+
if (!user) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
user.all_permissions.forEach(p => this.permissions.set(this.parsePermission(p).feature, new ResolvedPermission()));
|
|
333
|
+
user.all_permissions.forEach(p => {
|
|
334
|
+
const permission = this.parsePermission(p);
|
|
335
|
+
if (permission.capability === "view") {
|
|
336
|
+
this.permissions.get(permission.feature).canView = true;
|
|
337
|
+
}
|
|
338
|
+
else if (permission.capability === "delete") {
|
|
339
|
+
this.permissions.get(permission.feature).canDelete = true;
|
|
340
|
+
}
|
|
341
|
+
else if (permission.capability === "change") {
|
|
342
|
+
this.permissions.get(permission.feature).canEdit = true;
|
|
343
|
+
}
|
|
344
|
+
else if (permission.capability === "add") {
|
|
345
|
+
this.permissions.get(permission.feature).canAdd = true;
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
console.log("Got permissions:", this.permissions);
|
|
200
349
|
}
|
|
201
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserService, deps:
|
|
350
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
202
351
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserService, providedIn: 'root' });
|
|
203
352
|
}
|
|
204
353
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserService, decorators: [{
|
|
@@ -206,23 +355,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
206
355
|
args: [{
|
|
207
356
|
providedIn: 'root',
|
|
208
357
|
}]
|
|
209
|
-
}]
|
|
358
|
+
}] });
|
|
210
359
|
|
|
211
|
-
class GroupService extends
|
|
360
|
+
class GroupService extends ItemService {
|
|
212
361
|
userService = inject(UserService);
|
|
213
362
|
userItems = new BehaviorSubject([]);
|
|
363
|
+
_url = Group.plural;
|
|
364
|
+
itemType = Group.plural;
|
|
214
365
|
constructor() {
|
|
215
|
-
super(
|
|
366
|
+
super();
|
|
216
367
|
this.userService.loggedInUser.subscribe(user => this.refreshUserItems(user));
|
|
217
368
|
}
|
|
218
369
|
refreshUserItems(user) {
|
|
219
370
|
if (user) {
|
|
220
|
-
this.getForUser(user).subscribe(items => this.userItems.next(items));
|
|
371
|
+
this.getForUser(user).subscribe(items => this.userItems.next(items.results));
|
|
221
372
|
}
|
|
222
373
|
else {
|
|
223
374
|
this.userItems.next([]);
|
|
224
375
|
}
|
|
225
376
|
}
|
|
377
|
+
instantiateType(item) {
|
|
378
|
+
return new Group(item);
|
|
379
|
+
}
|
|
226
380
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
227
381
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupService, providedIn: 'root' });
|
|
228
382
|
}
|
|
@@ -233,11 +387,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
233
387
|
}]
|
|
234
388
|
}], ctorParameters: () => [] });
|
|
235
389
|
|
|
236
|
-
class
|
|
237
|
-
|
|
238
|
-
|
|
390
|
+
class Address {
|
|
391
|
+
static typename = "address";
|
|
392
|
+
static plural = "addresses";
|
|
393
|
+
id = 0;
|
|
394
|
+
url = "";
|
|
395
|
+
line1 = "";
|
|
396
|
+
line2 = "";
|
|
397
|
+
line3 = "";
|
|
398
|
+
city = "";
|
|
399
|
+
region = "";
|
|
400
|
+
postcode = "";
|
|
401
|
+
country = "";
|
|
402
|
+
country_name = "";
|
|
403
|
+
country_flag = "";
|
|
404
|
+
members = [];
|
|
405
|
+
constructor(params = {}) {
|
|
406
|
+
Object.assign(this, params);
|
|
239
407
|
}
|
|
240
|
-
|
|
408
|
+
}
|
|
409
|
+
class Organization {
|
|
410
|
+
static typename = "organization";
|
|
411
|
+
static plural = "organizations";
|
|
412
|
+
id = 0;
|
|
413
|
+
url = "";
|
|
414
|
+
name = "";
|
|
415
|
+
acronym = "";
|
|
416
|
+
description = "";
|
|
417
|
+
address = "";
|
|
418
|
+
website = "";
|
|
419
|
+
members = [];
|
|
420
|
+
constructor(params = {}) {
|
|
421
|
+
Object.assign(this, params);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
class OrganizationService extends ItemService {
|
|
426
|
+
_url = Organization.plural;
|
|
427
|
+
itemType = Organization.plural;
|
|
428
|
+
userService = inject(UserService);
|
|
429
|
+
instantiateType(item) {
|
|
430
|
+
return new Organization(item);
|
|
431
|
+
}
|
|
432
|
+
canCreate() {
|
|
433
|
+
return this.userService.hasAddPermission(Organization.typename);
|
|
434
|
+
}
|
|
435
|
+
canView() {
|
|
436
|
+
return this.userService.hasViewPermission(Organization.typename);
|
|
437
|
+
}
|
|
438
|
+
canEdit() {
|
|
439
|
+
return this.userService.hasEditPermission(Organization.typename);
|
|
440
|
+
}
|
|
441
|
+
canDelete() {
|
|
442
|
+
return this.userService.hasDeletePermission(Organization.typename);
|
|
443
|
+
}
|
|
444
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
241
445
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationService, providedIn: 'root' });
|
|
242
446
|
}
|
|
243
447
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationService, decorators: [{
|
|
@@ -245,7 +449,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
245
449
|
args: [{
|
|
246
450
|
providedIn: 'root'
|
|
247
451
|
}]
|
|
248
|
-
}]
|
|
452
|
+
}] });
|
|
249
453
|
|
|
250
454
|
class LeftNavService {
|
|
251
455
|
activeOptions = new Set();
|
|
@@ -298,7 +502,7 @@ class TopBarComponent {
|
|
|
298
502
|
this.userService.logout();
|
|
299
503
|
}
|
|
300
504
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: TopBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
301
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: TopBarComponent, isStandalone: true, selector: "lib-top-bar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n@if(user(); as user){\n<mat-toolbar style=\"height:60px\">\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon>home</mat-icon>\n </a>\n <span>{{title()}}</span>\n <span class=\"topbar-spacer\"></span>\n <span>{{user.username}}</span>\n \n <button mat-icon-button aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon>person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <button mat-menu-item (click)=\"onLogout()\">Log Out</button>\n </mat-menu>\n</mat-toolbar>\n}\n", styles: [".topbar-spacer{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type:
|
|
505
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: TopBarComponent, isStandalone: true, selector: "lib-top-bar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n@if(user(); as user){\n<mat-toolbar style=\"height:60px\">\n <a mat-icon-button aria-label=\"Home\" [routerLink]=\"['home']\">\n <mat-icon>home</mat-icon>\n </a>\n <span>{{title()}}</span>\n <span class=\"topbar-spacer\"></span>\n <span>{{user.username}}</span>\n \n <button mat-icon-button aria-label=\"User Profile\" [matMenuTriggerFor]=\"profile_menu\">\n <mat-icon>person</mat-icon>\n </button>\n\n <mat-menu #profile_menu=\"matMenu\">\n <button mat-menu-item (click)=\"onLogout()\">Log Out</button>\n </mat-menu>\n</mat-toolbar>\n}\n", styles: [".topbar-spacer{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
|
|
302
506
|
}
|
|
303
507
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: TopBarComponent, decorators: [{
|
|
304
508
|
type: Component,
|
|
@@ -307,15 +511,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
307
511
|
|
|
308
512
|
class LeftNavComponent {
|
|
309
513
|
_leftNavService = inject(LeftNavService);
|
|
514
|
+
sideNavContent = viewChild(MatSidenavContent, ...(ngDevMode ? [{ debugName: "sideNavContent" }] : []));
|
|
310
515
|
getOptions() {
|
|
311
516
|
return this._leftNavService.activeOptions;
|
|
312
517
|
}
|
|
313
518
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LeftNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
314
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LeftNavComponent, isStandalone: true, selector: "lib-left-nav", ngImport: i0, template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet/>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:160px}.is-active{background-color:#d3d3d3}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type:
|
|
519
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LeftNavComponent, isStandalone: true, selector: "lib-left-nav", viewQueries: [{ propertyName: "sideNavContent", first: true, predicate: MatSidenavContent, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:160px}.is-active{background-color:#d3d3d3}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$1.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$1.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$1.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
|
|
315
520
|
}
|
|
316
521
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LeftNavComponent, decorators: [{
|
|
317
522
|
type: Component,
|
|
318
|
-
args: [{ selector: 'lib-left-nav', imports: [MatSidenavModule, MatListModule, RouterOutlet, RouterModule], template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet/>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:160px}.is-active{background-color:#d3d3d3}\n"] }]
|
|
523
|
+
args: [{ selector: 'lib-left-nav', imports: [MatSidenavModule, MatListModule, RouterOutlet, RouterModule], template: "<mat-sidenav-container class=\"leftnav-container\">\n <mat-sidenav mode=\"side\" class=\"leftnav-side\" opened>\n <mat-nav-list>\n @for (option of getOptions(); track option) {\n <a mat-list-item [routerLink]=\"option.route\" [routerLinkActive]=\"['is-active']\">{{ option.name }}</a>\n }\n </mat-nav-list>\n </mat-sidenav>\n <mat-sidenav-content class=\"leftnav-content\"> \n <router-outlet />\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host{display:flex;flex-direction:column}.leftnav-container{flex-grow:1;display:flex}.leftnav-content{display:flex;flex-grow:1;height:90vh}.leftnav-side{padding:5px;width:160px}.is-active{background-color:#d3d3d3}\n"] }]
|
|
319
524
|
}] });
|
|
320
525
|
|
|
321
526
|
const LOGIN_USER = new InjectionToken("Default login user - used for testing");
|
|
@@ -354,7 +559,7 @@ class LandingComponent {
|
|
|
354
559
|
this.router.navigateByUrl("/home");
|
|
355
560
|
}
|
|
356
561
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LandingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
357
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LandingComponent, isStandalone: true, selector: "lib-landing", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n @if(message(); as message){\n <p>{{message}}</p>\n }\n \n <mat-card style=\"text-align:center;\">\n <form class=\"base-form\" #loginForm=\"ngForm\" (ngSubmit)=\"login()\">\n <mat-card-content>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n [(ngModel)]=\"loginUser.name\"\n name=\"username\"\n required>\n </mat-form-field>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Password\"\n type=\"password\"\n [(ngModel)]=\"loginUser.password\"\n name=\"password\"\n required>\n </mat-form-field>\n </mat-card-content>\n <div *ngIf=\"loginError\" class=\"error\">\n <mat-icon>error</mat-icon><p>{{loginError()}}</p>\n </div>\n <button mat-flat-button\n type=\"submit\"\n [disabled]=\"!loginForm.form.valid\">Log In</button>\n </form>\n </mat-card>\n\n\n \n", styles: [":host{display:flex;align-items:center;flex-grow:1;background-color:#a5b3c9;flex-direction:column}.base-form{padding:10px}.form-field{display:flex}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$
|
|
562
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: LandingComponent, isStandalone: true, selector: "lib-landing", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "\n @if(message(); as message){\n <p>{{message}}</p>\n }\n \n <mat-card style=\"text-align:center;\">\n <form class=\"base-form\" #loginForm=\"ngForm\" (ngSubmit)=\"login()\">\n <mat-card-content>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n [(ngModel)]=\"loginUser.name\"\n name=\"username\"\n required>\n </mat-form-field>\n <mat-form-field class=\"form-field\">\n <input matInput\n placeholder=\"Password\"\n type=\"password\"\n [(ngModel)]=\"loginUser.password\"\n name=\"password\"\n required>\n </mat-form-field>\n </mat-card-content>\n <div *ngIf=\"loginError\" class=\"error\">\n <mat-icon>error</mat-icon><p>{{loginError()}}</p>\n </div>\n <button mat-flat-button\n type=\"submit\"\n [disabled]=\"!loginForm.form.valid\">Log In</button>\n </form>\n </mat-card>\n\n\n \n", styles: [":host{display:flex;align-items:center;flex-grow:1;background-color:#a5b3c9;flex-direction:column}.base-form{padding:10px}.form-field{display:flex}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
358
563
|
}
|
|
359
564
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: LandingComponent, decorators: [{
|
|
360
565
|
type: Component,
|
|
@@ -365,26 +570,38 @@ class DetailView {
|
|
|
365
570
|
item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
|
|
366
571
|
route = inject(ActivatedRoute);
|
|
367
572
|
userService = inject(UserService);
|
|
368
|
-
|
|
369
|
-
constructor(
|
|
370
|
-
this.
|
|
573
|
+
itemService;
|
|
574
|
+
constructor(itemService) {
|
|
575
|
+
this.itemService = itemService;
|
|
371
576
|
}
|
|
372
577
|
onInit() {
|
|
373
578
|
this.getItem();
|
|
374
579
|
}
|
|
375
|
-
onItemAvailable() {
|
|
580
|
+
onItemAvailable(item) {
|
|
581
|
+
this.item.set(item);
|
|
376
582
|
this.userService.loggedInUser.subscribe(user => { if (user) {
|
|
377
|
-
this.onItemAndUserAvailable(user);
|
|
583
|
+
this.onItemAndUserAvailable(item, user);
|
|
378
584
|
} });
|
|
379
585
|
}
|
|
380
|
-
onItemAndUserAvailable(
|
|
586
|
+
onItemAndUserAvailable(_item, _user) { }
|
|
381
587
|
getItem() {
|
|
382
588
|
const id = Number(this.route.snapshot.paramMap.get('id'));
|
|
383
|
-
this.
|
|
384
|
-
this.
|
|
385
|
-
this.onItemAvailable();
|
|
589
|
+
this.itemService.getItem(id).subscribe(item => {
|
|
590
|
+
this.onItemAvailable(item);
|
|
386
591
|
});
|
|
387
592
|
}
|
|
593
|
+
onDelete() {
|
|
594
|
+
const item = this.item();
|
|
595
|
+
if (item) {
|
|
596
|
+
this.itemService.deleteItem(item.id);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
canEdit() {
|
|
600
|
+
return this.itemService.canEdit();
|
|
601
|
+
}
|
|
602
|
+
canDelete() {
|
|
603
|
+
return this.itemService.canDelete();
|
|
604
|
+
}
|
|
388
605
|
}
|
|
389
606
|
|
|
390
607
|
class EditView {
|
|
@@ -396,8 +613,8 @@ class EditView {
|
|
|
396
613
|
_location = inject(Location);
|
|
397
614
|
_userService = inject(UserService);
|
|
398
615
|
_restService;
|
|
399
|
-
constructor(
|
|
400
|
-
this._restService =
|
|
616
|
+
constructor(_restService) {
|
|
617
|
+
this._restService = _restService;
|
|
401
618
|
}
|
|
402
619
|
onInit() {
|
|
403
620
|
this.getItem();
|
|
@@ -494,75 +711,116 @@ class EditView {
|
|
|
494
711
|
}
|
|
495
712
|
|
|
496
713
|
class ListView {
|
|
497
|
-
|
|
714
|
+
count = signal(0, ...(ngDevMode ? [{ debugName: "count" }] : []));
|
|
498
715
|
items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
499
|
-
|
|
716
|
+
next_url = null;
|
|
500
717
|
_route = inject(ActivatedRoute);
|
|
501
718
|
_location = inject(Location);
|
|
502
719
|
_userService = inject(UserService);
|
|
503
|
-
|
|
504
|
-
constructor(
|
|
505
|
-
this.
|
|
506
|
-
}
|
|
507
|
-
onInit() {
|
|
508
|
-
this.getItems();
|
|
720
|
+
_itemService;
|
|
721
|
+
constructor(_itemService) {
|
|
722
|
+
this._itemService = _itemService;
|
|
509
723
|
}
|
|
510
|
-
getItems() {
|
|
724
|
+
getItems(query = new ItemQuery()) {
|
|
511
725
|
if (this.isSelfList()) {
|
|
512
726
|
this._userService.loggedInUser.subscribe(user => {
|
|
513
727
|
if (user) {
|
|
514
|
-
this.
|
|
728
|
+
this.onUserAvailable(user, query);
|
|
515
729
|
}
|
|
516
730
|
});
|
|
517
731
|
}
|
|
518
732
|
else {
|
|
519
|
-
this.
|
|
733
|
+
this._itemService.get(query).subscribe(items => this.onItems(items));
|
|
520
734
|
}
|
|
521
735
|
}
|
|
522
|
-
|
|
523
|
-
this.
|
|
524
|
-
this.
|
|
736
|
+
onItems(paginated) {
|
|
737
|
+
this.count.set(paginated.count);
|
|
738
|
+
this.items.set(paginated.results);
|
|
739
|
+
this.next_url = paginated.next;
|
|
740
|
+
}
|
|
741
|
+
onUserAvailable(user, query) {
|
|
742
|
+
this._itemService.getForUser(user, query).subscribe(items => this.onItems(items));
|
|
525
743
|
}
|
|
526
744
|
isSelfList() {
|
|
527
745
|
const url_segments = this._route.snapshot.url;
|
|
528
|
-
|
|
529
|
-
if (url_segments[1].path == "self") {
|
|
530
|
-
return true;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
return false;
|
|
746
|
+
return (url_segments.length == 2) && (url_segments[1].path == "self");
|
|
534
747
|
}
|
|
535
748
|
goBack() {
|
|
536
749
|
this._location.back();
|
|
537
750
|
}
|
|
538
751
|
}
|
|
539
752
|
|
|
753
|
+
class SelectTableComponent {
|
|
754
|
+
itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
|
|
755
|
+
selected = input([], ...(ngDevMode ? [{ debugName: "selected" }] : []));
|
|
756
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
757
|
+
columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
758
|
+
itemAdded = output();
|
|
759
|
+
itemRemoved = output();
|
|
760
|
+
searchChanged = output();
|
|
761
|
+
columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
|
|
762
|
+
searchControl = new FormControl('');
|
|
763
|
+
table = viewChild(MatTable, ...(ngDevMode ? [{ debugName: "table" }] : []));
|
|
764
|
+
ngOnInit() {
|
|
765
|
+
this.searchControl.valueChanges.subscribe(value => this.searchChanged.emit(value));
|
|
766
|
+
}
|
|
767
|
+
remove(id) {
|
|
768
|
+
this.itemRemoved.emit(id);
|
|
769
|
+
this.table()?.renderRows();
|
|
770
|
+
}
|
|
771
|
+
add() {
|
|
772
|
+
if (this.searchControl.value) {
|
|
773
|
+
this.itemAdded.emit(this.searchControl.value);
|
|
774
|
+
}
|
|
775
|
+
this.table()?.renderRows();
|
|
776
|
+
}
|
|
777
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SelectTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
778
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: SelectTableComponent, isStandalone: true, selector: "lib-select-table", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemAdded: "itemAdded", itemRemoved: "itemRemoved", searchChanged: "searchChanged" }, viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }], ngImport: i0, template: "<div class='select-container'>\n <div>\n <mat-form-field>\n <mat-label>Add {{itemType()}}</mat-label>\n <input \n type=\"text\"\n aria-label=\"Selected item\"\n matInput\n [formControl]=\"searchControl\" \n [matAutocomplete]=\"auto\">\n\n <mat-autocomplete #auto=\"matAutocomplete\">\n @for(item of options(); track item.item.id){\n <mat-option [value]=\"item.title\">{{item.title}}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n\n <button mat-mini-fab type=\"button\" class=\"form_action_button\" (click)=\"add()\">\n <mat-icon>add\n </mat-icon>\n </button>\n </div>\n\n @if(selected().length > 0){\n <table mat-table [dataSource]=\"selected()\" class=\"mat-elevation-z8\">\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"remove\">\n <th mat-header-cell *matHeaderCellDef>Remove\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <button mat-icon-button\n color=\"primary\"\n aria-label=\"Remove an item\"\n (click)=\"remove(element.id)\">\n <mat-icon>remove\n </mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n </table>\n }\n</div>", styles: [".select-container,.table_container{display:flex;text-align:center;justify-content:center;flex-direction:column}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$4.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i6$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i6$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
|
|
779
|
+
}
|
|
780
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SelectTableComponent, decorators: [{
|
|
781
|
+
type: Component,
|
|
782
|
+
args: [{ selector: 'lib-select-table', imports: [MatTableModule,
|
|
783
|
+
MatFormFieldModule,
|
|
784
|
+
MatButtonModule,
|
|
785
|
+
MatSelectModule,
|
|
786
|
+
MatIconModule,
|
|
787
|
+
MatAutocompleteModule,
|
|
788
|
+
ReactiveFormsModule,
|
|
789
|
+
MatInputModule], template: "<div class='select-container'>\n <div>\n <mat-form-field>\n <mat-label>Add {{itemType()}}</mat-label>\n <input \n type=\"text\"\n aria-label=\"Selected item\"\n matInput\n [formControl]=\"searchControl\" \n [matAutocomplete]=\"auto\">\n\n <mat-autocomplete #auto=\"matAutocomplete\">\n @for(item of options(); track item.item.id){\n <mat-option [value]=\"item.title\">{{item.title}}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n\n <button mat-mini-fab type=\"button\" class=\"form_action_button\" (click)=\"add()\">\n <mat-icon>add\n </mat-icon>\n </button>\n </div>\n\n @if(selected().length > 0){\n <table mat-table [dataSource]=\"selected()\" class=\"mat-elevation-z8\">\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"remove\">\n <th mat-header-cell *matHeaderCellDef>Remove\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <button mat-icon-button\n color=\"primary\"\n aria-label=\"Remove an item\"\n (click)=\"remove(element.id)\">\n <mat-icon>remove\n </mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\">\n </tr>\n <tr mat-row *matRowDef=\"let row; columns: columnNames();\">\n </tr>\n </table>\n }\n</div>", styles: [".select-container,.table_container{display:flex;text-align:center;justify-content:center;flex-direction:column}.form_action_button{padding:5px;margin:5px}\n"] }]
|
|
790
|
+
}] });
|
|
791
|
+
|
|
540
792
|
class BackButtonComponent {
|
|
541
793
|
location = inject(Location);
|
|
542
794
|
goBack() {
|
|
543
795
|
this.location.back();
|
|
544
796
|
}
|
|
545
797
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: BackButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
546
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: BackButtonComponent, isStandalone: true, selector: "lib-back-button", ngImport: i0, template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [".padded-button{
|
|
798
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: BackButtonComponent, isStandalone: true, selector: "lib-back-button", ngImport: i0, template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [".padded-button{margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
|
|
547
799
|
}
|
|
548
800
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: BackButtonComponent, decorators: [{
|
|
549
801
|
type: Component,
|
|
550
|
-
args: [{ selector: 'lib-back-button', imports: [MatIconModule, MatButtonModule], template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [".padded-button{
|
|
802
|
+
args: [{ selector: 'lib-back-button', imports: [MatIconModule, MatButtonModule], template: "<a mat-icon-button class=\"padded-button\"\n (click)=\"goBack()\"\n (keydown)=\"goBack()\"\n tabindex=\"0\"\n role=\"button\">\n<mat-icon>arrow_back</mat-icon>\n</a>\n\n", styles: [".padded-button{margin:5px}\n"] }]
|
|
551
803
|
}] });
|
|
552
804
|
|
|
553
805
|
class DetailHeaderComponent {
|
|
554
806
|
id = input(0, ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
555
807
|
text = input("", ...(ngDevMode ? [{ debugName: "text" }] : []));
|
|
556
808
|
route = input("", ...(ngDevMode ? [{ debugName: "route" }] : []));
|
|
809
|
+
canEdit = input(false, ...(ngDevMode ? [{ debugName: "canEdit" }] : []));
|
|
810
|
+
canDelete = input(false, ...(ngDevMode ? [{ debugName: "canDelete" }] : []));
|
|
811
|
+
deleteClicked = output();
|
|
557
812
|
fullRoute = computed(() => "/" + this.route() + "s/edit/", ...(ngDevMode ? [{ debugName: "fullRoute" }] : []));
|
|
813
|
+
deleteClick() {
|
|
814
|
+
this.deleteClicked.emit();
|
|
815
|
+
}
|
|
558
816
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
559
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
817
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: DetailHeaderComponent, isStandalone: true, selector: "lib-detail-header", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, route: { classPropertyName: "route", publicName: "route", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, canDelete: { classPropertyName: "canDelete", publicName: "canDelete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteClicked: "deleteClicked" }, ngImport: i0, template: "<div class=\"container\">\n\n <h1 class=\"header\">{{text()}}</h1>\n\n <div class=\"controls\">\n @if(canEdit()){\n <a mat-mini-fab class=\"control-button\" matTooltip=\"Edit the item\" title=\"Click to edit this item\" aria-label=\"Click to edit this item\"\n [routerLink]=\"[fullRoute(), id()]\">\n <mat-icon>edit</mat-icon>\n </a>\n }\n\n @if(canDelete()){\n <button mat-mini-fab class=\"control-button\" (click)=\"deleteClick()\" matTooltip=\"Delete the item\" title=\"Click to delete this item\"\n aria-label=\"Click to delete this item\">\n <mat-icon>delete</mat-icon></button>\n }\n </div>\n\n</div>", styles: [".container{width:100%;max-width:500px;padding:5px}.header{width:100%;padding:5px;margin:5px}.controls{display:flex;flex-direction:row;align-content:center;justify-content:center}.control-button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
|
|
560
818
|
}
|
|
561
819
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: DetailHeaderComponent, decorators: [{
|
|
562
820
|
type: Component,
|
|
563
821
|
args: [{ selector: 'lib-detail-header', imports: [RouterModule,
|
|
564
822
|
MatButtonModule,
|
|
565
|
-
MatIconModule], template: "<div class=\"container\">\n
|
|
823
|
+
MatIconModule, MatTooltipModule], template: "<div class=\"container\">\n\n <h1 class=\"header\">{{text()}}</h1>\n\n <div class=\"controls\">\n @if(canEdit()){\n <a mat-mini-fab class=\"control-button\" matTooltip=\"Edit the item\" title=\"Click to edit this item\" aria-label=\"Click to edit this item\"\n [routerLink]=\"[fullRoute(), id()]\">\n <mat-icon>edit</mat-icon>\n </a>\n }\n\n @if(canDelete()){\n <button mat-mini-fab class=\"control-button\" (click)=\"deleteClick()\" matTooltip=\"Delete the item\" title=\"Click to delete this item\"\n aria-label=\"Click to delete this item\">\n <mat-icon>delete</mat-icon></button>\n }\n </div>\n\n</div>", styles: [".container{width:100%;max-width:500px;padding:5px}.header{width:100%;padding:5px;margin:5px}.controls{display:flex;flex-direction:row;align-content:center;justify-content:center}.control-button{padding:5px;margin:5px}\n"] }]
|
|
566
824
|
}] });
|
|
567
825
|
|
|
568
826
|
class FileUploadComponent {
|
|
@@ -597,7 +855,7 @@ class FileUploadComponent {
|
|
|
597
855
|
};
|
|
598
856
|
}
|
|
599
857
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FileUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
600
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FileUploadComponent, isStandalone: true, selector: "lib-file-upload", inputs: { files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { previewLoaded: "previewLoaded", fileUploaded: "fileUploaded" }, ngImport: i0, template: "<div class=\"container\">\n @for( file of files(); track file.name)\n {\n @if (file.local)\n {\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.local}}\" style=\"height:120px;\">\n </div> \n }\n @else\n {\n @if (file.remote){\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.remote}}\" style=\"height:120px;\">\n </div>\n }\n @else {\n <div>\n <span>Upload a {{file.display_name}}</span>\n </div> \n }\n \n }\n\n <div class=\"button-row\">\n <button mat-mini-fab (click)=\"fileInput.click()\">\n <mat-icon>attachment</mat-icon>\n </button>\n <input hidden type=\"file\" #fileInput (change)=\"onFileUpload(file.name, $event)\"/>\n </div> \n } \n</div>\n", styles: [".container{padding:10px;display:flex;justify-content:center;text-align:center;flex-direction:column;max-width:300px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3
|
|
858
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: FileUploadComponent, isStandalone: true, selector: "lib-file-upload", inputs: { files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { previewLoaded: "previewLoaded", fileUploaded: "fileUploaded" }, ngImport: i0, template: "<div class=\"container\">\n @for( file of files(); track file.name)\n {\n @if (file.local)\n {\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.local}}\" style=\"height:120px;\">\n </div> \n }\n @else\n {\n @if (file.remote){\n <div class=\"image_holder\">\n <p>Update {{file.display_name}}</p>\n <img alt=\"{{file.display_name}}\" src=\"{{file.remote}}\" style=\"height:120px;\">\n </div>\n }\n @else {\n <div>\n <span>Upload a {{file.display_name}}</span>\n </div> \n }\n \n }\n\n <div class=\"button-row\">\n <button mat-mini-fab (click)=\"fileInput.click()\">\n <mat-icon>attachment</mat-icon>\n </button>\n <input hidden type=\"file\" #fileInput (change)=\"onFileUpload(file.name, $event)\"/>\n </div> \n } \n</div>\n", styles: [".container{padding:10px;display:flex;justify-content:center;text-align:center;flex-direction:column;max-width:300px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }] });
|
|
601
859
|
}
|
|
602
860
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: FileUploadComponent, decorators: [{
|
|
603
861
|
type: Component,
|
|
@@ -625,13 +883,13 @@ class UserDetailComponent extends DetailView {
|
|
|
625
883
|
this.onInit();
|
|
626
884
|
}
|
|
627
885
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
628
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserDetailComponent, isStandalone: true, selector: "lib-user-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"typename\"></lib-detail-header>\n\n @if(item.profile_url){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.url}}{{item.profile_url}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route"] }] });
|
|
886
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserDetailComponent, isStandalone: true, selector: "lib-user-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"typename\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete\"></lib-detail-header>\n\n @if(item.profile_url){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.url}}{{item.profile_url}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }] });
|
|
629
887
|
}
|
|
630
888
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserDetailComponent, decorators: [{
|
|
631
889
|
type: Component,
|
|
632
890
|
args: [{ selector: 'lib-user-detail', imports: [NgIf,
|
|
633
891
|
BackButtonComponent,
|
|
634
|
-
DetailHeaderComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"typename\"></lib-detail-header>\n\n @if(item.profile_url){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.url}}{{item.profile_url}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
|
|
892
|
+
DetailHeaderComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.username\"\n [id]=\"item.id\"\n [route]=\"typename\"\n [canEdit]=\"canEdit()\"\n [canDelete]=\"canDelete()\"\n (onDelete)=\"onDelete\"></lib-detail-header>\n\n @if(item.profile_url){\n <div class=\"image-holder\">\n <img alt=\"User Profile Image\" src=\"{{item.url}}{{item.profile_url}}\" style=\"height:120px;\">\n </div> \n }\n \n <div class=\"item-field\">\n <span><b>Email: </b></span>\n {{item.email}}\n </div>\n \n <div class=\"item-field\">\n <span><b>First Name: </b></span>\n {{item.first_name}}\n </div>\n \n <div class=\"item-field\">\n <span><b>Last Name: </b></span>\n {{item.last_name}}\n </div>\n \n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
|
|
635
893
|
}], ctorParameters: () => [] });
|
|
636
894
|
|
|
637
895
|
class UserEditComponent extends EditView {
|
|
@@ -706,7 +964,7 @@ class UserEditComponent extends EditView {
|
|
|
706
964
|
} ; });
|
|
707
965
|
}
|
|
708
966
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
709
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserEditComponent, isStandalone: true, selector: "lib-user-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading()}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Username</mat-label>\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n formControlName=\"username\"\n name=\"username\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label>Email</mat-label>\n <input matInput\n placeholder=\"Email\"\n type=\"text\"\n formControlName=\"email\"\n name=\"email\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>First Name</mat-label>\n <input matInput\n placeholder=\"First Name\"\n type=\"text\"\n formControlName=\"first_name\"\n name=\"first_name\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label>Last Name</mat-label>\n <input matInput\n placeholder=\"Last Name\"\n type=\"text\"\n formControlName=\"last_name\"\n name=\"last_name\">\n </mat-form-field>\n\n <lib-file-upload [files]=\"files()\"\n (previewLoaded)=\"onPreviewLoaded($event)\"\n (fileUploaded)=\"onFileUploaded($event)\"></lib-file-upload>\n \n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div>\n \n </form>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.item_view{display:flex;justify-content:left;align-items:left;flex-direction:column}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$
|
|
967
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserEditComponent, isStandalone: true, selector: "lib-user-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading()}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Username</mat-label>\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n formControlName=\"username\"\n name=\"username\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label>Email</mat-label>\n <input matInput\n placeholder=\"Email\"\n type=\"text\"\n formControlName=\"email\"\n name=\"email\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>First Name</mat-label>\n <input matInput\n placeholder=\"First Name\"\n type=\"text\"\n formControlName=\"first_name\"\n name=\"first_name\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label>Last Name</mat-label>\n <input matInput\n placeholder=\"Last Name\"\n type=\"text\"\n formControlName=\"last_name\"\n name=\"last_name\">\n </mat-form-field>\n\n <lib-file-upload [files]=\"files()\"\n (previewLoaded)=\"onPreviewLoaded($event)\"\n (fileUploaded)=\"onFileUploaded($event)\"></lib-file-upload>\n \n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div>\n \n </form>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.item_view{display:flex;justify-content:left;align-items:left;flex-direction:column}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FileUploadComponent, selector: "lib-file-upload", inputs: ["files"], outputs: ["previewLoaded", "fileUploaded"] }] });
|
|
710
968
|
}
|
|
711
969
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserEditComponent, decorators: [{
|
|
712
970
|
type: Component,
|
|
@@ -721,51 +979,305 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
721
979
|
], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-edit-container\">\n\n <h1 class=\"item-edit-header\">{{heading()}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label>Username</mat-label>\n <input matInput\n placeholder=\"Username\"\n type=\"text\"\n formControlName=\"username\"\n name=\"username\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label>Email</mat-label>\n <input matInput\n placeholder=\"Email\"\n type=\"text\"\n formControlName=\"email\"\n name=\"email\">\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label>First Name</mat-label>\n <input matInput\n placeholder=\"First Name\"\n type=\"text\"\n formControlName=\"first_name\"\n name=\"first_name\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label>Last Name</mat-label>\n <input matInput\n placeholder=\"Last Name\"\n type=\"text\"\n formControlName=\"last_name\"\n name=\"last_name\">\n </mat-form-field>\n\n <lib-file-upload [files]=\"files()\"\n (previewLoaded)=\"onPreviewLoaded($event)\"\n (fileUploaded)=\"onFileUploaded($event)\"></lib-file-upload>\n \n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.valid\">\n <mat-icon>save</mat-icon></button>\n \n <button mat-fab\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon></button>\n </div>\n \n </form>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.item_view{display:flex;justify-content:left;align-items:left;flex-direction:column}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"] }]
|
|
722
980
|
}], ctorParameters: () => [] });
|
|
723
981
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
}
|
|
982
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
983
|
+
class ListTableViewComponent {
|
|
984
|
+
itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
|
|
985
|
+
columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
986
|
+
dataSource = input(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : []));
|
|
987
|
+
searchFilter = input("", ...(ngDevMode ? [{ debugName: "searchFilter" }] : []));
|
|
988
|
+
pageSizeOptions = [20, 50, 100];
|
|
989
|
+
initialPageSize = 20;
|
|
990
|
+
columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
|
|
991
|
+
sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
|
|
992
|
+
paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : []));
|
|
728
993
|
ngOnInit() {
|
|
729
|
-
this.
|
|
994
|
+
const data_source = this.dataSource();
|
|
995
|
+
if (data_source) {
|
|
996
|
+
data_source.fetch(new ItemQuery({ page_size: this.initialPageSize }));
|
|
997
|
+
}
|
|
730
998
|
}
|
|
731
|
-
|
|
732
|
-
|
|
999
|
+
ngAfterViewInit() {
|
|
1000
|
+
const paginator = this.paginator();
|
|
1001
|
+
const sort = this.sort();
|
|
1002
|
+
if (!paginator || !sort) {
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
sort.sortChange.subscribe(() => this.reset());
|
|
1006
|
+
merge(sort.sortChange, paginator.page)
|
|
1007
|
+
.pipe(tap(() => this.fetch()))
|
|
1008
|
+
.subscribe();
|
|
1009
|
+
}
|
|
1010
|
+
reset() {
|
|
1011
|
+
const paginator = this.paginator();
|
|
1012
|
+
if (!paginator) {
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
paginator.pageIndex = 0;
|
|
1016
|
+
}
|
|
1017
|
+
fetch() {
|
|
1018
|
+
const paginator = this.paginator();
|
|
1019
|
+
const sort = this.sort();
|
|
1020
|
+
const data_source = this.dataSource();
|
|
1021
|
+
if (!paginator || !sort || !data_source) {
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
data_source.fetch(new ItemQuery({
|
|
1025
|
+
page: paginator.pageIndex + 1,
|
|
1026
|
+
page_size: paginator.pageSize,
|
|
1027
|
+
sort_order: sort.direction,
|
|
1028
|
+
sort_field: sort.active,
|
|
1029
|
+
filter: this.searchFilter()
|
|
1030
|
+
}));
|
|
1031
|
+
}
|
|
1032
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1033
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: ListTableViewComponent, isStandalone: true, selector: "lib-list-table-view", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, searchFilter: { classPropertyName: "searchFilter", publicName: "searchFilter", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], ngImport: i0, template: "@if (dataSource(); as dataSource) {\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n matSortActive=\"name\"\n matSortDisableClear\n matSortDirection=\"desc\"\n class=\"mat-elevation-z8\"\n >\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: columnNames()\"\n [routerLink]=\"['/' + itemType() + '/detail/', row.id]\"\n [routerLinkActive]=\"['is-active']\"\n ></tr>\n </table>\n\n <mat-paginator\n [length]=\"dataSource.length()\"\n [pageSize]=\"20\"\n [pageSizeOptions]=\"pageSizeOptions\"\n aria-label=\"Select page\"\n >\n </mat-paginator>\n}\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$4.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i3$3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3$3.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
|
|
733
1034
|
}
|
|
734
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type:
|
|
1035
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListTableViewComponent, decorators: [{
|
|
735
1036
|
type: Component,
|
|
736
|
-
args: [{ selector: 'lib-
|
|
1037
|
+
args: [{ selector: 'lib-list-table-view', imports: [MatTableModule,
|
|
1038
|
+
ReactiveFormsModule,
|
|
737
1039
|
MatButtonModule,
|
|
1040
|
+
MatInputModule,
|
|
738
1041
|
MatIconModule,
|
|
739
|
-
|
|
740
|
-
|
|
1042
|
+
MatPaginatorModule,
|
|
1043
|
+
MatSortModule,
|
|
1044
|
+
RouterModule
|
|
1045
|
+
], template: "@if (dataSource(); as dataSource) {\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n matSortActive=\"name\"\n matSortDisableClear\n matSortDirection=\"desc\"\n class=\"mat-elevation-z8\"\n >\n @for (column of columns(); track column.name) {\n <ng-container matColumnDef=\"{{ column.name }}\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element[column.name] }}</td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames()\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: columnNames()\"\n [routerLink]=\"['/' + itemType() + '/detail/', row.id]\"\n [routerLinkActive]=\"['is-active']\"\n ></tr>\n </table>\n\n <mat-paginator\n [length]=\"dataSource.length()\"\n [pageSize]=\"20\"\n [pageSizeOptions]=\"pageSizeOptions\"\n aria-label=\"Select page\"\n >\n </mat-paginator>\n}\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"] }]
|
|
1046
|
+
}] });
|
|
741
1047
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
this.itemRemoved.emit(id);
|
|
752
|
-
this.table()?.renderRows();
|
|
1048
|
+
// Datasource needs any
|
|
1049
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1050
|
+
class ListScrollViewComponent {
|
|
1051
|
+
searchTerm = input("", ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
1052
|
+
pageSize = input(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
|
|
1053
|
+
dataSource = input(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : []));
|
|
1054
|
+
listItemTemplate = input(null, ...(ngDevMode ? [{ debugName: "listItemTemplate" }] : []));
|
|
1055
|
+
ngOnInit() {
|
|
1056
|
+
this.reset();
|
|
753
1057
|
}
|
|
754
|
-
|
|
755
|
-
this.
|
|
756
|
-
|
|
1058
|
+
reset() {
|
|
1059
|
+
const data_source = this.dataSource();
|
|
1060
|
+
if (!data_source) {
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
// sort_order: this.sort!.direction,
|
|
1064
|
+
// sort_field: this.sort!.active,
|
|
1065
|
+
data_source.reset(this.searchTerm(), this.pageSize());
|
|
757
1066
|
}
|
|
758
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type:
|
|
759
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
1067
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1068
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.1", type: ListScrollViewComponent, isStandalone: true, selector: "lib-list-scroll-view", inputs: { searchTerm: { classPropertyName: "searchTerm", publicName: "searchTerm", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, listItemTemplate: { classPropertyName: "listItemTemplate", publicName: "listItemTemplate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-nav-list>\n <cdk-virtual-scroll-viewport\n itemSize=\"150\"\n class=\"scrollable-list\"\n style=\"height: 600px; width: 500px\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource()\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item }\"\n >\n </ng-container>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</mat-nav-list>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2$4.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2$4.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2$4.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
|
|
760
1069
|
}
|
|
761
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type:
|
|
1070
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListScrollViewComponent, decorators: [{
|
|
762
1071
|
type: Component,
|
|
763
|
-
args: [{ selector: 'lib-
|
|
764
|
-
|
|
1072
|
+
args: [{ selector: 'lib-list-scroll-view', imports: [MatListModule,
|
|
1073
|
+
NgTemplateOutlet,
|
|
1074
|
+
ScrollingModule], template: "<mat-nav-list>\n <cdk-virtual-scroll-viewport\n itemSize=\"150\"\n class=\"scrollable-list\"\n style=\"height: 600px; width: 500px\"\n >\n <ng-container *cdkVirtualFor=\"let item of dataSource()\">\n <ng-container\n *ngTemplateOutlet=\"listItemTemplate(); context: { item: item }\"\n >\n </ng-container>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</mat-nav-list>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"] }]
|
|
1075
|
+
}] });
|
|
1076
|
+
|
|
1077
|
+
class SearchBarComponent {
|
|
1078
|
+
itemType = input("", ...(ngDevMode ? [{ debugName: "itemType" }] : []));
|
|
1079
|
+
sortFields = input([], ...(ngDevMode ? [{ debugName: "sortFields" }] : []));
|
|
1080
|
+
sortAscending = signal(true, ...(ngDevMode ? [{ debugName: "sortAscending" }] : []));
|
|
1081
|
+
searchChanged = output();
|
|
1082
|
+
searchFilter = new FormControl();
|
|
1083
|
+
ngAfterViewInit() {
|
|
1084
|
+
this.searchFilter.valueChanges.pipe(debounceTime(150), distinctUntilChanged(), tap(() => {
|
|
1085
|
+
this.searchEntered();
|
|
1086
|
+
})).subscribe();
|
|
1087
|
+
}
|
|
1088
|
+
clearSearch() {
|
|
1089
|
+
this.searchFilter.setValue("");
|
|
1090
|
+
}
|
|
1091
|
+
searchEntered() {
|
|
1092
|
+
this.searchChanged.emit(this.searchFilter.value);
|
|
1093
|
+
}
|
|
1094
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1095
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: SearchBarComponent, isStandalone: true, selector: "lib-search-bar", inputs: { itemType: { classPropertyName: "itemType", publicName: "itemType", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchChanged: "searchChanged" }, ngImport: i0, template: "<div class=\"container\">\n <mat-form-field class=\"search\" style=\"margin: 10px;\">\n <mat-label>Search</mat-label>\n <input matInput [formControl]=\"searchFilter\" placeholder=\"Search {{ itemType() | titlecase }}\" />\n\n @if(searchFilter.value){\n <button matSuffix mat-icon-button aria-label=\"Cancel\" (click)=\"clearSearch()\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n @else(){\n <button matSuffix mat-icon-button aria-label=\"Search\">\n <mat-icon>search</mat-icon>\n </button>\n }\n </mat-form-field>\n\n @if(sortFields().length > 0){\n <mat-form-field style=\"margin: 10px\">\n <mat-label>Sort By</mat-label>\n <mat-select>\n @for(field of sortFields(); track field)\n {\n <mat-option>{{field}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <button mat-icon-button aria-label=\"Sort Order\" matTooltip=\"Toggle sort order\">\n <mat-icon>sort</mat-icon>\n </button>\n }\n</div>", styles: [".container{width:100%;display:flex;flex-wrap:wrap;flex-direction:row;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
|
|
1096
|
+
}
|
|
1097
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: SearchBarComponent, decorators: [{
|
|
1098
|
+
type: Component,
|
|
1099
|
+
args: [{ selector: 'lib-search-bar', imports: [ReactiveFormsModule,
|
|
1100
|
+
MatInputModule,
|
|
1101
|
+
MatTooltipModule,
|
|
765
1102
|
MatButtonModule,
|
|
766
1103
|
MatSelectModule,
|
|
767
1104
|
MatIconModule,
|
|
768
|
-
|
|
1105
|
+
TitleCasePipe], template: "<div class=\"container\">\n <mat-form-field class=\"search\" style=\"margin: 10px;\">\n <mat-label>Search</mat-label>\n <input matInput [formControl]=\"searchFilter\" placeholder=\"Search {{ itemType() | titlecase }}\" />\n\n @if(searchFilter.value){\n <button matSuffix mat-icon-button aria-label=\"Cancel\" (click)=\"clearSearch()\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n @else(){\n <button matSuffix mat-icon-button aria-label=\"Search\">\n <mat-icon>search</mat-icon>\n </button>\n }\n </mat-form-field>\n\n @if(sortFields().length > 0){\n <mat-form-field style=\"margin: 10px\">\n <mat-label>Sort By</mat-label>\n <mat-select>\n @for(field of sortFields(); track field)\n {\n <mat-option>{{field}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <button mat-icon-button aria-label=\"Sort Order\" matTooltip=\"Toggle sort order\">\n <mat-icon>sort</mat-icon>\n </button>\n }\n</div>", styles: [".container{width:100%;display:flex;flex-wrap:wrap;flex-direction:row;align-items:center;justify-content:center}\n"] }]
|
|
1106
|
+
}] });
|
|
1107
|
+
|
|
1108
|
+
class ListDataSource extends DataSource {
|
|
1109
|
+
length = signal(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
|
|
1110
|
+
loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1111
|
+
searchTerm = signal("", ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
1112
|
+
pageSize = signal(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
|
|
1113
|
+
consumerType;
|
|
1114
|
+
items = new BehaviorSubject([]);
|
|
1115
|
+
itemService;
|
|
1116
|
+
subscription = new Subscription();
|
|
1117
|
+
fetchedPages = new Set();
|
|
1118
|
+
constructor(itemService, consumerType = "table") {
|
|
1119
|
+
super();
|
|
1120
|
+
this.itemService = itemService;
|
|
1121
|
+
this.consumerType = consumerType;
|
|
1122
|
+
}
|
|
1123
|
+
connect(collectionViewer) {
|
|
1124
|
+
if (!this.hasTableConsumer()) {
|
|
1125
|
+
this.subscription.add(collectionViewer.viewChange.subscribe((range) => this.onRange(range)));
|
|
1126
|
+
}
|
|
1127
|
+
return this.items.asObservable();
|
|
1128
|
+
}
|
|
1129
|
+
hasTableConsumer() {
|
|
1130
|
+
return this.consumerType === "table";
|
|
1131
|
+
}
|
|
1132
|
+
onRange(range) {
|
|
1133
|
+
const start_page = Math.floor(range.start / this.pageSize());
|
|
1134
|
+
const end_page = Math.floor(range.end / this.pageSize());
|
|
1135
|
+
for (let idx = start_page; idx <= end_page; idx++) {
|
|
1136
|
+
this.fetchPage(idx);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
reset(searchTerm = "", pageSize = 20) {
|
|
1140
|
+
this.fetchedPages = new Set();
|
|
1141
|
+
this.length.set(0);
|
|
1142
|
+
this.searchTerm.set(searchTerm);
|
|
1143
|
+
this.pageSize.set(pageSize);
|
|
1144
|
+
this.loading.set(true);
|
|
1145
|
+
this.items.next([]);
|
|
1146
|
+
this.fetchPage(0);
|
|
1147
|
+
}
|
|
1148
|
+
fetchPage(idx) {
|
|
1149
|
+
if (this.fetchedPages.has(idx)) {
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
this.fetchedPages.add(idx);
|
|
1153
|
+
this.fetch(new ItemQuery({ page: idx + 1,
|
|
1154
|
+
page_size: this.pageSize(),
|
|
1155
|
+
filter: this.searchTerm() }));
|
|
1156
|
+
}
|
|
1157
|
+
fetch(query) {
|
|
1158
|
+
this.loading.set(true);
|
|
1159
|
+
this.itemService.get(query).pipe(catchError(() => of(new Paginated())), finalize(() => this.loading.set(false))).subscribe(response => this.onResponse(response));
|
|
1160
|
+
}
|
|
1161
|
+
onResponse(response) {
|
|
1162
|
+
this.length.set(response.count);
|
|
1163
|
+
if (this.hasTableConsumer()) {
|
|
1164
|
+
this.items.next(response.results);
|
|
1165
|
+
}
|
|
1166
|
+
else {
|
|
1167
|
+
this.items.next([...this.items.value, ...response.results]);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
disconnect() {
|
|
1171
|
+
this.items.complete();
|
|
1172
|
+
if (this.subscription) {
|
|
1173
|
+
this.subscription.unsubscribe();
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
class ListViewComponent {
|
|
1179
|
+
viewType = input("table", ...(ngDevMode ? [{ debugName: "viewType" }] : []));
|
|
1180
|
+
itemService = input(...(ngDevMode ? [undefined, { debugName: "itemService" }] : []));
|
|
1181
|
+
itemDetailTemplate = input(null, ...(ngDevMode ? [{ debugName: "itemDetailTemplate" }] : []));
|
|
1182
|
+
columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
1183
|
+
sortFields = input([], ...(ngDevMode ? [{ debugName: "sortFields" }] : []));
|
|
1184
|
+
selectedViewType = signal("table", ...(ngDevMode ? [{ debugName: "selectedViewType" }] : []));
|
|
1185
|
+
pageSize = 20;
|
|
1186
|
+
pageSizeOptions = [20, 50, 100];
|
|
1187
|
+
dataSource = undefined;
|
|
1188
|
+
sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
|
|
1189
|
+
columnNames = computed(() => this.columns().map(c => c.name), ...(ngDevMode ? [{ debugName: "columnNames" }] : []));
|
|
1190
|
+
searchTerm = "";
|
|
1191
|
+
ngOnInit() {
|
|
1192
|
+
this.selectedViewType.set(this.viewType());
|
|
1193
|
+
this.resetDataSource();
|
|
1194
|
+
}
|
|
1195
|
+
ngAfterViewInit() {
|
|
1196
|
+
const sort = this.sort();
|
|
1197
|
+
if (sort) {
|
|
1198
|
+
sort.sortChange.pipe(tap(() => this.reset())).subscribe();
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
onSearchChange(value) {
|
|
1202
|
+
this.searchTerm = value;
|
|
1203
|
+
this.reset();
|
|
1204
|
+
}
|
|
1205
|
+
canCreate() {
|
|
1206
|
+
const item_service = this.itemService();
|
|
1207
|
+
if (item_service) {
|
|
1208
|
+
return item_service.canCreate();
|
|
1209
|
+
}
|
|
1210
|
+
return false;
|
|
1211
|
+
}
|
|
1212
|
+
itemType() {
|
|
1213
|
+
const item_service = this.itemService();
|
|
1214
|
+
if (item_service) {
|
|
1215
|
+
return item_service.itemType;
|
|
1216
|
+
}
|
|
1217
|
+
return "";
|
|
1218
|
+
}
|
|
1219
|
+
isTableView() {
|
|
1220
|
+
return this.selectedViewType() === "table";
|
|
1221
|
+
}
|
|
1222
|
+
resetDataSource() {
|
|
1223
|
+
const item_service = this.itemService();
|
|
1224
|
+
if (item_service) {
|
|
1225
|
+
this.dataSource = new ListDataSource(item_service, this.selectedViewType());
|
|
1226
|
+
}
|
|
1227
|
+
this.reset();
|
|
1228
|
+
}
|
|
1229
|
+
reset() {
|
|
1230
|
+
if (this.dataSource) {
|
|
1231
|
+
this.dataSource.reset(this.searchTerm, this.pageSize);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
viewChanged(event) {
|
|
1235
|
+
this.selectedViewType.set(event.value);
|
|
1236
|
+
console.log(this.selectedViewType());
|
|
1237
|
+
this.resetDataSource();
|
|
1238
|
+
}
|
|
1239
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1240
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: ListViewComponent, isStandalone: true, selector: "lib-list-view", inputs: { viewType: { classPropertyName: "viewType", publicName: "viewType", isSignal: true, isRequired: false, transformFunction: null }, itemService: { classPropertyName: "itemService", publicName: "itemService", isSignal: true, isRequired: false, transformFunction: null }, itemDetailTemplate: { classPropertyName: "itemDetailTemplate", publicName: "itemDetailTemplate", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, sortFields: { classPropertyName: "sortFields", publicName: "sortFields", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"container\">\n <div class=\"header\">\n <h1 class=\"title\">{{ itemType() | titlecase }}</h1>\n\n @if (canCreate()) {\n <div class=\"button-container\">\n <a mat-fab class=\"padded-button\" \n aria-label=\"Add new item\" \n matTooltip=\"Add new item\" [routerLink]=\"['create']\">\n <mat-icon>add</mat-icon></a>\n </div>\n }\n </div>\n\n <div class=\"controls\">\n <lib-search-bar \n [itemType]=\"itemType()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"\n ></lib-search-bar>\n\n @if(itemDetailTemplate()){\n <div style=\"margin: 10px\">\n <mat-button-toggle-group name=\"viewType\" aria-label=\"View Type\" [value]=\"selectedViewType()\"\n (change)=\"viewChanged($event)\">\n <mat-button-toggle value=\"table\" matTooltip=\"Show as table\">\n <mat-icon>table_view</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"scroll\" matTooltip=\"Show as list\">\n <mat-icon>list</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n }\n </div>\n\n @if (dataSource && dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n }\n @else {\n <lib-list-scroll-view [listItemTemplate]=\"itemDetailTemplate()\" [dataSource]=\"dataSource\"></lib-list-scroll-view>\n }\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.header{display:flex;flex-direction:row;align-items:center;justify-content:center}.title{text-align:center;padding:10px}.controls{display:flex;align-items:center;justify-content:center;flex-wrap:wrap}\n"], dependencies: [{ kind: "component", type: ListTableViewComponent, selector: "lib-list-table-view", inputs: ["itemType", "columns", "dataSource", "searchFilter"] }, { kind: "component", type: ListScrollViewComponent, selector: "lib-list-scroll-view", inputs: ["searchTerm", "pageSize", "dataSource", "listItemTemplate"] }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i1$5.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i1$5.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2$5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: SearchBarComponent, selector: "lib-search-bar", inputs: ["itemType", "sortFields"], outputs: ["searchChanged"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
|
|
1241
|
+
}
|
|
1242
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: ListViewComponent, decorators: [{
|
|
1243
|
+
type: Component,
|
|
1244
|
+
args: [{ selector: 'lib-list-view', imports: [ListTableViewComponent,
|
|
1245
|
+
ListScrollViewComponent,
|
|
1246
|
+
BackButtonComponent,
|
|
1247
|
+
MatFormFieldModule,
|
|
1248
|
+
MatButtonToggleModule,
|
|
1249
|
+
MatProgressSpinnerModule,
|
|
1250
|
+
MatIconModule,
|
|
1251
|
+
ReactiveFormsModule,
|
|
1252
|
+
RouterModule,
|
|
1253
|
+
TitleCasePipe,
|
|
1254
|
+
MatInputModule,
|
|
1255
|
+
MatTooltipModule,
|
|
1256
|
+
MatButtonModule,
|
|
1257
|
+
SearchBarComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"container\">\n <div class=\"header\">\n <h1 class=\"title\">{{ itemType() | titlecase }}</h1>\n\n @if (canCreate()) {\n <div class=\"button-container\">\n <a mat-fab class=\"padded-button\" \n aria-label=\"Add new item\" \n matTooltip=\"Add new item\" [routerLink]=\"['create']\">\n <mat-icon>add</mat-icon></a>\n </div>\n }\n </div>\n\n <div class=\"controls\">\n <lib-search-bar \n [itemType]=\"itemType()\"\n [sortFields]=\"sortFields()\"\n (searchChanged)=\"onSearchChange($event)\"\n ></lib-search-bar>\n\n @if(itemDetailTemplate()){\n <div style=\"margin: 10px\">\n <mat-button-toggle-group name=\"viewType\" aria-label=\"View Type\" [value]=\"selectedViewType()\"\n (change)=\"viewChanged($event)\">\n <mat-button-toggle value=\"table\" matTooltip=\"Show as table\">\n <mat-icon>table_view</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"scroll\" matTooltip=\"Show as list\">\n <mat-icon>list</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n }\n </div>\n\n @if (dataSource && dataSource.loading()) {\n <div class=\"spinner-container\">\n <mat-spinner></mat-spinner>\n </div>\n }\n\n @if(isTableView()) {\n <lib-list-table-view [itemType]=\"itemType()\" [columns]=\"columns()\" [dataSource]=\"dataSource\">\n </lib-list-table-view>\n }\n @else {\n <lib-list-scroll-view [listItemTemplate]=\"itemDetailTemplate()\" [dataSource]=\"dataSource\"></lib-list-scroll-view>\n }\n</div>", styles: [":host{flex-grow:1}.container{display:flex;padding:10px;flex-direction:column;justify-content:center;text-align:center;align-items:center}.header{display:flex;flex-direction:row;align-items:center;justify-content:center}.title{text-align:center;padding:10px}.controls{display:flex;align-items:center;justify-content:center;flex-wrap:wrap}\n"] }]
|
|
1258
|
+
}] });
|
|
1259
|
+
|
|
1260
|
+
class UserListDetailComponent {
|
|
1261
|
+
item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
|
|
1262
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1263
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: UserListDetailComponent, isStandalone: true, selector: "lib-user-list-detail", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-card mat-list-item class=\"item-card\">\n @if(item(); as item){\n <mat-card-header>\n <mat-card-title-group style=\"padding: 5px\">\n <mat-card-title\n >{{ item.first_name }} {{ item.last_name }}</mat-card-title\n >\n <mat-card-subtitle>{{ item.username }}</mat-card-subtitle>\n </mat-card-title-group>\n </mat-card-header>\n\n <mat-card-content>\n <p>Email: {{ item.email }}</p>\n </mat-card-content>\n }\n</mat-card>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i1$3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i1$3.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i1$3.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "component", type: i1$3.MatCardTitleGroup, selector: "mat-card-title-group" }] });
|
|
1264
|
+
}
|
|
1265
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserListDetailComponent, decorators: [{
|
|
1266
|
+
type: Component,
|
|
1267
|
+
args: [{ selector: 'lib-user-list-detail', imports: [MatListModule,
|
|
1268
|
+
MatCardModule], template: "<mat-card mat-list-item class=\"item-card\">\n @if(item(); as item){\n <mat-card-header>\n <mat-card-title-group style=\"padding: 5px\">\n <mat-card-title\n >{{ item.first_name }} {{ item.last_name }}</mat-card-title\n >\n <mat-card-subtitle>{{ item.username }}</mat-card-subtitle>\n </mat-card-title-group>\n </mat-card-header>\n\n <mat-card-content>\n <p>Email: {{ item.email }}</p>\n </mat-card-content>\n }\n</mat-card>\n", styles: [":host{flex-grow:1}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"] }]
|
|
1269
|
+
}] });
|
|
1270
|
+
|
|
1271
|
+
class UserComponent {
|
|
1272
|
+
viewType = signal("list", ...(ngDevMode ? [{ debugName: "viewType" }] : []));
|
|
1273
|
+
itemService = inject(UserService);
|
|
1274
|
+
columns = [{ name: 'username', title: 'Name', element_type: 'string' }];
|
|
1275
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1276
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: UserComponent, isStandalone: true, selector: "lib-user", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [itemDetailTemplate]=\"listItemTemplate\"\n [columns]=\"columns\"\n [viewType]=\"viewType()\"\n >\n <ng-template #listItemTemplate let-item=\"item\">\n <lib-user-list-detail [item]=\"item\"\n [routerLink]=\"['/' + itemService.itemType + '/detail/', item.id]\"\n [routerLinkActive]=\"['is-active']\">\n </lib-user-list-detail>\n </ng-template>\n</lib-list-view>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields"] }, { kind: "component", type: UserListDetailComponent, selector: "lib-user-list-detail", inputs: ["item"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
|
|
1277
|
+
}
|
|
1278
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: UserComponent, decorators: [{
|
|
1279
|
+
type: Component,
|
|
1280
|
+
args: [{ selector: 'lib-user', imports: [ListViewComponent, UserListDetailComponent, RouterModule], template: "<lib-list-view\n [itemService]=\"itemService\"\n [itemDetailTemplate]=\"listItemTemplate\"\n [columns]=\"columns\"\n [viewType]=\"viewType()\"\n >\n <ng-template #listItemTemplate let-item=\"item\">\n <lib-user-list-detail [item]=\"item\"\n [routerLink]=\"['/' + itemService.itemType + '/detail/', item.id]\"\n [routerLinkActive]=\"['is-active']\">\n </lib-user-list-detail>\n </ng-template>\n</lib-list-view>\n", styles: [":host{flex-grow:1}\n"] }]
|
|
769
1281
|
}] });
|
|
770
1282
|
|
|
771
1283
|
class GroupDetailComponent extends DetailView {
|
|
@@ -777,7 +1289,7 @@ class GroupDetailComponent extends DetailView {
|
|
|
777
1289
|
this.onInit();
|
|
778
1290
|
}
|
|
779
1291
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
780
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: GroupDetailComponent, isStandalone: true, selector: "lib-group-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item) {\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [route]=\"typename\"></lib-detail-header>\n \n <div class=\"item-field\">{{item.name}}</div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route"] }] });
|
|
1292
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: GroupDetailComponent, isStandalone: true, selector: "lib-group-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item) {\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [route]=\"typename\"></lib-detail-header>\n \n <div class=\"item-field\">{{item.name}}</div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }] });
|
|
781
1293
|
}
|
|
782
1294
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupDetailComponent, decorators: [{
|
|
783
1295
|
type: Component,
|
|
@@ -786,113 +1298,230 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
786
1298
|
DetailHeaderComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n @if(item(); as item) {\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [route]=\"typename\"></lib-detail-header>\n \n <div class=\"item-field\">{{item.name}}</div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}\n"] }]
|
|
787
1299
|
}], ctorParameters: () => [] });
|
|
788
1300
|
|
|
789
|
-
class GroupComponent
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
super(inject(GroupService));
|
|
793
|
-
}
|
|
794
|
-
ngOnInit() {
|
|
795
|
-
this.onInit();
|
|
796
|
-
}
|
|
1301
|
+
class GroupComponent {
|
|
1302
|
+
itemService = inject(GroupService);
|
|
1303
|
+
columns = [{ name: 'name', title: 'Name', element_type: 'string' }];
|
|
797
1304
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
798
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: GroupComponent, isStandalone: true, selector: "lib-group",
|
|
1305
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: GroupComponent, isStandalone: true, selector: "lib-group", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields"] }] });
|
|
799
1306
|
}
|
|
800
1307
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: GroupComponent, decorators: [{
|
|
801
1308
|
type: Component,
|
|
802
|
-
args: [{ selector: 'lib-group', imports: [
|
|
803
|
-
|
|
804
|
-
MatButtonModule,
|
|
805
|
-
MatIconModule,
|
|
806
|
-
RouterModule
|
|
807
|
-
], template: "<div class=\"tabular-list-container\">\n <div>\n <table mat-table [dataSource]=\"items()\" class=\"mat-elevation-z8\">\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>Name</th>\n <td mat-cell *matCellDef=\"let element\"> {{element.name}} </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n [routerLink]=\"['/groups/detail/', row.id]\"\n [routerLinkActive]=\"['is-active']\"\n ></tr>\n </table>\n </div>\n</div>\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.is-active{font-weight:700}\n"] }]
|
|
808
|
-
}], ctorParameters: () => [] });
|
|
1309
|
+
args: [{ selector: 'lib-group', imports: [ListViewComponent], template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n", styles: [":host{flex-grow:1}\n"] }]
|
|
1310
|
+
}] });
|
|
809
1311
|
|
|
810
|
-
class OrganizationComponent
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
ngOnInit() {
|
|
816
|
-
this.onInit();
|
|
817
|
-
}
|
|
1312
|
+
class OrganizationComponent {
|
|
1313
|
+
itemService = inject(OrganizationService);
|
|
1314
|
+
columns = [{ name: 'name', title: 'Name', element_type: 'string' },
|
|
1315
|
+
{ name: 'website', title: 'Website', element_type: 'url' },
|
|
1316
|
+
{ name: 'is_partner', title: 'Is Partner', element_type: 'boolean' }];
|
|
818
1317
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
819
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: OrganizationComponent, isStandalone: true, selector: "lib-organization",
|
|
1318
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.1", type: OrganizationComponent, isStandalone: true, selector: "lib-organization", ngImport: i0, template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n\n\n", styles: [":host{flex-grow:1}\n"], dependencies: [{ kind: "component", type: ListViewComponent, selector: "lib-list-view", inputs: ["viewType", "itemService", "itemDetailTemplate", "columns", "sortFields"] }] });
|
|
820
1319
|
}
|
|
821
1320
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationComponent, decorators: [{
|
|
822
1321
|
type: Component,
|
|
823
1322
|
args: [{ selector: 'lib-organization', imports: [
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
1323
|
+
ListViewComponent
|
|
1324
|
+
], template: "<lib-list-view\n [itemService]=\"itemService\"\n [columns]=\"columns\"\n >\n</lib-list-view>\n\n\n\n", styles: [":host{flex-grow:1}\n"] }]
|
|
1325
|
+
}] });
|
|
1326
|
+
|
|
1327
|
+
class AddressService extends ItemService {
|
|
1328
|
+
_url = Address.plural;
|
|
1329
|
+
itemType = Address.plural;
|
|
1330
|
+
instantiateType(item) {
|
|
1331
|
+
return new Address(item);
|
|
1332
|
+
}
|
|
1333
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
1334
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, providedIn: 'root' });
|
|
1335
|
+
}
|
|
1336
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressService, decorators: [{
|
|
1337
|
+
type: Injectable,
|
|
1338
|
+
args: [{
|
|
1339
|
+
providedIn: 'root'
|
|
1340
|
+
}]
|
|
1341
|
+
}] });
|
|
1342
|
+
|
|
1343
|
+
class AddressDetailComponent {
|
|
1344
|
+
address = input(...(ngDevMode ? [undefined, { debugName: "address" }] : []));
|
|
1345
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1346
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: AddressDetailComponent, isStandalone: true, selector: "lib-address-detail", inputs: { address: { classPropertyName: "address", publicName: "address", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(address(); as address){\n<div class=\"item-field\" style=\"display:flex;flex-wrap: wrap;justify-content: center;align-content: center;\">\n <span style=\"margin-left: 3px;\">{{address.line1}}, </span>\n <span style=\"margin-left: 3px;\">{{address.line2}},</span>\n @if(address.line3){\n <span style=\"margin-left: 3px;\">{{address.line3}},</span>\n }\n @if(address.city){\n <span style=\"margin-left: 3px;\">{{address.city}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.region}},</span>\n @if(address.postcode){ \n <span style=\"margin-left: 3px;\">{{address.postcode}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.country_name}}</span>\n</div>\n}", styles: [""] });
|
|
1347
|
+
}
|
|
1348
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressDetailComponent, decorators: [{
|
|
1349
|
+
type: Component,
|
|
1350
|
+
args: [{ selector: 'lib-address-detail', imports: [], template: "@if(address(); as address){\n<div class=\"item-field\" style=\"display:flex;flex-wrap: wrap;justify-content: center;align-content: center;\">\n <span style=\"margin-left: 3px;\">{{address.line1}}, </span>\n <span style=\"margin-left: 3px;\">{{address.line2}},</span>\n @if(address.line3){\n <span style=\"margin-left: 3px;\">{{address.line3}},</span>\n }\n @if(address.city){\n <span style=\"margin-left: 3px;\">{{address.city}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.region}},</span>\n @if(address.postcode){ \n <span style=\"margin-left: 3px;\">{{address.postcode}},</span>\n }\n <span style=\"margin-left: 3px;\">{{address.country_name}}</span>\n</div>\n}" }]
|
|
1351
|
+
}] });
|
|
830
1352
|
|
|
831
1353
|
class OrganizationDetailComponent extends DetailView {
|
|
832
1354
|
typename = "organization";
|
|
1355
|
+
address = signal(null, ...(ngDevMode ? [{ debugName: "address" }] : []));
|
|
1356
|
+
addressService = inject(AddressService);
|
|
833
1357
|
constructor() {
|
|
834
1358
|
super(inject(OrganizationService));
|
|
835
1359
|
}
|
|
836
1360
|
ngOnInit() {
|
|
837
1361
|
this.onInit();
|
|
838
1362
|
}
|
|
1363
|
+
onItemAndUserAvailable(item, _user) {
|
|
1364
|
+
this.addressService.getUrl(item.address).subscribe(address => this.address.set(address));
|
|
1365
|
+
}
|
|
839
1366
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
840
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: OrganizationDetailComponent, isStandalone: true, selector: "lib-organization-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [route]=\"typename\"></lib-detail-header>\n\n
|
|
1367
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: OrganizationDetailComponent, isStandalone: true, selector: "lib-organization-detail", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [canEdit]=\"itemService.canEdit()\"\n [canDelete]=\"itemService.canDelete()\"\n [route]=\"typename\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n @if(address(); as address)\n {\n <h3>Address</h3>\n <lib-address-detail [address]=\"address\"></lib-address-detail>\n }\n <div class=\"item-field\">\n <h3>Website</h3>{{item.website}}\n </div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.padded_button{padding:5px}\n"], dependencies: [{ kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: DetailHeaderComponent, selector: "lib-detail-header", inputs: ["id", "text", "route", "canEdit", "canDelete"], outputs: ["deleteClicked"] }, { kind: "component", type: AddressDetailComponent, selector: "lib-address-detail", inputs: ["address"] }] });
|
|
841
1368
|
}
|
|
842
1369
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationDetailComponent, decorators: [{
|
|
843
1370
|
type: Component,
|
|
844
|
-
args: [{ selector: 'lib-organization-detail', imports: [
|
|
845
|
-
|
|
846
|
-
DetailHeaderComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [route]=\"typename\"></lib-detail-header>\n\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n <div class=\"item-field\">\n <h3>Address</h3>{{item.address}}\n </div>\n \n <div class=\"item-field\">\n <h3>Website</h3>{{item.website}}\n </div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.padded_button{padding:5px}\n"] }]
|
|
1371
|
+
args: [{ selector: 'lib-organization-detail', imports: [BackButtonComponent,
|
|
1372
|
+
DetailHeaderComponent, AddressDetailComponent], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-detail-container\">\n\n <lib-detail-header\n [text]=\"item.name\"\n [id]=\"item.id\"\n [canEdit]=\"itemService.canEdit()\"\n [canDelete]=\"itemService.canDelete()\"\n [route]=\"typename\"></lib-detail-header>\n\n <div class=\"item-field\">\n {{item.description}}\n </div>\n \n @if(address(); as address)\n {\n <h3>Address</h3>\n <lib-address-detail [address]=\"address\"></lib-address-detail>\n }\n <div class=\"item-field\">\n <h3>Website</h3>{{item.website}}\n </div>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.padded_button{padding:5px}\n"] }]
|
|
847
1373
|
}], ctorParameters: () => [] });
|
|
848
1374
|
|
|
1375
|
+
class AddressEditComponent {
|
|
1376
|
+
countryOptions = input([], ...(ngDevMode ? [{ debugName: "countryOptions" }] : []));
|
|
1377
|
+
form = input(...(ngDevMode ? [undefined, { debugName: "form" }] : []));
|
|
1378
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1379
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: AddressEditComponent, isStandalone: true, selector: "lib-address-edit", inputs: { countryOptions: { classPropertyName: "countryOptions", publicName: "countryOptions", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(form(); as form){\n<div [formGroup]=\"form\" style=\"display: flex; flex-direction: column; width:100%\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line1\">Line 1</mat-label>\n <input matInput placeholder=\"Address Line 1\" type=\"text\" id=\"line1\" formControlName=\"line1\" name=\"line1\"\n required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line2\">Line 2</mat-label>\n <input matInput placeholder=\"Address Line 2\" type=\"text\" id=\"line2\" formControlName=\"line2\" name=\"line1\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line3\">Line 3</mat-label>\n <input matInput placeholder=\"Address Line 3\" type=\"text\" id=\"line3\" formControlName=\"line3\" name=\"line3\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"city\">City</mat-label>\n <input matInput placeholder=\"City\" type=\"text\" id=\"city\" formControlName=\"city\" name=\"city\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"region\">Region</mat-label>\n <input matInput placeholder=\"Region\" type=\"text\" id=\"region\" formControlName=\"region\" name=\"region\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"line1\">Post Code</mat-label>\n <input matInput placeholder=\"Post Code\" type=\"text\" id=\"postcode\" formControlName=\"postcode\" name=\"postcode\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"country\">Country</mat-label>\n <mat-select formControlName=\"country\" name=\"country\" id=\"country\" required>\n @for(country of countryOptions(); track $index){\n <mat-option [value]=\"country.code\">{{country.name}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n}", styles: [""], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
|
|
1380
|
+
}
|
|
1381
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: AddressEditComponent, decorators: [{
|
|
1382
|
+
type: Component,
|
|
1383
|
+
args: [{ selector: 'lib-address-edit', imports: [MatFormFieldModule,
|
|
1384
|
+
MatSelectModule,
|
|
1385
|
+
MatInputModule,
|
|
1386
|
+
ReactiveFormsModule
|
|
1387
|
+
], template: "@if(form(); as form){\n<div [formGroup]=\"form\" style=\"display: flex; flex-direction: column; width:100%\">\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line1\">Line 1</mat-label>\n <input matInput placeholder=\"Address Line 1\" type=\"text\" id=\"line1\" formControlName=\"line1\" name=\"line1\"\n required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line2\">Line 2</mat-label>\n <input matInput placeholder=\"Address Line 2\" type=\"text\" id=\"line2\" formControlName=\"line2\" name=\"line1\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"line3\">Line 3</mat-label>\n <input matInput placeholder=\"Address Line 3\" type=\"text\" id=\"line3\" formControlName=\"line3\" name=\"line3\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"city\">City</mat-label>\n <input matInput placeholder=\"City\" type=\"text\" id=\"city\" formControlName=\"city\" name=\"city\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"region\">Region</mat-label>\n <input matInput placeholder=\"Region\" type=\"text\" id=\"region\" formControlName=\"region\" name=\"region\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"line1\">Post Code</mat-label>\n <input matInput placeholder=\"Post Code\" type=\"text\" id=\"postcode\" formControlName=\"postcode\" name=\"postcode\" required>\n </mat-form-field>\n\n <mat-form-field class=\"form-field\">\n <mat-label for=\"country\">Country</mat-label>\n <mat-select formControlName=\"country\" name=\"country\" id=\"country\" required>\n @for(country of countryOptions(); track $index){\n <mat-option [value]=\"country.code\">{{country.name}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n}" }]
|
|
1388
|
+
}] });
|
|
1389
|
+
|
|
1390
|
+
class AddressForm {
|
|
1391
|
+
formBuilder = inject(FormBuilder);
|
|
1392
|
+
form = this.formBuilder.group({
|
|
1393
|
+
line1: [''],
|
|
1394
|
+
line2: [''],
|
|
1395
|
+
line3: [''],
|
|
1396
|
+
city: [''],
|
|
1397
|
+
region: [''],
|
|
1398
|
+
postcode: [''],
|
|
1399
|
+
country: ['']
|
|
1400
|
+
});
|
|
1401
|
+
setValue(item) {
|
|
1402
|
+
this.form.setValue({
|
|
1403
|
+
line1: item.line1,
|
|
1404
|
+
line2: item.line2,
|
|
1405
|
+
line3: item.line3,
|
|
1406
|
+
city: item.city,
|
|
1407
|
+
region: item.region,
|
|
1408
|
+
postcode: item.postcode,
|
|
1409
|
+
country: item.country
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
updateItem(item) {
|
|
1413
|
+
const value = this.form.value;
|
|
1414
|
+
item.line1 = value.line1 || "";
|
|
1415
|
+
item.line2 = value.line2 || "";
|
|
1416
|
+
item.line3 = value.line3 || "";
|
|
1417
|
+
item.city = value.city || "";
|
|
1418
|
+
item.region = value.region || "";
|
|
1419
|
+
item.postcode = value.postcode || "";
|
|
1420
|
+
item.country = value.country || "";
|
|
1421
|
+
return item;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
class OrganizationForm {
|
|
1426
|
+
formBuilder = inject(FormBuilder);
|
|
1427
|
+
form;
|
|
1428
|
+
address = new AddressForm();
|
|
1429
|
+
constructor() {
|
|
1430
|
+
this.form = this.formBuilder.group({
|
|
1431
|
+
name: [''],
|
|
1432
|
+
acronym: [''],
|
|
1433
|
+
description: [''],
|
|
1434
|
+
website: [''],
|
|
1435
|
+
address: [this.address.form]
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
updateFromItem(item) {
|
|
1439
|
+
this.form.setValue({
|
|
1440
|
+
name: item.name,
|
|
1441
|
+
acronym: item.acronym,
|
|
1442
|
+
description: item.description,
|
|
1443
|
+
website: item.website,
|
|
1444
|
+
address: this.address.form
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
updateItem(item) {
|
|
1448
|
+
item.name = this.form.value.name || "";
|
|
1449
|
+
item.acronym = this.form.value.acronym || "";
|
|
1450
|
+
item.description = this.form.value.description || "";
|
|
1451
|
+
item.website = this.form.value.website || "";
|
|
1452
|
+
return item;
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
849
1456
|
class OrganizationEditComponent extends EditView {
|
|
1457
|
+
typename = "Organization";
|
|
850
1458
|
countryOptions = signal([], ...(ngDevMode ? [{ debugName: "countryOptions" }] : []));
|
|
851
1459
|
candidateMembers = signal([], ...(ngDevMode ? [{ debugName: "candidateMembers" }] : []));
|
|
852
1460
|
selectedMembers = signal([], ...(ngDevMode ? [{ debugName: "selectedMembers" }] : []));
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
country: [''] });
|
|
1461
|
+
columns = [{ name: 'first_name', title: 'First Name', element_type: 'string' },
|
|
1462
|
+
{ name: 'last_name', title: 'Surname', element_type: 'string' },
|
|
1463
|
+
{ name: 'username', title: 'Username', element_type: 'string' },
|
|
1464
|
+
{ name: 'email', title: 'Email', element_type: 'string' }];
|
|
1465
|
+
form = new OrganizationForm();
|
|
1466
|
+
address = new Address();
|
|
1467
|
+
addressService = inject(AddressService);
|
|
861
1468
|
constructor() {
|
|
862
1469
|
super(inject(OrganizationService));
|
|
863
1470
|
}
|
|
864
1471
|
ngOnInit() {
|
|
865
1472
|
this.onInit();
|
|
866
|
-
this.
|
|
1473
|
+
this.addressService.getOptions().subscribe(options => this.onOptions(options));
|
|
867
1474
|
}
|
|
868
1475
|
onItemAndUserAvailable(_) {
|
|
869
1476
|
const item = this.item();
|
|
870
1477
|
if (item) {
|
|
871
|
-
this.
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
});
|
|
878
|
-
this._userService.get("?organization=" + item.id).subscribe(users => this.selectedMembers.set(users));
|
|
879
|
-
this._userService.get().subscribe(users => this.candidateMembers.set(users));
|
|
1478
|
+
this.fetchAddress(item.address);
|
|
1479
|
+
this.form.updateFromItem(item);
|
|
1480
|
+
const queries = new Map([["organization", item.id.toString()]]);
|
|
1481
|
+
const query = new ItemQuery({ queries: queries });
|
|
1482
|
+
this._userService.get(query).subscribe(users => this.selectedMembers.set(users.results));
|
|
1483
|
+
this._userService.get().subscribe(users => this.updateCandidates(users));
|
|
880
1484
|
}
|
|
881
1485
|
}
|
|
1486
|
+
updateCandidates(users) {
|
|
1487
|
+
this.candidateMembers.set(users.results.map(user => { return { title: user.username, item: user }; }));
|
|
1488
|
+
}
|
|
882
1489
|
submit() {
|
|
883
|
-
this.
|
|
884
|
-
|
|
1490
|
+
this.syncFromForm();
|
|
1491
|
+
if (this.createMode()) {
|
|
1492
|
+
this.createAddress().subscribe(_ => super.submit());
|
|
1493
|
+
}
|
|
1494
|
+
else {
|
|
1495
|
+
this.updateAddress();
|
|
1496
|
+
super.submit();
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
fetchAddress(url) {
|
|
1500
|
+
if (url) {
|
|
1501
|
+
this.addressService.getUrl(url).subscribe(address => this.onAddressUpdated(address));
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
updateAddress() {
|
|
1505
|
+
this.addressService.putItem(this.address).subscribe(address => this.onAddressUpdated(address));
|
|
1506
|
+
}
|
|
1507
|
+
createAddress() {
|
|
1508
|
+
return this.addressService.postItem(this.address).pipe(tap(address => { this.onAddressCreated(address); }));
|
|
1509
|
+
}
|
|
1510
|
+
onAddressUpdated(address) {
|
|
1511
|
+
this.address = address;
|
|
1512
|
+
this.form.address.setValue(this.address);
|
|
1513
|
+
}
|
|
1514
|
+
onAddressCreated(address) {
|
|
1515
|
+
this.onAddressUpdated(address);
|
|
1516
|
+
this.item.update(item => { if (item) {
|
|
1517
|
+
item.address = address.url;
|
|
885
1518
|
} return item; });
|
|
886
|
-
super.submit();
|
|
887
1519
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
item.
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
item.website = this.form.value.website || "";
|
|
894
|
-
item.country = this.form.value.country || "";
|
|
895
|
-
return item;
|
|
1520
|
+
syncFromForm() {
|
|
1521
|
+
this.address = this.form.address.updateItem(this.address);
|
|
1522
|
+
this.item.update((item) => { if (item) {
|
|
1523
|
+
item = this.form.updateItem(item);
|
|
1524
|
+
} return item; });
|
|
896
1525
|
}
|
|
897
1526
|
getTemplateItem() {
|
|
898
1527
|
return new Organization();
|
|
@@ -903,7 +1532,7 @@ class OrganizationEditComponent extends EditView {
|
|
|
903
1532
|
}
|
|
904
1533
|
}
|
|
905
1534
|
onCountryChoices(choices) {
|
|
906
|
-
this.countryOptions.update(() => choices.map(c => c.display_name));
|
|
1535
|
+
this.countryOptions.update(() => choices.map(c => { return { name: c.display_name, code: c.value, flag: "" }; }));
|
|
907
1536
|
}
|
|
908
1537
|
onMemberRemoved(id) {
|
|
909
1538
|
const url = this.selectedMembers().find(m => m.id == id).url;
|
|
@@ -912,24 +1541,32 @@ class OrganizationEditComponent extends EditView {
|
|
|
912
1541
|
item.members.filter(m => m != url);
|
|
913
1542
|
} return item; });
|
|
914
1543
|
}
|
|
915
|
-
onMemberAdded(
|
|
916
|
-
const selected = this.candidateMembers().find(m => m.
|
|
1544
|
+
onMemberAdded(title) {
|
|
1545
|
+
const selected = this.candidateMembers().find(m => m.title == title);
|
|
917
1546
|
if (selected) {
|
|
918
|
-
this.selectedMembers.update(members => { members.push(selected); return members; });
|
|
1547
|
+
this.selectedMembers.update(members => { members.push(selected.item); return members; });
|
|
919
1548
|
}
|
|
920
|
-
this.candidateMembers.update(members => members.filter(m => m.
|
|
921
|
-
const url = this.selectedMembers().find(m => m.
|
|
1549
|
+
this.candidateMembers.update(members => members.filter(m => m.title != title));
|
|
1550
|
+
const url = this.selectedMembers().find(m => m.username == title).url;
|
|
922
1551
|
this.item.update(item => { if (item) {
|
|
923
1552
|
item.members.push(url);
|
|
924
1553
|
} return item; });
|
|
925
1554
|
}
|
|
1555
|
+
onSearchChanged(searchTerm) {
|
|
1556
|
+
console.log("Batch requested");
|
|
1557
|
+
if (searchTerm) {
|
|
1558
|
+
this._userService.get(new ItemQuery({ filter: searchTerm })).subscribe(users => this.updateCandidates(users));
|
|
1559
|
+
}
|
|
1560
|
+
else {
|
|
1561
|
+
this._userService.get().subscribe(users => this.updateCandidates(users));
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
926
1564
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
927
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: OrganizationEditComponent, isStandalone: true, selector: "lib-organization-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-edit-container\">\n \n <h1 class=\"item-edit-header\">{{heading()}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label
|
|
1565
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.1", type: OrganizationEditComponent, isStandalone: true, selector: "lib-organization-edit", usesInheritance: true, ngImport: i0, template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-edit-container\">\n \n <h1 class=\"item-edit-header\">{{heading()}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"name\">Name</mat-label>\n <input matInput placeholder=\"Name\"\n type=\"text\"\n id=\"name\"\n formControlName=\"name\"\n name=\"name\"\n required>\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label for=\"acronym\">Acronym</mat-label> \n <input matInput placeholder=\"Acronym\"\n type=\"text\"\n id=\"acronym\"\n formControlName=\"acronym\"\n name=\"acronym\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"Description\"\n type=\"text\"\n id=\"description\"\n formControlName=\"description\"\n name=\"description\"\n class=\"medium-textarea\"\n required></textarea>\n </mat-form-field>\n\n <h3>Address</h3>\n <lib-address-edit \n [countryOptions]=\"countryOptions()\"\n [form]=\"form.address.form\"\n ></lib-address-edit>\n\n <h3>Members</h3>\n <lib-select-table [selected]=\"selectedMembers()\"\n [itemType]=\"'Members'\"\n [columns]=\"columns\"\n [options]=\"candidateMembers()\"\n (itemAdded)=\"onMemberAdded($event)\"\n (itemRemoved)=\"onMemberRemoved($event)\"\n (searchChanged)=\"onSearchChanged($event)\">\n </lib-select-table>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon>\n </button>\n \n <button mat-fab\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n \n </form>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.medium-textarea{min-height:150px}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: BackButtonComponent, selector: "lib-back-button" }, { kind: "component", type: AddressEditComponent, selector: "lib-address-edit", inputs: ["countryOptions", "form"] }, { kind: "component", type: SelectTableComponent, selector: "lib-select-table", inputs: ["itemType", "selected", "options", "columns"], outputs: ["itemAdded", "itemRemoved", "searchChanged"] }] });
|
|
928
1566
|
}
|
|
929
1567
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImport: i0, type: OrganizationEditComponent, decorators: [{
|
|
930
1568
|
type: Component,
|
|
931
|
-
args: [{ selector: 'lib-organization-edit', imports: [
|
|
932
|
-
UserSelectComponent,
|
|
1569
|
+
args: [{ selector: 'lib-organization-edit', imports: [
|
|
933
1570
|
ReactiveFormsModule,
|
|
934
1571
|
MatButtonModule,
|
|
935
1572
|
MatInputModule,
|
|
@@ -937,7 +1574,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
937
1574
|
MatFormFieldModule,
|
|
938
1575
|
MatIconModule,
|
|
939
1576
|
MatCheckboxModule,
|
|
940
|
-
BackButtonComponent
|
|
1577
|
+
BackButtonComponent,
|
|
1578
|
+
AddressEditComponent,
|
|
1579
|
+
SelectTableComponent
|
|
1580
|
+
], template: "<lib-back-button></lib-back-button>\n\n<div class=\"content-container\">\n\n @if(item(); as item){\n <div class=\"item-edit-container\">\n \n <h1 class=\"item-edit-header\">{{heading()}}</h1>\n\n <form class=\"form-card\" [formGroup]=\"form.form\" (ngSubmit)=\"submit()\">\n\n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"name\">Name</mat-label>\n <input matInput placeholder=\"Name\"\n type=\"text\"\n id=\"name\"\n formControlName=\"name\"\n name=\"name\"\n required>\n </mat-form-field>\n \n <mat-form-field class=\"form-field\">\n <mat-label for=\"acronym\">Acronym</mat-label> \n <input matInput placeholder=\"Acronym\"\n type=\"text\"\n id=\"acronym\"\n formControlName=\"acronym\"\n name=\"acronym\">\n </mat-form-field>\n \n <mat-form-field class=\"form-field-wide\">\n <mat-label for=\"description\">Description</mat-label>\n <textarea matInput placeholder=\"Description\"\n type=\"text\"\n id=\"description\"\n formControlName=\"description\"\n name=\"description\"\n class=\"medium-textarea\"\n required></textarea>\n </mat-form-field>\n\n <h3>Address</h3>\n <lib-address-edit \n [countryOptions]=\"countryOptions()\"\n [form]=\"form.address.form\"\n ></lib-address-edit>\n\n <h3>Members</h3>\n <lib-select-table [selected]=\"selectedMembers()\"\n [itemType]=\"'Members'\"\n [columns]=\"columns\"\n [options]=\"candidateMembers()\"\n (itemAdded)=\"onMemberAdded($event)\"\n (itemRemoved)=\"onMemberRemoved($event)\"\n (searchChanged)=\"onSearchChanged($event)\">\n </lib-select-table>\n\n <div class=\"button_group\">\n <button mat-fab\n class=\"form_action_button\"\n type=\"submit\"\n [disabled]=\"!form.form.valid\">\n <mat-icon>save</mat-icon>\n </button>\n \n <button mat-fab\n class=\"form_action_button\"\n (click)=\"cancel()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n \n </form>\n </div>\n }\n</div>\n", styles: [":host{flex-grow:1}.medium-textarea{min-height:150px}.checkbox_group{justify-content:left;display:flex;flex-direction:column}.button_group{margin:10px;display:flex;flex-direction:row;justify-content:center}.btn-block{padding:5px}.form_action_button{padding:5px;margin:5px}\n"] }]
|
|
941
1581
|
}], ctorParameters: () => [] });
|
|
942
1582
|
|
|
943
1583
|
/*
|
|
@@ -948,5 +1588,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.1", ngImpor
|
|
|
948
1588
|
* Generated bundle index. Do not edit.
|
|
949
1589
|
*/
|
|
950
1590
|
|
|
951
|
-
export { ApiError, BackButtonComponent, DetailHeaderComponent, DetailView, ENDPOINT_URL, EditView, ErrorCode, FileRecord, FileUploadComponent, Group, GroupComponent, GroupDetailComponent, GroupService, LOGIN_USER, LandingComponent, LeftNavComponent, LeftNavService, ListView,
|
|
1591
|
+
export { ApiError, BackButtonComponent, DetailHeaderComponent, DetailView, ENDPOINT_URL, EditView, ErrorCode, FileRecord, FileUploadComponent, Group, GroupComponent, GroupDetailComponent, GroupService, ItemQuery, LOGIN_USER, LandingComponent, LeftNavComponent, LeftNavService, ListView, OrganizationComponent, OrganizationDetailComponent, OrganizationEditComponent, OrganizationService, Paginated, Permission, PortalMember, ResolvedPermission, RestService, SelectTableComponent, TopBarComponent, UserComponent, UserDetailComponent, UserEditComponent, UserService };
|
|
952
1592
|
//# sourceMappingURL=ichec-angular-core.mjs.map
|