Skip to content

Commit

Permalink
tweaks'
Browse files Browse the repository at this point in the history
  • Loading branch information
nleroy917 committed Jul 25, 2024
1 parent dc7e53a commit 698ebcc
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 42 deletions.
2 changes: 1 addition & 1 deletion pephub/routers/api/v1/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ async def create_view_of_the_project(
_LOGGER.error(f"Could not create view. Error: {e}")
raise HTTPException(
status_code=409,
detail="Could not create view",
detail="This view already exists in the project.",
)
return JSONResponse(
content={
Expand Down
50 changes: 32 additions & 18 deletions web/src/components/modals/add-view-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ export const ViewOptionsModal = (props: Props) => {
noFail: false,
};

viewMutations.addViewMutation.mutate(createViewRequest);
viewMutations.addViewMutation.mutate(createViewRequest, {
onSuccess: () => {
onHide();
},
});

resetForm({}, { keepValues: false });
};
Expand All @@ -95,13 +99,13 @@ export const ViewOptionsModal = (props: Props) => {
{filteredSamples ? (
<div className="">
<h6 className="mb-1">Save View</h6>
<p className="mb-3 text-xs">
<p className="mb-3">
Save the current filtered sample table state as a view by providing a name (required) and description
(optional) for the view.
</p>
<form>
<div className="input-group mb-2">
<span className="input-group-text text-xs">Name</span>
<span className="input-group-text">Name</span>
<input
{...register('name', {
required: {
Expand All @@ -113,46 +117,52 @@ export const ViewOptionsModal = (props: Props) => {
message: "View Name must contain only alphanumeric characters, '-', or '_'.",
},
})}
placeholder="..."
type="text"
className="form-control text-xs"
className="form-control"
id="view-name"
aria-describedby="view-name-help"
/>
</div>
<div className="input-group">
<span className="input-group-text text-xs">Description</span>
<input
<div className="mt-1">
<label htmlFor="view-description" className="form-label fw-bold">
Description
</label>
<textarea
{...register('description')}
placeholder="..."
type="text"
className="form-control text-xs"
className="form-control"
id="view-description"
aria-describedby="view-description-help"
/>
</div>
<ErrorMessage
errors={errors}
name="name"
render={({ message }) => (message ? <p className="text-danger text-xs pt-1 mb-0">{message}</p> : null)}
render={({ message }) => (message ? <p className="text-danger pt-1 mb-0">{message}</p> : null)}
/>
<button
disabled={!isValid || !!errors.name?.message}
disabled={
filteredSamples.length === 0 ||
!isValid ||
!!errors.name?.message ||
viewMutations.addViewMutation.isPending
}
type="button"
className="btn btn-success px-2 mt-3 text-xs"
className="btn btn-success px-2 mt-3"
onClick={() => {
onSubmit();
resetForm();
}}
>
<i className="bi bi-plus-lg"></i> Save New View
<i className="bi bi-plus-circle me-1"></i>
{viewMutations.addViewMutation.isPending ? 'Creating...' : 'Create'}
</button>
</form>
<hr />
</div>
) : null}
<div className="">
<h6 className="mb-1">Remove View</h6>
<p className="mb-3 text-xs">Remove an existing view by selecting it from the dropdown menu.</p>
<p className="mb-3">Remove an existing view by selecting it from the dropdown menu.</p>
<ReactSelect
styles={{
control: (provided) => ({
Expand Down Expand Up @@ -198,8 +208,12 @@ export const ViewOptionsModal = (props: Props) => {
}
}
/>
<button disabled={deleteState} onClick={handleDeleteView} className="btn btn-danger px-2 mt-3 text-xs">
<i className="bi bi-trash"></i> Remove View
<button
disabled={deleteState || viewMutations.removeViewMutation.isPending || selectedViewDelete === null}
onClick={handleDeleteView}
className="btn btn-danger px-2 mt-3"
>
<i className="bi bi-trash"></i> {viewMutations.removeViewMutation.isPending ? 'Removing...' : 'Remove'}
</button>
</div>
</Modal.Body>
Expand Down
25 changes: 23 additions & 2 deletions web/src/components/project/project-interface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import { useProjectConfig } from '../../hooks/queries/useProjectConfig';
import { useProjectHistory } from '../../hooks/queries/useProjectHistory';
import { useSampleTable } from '../../hooks/queries/useSampleTable';
import { useSubsampleTable } from '../../hooks/queries/useSubsampleTable';
import { useView } from '../../hooks/queries/useView';
import { useCurrentHistoryId } from '../../hooks/stores/useCurrentHistoryId';
import { useProjectPageView } from '../../hooks/stores/useProjectPageView';
import { useProjectSelectedView } from '../../hooks/stores/useProjectSelectedViewStore';
import { getOS } from '../../utils/etc';
import { canEdit } from '../../utils/permissions';
import { arraysToSampleList, sampleListToArrays } from '../../utils/sample-table';
Expand Down Expand Up @@ -52,8 +54,21 @@ export const ProjectInterface = (props: Props) => {
const { data: historyData } = useProjectHistory(namespace, projectName, tag, currentHistoryId);

// fetch the page view (samples, subsamples, config)
// this is not the DATA view, which is a separate idea
const { pageView, setPageView } = useProjectPageView();

// the is the DATA view, i.e. a slice of the sample table
const { view } = useProjectSelectedView();

const { data: viewData } = useView({
namespace,
project: projectName,
tag,
view,
enabled: !!view,
});
const viewSamples = viewData?._samples || [];

// form to store project updated fields temporarily
// on the client before submitting to the server
const projectUpdates = useForm<ProjectUpdateFields>({
Expand Down Expand Up @@ -191,8 +206,14 @@ export const ProjectInterface = (props: Props) => {
onChange={(samples) => {
onChange(samples);
}}
readOnly={!userCanEdit}
data={currentHistoryId ? sampleListToArrays(historyData?._sample_dict || []) : newSamples}
readOnly={!userCanEdit || view !== undefined}
data={
view !== undefined
? sampleListToArrays(viewSamples)
: currentHistoryId
? sampleListToArrays(historyData?._sample_dict || [])
: newSamples
}
height={window.innerHeight - 15 - (projectDataRef.current?.offsetTop || 300)}
setFilteredSamples={(samples) => setFilteredSamples(samples)}
sampleTableIndex={sampleTableIndex}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { useValidation } from '../../hooks/queries/useValidation';
import { canEdit } from '../../utils/permissions';
import { StatusIcon } from '../badges/status-icons';
import { ProjectDataNav } from '../layout/project-data-nav';
import { ValidationTooltip } from '../tooltips/validation-tooltip';
import { ValidationResult } from './validation/validation-result';

type ProjectValidationAndEditButtonsProps = {
Expand Down Expand Up @@ -55,12 +54,13 @@ export const ProjectValidationAndEditButtons = (props: ProjectValidationAndEditB
<>
<OverlayTrigger
overlay={
<Tooltip id="validation" style={{position:"fixed"}}>
As you edit your project below, it will be validated against the schema currently selected for it.
<Tooltip id="validation" style={{ position: 'fixed' }}>
As you edit your project below, it will be validated against the schema currently selected for
it.
</Tooltip>
}
delay={{ show: 250, hide: 500 }}
trigger={["hover"]}
trigger={['hover']}
>
<div className="d-flex align-items-center">
<StatusIcon className="text-2xl" variant="warning" />
Expand Down
5 changes: 5 additions & 0 deletions web/src/components/project/view-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export const ViewSelector = (props: ViewSelectorProps) => {
const [searchParams, setSearchParams] = useSearchParams();

const { namespace, projectName, tag } = useProjectPage();

// this is the DATA view, i.e. a slice of the sample table
// to inprove performance and usability
// this is NOT the PAGE view, which is
// which tab the user is currently viewing (a separate idea)
const { view, setView } = useProjectSelectedView();

const projectViewsQuery = useProjectViews(namespace, projectName, tag);
Expand Down
33 changes: 16 additions & 17 deletions web/src/components/tables/sample-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,30 +57,29 @@ export const SampleTable = (props: Props) => {
const numColumns = data.length > 0 ? data[0].length : 0;

const ph_id_col = data[0].indexOf('ph_id');
let sampleTableIndexCol = 0;
if (sampleTableIndex) {
sampleTableIndexCol = data[0].indexOf(sampleTableIndex);
}

return (
<HotTable
afterFilter={(k) => {
if (!setFilteredSamples) {
return;
}
setFilteredSamples(
//@ts-ignore this is way too complex to type right now
k.length > 0
? hotRef.current?.hotInstance
?.getData()
.map(
(subArray) =>
subArray[
hotRef.current?.hotInstance
?.getData()[0]
.findIndex((x: any) => x == (sampleTableIndex ? sampleTableIndex : 'sample_name'))
],
)
.filter((element) => element != null)
.slice(1)
: null,
);

// if there are filters applied, then filter the samples
if (k.length > 0) {
const hotdata = hotRef.current?.hotInstance?.getData() || [];
const filteredSamples = hotdata
.map((subArray) => subArray[sampleTableIndexCol])
.filter((element) => element != null);
setFilteredSamples(filteredSamples);
// if there are no filters applied, then set the filtered samples to an empty array
} else {
setFilteredSamples([]);
}
}}
ref={hotRef}
data={data}
Expand Down

0 comments on commit 698ebcc

Please sign in to comment.