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

Displaying identifiers for project drop downs #1352

Merged
merged 21 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* [REST]: Updated synchronizing of sample data to remove sequencing objects and assemblies that no longer exist on the remote sample. See [PR 1345](https://github.com/phac-nml/irida/pull/1345)
* [UI]: Fixed issue with filtering samples by files using a windows encoded text file causing sample name truncation. See [PR 1346](https://github.com/phac-nml/irida/pull/1346)
* [Developer]: Fixed deleting a project with project subscriptions. See [PR 1348](https://github.com/phac-nml/irida/pull/1348)
* [Developer]: Add identifier to project drop-downs. See [PR 1352](https://github.com/phac-nml/irida/pull/1352)

## [22.05.5] - 2022/06/28
* [UI]: Fixed bug preventing export of project samples table due to invalid url. [PR 1331](https://github.com/phac-nml/irida/pull/1331)
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,9 @@ project.nav.details=Recent Activity
project.nav.settings=Settings
project.nav.samples.import-metadata=Import Sample Metadata

# Project select
ProjectSelect.label.id=id: {0}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try using uppercase on the ID, I think it might look better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see ca4b83f.


# KEPT FOR LEGACY PURPOSES (still used on user_details.html and groups.html)
project.table.collaborator.name=Name
project.table.collaborator.role=Project Role
Expand Down
78 changes: 78 additions & 0 deletions src/main/webapp/resources/js/components/project/ProjectSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from "react";
import { Select, SelectProps, Tag, Typography } from "antd";

export type Project = { identifier: number; name: string };
joshsadam marked this conversation as resolved.
Show resolved Hide resolved

export interface ProjectSelectProps extends SelectProps {
projects: Project[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to describe all you parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reached out about this comment. Instructed to disregard.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I though you had decided to go with ProjectMinimal here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see 76ba866.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After generalising the component, I think picking id and name form IridaBase makes the most sense now. Please see 9942971.

}

/**
* React component for displaying a project drop-down menu.
* @param {list} projects - list of projects that is to be displayed
* @param {function} onChange - function that is called when select option has changed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using TypeScript you do not need to add the type also to the JSDoc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see 76ae170.

* @param {number} defaultValue - project identifier of the project that is to be displayed by default
* @returns {JSX.Element}
* @constructor
*/
export function ProjectSelect({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder we could generalize this to be a select for anything that has an id?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so... I just need a good name. Please see d19ce2b.

projects,
onChange = undefined,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt you want the onChange to ever be undefined

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see 8023bed.

defaultValue = null,
}: ProjectSelectProps): JSX.Element {
const [options, setOptions] = React.useState(() => formatOptions(projects));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to state what type the options are. I think the best way that I have come across is:

const [options, setOptions] = React.useState<SelectOptions[]>(()=>formatOptions(projects));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see 7bfbc4e.


function formatOptions(values: Project[]) {
if (!values) return [];
return values.map((project) => ({
label: (
<div
style={{
display: "flex",
justifyContent: "space-between",
width: "100%",
}}
>
<Typography.Text ellipsis={{ tooltip: true }}>
{project.name}
</Typography.Text>
<Tag>{i18n("ProjectSelect.label.id", project.identifier)}</Tag>
</div>
),
value: project.identifier,
selected: project.name,
}));
}

React.useEffect(() => {
setOptions(formatOptions(projects));
}, [projects]);

const handleSearch = (value: string) => {
const lowerValue = value.toLowerCase();

const available = projects.filter(
(project) =>
project.name.toLowerCase().includes(lowerValue) ||
project.identifier.toString() === value
);
const formatted = formatOptions(available);
setOptions(formatted);
};

return (
<Select
optionLabelProp="selected"
autoFocus
showSearch
size="large"
style={{ width: `100%` }}
options={options}
className="t-project-select"
filterOption={false}
onSearch={handleSearch}
onChange={onChange}
defaultValue={defaultValue}
/>
);
}
45 changes: 6 additions & 39 deletions src/main/webapp/resources/js/pages/projects/share/ShareProject.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Select, Space, Typography } from "antd";
import { Space, Typography } from "antd";
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { ProjectSelect } from "../../../components/project/ProjectSelect";
import { setProject } from "./shareSlice";
import { useDispatch, useSelector } from "react-redux";

/**
* React component for selecting the project to share a sample with.
Expand All @@ -12,33 +13,6 @@ import { setProject } from "./shareSlice";
export function ShareProject({ projects }) {
const dispatch = useDispatch();
const { targetProject } = useSelector((state) => state.shareReducer);
const [options, setOptions] = React.useState(() => formatOptions(projects));

function formatOptions(values) {
if (!values) return [];
return values.map((project) => ({
label: project.name,
value: project.identifier,
}));
}

React.useEffect(() => {
setOptions(
projects.map((project) => ({
label: project.name,
value: project.identifier,
}))
);
}, [projects]);

const handleSearch = (value) => {
const lowerValue = value.toLowerCase();
const available = projects.filter((project) =>
project.name.toLowerCase().includes(lowerValue)
);
const formatted = formatOptions(available);
setOptions(formatted);
};

function onChange(projectId) {
const project = projects.find((p) => p.identifier === projectId);
Expand All @@ -50,17 +24,10 @@ export function ShareProject({ projects }) {
<Typography.Title level={5}>
{i18n("ShareSamples.projects")}
</Typography.Title>
<Select
autoFocus
showSearch
size="large"
style={{ width: `100%` }}
options={options}
className="t-share-project"
filterOption={false}
onSearch={handleSearch}
<ProjectSelect
projects={projects}
onChange={onChange}
defaultValue={targetProject ? targetProject.identifier : null}
defaultValue={targetProject?.identifier}
/>
</Space>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import static ca.corefacility.bioinformatics.irida.ria.integration.pages.AbstractPage.waitForTime;

public class ShareSamplesPage {
@FindBy(css = ".t-share-project .ant-select-selection-search-input")
@FindBy(css = ".t-project-select .ant-select-selection-search-input")
private WebElement shareProjectSelect;

@FindBy(className = "ant-select-dropdown")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add testing for searching for a project by it's identifier please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see 3aa96c6.

Expand Down Expand Up @@ -147,15 +147,15 @@ public boolean isShareSingleSuccessDisplayed() {
public boolean isSomeSamplesSameIdsWarningDisplayed() {
try {
return someSamplesSameIdsWarning.isDisplayed();
} catch(Exception e) {
} catch (Exception e) {
return false;
}
}

public boolean isSomeSamplesSameNamesWarningDisplayed() {
try {
return someSamplesSameNamesWarning.isDisplayed();
} catch(Exception e) {
} catch (Exception e) {
return false;
}
}
Expand Down