@happyvertical/smrt-projects 0.39.4 → 0.39.7
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/AGENTS.md +36 -1
- package/SERVICE_TIME_MIGRATION.md +23 -0
- package/dist/collections/DevelopmentRequestHistories.d.ts +7 -0
- package/dist/collections/DevelopmentRequestHistories.d.ts.map +1 -0
- package/dist/collections/DevelopmentRequests.d.ts +20 -0
- package/dist/collections/DevelopmentRequests.d.ts.map +1 -0
- package/dist/collections/ProjectIntegrationAudits.d.ts +7 -0
- package/dist/collections/ProjectIntegrationAudits.d.ts.map +1 -0
- package/dist/collections/ProjectIntegrations.d.ts +28 -0
- package/dist/collections/ProjectIntegrations.d.ts.map +1 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1673 -33
- package/dist/index.js.map +1 -1
- package/dist/managed-client.d.ts +13 -0
- package/dist/managed-client.d.ts.map +1 -0
- package/dist/manifest.json +4790 -1109
- package/dist/models/DevelopmentRequest.d.ts +35 -0
- package/dist/models/DevelopmentRequest.d.ts.map +1 -0
- package/dist/models/DevelopmentRequestHistory.d.ts +22 -0
- package/dist/models/DevelopmentRequestHistory.d.ts.map +1 -0
- package/dist/models/ProjectIntegration.d.ts +24 -0
- package/dist/models/ProjectIntegration.d.ts.map +1 -0
- package/dist/models/ProjectIntegrationAudit.d.ts +16 -0
- package/dist/models/ProjectIntegrationAudit.d.ts.map +1 -0
- package/dist/models/delivery-control-plane.d.ts +83 -0
- package/dist/models/delivery-control-plane.d.ts.map +1 -0
- package/dist/models/service-evidence.d.ts +79 -0
- package/dist/models/service-evidence.d.ts.map +1 -0
- package/dist/services/assistance-request-service.d.ts +45 -0
- package/dist/services/assistance-request-service.d.ts.map +1 -0
- package/dist/services/delivery-service.d.ts +55 -0
- package/dist/services/delivery-service.d.ts.map +1 -0
- package/dist/services/development-request-service.d.ts +61 -0
- package/dist/services/development-request-service.d.ts.map +1 -0
- package/dist/services/index.d.ts +6 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/service-evidence-service.d.ts +48 -0
- package/dist/services/service-evidence-service.d.ts.map +1 -0
- package/dist/services/subscription-commercial-resolver.d.ts +17 -0
- package/dist/services/subscription-commercial-resolver.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +1823 -148
- package/dist/svelte/AssistanceLauncher.svelte +96 -0
- package/dist/svelte/AssistanceLauncher.svelte.d.ts +12 -0
- package/dist/svelte/AssistanceLauncher.svelte.d.ts.map +1 -0
- package/dist/svelte/DeliveryStatus.svelte +71 -0
- package/dist/svelte/DeliveryStatus.svelte.d.ts +8 -0
- package/dist/svelte/DeliveryStatus.svelte.d.ts.map +1 -0
- package/dist/svelte/DevelopmentBoard.svelte +103 -0
- package/dist/svelte/DevelopmentBoard.svelte.d.ts +10 -0
- package/dist/svelte/DevelopmentBoard.svelte.d.ts.map +1 -0
- package/dist/svelte/DevelopmentRequestDetail.svelte +92 -0
- package/dist/svelte/DevelopmentRequestDetail.svelte.d.ts +9 -0
- package/dist/svelte/DevelopmentRequestDetail.svelte.d.ts.map +1 -0
- package/dist/svelte/PreviewApprovalPanel.svelte +63 -0
- package/dist/svelte/PreviewApprovalPanel.svelte.d.ts +10 -0
- package/dist/svelte/PreviewApprovalPanel.svelte.d.ts.map +1 -0
- package/dist/svelte/ServiceEvidenceList.svelte +103 -0
- package/dist/svelte/ServiceEvidenceList.svelte.d.ts +8 -0
- package/dist/svelte/ServiceEvidenceList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/DevelopmentRequestForm.svelte +70 -0
- package/dist/svelte/components/DevelopmentRequestForm.svelte.d.ts +19 -0
- package/dist/svelte/components/DevelopmentRequestForm.svelte.d.ts.map +1 -0
- package/dist/svelte/components/DevelopmentRequestList.svelte +218 -0
- package/dist/svelte/components/DevelopmentRequestList.svelte.d.ts +22 -0
- package/dist/svelte/components/DevelopmentRequestList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/__tests__/DeliverySurfaces.test.js +98 -0
- package/dist/svelte/components/__tests__/DevelopmentRequest.test.js +52 -0
- package/dist/svelte/delivery-types.d.ts +36 -0
- package/dist/svelte/delivery-types.d.ts.map +1 -0
- package/dist/svelte/delivery-types.js +1 -0
- package/dist/svelte/i18n.d.ts +30 -0
- package/dist/svelte/i18n.d.ts.map +1 -1
- package/dist/svelte/i18n.js +30 -0
- package/dist/svelte/index.d.ts +18 -1
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +18 -1
- package/dist/types.d.ts +79 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +106 -10
- package/dist/ui.js.map +1 -1
- package/package.json +11 -9
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Form, Input, Textarea } from '@happyvertical/smrt-ui/forms';
|
|
3
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
4
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
5
|
+
import type {
|
|
6
|
+
DevelopmentRequestEvidence,
|
|
7
|
+
ManagedAssistanceRequestInput,
|
|
8
|
+
} from '../types.js';
|
|
9
|
+
import { M } from './i18n.js';
|
|
10
|
+
|
|
11
|
+
export interface Props {
|
|
12
|
+
requesterId: string;
|
|
13
|
+
applicationContext?: Record<string, unknown>;
|
|
14
|
+
evidence?: DevelopmentRequestEvidence[];
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
onsubmit?: (value: ManagedAssistanceRequestInput) => void | Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
requesterId,
|
|
21
|
+
applicationContext = {},
|
|
22
|
+
evidence = [],
|
|
23
|
+
disabled = false,
|
|
24
|
+
onsubmit,
|
|
25
|
+
}: Props = $props();
|
|
26
|
+
const { t } = useI18n();
|
|
27
|
+
let subject = $state('');
|
|
28
|
+
let message = $state('');
|
|
29
|
+
|
|
30
|
+
async function submit(event: SubmitEvent) {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
if (disabled || !onsubmit || !subject.trim() || !message.trim()) return;
|
|
33
|
+
await onsubmit({
|
|
34
|
+
requesterId,
|
|
35
|
+
subject: subject.trim(),
|
|
36
|
+
applicationContext,
|
|
37
|
+
conversation: [{ body: message.trim() }],
|
|
38
|
+
evidence,
|
|
39
|
+
});
|
|
40
|
+
subject = '';
|
|
41
|
+
message = '';
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<section class="assistance">
|
|
46
|
+
<Form onsubmit={submit}>
|
|
47
|
+
<header>
|
|
48
|
+
<h2>{t(M['projects.assistance.title'])}</h2>
|
|
49
|
+
<p>{t(M['projects.assistance.description'])}</p>
|
|
50
|
+
</header>
|
|
51
|
+
<label>
|
|
52
|
+
{t(M['projects.assistance.subject'])}
|
|
53
|
+
<Input bind:value={subject} required {disabled} />
|
|
54
|
+
</label>
|
|
55
|
+
<label>
|
|
56
|
+
{t(M['projects.assistance.need'])}
|
|
57
|
+
<Textarea bind:value={message} rows={4} required {disabled}></Textarea>
|
|
58
|
+
</label>
|
|
59
|
+
<footer>
|
|
60
|
+
<Button type="submit" {disabled}>
|
|
61
|
+
{t(M['projects.assistance.submit'])}
|
|
62
|
+
</Button>
|
|
63
|
+
</footer>
|
|
64
|
+
</Form>
|
|
65
|
+
</section>
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
.assistance {
|
|
69
|
+
max-width: 42rem;
|
|
70
|
+
}
|
|
71
|
+
.assistance :global(form) {
|
|
72
|
+
display: grid;
|
|
73
|
+
gap: var(--smrt-spacing-4);
|
|
74
|
+
}
|
|
75
|
+
.assistance header {
|
|
76
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
77
|
+
padding-bottom: var(--smrt-spacing-3);
|
|
78
|
+
}
|
|
79
|
+
.assistance h2,
|
|
80
|
+
.assistance p {
|
|
81
|
+
margin: 0;
|
|
82
|
+
}
|
|
83
|
+
.assistance p {
|
|
84
|
+
color: var(--smrt-color-on-surface-variant);
|
|
85
|
+
margin-top: var(--smrt-spacing-1);
|
|
86
|
+
}
|
|
87
|
+
.assistance label {
|
|
88
|
+
display: grid;
|
|
89
|
+
font-weight: 600;
|
|
90
|
+
gap: var(--smrt-spacing-1);
|
|
91
|
+
}
|
|
92
|
+
.assistance footer {
|
|
93
|
+
display: flex;
|
|
94
|
+
justify-content: flex-end;
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DevelopmentRequestEvidence, ManagedAssistanceRequestInput } from '../types.js';
|
|
2
|
+
export interface Props {
|
|
3
|
+
requesterId: string;
|
|
4
|
+
applicationContext?: Record<string, unknown>;
|
|
5
|
+
evidence?: DevelopmentRequestEvidence[];
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
onsubmit?: (value: ManagedAssistanceRequestInput) => void | Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
declare const AssistanceLauncher: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type AssistanceLauncher = ReturnType<typeof AssistanceLauncher>;
|
|
11
|
+
export default AssistanceLauncher;
|
|
12
|
+
//# sourceMappingURL=AssistanceLauncher.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssistanceLauncher.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/AssistanceLauncher.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,0BAA0B,EAC1B,6BAA6B,EAC9B,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,KAAK;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AA6DD,QAAA,MAAM,kBAAkB,2CAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import type { DeliveryEventView } from './delivery-types.js';
|
|
4
|
+
import { M } from './i18n.js';
|
|
5
|
+
|
|
6
|
+
export interface Props {
|
|
7
|
+
events?: DeliveryEventView[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { events = [] }: Props = $props();
|
|
11
|
+
const { t } = useI18n();
|
|
12
|
+
const format = (value: Date | string) =>
|
|
13
|
+
new Intl.DateTimeFormat(undefined, {
|
|
14
|
+
dateStyle: 'medium',
|
|
15
|
+
timeStyle: 'short',
|
|
16
|
+
}).format(new Date(value));
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<ol class="delivery" aria-label={t(M['projects.delivery_status.aria'])}>
|
|
20
|
+
{#each [...events].sort((a, b) => a.sequence - b.sequence) as event (event.id)}
|
|
21
|
+
<li>
|
|
22
|
+
<span class="marker" aria-hidden="true"></span>
|
|
23
|
+
<div>
|
|
24
|
+
<strong>{event.label ?? event.type.replaceAll('_', ' ')}</strong>
|
|
25
|
+
{#if event.detail}<p>{event.detail}</p>{/if}
|
|
26
|
+
<time datetime={new Date(event.occurredAt).toISOString()}>
|
|
27
|
+
{format(event.occurredAt)}
|
|
28
|
+
</time>
|
|
29
|
+
</div>
|
|
30
|
+
</li>
|
|
31
|
+
{/each}
|
|
32
|
+
</ol>
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
.delivery {
|
|
36
|
+
list-style: none;
|
|
37
|
+
margin: 0;
|
|
38
|
+
padding: 0;
|
|
39
|
+
}
|
|
40
|
+
.delivery li {
|
|
41
|
+
display: grid;
|
|
42
|
+
gap: var(--smrt-spacing-3);
|
|
43
|
+
grid-template-columns: 1rem 1fr;
|
|
44
|
+
padding-bottom: var(--smrt-spacing-5);
|
|
45
|
+
position: relative;
|
|
46
|
+
}
|
|
47
|
+
.delivery li:not(:last-child)::before {
|
|
48
|
+
background: var(--smrt-color-outline-variant);
|
|
49
|
+
content: '';
|
|
50
|
+
height: 100%;
|
|
51
|
+
left: 0.35rem;
|
|
52
|
+
position: absolute;
|
|
53
|
+
top: 0.65rem;
|
|
54
|
+
width: 1px;
|
|
55
|
+
}
|
|
56
|
+
.marker {
|
|
57
|
+
background: var(--smrt-color-primary);
|
|
58
|
+
border-radius: var(--smrt-radius-full);
|
|
59
|
+
height: 0.7rem;
|
|
60
|
+
margin-top: var(--smrt-spacing-1);
|
|
61
|
+
width: 0.7rem;
|
|
62
|
+
z-index: 1;
|
|
63
|
+
}
|
|
64
|
+
.delivery p {
|
|
65
|
+
margin: var(--smrt-spacing-1) 0;
|
|
66
|
+
}
|
|
67
|
+
.delivery time {
|
|
68
|
+
color: var(--smrt-color-on-surface-variant);
|
|
69
|
+
font-size: var(--smrt-typography-label-small-size);
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DeliveryEventView } from './delivery-types.js';
|
|
2
|
+
export interface Props {
|
|
3
|
+
events?: DeliveryEventView[];
|
|
4
|
+
}
|
|
5
|
+
declare const DeliveryStatus: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type DeliveryStatus = ReturnType<typeof DeliveryStatus>;
|
|
7
|
+
export default DeliveryStatus;
|
|
8
|
+
//# sourceMappingURL=DeliveryStatus.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeliveryStatus.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/DeliveryStatus.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI7D,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAmCD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import type { DevelopmentRequestView } from './delivery-types.js';
|
|
4
|
+
import { M } from './i18n.js';
|
|
5
|
+
|
|
6
|
+
export interface Props {
|
|
7
|
+
requests?: DevelopmentRequestView[];
|
|
8
|
+
columns?: string[];
|
|
9
|
+
onselect?: (request: DevelopmentRequestView) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
requests = [],
|
|
14
|
+
columns = ['submitted', 'triaged', 'planned', 'in_progress', 'completed'],
|
|
15
|
+
onselect,
|
|
16
|
+
}: Props = $props();
|
|
17
|
+
const { t } = useI18n();
|
|
18
|
+
const inColumn = (column: string) =>
|
|
19
|
+
requests.filter(
|
|
20
|
+
(request) =>
|
|
21
|
+
(request.deliveryStatus || request.status).toLowerCase() ===
|
|
22
|
+
column.toLowerCase(),
|
|
23
|
+
);
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<section class="board" aria-label={t(M['projects.development_board.aria'])}>
|
|
27
|
+
{#if requests.length === 0}
|
|
28
|
+
<p class="empty">{t(M['projects.development_board.empty'])}</p>
|
|
29
|
+
{:else}
|
|
30
|
+
{#each columns as column (column)}
|
|
31
|
+
<div class="lane">
|
|
32
|
+
<header>
|
|
33
|
+
<h3>{column.replaceAll('_', ' ')}</h3>
|
|
34
|
+
<span>{inColumn(column).length}</span>
|
|
35
|
+
</header>
|
|
36
|
+
<div class="lane__items">
|
|
37
|
+
{#each inColumn(column) as request (request.id)}
|
|
38
|
+
<!-- raw-primitive-allow: each board row is a semantic selection control -->
|
|
39
|
+
<button type="button" onclick={() => onselect?.(request)}>
|
|
40
|
+
<strong>{request.title ?? request.description}</strong>
|
|
41
|
+
<small>
|
|
42
|
+
{request.type}
|
|
43
|
+
{request.requesterLabel ? ` · ${request.requesterLabel}` : ''}
|
|
44
|
+
</small>
|
|
45
|
+
</button>
|
|
46
|
+
{/each}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
{/each}
|
|
50
|
+
{/if}
|
|
51
|
+
</section>
|
|
52
|
+
|
|
53
|
+
<style>
|
|
54
|
+
.board {
|
|
55
|
+
display: grid;
|
|
56
|
+
gap: var(--smrt-spacing-5);
|
|
57
|
+
grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
|
|
58
|
+
overflow-x: auto;
|
|
59
|
+
}
|
|
60
|
+
.lane {
|
|
61
|
+
min-width: 0;
|
|
62
|
+
}
|
|
63
|
+
.empty {
|
|
64
|
+
color: var(--smrt-color-on-surface-variant);
|
|
65
|
+
grid-column: 1 / -1;
|
|
66
|
+
margin: 0;
|
|
67
|
+
padding: var(--smrt-spacing-5) var(--smrt-spacing-1);
|
|
68
|
+
}
|
|
69
|
+
.lane header {
|
|
70
|
+
align-items: center;
|
|
71
|
+
border-bottom: 2px solid var(--smrt-color-primary);
|
|
72
|
+
display: flex;
|
|
73
|
+
justify-content: space-between;
|
|
74
|
+
padding: var(--smrt-spacing-2) var(--smrt-spacing-1);
|
|
75
|
+
}
|
|
76
|
+
.lane h3 {
|
|
77
|
+
font-size: var(--smrt-typography-label-medium-size);
|
|
78
|
+
margin: 0;
|
|
79
|
+
text-transform: uppercase;
|
|
80
|
+
}
|
|
81
|
+
.lane__items {
|
|
82
|
+
display: grid;
|
|
83
|
+
}
|
|
84
|
+
.lane__items button {
|
|
85
|
+
background: transparent;
|
|
86
|
+
border: 0;
|
|
87
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
88
|
+
color: inherit;
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
display: grid;
|
|
91
|
+
gap: var(--smrt-spacing-1);
|
|
92
|
+
padding: var(--smrt-spacing-4) var(--smrt-spacing-1);
|
|
93
|
+
text-align: left;
|
|
94
|
+
transition: transform 120ms ease;
|
|
95
|
+
}
|
|
96
|
+
.lane__items button:hover,
|
|
97
|
+
.lane__items button:focus-visible {
|
|
98
|
+
transform: translateX(var(--smrt-spacing-1));
|
|
99
|
+
}
|
|
100
|
+
.lane small {
|
|
101
|
+
color: var(--smrt-color-on-surface-variant);
|
|
102
|
+
}
|
|
103
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DevelopmentRequestView } from './delivery-types.js';
|
|
2
|
+
export interface Props {
|
|
3
|
+
requests?: DevelopmentRequestView[];
|
|
4
|
+
columns?: string[];
|
|
5
|
+
onselect?: (request: DevelopmentRequestView) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const DevelopmentBoard: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type DevelopmentBoard = ReturnType<typeof DevelopmentBoard>;
|
|
9
|
+
export default DevelopmentBoard;
|
|
10
|
+
//# sourceMappingURL=DevelopmentBoard.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevelopmentBoard.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/DevelopmentBoard.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAIlE,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACtD;AAoDD,QAAA,MAAM,gBAAgB,2CAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import DeliveryStatus from './DeliveryStatus.svelte';
|
|
4
|
+
import type {
|
|
5
|
+
DeliveryEventView,
|
|
6
|
+
DevelopmentRequestView,
|
|
7
|
+
} from './delivery-types.js';
|
|
8
|
+
import { M } from './i18n.js';
|
|
9
|
+
|
|
10
|
+
export interface Props {
|
|
11
|
+
request: DevelopmentRequestView;
|
|
12
|
+
events?: DeliveryEventView[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { request, events = [] }: Props = $props();
|
|
16
|
+
const { t } = useI18n();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<article
|
|
20
|
+
class="detail"
|
|
21
|
+
aria-label={t(M['projects.development_request.detail_aria'])}
|
|
22
|
+
>
|
|
23
|
+
<header>
|
|
24
|
+
<div>
|
|
25
|
+
<span>{request.type}</span>
|
|
26
|
+
<h2>{request.title ?? request.description}</h2>
|
|
27
|
+
</div>
|
|
28
|
+
<strong>{request.deliveryStatus ?? request.status}</strong>
|
|
29
|
+
</header>
|
|
30
|
+
|
|
31
|
+
{#if request.title}<p>{request.description}</p>{/if}
|
|
32
|
+
|
|
33
|
+
<dl>
|
|
34
|
+
<div>
|
|
35
|
+
<dt>{t(M['projects.development_request.status'])}</dt>
|
|
36
|
+
<dd>{request.deliveryStatus ?? request.status}</dd>
|
|
37
|
+
</div>
|
|
38
|
+
{#if request.visibility}
|
|
39
|
+
<div>
|
|
40
|
+
<dt>{t(M['projects.development_request.visibility'])}</dt>
|
|
41
|
+
<dd>{request.visibility}</dd>
|
|
42
|
+
</div>
|
|
43
|
+
{/if}
|
|
44
|
+
{#if request.requesterLabel}
|
|
45
|
+
<div>
|
|
46
|
+
<dt>{t(M['projects.development_request.requester'])}</dt>
|
|
47
|
+
<dd>{request.requesterLabel}</dd>
|
|
48
|
+
</div>
|
|
49
|
+
{/if}
|
|
50
|
+
</dl>
|
|
51
|
+
|
|
52
|
+
{#if events.length > 0}<DeliveryStatus {events} />{/if}
|
|
53
|
+
</article>
|
|
54
|
+
|
|
55
|
+
<style>
|
|
56
|
+
.detail {
|
|
57
|
+
display: grid;
|
|
58
|
+
gap: var(--smrt-spacing-5);
|
|
59
|
+
}
|
|
60
|
+
header {
|
|
61
|
+
align-items: start;
|
|
62
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
63
|
+
display: flex;
|
|
64
|
+
gap: var(--smrt-spacing-5);
|
|
65
|
+
justify-content: space-between;
|
|
66
|
+
padding-bottom: var(--smrt-spacing-4);
|
|
67
|
+
}
|
|
68
|
+
header div {
|
|
69
|
+
display: grid;
|
|
70
|
+
gap: var(--smrt-spacing-1);
|
|
71
|
+
}
|
|
72
|
+
header span,
|
|
73
|
+
dt {
|
|
74
|
+
color: var(--smrt-color-on-surface-variant);
|
|
75
|
+
font-size: var(--smrt-typography-label-medium-size);
|
|
76
|
+
}
|
|
77
|
+
h2,
|
|
78
|
+
p,
|
|
79
|
+
dl,
|
|
80
|
+
dd {
|
|
81
|
+
margin: 0;
|
|
82
|
+
}
|
|
83
|
+
dl {
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-wrap: wrap;
|
|
86
|
+
gap: var(--smrt-spacing-5);
|
|
87
|
+
}
|
|
88
|
+
dl div {
|
|
89
|
+
display: grid;
|
|
90
|
+
gap: var(--smrt-spacing-1);
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DeliveryEventView, DevelopmentRequestView } from './delivery-types.js';
|
|
2
|
+
export interface Props {
|
|
3
|
+
request: DevelopmentRequestView;
|
|
4
|
+
events?: DeliveryEventView[];
|
|
5
|
+
}
|
|
6
|
+
declare const DevelopmentRequestDetail: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type DevelopmentRequestDetail = ReturnType<typeof DevelopmentRequestDetail>;
|
|
8
|
+
export default DevelopmentRequestDetail;
|
|
9
|
+
//# sourceMappingURL=DevelopmentRequestDetail.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevelopmentRequestDetail.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/DevelopmentRequestDetail.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,qBAAqB,CAAC;AAI7B,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,sBAAsB,CAAC;IAChC,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAiDD,QAAA,MAAM,wBAAwB,2CAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
4
|
+
import type { PreviewApprovalView } from './delivery-types.js';
|
|
5
|
+
import { M } from './i18n.js';
|
|
6
|
+
|
|
7
|
+
export interface Props {
|
|
8
|
+
preview: PreviewApprovalView;
|
|
9
|
+
busy?: boolean;
|
|
10
|
+
ondecide?: (approved: boolean) => void | Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { preview, busy = false, ondecide }: Props = $props();
|
|
14
|
+
const { t } = useI18n();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<section class="preview">
|
|
18
|
+
<div>
|
|
19
|
+
<span>{t(M['projects.preview.label'], { id: preview.previewId })}</span>
|
|
20
|
+
<strong>{preview.status}</strong>
|
|
21
|
+
</div>
|
|
22
|
+
{#if preview.previewUrl}
|
|
23
|
+
<a href={preview.previewUrl} target="_blank" rel="noopener noreferrer">
|
|
24
|
+
{t(M['projects.preview.open'])}
|
|
25
|
+
</a>
|
|
26
|
+
{/if}
|
|
27
|
+
{#if preview.status === 'pending'}
|
|
28
|
+
<footer>
|
|
29
|
+
<Button
|
|
30
|
+
variant="secondary"
|
|
31
|
+
disabled={busy}
|
|
32
|
+
onclick={() => ondecide?.(false)}
|
|
33
|
+
>
|
|
34
|
+
{t(M['projects.preview.reject'])}
|
|
35
|
+
</Button>
|
|
36
|
+
<Button disabled={busy} onclick={() => ondecide?.(true)}>
|
|
37
|
+
{t(M['projects.preview.approve'])}
|
|
38
|
+
</Button>
|
|
39
|
+
</footer>
|
|
40
|
+
{/if}
|
|
41
|
+
</section>
|
|
42
|
+
|
|
43
|
+
<style>
|
|
44
|
+
.preview {
|
|
45
|
+
border-block: 1px solid var(--smrt-color-outline-variant);
|
|
46
|
+
display: grid;
|
|
47
|
+
gap: var(--smrt-spacing-4);
|
|
48
|
+
padding: var(--smrt-spacing-4) 0;
|
|
49
|
+
}
|
|
50
|
+
.preview > div {
|
|
51
|
+
display: flex;
|
|
52
|
+
justify-content: space-between;
|
|
53
|
+
}
|
|
54
|
+
.preview a {
|
|
55
|
+
color: var(--smrt-color-primary);
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
}
|
|
58
|
+
.preview footer {
|
|
59
|
+
display: flex;
|
|
60
|
+
gap: var(--smrt-spacing-3);
|
|
61
|
+
justify-content: flex-end;
|
|
62
|
+
}
|
|
63
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PreviewApprovalView } from './delivery-types.js';
|
|
2
|
+
export interface Props {
|
|
3
|
+
preview: PreviewApprovalView;
|
|
4
|
+
busy?: boolean;
|
|
5
|
+
ondecide?: (approved: boolean) => void | Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
declare const PreviewApprovalPanel: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type PreviewApprovalPanel = ReturnType<typeof PreviewApprovalPanel>;
|
|
9
|
+
export default PreviewApprovalPanel;
|
|
10
|
+
//# sourceMappingURL=PreviewApprovalPanel.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreviewApprovalPanel.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/PreviewApprovalPanel.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAI/D,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAsCD,QAAA,MAAM,oBAAoB,2CAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import type { ServiceEvidenceView } from './delivery-types.js';
|
|
4
|
+
import { M } from './i18n.js';
|
|
5
|
+
|
|
6
|
+
export interface Props {
|
|
7
|
+
entries?: ServiceEvidenceView[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { entries = [] }: Props = $props();
|
|
11
|
+
const { t } = useI18n();
|
|
12
|
+
|
|
13
|
+
const money = (amount = 0, currency = 'USD') =>
|
|
14
|
+
new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(
|
|
15
|
+
amount,
|
|
16
|
+
);
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<section
|
|
20
|
+
class="evidence"
|
|
21
|
+
aria-label={t(M['projects.service_evidence.aria'])}
|
|
22
|
+
>
|
|
23
|
+
{#each entries as entry (entry.id)}
|
|
24
|
+
<article>
|
|
25
|
+
<div>
|
|
26
|
+
<strong>{entry.context}</strong>
|
|
27
|
+
<small>
|
|
28
|
+
{entry.participant} · {(entry.durationSeconds / 3600).toFixed(2)} h ·
|
|
29
|
+
{entry.status}
|
|
30
|
+
</small>
|
|
31
|
+
</div>
|
|
32
|
+
<dl>
|
|
33
|
+
<div>
|
|
34
|
+
<dt>{t(M['projects.service_evidence.client'])}</dt>
|
|
35
|
+
<dd>{money(entry.chargeAmount, entry.currency)}</dd>
|
|
36
|
+
</div>
|
|
37
|
+
<div>
|
|
38
|
+
<dt>{t(M['projects.service_evidence.provider'])}</dt>
|
|
39
|
+
<dd>{money(entry.compensationAmount, entry.currency)}</dd>
|
|
40
|
+
</div>
|
|
41
|
+
<div>
|
|
42
|
+
<dt>{t(M['projects.service_evidence.margin'])}</dt>
|
|
43
|
+
<dd>
|
|
44
|
+
{money(
|
|
45
|
+
(entry.chargeAmount ?? 0) - (entry.compensationAmount ?? 0),
|
|
46
|
+
entry.currency,
|
|
47
|
+
)}
|
|
48
|
+
</dd>
|
|
49
|
+
</div>
|
|
50
|
+
</dl>
|
|
51
|
+
</article>
|
|
52
|
+
{/each}
|
|
53
|
+
</section>
|
|
54
|
+
|
|
55
|
+
<style>
|
|
56
|
+
.evidence {
|
|
57
|
+
border-top: 1px solid var(--smrt-color-outline-variant);
|
|
58
|
+
}
|
|
59
|
+
.evidence article {
|
|
60
|
+
align-items: center;
|
|
61
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
62
|
+
display: grid;
|
|
63
|
+
gap: var(--smrt-spacing-4);
|
|
64
|
+
grid-template-columns: 1fr auto;
|
|
65
|
+
padding: var(--smrt-spacing-4) var(--smrt-spacing-1);
|
|
66
|
+
}
|
|
67
|
+
.evidence article > div {
|
|
68
|
+
display: grid;
|
|
69
|
+
gap: var(--smrt-spacing-1);
|
|
70
|
+
}
|
|
71
|
+
.evidence small,
|
|
72
|
+
.evidence dt {
|
|
73
|
+
color: var(--smrt-color-on-surface-variant);
|
|
74
|
+
}
|
|
75
|
+
.evidence dl {
|
|
76
|
+
display: flex;
|
|
77
|
+
gap: var(--smrt-spacing-5);
|
|
78
|
+
margin: 0;
|
|
79
|
+
}
|
|
80
|
+
.evidence dl div {
|
|
81
|
+
display: grid;
|
|
82
|
+
gap: var(--smrt-spacing-1);
|
|
83
|
+
text-align: right;
|
|
84
|
+
}
|
|
85
|
+
.evidence dt {
|
|
86
|
+
font-size: var(--smrt-typography-label-medium-size);
|
|
87
|
+
}
|
|
88
|
+
.evidence dd {
|
|
89
|
+
font-variant-numeric: tabular-nums;
|
|
90
|
+
margin: 0;
|
|
91
|
+
}
|
|
92
|
+
@media (max-width: 40rem) {
|
|
93
|
+
.evidence article {
|
|
94
|
+
grid-template-columns: 1fr;
|
|
95
|
+
}
|
|
96
|
+
.evidence dl {
|
|
97
|
+
justify-content: space-between;
|
|
98
|
+
}
|
|
99
|
+
.evidence dl div {
|
|
100
|
+
text-align: left;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ServiceEvidenceView } from './delivery-types.js';
|
|
2
|
+
export interface Props {
|
|
3
|
+
entries?: ServiceEvidenceView[];
|
|
4
|
+
}
|
|
5
|
+
declare const ServiceEvidenceList: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type ServiceEvidenceList = ReturnType<typeof ServiceEvidenceList>;
|
|
7
|
+
export default ServiceEvidenceList;
|
|
8
|
+
//# sourceMappingURL=ServiceEvidenceList.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceEvidenceList.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/ServiceEvidenceList.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAI/D,MAAM,WAAW,KAAK;IACpB,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAqDD,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|