Skip to content

Commit

Permalink
Update SHL Label and remove SHL page components
Browse files Browse the repository at this point in the history
  • Loading branch information
daniellrgn committed Jan 30, 2024
1 parent 66ce54e commit 9f549d7
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/lib/AddFileLTT.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
let shcsToAdd: SHCFile[] = [];
let singleIPS = true;
let label = 'SHL from ' + new Date().toISOString().slice(0, 10);
let label = 'Let’s Talk Tech Choices Summary (' + new Date().toISOString().slice(0, 10) + ')';
let expiration: number | null = -1;
let type = 'password';
let showPassword = false;
Expand Down
257 changes: 257 additions & 0 deletions src/lib/HealthLinkLTT.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<script lang="ts">
import QRCode from 'qrcode';
import { getContext } from 'svelte';
import {
Button,
Card,
CardBody,
CardFooter,
CardHeader,
CardSubtitle,
CardText,
CardTitle,
Col,
FormGroup,
Icon,
Input,
Label,
Modal,
ModalBody,
ModalHeader,
ModalFooter,
Row
} from 'sveltestrap';
import { goto } from '$app/navigation';
import type { Writable } from 'svelte/store';
import type { SHLAdminParams, SHLClient } from './managementClient';
export let shl: SHLAdminParams;
let shlControlled: SHLAdminParams;
let open = false;
const toggle = () => (open = !open);
function syncProps(shl: SHLAdminParams) {
shlControlled = JSON.parse(JSON.stringify(shl));
}
$: syncProps(shl);
let shlStore: Writable<SHLAdminParams[]> = getContext('shlStore');
let shlClient: SHLClient = getContext('shlClient');
let copyNotice = '';
let href: Promise<string>;
let qrCode: Promise<string>;
let showPassword = false;
$: type = showPassword ? 'text' : 'password';
$: icon = showPassword ? 'eye-slash-fill' : 'eye-fill';
$: {
href = getUrl(shl);
}
$: {
qrCode = href.then((r) => QRCode.toDataURL(r, { errorCorrectionLevel: 'M' }));
}
let canShare = navigator?.canShare?.({ url: 'https://example.com', title: 'Title' });
async function getUrl(shl: SHLAdminParams) {
let shlMin = {
id: shl.id,
managementToken: shl.managementToken,
encryptionKey: shl.encryptionKey,
files: []
}
return await shlClient.toLink(shlMin);
}
async function copyShl() {
let copyNoticePrev = copyNotice;
copyNotice = '...';
let text = await getUrl(shl);
navigator.clipboard.writeText(text);
copyNotice = 'Copied!';
setTimeout(() => {
copyNotice = copyNoticePrev;
}, 1000);
}
async function deleteShl() {
shlClient.deleteShl(shl);
$shlStore = $shlStore.filter((l) => l.id !== shl.id);
toggle();
goto('/');
}
async function addFile() {
goto(`/create?shlid=${shl.id}`);
}
async function deleteFile(fileContent:string) {
shl = await shlClient.deleteFile(shl, fileContent).then((shl) => {
let updatedFiles = shl.files.filter((f) => f.contentEncrypted !== fileContent);
shl.files = updatedFiles;
return shl;
});
$shlStore[$shlStore.findIndex(obj => obj.id === shl.id)] = shl;
}
</script>
<Row cols={{ md: 2, sm: 1 }}>
<Col>
<Card class="mb-3" color="light">
<CardHeader>
<CardTitle>
<Icon name={shl.passcode ? 'lock' : 'unlock'} />
{shl.label}</CardTitle
>
</CardHeader>
<CardBody>
{#if shl.exp}
<CardSubtitle color="success">
Expires: {new Date(shl.exp * 1000).toISOString().slice(0, 10)}
</CardSubtitle>
{/if}

<CardText>
{#await qrCode then dataUrl}
<p class="logo">
<img class="qr" alt="QR Code for SHL" src={dataUrl} />
<img class="logo" alt="Let's Talk Tech Logo" src='/img/ltt-logo.svg' />
</p>
{/await}
</CardText>
</CardBody>
<CardFooter>
{#if canShare}
<Button
size="sm"
color="success"
on:click={async () => {
navigator.share({ url: await href, title: shl.label });
}}><Icon name="share" /> Share</Button
>
{/if}
<Button size="sm" color="success" on:click={copyShl} disabled={!!copyNotice}>
<Icon name="clipboard" />
{#if copyNotice}
{copyNotice}
{:else}
Copy Link
{/if}
</Button>
{#await href then href}
<Button size="sm" color="success" {href} target="_blank">
<Icon name="box-arrow-up-right" /> View IPS
</Button>
{/await}
</CardFooter>
</Card>
</Col>
<Col>
<FormGroup class="label shlbutton">
<Label for="label">Label for SMART Health Link</Label>
<Input
name="label"
maxlength={40}
type="text"
bind:value={shlControlled.label}
placeholder="label"
/>
<Button
size="sm"
color="secondary"
disabled={(shl.label || '') === (shlControlled.label || '')}
on:click={async () => {
$shlStore = $shlStore.map((e) => {
if (e.id === shl.id) {
shl = { ...shl, label: shlControlled.label };
return shl;
} else {
return e;
}
});
}}>
<Icon name="sticky" /> Update Label
</Button>
</FormGroup>
<FormGroup class="passcode shlbutton">
<Label for="passcode">Add or Update Passcode (optional)</Label>
<div style="position:relative">
<Input
maxlength={40}
name="passcode"
type={type}
bind:value={shlControlled.passcode}
placeholder="Assign Passcode"
/>
<Icon name={icon}
style="position: absolute;
cursor: pointer;
height: 25px;
width: 20px;
top: 6px;
right: 10px;
color: rgb(50, 50, 50);"
onclick={() => showPassword = !showPassword}/>
</div>
<Button
size="sm"
color="secondary"
disabled={(shl.passcode || '') === (shlControlled.passcode || '')}
on:click={async () => {
await shlClient.resetShl({ ...shl, passcode: shlControlled.passcode });
$shlStore = $shlStore.map((e) =>
e.id === shl.id ? { ...shl, passcode: shlControlled.passcode } : e
);
}}><Icon name="lock" /> Update Passcode</Button>
</FormGroup>
<FormGroup class="shlbutton">
<Button size="sm" on:click={toggle} color="danger">Delete SMART Health Link</Button>
<Modal isOpen={open} backdrop="static" {toggle}>
<ModalHeader {toggle}>Delete SMART Health Link</ModalHeader>
<ModalBody>
"{shl.label}" will be permanently deleted. Continue?
</ModalBody>
<ModalFooter>
<Button color="danger" on:click={deleteShl}><Icon name="trash" /> Delete SHL</Button>
<Button color="secondary" on:click={toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</FormGroup>
</Col>
</Row>

<style>
img.qr {
height: 100%;
}
p.logo {
position: relative;
width: 250px;
height: 250px;
}
img.logo {
position: absolute;
background: white;
width: 100px;
left: calc(50% - 50px);
top: calc(50% - 1em);
border: 2px solid white;
box-sizing: border-box;
}
:global(.shlbutton) {
width: 300px !important;
}
:global(.shlbutton input, .shlbutton button) {
width: 100%;
display: inline-block;
}
:global(div.card) {
max-width: 300px;
}
:global(.card-title) {
font-size: 1em;
font-weight: bold;
}
</style>
4 changes: 2 additions & 2 deletions src/routes/view/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { page } from '$app/stores';
import { getContext } from 'svelte';
import type { Writable } from 'svelte/store';
import HealthLink from '$lib/HealthLink.svelte';
import HealthLinkLTT from '$lib/HealthLinkLTT.svelte';
import type { SHLAdminParams } from '$lib/managementClient';
let shlStore: Writable<SHLAdminParams[]> = getContext('shlStore');
let shl: SHLAdminParams | undefined;
Expand All @@ -12,7 +12,7 @@
</script>

{#if shl}
<HealthLink {shl} />
<HealthLinkLTT {shl} />
{:else}
SHLink {$page.params.id} Not Found
{/if}

0 comments on commit 9f549d7

Please sign in to comment.