Skip to content

Commit 8aeaa08

Browse files
committed
Allow storing multiple SHLs
Workaround popper.js import bug Valid GH workflows
1 parent 33456e7 commit 8aeaa08

File tree

6 files changed

+80
-25
lines changed

6 files changed

+80
-25
lines changed

.github/workflows/deploy.yml

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ jobs:
2525
- name: Install dependencies
2626
run: npm ci
2727

28+
- name: Patch per https://github.com/trasherdk/sveltestrap/issues/5
29+
run: ./fix-popper.sh
30+
2831
- name: Build SvelteKit
2932
run: npm run build
3033

fix-popper.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
sed -i '/2\.11\.6/a \ \ "type": "module",' node_modules/@popperjs/core/package.json

src/AddFile.svelte

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
let submitting = false;
1313
let summaryUrl = EXAMPLE_IPS;
1414
let inputUrl: HTMLFormElement;
15+
let label = "SHL from " + new Date().toISOString().slice(0, 10);
1516
1617
onMount(() => {
1718
inputUrl.getElementsByTagName('input').item(0)?.select();
@@ -49,7 +50,8 @@
4950
verifiableCredential: [shc]
5051
},
5152
patient,
52-
content
53+
content,
54+
label
5355
});
5456
} catch (e) {
5557
console.log('Failed', e);
@@ -85,6 +87,10 @@
8587
<Label>Bundle <code>.json</code>, or signed <code>.smart-health-card</code></Label>
8688
<Input width="100%" type="text" bind:value={summaryUrl} />
8789
</FormGroup>
90+
<FormGroup>
91+
<Label>Label</Label>
92+
<Input width="100%" type="text" bind:value={label} />
93+
</FormGroup>
8894
<Button color="primary" disabled={!summaryUrlValidated || submitting} type="submit">
8995
{#if !submitting}
9096
Fetch IPS

src/routes/+layout.svelte

+59-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,34 @@
11
<script lang="ts">
2-
import 'bootstrap/dist/css/bootstrap.min.css';
3-
import { Col, Container, Row } from 'sveltestrap';
4-
import { Nav, Navbar, NavbarBrand, NavItem, NavLink } from 'sveltestrap';
2+
import { Col, Container, Icon, Row, Styles } from 'sveltestrap';
3+
import { browser } from '$app/environment';
54
import { setContext } from 'svelte';
6-
import { SHLClient } from '../managementClient';
75
import { writable } from 'svelte/store';
6+
import {
7+
ButtonDropdown,
8+
DropdownItem,
9+
DropdownMenu,
10+
DropdownToggle,
11+
Navbar,
12+
NavbarBrand
13+
} from 'sveltestrap';
14+
import { SHLClient, type SHLAdminParams } from '../managementClient';
15+
16+
const LOCAL_STORAGE_KEY = 'shlips_store';
17+
let shlStore = writable<SHLAdminParams[]>(
18+
browser && window.localStorage[LOCAL_STORAGE_KEY]
19+
? JSON.parse(window.localStorage[LOCAL_STORAGE_KEY])
20+
: []
21+
);
22+
23+
let selectedShl = writable<number | undefined>($shlStore.length > 0 ? 0 : undefined);
24+
setContext('selectedShl', selectedShl);
25+
26+
$: {
27+
if (browser && $shlStore) window.localStorage[LOCAL_STORAGE_KEY] = JSON.stringify($shlStore);
28+
}
29+
30+
setContext('shlStore', shlStore);
31+
832
let shlClient = new SHLClient();
933
setContext('shlClient', shlClient);
1034
@@ -13,19 +37,44 @@
1337
</script>
1438

1539
<Container class="main" fluid>
40+
<Styles />
1641
<Row>
1742
<Col>
1843
<Navbar>
1944
<NavbarBrand href="/">SMART Health Links for IPS</NavbarBrand>
20-
<Nav class="ms-auto" navbar>
21-
<NavItem>
22-
<NavLink
45+
<ButtonDropdown size="sm">
46+
<DropdownToggle color="primary" caret>Actions...</DropdownToggle>
47+
<DropdownMenu>
48+
<DropdownItem on:click={() => ($selectedShl = undefined)}>Add New SHLink</DropdownItem>
49+
<DropdownItem on:click={() => $reset++}>Reset Demo</DropdownItem>
50+
{#if $shlStore.length > 0}
51+
<DropdownItem divider />
52+
<DropdownItem header>Stored SHLinks</DropdownItem>
53+
{#each $shlStore as shl, i}
54+
<DropdownItem
55+
on:click={() => {
56+
if ($selectedShl !== undefined) {
57+
if (i < $selectedShl) {
58+
$selectedShl--;
59+
}
60+
}
61+
const newStore = [...$shlStore];
62+
newStore.splice(i, 1);
63+
$shlStore = newStore;
64+
if ($shlStore.length == 0) {
65+
$selectedShl = undefined;
66+
}
67+
}}><Icon name="trash" /> {shl.label || `SHLink ${i + 1}`}</DropdownItem
68+
>
69+
{/each}
70+
{/if}
71+
</DropdownMenu>
72+
</ButtonDropdown>
73+
<!-- <NavLink
2374
on:click={() => {
2475
$reset++;
2576
}}>Reset SHL</NavLink
26-
>
27-
</NavItem>
28-
</Nav>
77+
> -->
2978
</Navbar>
3079
</Col>
3180
</Row>

src/routes/+page.svelte

+8-14
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,27 @@
88
import type { SHCRetrieveEvent } from '../types';
99
1010
let shlClient: SHLClient = getContext('shlClient');
11-
11+
let shlStore: Writable<SHLAdminParams[]> = getContext('shlStore');
12+
let selectedShl: Writable<number | undefined> = getContext('selectedShl');
1213
let reset: Writable<number> = getContext('reset');
1314
14-
const LOCAL_STORAGE_KEY = 'shlips_store';
15-
let shl: SHLAdminParams | undefined =
16-
browser && window.localStorage[LOCAL_STORAGE_KEY]
17-
? JSON.parse(window.localStorage[LOCAL_STORAGE_KEY])
18-
: undefined;
19-
20-
$: if ($reset) shl = undefined;
21-
$: {
22-
if (browser && shl) window.localStorage[LOCAL_STORAGE_KEY] = JSON.stringify(shl);
23-
}
15+
$: if ($reset) $shlStore = [];
2416
2517
async function newShlFromShc(details: SHCRetrieveEvent) {
2618
const shlCreated = await shlClient.createShl();
2719
shlClient.addFile(shlCreated, details.shc, 'application/smart-health-card');
20+
shlCreated.label = details.label;
2821
return shlCreated;
2922
}
3023
</script>
3124

32-
{#if shl}
33-
<HealthLink {shl} />
25+
{#if $selectedShl !== undefined}
26+
<HealthLink shl={$shlStore[$selectedShl]} />
3427
{:else if browser}
3528
<AddFile
3629
on:shc-retrieved={async ({ detail }) => {
37-
shl = await newShlFromShc(detail);
30+
$shlStore = [...$shlStore, await newShlFromShc(detail)];
31+
$selectedShl = $shlStore.length - 1;
3832
}}
3933
/>
4034
{:else}

src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
export interface SHCRetrieveEvent {
33
shc: SHCFile;
44
patient: string;
5+
label?: string;
56
content: Bundle;
67
}
78

0 commit comments

Comments
 (0)