Skip to content

Commit

Permalink
Refactor to Amplify JS 6; package version updates
Browse files Browse the repository at this point in the history
  • Loading branch information
yyao84 committed Apr 2, 2024
1 parent 9a9889e commit 602fdce
Show file tree
Hide file tree
Showing 34 changed files with 2,331 additions and 3,909 deletions.
17 changes: 15 additions & 2 deletions .github/workflows/ui-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,21 @@ jobs:
run: yarn install --immutable --immutable-cache --check-cache

- name: Mock aws-custom.json
run: >
echo "{\"healthScribeServiceRole\":\"arn:aws:iam::0123456789012:role/healthScribeServiceRole\"}" > ./aws-custom.json
run: |
cat > ./aws-custom.json << EOF
{
"healthScribeServiceRole": "arn:aws:iam::0123456789012:role/healthScribeServiceRole"
}
EOF
- name: Mock amplifyconfiguration.json
run: |
cat > ./amplifyconfiguration.json << EOF
{
"aws_project_region": "us-east-1",
"aws_user_files_s3_bucket": "s3bucket",
}
EOF
- name: Type Check
run: yarn run type-check
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ storage using [Amazon Simple Storage Service (S3)](https://aws.amazon.com/s3/).
- [FAQ](#faq)
- [The public sample repo has been updated. How do I update my local deployment to the latest code?](#the-public-sample-repo-has-been-updated-how-do-i-update-my-local-deployment-to-the-latest-code)
- [Can I use this UI with existing AWS HealthScribe jobs?](#can-i-use-this-ui-with-existing-aws-healthscribe-jobs)
- [Can I deploy this demo from a private repository?](#can-i-deploy-this-demo-from-a-private-repository)
- [Security](#security)
- [License](#license)
<!-- TOC -->
Expand Down
6 changes: 3 additions & 3 deletions amplify/backend/custom/addBucketLogging/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@aws-amplify/cli-extensibility-helper": "^3.0.16",
"constructs": "^10.2.70"
"@aws-amplify/cli-extensibility-helper": "^3.0.26",
"constructs": "^10.3.0"
},
"devDependencies": {
"typescript": "^5.2.2"
"typescript": "^5.4.3"
}
}
6 changes: 3 additions & 3 deletions amplify/backend/function/addBucketLogging/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"main": "index.js",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/client-s3": "^3.400.0",
"axios": "^1.5.0",
"axios-retry": "^3.7.0"
"@aws-sdk/client-s3": "^3.540.0",
"axios": "^1.6.8",
"axios-retry": "^3.9.1"
}
}
4 changes: 2 additions & 2 deletions amplify/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@aws-amplify/cli-extensibility-helper": "^3.0.16"
"@aws-amplify/cli-extensibility-helper": "^3.0.26"
},
"devDependencies": {
"typescript": "^5.2.2"
"typescript": "^5.4.3"
}
}
54 changes: 28 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,57 @@
"type-check": "tsc"
},
"dependencies": {
"@aws-amplify/ui": "^5.9.0",
"@aws-amplify/ui-react": "^5.3.3",
"@aws-sdk/client-comprehendmedical": "^3.529.1",
"@aws-sdk/client-polly": "^3.529.1",
"@aws-sdk/client-s3": "^3.529.1",
"@aws-sdk/lib-storage": "^3.529.1",
"@aws-sdk/s3-request-presigner": "^3.529.1",
"@cloudscape-design/collection-hooks": "^1.0.38",
"@cloudscape-design/components": "^3.0.566",
"@cloudscape-design/design-tokens": "^3.0.34",
"@cloudscape-design/global-styles": "^1.0.24",
"ace-builds": "^1.32.7",
"aws-amplify": "^5.3.17",
"axios": "^1.6.7",
"@aws-amplify/ui": "^6.0.12",
"@aws-amplify/ui-react": "^6.1.6",
"@aws-sdk/client-comprehendmedical": "^3.540.0",
"@aws-sdk/client-polly": "^3.540.0",
"@aws-sdk/client-s3": "^3.540.0",
"@aws-sdk/client-transcribe": "^3.540.0",
"@aws-sdk/lib-storage": "^3.540.0",
"@aws-sdk/s3-request-presigner": "^3.540.0",
"@cloudscape-design/collection-hooks": "^1.0.43",
"@cloudscape-design/components": "^3.0.593",
"@cloudscape-design/design-tokens": "^3.0.35",
"@cloudscape-design/global-styles": "^1.0.26",
"ace-builds": "^1.32.9",
"aws-amplify": "^6.0.26",
"axios": "^1.6.8",
"crunker": "^2.4.0",
"dayjs": "^1.11.10",
"framer-motion": "^11.0.8",
"framer-motion": "^11.0.24",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-ace": "^10.1.0",
"react-ace": "^11.0.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-hot-toast": "^2.4.1",
"react-router-dom": "^6.22.3",
"timekeeper": "^2.3.1",
"use-debounce": "^10.0.0",
"uuid4": "^2.0.3",
"wavesurfer.js": "7.7.3"
"wavesurfer.js": "7.7.7"
},
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/lodash": "^4.14.202",
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
"@types/lodash": "^4.17.0",
"@types/node": "^20.12.2",
"@types/react": "^18.2.73",
"@types/react-dom": "^18.2.23",
"@types/uuid4": "^2.0.3",
"@types/wavesurfer.js": "^6.0.12",
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
"@typescript-eslint/eslint-plugin": "^7.5.0",
"@typescript-eslint/parser": "^7.5.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.0",
"eslint-plugin-react": "^7.34.1",
"pre-commit": "^1.2.2",
"prettier": "^3.2.5",
"typescript": "^5.4.2",
"vite": "^5.1.5",
"vite-plugin-static-copy": "^1.0.1"
"typescript": "^5.4.3",
"vite": "^5.2.7",
"vite-plugin-static-copy": "^1.0.2"
},
"pre-commit": "lint",
"license": "MIT",
Expand Down
5 changes: 0 additions & 5 deletions src/aws-exports.d.ts

This file was deleted.

10 changes: 2 additions & 8 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@ import { Navigate, Route, Routes } from 'react-router-dom';
import AppLayout from '@cloudscape-design/components/app-layout';
import Flashbar from '@cloudscape-design/components/flashbar';

import { Amplify } from 'aws-amplify';

import awsExports from '@/aws-exports';
import Breadcrumbs from '@/components/Breadcrumbs';
import SideNav from '@/components/SideNav';
import SuspenseLoader from '@/components/SuspenseLoader';
import TopNav from '@/components/TopNav';
import Welcome from '@/components/Welcome';
import { useAuthContext } from '@/store/auth';
import { useNotificationsContext } from '@/store/notifications';
import { isUserEmailVerified } from '@/utils/Auth/isUserEmailVerified';

Amplify.configure(awsExports);

// Lazy components
const Debug = lazy(() => import('@/components/Debug'));
Expand All @@ -30,12 +24,12 @@ const NewConversation = lazy(() => import('@/components/NewConversation'));
const GenerateAudio = lazy(() => import('@/components/GenerateAudio'));

export default function App() {
const { user } = useAuthContext();
const { isUserAuthenticated } = useAuthContext();
const { flashbarItems } = useNotificationsContext();

const content = (
<Suspense fallback={<SuspenseLoader />}>
{isUserEmailVerified(user) ? (
{isUserAuthenticated ? (
<Routes>
<Route index element={<Welcome />} />
<Route path="/debug" element={<Debug />} />
Expand Down
27 changes: 11 additions & 16 deletions src/components/Auth/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
// This is a modal authentication component that displays the AWS Amplify Authenticator.
import React, { useMemo } from 'react';

import * as awsui from '@cloudscape-design/design-tokens';
import Box from '@cloudscape-design/components/box';
import Button from '@cloudscape-design/components/button';
import Modal from '@cloudscape-design/components/modal';
import SpaceBetween from '@cloudscape-design/components/space-between';

import { Authenticator, ThemeProvider, defaultDarkModeOverride } from '@aws-amplify/ui-react';
import { Authenticator, Theme, ThemeProvider, defaultDarkModeOverride } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import { useAppThemeContext } from '@/store/appTheme';
Expand Down Expand Up @@ -42,30 +43,24 @@ export default function Auth({ visible, setVisible }: AuthParams) {
/**
* Amplify-UI's <Authentication /> uses 80 for the button, 90 for hover
* Override to Cloudscape colors - https://cloudscape.design/foundation/visual-foundation/colors/
* light mode primary : blue-800 #033160
* light mode hover : blue-600 #0972d3
* dark mode primary : blue-500 #539fe5
* dark mode hover : blue-400 #89bdee
*/
const theme = {
const amplifyTheme: Theme = {
name: 'AuthTheme',
overrides: [defaultDarkModeOverride],
tokens: {
colors: {
brand: {
primary: {
80: appTheme === 'theme.light' ? '#033160' : '#539fe5',
90: appTheme === 'theme.light' ? '#0972d3' : '#89bdee',
100: appTheme === 'theme.light' ? '#033160' : '#539fe5',
},
primary: {
80: awsui.colorBackgroundButtonPrimaryActive,
90: awsui.colorBackgroundButtonPrimaryDefault,
100: awsui.colorBackgroundButtonPrimaryActive,
},
},
components: {
tabs: {
item: {
_hover: {
color: {
value: appTheme === 'theme.light' ? '#0972d3' : '#89bdee',
value: awsui.colorBackgroundButtonPrimaryDefault,
},
},
},
Expand All @@ -75,9 +70,9 @@ export default function Auth({ visible, setVisible }: AuthParams) {
};

const colorMode = useMemo(() => {
if (appTheme === 'theme.light') {
if (appTheme.color === 'appTheme.light') {
return 'light';
} else if (appTheme === 'theme.dark') {
} else if (appTheme.color === 'appTheme.dark') {
return 'dark';
} else {
return 'system';
Expand All @@ -98,7 +93,7 @@ export default function Auth({ visible, setVisible }: AuthParams) {
</Box>
}
>
<ThemeProvider theme={theme} colorMode={colorMode}>
<ThemeProvider theme={amplifyTheme} colorMode={colorMode}>
<Authenticator components={authUiComponents}>
<Box variant="p" textAlign="center">
You will be redirected shortly.
Expand Down
21 changes: 12 additions & 9 deletions src/components/Conversation/Conversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { useParams } from 'react-router-dom';
import ContentLayout from '@cloudscape-design/components/content-layout';
import Grid from '@cloudscape-design/components/grid';

import { MedicalScribeJob } from '@aws-sdk/client-transcribe';

import { useAudio } from '@/hooks/useAudio';
import { useNotificationsContext } from '@/store/notifications';
import { IAuraClinicalDocOutput, IAuraTranscriptOutput } from '@/types/HealthScribe';
Expand All @@ -17,14 +19,13 @@ import LeftPanel from './LeftPanel';
import RightPanel from './RightPanel';
import TopPanel from './TopPanel';
import ViewResults from './ViewResults';
import { HealthScribeJob } from './types';

export default function Conversation() {
const { conversationName } = useParams();
const { addFlashMessage } = useNotificationsContext();

const [jobLoading, setJobLoading] = useState(true); // Is getHealthScribeJob in progress
const [jobDetails, setJobDetails] = useState<HealthScribeJob | null>(null); // HealthScribe job details
const [jobDetails, setJobDetails] = useState<MedicalScribeJob | null>(null); // HealthScribe job details
const [viewResultsModal, setViewResultsModal] = useState<boolean>(false); // Is view results modal open

const [clinicalDocument, setClinicalDocument] = useState<IAuraClinicalDocOutput | null>(null);
Expand All @@ -47,19 +48,21 @@ export default function Conversation() {
try {
setJobLoading(true);
const getHealthScribeJobRsp = await getHealthScribeJob({ MedicalScribeJobName: conversationName });
const MedicalScribeJob = getHealthScribeJobRsp.data?.MedicalScribeJob;
if (Object.keys(MedicalScribeJob).length > 0) {
setJobDetails(MedicalScribeJob);
const medicalScribeJob = getHealthScribeJobRsp?.MedicalScribeJob;

if (typeof medicalScribeJob === 'undefined') return;
if (Object.keys(medicalScribeJob).length > 0) {
setJobDetails(medicalScribeJob);
}

// Get Clinical Document from result S3 URL
const clinicalDocumentUri = MedicalScribeJob.MedicalScribeOutput?.ClinicalDocumentUri;
const clinicalDocumentRsp = await getObject(getS3Object(clinicalDocumentUri));
const clinicalDocumentUri = medicalScribeJob.MedicalScribeOutput?.ClinicalDocumentUri;
const clinicalDocumentRsp = await getObject(getS3Object(clinicalDocumentUri || ''));
setClinicalDocument(JSON.parse((await clinicalDocumentRsp?.Body?.transformToString()) || ''));

// Get Transcript File from result S3 URL
const transcriptFileUri = MedicalScribeJob.MedicalScribeOutput?.TranscriptFileUri;
const transcriptFileRsp = await getObject(getS3Object(transcriptFileUri));
const transcriptFileUri = medicalScribeJob.MedicalScribeOutput?.TranscriptFileUri;
const transcriptFileRsp = await getObject(getS3Object(transcriptFileUri || ''));
setTranscriptFile(JSON.parse((await transcriptFileRsp?.Body?.transformToString()) || ''));
} catch (e) {
setJobDetails(null);
Expand Down
5 changes: 3 additions & 2 deletions src/components/Conversation/TopPanel/TopPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Header from '@cloudscape-design/components/header';
import SpaceBetween from '@cloudscape-design/components/space-between';
import Spinner from '@cloudscape-design/components/spinner';

import { MedicalScribeJob } from '@aws-sdk/client-transcribe';
import reduce from 'lodash/reduce';
import WaveSurfer from 'wavesurfer.js';
import RegionsPlugin from 'wavesurfer.js/dist/plugins/regions';
Expand All @@ -22,13 +23,13 @@ import { IAuraTranscriptOutput } from '@/types/HealthScribe';
import { getPresignedUrl, getS3Object } from '@/utils/S3Api';

import AudioControls from '../../Common/AudioControls';
import { HealthScribeJob, SmallTalkList } from '../types';
import { SmallTalkList } from '../types';
import styles from './TopPanel.module.css';
import { extractRegions } from './extractRegions';

type TopPanelProps = {
jobLoading: boolean;
jobDetails: HealthScribeJob | null;
jobDetails: MedicalScribeJob | null;
transcriptFile: IAuraTranscriptOutput | null;
wavesurfer: React.MutableRefObject<WaveSurfer | undefined>;
smallTalkCheck: boolean;
Expand Down
10 changes: 5 additions & 5 deletions src/components/Conversation/ViewResults/ViewResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ import 'ace-builds/src-noconflict/theme-twilight';
import { useAppThemeContext } from '@/store/appTheme';

type ReadOnlyAceEditorProps = {
appTheme: string;
appColor: string;
value: string;
};

function ReadOnlyAceEditor({ appTheme, value }: ReadOnlyAceEditorProps) {
function ReadOnlyAceEditor({ appColor, value }: ReadOnlyAceEditorProps) {
return (
<AceEditor
name="transcriptJsonEditor"
mode="json"
theme={appTheme === 'theme.light' ? 'github' : 'twilight'}
theme={appColor === 'theme.light' ? 'github' : 'twilight'}
value={value}
width="100%"
wrapEnabled={true}
Expand Down Expand Up @@ -52,10 +52,10 @@ export default function ViewResults({
<Modal size="max" onDismiss={() => setVisible(false)} visible={visible} header="HealthScribe Results">
<Grid gridDefinition={[{ colspan: 6 }, { colspan: 6 }]}>
<Container header={<Header variant="h3">Transcript</Header>}>
<ReadOnlyAceEditor appTheme={appTheme} value={transcriptString} />
<ReadOnlyAceEditor appColor={appTheme.color} value={transcriptString} />
</Container>
<Container header={<Header variant="h3">Clinical Documentation</Header>}>
<ReadOnlyAceEditor appTheme={appTheme} value={clinicalDocumentString} />
<ReadOnlyAceEditor appColor={appTheme.color} value={clinicalDocumentString} />
</Container>
</Grid>
</Modal>
Expand Down
Loading

0 comments on commit 602fdce

Please sign in to comment.