Skip to content
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

Refactor profile page #125

Merged
merged 7 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
49 changes: 49 additions & 0 deletions src/api/annotation/GetCreatorAnnotations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* Import Dependencies */
import axios from 'axios';
import KeycloakService from 'app/Keycloak';

/* Import Types */
import { Annotation } from 'app/types/Annotation';
import { JSONResultArray } from 'app/Types';

/* Import Exceptions */
import { NotFoundException } from 'app/Exceptions';


/**
* Function for fetching a the logged in user's annotations
* @returns Array of Annotations
*/
const GetCreatorAnnotations = async () => {
let creatorAnnotations: Annotation[] = [];

const token = KeycloakService.GetToken();

if (token) {
try {
const result = await axios({
method: 'get',
url: `annotation/creator`,
responseType: 'json',
headers: {
'Content-type': 'application/json',
'Authorization': `Bearer ${token}`
}
});

/* Get result data from JSON */
const data: JSONResultArray = result.data;

/* Set creator annotation items */
data.data.forEach(dataRow => {
creatorAnnotations.push(dataRow.attributes as Annotation);
});
} catch (error: any) {
throw (NotFoundException('Creator Annotations', error.request.responseURL));
};
}

return creatorAnnotations;
};

export default GetCreatorAnnotations;
48 changes: 48 additions & 0 deletions src/api/masJobRecord/GetCreatorMasJobRecords.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* Import Dependencies */
import axios from 'axios';
import KeycloakService from 'app/Keycloak';

/* Import Types */
import { MasJobRecord, JSONResultArray } from 'app/Types';

/* Import Exceptions */
import { NotFoundException } from 'app/Exceptions';


/**
* Function for fetching a the logged in user's MAS job records
* @returns Array of MAS job records
*/
const GetCreatorMasJobRecords = async () => {
let creatorMasJobRecords: MasJobRecord[] = [];

const token = KeycloakService.GetToken();

if (token) {
try {
const result = await axios({
method: 'get',
url: `mjr/creator/${KeycloakService.GetSubject()}`,
TomDijkema marked this conversation as resolved.
Show resolved Hide resolved
responseType: 'json',
headers: {
'Content-type': 'application/json',
'Authorization': `Bearer ${token}`
}
});

/* Get result data from JSON */
const data: JSONResultArray = result.data;

/* Set creator MAS job record items */
data.data.forEach(dataRow => {
creatorMasJobRecords.push(dataRow.attributes as MasJobRecord);
});
} catch (error: any) {
throw (NotFoundException('Creator MAS job records', error.request.responseURL));
};
}

return creatorMasJobRecords;
};

export default GetCreatorMasJobRecords;
52 changes: 52 additions & 0 deletions src/app/config/table/UserAnnotationRecordsTableConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* Import Dependencies */
import { createColumnHelper } from '@tanstack/react-table';

/* Import Utilities */
import { MakeJsonPathReadableString } from 'app/utilities/SchemaUtilities';


/**
* Config function that sets up the basic table column template for the user annotation records table on the profile page
* @returns Table columns
*/
const UserAnnotationRecordsTableConfig = () => {
/* User annotation record type */
type UserAnnotationRecord = {
jsonPath: string,
motivation: string,
value: string | number | boolean
};

/* Base variables */
const columnHelper = createColumnHelper<UserAnnotationRecord>();

/* Table columns */
const columns = [
columnHelper.accessor('jsonPath', {
header: 'Target',
cell: info => MakeJsonPathReadableString(info.getValue()),
meta: {
widthInRem: 10,
pinned: true
}
}),
columnHelper.accessor('motivation', {
header: 'Motivation',
meta: {
widthInRem: 10,
pinned: true
}
}),
columnHelper.accessor('value', {
header: 'Annotation value',
meta: {
widthInRem: 10,
pinned: true
}
})
];

return { columns };
};

export default UserAnnotationRecordsTableConfig;
61 changes: 61 additions & 0 deletions src/app/config/table/UserMasJobRecordsTableConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* Import Dependencies */
import { createColumnHelper } from '@tanstack/react-table';
import { format } from 'date-fns';


/**
* Config function that sets up the basic table column template for the user MAS job records table on the profile page
* @returns Table columns
*/
const UserMasJobRecordsTableConfig = () => {
/* User annotation record type */
type UserMasJobRecord = {
targetId: string,
scheduled: string,
completed: string,
state: string
};

/* Base variables */
const columnHelper = createColumnHelper<UserMasJobRecord>();



/* Table columns */
const columns = [
columnHelper.accessor('targetId', {
header: 'Target ID',
meta: {
widthInRem: 10,
pinned: true
}
}),
columnHelper.accessor('scheduled', {
header: 'Scheduled',
cell: (info) => format(info.getValue(), 'MMMM dd - yyyy'),
meta: {
widthInRem: 10,
pinned: true
}
}),
columnHelper.accessor('completed', {
header: 'Completed',
cell: (info) => format(info.getValue(), 'MMMM dd - yyyy'),
meta: {
widthInRem: 10,
pinned: true
}
}),
columnHelper.accessor('state', {
header: 'State',
meta: {
widthInRem: 10,
pinned: true
}
})
];

return { columns };
};

export default UserMasJobRecordsTableConfig;
23 changes: 13 additions & 10 deletions src/components/digitalMedia/components/topBar/TopBar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Import Dependencies */
import KeycloakService from "app/Keycloak";
import { useState } from "react";
import { Row, Col } from "react-bootstrap";
import { useNavigate } from "react-router-dom";
Expand Down Expand Up @@ -139,16 +140,18 @@ const TopBar = (props: Props) => {
}
</Row>
</Col>
<Col lg="auto">
<Button type="button"
variant="primary"
OnClick={() => SetAnnotoriousMode(annotoriousMode === 'move' ? 'draw' : 'move')}
>
<p>
{annotoriousMode === 'move' ? 'Visual Annotation' : 'Cancel visual annotation'}
</p>
</Button>
</Col>
{KeycloakService.IsLoggedIn() &&
<Col lg="auto">
<Button type="button"
variant="primary"
OnClick={() => SetAnnotoriousMode(annotoriousMode === 'move' ? 'draw' : 'move')}
>
<p>
{annotoriousMode === 'move' ? 'Visual Annotation' : 'Cancel visual annotation'}
</p>
</Button>
</Col>
}
<Col>
<TopBarActions actionDropdownItems={actionDropdownItems}
annotationMode={annotationMode}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
/* Import Dependencies */
import { Row, Col, Card } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';

/* Import Utilities */
import { MakeReadableString } from 'app/Utilities';

/* Import Types */
import { DigitalMedia } from 'app/types/DigitalMedia';

/* Import Components */
import { Audio, File, Image, Video } from 'components/elements/media/MediaComponents';
import { Button } from 'components/elements/customUI/CustomUI';


/* Props Type */
Expand All @@ -22,6 +27,9 @@ type Props = {
const DigitalSpecimenDigitalMedia = (props: Props) => {
const { digitalSpecimenDigitalMedia } = props;

/* Hooks */
const navigate = useNavigate();

/* Base variables */
const digitalMediaComponentsDict: {
[mediaType: string]: JSX.Element[]
Expand All @@ -33,10 +41,16 @@ const DigitalSpecimenDigitalMedia = (props: Props) => {
case 'Image':
case 'StillImage':
(digitalMediaComponentsDict.images || (digitalMediaComponentsDict.images = [])).push(
<Image accessURI={digitalMedia['ac:accessURI']}
sizeOrientation="height"
hoverText={digitalMedia['ods:ID']}
/>);
<Button type="button"
variant="blank"
className="h-100 w-100 px-0 py-0 object-fit-contain"
OnClick={() => navigate(`/dm/${digitalMedia['ods:ID'].replace(import.meta.env.VITE_DOI_URL, '')}`)}
>
<Image accessURI={digitalMedia['ac:accessURI']}
sizeOrientation="height"
/>
</Button>
);

break;
case 'Sound':
Expand All @@ -62,10 +76,35 @@ const DigitalSpecimenDigitalMedia = (props: Props) => {
<div className="h-100">
{/* Render dedicated media components per type */}
{Object.entries(digitalMediaComponentsDict).map(([mediaType, digitalMediaComponents]) => (
<Row key={mediaType}>
<Col>
<Card>
{digitalMediaComponents}
<Row key={mediaType}
className="h-25"
>
<Col className="h-100">
<Card className="h-100 d-flex flex-column py-2">
<Row>
<Col className="mx-3">
<p className="fs-4 tc-primary fw-lightBold">
{MakeReadableString(mediaType)}
</p>
</Col>
</Row>
<Row className="flex-grow-1 overflow-hidden mt-1">
<Col className="h-100">
<div className="h-100 horizontalScroll">
{digitalMediaComponents.map((digitalMediaComponent, index) => {
const key = `digitalMediaComponent-${index}`;

return (
<div key={key}
className="w-25 h-100 d-inline-block bgc-grey-light mx-3"
>
{digitalMediaComponent}
</div>
);
})}
</div>
</Col>
</Row>
</Card>
</Col>
</Row>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,12 @@ const PropertiesTable = (props: Props) => {

/* Set Table data */
const tableData: DataRow[] = [];
let counter: number = 0;

for (const property in properties) {
tableData.push({
key: property,
value: properties[property]
});

counter++;
};

return (
Expand Down
12 changes: 7 additions & 5 deletions src/components/elements/customUI/multiSelect/MultiSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ const MultiSelect = (props: Props) => {

return classNames({
"hover-grey": !selected,
"bgc-grey": selected,
// 'd-none': !multiSelectTrigger && !selected
"bgc-grey": selected
});
};

Expand Down Expand Up @@ -156,15 +155,18 @@ const MultiSelect = (props: Props) => {
}}
onClick={() => {
setMultiSelectTrigger(true);
OnClick?.();
OnClick?.(true);
}}
/>

{/* Absolute chevron down */}
{/* Absolute chevron up or down */}
<Button type="button"
variant="blank"
className="position-absolute end-0 me-1"
OnClick={() => setMultiSelectTrigger(!multiSelectTrigger)}
OnClick={() => {
setMultiSelectTrigger(!multiSelectTrigger);
OnClick?.();
}}
>
<FontAwesomeIcon icon={multiSelectTrigger ? faChevronUp : faChevronDown}
className="tc-primary"
Expand Down
Loading
Loading