Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
23 changes: 23 additions & 0 deletions frontend/src/components/ContainerWithSpinner.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import SmallSpinner from "./SmallSpinner";

const ContainerWithSpinner = ({ loading = false, children }) => {
return (
<div style={{ position: "relative" }}>
<div style={{ paddingRight: loading ? 32 : 0 }}>{children}</div>
{loading ? (
<div
style={{
position: "absolute",
right: 8,
bottom: 8,
}}
>
<SmallSpinner />
</div>
) : null}
</div>
);
};

export default ContainerWithSpinner;
6 changes: 4 additions & 2 deletions frontend/src/components/DataTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,14 @@ const MyDataTable = observer(
}
}, [store.selectedRows.length, store.projectBannerStatusCode]);

const { data: siteSettingsData } = useGetSiteSettings();
const { data: siteSettingsData, loading: siteSettingsLoading } =
useGetSiteSettings();
useEffect(() => {
if (siteSettingsData) {
store.setSiteSettingsData(siteSettingsData);
store.setSiteSettingsLoading(siteSettingsLoading);
}
}, [siteSettingsData]);
}, [siteSettingsData, siteSettingsLoading]);

useEffect(() => {
setData(tableData.map((row, index) => ({ tableID: index, ...row })));
Expand Down
22 changes: 19 additions & 3 deletions frontend/src/components/Form/FormGroupMultiSelect.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,45 @@ export default function FormGroupMultiSelect({
field = "field",
filterKey,
store,
loading = false,
}) {
const isDisabled = loading;

const displayOptions = loading
? [
{
label: "Loading…",
value: "__loading__",
isDisabled: true,
},
]
: options;

return (
<FormGroup className="mt-2">
{noLabel ? null : (
<FormLabel>
<FormattedMessage id={label} defaultMessage={label} />
</FormLabel>
)}

{noDesc ? null : (
<Description>
<FormattedMessage id={`${label}_DESC`} />
</Description>
)}

<MultiSelect
options={options}
options={displayOptions}
isMulti={isMulti}
term={term}
field={field}

filterKey={filterKey}
store={store}
></MultiSelect>
disabled={isDisabled}
placeholder={loading ? "Loading…" : undefined}
noOptionsMessage={() => (loading ? "Loading…" : "No options")}
/>
</FormGroup>
);
}
13 changes: 13 additions & 0 deletions frontend/src/components/SmallSpinner.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import { Spinner } from "react-bootstrap";

const SmallSpinner = () => (
<Spinner
animation="border"
size="sm"
role="status"
aria-label="loading"
style={{ width: 16, height: 16 }}
/>
);
export default SmallSpinner;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import FormGroupMultiSelect from "../Form/FormGroupMultiSelect";
import BioMeasurements from "../Form/BioMeasurements";
import { useIntl } from "react-intl";
import { observer } from "mobx-react-lite";
import ContainerWithSpinner from "../ContainerWithSpinner";

const BiologicalSamplesAndAnalysesFilter = ({ data, store }) => {
const intl = useIntl();
Expand Down Expand Up @@ -266,30 +267,34 @@ const BiologicalSamplesAndAnalysesFilter = ({ data, store }) => {
filterKey={"Biological Sample ID"}
store={store}
/>
<FormGroupMultiSelect
isMulti={true}
noDesc={true}
label="FILTER_HAPLO_TYPE"
options={haploTypeOptions || []}
field={"haplotype"}
filterId={"haplotype"}
term={"terms"}
filterKey={"Haplotype"}
store={store}
/>

<FormGroupMultiSelect
isMulti={true}
noDesc={true}
label="FILTER_GENETIC_SEX"
options={geneticSexOptions || []}
field={"geneticSex"}
term={"terms"}
filterId={"geneticSex"}
filterKey={"Genetic Sex"}
store={store}
/>

<ContainerWithSpinner loading={store.siteSettingsLoading}>
<FormGroupMultiSelect
isMulti={true}
noDesc={true}
label="FILTER_HAPLO_TYPE"
options={haploTypeOptions || []}
field={"haplotype"}
filterId={"haplotype"}
term={"terms"}
filterKey={"Haplotype"}
store={store}
loading={store.siteSettingsLoading}
/>
</ContainerWithSpinner>
<ContainerWithSpinner loading={store.siteSettingsLoading}>
<FormGroupMultiSelect
isMulti={true}
noDesc={true}
label="FILTER_GENETIC_SEX"
options={geneticSexOptions || []}
field={"geneticSex"}
term={"terms"}
filterId={"geneticSex"}
filterKey={"Genetic Sex"}
store={store}
loading={store.siteSettingsLoading}
/>
</ContainerWithSpinner>
<BioMeasurements
data={bioMeasurementOptions}
filterId={"biologicalMeasurements"}
Expand Down
26 changes: 14 additions & 12 deletions frontend/src/components/filterFields/DateFilter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { FormLabel, FormGroup } from "react-bootstrap";
import { observer } from "mobx-react-lite";
import { DatePicker } from "antd";
import dayjs from "dayjs";
import ContainerWithSpinner from "../ContainerWithSpinner";

const FMT = "YYYY-MM-DD";
const toDayjs = (s) => (s ? dayjs(s) : null);
Expand Down Expand Up @@ -143,18 +144,19 @@ const DateFilter = observer(({ data, store }) => {
</FormGroup>
</div>
</>

<FormGroupMultiSelect
isMulti={true}
noDesc
label="FILTER_VERBATIM_EVENT_DATE"
options={verbatimeventdateOptions}
term="terms"
field="verbatimEventDate"
filterKey="Verbatim Event Date"
store={store}
/>

<ContainerWithSpinner loading={store.siteSettingsLoading}>
<FormGroupMultiSelect
isMulti={true}
noDesc
label="FILTER_VERBATIM_EVENT_DATE"
options={verbatimeventdateOptions}
term="terms"
field="verbatimEventDate"
filterKey="Verbatim Event Date"
store={store}
loading={store.siteSettingsLoading}
/>
</ContainerWithSpinner>
<>
<FormLabel className="mt-3">
<FormattedMessage id="FILTER_ENCOUNTER_SUBMISSION_DATE" />
Expand Down
102 changes: 58 additions & 44 deletions frontend/src/components/filterFields/ImageLabelFilter.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from "react";
import React from "react";
import { FormattedMessage } from "react-intl";
import Form from "react-bootstrap/Form";
import FormGroupMultiSelect from "../Form/FormGroupMultiSelect";
import Description from "../Form/Description";
import AndSelector from "../AndSelector";
import LabelledKeywordFilter from "../Form/LabelledKeywordFilter";
import { observer } from "mobx-react-lite";
import ContainerWithSpinner from "../ContainerWithSpinner";

const ImageLabelFilter = observer(({ data, store }) => {
const keywordsOptions =
Expand Down Expand Up @@ -38,13 +39,17 @@ const ImageLabelFilter = observer(({ data, store }) => {

const [isChecked_keyword, setIsChecked_keyword] = React.useState(false);

const keywordsFormValue = store.formFilters?.find(
(filter) => filter.filterId.includes("mediaAssetKeywords"))?.query?.term;
const keywordsANDChecked = keywordsFormValue && ("mediaAssetKeywords" in keywordsFormValue) ? true : isChecked_keyword;
const formValues = store.formFilters.filter(item => item.filterId.includes("mediaAssetKeywords"));
const value = formValues?.map(item => item.query?.term?.mediaAssetKeywords);


const keywordsFormValue = store.formFilters?.find((filter) =>
filter.filterId.includes("mediaAssetKeywords"),
)?.query?.term;
const keywordsANDChecked =
keywordsFormValue && "mediaAssetKeywords" in keywordsFormValue
? true
: isChecked_keyword;
const formValues = store.formFilters.filter((item) =>
item.filterId.includes("mediaAssetKeywords"),
);
const value = formValues?.map((item) => item.query?.term?.mediaAssetKeywords);

return (
<div>
Expand All @@ -59,8 +64,11 @@ const ImageLabelFilter = observer(({ data, store }) => {
type="checkbox"
id="custom-checkbox"
label={label}
checked={store.formFilters?.find(
(filter) => filter.filterId === "numberMediaAssets")?.query?.range?.numberMediaAssets?.gte === 1}
checked={
store.formFilters?.find(
(filter) => filter.filterId === "numberMediaAssets",
)?.query?.range?.numberMediaAssets?.gte === 1
}
onChange={(e) => {
if (e.target.checked) {
console.log(1);
Expand All @@ -76,8 +84,7 @@ const ImageLabelFilter = observer(({ data, store }) => {
},
"Number Media Assets",
);
}
else {
} else {
store.removeFilter("numberMediaAssets");
}
}}
Expand Down Expand Up @@ -118,43 +125,50 @@ const ImageLabelFilter = observer(({ data, store }) => {
value={value}
/>
) : (
<ContainerWithSpinner loading={store.siteSettingsLoading}>
<FormGroupMultiSelect
isMulti={true}
noLabel={true}
label="FILTER_KEYWORDS"
options={keywordsOptions}
field="mediaAssetKeywords"
term="terms"
filterKey="Media Asset Keywords"
store={store}
loading={store.siteSettingsLoading}
/>
</ContainerWithSpinner>
)}

<LabelledKeywordFilter data={data} store={store} />
<ContainerWithSpinner loading={store.siteSettingsLoading}>
<FormGroupMultiSelect
isMulti={true}
noLabel={true}
label="FILTER_KEYWORDS"
options={keywordsOptions}
field="mediaAssetKeywords"
label="FILTER_VIEWPOINT"
noDesc={true}
options={viewPointOptions}
filterId="annotationViewpoints"
term="terms"
filterKey="Media Asset Keywords"
field={"annotationViewpoints"}
filterKey={"View Point"}
store={store}
loading={store.siteSettingsLoading}
/>
)}

<LabelledKeywordFilter data={data} store={store} />

<FormGroupMultiSelect
isMulti={true}
label="FILTER_VIEWPOINT"
noDesc={true}
options={viewPointOptions}
filterId="annotationViewpoints"
term="terms"
field={"annotationViewpoints"}
filterKey={"View Point"}
store={store}
/>

<FormGroupMultiSelect
isMulti={true}
label="FILTER_IA_CLASS"
noDesc={true}
options={iaClassOptions}
filterId="annotationIAClasses"
field={"annotationIAClasses"}
term="terms"
filterKey={"IA Class"}
store={store}
/>
</ContainerWithSpinner>
<ContainerWithSpinner loading={store.siteSettingsLoading}>
<FormGroupMultiSelect
isMulti={true}
label="FILTER_IA_CLASS"
noDesc={true}
options={iaClassOptions}
filterId="annotationIAClasses"
field={"annotationIAClasses"}
term="terms"
filterKey={"IA Class"}
store={store}
loading={store.siteSettingsLoading}
/>
</ContainerWithSpinner>
</div>
);
});
Expand Down
Loading
Loading