Skip to content

Commit

Permalink
Use KeyValueTable component to display metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
apdavison committed Mar 7, 2024
1 parent 36506d4 commit 47260eb
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 143 deletions.
4 changes: 1 addition & 3 deletions apps/nar-v3/__tests__/components/DatasetCard.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import { describe, test, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";


import DatasetCard from "../../src/components/DatasetCard";


describe("DatasetCard component", () => {
test("should render without errors", async () => {
const dataset = {
Expand Down Expand Up @@ -545,7 +543,7 @@ describe("DatasetCard component", () => {
],
biologicalSex: "male",
},
]
],
};

render(<DatasetCard dataset={dataset} />);
Expand Down
54 changes: 20 additions & 34 deletions apps/nar-v3/src/components/CellPatchingCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,53 +21,39 @@ import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";

import Connection from "./Connection";
import KeyValueTable from "./KeyValueTable";
import styles from "../styles";
import { formatQuant } from "../utility";

function CellPatchingCard(props) {
const activity = props.activity;

const data = {
"Electrode description": activity.device[0].device.description,
"Pipette solution (more details to come)": activity.device[0].pipetteSolution.name,
"Seal resistance": activity.device[0].sealResistance.value
.map((item) => formatQuant(item))
.join(", "),
"Series resistance": activity.device[0].seriesResistance.value
.map((item) => formatQuant(item))
.join(", "),
"Holding potential": activity.device[0].holdingPotential.value
.map((item) => formatQuant(item))
.join(", "),
"Bath solution (more details to come)": activity.tissueBathSolution.name,
"Bath temperature": formatQuant(activity.bathTemperature),
Description: activity.description,
Type: activity.variation,
};

if (activity) {
return (
<>
<Connection />
<Box sx={styles.activity} component={Paper} variant="outlined">
<h2>Cell patching</h2>
<p>{activity.label}</p>

<dl>
<dt>Electrode description</dt>
<dd>{activity.device[0].device.description}</dd>
{/* activity.device[0].device.deviceType.name */}
{/* activity.device[0].device.manufacturer.fullName */}
<dt>Pipette solution (more details to come)</dt>
<dd>{activity.device[0].pipetteSolution.name}</dd>
<dt>Seal resistance</dt>
<dd>
{activity.device[0].sealResistance.value.map((item) => formatQuant(item)).join(", ")}
</dd>
<dt>Series resistance</dt>
<dd>
{activity.device[0].seriesResistance.value
.map((item) => formatQuant(item))
.join(", ")}
</dd>
<dt>Holding potential</dt>
<dd>
{activity.device[0].holdingPotential.value
.map((item) => formatQuant(item))
.join(", ")}
</dd>

<dt>Bath solution (more details to come)</dt>
<dd>{activity.tissueBathSolution.name}</dd>
<dt>Bath temperature</dt>
<dd>{formatQuant(activity.bathTemperature)}</dd>
<dt>Description</dt>
<dd>{activity.description}</dd>
<dt>Type</dt>
<dd>{activity.variation}</dd>
</dl>
<KeyValueTable boldKeys data={data} />
</Box>
</>
);
Expand Down
34 changes: 18 additions & 16 deletions apps/nar-v3/src/components/DataFileCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,35 @@ import Paper from "@mui/material/Paper";

import { formatQuant } from "../utility";
import Connection from "./Connection";
import KeyValueTable from "./KeyValueTable";
import styles from "../styles";

function DataFileCard(props) {
const fileObj = props.fileObj;

const data = {
"Data type": fileObj.dataType ? fileObj.dataType.name : "unknown",
Format: fileObj.format ? fileObj.format.name : "unknown",
Hash: (
<>
{fileObj.hash.map((item) => (
<span key={item.algorithm}>
{item.algorithm}: {item.digest}&nbsp;
</span>
))}
</>
),
Size: formatQuant(fileObj.storageSize),
};

if (fileObj) {
return (
<>
<Connection />
<Box sx={styles.entity} component={Paper} variant="outlined">
<h2>File {fileObj.name}</h2>
<dl>
<dt>Data type</dt>
<dd>{fileObj.dataType ? fileObj.dataType.name : "unknown"}</dd>
<dt>Format</dt>
<dd>{fileObj.format ? fileObj.format.name : "unknown"}</dd>
<dt>Hash</dt>
<dd>
{fileObj.hash.map((item) => (
<span key={item.algorithm}>
{item.algorithm}: {item.digest}&nbsp;
</span>
))}
</dd>
<dt>Size</dt>
<dd>{formatQuant(fileObj.storageSize)}</dd>
</dl>

<KeyValueTable boldKeys data={data} />
</Box>
</>
);
Expand Down
42 changes: 42 additions & 0 deletions apps/nar-v3/src/components/KeyValueTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { isValidElement } from "react";
import { Table, TableBody, TableRow, TableCell } from "@mui/material";

function KeyValueTable(props) {
let formatKey = (key) => {
return key;
};
if (props.boldKeys) {
formatKey = (key) => {
return <b>{key}</b>;
};
}

let rows = [];
if (props.data) {
for (const [key, value] of Object.entries(props.data)) {
let valueStr = value;
if (!isValidElement(value)) {
// allow passing JSX as values
valueStr = String(value);
if (Array.isArray(value)) {
valueStr = value.join(", ");
}
}

rows.push(
<TableRow key={key} sx={{ "&:last-child td": { border: 0 } }}>
<TableCell>{formatKey(key)}</TableCell>
<TableCell sx={{ whiteSpace: "normal", wordBreak: "break-word" }}>{valueStr}</TableCell>
</TableRow>
);
}
}

return (
<Table size="small" aria-label="key-value table">
<TableBody>{rows}</TableBody>
</Table>
);
}

export default KeyValueTable;
9 changes: 5 additions & 4 deletions apps/nar-v3/src/components/PatchedCellCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,23 @@ import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";

import Connection from "./Connection";
import KeyValueTable from "./KeyValueTable";
import styles from "../styles";

function PatchedCellCard(props) {
if (props.cell) {
const cell = props.cell.cell;

if (cell) {
const data = {
Location: cell.anatomicalLocation.map((item) => item.name).join(", "),
};
return (
<>
<Connection />
<Box sx={styles.entity} component={Paper} variant="outlined">
<h2>Patched cell #{cell.internalIdentifier}</h2>
<dl>
<dt>Location</dt>
<dd>{cell.anatomicalLocation.map((item) => item.name).join(", ")}</dd>
</dl>
<KeyValueTable boldKeys data={data} />
</Box>
</>
);
Expand Down
62 changes: 25 additions & 37 deletions apps/nar-v3/src/components/RecordingCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { Fragment } from "react";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";

import Connection from "./Connection";
import KeyValueTable from "./KeyValueTable";
import styles from "../styles";
import { formatQuant, formatUnits } from "../utility";

Expand All @@ -30,6 +30,26 @@ function RecordingCard(props) {
const stimulation = props.stimulation;

if (recording) {
const recordingData = {
Description: recording.description,
"Additional remarks": recording.device.metadata.additionalRemarks,
"Sampling frequency": formatQuant(recording.device.metadata.samplingFrequency),
Channels: (
<ul>
{recording.device.metadata.channel.map((item) => (
<li key={item.internalIdentifier}>
{item.internalIdentifier} ({formatUnits(item.unit)})
</li>
))}
</ul>
),
};
const stimulationData = {
Type: "Current injection",
Description: stimulation.stimulus[0].lookupLabel,
"Epoch duration": formatQuant(stimulation.stimulus[0].epoch),
Identifier: stimulation.stimulus[0].internalIdentifier,
};
const stimulusSpec = JSON.parse(stimulation.stimulus[0].specification.configuration);

return (
Expand All @@ -38,46 +58,14 @@ function RecordingCard(props) {
<Box sx={styles.activity} component={Paper} variant="outlined">
<h2>Recording</h2>
<p>{recording.label}</p>
<dl>
<dt>Description</dt>
<dd>{recording.description}</dd>
<dt>Additional remarks</dt>
<dd>{recording.device.metadata.additionalRemarks}</dd>
<dt>Sampling frequency</dt>
<dd>{formatQuant(recording.device.metadata.samplingFrequency)}</dd>
<dt>Channels</dt>
<dd>
<ul>
{recording.device.metadata.channel.map((item) => (
<li key={item.internalIdentifier}>
{item.internalIdentifier} ({formatUnits(item.unit)})
</li>
))}
</ul>
</dd>
</dl>
<KeyValueTable boldKeys data={recordingData} />

<h2>Stimulation</h2>
<p>{stimulation.label}</p>
<dl>
<dt>Type</dt>
<dd>Current injection</dd>
<dt>Description</dt>
<dd>{stimulation.stimulus[0].lookupLabel}</dd>
<dt>Epoch duration</dt>
<dd>{formatQuant(stimulation.stimulus[0].epoch)}</dd>
<dt>Identifier</dt>
<dd>{stimulation.stimulus[0].internalIdentifier}</dd>
</dl>
<KeyValueTable boldKeys data={stimulationData} />

<h3>Specification</h3>
<dl>
{Object.entries(stimulusSpec).map((item, index) => (
<Fragment key={index}>
<dt key={`key${index}`}>{item[0]}</dt>
<dd key={`value${index}`}>{item[1]}</dd>
</Fragment>
))}
</dl>
<KeyValueTable boldKeys data={stimulusSpec} />
</Box>
</>
);
Expand Down
11 changes: 7 additions & 4 deletions apps/nar-v3/src/components/SliceCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Paper from "@mui/material/Paper";
import Stack from "@mui/material/Stack";

import Connection from "./Connection";
import KeyValueTable from "./KeyValueTable";
import { NavigateNext, NavigatePrevious } from "./Navigation";
import styles from "../styles";

Expand All @@ -29,6 +30,11 @@ function SliceCard(props) {
const slice = props.slices[props.index].slice;

if (slice) {
const data = {
"Location (todo: add link outs)": slice.anatomicalLocation
.map((item) => item.name)
.join(", "),
};
return (
<>
<Connection />
Expand All @@ -45,10 +51,7 @@ function SliceCard(props) {
<p>
({props.index + 1} of {props.slices.length})
</p>
<dl>
<dt>Location (todo: add link outs)</dt>
<dd>{slice.anatomicalLocation.map((item) => item.name).join(", ")}</dd>
</dl>
<KeyValueTable boldKeys data={data} />
</Box>
<Stack sx={{ width: "60px" }} justifyContent="center">
{props.index < props.slices.length - 1 ? (
Expand Down
35 changes: 14 additions & 21 deletions apps/nar-v3/src/components/SlicePreparationCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,32 @@ import Paper from "@mui/material/Paper";

import { formatQuant } from "../utility";
import Connection from "./Connection";
import KeyValueTable from "./KeyValueTable";
import styles from "../styles";

function SlicePreparationCard(props) {
const activity = props.activity;

if (activity) {
const data = {
"Device name": activity.device[0].device.name,
"Device type": activity.device[0].device.deviceType,
Manufacturer:
activity.device[0].device.manufacturer.fullName ||
activity.device[0].device.manufacturer.shortName,
"Slice thickness": formatQuant(activity.device[0].sliceThickness),
"Slicing plane": activity.device[0].slicingPlane,
"Study targets": activity.studyTarget.join(", "),
Temperature: formatQuant(activity.temperature),
"Dissecting solution (full details to come)": activity.tissueBathSolution.name,
};
return (
<>
<Connection />
<Box sx={styles.activity} component={Paper} variant="outlined">
<h2>Slice preparation</h2>
<p>{activity.label}</p>
<dl>
<dt>Device name</dt>
<dd>{activity.device[0].device.name}</dd>
<dt>Device type</dt>
<dd>{activity.device[0].device.deviceType}</dd>
<dt>Manufacturer</dt>
<dd>
{activity.device[0].device.manufacturer.fullName ||
activity.device[0].device.manufacturer.shortName}
</dd>
<dt>Slice thickness</dt>
<dd>{formatQuant(activity.device[0].sliceThickness)}</dd>
<dt>Slicing plane</dt>
<dd>{activity.device[0].slicingPlane}</dd>
<dt>Study targets</dt>
<dd>{activity.studyTarget.join(", ")}</dd>
<dt>Temperature</dt>
<dd>{formatQuant(activity.temperature)}</dd>
<dt>Dissecting solution (full details to come)</dt>
<dd>{activity.tissueBathSolution.name}</dd>
</dl>
<KeyValueTable boldKeys data={data} />
</Box>
</>
);
Expand Down
Loading

0 comments on commit 47260eb

Please sign in to comment.