@magda/external-ui-plugin-sdk 2.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +15 -0
  2. package/dist/index.d.ts +556 -0
  3. package/package.json +44 -0
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ ### MAGDA External UI Plugin SDK
2
+
3
+ Magda allows you to build / bundle React UI components with your own logic and supply the customised UI components to Magda at the time of deployment (via [Helm chart config](https://github.com/magda-io/magda/tree/master/deploy/helm/internal-charts/web-server)) to replace the functionality of existing UI components. For those custom built UI components, we call External UI Plugin Components.
4
+
5
+ For more information of how to create / config External UI Plugin Components, please refer to [magda-plugin-ui-component-examples repo](https://github.com/magda-io/magda-plugin-ui-component-examples).
6
+
7
+ This SDK at this moment only contains typescript types of all key data structures.
8
+
9
+ Not all built-in Magda built-in components can be replaced by an External UI Plugin Component.
10
+
11
+ For the list of replacable components, please refer to exported component types.
12
+
13
+ ### Documentation
14
+
15
+ SDK document is available from [here](./docs/modules.md).
@@ -0,0 +1,556 @@
1
+ import { ComponentType } from 'react';
2
+ import { History as History_2 } from 'history';
3
+ import { Location as Location_2 } from 'history';
4
+ import { match } from 'react-router-dom';
5
+
6
+ declare type Access = {
7
+ location?: string;
8
+ useStorageApi?: boolean;
9
+ note?: string;
10
+ };
11
+
12
+ declare interface CkanExportAspectProperties {
13
+ status: CkanExportStatus;
14
+ exportUserId?: string;
15
+ ckanId?: string;
16
+ hasCreated: boolean;
17
+ exportRequired: boolean;
18
+ exportAttempted: boolean;
19
+ lastExportAttemptTime?: Date;
20
+ exportError?: string;
21
+ }
22
+
23
+ declare interface CkanExportAspectType {
24
+ [key: string]: CkanExportAspectProperties;
25
+ }
26
+
27
+ declare type CkanExportStatus = "withdraw" | "retain";
28
+
29
+ /**
30
+ * The common properties that all external UI plugins will receive.
31
+ *
32
+ * @export
33
+ * @interface CommonPropsType
34
+ */
35
+ export declare interface CommonPropsType {
36
+ /**
37
+ * Whether or not the user profile loading request is still in progress.
38
+ *
39
+ * @type {boolean}
40
+ * @memberof CommonPropsType
41
+ */
42
+ isFetchingWhoAmI: boolean;
43
+
44
+ /**
45
+ * the user profile data including roles, permission & orgUnit information.
46
+ *
47
+ * @type {User}
48
+ * @memberof CommonPropsType
49
+ */
50
+ user: User;
51
+
52
+ /**
53
+ * When it's not `null`, this fields contains the error thrown by the user profile loading request
54
+ */
55
+ whoAmIError: Error | null;
56
+
57
+ /**
58
+ * The `config` field contains all frontend config data fields.
59
+ * External UI plugin developer might be interested in `config.extraConfigData` field.
60
+ * `config.extraConfigData` field serves as an interface to config external UI plugin at deployment time.
61
+ * External UI plugin related config data can be supplied via [web-server](https://github.com/magda-io/magda/tree/master/deploy/helm/internal-charts/web-server) helm chart.
62
+ *
63
+ * @type {ConfigDataType}
64
+ * @memberof CommonPropsType
65
+ */
66
+ config: ConfigDataType;
67
+
68
+ /**
69
+ * The [history object](https://github.com/remix-run/history/blob/v4/docs/Navigation.md) that you can use to control application navigation.
70
+ * e.g. switch to a new url.
71
+ *
72
+ * @type {History<any>}
73
+ * @memberof CommonPropsType
74
+ */
75
+ history: History_2<any>;
76
+
77
+ /**
78
+ * The [location object](https://github.com/remix-run/history/blob/v4/docs/GettingStarted.md#listening) object implements
79
+ * a subset of [the window.location interface](https://developer.mozilla.org/en-US/docs/Web/API/Location).
80
+ *
81
+ * @type {Location<any>}
82
+ * @memberof CommonPropsType
83
+ */
84
+ location: Location_2<any>;
85
+
86
+ /**
87
+ * The match data is about a route at the given path relative to the current location.
88
+ * It's generated by [react-router](https://v5.reactrouter.com/web/api/match).
89
+ *
90
+ * @type {match<any>}
91
+ * @memberof CommonPropsType
92
+ */
93
+ match: match<any>;
94
+
95
+ /**
96
+ * When called, this function will dispatch the `sign out` action to sign the current user out.
97
+ *
98
+ * @memberof CommonPropsType
99
+ */
100
+ requestSignOut: () => Promise<void>;
101
+
102
+ /**
103
+ * When called, this function will dispatch an action to force the current user profile data to be reloaded / refreshed.
104
+ * You may only want to call it after you just modified the user's profile.
105
+ *
106
+ * @memberof CommonPropsType
107
+ */
108
+ requestWhoAmI: () => Promise<void>;
109
+
110
+ /**
111
+ * When called, this function will dispatch an action to make all client side resource items (e.g. header & footer items etc.)
112
+ * to be reloaded. You may only want to call it after the current user profile changed or any content items have been updated.
113
+ * You can optionally passing a boolean parameter `noCache` to control the cache behaviour during the loading.
114
+ * Its default value is `false`.
115
+ *
116
+ * @memberof CommonPropsType
117
+ */
118
+ fetchContent: (noCache?: boolean) => Promise<void>;
119
+ }
120
+
121
+ declare type CompatiblePreviews = {
122
+ map?: boolean;
123
+ chart?: boolean;
124
+ table?: boolean;
125
+ json?: boolean;
126
+ html?: boolean;
127
+ text?: boolean;
128
+ rss?: boolean;
129
+ google?: boolean;
130
+ };
131
+
132
+ declare interface ConfigDataType {
133
+ image?: {
134
+ pullPolicy?: string;
135
+ repository?: string;
136
+ tag?: string;
137
+ };
138
+ authApiBaseUrl?: string;
139
+ baseUrl?: string;
140
+ authPluginRedirectUrl?: string;
141
+ baseExternalUrl?: string;
142
+ uiBaseUrl?: string;
143
+ showNotificationBanner?: boolean;
144
+ contentApiBaseUrl?: string;
145
+ previewMapBaseUrl?: string;
146
+ indexerApiBaseUrl?: string;
147
+ registryApiBaseUrl?: string;
148
+ registryApiReadOnlyBaseUrl?: string;
149
+ searchApiBaseUrl?: string;
150
+ correspondenceApiBaseUrl?: string;
151
+ storageApiBaseUrl?: string;
152
+ gapiIds?: Array<string>;
153
+ adminApiBaseUrl?: string;
154
+ disableAuthenticationFeatures?: boolean;
155
+ fallbackUrl?: string;
156
+ featureFlags?: {
157
+ [id: string]: boolean;
158
+ };
159
+ useMagdaStorageByDefault?: boolean;
160
+ vocabularyApiEndpoints: string[];
161
+ defaultOrganizationId?: string;
162
+ defaultContactEmail?: string;
163
+ custodianOrgLevel: number;
164
+ automaticPreviewMaxFileSize: number;
165
+ mandatoryFields: ValidationFieldList;
166
+ dateConfig?: DateConfig;
167
+ noManualKeywords?: boolean;
168
+ noManualThemes?: boolean;
169
+ datasetThemes?: string[];
170
+ keywordsBlackList?: string[];
171
+ openfaasBaseUrl?: string;
172
+ ckanExportServers: {
173
+ [ckanServerUrl: string]: boolean;
174
+ };
175
+ defaultCkanServer: string;
176
+ defaultTimeZone?: string;
177
+ enableCrawlerViews?: boolean;
178
+ discourseSiteUrl?: string;
179
+ discourseIntegrationDatasetPage?: boolean;
180
+ discourseIntegrationDistributionPage?: boolean;
181
+ externalUIComponents?: string[];
182
+ externalCssFiles?: string[];
183
+ homePageUrl?: string;
184
+ supportExternalTerriaMapV7?: boolean;
185
+ openInExternalTerriaMapButtonText?: string;
186
+ openInExternalTerriaMapTargetUrl?: string;
187
+ extraConfigData?: {
188
+ // extraConfigData is mainly for config data passing to external UI plugins
189
+ [key: string]: any;
190
+ };
191
+ previewMapFormatPerference?: RawPreviewMapFormatPerferenceItem[];
192
+ showContactButtonForNoContactPointDataset?: boolean;
193
+ defaultDatasetBucket?: string;
194
+ anonymousUserLandingPage?: string;
195
+ authenticatedUserLandingPage?: string;
196
+ authStatusRefreshInterval?: number;
197
+ }
198
+
199
+ /**
200
+ * Footer copyright config item
201
+ *
202
+ * @export
203
+ * @interface CopyRightItem
204
+ */
205
+ export declare interface CopyRightItem {
206
+ href: string;
207
+ htmlContent: string;
208
+ logoSrc: string;
209
+ order: number;
210
+ }
211
+
212
+ declare type CurrencyData = {
213
+ status: "CURRENT" | "SUPERSEDED" | "RETIRED";
214
+ retireReason?: string;
215
+ supersededBy?: {
216
+ id?: string[];
217
+ name?: string;
218
+ }[];
219
+ };
220
+
221
+ export declare type DatasetEditButtonComponentPropsType = {
222
+ dataset: ParsedDataset;
223
+ };
224
+
225
+ /**
226
+ * Dataset page `Edit Dataset` button external plugin component type
227
+ * @category External UI Plugin Component Types
228
+ */
229
+ export declare type DatasetEditButtonComponentType = ComponentType<
230
+ DatasetEditButtonComponentPropsType
231
+ >;
232
+
233
+ export declare type DatasetLikeButtonComponentPropsType = {
234
+ dataset: ParsedDataset;
235
+ };
236
+
237
+ /**
238
+ * Search Result page `Like Button` external plugin component type
239
+ * Please note: the `Like Button` on search result page is hidden unless a plugin component is supplied.
240
+ * @category External UI Plugin Component Types
241
+ */
242
+ export declare type DatasetLikeButtonComponentType = ComponentType<
243
+ DatasetLikeButtonComponentPropsType
244
+ >;
245
+
246
+ declare interface DateConfig {
247
+ dateFormats: string[];
248
+ dateRegexes: {
249
+ dateRegex: RegExp;
250
+ startDateRegex: RegExp;
251
+ endDateRegex: RegExp;
252
+ };
253
+ }
254
+
255
+ export declare type ExtraVisualisationSectionComponentPropsType = {
256
+ dataset: ParsedDataset;
257
+ distributionId?: string;
258
+ };
259
+
260
+ /**
261
+ * Visualisation Section external plugin component type.
262
+ * This plugin will be mounted on dataset or distribution page.
263
+ * More info & example please refer to repo: [magda-ui-plugin-component-dap-thumbnail-viewer](https://github.com/magda-io/magda-ui-plugin-component-dap-thumbnail-viewer)
264
+ * @category External UI Plugin Component Types
265
+ */
266
+ export declare type ExtraVisualisationSectionComponentType = ComponentType<
267
+ ExtraVisualisationSectionComponentPropsType
268
+ >;
269
+
270
+ declare type FetchError = {
271
+ title: string;
272
+ detail: string;
273
+ };
274
+
275
+ export declare type FooterComponentPropsType = {
276
+ noTopMargin: boolean;
277
+ footerMediumNavs: FooterNavLinkGroup[];
278
+ footerSmallNavs: FooterNavLinkGroup[];
279
+ footerCopyRightItems: CopyRightItem[];
280
+ };
281
+
282
+ /**
283
+ * Footer external plugin component type
284
+ * @category External UI Plugin Component Types
285
+ */
286
+ export declare type FooterComponentType = ComponentType<FooterComponentPropsType>;
287
+
288
+ /**
289
+ * Footer Navigation Link Config Item
290
+ *
291
+ * @export
292
+ * @interface FooterNavLink
293
+ */
294
+ export declare interface FooterNavLink {
295
+ href: string;
296
+ label: string;
297
+ order: number;
298
+ }
299
+
300
+ /**
301
+ * Footer Navigation Link Group
302
+ *
303
+ * @export
304
+ * @interface FooterNavLinkGroup
305
+ */
306
+ export declare interface FooterNavLinkGroup {
307
+ label: string;
308
+ links: FooterNavLink[];
309
+ order: number;
310
+ }
311
+
312
+ export declare interface HeaderComponentProps {
313
+ headerNavItems: HeaderNavItem[];
314
+ }
315
+
316
+ /**
317
+ * Header external plugin component type
318
+ * @category External UI Plugin Component Types
319
+ */
320
+ export declare type HeaderComponentType = ComponentType<HeaderComponentProps>;
321
+
322
+ /**
323
+ * The type of Header Navigation Item
324
+ *
325
+ * @export
326
+ * @interface HeaderNavItem
327
+ */
328
+ export declare interface HeaderNavItem {
329
+ default?: {
330
+ href: string;
331
+ label: string;
332
+ rel?: string;
333
+ target?: string;
334
+ };
335
+ auth?: Record<string, never>;
336
+ order: number;
337
+ }
338
+
339
+ declare type OperationRecord = {
340
+ id: string;
341
+ uri: string;
342
+ name: string;
343
+ description: string;
344
+ resource_id: string;
345
+ };
346
+
347
+ declare type OrgUnit = {
348
+ id: string;
349
+ name: string;
350
+ description: string;
351
+ left?: number;
352
+ right?: number;
353
+ create_by?: string;
354
+ create_time?: string;
355
+ edit_by?: string;
356
+ edit_time?: string;
357
+ };
358
+
359
+ declare type ParsedDataset = {
360
+ identifier?: string;
361
+ title: string;
362
+ accrualPeriodicity?: string;
363
+ accrualPeriodicityRecurrenceRule?: string;
364
+ currency?: CurrencyData;
365
+ issuedDate?: string;
366
+ updatedDate?: string;
367
+ landingPage: string;
368
+ tags: Array<string>;
369
+ description: string;
370
+ distributions: Array<ParsedDistribution>;
371
+ temporalCoverage?: TemporalCoverage;
372
+ themes: string[];
373
+ publisher: Publisher;
374
+ source?: string;
375
+ linkedDataRating: number;
376
+ contactPoint: string;
377
+ error?: FetchError;
378
+ hasQuality?: boolean;
379
+ sourceDetails?: any;
380
+ provenance?: ParsedProvenance;
381
+ publishingState?: string;
382
+ spatialCoverageBbox?: any;
383
+ temporalExtent?: any;
384
+ accessLevel?: string;
385
+ informationSecurity?: ParsedInformationSecurity;
386
+ accessControl?: {
387
+ ownerId: string;
388
+ orgUnitId: string;
389
+ preAuthorisedPermissionIds: string[];
390
+ };
391
+ ckanExport?: CkanExportAspectType;
392
+ access: Access;
393
+ };
394
+
395
+ declare type ParsedDistribution = {
396
+ identifier?: string;
397
+ title: string;
398
+ description: string;
399
+ format: string;
400
+ downloadURL?: string;
401
+ accessURL?: string;
402
+ updatedDate?: string;
403
+ license: string | any;
404
+ linkActive: boolean;
405
+ linkStatusAvailable: boolean;
406
+ isTimeSeries: boolean;
407
+ chartFields?: any;
408
+ compatiblePreviews: CompatiblePreviews;
409
+ accessNotes?: string;
410
+ visualizationInfo: any;
411
+ sourceDetails: any;
412
+ ckanResource: any;
413
+ publishingState?: string;
414
+ accessControl?: {
415
+ ownerId: string;
416
+ orgUnitId: string;
417
+ preAuthorisedPermissionIds: string[];
418
+ };
419
+ version?: VersionAspectData;
420
+ byteSize?: number;
421
+ };
422
+
423
+ declare type ParsedInformationSecurity = {
424
+ disseminationLimits: string[];
425
+ classification: string;
426
+ };
427
+
428
+ declare type ParsedProvenance = {
429
+ mechanism?: string;
430
+ sourceSystem?: string;
431
+ derivedFrom?: string;
432
+ affiliatedOrganizations?: Record_2[];
433
+ isOpenData?: boolean;
434
+ };
435
+
436
+ declare interface PermissionRecord {
437
+ id: string;
438
+ name: string;
439
+ description: string;
440
+ resource_id: string;
441
+ user_ownership_constraint: boolean;
442
+ org_unit_ownership_constraint: boolean;
443
+ pre_authorised_constraint: boolean;
444
+ owner_id: string;
445
+ create_time: string;
446
+ create_by: string;
447
+ edit_time: string;
448
+ edit_by: string;
449
+ }
450
+
451
+ export declare const PREFIX = "MagdaPluginComponent";
452
+
453
+ declare type Publisher = {
454
+ id: string;
455
+ name: string;
456
+ message?: string;
457
+ aspects: {
458
+ source?: {
459
+ url: string;
460
+ type: string;
461
+ };
462
+ "organization-details"?: {
463
+ name: string;
464
+ title: string;
465
+ imageUrl: string;
466
+ description: string;
467
+ };
468
+ };
469
+ };
470
+
471
+ declare interface RawPreviewMapFormatPerferenceItem {
472
+ format: string;
473
+ isDataFile?: boolean;
474
+ urlRegex?: string;
475
+ }
476
+
477
+ declare type Record_2 = {
478
+ id: string;
479
+ name: string;
480
+ aspects: { [aspectId: string]: any };
481
+ };
482
+
483
+ declare type Role = {
484
+ id: string;
485
+ name: string;
486
+ description: string;
487
+ permissionIds: string[];
488
+ };
489
+
490
+ declare interface RolePermissionRecord extends PermissionRecord {
491
+ resource_uri: string;
492
+ operations?: OperationRecord[];
493
+ }
494
+
495
+ declare type TemporalCoverage = {
496
+ intervals: {
497
+ start?: string;
498
+ end?: string;
499
+ startIndeterminate?: "unknown" | "now" | "before" | "after";
500
+ endIndeterminate?: "unknown" | "now" | "before" | "after";
501
+ }[];
502
+ };
503
+
504
+ declare type User = {
505
+ id: string;
506
+ displayName: string;
507
+ email: string;
508
+ photoURL: string;
509
+ source: string;
510
+ sourceId?: string;
511
+ isAdmin: boolean;
512
+ roles: Role[];
513
+ permissions: RolePermissionRecord[];
514
+ orgUnitId?: string;
515
+ orgUnit?: OrgUnit;
516
+ managingOrgUnitIds?: string[];
517
+ };
518
+
519
+ /**
520
+ * A global module to manage / coordinate validation workflow.
521
+ * The overall workflow:
522
+ * - every UI component should attempt to register itself to participant the validation
523
+ * - ValidationManager will determine whether should get the component involved in the validation process based on config
524
+ * - UI components are also responsible for
525
+ * - Register the component when componentDidMount and de-register itself when componentWillUnmount
526
+ * - Supplie functions for updating component's valid / invalid status (see definition of `ValidationItem`)
527
+ * - call `onInputFocusOut` when focus is removed from the component
528
+ * - `ValidationManager` supplies `useValidation` hook to facilite this process
529
+ * - `ValidationManager` also provides function like `validateAll` to validate all active components on screen
530
+ * - To enable `ValidationManager`, `setStateDataGetter` should also be called when the page component is mounted so that `ValidationManager` has access to state data
531
+ */
532
+
533
+ /**
534
+ * A list of field json path (query against [add dataset page state](https://github.com/magda-io/magda/blob/master/magda-web-client/src/Components/Dataset/Add/DatasetAddCommon.ts#L133) that should be validated / Mandatory.
535
+ * We currently don't use json path here to query any json data.
536
+ * Use json path as a standard way to name the mandatory field only.
537
+ * e.g. ["$.dataset.title", "$.distributions[1].license", "$.dataset.defaultLicense"]
538
+ */
539
+ declare type ValidationFieldList = string[];
540
+
541
+ declare type VersionAspectData = {
542
+ currentVersionNumber: number;
543
+ versions: VersionItem[];
544
+ };
545
+
546
+ declare type VersionItem = {
547
+ versionNumber: number;
548
+ createTime: string;
549
+ creatorId?: string;
550
+ description: string;
551
+ title: string;
552
+ internalDataFileUrl?: string;
553
+ eventId?: number;
554
+ };
555
+
556
+ export { }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@magda/external-ui-plugin-sdk",
3
+ "description": "MAGDA external UI plugin SDK",
4
+ "version": "2.2.0-alpha.1",
5
+ "scripts": {
6
+ "prebuild": "rimraf dist tsconfig.tsbuildinfo",
7
+ "build": "api-extractor run -l",
8
+ "docs": "which typedoc; if [ $? -eq 1 ]; then echo \"Error: typedoc is required.\";else typedoc;fi",
9
+ "release": "npm publish || echo \"Skip releasing npm package @magda/external-ui-plugin-sdk.\""
10
+ },
11
+ "author": "Jacky Jiang",
12
+ "license": "Apache-2.0",
13
+ "main": "",
14
+ "types": "dist/index.d.ts",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/magda-io/magda.git",
18
+ "directory": "packages/external-ui-plugin-sdk"
19
+ },
20
+ "devDependencies": {
21
+ "@magda/web-client": "^2.2.0-alpha.1",
22
+ "typescript": "~4.2.4"
23
+ },
24
+ "peerDependencies": {
25
+ "@types/react": "^16.8.17",
26
+ "@types/history": "^4.7.11",
27
+ "@types/react-router-dom": "^5.3.3"
28
+ },
29
+ "magda": {
30
+ "language": "typescript",
31
+ "categories": {
32
+ "npmPackage": true,
33
+ "useCommonLib": true
34
+ }
35
+ },
36
+ "keywords": [
37
+ "Magda",
38
+ "External UI Plugin",
39
+ "SDK"
40
+ ],
41
+ "files": [
42
+ "dist"
43
+ ]
44
+ }