Skip to content

Commit

Permalink
fix: fix OrganizationMemberList overflow
Browse files Browse the repository at this point in the history
  • Loading branch information
DasProffi committed Aug 6, 2023
1 parent 85102b2 commit 41118d3
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 112 deletions.
95 changes: 51 additions & 44 deletions lib/components/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { tw, tx } from '../twind'
import type { ReactElement } from 'react'
import { Checkbox } from './user_input/Checkbox'
import { Pagination } from './Pagination'
import { noop } from './user_input/Input'
import { noop } from '../util/noop'
import SimpleBarReact from 'simplebar-react'

export type TableStatePagination = {
currentPage: number,
Expand Down Expand Up @@ -229,49 +230,55 @@ export const Table = <T, >({
const cellPadding = 'py-1 px-2'

return (
<div className={tw('flex flex-col gap-y-4 items-center')}>
<table className={tw('w-full')}>
<thead>
<tr className={headerRow}>
{header && tableState.selection && (
<th className={headerPaddingHead}>
<Checkbox
checked={tableState.selection.hasSelectedSome ? 'indeterminate' : tableState.selection.hasSelectedAll}
onChange={() => updateTableState(changeTableSelectionAll(tableState, data, identifierMapping))}
/>
</th>
)}
{header && header.map((value, index) => (
<th key={`tableHeader${index}`} className={headerPaddingHead}>
<div className={tw('flex flex-row justify-start px-2')}>
{value}
</div>
</th>
)
)}
</tr>
</thead>
<tbody>
{shownElements.map((value, rowIndex) => (
<tr key={identifierMapping(value)} >
{tableState.selection && (
<td className={tx(cellPadding, { [headerPaddingBody]: rowIndex === 0 })}>
<Checkbox
checked={isDataObjectSelected(tableState, value, identifierMapping)}
onChange={() => {
updateTableState(changeTableSelectionSingle(tableState, value, data.length, identifierMapping))
}}
/>
</td>
)}
{rowMappingToCells(value).map((value1, index) => <td key={index} className={tx(cellPadding, { [headerPaddingBody]: rowIndex === 0 })}>{value1}</td>)}
</tr>
))}
</tbody>
</table>
{tableState.pagination &&
<Pagination page={currentPage} numberOfPages={pageCount} onPageChanged={page => updateTableState({ ...tableState, pagination: { entriesPerPage, currentPage: page } })}/>
}
<div className={tw('flex flex-col gap-y-4 overflow-hidden')}>
<div>
<SimpleBarReact>
<table className={tw('w-full mb-[12px]')}>
<thead>
<tr className={headerRow}>
{header && tableState.selection && (
<th className={headerPaddingHead}>
<Checkbox
checked={tableState.selection.hasSelectedSome ? 'indeterminate' : tableState.selection.hasSelectedAll}
onChange={() => updateTableState(changeTableSelectionAll(tableState, data, identifierMapping))}
/>
</th>
)}
{header && header.map((value, index) => (
<th key={`tableHeader${index}`} className={headerPaddingHead}>
<div className={tw('flex flex-row justify-start px-2')}>
{value}
</div>
</th>
)
)}
</tr>
</thead>
<tbody>
{shownElements.map((value, rowIndex) => (
<tr key={identifierMapping(value)}>
{tableState.selection && (
<td className={tx(cellPadding, { [headerPaddingBody]: rowIndex === 0 })}>
<Checkbox
checked={isDataObjectSelected(tableState, value, identifierMapping)}
onChange={() => {
updateTableState(changeTableSelectionSingle(tableState, value, data.length, identifierMapping))
}}
/>
</td>
)}
{rowMappingToCells(value).map((value1, index) => <td key={index} className={tx(cellPadding, { [headerPaddingBody]: rowIndex === 0 })}>{value1}</td>)}
</tr>
))}
</tbody>
</table>
</SimpleBarReact>
</div>
<div className={tw('flex flex-row justify-center')}>
{tableState.pagination &&
<Pagination page={currentPage} numberOfPages={pageCount} onPageChanged={page => updateTableState({ ...tableState, pagination: { entriesPerPage, currentPage: page } })}/>
}
</div>
</div>
)
}
4 changes: 3 additions & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.1.6",
"webpack": "5.88.2"
"webpack": "5.88.2",
"simplebar-core": "1.2.4",
"simplebar-react": "3.2.4"
},
"devDependencies": {
"@babel/preset-env": "7.22.9",
Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions tasks/components/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ const Avatar = ({ avatarUrl, alt, size = 'medium' }: AvatarProps) => {
return (
<div className={tw('rounded-full')}>
<img className={tx('rounded-full border border-slate-200 group-hover:border-indigo-200 flex justify-evenly items-center', {
'h-6 w-6': size === 'tiny',
'h-8 w-8': size === 'small',
'h-12 w-12': size === 'medium',
'h-16 w-16': size === 'large'
'h-6 w-6 min-h-[24px] min-w-[24px]': size === 'tiny',
'h-8 w-8 min-h-[32px] min-w-[32px]': size === 'small',
'h-12 w-12 min-h-[48px] min-w-[48px]': size === 'medium',
'h-16 w-16 min-h-[64px] min-w-[64px]': size === 'large'
})} src={avatarUrl} alt={alt} />
</div>
)
Expand Down
124 changes: 61 additions & 63 deletions tasks/components/OrganizationMemberList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
useRemoveMemberMutation
} from '../mutations/organization_mutations'
import { OrganizationContext } from '../pages/organizations'
import { LoadingAndErrorComponent } from '@helpwave/common/components/LoadingAndErrorComponent'

type OrganizationMemberListTranslation = {
edit: string,
Expand Down Expand Up @@ -97,16 +98,6 @@ export const OrganizationMemberList = ({

const [deleteDialogState, setDeleteDialogState] = useState<DeleteDialogState>(defaultDeleteDialogState)

// TODO add view for loading
if (isLoading && !members) {
return <div>Loading Widget</div>
}

// TODO add view for error or error handling
if (isError && !members) {
return <div>Error Message</div>
}

const hasSelectedMultiple = !!tableState.selection && tableState.selection.currentSelection.length > 1
const idMapping = (dataObject: OrgMember) => dataObject.id

Expand All @@ -131,61 +122,68 @@ export const OrganizationMemberList = ({
}}
confirmType="negative"
/>
<div className={tw('flex flex-row justify-between items-center mb-2')}>
<Span type="tableName">{translation.members + ` (${usedMembers.length})`}</Span>
<div className={tw('flex flex-row gap-x-2')}>
{tableState.selection && tableState.selection.currentSelection.length > 0 && (
<Button
onClick={() => setDeleteDialogState({ isShowing: true })}
color="negative"
>
{translation.removeSelection}
</Button>
)}
<LoadingAndErrorComponent
hasError={(isError || !data) && !members}
isLoading={!members && isLoading}
errorProps={{ classname: tw('border-2 border-gray-600 rounded-xl min-h-[300px]') }}
loadingProps={{ classname: tw('border-2 border-gray-600 rounded-xl min-h-[300px]') }}
>
<div className={tw('flex flex-row justify-between items-center mb-2')}>
<Span type="tableName">{translation.members + ` (${usedMembers.length})`}</Span>
<div className={tw('flex flex-row gap-x-2')}>
{tableState.selection && tableState.selection.currentSelection.length > 0 && (
<Button
onClick={() => setDeleteDialogState({ isShowing: true })}
color="negative"
>
{translation.removeSelection}
</Button>
)}
</div>
</div>
</div>
<Table
data={usedMembers}
stateManagement={[tableState, setTableState]}
header={[
<div key="member" className={tw('flex flex-row')}>
<Span type="tableHeader">{translation.member}</Span>
</div>,
<div key="role" className={tw('flex flex-row')}>
<Span type="tableHeader">{translation.role}</Span>
</div>,
<></>
]}
rowMappingToCells={dataObject => [
<div key="member" className={tw('flex flex-row items-center h-12')}>
<Avatar avatarUrl={dataObject.avatarURL} alt="" size="small"/>
<div className={tw('flex flex-col ml-2 max-w-[250px] overflow-hidden')}>
<Span className={tw('font-bold truncate')}>{dataObject.name}</Span>
<a href={`mailto:${dataObject.email}`} >
<Span type="description" className={tw('text-sm truncate')}>{dataObject.email}</Span>
</a>
<Table
data={usedMembers}
stateManagement={[tableState, setTableState]}
header={[
<div key="member" className={tw('flex flex-row')}>
<Span type="tableHeader">{translation.member}</Span>
</div>,
<div key="role" className={tw('flex flex-row')}>
<Span type="tableHeader">{translation.role}</Span>
</div>,
<></>
]}
rowMappingToCells={dataObject => [
<div key="member" className={tw('flex flex-row items-center h-12 overflow-hidden max-w-[200px]')}>
<Avatar avatarUrl={dataObject.avatarURL} alt="" size="small"/>
<div className={tw('flex flex-col ml-2')}>
<Span className={tw('font-bold truncate')}>{dataObject.name}</Span>
<a href={`mailto:${dataObject.email}`}>
<Span type="description" className={tw('text-sm truncate')}>{dataObject.email}</Span>
</a>
</div>
</div>,
<div key="role" className={tw('flex flex-row items-center mr-2')}>
<button className={tw('flex flex-row items-center')} onClick={() => { /* TODO allow changing roles */
}}>
<Span className={tw(`font-semibold`)}>
{translation.roleTypes[dataObject.role]}
</Span>
</button>
</div>,
<div key="remove" className={tw('flex flex-row justify-end')}>
<Button
onClick={() => setDeleteDialogState({ isShowing: true, member: dataObject })}
color="negative"
variant="textButton"
>
{translation.remove}
</Button>
</div>
</div>,
<div key="role" className={tw('flex flex-row items-center mr-2')}>
<button className={tw('flex flex-row items-center')} onClick={() => { /* TODO allow changing roles */
}}>
<Span className={tw(`font-semibold`)}>
{translation.roleTypes[dataObject.role]}
</Span>
</button>
</div>,
<div key="remove" className={tw('flex flex-row justify-end')}>
<Button
onClick={() => setDeleteDialogState({ isShowing: true, member: dataObject })}
color="negative"
variant="textButton"
>
{translation.remove}
</Button>
</div>
]}
identifierMapping={idMapping}
/>
]}
identifierMapping={idMapping}
/>
</LoadingAndErrorComponent>
</div>
)
}

0 comments on commit 41118d3

Please sign in to comment.