@api-client/ui 0.0.11 → 0.0.13
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/.eslintrc +8 -0
- package/demo/elements/authorization/cc.ts +56 -27
- package/demo/elements/index.html +3 -0
- package/demo/elements/store/file-picker.html +15 -0
- package/demo/elements/store/file-picker.ts +134 -0
- package/demo/elements/store/index.html +19 -0
- package/demo/store/StorePlugin.js +1 -0
- package/dist/bindings/base/FileBindings.d.ts +4 -0
- package/dist/bindings/base/FileBindings.d.ts.map +1 -1
- package/dist/bindings/base/FileBindings.js +21 -1
- package/dist/bindings/base/FileBindings.js.map +1 -1
- package/dist/bindings/base/StoreBindings.d.ts +6 -17
- package/dist/bindings/base/StoreBindings.d.ts.map +1 -1
- package/dist/bindings/base/StoreBindings.js +15 -60
- package/dist/bindings/base/StoreBindings.js.map +1 -1
- package/dist/bindings/web/WebFileBindings.js +1 -1
- package/dist/bindings/web/WebFileBindings.js.map +1 -1
- package/dist/define/http/certificate-add.d.ts +9 -0
- package/dist/define/http/certificate-add.d.ts.map +1 -0
- package/dist/define/http/certificate-add.js +10 -0
- package/dist/define/http/certificate-add.js.map +1 -0
- package/dist/define/store/file-picker.d.ts +9 -0
- package/dist/define/store/file-picker.d.ts.map +1 -0
- package/dist/define/store/file-picker.js +10 -0
- package/dist/define/store/file-picker.js.map +1 -0
- package/dist/define/{files → store}/share-file.d.ts +1 -1
- package/dist/define/store/share-file.d.ts.map +1 -0
- package/dist/define/{files → store}/share-file.js +2 -2
- package/dist/define/store/share-file.js.map +1 -0
- package/dist/define/ui/ui-segmented-button-set.d.ts +1 -1
- package/dist/define/ui/ui-segmented-button-set.d.ts.map +1 -1
- package/dist/define/ui/ui-segmented-button-set.js.map +1 -1
- package/dist/elements/authorization/ui/CC.styles.d.ts.map +1 -1
- package/dist/elements/authorization/ui/CC.styles.js +4 -9
- package/dist/elements/authorization/ui/CC.styles.js.map +1 -1
- package/dist/elements/authorization/ui/CcAuthorization.d.ts +14 -29
- package/dist/elements/authorization/ui/CcAuthorization.d.ts.map +1 -1
- package/dist/elements/authorization/ui/CcAuthorization.js +67 -158
- package/dist/elements/authorization/ui/CcAuthorization.js.map +1 -1
- package/dist/elements/http/CertificateAdd.element.d.ts +91 -0
- package/dist/elements/http/CertificateAdd.element.d.ts.map +1 -0
- package/dist/elements/http/CertificateAdd.element.js +389 -0
- package/dist/elements/http/CertificateAdd.element.js.map +1 -0
- package/dist/elements/http/CertificateAdd.styles.d.ts +3 -0
- package/dist/elements/http/CertificateAdd.styles.d.ts.map +1 -0
- package/dist/elements/http/CertificateAdd.styles.js +61 -0
- package/dist/elements/http/CertificateAdd.styles.js.map +1 -0
- package/dist/elements/project/ProjectRunReport.d.ts +2 -1
- package/dist/elements/project/ProjectRunReport.d.ts.map +1 -1
- package/dist/elements/project/ProjectRunReport.js.map +1 -1
- package/dist/elements/store/FilePicker.element.d.ts +87 -0
- package/dist/elements/store/FilePicker.element.d.ts.map +1 -0
- package/dist/elements/store/FilePicker.element.js +263 -0
- package/dist/elements/store/FilePicker.element.js.map +1 -0
- package/dist/elements/store/FilePicker.styles.d.ts +3 -0
- package/dist/elements/store/FilePicker.styles.d.ts.map +1 -0
- package/dist/elements/store/FilePicker.styles.js +73 -0
- package/dist/elements/store/FilePicker.styles.js.map +1 -0
- package/dist/elements/store/FilesLib.d.ts +10 -0
- package/dist/elements/store/FilesLib.d.ts.map +1 -0
- package/dist/elements/store/FilesLib.js +38 -0
- package/dist/elements/store/FilesLib.js.map +1 -0
- package/dist/elements/{files/ShareFile.d.ts → store/ShareFile.element.d.ts} +1 -1
- package/dist/elements/store/ShareFile.element.d.ts.map +1 -0
- package/dist/elements/{files/ShareFile.js → store/ShareFile.element.js} +1 -1
- package/dist/elements/store/ShareFile.element.js.map +1 -0
- package/dist/elements/store/ShareFile.styles.d.ts.map +1 -0
- package/dist/elements/{files → store}/ShareFile.styles.js.map +1 -1
- package/dist/events/EventTypes.d.ts +7 -7
- package/dist/events/EventTypes.d.ts.map +1 -1
- package/dist/events/EventTypes.js +8 -7
- package/dist/events/EventTypes.js.map +1 -1
- package/dist/events/Events.d.ts +7 -1
- package/dist/events/Events.d.ts.map +1 -1
- package/dist/events/Events.js +2 -0
- package/dist/events/Events.js.map +1 -1
- package/dist/events/FilesystemEvents.d.ts +8 -0
- package/dist/events/FilesystemEvents.d.ts.map +1 -0
- package/dist/events/FilesystemEvents.js +59 -0
- package/dist/events/FilesystemEvents.js.map +1 -0
- package/dist/events/HttpClientEvents.d.ts +0 -2
- package/dist/events/HttpClientEvents.d.ts.map +1 -1
- package/dist/events/HttpClientEvents.js +0 -2
- package/dist/events/HttpClientEvents.js.map +1 -1
- package/dist/events/StoreEvents.d.ts +8 -1
- package/dist/events/StoreEvents.d.ts.map +1 -1
- package/dist/events/StoreEvents.js +19 -0
- package/dist/events/StoreEvents.js.map +1 -1
- package/dist/http-client/idb/Arc18DataUpgrade.d.ts +0 -8
- package/dist/http-client/idb/Arc18DataUpgrade.d.ts.map +1 -1
- package/dist/http-client/idb/Arc18DataUpgrade.js +11 -206
- package/dist/http-client/idb/Arc18DataUpgrade.js.map +1 -1
- package/dist/http-client/store/StoreBroadcast.d.ts +0 -5
- package/dist/http-client/store/StoreBroadcast.d.ts.map +1 -1
- package/dist/http-client/store/StoreBroadcast.js +0 -7
- package/dist/http-client/store/StoreBroadcast.js.map +1 -1
- package/dist/lib/files/FileUtils.d.ts +9 -0
- package/dist/lib/files/FileUtils.d.ts.map +1 -0
- package/dist/lib/files/FileUtils.js +13 -0
- package/dist/lib/files/FileUtils.js.map +1 -0
- package/dist/mixins/RouteMixin.d.ts +4 -0
- package/dist/mixins/RouteMixin.d.ts.map +1 -1
- package/dist/mixins/RouteMixin.js +1 -0
- package/dist/mixins/RouteMixin.js.map +1 -1
- package/dist/pages/ApplicationScreen.d.ts +1 -1
- package/dist/pages/ApplicationScreen.d.ts.map +1 -1
- package/dist/pages/ApplicationScreen.js +4 -2
- package/dist/pages/ApplicationScreen.js.map +1 -1
- package/dist/pages/api-client/ApiClient.screen.d.ts +4 -6
- package/dist/pages/api-client/ApiClient.screen.d.ts.map +1 -1
- package/dist/pages/api-client/ApiClient.screen.js +39 -31
- package/dist/pages/api-client/ApiClient.screen.js.map +1 -1
- package/dist/pages/api-client/ApiClient.styles.d.ts.map +1 -1
- package/dist/pages/api-client/ApiClient.styles.js +0 -12
- package/dist/pages/api-client/ApiClient.styles.js.map +1 -1
- package/dist/pages/api-client/Authenticate.screen.d.ts +1 -1
- package/dist/pages/api-client/Authenticate.screen.d.ts.map +1 -1
- package/dist/pages/api-client/Authenticate.screen.js +2 -2
- package/dist/pages/api-client/Authenticate.screen.js.map +1 -1
- package/dist/pages/api-client/pages/Files.page.d.ts +6 -35
- package/dist/pages/api-client/pages/Files.page.d.ts.map +1 -1
- package/dist/pages/api-client/pages/Files.page.js +45 -141
- package/dist/pages/api-client/pages/Files.page.js.map +1 -1
- package/dist/pages/api-client/pages/Shared.page.d.ts +1 -5
- package/dist/pages/api-client/pages/Shared.page.d.ts.map +1 -1
- package/dist/pages/api-client/pages/Shared.page.js +1 -40
- package/dist/pages/api-client/pages/Shared.page.js.map +1 -1
- package/dist/pages/demo/DemoPage.d.ts +7 -0
- package/dist/pages/demo/DemoPage.d.ts.map +1 -1
- package/dist/pages/demo/DemoPage.js +14 -0
- package/dist/pages/demo/DemoPage.js.map +1 -1
- package/dist/store/FileSystem.d.ts +90 -0
- package/dist/store/FileSystem.d.ts.map +1 -0
- package/dist/store/FileSystem.js +260 -0
- package/dist/store/FileSystem.js.map +1 -0
- package/dist/styles/global-styles.d.ts.map +1 -1
- package/dist/styles/global-styles.js +7 -0
- package/dist/styles/global-styles.js.map +1 -1
- package/dist/ui/button/SegmentedButtonsSet.d.ts +14 -0
- package/dist/ui/button/SegmentedButtonsSet.d.ts.map +1 -1
- package/dist/ui/button/SegmentedButtonsSet.js.map +1 -1
- package/dist/ui/icons/Icons.d.ts +2 -1
- package/dist/ui/icons/Icons.d.ts.map +1 -1
- package/dist/ui/icons/Icons.js +1 -0
- package/dist/ui/icons/Icons.js.map +1 -1
- package/dist/ui/list/UiDropdownList.d.ts +9 -1
- package/dist/ui/list/UiDropdownList.d.ts.map +1 -1
- package/dist/ui/list/UiDropdownList.js +39 -17
- package/dist/ui/list/UiDropdownList.js.map +1 -1
- package/dist/ui/list/UiList.d.ts +6 -1
- package/dist/ui/list/UiList.d.ts.map +1 -1
- package/dist/ui/list/UiList.js +24 -9
- package/dist/ui/list/UiList.js.map +1 -1
- package/dist/ui/notification/SnackNotifications.d.ts +1 -0
- package/dist/ui/notification/SnackNotifications.d.ts.map +1 -1
- package/dist/ui/notification/SnackNotifications.js +7 -0
- package/dist/ui/notification/SnackNotifications.js.map +1 -1
- package/dist/ui/table/DataTable.d.ts +4 -0
- package/dist/ui/table/DataTable.d.ts.map +1 -1
- package/dist/ui/table/DataTable.js +23 -1
- package/dist/ui/table/DataTable.js.map +1 -1
- package/package.json +1 -1
- package/src/bindings/base/FileBindings.ts +25 -1
- package/src/bindings/base/StoreBindings.ts +16 -73
- package/src/bindings/web/WebFileBindings.ts +1 -1
- package/src/define/http/certificate-add.ts +12 -0
- package/src/define/store/file-picker.ts +12 -0
- package/src/define/{files → store}/share-file.ts +2 -2
- package/src/define/ui/ui-segmented-button-set.ts +1 -1
- package/src/elements/authorization/ui/CC.styles.ts +4 -9
- package/src/elements/authorization/ui/CcAuthorization.ts +67 -167
- package/src/elements/http/CertificateAdd.element.ts +443 -0
- package/src/elements/http/CertificateAdd.styles.ts +61 -0
- package/src/elements/project/ProjectRunReport.ts +2 -1
- package/src/elements/store/FilePicker.element.ts +297 -0
- package/src/elements/store/FilePicker.styles.ts +73 -0
- package/src/elements/store/FilesLib.ts +32 -0
- package/src/events/EventTypes.ts +8 -7
- package/src/events/Events.ts +2 -0
- package/src/events/FilesystemEvents.ts +63 -0
- package/src/events/HttpClientEvents.ts +0 -2
- package/src/events/StoreEvents.ts +21 -1
- package/src/http-client/idb/Arc18DataUpgrade.ts +84 -84
- package/src/http-client/store/StoreBroadcast.ts +0 -8
- package/src/lib/files/FileUtils.ts +12 -0
- package/src/mixins/RouteMixin.ts +8 -1
- package/src/pages/ApplicationScreen.ts +5 -3
- package/src/pages/api-client/ApiClient.screen.ts +42 -33
- package/src/pages/api-client/ApiClient.styles.ts +0 -12
- package/src/pages/api-client/Authenticate.screen.ts +2 -2
- package/src/pages/api-client/pages/Files.page.ts +48 -164
- package/src/pages/api-client/pages/Shared.page.ts +2 -40
- package/src/pages/demo/DemoPage.ts +17 -0
- package/src/store/FileSystem.ts +325 -0
- package/src/styles/global-styles.ts +7 -0
- package/src/ui/button/SegmentedButtonsSet.ts +16 -1
- package/src/ui/icons/Icons.ts +2 -1
- package/src/ui/list/UiDropdownList.ts +44 -17
- package/src/ui/list/UiList.ts +26 -10
- package/src/ui/notification/SnackNotifications.ts +8 -0
- package/src/ui/table/DataTable.ts +29 -3
- package/test/elements/http/BodyFormdataEditorElement.test.ts +458 -454
- package/test/elements/http/BodyMultipartEditorElement.test.ts +609 -605
- package/test/elements/http/BodyRawEditorElement.test.ts +60 -56
- package/test/elements/http/CertificateAdd.test.ts +430 -0
- package/test/elements/store/FilePicker.test.ts +241 -0
- package/test/env.js +3 -0
- package/test/events/EventTypes.test.ts +0 -22
- package/test/helpers/StoreHelper.ts +390 -0
- package/test/helpers/UiMock.ts +19 -2
- package/tsconfig.eslint.json +3 -1
- package/web-test-runner.config.mjs +50 -3
- package/dist/define/files/share-file.d.ts.map +0 -1
- package/dist/define/files/share-file.js.map +0 -1
- package/dist/elements/files/ShareFile.d.ts.map +0 -1
- package/dist/elements/files/ShareFile.js.map +0 -1
- package/dist/elements/files/ShareFile.styles.d.ts.map +0 -1
- package/dist/events/http-client/models/CertificatesEvents.d.ts +0 -12
- package/dist/events/http-client/models/CertificatesEvents.d.ts.map +0 -1
- package/dist/events/http-client/models/CertificatesEvents.js +0 -18
- package/dist/events/http-client/models/CertificatesEvents.js.map +0 -1
- package/dist/http-client/idb/AuthDataModel.d.ts +0 -60
- package/dist/http-client/idb/AuthDataModel.d.ts.map +0 -1
- package/dist/http-client/idb/AuthDataModel.js +0 -150
- package/dist/http-client/idb/AuthDataModel.js.map +0 -1
- package/dist/http-client/idb/HostsModel.d.ts +0 -25
- package/dist/http-client/idb/HostsModel.d.ts.map +0 -1
- package/dist/http-client/idb/HostsModel.js +0 -82
- package/dist/http-client/idb/HostsModel.js.map +0 -1
- package/dist/http-client/idb/LegacyMockedStore.d.ts +0 -214
- package/dist/http-client/idb/LegacyMockedStore.d.ts.map +0 -1
- package/dist/http-client/idb/LegacyMockedStore.js +0 -486
- package/dist/http-client/idb/LegacyMockedStore.js.map +0 -1
- package/src/events/http-client/models/CertificatesEvents.ts +0 -23
- package/src/http-client/idb/AuthDataModel.ts +0 -175
- package/src/http-client/idb/HostsModel.ts +0 -125
- package/src/http-client/idb/LegacyMockedStore.ts +0 -544
- package/test/apic-ui.test.ts +0 -31
- /package/dist/elements/{files → store}/ShareFile.styles.d.ts +0 -0
- /package/dist/elements/{files → store}/ShareFile.styles.js +0 -0
- /package/src/elements/{files/ShareFile.ts → store/ShareFile.element.ts} +0 -0
- /package/src/elements/{files → store}/ShareFile.styles.ts +0 -0
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
2
|
export default css `
|
|
3
|
-
.cert-meta {
|
|
4
|
-
display: inline-flex;
|
|
5
|
-
align-items: center;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
3
|
:host {
|
|
9
|
-
max-height: 300px;
|
|
10
4
|
display: flex;
|
|
11
5
|
flex-direction: column;
|
|
12
6
|
}
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
.certificate-info {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
margin-top: 20px;
|
|
17
12
|
}
|
|
18
13
|
`;
|
|
19
14
|
//# sourceMappingURL=CC.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CC.styles.js","sourceRoot":"","sources":["../../../../src/elements/authorization/ui/CC.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,eAAe,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"CC.styles.js","sourceRoot":"","sources":["../../../../src/elements/authorization/ui/CC.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,eAAe,GAAG,CAAA;;;;;;;;;;;CAWjB,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport default css`\n:host {\n display: flex;\n flex-direction: column;\n}\n\n.certificate-info {\n display: flex;\n align-items: center;\n margin-top: 20px;\n}\n`;\n"]}
|
|
@@ -1,37 +1,22 @@
|
|
|
1
1
|
import { nothing, TemplateResult } from "lit";
|
|
2
|
-
import {
|
|
3
|
-
import '@github/relative-time-element';
|
|
2
|
+
import { ICCAuthorization, HttpCertificate } from '@api-client/core/build/browser.js';
|
|
4
3
|
import { Authorization } from "./Authorization.js";
|
|
4
|
+
import type { FilePickerClosingReason } from "../../store/FilePicker.element.js";
|
|
5
|
+
import '../../../define/ui/ui-dropdown-list.js';
|
|
5
6
|
import '../../../define/ui/ui-button.js';
|
|
6
|
-
import '../../../define/ui/ui-
|
|
7
|
+
import '../../../define/ui/ui-icon-button.js';
|
|
8
|
+
import '../../../define/ui/ui-icon.js';
|
|
9
|
+
import '../../../define/store/file-picker.js';
|
|
7
10
|
export default class CcAuthorization extends Authorization {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
disconnectedCallback(): void;
|
|
15
|
-
protected handleBroadcast(e: MessageEvent): void;
|
|
16
|
-
protected handleCreated(event: BroadcastCreatedEvent): void;
|
|
17
|
-
protected handleDeleted(event: DeletedBroadcastEvent): void;
|
|
18
|
-
protected queryCertificates(): Promise<void>;
|
|
19
|
-
protected handleSelected(e: Event): void;
|
|
11
|
+
selectorRendered: boolean;
|
|
12
|
+
get config(): ICCAuthorization;
|
|
13
|
+
protected handleClose(e: CustomEvent<FilePickerClosingReason>): void;
|
|
14
|
+
setCertificate(key: string): Promise<void>;
|
|
15
|
+
protected handleDropDownOpen(): void;
|
|
16
|
+
protected handleClearCertificate(): void;
|
|
20
17
|
render(): TemplateResult;
|
|
21
18
|
protected renderEditor(): TemplateResult | typeof nothing;
|
|
22
|
-
protected
|
|
23
|
-
protected
|
|
24
|
-
protected renderList(items: HttpCertificate[], current?: ICertificate): TemplateResult;
|
|
25
|
-
protected renderNoneItem(selectedKey?: string): TemplateResult;
|
|
26
|
-
/**
|
|
27
|
-
* @param item The item to render
|
|
28
|
-
* @returns The template for the dropdown item.
|
|
29
|
-
*/
|
|
30
|
-
protected renderCertItem(item: HttpCertificate, selectedKey?: string): TemplateResult;
|
|
31
|
-
/**
|
|
32
|
-
* @param created The certificate created time.
|
|
33
|
-
* @returns The template for the cert time element.
|
|
34
|
-
*/
|
|
35
|
-
protected renderDateTime(created?: number): TemplateResult;
|
|
19
|
+
protected renderSelector(): TemplateResult;
|
|
20
|
+
protected renderSelection(certificate: HttpCertificate): TemplateResult;
|
|
36
21
|
}
|
|
37
22
|
//# sourceMappingURL=CcAuthorization.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CcAuthorization.d.ts","sourceRoot":"","sources":["../../../../src/elements/authorization/ui/CcAuthorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"CcAuthorization.d.ts","sourceRoot":"","sources":["../../../../src/elements/authorization/ui/CcAuthorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AACpD,OAAO,EACL,gBAAgB,EAAE,eAAe,EAClC,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAEjF,OAAO,wCAAwC,CAAC;AAChD,OAAO,iCAAiC,CAAC;AACzC,OAAO,sCAAsC,CAAC;AAC9C,OAAO,+BAA+B,CAAC;AACvC,OAAO,sCAAsC,CAAC;AAE9C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAC/C,gBAAgB,UAAS;IAElC,IAAI,MAAM,IAAI,gBAAgB,CAS7B;IAED,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,WAAW,CAAC,uBAAuB,CAAC,GAAG,IAAI;IAa9D,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAahD,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAOpC,SAAS,CAAC,sBAAsB,IAAI,IAAI;IAO/B,MAAM,IAAI,cAAc;IAOjC,SAAS,CAAC,YAAY,IAAI,cAAc,GAAG,OAAO,OAAO;IAWzD,SAAS,CAAC,cAAc,IAAI,cAAc;IAa1C,SAAS,CAAC,eAAe,CAAC,WAAW,EAAE,eAAe,GAAG,cAAc;CAcxE"}
|
|
@@ -1,114 +1,65 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import { html, nothing } from "lit";
|
|
3
|
+
import { Events as CoreEvents, CertificateFileKind, } from '@api-client/core/build/browser.js';
|
|
3
4
|
import { state } from "lit/decorators.js";
|
|
4
|
-
import { Events as CoreEvents, } from '@api-client/core/build/browser.js';
|
|
5
|
-
import '@github/relative-time-element';
|
|
6
5
|
import { Authorization } from "./Authorization.js";
|
|
7
6
|
import { Events } from "../../../events/Events.js";
|
|
8
|
-
import
|
|
7
|
+
import '../../../define/ui/ui-dropdown-list.js';
|
|
9
8
|
import '../../../define/ui/ui-button.js';
|
|
10
|
-
import '../../../define/ui/ui-
|
|
9
|
+
import '../../../define/ui/ui-icon-button.js';
|
|
10
|
+
import '../../../define/ui/ui-icon.js';
|
|
11
|
+
import '../../../define/store/file-picker.js';
|
|
11
12
|
export default class CcAuthorization extends Authorization {
|
|
12
13
|
constructor() {
|
|
13
|
-
super();
|
|
14
|
-
this.
|
|
15
|
-
this.channel = new BroadcastChannel(StoreBroadcast.certificates);
|
|
16
|
-
this.handleBroadcast = this.handleBroadcast.bind(this);
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.selectorRendered = false;
|
|
17
16
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
disconnectedCallback() {
|
|
24
|
-
super.disconnectedCallback();
|
|
25
|
-
this.channel.removeEventListener('message', this.handleBroadcast);
|
|
26
|
-
}
|
|
27
|
-
handleBroadcast(e) {
|
|
28
|
-
const event = e.data;
|
|
29
|
-
switch (event.operation) {
|
|
30
|
-
case 'created':
|
|
31
|
-
this.handleCreated(event);
|
|
32
|
-
break;
|
|
33
|
-
case 'deleted':
|
|
34
|
-
this.handleDeleted(event);
|
|
35
|
-
break;
|
|
36
|
-
default:
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
handleCreated(event) {
|
|
40
|
-
const cert = event.data;
|
|
41
|
-
if (!this.items) {
|
|
42
|
-
this.items = [];
|
|
43
|
-
}
|
|
44
|
-
const index = this.items.findIndex(i => i.key === cert.key);
|
|
45
|
-
if (index >= 0) {
|
|
46
|
-
this.items[index] = cert;
|
|
17
|
+
get config() {
|
|
18
|
+
const { authorization } = this;
|
|
19
|
+
if (!authorization) {
|
|
20
|
+
return {};
|
|
47
21
|
}
|
|
48
|
-
|
|
49
|
-
|
|
22
|
+
if (!authorization.config) {
|
|
23
|
+
authorization.config = {};
|
|
50
24
|
}
|
|
51
|
-
|
|
25
|
+
return authorization.config;
|
|
52
26
|
}
|
|
53
|
-
|
|
54
|
-
|
|
27
|
+
handleClose(e) {
|
|
28
|
+
const { canceled, file } = e.detail;
|
|
29
|
+
if (canceled) {
|
|
55
30
|
return;
|
|
56
31
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
32
|
+
this.setCertificate(file.key);
|
|
33
|
+
CoreEvents.Telemetry.event({
|
|
34
|
+
category: 'Certificates',
|
|
35
|
+
action: 'Authorization',
|
|
36
|
+
label: 'selected-certificate'
|
|
37
|
+
}, this);
|
|
63
38
|
}
|
|
64
|
-
async
|
|
65
|
-
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
this.querying = true;
|
|
39
|
+
async setCertificate(key) {
|
|
40
|
+
let result;
|
|
69
41
|
try {
|
|
70
|
-
|
|
71
|
-
if (!data) {
|
|
72
|
-
this.items = undefined;
|
|
73
|
-
throw new Error(`Certificates query not handled by the store.`);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
this.items = data.items;
|
|
77
|
-
}
|
|
78
|
-
catch (cause) {
|
|
79
|
-
this.loadingError = cause.message;
|
|
42
|
+
result = await Events.Store.File.read(key, true, this);
|
|
80
43
|
}
|
|
81
|
-
|
|
82
|
-
this.querying = false;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
handleSelected(e) {
|
|
86
|
-
const { authorization } = this;
|
|
87
|
-
if (!authorization) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const radio = e.target;
|
|
91
|
-
const { checked, value } = radio;
|
|
92
|
-
if (!checked) {
|
|
44
|
+
catch (_) {
|
|
93
45
|
return;
|
|
94
46
|
}
|
|
95
|
-
const config =
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
config.certificate = cert;
|
|
47
|
+
const { config } = this;
|
|
48
|
+
config.certificate = result;
|
|
49
|
+
this.requestUpdate();
|
|
50
|
+
this.notifyChange();
|
|
51
|
+
}
|
|
52
|
+
handleDropDownOpen() {
|
|
53
|
+
this.selectorRendered = true;
|
|
54
|
+
if (this.isUpdatePending) {
|
|
55
|
+
this.scheduleUpdate();
|
|
105
56
|
}
|
|
57
|
+
}
|
|
58
|
+
handleClearCertificate() {
|
|
59
|
+
const { config } = this;
|
|
60
|
+
delete config.certificate;
|
|
61
|
+
this.requestUpdate();
|
|
106
62
|
this.notifyChange();
|
|
107
|
-
CoreEvents.Telemetry.event({
|
|
108
|
-
category: 'Certificates',
|
|
109
|
-
action: 'Authorization',
|
|
110
|
-
label: 'selected-certificate'
|
|
111
|
-
}, this);
|
|
112
63
|
}
|
|
113
64
|
render() {
|
|
114
65
|
return html `
|
|
@@ -117,85 +68,43 @@ export default class CcAuthorization extends Authorization {
|
|
|
117
68
|
`;
|
|
118
69
|
}
|
|
119
70
|
renderEditor() {
|
|
120
|
-
const {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
const hasItems = !!items && !!items.length;
|
|
125
|
-
if (!loadingError && !hasItems) {
|
|
126
|
-
return html `
|
|
127
|
-
${this.renderEmptyState()}
|
|
128
|
-
`;
|
|
129
|
-
}
|
|
130
|
-
const config = authorization.config || {};
|
|
71
|
+
const { config } = this;
|
|
72
|
+
const { certificate } = config;
|
|
73
|
+
// Note, the <form> element is required by the Authorization class for validation.
|
|
131
74
|
return html `
|
|
132
|
-
|
|
133
|
-
${
|
|
134
|
-
|
|
135
|
-
${this.renderList(items, config.certificate)}
|
|
136
|
-
</form>
|
|
137
|
-
` : ''}
|
|
75
|
+
<form autocomplete="on" class="auth-form cc-auth"></form>
|
|
76
|
+
${this.renderSelector()}
|
|
77
|
+
${certificate ? this.renderSelection(certificate) : nothing}
|
|
138
78
|
`;
|
|
139
79
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
renderEmptyState() {
|
|
144
|
-
return html `<p class="empty-screen body-large">There are no certificates installed in this application.</p>`;
|
|
145
|
-
}
|
|
146
|
-
renderList(items, current) {
|
|
147
|
-
const currentKey = current && current.key;
|
|
80
|
+
renderSelector() {
|
|
81
|
+
const { selectorRendered } = this;
|
|
82
|
+
const kinds = [CertificateFileKind];
|
|
148
83
|
return html `
|
|
149
|
-
|
|
150
|
-
${
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return html `
|
|
155
|
-
<label class="label-medium">
|
|
156
|
-
<ui-radio name="certificate" value="" .checked="${!selectedKey}" @change="${this.handleSelected}"></ui-radio>
|
|
157
|
-
None
|
|
158
|
-
</label>
|
|
159
|
-
`;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* @param item The item to render
|
|
163
|
-
* @returns The template for the dropdown item.
|
|
164
|
-
*/
|
|
165
|
-
renderCertItem(item, selectedKey) {
|
|
166
|
-
return html `
|
|
167
|
-
<div class="cert-item">
|
|
168
|
-
<label>
|
|
169
|
-
<ui-radio name="certificate" value="${item.key}" .checked="${item.key === selectedKey}" @change="${this.handleSelected}"></ui-radio>
|
|
170
|
-
<div class="cert-meta">
|
|
171
|
-
<span class="label-medium">${item.name}</span>
|
|
172
|
-
<span class="body-small">Added: ${this.renderDateTime(item.created)}</span>
|
|
173
|
-
</div>
|
|
174
|
-
</label>
|
|
84
|
+
<div class="selector">
|
|
85
|
+
<ui-dropdown-list @open="${this.handleDropDownOpen}">
|
|
86
|
+
<ui-button class="dropdown-trigger" type="tonal">Select a certificate</ui-button>
|
|
87
|
+
${selectorRendered ? html `<file-picker slot="dropdown" .kinds="${kinds}" @close="${this.handleClose}"></file-picker>` : nothing}
|
|
88
|
+
</ui-dropdown-list>
|
|
175
89
|
</div>
|
|
176
90
|
`;
|
|
177
91
|
}
|
|
178
|
-
|
|
179
|
-
* @param created The certificate created time.
|
|
180
|
-
* @returns The template for the cert time element.
|
|
181
|
-
*/
|
|
182
|
-
renderDateTime(created) {
|
|
183
|
-
if (!created) {
|
|
184
|
-
return html `<span>Unknown</span>`;
|
|
185
|
-
}
|
|
186
|
-
const d = new Date(created);
|
|
92
|
+
renderSelection(certificate) {
|
|
187
93
|
return html `
|
|
188
|
-
<
|
|
94
|
+
<div class="certificate-info body-medium">
|
|
95
|
+
Current certificate: ${certificate.name}
|
|
96
|
+
<ui-icon-button
|
|
97
|
+
aria-label="Remove certificate from authorization"
|
|
98
|
+
title="Remove certificate from authorization"
|
|
99
|
+
@click="${this.handleClearCertificate}"
|
|
100
|
+
>
|
|
101
|
+
<ui-icon role="presentation" icon="deleteOutline"></ui-icon>
|
|
102
|
+
</ui-icon-button>
|
|
103
|
+
</div>
|
|
189
104
|
`;
|
|
190
105
|
}
|
|
191
106
|
}
|
|
192
107
|
__decorate([
|
|
193
108
|
state()
|
|
194
|
-
], CcAuthorization.prototype, "
|
|
195
|
-
__decorate([
|
|
196
|
-
state()
|
|
197
|
-
], CcAuthorization.prototype, "querying", void 0);
|
|
198
|
-
__decorate([
|
|
199
|
-
state()
|
|
200
|
-
], CcAuthorization.prototype, "loadingError", void 0);
|
|
109
|
+
], CcAuthorization.prototype, "selectorRendered", void 0);
|
|
201
110
|
//# sourceMappingURL=CcAuthorization.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CcAuthorization.js","sourceRoot":"","sources":["../../../../src/elements/authorization/ui/CcAuthorization.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, nothing, TemplateResult } from \"lit\";\nimport { state } from \"lit/decorators.js\";\nimport {\n ICCAuthorization, HttpCertificate, Events as CoreEvents,\n ICertificate,\n BroadcastEvent,\n BroadcastCreatedEvent,\n DeletedBroadcastEvent,\n} from '@api-client/core/build/browser.js';\nimport '@github/relative-time-element';\nimport { Authorization } from \"./Authorization.js\";\nimport { Events } from \"../../../events/Events.js\";\nimport type RadioElement from \"../../../ui/input/RadioElement.js\";\nimport { StoreBroadcast } from \"../../../http-client/store/StoreBroadcast.js\";\nimport '../../../define/ui/ui-button.js';\nimport '../../../define/ui/ui-radio.js';\n\nexport default class CcAuthorization extends Authorization {\n @state() items?: ICertificate[];\n\n @state() querying = false;\n\n @state() loadingError?: string;\n\n channel = new BroadcastChannel(StoreBroadcast.certificates);\n\n constructor() {\n super();\n\n this.handleBroadcast = this.handleBroadcast.bind(this);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.channel.addEventListener('message', this.handleBroadcast);\n this.queryCertificates();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.channel.removeEventListener('message', this.handleBroadcast);\n }\n\n protected handleBroadcast(e: MessageEvent): void {\n const event = e.data as BroadcastEvent;\n switch (event.operation) {\n case 'created': this.handleCreated(event as BroadcastCreatedEvent); break;\n case 'deleted': this.handleDeleted(event as DeletedBroadcastEvent); break;\n default:\n }\n }\n\n protected handleCreated(event: BroadcastCreatedEvent): void {\n const cert = event.data as ICertificate;\n if (!this.items) {\n this.items = [];\n }\n const index = this.items.findIndex(i => i.key === cert.key);\n if (index >= 0) {\n this.items[index] = cert;\n } else {\n this.items.push(cert);\n }\n this.requestUpdate();\n }\n\n protected handleDeleted(event: DeletedBroadcastEvent): void {\n if (!this.items) {\n return;\n }\n const { key } = event;\n const index = this.items.findIndex(i => i.key === key);\n if (index >= 0) {\n this.items.splice(index, 1);\n this.requestUpdate();\n }\n }\n\n protected async queryCertificates(): Promise<void> {\n if (this.querying) {\n return;\n }\n this.querying = true;\n try {\n const data = await Events.HttpClient.Model.Certificate.list({ limit: 100, space: \"\" }); // the space should be filled by the bindings / hosting app\n if (!data) {\n this.items = undefined;\n throw new Error(`Certificates query not handled by the store.`);\n return;\n }\n this.items = data.items;\n } catch (cause) {\n this.loadingError = (cause as Error).message;\n } finally {\n this.querying = false;\n }\n }\n\n protected handleSelected(e: Event): void {\n const { authorization } = this;\n if (!authorization) {\n return;\n }\n\n const radio = e.target as RadioElement;\n const { checked, value } = radio;\n if (!checked) {\n return;\n }\n const config = authorization.config as ICCAuthorization || {} as ICCAuthorization;\n if (value === '') {\n delete config.certificate;\n } else {\n const cert = this.items?.find(i => i.key === value);\n if (!cert) {\n return;\n }\n config.certificate = cert;\n }\n this.notifyChange();\n\n CoreEvents.Telemetry.event({\n category: 'Certificates',\n action: 'Authorization',\n label: 'selected-certificate'\n }, this);\n }\n\n override render(): TemplateResult {\n return html`\n ${this.renderHeader()}\n ${this.renderEditor()}\n `;\n }\n\n protected renderEditor(): TemplateResult | typeof nothing {\n const { authorization, loadingError, items } = this;\n if (!authorization) {\n return nothing;\n }\n const hasItems = !!items && !!items.length;\n if (!loadingError && !hasItems) {\n return html`\n ${this.renderEmptyState()}\n `;\n }\n const config = authorization.config as ICCAuthorization || {} as ICCAuthorization;\n return html`\n ${loadingError ? this.renderErrorState(loadingError) : ''}\n ${hasItems ? html`\n <form autocomplete=\"on\" class=\"auth-form basic-auth\">\n ${this.renderList(items, config.certificate)}\n </form>\n ` : ''}\n `;\n }\n\n protected renderErrorState(error: string): TemplateResult {\n return html`<p class=\"error-message\">Unable to load certificates: ${error}.</p>`;\n }\n\n protected renderEmptyState(): TemplateResult {\n return html`<p class=\"empty-screen body-large\">There are no certificates installed in this application.</p>`;\n }\n\n protected renderList(items: HttpCertificate[], current?: ICertificate): TemplateResult {\n const currentKey = current && current.key;\n return html`\n ${this.renderNoneItem(currentKey)}\n ${items.map((item) => this.renderCertItem(item, currentKey))}\n `;\n }\n\n protected renderNoneItem(selectedKey?: string): TemplateResult {\n return html`\n <label class=\"label-medium\">\n <ui-radio name=\"certificate\" value=\"\" .checked=\"${!selectedKey}\" @change=\"${this.handleSelected}\"></ui-radio>\n None\n </label>\n `;\n }\n\n /**\n * @param item The item to render\n * @returns The template for the dropdown item.\n */\n protected renderCertItem(item: HttpCertificate, selectedKey?: string): TemplateResult {\n return html`\n <div class=\"cert-item\">\n <label>\n <ui-radio name=\"certificate\" value=\"${item.key}\" .checked=\"${item.key === selectedKey}\" @change=\"${this.handleSelected}\"></ui-radio>\n <div class=\"cert-meta\">\n <span class=\"label-medium\">${item.name}</span>\n <span class=\"body-small\">Added: ${this.renderDateTime(item.created)}</span>\n </div>\n </label>\n </div>\n `;\n }\n\n /**\n * @param created The certificate created time.\n * @returns The template for the cert time element.\n */\n protected renderDateTime(created?: number): TemplateResult {\n if (!created) {\n return html`<span>Unknown</span>`;\n }\n const d = new Date(created);\n return html`\n <relative-time datetime=\"${d.toISOString()}\"></relative-time>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CcAuthorization.js","sourceRoot":"","sources":["../../../../src/elements/authorization/ui/CcAuthorization.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAkB,MAAM,KAAK,CAAC;AACpD,OAAO,EAC8B,MAAM,IAAI,UAAU,EAAE,mBAAmB,GAC7E,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,wCAAwC,CAAC;AAChD,OAAO,iCAAiC,CAAC;AACzC,OAAO,sCAAsC,CAAC;AAC9C,OAAO,+BAA+B,CAAC;AACvC,OAAO,sCAAsC,CAAC;AAE9C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,aAAa;IAA1D;;QACW,qBAAgB,GAAG,KAAK,CAAC;IAkGpC,CAAC;IAhGC,IAAI,MAAM;QACR,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,aAAa,EAAE;YAClB,OAAO,EAAG,CAAC;SACZ;QACD,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;YACzB,aAAa,CAAC,MAAM,GAAG,EAAsB,CAAC;SAC/C;QACD,OAAO,aAAa,CAAC,MAA0B,CAAC;IAClD,CAAC;IAES,WAAW,CAAC,CAAuC;QAC3D,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;QACpC,IAAI,QAAQ,EAAE;YACZ,OAAO;SACR;QACD,IAAI,CAAC,cAAc,CAAE,IAAc,CAAC,GAAG,CAAC,CAAC;QACzC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;YACzB,QAAQ,EAAE,cAAc;YACxB,MAAM,EAAE,eAAe;YACvB,KAAK,EAAE,sBAAsB;SAC9B,EAAE,IAAI,CAAC,CAAC;IACX,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAW;QAC9B,IAAI,MAAe,CAAC;QACpB,IAAI;YACF,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;SACxD;QAAC,OAAO,CAAC,EAAE;YACV,OAAO;SACR;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACxB,MAAM,CAAC,WAAW,GAAG,MAAsB,CAAC;QAC5C,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAES,kBAAkB;QAC1B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,cAAc,EAAE,CAAC;SACvB;IACH,CAAC;IAES,sBAAsB;QAC9B,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACxB,OAAO,MAAM,CAAC,WAAW,CAAC;QAC1B,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;MACT,IAAI,CAAC,YAAY,EAAE;MACnB,IAAI,CAAC,YAAY,EAAE;KACpB,CAAC;IACJ,CAAC;IAES,YAAY;QACpB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;QAC/B,kFAAkF;QAClF,OAAO,IAAI,CAAA;;MAET,IAAI,CAAC,cAAc,EAAE;MACrB,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO;KAC1D,CAAC;IACJ,CAAC;IAES,cAAc;QACtB,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;QAClC,MAAM,KAAK,GAAiC,CAAC,mBAAmB,CAAC,CAAC;QAClE,OAAO,IAAI,CAAA;;iCAEkB,IAAI,CAAC,kBAAkB;;UAE9C,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAA,wCAAwC,KAAK,aAAa,IAAI,CAAC,WAAW,kBAAkB,CAAC,CAAC,CAAC,OAAO;;;KAGlI,CAAC;IACJ,CAAC;IAES,eAAe,CAAC,WAA4B;QACpD,OAAO,IAAI,CAAA;;6BAEc,WAAW,CAAC,IAAI;;;;kBAI3B,IAAI,CAAC,sBAAsB;;;;;KAKxC,CAAC;IACJ,CAAC;CACF;AAlGU;IAAR,KAAK,EAAE;yDAA0B","sourcesContent":["import { html, nothing, TemplateResult } from \"lit\";\nimport {\n ICCAuthorization, HttpCertificate, Events as CoreEvents, CertificateFileKind, ICertificate, IFile,\n} from '@api-client/core/build/browser.js';\nimport { state } from \"lit/decorators.js\";\nimport { Authorization } from \"./Authorization.js\";\nimport type { FilePickerClosingReason } from \"../../store/FilePicker.element.js\";\nimport { Events } from \"../../../events/Events.js\";\nimport '../../../define/ui/ui-dropdown-list.js';\nimport '../../../define/ui/ui-button.js';\nimport '../../../define/ui/ui-icon-button.js';\nimport '../../../define/ui/ui-icon.js';\nimport '../../../define/store/file-picker.js';\n\nexport default class CcAuthorization extends Authorization {\n @state() selectorRendered = false;\n\n get config(): ICCAuthorization {\n const { authorization } = this;\n if (!authorization) {\n return { };\n }\n if (!authorization.config) {\n authorization.config = {} as ICCAuthorization;\n }\n return authorization.config as ICCAuthorization;\n }\n\n protected handleClose(e: CustomEvent<FilePickerClosingReason>): void {\n const { canceled, file } = e.detail;\n if (canceled) {\n return;\n }\n this.setCertificate((file as IFile).key);\n CoreEvents.Telemetry.event({\n category: 'Certificates',\n action: 'Authorization',\n label: 'selected-certificate'\n }, this);\n }\n\n async setCertificate(key: string): Promise<void> {\n let result: unknown;\n try {\n result = await Events.Store.File.read(key, true, this);\n } catch (_) {\n return;\n }\n const { config } = this;\n config.certificate = result as ICertificate;\n this.requestUpdate();\n this.notifyChange();\n }\n\n protected handleDropDownOpen(): void {\n this.selectorRendered = true;\n if (this.isUpdatePending) {\n this.scheduleUpdate();\n }\n }\n\n protected handleClearCertificate(): void {\n const { config } = this;\n delete config.certificate;\n this.requestUpdate();\n this.notifyChange();\n }\n\n override render(): TemplateResult {\n return html`\n ${this.renderHeader()}\n ${this.renderEditor()}\n `;\n }\n\n protected renderEditor(): TemplateResult | typeof nothing {\n const { config } = this;\n const { certificate } = config;\n // Note, the <form> element is required by the Authorization class for validation.\n return html`\n <form autocomplete=\"on\" class=\"auth-form cc-auth\"></form>\n ${this.renderSelector()}\n ${certificate ? this.renderSelection(certificate) : nothing}\n `;\n }\n\n protected renderSelector(): TemplateResult {\n const { selectorRendered } = this;\n const kinds: typeof CertificateFileKind[] = [CertificateFileKind];\n return html`\n <div class=\"selector\">\n <ui-dropdown-list @open=\"${this.handleDropDownOpen}\">\n <ui-button class=\"dropdown-trigger\" type=\"tonal\">Select a certificate</ui-button>\n ${selectorRendered ? html`<file-picker slot=\"dropdown\" .kinds=\"${kinds}\" @close=\"${this.handleClose}\"></file-picker>` : nothing}\n </ui-dropdown-list>\n </div>\n `;\n }\n\n protected renderSelection(certificate: HttpCertificate): TemplateResult {\n return html`\n <div class=\"certificate-info body-medium\">\n Current certificate: ${certificate.name}\n <ui-icon-button \n aria-label=\"Remove certificate from authorization\" \n title=\"Remove certificate from authorization\"\n @click=\"${this.handleClearCertificate}\"\n >\n <ui-icon role=\"presentation\" icon=\"deleteOutline\"></ui-icon>\n </ui-icon-button>\n </div>\n `;\n }\n}\n"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/// <reference types="pouchdb-core" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { CertificateType } from "@api-client/core/build/browser.js";
|
|
4
|
+
import { CSSResult, nothing, TemplateResult } from "lit";
|
|
5
|
+
import ApiElement from "../ApiElement.js";
|
|
6
|
+
import type { ISegmentedButtonSelectionDetail } from '../../ui/button/SegmentedButtonsSet.js';
|
|
7
|
+
import '../../define/ui/ui-segmented-button.js';
|
|
8
|
+
import '../../define/ui/ui-segmented-button-set.js';
|
|
9
|
+
import '../../define/ui/ui-text-field.js';
|
|
10
|
+
import '../../define/ui/ui-button.js';
|
|
11
|
+
import '../../define/ui/ui-icon.js';
|
|
12
|
+
import '../../define/ui/ui-progress.js';
|
|
13
|
+
interface CertificateInfo {
|
|
14
|
+
fileName: string;
|
|
15
|
+
contents: ArrayBuffer | Buffer;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* An element that renders a certificate import UI.
|
|
19
|
+
*
|
|
20
|
+
* Notes for implementation:
|
|
21
|
+
* - `p12` is a single file, may have a passphrase
|
|
22
|
+
* - `pem` is 2 files: the certificate and the key
|
|
23
|
+
* - `pem` may have a `passphrase` on the key but not on the certificate.
|
|
24
|
+
*/
|
|
25
|
+
export default class CertificateAdd extends ApiElement {
|
|
26
|
+
static get styles(): CSSResult[];
|
|
27
|
+
/**
|
|
28
|
+
* The type of the certificate to import.
|
|
29
|
+
* @attribute
|
|
30
|
+
*/
|
|
31
|
+
importType: CertificateType;
|
|
32
|
+
/**
|
|
33
|
+
* The parent folder where to insert the imported certificate.
|
|
34
|
+
* @attribute
|
|
35
|
+
*/
|
|
36
|
+
folder?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The current workspace for the file.
|
|
39
|
+
* @attribute
|
|
40
|
+
*/
|
|
41
|
+
space?: string;
|
|
42
|
+
/**
|
|
43
|
+
* When an IO operation is in progress.
|
|
44
|
+
*/
|
|
45
|
+
working?: boolean;
|
|
46
|
+
certificateFile?: CertificateInfo;
|
|
47
|
+
keyFile?: CertificateInfo;
|
|
48
|
+
/**
|
|
49
|
+
* The password for the certificate
|
|
50
|
+
*/
|
|
51
|
+
certificatePassword?: string;
|
|
52
|
+
/**
|
|
53
|
+
* The password for the key.
|
|
54
|
+
*/
|
|
55
|
+
keyPassword?: string;
|
|
56
|
+
/**
|
|
57
|
+
* The user entered certificate name.
|
|
58
|
+
*/
|
|
59
|
+
protected certificateName?: string;
|
|
60
|
+
get hasKeyImport(): boolean;
|
|
61
|
+
get hasCertificatePasswordInput(): boolean;
|
|
62
|
+
protected handleViewSelection(e: CustomEvent<ISegmentedButtonSelectionDetail>): void;
|
|
63
|
+
protected handleNameChange(e: Event): void;
|
|
64
|
+
protected handleCertificatePasswordChange(e: Event): void;
|
|
65
|
+
protected handleKeyPasswordChange(e: Event): void;
|
|
66
|
+
protected handleSelectCertificate(): void;
|
|
67
|
+
protected handleSelectKey(): void;
|
|
68
|
+
selectCertificateFLow(): Promise<void>;
|
|
69
|
+
selectKeyFLow(): Promise<void>;
|
|
70
|
+
protected isValidDropTarget(dt: DataTransfer): boolean;
|
|
71
|
+
protected handleFileDragEnter(e: DragEvent): void;
|
|
72
|
+
protected handleFileDragLeave(e: DragEvent): void;
|
|
73
|
+
protected handleFileDragOver(e: DragEvent): void;
|
|
74
|
+
protected handleFileDrop(e: DragEvent): void;
|
|
75
|
+
processDroppedFile(file: File, kind: 'certificate' | 'key'): Promise<void>;
|
|
76
|
+
protected handleCancel(): void;
|
|
77
|
+
protected handleImport(): void;
|
|
78
|
+
submit(): Promise<void>;
|
|
79
|
+
reportValidity(): boolean;
|
|
80
|
+
protected render(): TemplateResult;
|
|
81
|
+
protected renderViewToggle(): TemplateResult;
|
|
82
|
+
protected renderNameInput(): TemplateResult;
|
|
83
|
+
protected renderCertificateFile(): TemplateResult;
|
|
84
|
+
protected renderCertificatePasswordInput(): TemplateResult | typeof nothing;
|
|
85
|
+
protected renderKeyFile(): TemplateResult | typeof nothing;
|
|
86
|
+
protected renderKeyPasswordInput(): TemplateResult | typeof nothing;
|
|
87
|
+
protected renderImportButton(): TemplateResult;
|
|
88
|
+
protected renderProgress(): TemplateResult | typeof nothing;
|
|
89
|
+
}
|
|
90
|
+
export {};
|
|
91
|
+
//# sourceMappingURL=CertificateAdd.element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CertificateAdd.element.d.ts","sourceRoot":"","sources":["../../../src/elements/http/CertificateAdd.element.ts"],"names":[],"mappings":"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"}
|