react-bootstrap#Collapse TypeScript Examples
The following examples show how to use
react-bootstrap#Collapse.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AccContractCard.tsx From devex with GNU General Public License v3.0 | 6 votes |
AccContractCard: React.FC<IProps> = ({ contract, index }) => {
const [showContractState, setShowContractState] = useState<boolean>(false)
return <Card className='acc-contract-card'>
<Card.Body onClick={() => { setShowContractState((prevState) => !prevState) }} key={index}>
<div>
<span className='mono'>
{`${index + 1}) `}
{<QueryPreservingLink onClick={(e: React.MouseEvent<HTMLAnchorElement>) => { e.stopPropagation() }}
to={`/address/${hexAddrToZilAddr(contract.address)}`}>
{hexAddrToZilAddr(contract.address)}
</QueryPreservingLink>}
</span>
<span>
<FontAwesomeIcon icon={showContractState ? faChevronUp : faChevronDown} />
</span>
</div>
</Card.Body>
<Collapse in={showContractState}>
<div>
<pre className='display-block'>
{JSON.stringify(contract.state, null, 2)}
</pre>
</div>
</Collapse>
</Card>
}
Example #2
Source File: FilterItemComponent.tsx From rcsb-saguaro-app with MIT License | 5 votes |
render():JSX.Element {
return (<>
<ItemComponent onClick={()=>this.setState({collapseIn:!this.state.collapseIn})} >FILTER</ItemComponent>
<Collapse in={this.state.collapseIn}>
<div className={"position-absolute"} ></div>
</Collapse>
</>);
}
Example #3
Source File: DSBlockDetailsPage.tsx From devex with GNU General Public License v3.0 | 4 votes |
DSBlockDetailsPage: React.FC = () => {
const { blockNum } = useParams()
const networkContext = useContext(NetworkContext)
const { dataService } = networkContext!
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [data, setData] = useState<DsBlockObj | null>(null)
const [latestDSBlockNum, setLatestDSBlockNum] = useState<number | null>(null)
const [minerInfo, setMinerInfo] = useState<MinerInfo | null>(null)
const [currShardIdx, setCurrShardIdx] = useState<number>(0)
const [showMore, setShowMore] = useState<boolean>(false)
// Fetch data
useEffect(() => {
setIsLoading(true)
if (!dataService) return
let latestDSBlockNum: number
let receivedData: DsBlockObj
let minerInfo: MinerInfo
const getData = async () => {
try {
if (isNaN(blockNum))
throw new Error('Not a valid block number')
receivedData = await dataService.getDSBlockDetails(blockNum)
latestDSBlockNum = await dataService.getNumDSBlocks()
try { // wrapped in another try catch because it is optional
minerInfo = await dataService.getMinerInfo(blockNum)
} catch (e) { console.log(e) }
if (receivedData)
setData(receivedData)
if (latestDSBlockNum)
setLatestDSBlockNum(latestDSBlockNum)
if (minerInfo)
setMinerInfo(minerInfo)
} catch (e) {
console.log(e)
setError(e)
} finally {
setIsLoading(false)
}
}
getData()
return () => {
setData(null)
setLatestDSBlockNum(null)
setMinerInfo(null)
setError(null)
setCurrShardIdx(0)
setShowMore(false)
}
}, [blockNum, dataService])
return <>
{isLoading ? <div className='center-spinner'><Spinner animation="border" /></div> : null}
{error
? <NotFoundPage />
: data && (
<>
<div className='dsblock-header'>
<h3 className='mb-1'>
<span className='mr-1'>
<FontAwesomeIcon className='fa-icon' icon={faCubes} />
</span>
<span className='ml-2'>
DS Block
</span>
{' '}
<span className='subtext'>#{data.header.BlockNum}</span>
<LabelStar type='DS Block' />
</h3>
<span>
<QueryPreservingLink
className={parseInt(data.header.BlockNum) === 0
? 'disabled mr-3' : 'mr-3'}
to={`/dsbk/${parseInt(data.header.BlockNum) - 1}`}>
<FontAwesomeIcon size='2x' className='fa-icon' icon={faCaretSquareLeft} />
</QueryPreservingLink>
<QueryPreservingLink
className={latestDSBlockNum && parseInt(data.header.BlockNum) === latestDSBlockNum - 1 ? 'disabled' : ''}
to={`/dsbk/${parseInt(data.header.BlockNum) + 1}`}>
<FontAwesomeIcon size='2x' className='fa-icon' icon={faCaretSquareRight} />
</QueryPreservingLink>
</span>
</div>
<Card className='dsblock-details-card'>
<Card.Body>
<Container>
<Row>
<Col>
<div className='dsblock-detail'>
<span>Date:</span>
<span>
{timestampToDisplay(data.header.Timestamp)}
{' '}
({timestampToTimeago(data.header.Timestamp)})
</span>
</div>
</Col>
<Col>
<div className='dsblock-detail'>
<span>Difficulty:</span>
<span>{data.header.Difficulty}</span>
</div>
</Col>
</Row>
<Row>
<Col>
<div className='dsblock-detail'>
<span>DS Difficulty:</span>
<span>{data.header.DifficultyDS}</span>
</div>
</Col>
<Col>
<div className='dsblock-detail'>
<span>Gas Price:</span>
<span>{qaToZil(data.header.GasPrice)}</span>
</div>
</Col>
</Row>
<Row>
<Col>
<div className='dsblock-detail'>
<span>DS Leader:</span>
<span>
<QueryPreservingLink to={`/address/${pubKeyToZilAddr(data.header.LeaderPubKey)}`}>
{pubKeyToZilAddr(data.header.LeaderPubKey)}
</QueryPreservingLink>
</span>
</div>
</Col>
</Row>
<Row>
<Col>
<div className='dsblock-detail'>
<span>Signature:</span>
<span className='dsblock-signature'>{data.signature}</span>
</div>
</Col>
</Row>
</Container>
</Card.Body>
</Card>
{data.header.PoWWinners.length > 0 && (
<Card className='dsblock-details-card'>
<Card.Body>
<Container className='mono'>
<h6 className='mb-2'>PoW Winners</h6>
{data.header.PoWWinners.map((x, index) => <div key={index}>[{index}]
{' '}
<QueryPreservingLink to={`/address/${pubKeyToZilAddr(x)}`}>{pubKeyToZilAddr(x)}</QueryPreservingLink></div>)}
</Container>
</Card.Body>
</Card>
)}
{minerInfo &&
<>
<Collapse in={showMore}>
<Row>
<Col>
<Card className='miner-card'>
<Card.Body>
<Container className='mono'>
<Row className='justify-content-between'>
<span>DS Committee</span>
<span>Total: <strong>{minerInfo.dscommittee.length}</strong></span>
</Row>
<Row className='justify-content-center'>
{minerInfo.dscommittee.length > 0
? <MinerTable addresses={minerInfo.dscommittee} />
: <span className='my-3'>No addresses to show</span>
}
</Row>
</Container>
</Card.Body>
</Card>
</Col>
<Col>
<Card className='miner-card ml-auto'>
<Card.Body>
<Container className='mono'>
<Row className='justify-content-between'>
<Col>
<span>Shard {currShardIdx + 1} of {minerInfo.shards.length}</span>
</Col>
<Col className='text-center shard-toggle'>
<span>
<FontAwesomeIcon size='2x'
cursor='pointer'
onClick={currShardIdx === 0 ? undefined : () => (setCurrShardIdx(currShardIdx - 1))}
className={currShardIdx === 0 ? 'disabled' : ''} icon={faAngleLeft} />
<FontAwesomeIcon size='2x'
cursor='pointer'
onClick={currShardIdx === minerInfo.shards.length - 1 ? undefined : () => (setCurrShardIdx(currShardIdx + 1))}
className={currShardIdx === minerInfo.shards.length - 1 ? 'disabled ml-3' : 'ml-3'} icon={faAngleRight} />
</span>
</Col>
<Col className='text-right'>
<span>
Total:
{' '}
<strong>{minerInfo.shards[currShardIdx].nodes.length}</strong>
</span>
</Col>
</Row>
<Row className='justify-content-center'>
{minerInfo.shards[currShardIdx].nodes.length > 0
? <MinerTable addresses={minerInfo.shards[currShardIdx].nodes} />
: <span className='my-3'>No addresses to show</span>
}
</Row>
</Container>
</Card.Body>
</Card>
</Col>
</Row>
</Collapse>
</>
}
<Container className='showmore-container' onClick={() => setShowMore(!showMore)}>
<Row>
<FontAwesomeIcon icon={showMore ? faAngleUp : faAngleDown} size='2x' className='fa-icon' />
</Row>
</Container>
</>
)}
</>
}
Example #4
Source File: group-modal.component.tsx From cwa-quick-test-frontend with Apache License 2.0 | 4 votes |
GroupModal = (props: any) => { const [btnOkDisabled, setBtnOkDisabled] = React.useState(true); const { t } = useTranslation(); const { keycloak } = useKeycloak(); const [data, setData] = React.useState(''); const [validated, setValidated] = React.useState(false); const [isReady, setIsReady] = React.useState(false); const [isNew, setIsNew] = React.useState(true); const [options, setOptions] = React.useState<JSX.Element[]>(); const [dropdownItems, setDropdownItems] = React.useState<JSX.Element[]>(); const [dropdownList] = React.useState<string[]>(['https://', 'http://']); const [selectedDropdownValue, setSelectedDropdownValue] = React.useState<string>(dropdownList[0]); const [websiteValue, setWebsiteValue] = React.useState(''); const [displayOpeningHours, setDisplayOpeningHours] = React.useState(''); const [errorOpeningHour, setErrorOpeningHour] = React.useState(''); const groupReloaded = (group: IGroupDetails) => { if (group) { setData(unpackData(group.pocDetails)) group.parentGroup = props.parentGroupId; if (group.website) { let website = ''; for (const item of dropdownList) { if (group.website.startsWith(item)) { website = group.website.slice(item.length, group.website.length); setSelectedDropdownValue(item); } } setWebsiteValue(website); } else { setWebsiteValue(''); setSelectedDropdownValue(dropdownList[0]); } } setBtnOkDisabled(false); } const [group, updateGroup, setGroup] = useGetGroupDetails(groupReloaded, props.handleError); React.useEffect(() => { getDropdownItems(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []) React.useEffect(() => { if (group) { setOptions(getOptions()); setDisplayOpeningHours( group.openingHours?.map( (element: string) => element) .join('\n') ); setIsReady(true); } setIsNew(!(group && group.id)); // eslint-disable-next-line react-hooks/exhaustive-deps }, [group]) React.useEffect(() => { setValidated(props.isSuccess) // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.isSuccess]); React.useEffect(() => { if (props.isCreationError) { setBtnOkDisabled(false) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.isCreationError]); const handleCancel = () => { setErrorOpeningHour(''); props.onCancel(); } const unpackData = (data: string) => { if (data) { data = data.replaceAll(',', '\n') } else { data = '' } return data; } const packData = (data: string) => { if (data) { data = data.replaceAll('\n', ',') } return data; } const handleOk = () => { if (props.handleOk) { setBtnOkDisabled(true); group.pocDetails = packData(data); if (websiteValue && ( websiteValue.startsWith('www.') || !( websiteValue.startsWith(dropdownList[0]) || websiteValue.startsWith(dropdownList[1]) ) )) { group.website = selectedDropdownValue + websiteValue; } else { group.website = websiteValue; } props.handleOk(group); } } const handleEnter = () => { if (props.onEnter) { props.onEnter(); } setBtnOkDisabled(false); if (props.groupId) { updateGroup(props.groupId); } else { setGroup({ ...emptyGroup }); setSelectedDropdownValue(dropdownList[0]); setData(''); setWebsiteValue(''); } } const handleExited = () => { setIsReady(false); props.onExit(); } const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { const form = event.currentTarget; event.preventDefault(); event.stopPropagation(); if (errorOpeningHour) { document.getElementById('formPocOpeningHours')?.focus(); return; } if (form.checkValidity()) { handleOk(); } } const updateGroupProp = (name: string, value: any) => { const ngroup = { ...group, [name]: value }; setGroup({ ...ngroup }); } const changeOpeningHoursHandler = (name: string, value: string) => { setDisplayOpeningHours(value); let error = undefined; const openingHours = value.split('\n'); if (openingHours.length > 7) { setErrorOpeningHour('opening-hours-to-much-lines-error'); return; } error = openingHours.find(element => { return !utils.isOpeningHoursValid(element); }); if (error) { setErrorOpeningHour('openening-hours-to-long-error'); } else { setErrorOpeningHour(''); updateGroupProp("openingHours", openingHours); } } const updateSearchPortalConsent = (name: string, value: any) => { const ngroup: IGroupDetails = { ...group, [name]: value }; if (value === false) { ngroup.email = ''; ngroup.website = ''; ngroup.openingHours = []; ngroup.appointmentRequired = false; } setGroup(ngroup); } const collectChildren = (idlist: string[], parentNode: IGroup) => { if (parentNode) { idlist.push(parentNode.id); parentNode.children.forEach(child => collectChildren(idlist, child as IGroup)); } } const getOptions = (): JSX.Element[] => { let result: JSX.Element[] = []; if (group && group.id) { const node = props.groups.find((groupNode: IGroupNode) => groupNode.group.id === group.id); const selfIdOrChildren: string[] = []; if (node) { collectChildren(selfIdOrChildren, node.group); } const fList = props.groups.filter((groupNode: IGroupNode) => selfIdOrChildren.indexOf(groupNode.group.id) < 0) result = fList.map((groupNode: IGroupNode) => <option key={groupNode.group.id} value={groupNode.group.id}>{"\u00A0\u00A0\u00A0\u00A0".repeat(groupNode.level) + groupNode.group.name}</option> ); // result.push(<option key="empty" value="empty">{t('translation:no-parentgroup-option')}</option>); } return result; } const getDropdownItems = () => { setDropdownItems( dropdownList.map( (item: string) => <Dropdown.Item onSelect={(eventKey: any) => setSelectedDropdownValue(eventKey)} eventKey={item} key={item} > {item} </Dropdown.Item>)); } return ( <Modal contentClassName='data-modal' size="lg" show={props.show} backdrop="static" keyboard={false} centered onEnter={handleEnter} onExited={handleExited} > {!isReady ? <CwaSpinner background='#eeeeee' /> : <Fade appear={true} in={true} > <Form className='form-flex' onSubmit={handleSubmit} validated={validated} > <Modal.Header id='data-header' className='pb-0' > <Modal.Title>{isNew ? t('translation:add-group') : t('translation:edit-group')}</Modal.Title> </Modal.Header> <Modal.Body className='bg-light'> {isNew ? <></> : <> <FormGroupSelect controlId='formGroupSelect' title={t('translation:parentgroup')} placeholder={t('translation:no-parentgroup-option')} value={group.parentGroup} onChange={(ent: any) => updateGroupProp('parentGroup', ent.target.value)} options={options} /> <hr /> </> } < FormGroupInput controlId='formFirstName' title={t('translation:name')} value={group ? group.name : ''} required onChange={(evt: any) => { updateGroupProp('name', evt.target.value); props.resetError(); }} maxLength={45} isInvalid={props.isCreationError} InvalidText={t('translation:group-conflict-error')} /> {/* <hr /> */} < FormGroupTextarea controlId='formAdressData' title={t('translation:address-testcenter')} placeholder={t('translation:address-testcenter-placeholder')} value={data} required onChange={(evt: any) => setData(evt.target.value)} type='textarea' maxLength={300} /> {utils.hasRole(keycloak, 'c19_quick_test_poc_nat_admin') ? <FormGroupPermissionCkb controlId='formenablePcr' title={t('translation:enablePcr')} //label={t('translation:for-counter')} onChange={(evt: any) => updateSearchPortalConsent('enablePcr', evt.currentTarget.checked)} type='checkbox' checked={group.enablePcr} /> : <></> } <hr /> {/* < FormGroupInput controlId='formBSNRInput' title={t('translation:bsnr')} placeholder={t('translation:bsnr-placeholder')} value={group ? group.bsnr : ''} onChange={(evt: any) => { updateGroupProp('bsnr', evt.target.value); props.resetError(); }} maxLength={9} prepend='i' tooltip={t('translation:bsnr-tooltip')} pattern={utils.pattern.BSNR} /> */} <FormGroupPermissionCkb controlId='formsearchPortalConsent' title={t('translation:searchPortalConsent')} //label={t('translation:for-counter')} onChange={(evt: any) => updateSearchPortalConsent('searchPortalConsent', evt.currentTarget.checked)} type='checkbox' checked={group.searchPortalConsent} /> <Collapse in={group.searchPortalConsent}> <div> < FormGroupInput controlId='formEmailInput' title={t('translation:email-address')} value={group?.email ? group.email : ''} onChange={(evt: any) => { updateGroupProp('email', evt.target.value); props.resetError(); }} type='email' pattern={utils.pattern.eMail} minLength={5} maxLength={255} /> < FormGroupInput controlId='formPocWebsite' title={t('translation:searchPortalWebsite')} placeholder={t('translation:searchPortalWebsitePlaceholder')} value={websiteValue} dropdown={dropdownItems} dropdownTitle={selectedDropdownValue} prepend='i' tooltip={t('translation:searchPortalWebsiteTooltip')} onChange={(evt: any) => { setWebsiteValue(evt.target.value); props.resetError(); }} maxLength={100} pattern={utils.pattern.url} /> < FormGroupTextarea controlId='formPocOpeningHours' title={t('translation:searchPortalOpeningHours')} value={displayOpeningHours} onChange={(evt: any) => { changeOpeningHoursHandler('openingHours', evt.target.value); props.resetError(); }} type='textarea' rows={7} pattern={utils.pattern.email} isInvalid={errorOpeningHour} invalidText={errorOpeningHour && t('translation:' + errorOpeningHour)} /> <FormGroupPermissionCkb controlId='formAppointmentRequired' title={t('translation:searchPortalAppointmentRequired')} onChange={(evt: any) => updateGroupProp('appointmentRequired', evt.currentTarget.checked)} type='checkbox' checked={group?.appointmentRequired ? group.appointmentRequired : false} /> </div> </Collapse> {!(group && group.pocId) ? <></> : <> <hr /> < FormGroupInput controlId='formPocId' title={t('translation:poc-id')} value={group && group.pocId ? group.pocId : ''} readOnly /> </> } </Modal.Body> <Modal.Footer id='data-footer'> <Container className='p-0'> <Row> <Col sm='6' lg='4' className='mb-2 mb-sm-0 p-0 pr-sm-2'> <Button className='p-0' block variant='outline-primary' onClick={handleCancel} > {t('translation:cancel')} </Button> </Col> <Col sm='6' lg='4' className='p-0 pl-sm-2'> <Button className='p-0' block type='submit' disabled={btnOkDisabled} > {isNew ? t('translation:add') : t('translation:edit')} <Spinner as="span" className='btn-spinner' animation="border" hidden={!btnOkDisabled} size="sm" role="status" aria-hidden="true" /> </Button> </Col> </Row> </Container> </Modal.Footer> </Form> </Fade> } </Modal> ) }
Example #5
Source File: group-table.component.tsx From cwa-quick-test-frontend with Apache License 2.0 | 4 votes |
GroupTable = (props: any) => {
// const context = React.useContext(AppContext);
const { t } = useTranslation();
const { keycloak } = useKeycloak();
const handleSuccess = () => {
setIsGroupCreationError(false);
setIsGroupSuccessfullUpdated(true);
setTimeout(setIsGroupEdit, 300, false);
setShowConfirm(false);
}
const [isGroupEdit, setIsGroupEdit] = React.useState(false);
const [editGroupId, setEditGroupId] = React.useState<string>('');
const [editGroupParentId, setEditGroupParentId] = React.useState<string>('');
const [showConfirm, setShowConfirm] = React.useState(false);
const [isGroupSuccessfullUpdated, setIsGroupSuccessfullUpdated] = React.useState(false);
const [isGroupCreationError, setIsGroupCreationError] = React.useState(false);
const [confirmMessage, setConfirmMessage] = React.useState('');
const [confirmTitle, setConfirmTitle] = React.useState('');
const [confirmHandle, setConfirmHandle] = React.useState<() => void>();
const [groupIsReady, setGroupIsReady] = React.useState(false);
const [
bGroups,
refreshGroups,
createGroup,
updateGroup,
deleteGroup
] = useGetGroups(() => setGroupIsReady(true), props.handleError);
React.useEffect(() => {
if (bGroups) {
const _groupNodes: IGroupNode[] = [];
flattenGroups(bGroups, _groupNodes, 0);
props.setGroupNodes(_groupNodes);
}
else {
props.setGroupNodes([]);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [bGroups]);
const flattenGroups = (groups: IGroup[], groupNodes: IGroupNode[], level: number, parentGroup?: string): void => {
groups.forEach((group: IGroup) => {
const gNode: IGroupNode = {
group: group,
parentGroup: parentGroup,
level: level,
};
groupNodes.push(gNode);
if (group.children) {
flattenGroups(group.children, groupNodes, level + 1, group.id);
}
});
}
const groupUpdate = (group: IGroupDetails) => {
if (group.id) {
if (keycloak.token) {
const uGroup: any = { ...group };
delete uGroup.parentGroup;
updateGroup(uGroup)
.then(() => {
const fgroupNode = props.groupNodes.find((groupNode: IGroupNode) => groupNode.group.id === group.id);
if (keycloak.token
&& fgroupNode
&& group.id
&& group.parentGroup
&& fgroupNode.parentGroup !== group.parentGroup) {
addGroupAsChild(group.id, group.parentGroup, keycloak.token)
.then(() => {
refreshGroups(() => { handleSuccess(); props.setUserReload(true); });
})
.catch(e => {
props.handleError(e);
});
} else {
refreshGroups(() => { handleSuccess(); props.setUserReload(true); });
}
})
.catch(e => {
if (e && e.message && (e.message as string).includes('409')) {
setIsGroupCreationError(true);
}
else {
props.handleError(e);
}
})
}
} else {
createGroup(group)
.then(() => {
refreshGroups(handleSuccess);
})
.catch(e => {
if (e && e.message && (e.message as string).includes('409')) {
setIsGroupCreationError(true);
}
else {
props.handleError(e);
}
})
}
// setIsGroupEdit(false);
}
const startEditGroup = (groupNode: IGroupNode) => {
setEditGroupId(groupNode.group.id);
setEditGroupParentId(groupNode.parentGroup ? groupNode.parentGroup : '');
setIsGroupEdit(true);
}
const handleDeleteGroup = (group: IGroup) => {
setConfirmTitle(t('translation:delete-group-title', { groupName: group.name }));
setConfirmMessage(t('translation:delete-group-msg'));
setShowConfirm(true);
const handle = () => {
if (keycloak.token && group.id) {
deleteGroup(group.id)
.then(() => {
refreshGroups(() => { handleSuccess(); props.setUserReload(true); });
})
.catch(e => {
if (e && e.message && (e.message as string).includes('412')) {
setShowConfirm(false);
props.handleError(e, t('translation:delete-group-error'), () => { });
}
else {
props.handleError(e);
}
})
}
};
// need to wrap a function again because react apply each function passed to hook
setConfirmHandle(() => handle);
}
return (<>
{
!(props.groupNodes && groupIsReady)
? <CwaSpinner background='#eeeeee' />
: <Collapse appear={true} in={true}>
<Container className='p-0 '>
<Table bordered hover>
<thead>
<tr>
<th>{t('translation:name')}</th>
<th></th>
</tr>
</thead>
<tbody>{
props.groupNodes.map((g: IGroupNode, i: number) =>
<tr key={i}>
<td width="90%">{utils.getIndent(g.level)}{g.group.name}</td>
<td className='td-btn'>
<Row className='m-0 justify-content-around'>
<Button
className="btn-icon edit-icon"
onClick={() => startEditGroup(g)}
>
</Button>
<Button className="btn-icon delete-icon"
onClick={() => handleDeleteGroup(g.group)}
/>
</Row>
</td>
</tr>
)
}
</tbody>
</Table>
<Button
className='btn-add'
size="sm"
variant="light"
onClick={() => { setEditGroupId(''); setIsGroupEdit(true) }}
>
<img className='mr-2' src={imageAdd} alt="Hinzufügen" />
{t('translation:add-group')}
</Button>
</Container>
</Collapse>
}
<GroupModal
show={isGroupEdit}
groupId={editGroupId}
parentGroupId={editGroupParentId}
handleOk={groupUpdate}
groups={props.groupNodes}
isSuccess={isGroupSuccessfullUpdated}
isCreationError={isGroupCreationError}
onEnter={() => setIsGroupSuccessfullUpdated(false)}
resetError={() => setIsGroupCreationError(false)}
handleError={
(err: any) => {
setIsGroupEdit(false);
props.handleError(err);
}
}
onCancel={
() => { setIsGroupEdit(false); }
}
onExit={
() => {
setIsGroupSuccessfullUpdated(false);
setIsGroupCreationError(false);
}
}
/>
<ConfirmModal
show={showConfirm}
title={confirmTitle}
message={confirmMessage}
onCancel={() => {
setConfirmHandle(undefined);
setShowConfirm(false);
}}
handleOk={() => {
if (confirmHandle) {
confirmHandle();
}
}}
/>
</>
)
}
Example #6
Source File: person-data-inputs.tsx From cwa-quick-test-frontend with Apache License 2.0 | 4 votes |
PersonInputs = (props: any) => {
const { t } = useTranslation();
const [givenNameTransliteration, givenNameTransliterationUpdate] =
useTransliterate();
const [familyNameTransliteration, familyNameTransliterationUpdate] =
useTransliterate();
const [givenName, setGivenName] = React.useState<string>('');
const [familyName, setFamilyName] = React.useState<string>('');
const [standardisedGivenName, setStandardisedGivenName] =
React.useState<string>('');
const [standardisedFamilyName, setStandardisedFamilyName] =
React.useState<string>('');
const [dateOfBirth, setDateOfBirth] = React.useState<Date>();
const [sex, setSex] = React.useState<Sex>();
React.useEffect(() => {
if (props && props.quickTest && props.quickTest.personData) {
const personData = props.quickTest.personData;
if (personData.givenName) {
handleGivenNameChanged(personData.givenName);
}
if (personData.standardisedGivenName) {
setStandardisedGivenName(personData.standardisedGivenName);
}
if (personData.familyName) {
handleFamilyNameChanged(personData.familyName);
}
setStandardisedFamilyName(personData.standardisedFamilyName);
if (personData.dateOfBirth) {
setDateOfBirth(new Date(personData.dateOfBirth));
}
if (personData.sex) {
setSex(personData.sex);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(() => {
const result: IPersonData = {
givenName: givenName,
familyName: familyName,
standardisedGivenName: props.dccConsent
? standardisedGivenName
: undefined,
standardisedFamilyName: props.dccConsent
? standardisedFamilyName
: undefined,
dateOfBirth: dateOfBirth,
sex: sex,
};
props.onChange(result);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
givenName,
familyName,
standardisedGivenName,
standardisedFamilyName,
dateOfBirth,
sex,
props.dccConsent,
]);
React.useEffect(() => {
setStandardisedGivenName(givenNameTransliteration);
}, [givenNameTransliteration]);
React.useEffect(() => {
setStandardisedFamilyName(familyNameTransliteration);
}, [familyNameTransliteration]);
const handleGivenNameChanged = (changedValue: string) => {
const regEx = new RegExp(utils.pattern.name);
if (regEx.test(changedValue)) {
setGivenName(changedValue);
// convert to ICAO and set the std field
givenNameTransliterationUpdate(changedValue);
}
// setStandardisedName(tmpICAOValue.substring(0, tmpICAOValue.length > 50 ? 50 : tmpICAOValue.length));
};
const handleFamilyNameChanged = (changedValue: string) => {
const regEx = new RegExp(utils.pattern.name);
if (regEx.test(changedValue)) {
setFamilyName(changedValue);
// convert to ICAO and set the std field
familyNameTransliterationUpdate(changedValue);
}
// setStandardisedName(tmpICAOValue.substring(0, tmpICAOValue.length > 50 ? 50 : tmpICAOValue.length));
};
const handleStandardisedNameChanged = (
changedValue: string,
setStandardisedName: (value: string) => void
) => {
const upperCaseChangedValue = changedValue.toUpperCase();
if (utils.isStandardisedNameValid(upperCaseChangedValue)) {
setStandardisedName(upperCaseChangedValue);
}
};
const handleDateOfBirthChange = (evt: Date | [Date, Date] | null) => {
const date = handleDateChange(evt);
setDateOfBirth(date);
};
const handleDateChange = (evt: Date | [Date, Date] | null) => {
let date: Date;
if (Array.isArray(evt)) date = evt[0];
else date = evt as Date;
if (date) {
date.setHours(12);
}
return date;
};
return (
<>
{/* first name input */}
<FormGroupInput
controlId='formGivenNameInput'
title={t('translation:first-name')}
value={givenName}
onChange={(evt: any) => handleGivenNameChanged(evt.target.value)}
required
maxLength={50}
/>
{/* name input */}
<FormGroupInput
controlId='formNameInput'
title={t('translation:name')}
value={familyName}
onChange={(evt: any) => handleFamilyNameChanged(evt.target.value)}
required
maxLength={50}
/>
<hr />
<Collapse in={props.dccConsent}>
<div>
{/* standardised first name input */}
<FormGroupInput
controlId='formStandadisedGivenNameInput'
title={t('translation:standardised-first-name')}
value={standardisedGivenName}
onChange={(evt: any) =>
handleStandardisedNameChanged(
evt.target.value,
setStandardisedGivenName
)
}
required={props.dccConsent}
pattern={utils.pattern.standardisedName}
maxLength={150}
prepend='i'
lableAlign='end'
tooltip={t('translation:standardised-first-name-tooltip')}
infoText={
<h5>
<strong>{t('translation:query-id-card')}</strong>
</h5>
}
/>
{/*standardised name input */}
<FormGroupInput
controlId='formStandadisedNameInput'
title={t('translation:standardised-name')}
value={standardisedFamilyName}
onChange={(evt: any) =>
handleStandardisedNameChanged(
evt.target.value,
setStandardisedFamilyName
)
}
required={props.dccConsent}
pattern={utils.pattern.standardisedName}
maxLength={150}
prepend='i'
tooltip={t('translation:standardised-name-tooltip')}
/>
<hr />
</div>
</Collapse>
{/* date of birth input */}
<Form.Group
as={Row}
controlId='formDateOfBirthInput'
className='pb-3 mb-0'
>
<Form.Label className='input-label ' column xs='5' sm='3'>
{t('translation:date-of-birth') + '*'}
</Form.Label>
<Col xs='7' sm='9' className='d-flex'>
<DatePicker
selected={dateOfBirth}
onChange={handleDateOfBirthChange}
locale='de'
dateFormat={utils.pickerDateFormat}
isClearable
placeholderText={t('translation:date-of-birth')}
className='qt-input form-control'
wrapperClassName='align-self-center'
showMonthDropdown
showYearDropdown
dropdownMode='select'
maxDate={new Date()}
minDate={new Date(1900, 0, 1, 12)}
openToDate={new Date(1990, 0, 1)}
required
/>
</Col>
</Form.Group>
{/* sex input */}
<Row>
<Form.Label className='input-label txt-no-wrap' column xs='5' sm='3'>
{t('translation:sex') + '*'}
</Form.Label>
<Col xs='7' sm='9' className='d-flex'>
<Row>
<FormGroupInlineRadio
controlId='sex-radio1'
name='sex-radios'
title={t('translation:male')}
checked={sex === Sex.MALE}
onChange={() => setSex(Sex.MALE)}
/>
<FormGroupInlineRadio
controlId='sex-radio2'
name='sex-radios'
title={t('translation:female')}
checked={sex === Sex.FEMALE}
onChange={() => setSex(Sex.FEMALE)}
required={true}
/>
<FormGroupInlineRadio
controlId='sex-radio3'
name='sex-radios'
title={t('translation:diverse')}
checked={sex === Sex.DIVERSE}
onChange={() => setSex(Sex.DIVERSE)}
/>
</Row>
</Col>
</Row>
</>
);
}
Example #7
Source File: user-table.component.tsx From cwa-quick-test-frontend with Apache License 2.0 | 4 votes |
UserTable = (props: any) => {
// const context = React.useContext(AppContext);
const { t } = useTranslation();
const { keycloak } = useKeycloak();
const handleSuccess = () => {
setIsUserSuccessfullUpdated(true);
setIsUserCreationError(false);
setTimeout(setShowUserModal, 300, false);
setShowConfirm(false);
}
const [bUsers,
// refreshUsers,
createUser,
readUser,
updateUser,
deleteUser] = useGetUsers(handleSuccess, props.handleError);
const [users, setUsers] = React.useState<IDisplayUser[]>([]);
const [reload, setReload] = React.useState(true);
const [showUserModal, setShowUserModal] = React.useState(false);
const [isUserSuccessfullUpdated, setIsUserSuccessfullUpdated] = React.useState(false);
const [isUserCreationError, setIsUserCreationError] = React.useState(false);
const [editUser, setEditUser] = React.useState<IDisplayUser>(emptyUser);
const [ownUserId, setOwnUserId] = React.useState<string>('');
const [showConfirm, setShowConfirm] = React.useState(false);
const [confirmMessage, setConfirmMessage] = React.useState('');
const [confirmTitle, setConfirmTitle] = React.useState('');
const [confirmHandle, setConfirmHandle] = React.useState<() => void>();
// set user name from keycloak
React.useEffect(() => {
if (keycloak.idTokenParsed) {
setOwnUserId((keycloak.idTokenParsed as any).sub ?? '');
}
}, [keycloak])
React.useEffect(() => {
if (bUsers) {
setUsers(bUsers);
setEditUser({ ...emptyUser });
}
}, [bUsers]);
React.useEffect(() => {
if (props.userReload) {
users.forEach((user => updateDisplayUser(user, false)));
props.setUserReload(false);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.userReload]);
React.useEffect(() => {
if (props.groupNodes && users && users.length > 0 && reload) {
setReload(false);
users.forEach((user => updateDisplayUser(user, true)));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(props.groupNodes), users, reload]);
const sortUsers = () => {
users.sort((a, b) => {
const nameA = a.username.toUpperCase(); // ignore upper and lowercase
const nameB = b.username.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
}
const addDisplayUser = (user: IDisplayUser) => {
setGroupPath(user);
user.displayRole = getDisplayRole(user);
users.push(user);
sortUsers();
setUsers(users);
}
const updateDisplayUser = (user: IDisplayUser, withApi: boolean, onSuccess?: () => void) => {
// set all groupPath for display
setGroupPath(user);
// set all rollDisplay async
if (withApi) {
readUser(user)
.then((response) => {
user.roleCounter = response.data.roleCounter;
user.roleLab = response.data.roleLab;
user.displayRole = getDisplayRole(user);
})
.finally(() => {
updateUsers(user);
if (onSuccess) {
onSuccess();
}
})
}
else {
updateUsers(user);
}
}
const updateUsers = (user: IDisplayUser | IUser) => {
const _users: IDisplayUser[] = [...users];
_users[_users.findIndex(_user => user.id === _user.id)] = { ...user };
setUsers(_users);
}
const removeUsers = (user: IDisplayUser | IUser) => {
users.splice(users.findIndex(_user => user.id === _user.id), 1);
setUsers(users);
}
const userUpdate = (user: IUser) => {
if (editUser && editUser.username) {
const fuser = users.find(u => u.username === user.username);
if (!user.password) {
user.password = undefined;
}
updateUser(user)
.then(() => {
if (
fuser
&& fuser.subGroup !== user.subGroup
&& keycloak.token
&& user.subGroup
) {
addUserToGroup(user.id, user.subGroup, keycloak.token)
.then(() => {
updateDisplayUser(user, true, handleSuccess);
})
.catch(e => {
props.handleError(e);
});
} else {
updateDisplayUser(user, true, handleSuccess);
}
})
} else {
const newUser: any = { ...user };
createUser(newUser)
.then((response) => {
const displayUser: IDisplayUser = { ...response.data };
addDisplayUser(displayUser);
handleSuccess();
})
.catch(e => {
if (e && e.message && (e.message as string).includes('409')) {
setIsUserCreationError(true);
}
else {
props.handleError(e);
}
})
}
}
const startEditUser = (user: IUser) => {
setEditUser({ ...user });
setShowUserModal(true);
}
const handleDeleteUser = (user: IDisplayUser) => {
setConfirmTitle(t('translation:delete-user-title', { userName: user.username }));
setConfirmMessage('');
setShowConfirm(true);
const handle = () => {
if (keycloak.token && user.username) {
deleteUser(user.id)
.then(() => {
removeUsers(user);
handleSuccess();
})
.catch(e => {
props.handleError(e);
})
}
};
// need to wrap a function again because react apply each function passed to hook
setConfirmHandle(() => handle);
}
const getDisplayRole = (user: IUser) => {
let roleString = '';
if (user.roleLab) {
roleString = t('translation:lab');
}
if (user.roleCounter) {
if (roleString) {
roleString += ', ';
}
roleString += t('translation:counter');
}
return roleString;
}
const setGroupPath = (user: IDisplayUser) => {
if (user.subGroup) {
const _groupName = getGroupPath(user.subGroup);
if (_groupName) {
user.displayGroup = _groupName;
}
else {
user.subGroup = '';
user.displayGroup = '';
}
}
else {
user.displayGroup = '';
}
}
const getGroupPath = (groupId: string | null): string => {
let groupName = ''
if (props.groupNodes && groupId) {
const fNode = (props.groupNodes as IGroupNode[]).find(gnode => gnode.group.id === groupId);
if (fNode) {
groupName = fNode.group.path;
}
}
return groupName;
}
return (<>
{
!(users && users.length > 0)
? <CwaSpinner background='#eeeeee' />
: <Collapse appear={true} in={true}>
<Container className='p-0 '>
<Table bordered hover responsive>
<thead>
<tr>
<th>{t('translation:user-name')}</th>
<th>{t('translation:first-name')}</th>
<th>{t('translation:name')}</th>
<th>{t('translation:group')}</th>
<th>{t('translation:permission')}</th>
<th></th>
</tr>
</thead>
<tbody>{
users.map((u, i) =>
<tr key={i}>
<td>{u.subGroup || (ownUserId && u.id === ownUserId)
? <></>
: <OverlayTrigger
placement='top-end'
overlay={
<Tooltip id='no-group-tooltip'>
{t('translation:no-group-tooltip')}
</Tooltip>
}
>
<span className='ff-fa px-1'> </span>
</OverlayTrigger>}
{u.username}</td>
<td>{u.firstName}</td>
<td>{u.lastName}</td>
<td>
{
u.displayGroup
? u.displayGroup
: u.subGroup
? <Spinner
animation="border"
className='d-flex mx-auto'
size="sm"
role="status"
aria-hidden="true"
variant='primary'
/>
: <></>
}
</td>
<td>{
u.displayRole !== undefined
? u.displayRole
: <Spinner
animation="border"
className='d-flex mx-auto'
size="sm"
role="status"
aria-hidden="true"
variant='primary'
/>
}
</td>
<td className='td-btn'>
<Row className='m-0 justify-content-around'>
<Button
className="btn-icon edit-icon"
onClick={() => startEditUser({ ...u })}
>
</Button>
<Button className="btn-icon delete-icon"
onClick={() => handleDeleteUser(u)}
disabled={!(ownUserId && u.id !== ownUserId)}
/>
</Row>
</td>
</tr>
)
}</tbody>
</Table>
<Button
className='btn-add'
size="sm"
variant="light"
onClick={() => { setEditUser({ ...emptyUser }); setShowUserModal(true) }}>
<img className='mr-2' src={imageAdd} alt="Hinzufügen" />
{t('translation:add-user')}
</Button>
</Container>
</Collapse>
}
<UserModal
show={showUserModal}
groups={props.groupNodes}
handleOk={userUpdate}
user={editUser}
onEnter={() => setIsUserSuccessfullUpdated(false)}
isSuccess={isUserSuccessfullUpdated}
isCreationError={isUserCreationError}
resetError={() => setIsUserCreationError(false)}
onCancel={() => setShowUserModal(false)}
onExit={
() => {
setEditUser({ ...emptyUser });
setIsUserSuccessfullUpdated(false);
setIsUserCreationError(false);
}
}
/>
<ConfirmModal
show={showConfirm}
title={confirmTitle}
message={confirmMessage}
onCancel={() => {
setConfirmHandle(undefined);
setShowConfirm(false);
}}
handleOk={() => {
if (confirmHandle) {
confirmHandle();
}
}}
/>
</>
)
}
Example #8
Source File: record-patient-data.component.tsx From cwa-quick-test-frontend with Apache License 2.0 | 4 votes |
RecordPatientData = (props: any) => {
const context = React.useContext(AppContext);
const { t } = useTranslation();
const { keycloak } = useKeycloak();
const [isInit, setIsInit] = React.useState(false)
const [uuIdHash, setUuIdHash] = React.useState('');
const [isBack, setIsBack] = React.useState(true);
const isBackRef = React.useRef(isBack);
isBackRef.current = isBack;
const [processId, setProcessId] = React.useState('');
const processIdRef = React.useRef(processId);
processIdRef.current = processId;
const [person, setPerson] = React.useState<IPersonData>();
const [address, setAddress] = React.useState<IAddressData>();
const [pcrEnabled, setPcrEnabled] = React.useState(false);
const [testType, setTestType] = React.useState(TestType.RAT);
const [phoneNumber, setPhoneNumber] = React.useState('');
const [emailAddress, setEmailAddress] = React.useState('');
const [additionalInfo, setAdditionalInfo] = React.useState('');
const [consent, setConsent] = React.useState(false);
const [dccConsent, setDccConsent] = React.useState(false);
const [dccNoConsent, setDccNoConsent] = React.useState(false);
const [persDataInQR, setIncludePersData] = React.useState(false)
const [privacyAgreement, setPrivacyAgreement] = React.useState(false)
const [validated, setValidated] = React.useState(false);
const handleError = (error: any) => {
let msg = '';
if (error) {
msg = error.message
}
if (error && error.message && (error.message as string).includes('412')) {
msg = t('translation:no-group-error');
}
props.setError({ error: error, message: msg, onCancel: context.navigation!.toLanding });
}
const handleDelete = () => { deleteQuicktest(processIdRef.current); }
const [uuid, deleteQuicktest] = useGetUuid(props?.quickTest?.uuId, undefined, handleError);
useOnUnload(() => handleDelete);
React.useEffect(() => {
return () => {
if (isBackRef.current) {
handleDelete();
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
React.useEffect(() => {
if (keycloak.idTokenParsed) {
setPcrEnabled(!!(keycloak.idTokenParsed as any).pcr_enabled);
}
}, [keycloak])
// set values from props or new uuid on mount
React.useEffect(() => {
if (props.quickTest) {
const p = props.quickTest;
setConsent(p.processingConsens);
setIncludePersData(p.includePersData);
setPrivacyAgreement(p.privacyAgreement);
setPhoneNumber(p.phoneNumber);
if (p.emailAddress) {
setEmailAddress(p.emailAddress);
}
if (p.additionalInfo) {
setAdditionalInfo(p.additionalInfo);
}
setDccConsent(p.dccConsent);
setDccNoConsent(!p.dccConsent);
setTestType(p.testType);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.quickTest]);
// set hash from uuid
React.useEffect(() => {
if (uuid) {
setUuIdHash(sha256(uuid).toString());
}
}, [uuid]);
// set process id from hash
React.useEffect(() => {
setProcessId(utils.shortHash(uuIdHash));
}, [uuIdHash]);
// set ready state for spinner
React.useEffect(() => {
if (processId && context.navigation && context.valueSets) {
setIsInit(true);
}
}, [processId, context.navigation, context.valueSets])
const handleDccConsentChange = (evt: any) => {
setDccConsent(true)
setDccNoConsent(false);
}
const handleDccNoConsentChange = (evt: any) => {
setDccConsent(false)
setDccNoConsent(true);
}
const handleConsentChange = (evt: any) => {
setConsent(!consent)
setIncludePersData(false);
}
const handlePersDataInQRChange = (evt: any) => {
setIncludePersData(!persDataInQR);
setConsent(false);
}
const handleCancel = () => {
props.setQuickTest(undefined);
context.navigation!.toLanding();
}
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
const form = event.currentTarget;
event.preventDefault();
event.stopPropagation();
setValidated(true);
setIsBack(false);
if (form.checkValidity() && person) {
props.setQuickTest({
personData: person,
addressData: address,
processingConsens: consent,
uuId: uuid,
includePersData: persDataInQR,
privacyAgreement: privacyAgreement,
phoneNumber: phoneNumber,
emailAddress: emailAddress || undefined,
dccConsent: dccConsent,
additionalInfo: additionalInfo || undefined,
testType: testType
})
setTimeout(context.navigation!.toShowRecordPatient, 200);
}
}
return (
!(isInit && context && context.valueSets)
? <CwaSpinner />
: <Fade appear={true} in={true} >
<Container className='form-flex p-0 '>
<Row id='process-row'>
<span className='font-weight-bold mr-2'>{t('translation:process')}</span>
<span>{processId}</span>
</Row>
<Card id='data-card'>
<Form className='form-flex' onSubmit={handleSubmit} validated={validated}>
{/*
header with title and id card query
*/}
<CardHeader idCard={true} title={t('translation:record-result2')} />
{/*
content area with patient inputs and check box
*/}
<Card.Body id='data-body' className='pt-0'>
{/* dccConsent */}
<Row className='yellow'>
<Col className='p-0' xs='5' sm='3'>
<Row className='m-0 mb-2'>
<Col className='p-0' xs='auto'>
<Form.Label className='input-label pl-1'>
{t('translation:testZertifikat')}*
</Form.Label>
</Col>
<Col className='p-0 jcc-xs-jcfs-lg ml-lg-2 d-flex'>
<Image className="eu-flag" src={eu_logo} />
</Col>
</Row>
</Col>
<Col xs='7' sm='9'>
<Row className='m-0'>
<Form.Label className='input-label m-0'>{t('translation:dccConsent')}</Form.Label>
</Row>
<Collapse in={dccConsent}>
<Row className='m-0 my-1'>
<Form.Label className='input-label text-justify m-0'>
<Form.Label className='input-label mb-0 mr-2'>

</Form.Label>
{t('translation:dccConsent-cwa-only')}
</Form.Label>
</Row>
</Collapse>
<Row className='m-0 mb-2'>
<FormGroupDccConsentRadio controlId='dccConsent-radio1' name="dccConsent-radios" title={t('translation:ja')}
checked={dccConsent}
onChange={handleDccConsentChange}
required={true}
/>
<FormGroupDccConsentRadio controlId='dccConsent-radio2' name="dccConsent-radios" title={t('translation:nein')}
checked={dccNoConsent}
onChange={handleDccNoConsentChange}
required={true}
/>
</Row>
</Col>
</Row>
<hr />
{!pcrEnabled
? <></>
: <>
<Row>
<Form.Label className='input-label txt-no-wrap' column xs='5' sm='3'>{t('translation:test-type') + '*'}</Form.Label>
<Col xs='7' sm='9' className='d-flex'>
<Row>
<FormGroupInlineRadio controlId='test-type1' name="test-type-radios" title={t(`translation:${TestType.RAT}`)} sm='6'
checked={testType === TestType.RAT}
onChange={() => setTestType(TestType.RAT)}
/>
<FormGroupInlineRadio controlId='test-type2' name="test-type-radios" title={t(`translation:${TestType.PCR}`)} sm='6'
checked={testType === TestType.PCR}
onChange={() => setTestType(TestType.PCR)}
required={true}
/>
</Row>
</Col>
</Row>
<hr />
</>
}
<PersonInputs quickTest={props.quickTest} onChange={setPerson} dccConsent={dccConsent} onDccChanged={setDccConsent} />
<hr />
{/* address input */}
<AddressInputs quickTest={props.quickTest} onChange={setAddress} />
<hr />
{/* phone number input */}
< FormGroupInput controlId='formPhoneInput' title={t('translation:phone-number')}
value={phoneNumber}
onChange={(evt: any) => setPhoneNumber(evt.target.value)}
type='tel'
required
pattern={utils.pattern.tel}
maxLength={79}
/>
< FormGroupInput controlId='formEmailInput' title={t('translation:email-address')}
value={emailAddress}
onChange={(evt: any) => setEmailAddress(evt.target.value)}
type='email'
pattern={utils.pattern.eMail}
minLength={5}
maxLength={255}
/>
< FormGroupInput controlId='formAdditionalInfo' title={t('translation:additional-info')}
value={additionalInfo}
onChange={(evt: any) => setAdditionalInfo(evt.target.value)}
type='text'
minLength={1}
maxLength={250}
prepend='i'
tooltip={t('translation:additional-info-tooltip')}
/>
<hr />
{/* processing consent check box */}
<FormGroupConsentCkb controlId='formConsentCheckbox' title={t('translation:processing-consent-title')}
accordion={t('translation:processing-consent')}
onClick={handleConsentChange}
onChange={handleConsentChange}
type='radio'
name="check-radios"
checked={consent}
required={dccConsent}
/>
<FormGroupConsentCkb controlId='formKeepPrivateCheckbox' title={t('translation:patientdata-exclude-title')}
accordion={t('translation:patientdata-exclude')}
onClick={handlePersDataInQRChange}
onChange={handlePersDataInQRChange}
type='radio'
name="check-radios"
checked={persDataInQR}
required={dccConsent}
/>
<FormGroupConsentCkb controlId='formDataPrivacyCheckbox' title={t('translation:data-privacy-approve')}
onChange={(evt: any) => setPrivacyAgreement(evt.currentTarget.checked)}
type='checkbox'
checked={privacyAgreement}
required
/>
</Card.Body>
{/*
footer with clear and nex button
*/}
<CardFooter handleCancel={handleCancel} />
</Form>
</Card>
</Container>
</Fade>
)
}
Example #9
Source File: index.tsx From nouns-monorepo with GNU General Public License v3.0 | 4 votes |
ProfileActivityFeed: React.FC<ProfileActivityFeedProps> = props => {
const { nounId } = props;
const MAX_EVENTS_SHOW_ABOVE_FOLD = 5;
const [truncateProposals, setTruncateProposals] = useState(true);
const { loading, error, data } = useQuery(nounVotingHistoryQuery(nounId));
const {
loading: proposalTimestampLoading,
error: proposalTimestampError,
data: proposalCreatedTimestamps,
} = useQuery(createTimestampAllProposals());
const nounCanVoteTimestamp = useNounCanVoteTimestamp(nounId);
const { data: proposals } = useAllProposals();
if (loading || !proposals || !proposals.length || proposalTimestampLoading) {
return <></>;
} else if (error || proposalTimestampError) {
return (
<div>
<Trans>Failed to fetch Noun activity history</Trans>
</div>
);
}
const nounVotes: { [key: string]: NounVoteHistory } = data.noun.votes
.slice(0)
.reduce((acc: any, h: NounVoteHistory, i: number) => {
acc[h.proposal.id] = h;
return acc;
}, {});
const filteredProposals = proposals.filter((p: Proposal, id: number) => {
return (
parseInt(proposalCreatedTimestamps.proposals[id].createdTimestamp) >
nounCanVoteTimestamp.toNumber() ||
(p.id && nounVotes[p.id])
);
});
return (
<Section fullWidth={false}>
<Col lg={{ span: 10, offset: 1 }}>
<div className={classes.headerWrapper}>
<h1>
<Trans>Activity</Trans>
</h1>
</div>
{filteredProposals && filteredProposals.length ? (
<>
<Table responsive hover className={classes.aboveTheFoldEventsTable}>
<tbody className={classes.nounInfoPadding}>
{filteredProposals?.length ? (
filteredProposals
.slice(0)
.reverse()
.slice(0, MAX_EVENTS_SHOW_ABOVE_FOLD)
.map((p: Proposal, i: number) => {
const vote = p.id ? nounVotes[p.id] : undefined;
return <NounProfileVoteRow proposal={p} vote={vote} key={i} />;
})
) : (
<LoadingNoun />
)}
</tbody>
</Table>
<Collapse in={!truncateProposals}>
<div>
<Table responsive hover>
<tbody className={classes.nounInfoPadding}>
{filteredProposals?.length ? (
filteredProposals
.slice(0)
.reverse()
.slice(MAX_EVENTS_SHOW_ABOVE_FOLD, filteredProposals.length)
.map((p: Proposal, i: number) => {
const vote = p.id ? nounVotes[p.id] : undefined;
return <NounProfileVoteRow proposal={p} vote={vote} key={i} />;
})
) : (
<LoadingNoun />
)}
</tbody>
</Table>
</div>
</Collapse>
{filteredProposals.length <= MAX_EVENTS_SHOW_ABOVE_FOLD ? (
<></>
) : (
<>
{truncateProposals ? (
<div
className={classes.expandCollapseCopy}
onClick={() => setTruncateProposals(false)}
>
<Trans>Show all {filteredProposals.length} events </Trans>{' '}
<FontAwesomeIcon icon={faChevronDown} />
</div>
) : (
<div
className={classes.expandCollapseCopy}
onClick={() => setTruncateProposals(true)}
>
<Trans>Show fewer</Trans> <FontAwesomeIcon icon={faChevronUp} />
</div>
)}
</>
)}
</>
) : (
<div className={classes.nullStateCopy}>
<Trans>This Noun has no activity, since it was just created. Check back soon!</Trans>
</div>
)}
</Col>
</Section>
);
}