Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
shemy-gan committed Aug 4, 2021
2 parents 6fde866 + 69a7bc4 commit ad72d1a
Show file tree
Hide file tree
Showing 22 changed files with 682 additions and 108 deletions.
2 changes: 1 addition & 1 deletion packages/common-ui/lib/formik-connected/SubmitButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const SubmitButton = connect<SubmitButtonProps>(
<button
{...buttonPropsObj}
className={`btn ${className} ${hidePrimaryClass ? "" : "btn-primary"}`}
style={{ ...buttonPropsObj.style, width: "10rem" }}
style={{ width: "10rem", ...buttonPropsObj.style }}
type="submit"
>
{children || <CommonMessage id="submitBtnText" />}
Expand Down
1 change: 1 addition & 0 deletions packages/common-ui/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ export * from "./formik-connected/TextFieldWithRemoveButton";
export * from "./formik-connected/CheckBoxWithoutWrapper";
export * from "./formik-connected/NumberSpinnerField";
export * from "./formik-connected/SelectFieldWithNav";
export * from "./text-field-with-multiplication-button/TextFieldWithMultiplicationButton";
3 changes: 3 additions & 0 deletions packages/common-ui/lib/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ export function ModalProvider({ appElement, children }: ModalProviderProps) {
className="Modal__Bootstrap modal-dialog"
// Make sure the modal is in front of the Bootstrap nav bar:
style={{ overlay: { zIndex: 1040 } }}
// Not sure why WCAG error occurs since title of window does exist
// General text added but better to pass in title of window
contentLabel={"Popup dialog window"}
>
{modals.length && (
<style>{`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { ChangeEvent, InputHTMLAttributes, useRef } from "react";
import { TextField, TextFieldProps } from "../formik-connected/TextField";

/**
* Shows buttons for degree, minute and second entry.
*/
export function TextFieldWithMultiplicationButton(props: TextFieldProps) {
return (
<TextField
{...props}
customInput={inputProps => (
<InputWithMultiplicationButton {...inputProps} />
)}
/>
);
}

export function InputWithMultiplicationButton({
...inputProps
}: InputHTMLAttributes<any>) {
const inputRef = useRef<HTMLInputElement>(null);

function insertSymbol(symbol: string) {
const input = inputRef.current;
if (input) {
const text = String(inputProps.value ?? "");
const cursor = input.selectionStart ?? text.length;

const newValue = `${text.slice(0, cursor)}${symbol}${text.slice(cursor)}`;

inputProps.onChange?.({
target: { value: newValue }
} as ChangeEvent<HTMLInputElement>);

setImmediate(() => {
input.focus();
input.selectionStart = cursor + 1;
});
}
}

const symbolToAdd = "×";

return (
<div className="input-group">
<input type="text" {...inputProps} ref={inputRef} />
<button
key={symbolToAdd}
tabIndex={-1}
className={"btn btn-info multiplication-button"}
type="button"
style={{ width: "3rem" }}
onClick={() => insertSymbol(symbolToAdd)}
>
{symbolToAdd}
</button>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DinaForm } from "../../formik-connected/DinaForm";
import { mountWithAppContext } from "../../test-util/mock-app-context";
import { TextFieldWithMultiplicationButton } from "../TextFieldWithMultiplicationButton";

describe("TextFieldWithMultiplicationButton component", () => {
it("appends the symbol at the end.", async () => {
const wrapper = mountWithAppContext(
<DinaForm initialValues={{}}>
<TextFieldWithMultiplicationButton name="myField" />
</DinaForm>
);
wrapper.find("input").simulate("change", { target: { value: "species1" } });
wrapper.find("button.multiplication-button").at(0).simulate("click");
wrapper.update();
expect(wrapper.find("input").prop("value")).toEqual("species1×");
});
});
175 changes: 175 additions & 0 deletions packages/dina-ui/components/collection/DeterminationField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import {
AutoSuggestTextField,
DateField,
FieldSet,
TextField,
TextFieldWithMultiplicationButton,
useDinaFormContext,
FormikButton
} from "common-ui";
import { DinaMessage, useDinaIntl } from "../../intl/dina-ui-intl";
import { FieldArray } from "formik";
import { Determination } from "packages/dina-ui/types/collection-api/resources/Determination";
import { Tab, TabList, TabPanel, Tabs } from "react-tabs";
import { MaterialSample } from "packages/dina-ui/types/collection-api";
import { useState } from "react";
import { clamp } from "lodash";
export interface DeterminationFieldProps {
className?: string;
namePrefix?: string;
}

export const DETERMINATION_FIELDS = [
"verbatimScientificName",
"verbatimAgent",
"verbatimDate",
"typeStatus",
"typeStatusEvidence",
"determiner",
"determinedOn",
"qualifier",
"scientificNameSource",
"scientificName"
] as const;

export function DeterminationField({
className,
namePrefix = ""
}: DeterminationFieldProps) {
const [activeTabIdx, setActiveTabIdx] = useState(0);
const { readOnly, isTemplate } = useDinaFormContext();
const determinationsPath = "determination";
return (
<FieldSet
className={className}
id="determination-section"
legend={<DinaMessage id="determination" />}
>
<FieldArray name="determination">
{({ form, push, remove }) => {
const determinations =
(form.values.determination as Determination[]) ?? [];
function addDetermination() {
push({});
setActiveTabIdx(determinations.length);
}

function removeDetermination(index: number) {
remove(index);
setActiveTabIdx(current =>
clamp(current, 0, determinations.length - 2)
);
}

const determinationInternal = (index, commonRoot) => (
<TabPanel key={index}>
<div className="row">
<div className="col-md-6">
<TextFieldWithMultiplicationButton
name={`${namePrefix}${commonRoot}verbatimScientificName`}
customName="verbatimScientificName"
className="col-sm-6 verbatimScientificName"
/>
<AutoSuggestTextField<MaterialSample>
name={`${namePrefix}${commonRoot}verbatimAgent`}
customName="verbatimAgent"
className="col-sm-6"
query={() => ({
path: "collection-api/material-sample"
})}
suggestion={sample =>
(sample.determination?.map(
det => det?.verbatimAgent
) as any) ?? []
}
/>
<DateField
name={`${namePrefix}${commonRoot}verbatimDate`}
customName="verbatimDate"
className="col-sm-6"
/>
<TextField
name={`${namePrefix}${commonRoot}verbatimRemarks`}
customName="vebatimRemarks"
multiLines={true}
/>
</div>
<div className="col-md-6">
<TextField
name={`${namePrefix}${commonRoot}typeStatus`}
customName="typeStatus"
multiLines={true}
/>
<TextField
name={`${namePrefix}${commonRoot}typeStatusEvidence`}
customName="typeStatusEvidence"
multiLines={true}
/>
<TextField
name={`${namePrefix}${commonRoot}qualifier`}
customName="qualifier"
multiLines={true}
/>
</div>
{!readOnly && !isTemplate && (
<div className="list-inline mb-3">
<FormikButton
className="list-inline-item btn btn-primary add-assertion-button"
onClick={addDetermination}
>
<DinaMessage id="addAnotherDetermination" />
</FormikButton>
<FormikButton
className="list-inline-item btn btn-dark"
onClick={() => removeDetermination(index)}
>
<DinaMessage id="removeDeterminationLabel" />
</FormikButton>
</div>
)}
</div>
</TabPanel>
);
// Always shows the panel without tabs when it is a template
return (
<div className="determination-section">
<Tabs selectedIndex={activeTabIdx} onSelect={setActiveTabIdx}>
{isTemplate ? null : (
// Only show the tabs when there is more than 1 assertion:
<TabList
className={`react-tabs__tab-list ${
determinations.length === 1 ? "d-none" : ""
}`}
>
{determinations.map((_, index) => (
<Tab key={index}>
<span className="m-3">{index + 1}</span>
</Tab>
))}
</TabList>
)}
{isTemplate
? determinationInternal(0, `${determinationsPath}[${0}].`)
: determinations.length
? determinations.map((_, index) => {
const determinationPath = `${determinationsPath}[${index}]`;
const commonRoot = determinationPath + ".";
return determinationInternal(index, commonRoot);
})
: null}
</Tabs>
{!readOnly && !isTemplate && !determinations?.length && (
<FormikButton
className="list-inline-item btn btn-primary add-assertion-button"
onClick={addDetermination}
>
<DinaMessage id="addDetermination" />
</FormikButton>
)}
</div>
);
}}
</FieldArray>
</FieldSet>
);
}
Loading

0 comments on commit ad72d1a

Please sign in to comment.