Skip to content

Commit

Permalink
[MDS-4865] Add & Delete Project Relationships (#2853)
Browse files Browse the repository at this point in the history
* convert some of the important files to typescript and remove extraneous props

* add system flag, put in common folder

* webpack: fix redux issue on MS. Otherwise, just bringing stuff into the common package

* change reduxy files to ts, add actions, reducers, etc, for project links. Also added in system flag

* add 'create many' for project links on BE, give a unique name, tweak URL pattern a bit

* move columns to belong with table, make component be able to display form on form pages and only table otherwise

* some validation should be added, but adding project links now works FE - BE

* get project links working on MS again, delete functionality, deal with another webpack issue

* fix 2 FE bugs: loading project on project form page, and added null check to major project table

* updated some tests. Changes to TS to better resolve issues. Added missing values, adjusted to changes in code, etc. Skipped the ProjectLinks one because it can't find redux

* remove unused things

* fix diff

* test pass?

* fix css issue.

---------

Co-authored-by: Henry Oforeh <[email protected]>
  • Loading branch information
taraepp and henryoforeh-dev authored Dec 18, 2023
1 parent 66fcd54 commit 675b56c
Show file tree
Hide file tree
Showing 81 changed files with 4,367 additions and 1,812 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,6 @@ module.exports = {
"@typescript-eslint/default-param-last": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-children-prop": 0,
"@typescript-eslint/lines-between-class-members": 0,
},
};
79 changes: 79 additions & 0 deletions services/common/src/components/forms/RenderAutoComplete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from "react";
import PropTypes from "prop-types";
import { Form } from "@ant-design/compatible";
import "@ant-design/compatible/assets/index.css";
import { Select } from "antd";

/**
* @constant RenderAutoComplete - Ant Design `AutoComplete` component for redux-form.
*
*/

const propTypes = {
handleChange: PropTypes.func.isRequired,
handleSelect: PropTypes.func.isRequired,
data: PropTypes.arrayOf(PropTypes.any).isRequired,
placeholder: PropTypes.string,
disabled: PropTypes.bool,
meta: PropTypes.objectOf(PropTypes.any),
input: PropTypes.objectOf(PropTypes.any),
selected: PropTypes.objectOf(PropTypes.any),
};

const defaultProps = {
placeholder: "",
disabled: false,
meta: {},
input: null,
selected: undefined,
};

const RenderAutoComplete = (props) => {
return (
<Form.Item
label={JSON.stringify(props.selected)}
validateStatus={
props.meta.touched ? (props.meta.error && "error") || (props.meta.warning && "warning") : ""
}
help={
props.meta.touched &&
((props.meta.error && <span>{props.meta.error}</span>) ||
(props.meta.warning && <span>{props.meta.warning}</span>))
}
>
<Select
showSearch
virtual={false}
defaultActiveFirstOption={false}
notFoundContent="Not Found"
allowClear
dropdownMatchSelectWidth
defaultValue={props.input ? props.input.value : undefined}
value={props.input ? props.input.value : undefined}
style={{ width: "100%" }}
options={props.data}
placeholder={props.placeholder}
filterOption={(input, option) =>
option.label
.toString()
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
}
disabled={props.disabled}
onChange={props.input ? props.input.onChange : undefined}
onSelect={props.handleSelect}
onSearch={(event) => {
props.handleChange(event);
if (props.input) {
props.input.onChange(event);
}
}}
/>
</Form.Item>
);
};

RenderAutoComplete.propTypes = propTypes;
RenderAutoComplete.defaultProps = defaultProps;

export default RenderAutoComplete;
86 changes: 86 additions & 0 deletions services/common/src/components/forms/RenderAutoSizeField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import { Form } from "@ant-design/compatible";
import "@ant-design/compatible/assets/index.css";
import { Input } from "antd";

/**
* @constant RenderAutoSizeField - Ant Design `Input` autosize component for redux-form. (useful for notes/description)
*/

const propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
input: PropTypes.objectOf(PropTypes.any).isRequired,
label: PropTypes.string,
placeholder: PropTypes.string,
meta: PropTypes.objectOf(PropTypes.any).isRequired,
disabled: PropTypes.bool,
minRows: PropTypes.number,
maximumCharacters: PropTypes.number,
};

const defaultProps = {
placeholder: "",
label: "",
disabled: false,
minRows: 3,
maximumCharacters: 0,
};

const RenderAutoSizeField = (props) => {
const [remainingChars, setRemainingChars] = useState(props.maximumCharacters);
const [value, setValue] = useState(props.input?.value ?? "");

const handleTextAreaChange = (event) => {
setValue(event.target.value);
if (props.maximumCharacters > 0) {
const input = event.target.value;
const remaining = props.maximumCharacters - input.length;
setRemainingChars(remaining);
}
};

useEffect(() => {
if (props.input) {
const input = props.input.value;
const remaining = props.maximumCharacters - input.length;
setRemainingChars(remaining);
}
}, []);

return (
<Form.Item
label={props.label}
// placeholder={props.placeholder}
validateStatus={
props.meta.touched ? (props.meta.error && "error") || (props.meta.warning && "warning") : ""
}
help={
props.meta.touched &&
((props.meta.error && <span>{props.meta.error}</span>) ||
(props.meta.warning && <span>{props.meta.warning}</span>))
}
>
<Input.TextArea
disabled={props.disabled}
id={props.id}
{...props.input}
autoSize={{ minRows: props.minRows }}
placeholder={props.placeholder}
onChange={handleTextAreaChange}
value={value}
/>
{props.maximumCharacters > 0 && (
<div className="flex between">
<span>{`Maximum ${props.maximumCharacters} characters`}</span>
<span className="flex-end">{`${remainingChars} / ${props.maximumCharacters}`}</span>
</div>
)}
</Form.Item>
);
};

RenderAutoSizeField.propTypes = propTypes;
RenderAutoSizeField.defaultProps = defaultProps;

export default RenderAutoSizeField;
67 changes: 67 additions & 0 deletions services/common/src/components/forms/RenderCascader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import { Form } from "@ant-design/compatible";
import "@ant-design/compatible/assets/index.css";
import { Cascader } from "antd";

/**
* @constant RenderCascader - Ant Design `Cascader` component for redux-form.
*/

const propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
input: PropTypes.objectOf(PropTypes.any).isRequired,
placeholder: PropTypes.string.isRequired,
meta: PropTypes.objectOf(PropTypes.any).isRequired,
options: PropTypes.array.isRequired,
label: PropTypes.string,
changeOnSelect: PropTypes.bool,
};

const defaultProps = {
changeOnSelect: false,
label: "",
};

const RenderCascader = (props) => {
const [selectedValue, setSelectedValue] = useState(props.input.value || "");

const handleCascaderChange = (value) => {
props.input.onChange(value);
};

const handleCascaderOnChange = (value) => {
setSelectedValue(value);
};

return (
<Form.Item
label={props.label}
validateStatus={
props.meta.touched ? (props.meta.error && "error") || (props.meta.warning && "warning") : ""
}
help={
props.meta.touched &&
((props.meta.error && <span>{props.meta.error}</span>) ||
(props.meta.warning && <span>{props.meta.warning}</span>))
}
>
<Cascader
expandTrigger="hover"
id={props.id}
placeholder={props.placeholder}
options={props.options}
{...props.input}
changeOnSelect={props.changeOnSelect}
defaultValue={selectedValue}
value={handleCascaderChange(selectedValue)}
onChange={handleCascaderOnChange}
/>
</Form.Item>
);
};

RenderCascader.propTypes = propTypes;
RenderCascader.defaultProps = defaultProps;

export default RenderCascader;
40 changes: 40 additions & 0 deletions services/common/src/components/forms/RenderCheckbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import { Form } from "@ant-design/compatible";
import "@ant-design/compatible/assets/index.css";
import { Checkbox } from "antd";
/**
* @constant RenderCheckbox - Ant Design `Checkbox` component for redux-form.
*/

const propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
label: PropTypes.string.isRequired,
meta: PropTypes.objectOf(PropTypes.any).isRequired,
input: PropTypes.objectOf(PropTypes.string).isRequired,
disabled: PropTypes.bool.isRequired,
};

const RenderCheckbox = (props) => {
const [checked, setChecked] = useState(props.input.value || false);
const onChange = (e) => {
setChecked(e.target.checked);
};
return (
<Form.Item validateStatus={props.meta.touched ? props.meta.error && "error" : ""}>
<Checkbox
id={props.id}
{...props.input}
disabled={props.disabled}
checked={checked}
onChange={onChange}
>
{props.label}
</Checkbox>
</Form.Item>
);
};

RenderCheckbox.propTypes = propTypes;

export default RenderCheckbox;
57 changes: 57 additions & 0 deletions services/common/src/components/forms/RenderDate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from "react";
import PropTypes from "prop-types";
import moment from "moment";
import { Form } from "@ant-design/compatible";
import "@ant-design/compatible/assets/index.css";
import { DatePicker } from "antd";

/**
* @constant RenderDate - Ant Design `DatePicker` component for redux-form.
*/

const propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
input: PropTypes.objectOf(PropTypes.any).isRequired,
meta: PropTypes.objectOf(PropTypes.any).isRequired,
label: PropTypes.string,
placeholder: PropTypes.string,
disabled: PropTypes.bool,
showTime: PropTypes.bool,
};

const defaultProps = {
label: "",
placeholder: "",
disabled: false,
showTime: false,
};

const RenderDate = (props) => (
<Form.Item
label={props.label}
validateStatus={
props.meta.touched ? (props.meta.error && "error") || (props.meta.warning && "warning") : ""
}
help={
props.meta.touched &&
((props.meta.error && <span>{props.meta.error}</span>) ||
(props.meta.warning && <span>{props.meta.warning}</span>))
}
>
<DatePicker
disabled={props.disabled}
id={props.id}
{...props.input}
placeholder={props.placeholder}
onChange={(date, dateString) => props.input.onChange(dateString || null)}
value={props.input.value ? moment(props.input.value) : null}
showTime={props.showTime && { format: "HH:mm" }}
format={props.showTime && "YYYY-MM-DD HH:mm"}
/>
</Form.Item>
);

RenderDate.propTypes = propTypes;
RenderDate.defaultProps = defaultProps;

export default RenderDate;
Loading

0 comments on commit 675b56c

Please sign in to comment.