Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/scaffold.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,10 @@ async def _create_location_tree(

organization_ids = data.get("organization_ids", [])
if organization_ids:
allowed_types_for_orgs = {"HOSPITAL", "CLINIC", "PRACTICE", "TEAM"}
allowed_types_for_orgs = {"HOSPITAL", "CLINIC", "PRACTICE", "TEAM", "WARD"}
if location_type.value not in allowed_types_for_orgs:
logger.warning(
f"Organization IDs can only be assigned to HOSPITAL, CLINIC, PRACTICE, or TEAM. "
f"Organization IDs can only be assigned to HOSPITAL, CLINIC, PRACTICE, TEAM, or WARD. "
f"Skipping organization assignment for location '{name}' (type: {location_type.value})"
)
else:
Expand Down
8 changes: 4 additions & 4 deletions web/components/layout/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export const SurveyModal = () => {
}
}

setupSurvey().catch(() => {})
setupSurvey().catch(() => { })
}, [config.onboardingSurveyUrl, config.weeklySurveyUrl, user?.id, onboardingSurveyCompleted, weeklySurveyLastCompleted, surveyLastDismissed, isSurveyOpen])

const handleDismiss = () => {
Expand Down Expand Up @@ -498,7 +498,7 @@ export const Sidebar = ({ isOpen, onClose, ...props }: SidebarProps) => {
{translation('teams')}
</div>
</ExpandableHeader>
<ExpandableContent className="gap-y-0 pl-4 p-0">
<ExpandableContent className="!max-h-none !h-auto !overflow-visible gap-y-0 pl-4 p-0">
{context.teams.map(team => (
<SidebarLink key={team.id} href={`${locationRoute}/${team.id}`} onClick={onClose}>
{team.title}
Expand Down Expand Up @@ -526,7 +526,7 @@ export const Sidebar = ({ isOpen, onClose, ...props }: SidebarProps) => {
{translation('wards')}
</div>
</ExpandableHeader>
<ExpandableContent className="gap-y-0 pl-4 p-0">
<ExpandableContent className="!max-h-none !h-auto !overflow-visible gap-y-0 pl-4 p-0">
{context.wards.map(ward => (
<SidebarLink key={ward.id} href={`${locationRoute}/${ward.id}`} onClick={onClose}>
{ward.title}
Expand Down Expand Up @@ -554,7 +554,7 @@ export const Sidebar = ({ isOpen, onClose, ...props }: SidebarProps) => {
{translation('clinics')}
</div>
</ExpandableHeader>
<ExpandableContent className="gap-y-0 pl-4 p-0">
<ExpandableContent className="!max-h-none !h-auto !overflow-visible gap-y-0 pl-4 p-0">
{context.clinics.map(clinic => (
<SidebarLink key={clinic.id} href={`${locationRoute}/${clinic.id}`} onClick={onClose}>
{clinic.title}
Expand Down
16 changes: 8 additions & 8 deletions web/components/locations/LocationSelectionDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,25 @@ const LocationTreeItem = ({

if (!hasChildren) {
return (
<div className="flex-row-2 items-center rounded-lg px-4 py-1 transition-colors hover:bg-surface-hover">
<MinusIcon className="size-6 text-description" />
<div className="flex-row-2 items-center rounded-lg px-2 py-1 transition-colors hover:bg-surface-hover">
<MinusIcon className="size-6 text-description flex-shrink-0" />
{labelContent}
</div>
)
}

return (
<div className="flex flex-col">
<div className="flex flex-col mb-3">
<Expandable
label={labelContent}
clickOnlyOnHeader={true}
isExpanded={isExpanded}
onChange={(isOpen) => {
onExpandToggle(node.id, isOpen)
}}
className="!shadow-none !bg-transparent !rounded-none"
className="!shadow-none !bg-transparent !rounded-none w-full"
headerClassName="px-2 hover:bg-surface-hover rounded-lg transition-colors !text-text-primary hover:!text-text-primary flex-row-reverse justify-end cursor-pointer"
contentExpandedClassName="!max-h-none !overflow-visible border-l-2 border-divider ml-5 pl-2 pr-0 mt-1"
contentExpandedClassName="!max-h-none !h-auto !min-h-0 !overflow-visible !flex !flex-col px-1 data-[expanded]:py-2 border-l-2 border-divider ml-5 pl-2 pr-0 mt-1"
>
<div className="flex flex-col gap-1">
{node.children.map(child => (
Expand Down Expand Up @@ -269,7 +269,7 @@ export const LocationSelectionDialog = ({
return (node: LocationNodeType) => {
const kindStr = node.kind.toString().toUpperCase()
return allowedKinds.has(node.kind as LocationType) ||
allowedKinds.has(kindStr)
allowedKinds.has(kindStr)
}
} else if (useCase === 'clinic') {
return (node: LocationNodeType) => {
Expand All @@ -292,7 +292,7 @@ export const LocationSelectionDialog = ({
return (node: LocationNodeType) => {
const kindStr = node.kind.toString().toUpperCase()
return allowedKinds.has(node.kind as LocationType) ||
allowedKinds.has(kindStr)
allowedKinds.has(kindStr)
}
} else if (useCase === 'teams') {
const allowedKinds = new Set<string>([
Expand All @@ -306,7 +306,7 @@ export const LocationSelectionDialog = ({
return (node: LocationNodeType) => {
const kindStr = node.kind.toString().toUpperCase()
return allowedKinds.has(node.kind as LocationType) ||
allowedKinds.has(kindStr)
allowedKinds.has(kindStr)
}
}

Expand Down
4 changes: 2 additions & 2 deletions web/components/patients/PatientTasksView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export const PatientTasksView = ({
<Circle className="size-5 text-warning" />
{translation('openTasks')} ({openTasks.length})
</ExpandableHeader>
<ExpandableContent className="expandable-content-h-56 px-1 data-[expanded]:py-2">
<ExpandableContent className="!max-h-none !h-auto !overflow-visible px-1 data-[expanded]:py-2">
{openTasks.length === 0 &&
<div className="text-description italic">{translation('noOpenTasks')}</div>}
{openTasks.map(task => (
Expand All @@ -139,7 +139,7 @@ export const PatientTasksView = ({
<CheckCircle2 className="size-5 text-positive" />
{translation('closedTasks')} ({closedTasks.length})
</ExpandableHeader>
<ExpandableContent className="expandable-content-h-56 px-1 data-[expanded]:py-2">
<ExpandableContent className="!max-h-none !h-auto !overflow-visible px-1 data-[expanded]:py-2">
{closedTasks.length === 0 &&
<div className="text-description italic">{translation('noClosedTasks')}</div>}
{closedTasks.map(task => (
Expand Down
8 changes: 2 additions & 6 deletions web/hooks/useStateWithLocalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,8 @@ export const useStateWithLocalStorage = <T>({
}: useStateWithLocalStorageProps<T>): [T, Dispatch<SetStateAction<T>>] => {
const [value, setValue] = useState<T>(() => loadFromLocalStorage(key, defaultValue))

if('task-list-column-filters' === key) {
console.log('loading from localStorage', key, value)
}

useEffect(() => {
saveToLocalStorage(key, value)
}, [key,value])
}, [key, value])
return [value, setValue]
}
}
49 changes: 36 additions & 13 deletions web/hooks/useTasksContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ function filterLocationsByRootSubtree(
.map(loc => ({ id: loc.id, title: loc.title }))
}

const ROOT_LOCATION_KINDS = new Set<string>(['HOSPITAL', 'PRACTICE', 'CLINIC', 'TEAM', 'WARD'])

function isAllowedRootKind(kind: string | undefined): boolean {
if (!kind) return false
return ROOT_LOCATION_KINDS.has(kind.toString().toUpperCase())
}

type User = {
id: string,
name: string,
Expand Down Expand Up @@ -154,10 +161,10 @@ export const TasksContextProvider = ({ children }: PropsWithChildren) => {
const queryKey = query.queryKey as unknown[]
const queryKeyStr = JSON.stringify(queryKey)
return queryKeyStr.includes('GetPatients') ||
queryKeyStr.includes('GetTasks') ||
queryKeyStr.includes('GetLocations') ||
queryKeyStr.includes('GetGlobalData') ||
queryKeyStr.includes('GetOverviewData')
queryKeyStr.includes('GetTasks') ||
queryKeyStr.includes('GetLocations') ||
queryKeyStr.includes('GetGlobalData') ||
queryKeyStr.includes('GetOverviewData')
}
})
}
Expand All @@ -177,31 +184,46 @@ export const TasksContextProvider = ({ children }: PropsWithChildren) => {
useEffect(() => {
const totalPatientsCount = data?.patients?.length ?? 0
const waitingPatientsCount = data?.waitingPatients?.length ?? 0
const rootLocations = data?.me?.rootLocations?.map(loc => ({ id: loc.id, title: loc.title, kind: loc.kind })) ?? []
const backendRootLocations = data?.me?.rootLocations?.map(loc => ({ id: loc.id, title: loc.title, kind: loc.kind })) ?? []
const backendRootIds = new Set(backendRootLocations.map(loc => loc.id))

const allNodes = allLocationsData?.locationNodes ?? []
const allowedRootLocationIds = new Set(backendRootIds)
allNodes.forEach((node: { id: string, kind?: string }) => {
if (isAllowedRootKind(node.kind)) {
allowedRootLocationIds.add(node.id)
}
})

setState(prevState => {
let selectedRootLocationIds = prevState.selectedRootLocationIds || []

if (rootLocations.length > 0) {
const rootLocationIds = new Set(rootLocations.map(loc => loc.id))

if (allowedRootLocationIds.size > 0) {
const isInitialSet = storedSelectedRootLocationIds.length === 0

const validSelectedIds = selectedRootLocationIds.filter(id => rootLocationIds.has(id))
const validSelectedIds = selectedRootLocationIds.filter(id => allowedRootLocationIds.has(id))
if (validSelectedIds.length !== selectedRootLocationIds.length) {
selectedRootLocationIds = validSelectedIds
}

const validStoredIds = storedSelectedRootLocationIds.filter(id => rootLocationIds.has(id))
const validStoredIds = storedSelectedRootLocationIds.filter(id => allowedRootLocationIds.has(id))
if (validStoredIds.length !== storedSelectedRootLocationIds.length) {
setStoredSelectedRootLocationIds(validStoredIds)
}

if (isInitialSet && selectedRootLocationIds.length === 0) {
selectedRootLocationIds = rootLocations.map(loc => loc.id)
selectedRootLocationIds = backendRootLocations.map(loc => loc.id)
}
}

const selectedIdsSet = new Set(selectedRootLocationIds)
const rootLocations: Array<{ id: string, title: string, kind?: string }> = [...backendRootLocations]
allNodes.forEach((node: { id: string, title: string, kind?: string }) => {
if (selectedIdsSet.has(node.id) && isAllowedRootKind(node.kind) && !backendRootIds.has(node.id)) {
rootLocations.push({ id: node.id, title: node.title, kind: node.kind })
}
})

return {
...prevState,
user: data?.me ? {
Expand Down Expand Up @@ -258,7 +280,8 @@ export const TasksContextProvider = ({ children }: PropsWithChildren) => {
setState(prevState => {
const newState = typeof updater === 'function' ? updater(prevState) : updater
if (newState.selectedRootLocationIds !== prevState.selectedRootLocationIds) {
setStoredSelectedRootLocationIds(newState.selectedRootLocationIds || [])
const idsToStore = newState.selectedRootLocationIds || []
setStoredSelectedRootLocationIds(idsToStore)
}
return newState
})
Expand All @@ -275,4 +298,4 @@ export const TasksContextProvider = ({ children }: PropsWithChildren) => {
{children}
</TasksContext.Provider>
)
}
}
4 changes: 2 additions & 2 deletions web/pages/wards/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ const WardsOverviewPage: NextPage = () => {
</div>
)}
headerClassName="typography-label-md font-bold !px-4 !py-4 rounded-xl"
contentExpandedClassName="pb-4"
contentExpandedClassName="!max-h-none !h-auto !overflow-visible pb-4"
className="rounded-xl"
isExpanded={true}
>
Expand All @@ -259,7 +259,7 @@ const WardsOverviewPage: NextPage = () => {
key={index}
label={wardGroup.name}
headerClassName="typography-label-md font-bold !px-4 !py-4 rounded-xl"
contentExpandedClassName="pb-4"
contentExpandedClassName="!max-h-none !h-auto !overflow-visible pb-4"
className="rounded-xl"
isExpanded={false}
>
Expand Down
Loading