@uxland/primary-shell 2.0.1-rc.2 → 2.1.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.
- package/dist/UI/components/patient-header/patient-header.d.ts +9 -0
- package/dist/UI/components/patient-header/template.d.ts +3 -0
- package/dist/UI/components/professional-header/professional-header.d.ts +9 -0
- package/dist/UI/components/professional-header/template.d.ts +3 -0
- package/dist/api/api.d.ts +2 -6
- package/dist/api/http-client/http-client.d.ts +6 -0
- package/dist/features/bootstrapper.d.ts +4 -0
- package/dist/features/get-patient-info/backend-adapter.d.ts +9 -0
- package/dist/features/get-patient-info/bootstrapper.d.ts +2 -0
- package/dist/features/get-patient-info/handler.d.ts +11 -0
- package/dist/features/get-patient-info/model.d.ts +7 -0
- package/dist/features/get-patient-info/request.d.ts +5 -0
- package/dist/features/get-user-info/backend-adapter.d.ts +9 -0
- package/dist/features/get-user-info/bootstrapper.d.ts +2 -0
- package/dist/features/get-user-info/handler.d.ts +11 -0
- package/dist/features/get-user-info/model.d.ts +8 -0
- package/dist/features/get-user-info/request.d.ts +5 -0
- package/dist/features/utils.d.ts +7 -0
- package/dist/index.js +12500 -8992
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +386 -345
- package/dist/index.umd.cjs.map +1 -1
- package/dist/infrastructure/ioc/container.d.ts +7 -0
- package/dist/infrastructure/ioc/types.d.ts +5 -0
- package/dist/plugin.d.ts +1 -1
- package/dist/style.css +1 -1
- package/package.json +18 -11
- package/src/UI/components/index.ts +2 -0
- package/src/UI/components/patient-header/patient-header.ts +28 -0
- package/src/UI/components/patient-header/styles.scss +25 -0
- package/src/UI/components/patient-header/template.ts +18 -0
- package/src/UI/components/primaria-shell/template.ts +4 -0
- package/src/UI/components/professional-header/professional-header.ts +27 -0
- package/src/UI/components/professional-header/styles.scss +25 -0
- package/src/UI/components/professional-header/template.ts +18 -0
- package/src/UI/fonts/fonts.css +48 -0
- package/src/UI/fonts/open-sans-v40-latin-300.woff2 +0 -0
- package/src/UI/fonts/open-sans-v40-latin-500.woff2 +0 -0
- package/src/UI/fonts/open-sans-v40-latin-600.woff2 +0 -0
- package/src/UI/fonts/open-sans-v40-latin-700.woff2 +0 -0
- package/src/UI/fonts/open-sans-v40-latin-800.woff2 +0 -0
- package/src/UI/fonts/open-sans-v40-latin-regular.woff2 +0 -0
- package/src/UI/shared-components/primaria-interaction/components/notifier-component.ts +2 -2
- package/src/UI/styles/index.css +18 -0
- package/src/api/api.ts +3 -13
- package/src/api/broker/factory.test.ts +8 -3
- package/src/api/broker/factory.ts +3 -0
- package/src/api/global-state/global-state.test.ts +1 -1
- package/src/api/global-state/global-state.ts +1 -1
- package/src/api/http-client/http-client.ts +14 -0
- package/src/features/bootstrapper.ts +16 -0
- package/src/features/get-patient-info/backend-adapter.ts +24 -0
- package/src/features/get-patient-info/bootstrapper.ts +17 -0
- package/src/features/get-patient-info/handler.ts +25 -0
- package/src/features/get-patient-info/model.ts +7 -0
- package/src/features/get-patient-info/request.ts +4 -0
- package/src/features/get-user-info/backend-adapter.ts +24 -0
- package/src/features/get-user-info/bootstrapper.ts +17 -0
- package/src/features/get-user-info/handler.ts +26 -0
- package/src/features/get-user-info/model.ts +8 -0
- package/src/features/get-user-info/request.ts +4 -0
- package/src/features/utils.ts +20 -0
- package/src/infrastructure/ioc/container.ts +14 -0
- package/src/infrastructure/ioc/types.ts +5 -0
- package/src/initializer.ts +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxland/primary-shell",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Primaria Shell",
|
|
5
5
|
"author": "UXLand <dev@uxland.es>",
|
|
6
6
|
"homepage": "https://github.com/uxland/harmonix/tree/app#readme",
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
"main": "src/index.ts",
|
|
10
10
|
"types": "dist/index.d.ts",
|
|
11
11
|
"module": "dist/index.js",
|
|
12
|
-
"files": [
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src"
|
|
15
|
+
],
|
|
13
16
|
"publishConfig": {
|
|
14
17
|
"access": "public",
|
|
15
18
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -18,18 +21,12 @@
|
|
|
18
21
|
"type": "git",
|
|
19
22
|
"url": "git+https://github.com/uxland/harmonix.git"
|
|
20
23
|
},
|
|
21
|
-
"scripts": {
|
|
22
|
-
"serve": "vite",
|
|
23
|
-
"start": "ng serve --host 0.0.0.0",
|
|
24
|
-
"build": "vite build",
|
|
25
|
-
"preview": "vite preview",
|
|
26
|
-
"publish-rc": "npm publish --tag rc"
|
|
27
|
-
},
|
|
28
24
|
"bugs": {
|
|
29
25
|
"url": "https://github.com/uxland/harmonix/issues"
|
|
30
26
|
},
|
|
31
27
|
"dependencies": {
|
|
32
|
-
"@uxland/harmonix": "^1.0.0"
|
|
28
|
+
"@uxland/harmonix": "^1.0.0",
|
|
29
|
+
"axios": "^1.7.2"
|
|
33
30
|
},
|
|
34
31
|
"devDependencies": {
|
|
35
32
|
"lit": "^3.1.0",
|
|
@@ -43,6 +40,16 @@
|
|
|
43
40
|
"mediatr-ts": "^1.2.1",
|
|
44
41
|
"tslib": "^2.3.0",
|
|
45
42
|
"vite": "^5.2.8",
|
|
43
|
+
"inversify": "^6.0.2",
|
|
44
|
+
"inversify-inject-decorators": "^3.1.0",
|
|
45
|
+
"jwt-decode": "^4.0.0",
|
|
46
46
|
"@salut/design-system-salut": "1.6.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"serve": "vite",
|
|
50
|
+
"start": "ng serve --host 0.0.0.0",
|
|
51
|
+
"build": "vite build",
|
|
52
|
+
"preview": "vite preview",
|
|
53
|
+
"publish-rc": "npm publish --tag rc"
|
|
47
54
|
}
|
|
48
|
-
}
|
|
55
|
+
}
|
|
@@ -3,3 +3,5 @@ import "./clinical-monitoring/clinical-monitoring";
|
|
|
3
3
|
import "./title-view/title-view";
|
|
4
4
|
import "./primaria-breadcumbs/primaria-breadcumbs";
|
|
5
5
|
import "../shared-components";
|
|
6
|
+
import "../components/patient-header/patient-header";
|
|
7
|
+
import "../components/professional-header/professional-header";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LitElement, css, html, unsafeCSS } from "lit";
|
|
2
|
+
import { customElement, property } from "lit/decorators.js";
|
|
3
|
+
import styles from "./styles.scss?inline";
|
|
4
|
+
import { template } from "./template";
|
|
5
|
+
import { shellApi } from "../../../api/api";
|
|
6
|
+
import { IPatientInfo } from "primary/shell/src/features/get-patient-info/model";
|
|
7
|
+
import { GetPatientInfo } from "../../../features/get-patient-info/request";
|
|
8
|
+
|
|
9
|
+
@customElement("patient-header")
|
|
10
|
+
export class PatientHeader extends LitElement {
|
|
11
|
+
render() {
|
|
12
|
+
return html`${template(this)}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static styles = css`
|
|
16
|
+
${unsafeCSS(styles)}
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
@property({ type: Object })
|
|
20
|
+
patient: IPatientInfo;
|
|
21
|
+
|
|
22
|
+
connectedCallback() {
|
|
23
|
+
super.connectedCallback();
|
|
24
|
+
shellApi.broker.send(new GetPatientInfo()).then((response: IPatientInfo) => {
|
|
25
|
+
this.patient = response;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
gap: 16px;
|
|
3
|
+
@include layout-horizontal;
|
|
4
|
+
@include layout-center;
|
|
5
|
+
.details {
|
|
6
|
+
color: var(--color-neutral-500);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.name-details {
|
|
11
|
+
display: flex;
|
|
12
|
+
@include layout-vertical;
|
|
13
|
+
line-height: 24px;
|
|
14
|
+
size: 14px;
|
|
15
|
+
.name {
|
|
16
|
+
font-family: var(--font-semibold);
|
|
17
|
+
color: var(--color-primary-700);
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
text-decoration: underline;
|
|
20
|
+
}
|
|
21
|
+
.details {
|
|
22
|
+
font-weight: 400;
|
|
23
|
+
font-family: var(--font-regular);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import { PatientHeader } from "./patient-header";
|
|
3
|
+
|
|
4
|
+
export const template = (props: PatientHeader) => html`
|
|
5
|
+
<div class="wrapper">
|
|
6
|
+
<dss-avatar size="lg" name="${props.patient.firstName.charAt(
|
|
7
|
+
0,
|
|
8
|
+
)}" surname="${props.patient.lastName.charAt(0)}"></dss-avatar>
|
|
9
|
+
<div class="name-details">
|
|
10
|
+
<div class="name">
|
|
11
|
+
${props.patient.firstName} ${props.patient.lastName}
|
|
12
|
+
</div>
|
|
13
|
+
<div class="details">
|
|
14
|
+
${props.patient.patientId}
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
`;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import "@salut/design-system-salut";
|
|
2
2
|
import "@salut/design-system-salut/css/main.css";
|
|
3
|
+
import "../../fonts/fonts.css";
|
|
4
|
+
import "../../styles/index.css";
|
|
3
5
|
import { html } from "lit";
|
|
4
6
|
import gencatLogo from "../../../UI/images/Gencat_Logotip.svg";
|
|
5
7
|
import salutLogo from "../../../UI/images/Salut_Logotip.svg";
|
|
@@ -13,9 +15,11 @@ export const template = (props: PrimariaShell) => html`
|
|
|
13
15
|
<img src=${salutLogo} alt="logo" />
|
|
14
16
|
</div>
|
|
15
17
|
<primaria-content-switcher id="header-region-container"></primaria-content-switcher>
|
|
18
|
+
<patient-header></patient-header>
|
|
16
19
|
</div>
|
|
17
20
|
<div class="header__right">
|
|
18
21
|
<div id="header-actions-region-container"></div>
|
|
22
|
+
<professional-header></professional-header>
|
|
19
23
|
</div>
|
|
20
24
|
</div>
|
|
21
25
|
<div class="main-container">
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { LitElement, css, html, unsafeCSS } from "lit";
|
|
2
|
+
import { customElement, property } from "lit/decorators.js";
|
|
3
|
+
import styles from "./styles.scss?inline";
|
|
4
|
+
import { template } from "./template";
|
|
5
|
+
import { shellApi } from "../../../api/api";
|
|
6
|
+
import { IUserInfo } from "primary/shell/src/features/get-user-info/model";
|
|
7
|
+
import { GetUserInfo } from "../../../features/get-user-info/request";
|
|
8
|
+
|
|
9
|
+
@customElement("professional-header")
|
|
10
|
+
export class ProfessionalHeader extends LitElement {
|
|
11
|
+
render() {
|
|
12
|
+
return html`${template(this)}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static styles = css`
|
|
16
|
+
${unsafeCSS(styles)}
|
|
17
|
+
`;
|
|
18
|
+
@property({ type: Object })
|
|
19
|
+
professional: IUserInfo;
|
|
20
|
+
|
|
21
|
+
connectedCallback() {
|
|
22
|
+
super.connectedCallback();
|
|
23
|
+
shellApi.broker.send(new GetUserInfo()).then((response: IUserInfo) => {
|
|
24
|
+
this.professional = response;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
gap: 16px;
|
|
3
|
+
@include layout-horizontal;
|
|
4
|
+
@include layout-center;
|
|
5
|
+
.details {
|
|
6
|
+
color: var(--color-neutral-500);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.name-details {
|
|
11
|
+
display: flex;
|
|
12
|
+
@include layout-vertical;
|
|
13
|
+
line-height: 24px;
|
|
14
|
+
size: 14px;
|
|
15
|
+
.name {
|
|
16
|
+
font-family: var(--font-semibold);
|
|
17
|
+
color: var(--color-primary-700);
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
text-decoration: underline;
|
|
20
|
+
}
|
|
21
|
+
.details {
|
|
22
|
+
font-weight: 400;
|
|
23
|
+
font-family: var(--font-regular);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import { ProfessionalHeader } from "./professional-header";
|
|
3
|
+
|
|
4
|
+
export const template = (props: ProfessionalHeader) => html`
|
|
5
|
+
<div class="wrapper">
|
|
6
|
+
<dss-avatar size="lg" name="${props.professional.firstName.charAt(
|
|
7
|
+
0,
|
|
8
|
+
)}" surname="${props.professional.lastName.charAt(0)}"></dss-avatar>
|
|
9
|
+
<div class="name-details">
|
|
10
|
+
<div class="name">
|
|
11
|
+
${props.professional.firstName} ${props.professional.lastName}
|
|
12
|
+
</div>
|
|
13
|
+
<div class="details">
|
|
14
|
+
${props.professional.speciality}
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
`;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* open-sans-300 - latin */
|
|
2
|
+
@font-face {
|
|
3
|
+
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
|
4
|
+
font-family: 'Open Sans';
|
|
5
|
+
font-style: normal;
|
|
6
|
+
font-weight: 300;
|
|
7
|
+
src: url('open-sans-v40-latin-300.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
|
8
|
+
}
|
|
9
|
+
/* open-sans-regular - latin */
|
|
10
|
+
@font-face {
|
|
11
|
+
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
|
12
|
+
font-family: 'Open Sans';
|
|
13
|
+
font-style: normal;
|
|
14
|
+
font-weight: 400;
|
|
15
|
+
src: url('open-sans-v40-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
|
16
|
+
}
|
|
17
|
+
/* open-sans-500 - latin */
|
|
18
|
+
@font-face {
|
|
19
|
+
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
|
20
|
+
font-family: 'Open Sans';
|
|
21
|
+
font-style: normal;
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
src: url('open-sans-v40-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
|
24
|
+
}
|
|
25
|
+
/* open-sans-600 - latin */
|
|
26
|
+
@font-face {
|
|
27
|
+
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
|
28
|
+
font-family: 'Open Sans';
|
|
29
|
+
font-style: normal;
|
|
30
|
+
font-weight: 600;
|
|
31
|
+
src: url('open-sans-v40-latin-600.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
|
32
|
+
}
|
|
33
|
+
/* open-sans-700 - latin */
|
|
34
|
+
@font-face {
|
|
35
|
+
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
|
36
|
+
font-family: 'Open Sans';
|
|
37
|
+
font-style: normal;
|
|
38
|
+
font-weight: 700;
|
|
39
|
+
src: url('open-sans-v40-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
|
40
|
+
}
|
|
41
|
+
/* open-sans-800 - latin */
|
|
42
|
+
@font-face {
|
|
43
|
+
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
|
44
|
+
font-family: 'Open Sans';
|
|
45
|
+
font-style: normal;
|
|
46
|
+
font-weight: 800;
|
|
47
|
+
src: url('open-sans-v40-latin-800.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
|
48
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -22,9 +22,9 @@ export class NotifierComponent extends LitElement {
|
|
|
22
22
|
render() {
|
|
23
23
|
return html`
|
|
24
24
|
<div class="snackbar ${this.options.type}">
|
|
25
|
-
<i class="dss-icon-button dss-icon-button--primary dss-icon-button--md ">
|
|
25
|
+
<dss-container><i class="dss-icon-button dss-icon-button--primary dss-icon-button--md ">
|
|
26
26
|
<span class="dss-icon">${ifDefined(getIcon(this.options.type))}</span>
|
|
27
|
-
</i>
|
|
27
|
+
</i></dss-container>
|
|
28
28
|
<div class="snackbar__message">${this.options.message ?? ""}</div>
|
|
29
29
|
<div class="snackbar__action">
|
|
30
30
|
<dss-container><button class="dss-icon-button dss-icon-button--success dss-icon-button--md">
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
body {
|
|
2
|
+
margin: 0;
|
|
3
|
+
overflow: hidden;
|
|
4
|
+
font-size: 14px;
|
|
5
|
+
background-color: #f5f6fa;
|
|
6
|
+
font-family: 'Open Sans', sans-serif;
|
|
7
|
+
pointer-events: auto !important;
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
html {
|
|
13
|
+
font-size: 14px;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
font-family: 'Open Sans', sans-serif;
|
|
16
|
+
width: 100%;
|
|
17
|
+
height: 100%;
|
|
18
|
+
}
|
package/src/api/api.ts
CHANGED
|
@@ -15,15 +15,12 @@ import {
|
|
|
15
15
|
import { PrimariaGlobalStateManager, createGlobalStateManager } from "./global-state/global-state";
|
|
16
16
|
import { PrimariaBroker } from "./broker/primaria-broker";
|
|
17
17
|
import { createBroker } from "./broker/factory";
|
|
18
|
+
import { HttpClient, createHttpClient } from "./http-client/http-client";
|
|
18
19
|
const broker = createBroker();
|
|
19
20
|
|
|
20
|
-
interface PrimariaHttpClient {
|
|
21
|
-
get(url: string): Promise<any>;
|
|
22
|
-
post(url: string, data: any): Promise<any>;
|
|
23
|
-
}
|
|
24
21
|
|
|
25
22
|
export interface PrimariaApi extends HarmonixApi {
|
|
26
|
-
httpClient:
|
|
23
|
+
httpClient: HttpClient;
|
|
27
24
|
interactionManager: PrimariaInteractionManager;
|
|
28
25
|
broker: PrimariaBroker;
|
|
29
26
|
regionManager: PrimariaRegionManager;
|
|
@@ -45,14 +42,7 @@ export const primariaApiFactory: ApiFactory<PrimariaApi> = (
|
|
|
45
42
|
return {
|
|
46
43
|
pluginInfo: pluginInfo,
|
|
47
44
|
regionManager: createRegionManagerProxy(pluginInfo, regionManager),
|
|
48
|
-
httpClient:
|
|
49
|
-
get: (url: string) => fetch(url).then((r) => r.json()),
|
|
50
|
-
post: (url: string, data: any) =>
|
|
51
|
-
fetch(url, {
|
|
52
|
-
method: "POST",
|
|
53
|
-
body: JSON.stringify(data),
|
|
54
|
-
}).then((r) => r.json()),
|
|
55
|
-
},
|
|
45
|
+
httpClient: createHttpClient(),
|
|
56
46
|
interactionManager: { ...createInteractionManager() },
|
|
57
47
|
broker: broker,
|
|
58
48
|
createLocaleManager: createLocaleManager(pluginInfo.pluginId) as any,
|
|
@@ -40,7 +40,7 @@ describe("Broker test", () => {
|
|
|
40
40
|
describe("Given some subscriptions for an event", () => {
|
|
41
41
|
let handlers: Mock[];
|
|
42
42
|
beforeEach(() => {
|
|
43
|
-
handlers = Array.from({
|
|
43
|
+
handlers = Array.from({length: 5}).map(() => {
|
|
44
44
|
const handler = vi.fn();
|
|
45
45
|
sut.subscribe("MyEvent", handler);
|
|
46
46
|
return handler;
|
|
@@ -48,15 +48,20 @@ describe("Broker test", () => {
|
|
|
48
48
|
});
|
|
49
49
|
describe("When event is published", () => {
|
|
50
50
|
beforeEach(() => {
|
|
51
|
-
sut.publish("MyEvent", {
|
|
51
|
+
sut.publish("MyEvent", {greeting: "Hello"});
|
|
52
52
|
});
|
|
53
53
|
it("Then handler is called", () => {
|
|
54
54
|
for (const handler of handlers) {
|
|
55
|
-
expect(handler).toBeCalledWith({
|
|
55
|
+
expect(handler).toBeCalledWith({greeting: "Hello"});
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
|
+
describe("Given no subscriptions for an event", () => {
|
|
61
|
+
it("When event is published, Then nothing happens", () => {
|
|
62
|
+
expect(() => sut.publish("MyEvent", { greeting: "Hello" })).not.toThrow();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
60
65
|
});
|
|
61
66
|
});
|
|
62
67
|
describe("Message broker test", () => {
|
|
@@ -30,6 +30,9 @@ class Broker implements PrimariaBroker {
|
|
|
30
30
|
publish(event: string | IEvent, payload?: unknown): Promise<void> {
|
|
31
31
|
const eventPayload =
|
|
32
32
|
typeof event === "string" ? this.getEvent(event as string, payload) : event;
|
|
33
|
+
const classConstructor = eventPayload.constructor || Object.getPrototypeOf(eventPayload).constructor;
|
|
34
|
+
const handlerSubscriptions = mediatorSettings.dispatcher.notifications._mappings.filter(m => m.notification === classConstructor);
|
|
35
|
+
if (!handlerSubscriptions.length) return Promise.resolve();
|
|
33
36
|
return this.mediator.publish(eventPayload);
|
|
34
37
|
}
|
|
35
38
|
subscribe<TEvent extends IEvent>(
|
|
@@ -25,7 +25,7 @@ describe("PrimariaGlobalStateManagerImpl", () => {
|
|
|
25
25
|
globalStateManager.setData(key, value);
|
|
26
26
|
|
|
27
27
|
expect(globalStateManager.getData(key)).toBe(value);
|
|
28
|
-
expect(brokerMock.publish).toHaveBeenCalledWith("
|
|
28
|
+
expect(brokerMock.publish).toHaveBeenCalledWith("data_set", {
|
|
29
29
|
key: key,
|
|
30
30
|
value: value,
|
|
31
31
|
});
|
|
@@ -19,7 +19,7 @@ class PrimariaGlobalStateManagerImpl implements PrimariaGlobalStateManager {
|
|
|
19
19
|
*/
|
|
20
20
|
setData(key: string, value: any): void {
|
|
21
21
|
this.state[key] = value;
|
|
22
|
-
this.broker.publish("
|
|
22
|
+
this.broker.publish("data_set", {
|
|
23
23
|
key: key,
|
|
24
24
|
value: value,
|
|
25
25
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
|
|
3
|
+
const token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1S2hQbXhscHB4d2sxUDVfWmQ5am9CeTV6N2p5MHFPd0ZWY3RwZjBDa0E4In0.eyJleHAiOjE3MjEzMDc3MTcsImlhdCI6MTcyMTMwNzQxNywianRpIjoiNWRkMDE1YzgtNTQ5Yy00ZGM2LWE4YWItMTUzNDJiMWRhNThmIiwiaXNzIjoiaHR0cHM6Ly9pbnRlZ3JhY2lvLnBkcy5oZXMuY2F0c2FsdXQuaW50cmFuZXQuZ2VuY2F0LmNhdC9hdXRoL3JlYWxtcy9FVEMiLCJzdWIiOiJlMjRlMzFlMC01NWZiLTRhZmEtYTQzNi0yYmRhOGYyYWQ0ZWUiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJldGMtY2NmLWludCIsInNlc3Npb25fc3RhdGUiOiJhY2M2ZDBlYi1iMTBjLTQ3ZDEtYjFlOC0xYWQ5ODU5NTAyNTkiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1oZXMtY2FtIl19LCJzY29wZSI6IiIsInNpZCI6ImFjYzZkMGViLWIxMGMtNDdkMS1iMWU4LTFhZDk4NTk1MDI1OSIsImNsaWVudEhvc3QiOiIxMC41My4yNTQuMTUwIiwiYWNjZXNzX3J1bGVzIjp7fSwiYWNjZXNzX2luZm8iOnsicGF0aWVudF9nZW5kZXIiOiIxIiwicGF0aWVudF9iaXJ0aGRhdGUiOiIxOTk5MDEwMSIsInByb2Zlc3Npb25hbF9yb2xlIjoiQURNIiwicHJvZmVzc2lvbmFsX2lkIjoiMTIzNDU2Nzg5MCIsInVwX2NvZGUiOiIwNzczMyIsInBhdGllbnRfZ2l2ZW5fbmFtZSI6ImNhc3RhbnkiLCJwYXRpZW50X2lkIjoiMTIzNDU2Nzg5MCIsInByb2Zlc3Npb25hbF9zcGVjaWFsaXR5IjoiU1BFQzAxIiwicHJvZmVzc2lvbmFsX3NlcnZpY2UiOiJTRVJWMDEiLCJwYXRpZW50X2xhc3RfbmFtZSI6IkFSRUdBTEwiLCJlcF9jb2RlIjoiMDIwOCJ9LCJjbGllbnRBZGRyZXNzIjoiMTAuNTMuMjU0LjE1MCIsImNsaWVudF9pZCI6ImV0Yy1jY2YtaW50In0.NiDKnMchNB4zqL9zOdq15G8y2BYGOyjk8n1xofB2WyxhVpbTXhXAgApS-4DCqczmdPt4sOwtt-FVVxcYku2gKcQQ1Leapb7CmHoUT_ak5ovOE8ZrD5Ryz6rfC_O1lO8Ut4M_J-KzMxj7WvUNYhkIqcHFSMwDdNC6xxc4ZYMOUI4bOif_Tiy7CxvMIpFGm1YS_jiGS2PGI8Y1o_1DApqMs88MxK9ItO-DIfQgKcR3wV6J-QZueaKVtih-kLma33TZc0jz7xG1EyOMJ5cC4r1Sxp877b9ut4JCmMaWOfWNf2tldLcpXTvV_BWg53YpwYOl4pvZdg3lFWEb009DofTQbQ"
|
|
4
|
+
let instance = axios.create({
|
|
5
|
+
headers: {
|
|
6
|
+
"Authorization": "Bearer "+ token
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
export interface HttpClient {
|
|
10
|
+
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
|
|
11
|
+
}
|
|
12
|
+
export const createHttpClient = () : HttpClient => {
|
|
13
|
+
return {request: instance.request}
|
|
14
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PrimariaApi } from "@uxland/primary-shell";
|
|
2
|
+
import { container } from "../infrastructure/ioc/container";
|
|
3
|
+
import { TYPES } from "../infrastructure/ioc/types";
|
|
4
|
+
import { bootstrapGetUserInfo, teardownGetUserInfo } from "./get-user-info/bootstrapper";
|
|
5
|
+
import { bootstrapGetPatientInfo, teardownGetPatientInfo } from "./get-patient-info/bootstrapper";
|
|
6
|
+
|
|
7
|
+
export const bootstrapFeatures = (api: PrimariaApi) => {
|
|
8
|
+
container.bind(TYPES.primaryApi).toConstantValue(api);
|
|
9
|
+
bootstrapGetUserInfo();
|
|
10
|
+
bootstrapGetPatientInfo();
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const teardownFeatures = () => {
|
|
14
|
+
teardownGetUserInfo();
|
|
15
|
+
teardownGetPatientInfo();
|
|
16
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { injectable } from "inversify";
|
|
2
|
+
import { IPatientInfo } from "./model";
|
|
3
|
+
import { jwtDecode } from "jwt-decode";
|
|
4
|
+
|
|
5
|
+
export abstract class PatientInfoBackendAdapter {
|
|
6
|
+
abstract getPatientInfo(): Promise<IPatientInfo>;
|
|
7
|
+
}
|
|
8
|
+
@injectable()
|
|
9
|
+
export class GetPatientInfoBackendAdapter implements PatientInfoBackendAdapter {
|
|
10
|
+
token =
|
|
11
|
+
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1S2hQbXhscHB4d2sxUDVfWmQ5am9CeTV6N2p5MHFPd0ZWY3RwZjBDa0E4In0.eyJleHAiOjE3MjEzMDc3MTcsImlhdCI6MTcyMTMwNzQxNywianRpIjoiNWRkMDE1YzgtNTQ5Yy00ZGM2LWE4YWItMTUzNDJiMWRhNThmIiwiaXNzIjoiaHR0cHM6Ly9pbnRlZ3JhY2lvLnBkcy5oZXMuY2F0c2FsdXQuaW50cmFuZXQuZ2VuY2F0LmNhdC9hdXRoL3JlYWxtcy9FVEMiLCJzdWIiOiJlMjRlMzFlMC01NWZiLTRhZmEtYTQzNi0yYmRhOGYyYWQ0ZWUiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJldGMtY2NmLWludCIsInNlc3Npb25fc3RhdGUiOiJhY2M2ZDBlYi1iMTBjLTQ3ZDEtYjFlOC0xYWQ5ODU5NTAyNTkiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1oZXMtY2FtIl19LCJzY29wZSI6IiIsInNpZCI6ImFjYzZkMGViLWIxMGMtNDdkMS1iMWU4LTFhZDk4NTk1MDI1OSIsImNsaWVudEhvc3QiOiIxMC41My4yNTQuMTUwIiwiYWNjZXNzX3J1bGVzIjp7fSwiYWNjZXNzX2luZm8iOnsicGF0aWVudF9nZW5kZXIiOiIxIiwicGF0aWVudF9iaXJ0aGRhdGUiOiIxOTk5MDEwMSIsInByb2Zlc3Npb25hbF9yb2xlIjoiQURNIiwicHJvZmVzc2lvbmFsX2lkIjoiMTIzNDU2Nzg5MCIsInVwX2NvZGUiOiIwNzczMyIsInBhdGllbnRfZ2l2ZW5fbmFtZSI6ImNhc3RhbnkiLCJwYXRpZW50X2lkIjoiMTIzNDU2Nzg5MCIsInByb2Zlc3Npb25hbF9zcGVjaWFsaXR5IjoiU1BFQzAxIiwicHJvZmVzc2lvbmFsX3NlcnZpY2UiOiJTRVJWMDEiLCJwYXRpZW50X2xhc3RfbmFtZSI6IkFSRUdBTEwiLCJlcF9jb2RlIjoiMDIwOCJ9LCJjbGllbnRBZGRyZXNzIjoiMTAuNTMuMjU0LjE1MCIsImNsaWVudF9pZCI6ImV0Yy1jY2YtaW50In0.NiDKnMchNB4zqL9zOdq15G8y2BYGOyjk8n1xofB2WyxhVpbTXhXAgApS-4DCqczmdPt4sOwtt-FVVxcYku2gKcQQ1Leapb7CmHoUT_ak5ovOE8ZrD5Ryz6rfC_O1lO8Ut4M_J-KzMxj7WvUNYhkIqcHFSMwDdNC6xxc4ZYMOUI4bOif_Tiy7CxvMIpFGm1YS_jiGS2PGI8Y1o_1DApqMs88MxK9ItO-DIfQgKcR3wV6J-QZueaKVtih-kLma33TZc0jz7xG1EyOMJ5cC4r1Sxp877b9ut4JCmMaWOfWNf2tldLcpXTvV_BWg53YpwYOl4pvZdg3lFWEb009DofTQbQ";
|
|
12
|
+
getPatientInfo(): Promise<IPatientInfo> {
|
|
13
|
+
const decodedToken = jwtDecode(this.token);
|
|
14
|
+
console.log(decodedToken);
|
|
15
|
+
const patientInfo: IPatientInfo = {
|
|
16
|
+
patientId: decodedToken.access_info.professional_id,
|
|
17
|
+
firstName: decodedToken.access_info.patient_given_name,
|
|
18
|
+
lastName: decodedToken.access_info.patient_last_name,
|
|
19
|
+
gender: decodedToken.access_info.patient_gender,
|
|
20
|
+
birthdate: decodedToken.access_info.patient_birthdate,
|
|
21
|
+
};
|
|
22
|
+
return Promise.resolve(patientInfo);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { shellApi } from "../../api/api";
|
|
2
|
+
import { container, registerDep, unregisterDep } from "../../infrastructure/ioc/container";
|
|
3
|
+
import { registerRequest, unregisterRequest } from "../utils";
|
|
4
|
+
import { GetPatientInfoBackendAdapter } from "./backend-adapter";
|
|
5
|
+
import { GetPatientInfoHandler } from "./handler";
|
|
6
|
+
import { GetPatientInfo } from "./request";
|
|
7
|
+
|
|
8
|
+
export const bootstrapGetPatientInfo = () => {
|
|
9
|
+
teardownGetPatientInfo();
|
|
10
|
+
registerRequest(shellApi, container)(GetPatientInfo, GetPatientInfoHandler);
|
|
11
|
+
registerDep(GetPatientInfoBackendAdapter);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const teardownGetPatientInfo = () => {
|
|
15
|
+
unregisterRequest(container)(GetPatientInfoHandler);
|
|
16
|
+
unregisterDep(GetPatientInfoBackendAdapter);
|
|
17
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { inject } from "inversify";
|
|
2
|
+
import { TYPES } from "../../infrastructure/ioc/types";
|
|
3
|
+
import { PrimariaApi } from "@uxland/primary-shell";
|
|
4
|
+
import { GetPatientInfoBackendAdapter, PatientInfoBackendAdapter } from "./backend-adapter";
|
|
5
|
+
import { GetPatientInfo } from "./request";
|
|
6
|
+
import { IPatientInfo } from "./model";
|
|
7
|
+
|
|
8
|
+
export class GetPatientInfoHandler {
|
|
9
|
+
constructor(
|
|
10
|
+
@inject(TYPES.primaryApi) private api: PrimariaApi,
|
|
11
|
+
@inject(GetPatientInfoBackendAdapter) private backendAdapter: PatientInfoBackendAdapter,
|
|
12
|
+
) {}
|
|
13
|
+
async handle(message: GetPatientInfo): Promise<IPatientInfo | undefined> {
|
|
14
|
+
try {
|
|
15
|
+
const patientInfo = await this.backendAdapter.getPatientInfo();
|
|
16
|
+
this.api.globalStateManager.setData("patientInfo", patientInfo);
|
|
17
|
+
return patientInfo;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
this.api.interactionManager.notify({
|
|
20
|
+
type: "error",
|
|
21
|
+
message: error.message,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { injectable } from "inversify";
|
|
2
|
+
import { IUserInfo } from "./model";
|
|
3
|
+
import { jwtDecode } from "jwt-decode";
|
|
4
|
+
|
|
5
|
+
export abstract class UserInfoBackendAdapter {
|
|
6
|
+
abstract getUserInfo(): Promise<IUserInfo>;
|
|
7
|
+
}
|
|
8
|
+
@injectable()
|
|
9
|
+
export class GetUserInfoBackendAdapter implements UserInfoBackendAdapter {
|
|
10
|
+
token =
|
|
11
|
+
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1S2hQbXhscHB4d2sxUDVfWmQ5am9CeTV6N2p5MHFPd0ZWY3RwZjBDa0E4In0.eyJleHAiOjE3MjEzMDc3MTcsImlhdCI6MTcyMTMwNzQxNywianRpIjoiNWRkMDE1YzgtNTQ5Yy00ZGM2LWE4YWItMTUzNDJiMWRhNThmIiwiaXNzIjoiaHR0cHM6Ly9pbnRlZ3JhY2lvLnBkcy5oZXMuY2F0c2FsdXQuaW50cmFuZXQuZ2VuY2F0LmNhdC9hdXRoL3JlYWxtcy9FVEMiLCJzdWIiOiJlMjRlMzFlMC01NWZiLTRhZmEtYTQzNi0yYmRhOGYyYWQ0ZWUiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJldGMtY2NmLWludCIsInNlc3Npb25fc3RhdGUiOiJhY2M2ZDBlYi1iMTBjLTQ3ZDEtYjFlOC0xYWQ5ODU5NTAyNTkiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1oZXMtY2FtIl19LCJzY29wZSI6IiIsInNpZCI6ImFjYzZkMGViLWIxMGMtNDdkMS1iMWU4LTFhZDk4NTk1MDI1OSIsImNsaWVudEhvc3QiOiIxMC41My4yNTQuMTUwIiwiYWNjZXNzX3J1bGVzIjp7fSwiYWNjZXNzX2luZm8iOnsicGF0aWVudF9nZW5kZXIiOiIxIiwicGF0aWVudF9iaXJ0aGRhdGUiOiIxOTk5MDEwMSIsInByb2Zlc3Npb25hbF9yb2xlIjoiQURNIiwicHJvZmVzc2lvbmFsX2lkIjoiMTIzNDU2Nzg5MCIsInVwX2NvZGUiOiIwNzczMyIsInBhdGllbnRfZ2l2ZW5fbmFtZSI6ImNhc3RhbnkiLCJwYXRpZW50X2lkIjoiMTIzNDU2Nzg5MCIsInByb2Zlc3Npb25hbF9zcGVjaWFsaXR5IjoiU1BFQzAxIiwicHJvZmVzc2lvbmFsX3NlcnZpY2UiOiJTRVJWMDEiLCJwYXRpZW50X2xhc3RfbmFtZSI6IkFSRUdBTEwiLCJlcF9jb2RlIjoiMDIwOCJ9LCJjbGllbnRBZGRyZXNzIjoiMTAuNTMuMjU0LjE1MCIsImNsaWVudF9pZCI6ImV0Yy1jY2YtaW50In0.NiDKnMchNB4zqL9zOdq15G8y2BYGOyjk8n1xofB2WyxhVpbTXhXAgApS-4DCqczmdPt4sOwtt-FVVxcYku2gKcQQ1Leapb7CmHoUT_ak5ovOE8ZrD5Ryz6rfC_O1lO8Ut4M_J-KzMxj7WvUNYhkIqcHFSMwDdNC6xxc4ZYMOUI4bOif_Tiy7CxvMIpFGm1YS_jiGS2PGI8Y1o_1DApqMs88MxK9ItO-DIfQgKcR3wV6J-QZueaKVtih-kLma33TZc0jz7xG1EyOMJ5cC4r1Sxp877b9ut4JCmMaWOfWNf2tldLcpXTvV_BWg53YpwYOl4pvZdg3lFWEb009DofTQbQ";
|
|
12
|
+
getUserInfo(): Promise<IUserInfo> {
|
|
13
|
+
const decodedToken = jwtDecode(this.token);
|
|
14
|
+
const userInfo: IUserInfo = {
|
|
15
|
+
userId: decodedToken.access_info.professional_id,
|
|
16
|
+
firstName: "Nom", // TODO get professional data
|
|
17
|
+
lastName: "Cognom", // TODO get professional data
|
|
18
|
+
role: decodedToken.access_info.professional_role,
|
|
19
|
+
speciality: decodedToken.access_info.professional_speciality,
|
|
20
|
+
service: decodedToken.access_info.professional_service,
|
|
21
|
+
};
|
|
22
|
+
return Promise.resolve(userInfo);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { shellApi } from "../../api/api";
|
|
2
|
+
import { container, registerDep, unregisterDep } from "../../infrastructure/ioc/container";
|
|
3
|
+
import { registerRequest, unregisterRequest } from "../utils";
|
|
4
|
+
import { GetUserInfoBackendAdapter } from "./backend-adapter";
|
|
5
|
+
import { GetUserInfoHandler } from "./handler";
|
|
6
|
+
import { GetUserInfo } from "./request";
|
|
7
|
+
|
|
8
|
+
export const bootstrapGetUserInfo = () => {
|
|
9
|
+
teardownGetUserInfo();
|
|
10
|
+
registerRequest(shellApi, container)(GetUserInfo, GetUserInfoHandler);
|
|
11
|
+
registerDep(GetUserInfoBackendAdapter);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const teardownGetUserInfo = () => {
|
|
15
|
+
unregisterRequest(container)(GetUserInfoHandler);
|
|
16
|
+
unregisterDep(GetUserInfoBackendAdapter);
|
|
17
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { PrimariaApi } from "@uxland/primary-shell";
|
|
2
|
+
import { TYPES } from "../../infrastructure/ioc/types";
|
|
3
|
+
import { inject } from "inversify";
|
|
4
|
+
import { GetUserInfo } from "./request";
|
|
5
|
+
import { IUserInfo } from "./model";
|
|
6
|
+
import { UserInfoBackendAdapter } from "./backend-adapter";
|
|
7
|
+
import { GetUserInfoBackendAdapter } from "./backend-adapter";
|
|
8
|
+
|
|
9
|
+
export class GetUserInfoHandler {
|
|
10
|
+
constructor(
|
|
11
|
+
@inject(TYPES.primaryApi) private api: PrimariaApi,
|
|
12
|
+
@inject(GetUserInfoBackendAdapter) private backendAdapter: UserInfoBackendAdapter,
|
|
13
|
+
) {}
|
|
14
|
+
async handle(message: GetUserInfo): Promise<IUserInfo | undefined> {
|
|
15
|
+
try {
|
|
16
|
+
const userInfo = await this.backendAdapter.getUserInfo();
|
|
17
|
+
this.api.globalStateManager.setData("userInfo", userInfo);
|
|
18
|
+
return userInfo;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
this.api.interactionManager.notify({
|
|
21
|
+
type: "error",
|
|
22
|
+
message: error.message,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|