-
Notifications
You must be signed in to change notification settings - Fork 41
Implement attachment viewer gallery in record sets #3363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
786ae34
Implement attachment viewer gallery in record sets
CarolineDenis c4b965b
Fix failing tests, change localized strings
CarolineDenis 319ec82
Allow to create record set from express search results
maxpatiiuk 0dafeaa
Lint code with ESLint and Prettier
maxpatiiuk 23e1586
Implement attachment viewer gallery in record sets
CarolineDenis 66f5d4c
Merge branch 'issue-2132' of https://github.com/specify/specify7 into…
CarolineDenis 69c67d0
Change variable name
CarolineDenis b596831
Fix failing tests
CarolineDenis 082e72c
Implement attachment viewer gallery in record sets
CarolineDenis fbf0c2c
Lint code with ESLint and Prettier
CarolineDenis cef641f
Merge branch 'issue-2132' of https://github.com/specify/specify7 into…
CarolineDenis f79e691
Implement attachment viewer gallery in record sets
CarolineDenis 0edc050
Merge branch 'issue-2132' of https://github.com/specify/specify7 into…
CarolineDenis 5921aa6
Lint code with ESLint and Prettier
CarolineDenis 9e7d597
Allow to make changes to atatchment
CarolineDenis a3fb90a
Remove obstrusive loading dialog
CarolineDenis 8c43fb0
Display previous fetched attachments while new ones are being fetched
CarolineDenis 0b58ab2
Lint code with ESLint and Prettier
CarolineDenis bdf456b
Simplify code
CarolineDenis a277044
Lint code with ESLint and Prettier
CarolineDenis d3f995f
Change shadows in attachment gallery
CarolineDenis 7053ebd
Change the minimum width value for attachment dialog
CarolineDenis 772178a
Lint code with ESLint and Prettier
CarolineDenis dab39e4
Merge remote-tracking branch 'origin/production' into issue-2132
CarolineDenis 86203e1
Lint code with ESLint and Prettier
CarolineDenis 86b120a
Delete loading gif for attachment thumbnail
CarolineDenis 9d0ac45
Merge remote-tracking branch 'origin/production' into issue-2132
CarolineDenis d347557
Disable attachment set until attachments are defined
CarolineDenis cbf4129
Lint code with ESLint and Prettier
CarolineDenis 983a29a
Merge remote-tracking branch 'origin/production' into issue-2132
CarolineDenis 1753216
Merge branch 'production' into issue-2132
CarolineDenis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
154 changes: 154 additions & 0 deletions
154
specifyweb/frontend/js_src/lib/components/Attachments/RecordSetAttachment.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| import React from 'react'; | ||
|
|
||
| import { useAsyncState } from '../../hooks/useAsyncState'; | ||
| import { useBooleanState } from '../../hooks/useBooleanState'; | ||
| import { useCachedState } from '../../hooks/useCachedState'; | ||
| import { attachmentsText } from '../../localization/attachments'; | ||
| import { commonText } from '../../localization/common'; | ||
| import { f } from '../../utils/functools'; | ||
| import type { RA } from '../../utils/types'; | ||
| import { filterArray } from '../../utils/types'; | ||
| import { Button } from '../Atoms/Button'; | ||
| import { serializeResource } from '../DataModel/helpers'; | ||
| import type { AnySchema } from '../DataModel/helperTypes'; | ||
| import type { SpecifyResource } from '../DataModel/legacyTypes'; | ||
| import type { CollectionObjectAttachment } from '../DataModel/types'; | ||
| import { Dialog, dialogClassNames } from '../Molecules/Dialog'; | ||
| import { defaultAttachmentScale } from '.'; | ||
| import { AttachmentGallery } from './Gallery'; | ||
|
|
||
| const haltIncrementSize = 300; | ||
|
|
||
| export function RecordSetAttachments<SCHEMA extends AnySchema>({ | ||
| records, | ||
| onFetch: handleFetch, | ||
| }: { | ||
| readonly records: RA<SpecifyResource<SCHEMA> | undefined>; | ||
| readonly onFetch: | ||
| | ((index: number) => Promise<RA<number | undefined> | void>) | ||
| | undefined; | ||
| }): JSX.Element { | ||
| const fetchedCount = React.useRef<number>(0); | ||
|
|
||
| const [showAttachments, handleShowAttachments, handleHideAttachments] = | ||
| useBooleanState(); | ||
|
|
||
| const [attachments] = useAsyncState( | ||
| React.useCallback(async () => { | ||
| const relatedAttachmentRecords = await Promise.all( | ||
| records.map(async (record) => | ||
| record | ||
| ?.rgetCollection(`${record.specifyModel.name}Attachments`) | ||
| .then( | ||
| ({ models }) => | ||
| models as RA<SpecifyResource<CollectionObjectAttachment>> | ||
| ) | ||
| ) | ||
| ); | ||
|
|
||
| const fetchCount = records.findIndex( | ||
| (record) => record?.populated !== true | ||
| ); | ||
|
|
||
| fetchedCount.current = fetchCount === -1 ? records.length : fetchCount; | ||
|
|
||
| const attachments = await Promise.all( | ||
| filterArray(relatedAttachmentRecords.flat()).map( | ||
| async (collectionObjectAttachment) => ({ | ||
| attachment: await collectionObjectAttachment | ||
| .rgetPromise('attachment') | ||
| .then((resource) => serializeResource(resource)), | ||
| related: collectionObjectAttachment, | ||
| }) | ||
| ) | ||
| ); | ||
|
|
||
| return { | ||
| attachments: attachments.map(({ attachment }) => attachment), | ||
| related: attachments.map(({ related }) => related), | ||
| }; | ||
| }, [records]), | ||
| false | ||
| ); | ||
| const attachmentsRef = React.useRef(attachments); | ||
|
|
||
| if (typeof attachments === 'object') attachmentsRef.current = attachments; | ||
|
|
||
| /* | ||
| * Stop fetching records if the first 300 don't have attachments | ||
| * to save computing resources. Ask the user to continue and fetch | ||
| * the next haltIncrementSize (300) if desired. | ||
| */ | ||
| const [haltValue, setHaltValue] = React.useState(39); | ||
| const halt = | ||
| attachments?.attachments.length === 0 && records.length >= haltValue; | ||
|
|
||
| const [scale = defaultAttachmentScale] = useCachedState( | ||
| 'attachments', | ||
| 'scale' | ||
| ); | ||
|
|
||
| return ( | ||
| <> | ||
| <Button.Icon | ||
| disabled={attachments === undefined} | ||
| icon="photos" | ||
| title="attachments" | ||
| onClick={handleShowAttachments} | ||
| /> | ||
| {showAttachments && ( | ||
| <Dialog | ||
| buttons={ | ||
| <Button.DialogClose>{commonText.close()}</Button.DialogClose> | ||
| } | ||
| className={{ | ||
| container: dialogClassNames.wideContainer, | ||
| }} | ||
| header={ | ||
| attachmentsRef.current?.attachments === undefined | ||
| ? attachmentsText.attachments() | ||
| : commonText.countLine({ | ||
| resource: attachmentsText.attachments(), | ||
| count: attachmentsRef.current.attachments.length, | ||
| }) | ||
| } | ||
| onClose={handleHideAttachments} | ||
| > | ||
| {halt ? ( | ||
| haltValue === records.length ? ( | ||
| <>{attachmentsText.noAttachments()}</> | ||
| ) : ( | ||
| <div className="flex flex-col gap-4"> | ||
| {attachmentsText.attachmentHaltLimit({ halt: haltValue })} | ||
| <Button.Warning | ||
| onClick={(): void => | ||
| setHaltValue( | ||
| Math.min(haltValue + haltIncrementSize, records.length) | ||
| ) | ||
| } | ||
| > | ||
| {attachmentsText.fetchNextAttachments()} | ||
| </Button.Warning> | ||
| </div> | ||
| ) | ||
| ) : ( | ||
| <AttachmentGallery | ||
| attachments={attachmentsRef?.current?.attachments ?? []} | ||
| isComplete={fetchedCount.current === records.length} | ||
| scale={scale} | ||
| onChange={(attachment, index): void => | ||
| void attachments?.related[index].set(`attachment`, attachment) | ||
| } | ||
| onFetchMore={ | ||
| attachments === undefined || handleFetch === undefined || halt | ||
| ? undefined | ||
| : async (): Promise<void> => | ||
| handleFetch?.(fetchedCount.current).then(f.void) | ||
| } | ||
| /> | ||
| )} | ||
| </Dialog> | ||
| )} | ||
| </> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.