diff --git a/frontend/src/v5/services/api/drawings.ts b/frontend/src/v5/services/api/drawings.ts index 38f12a9485..eee3cba474 100644 --- a/frontend/src/v5/services/api/drawings.ts +++ b/frontend/src/v5/services/api/drawings.ts @@ -16,7 +16,7 @@ */ import { AxiosResponse } from 'axios'; -import { DrawingStats, MinimumDrawing } from '@/v5/store/drawings/drawings.types'; +import { DrawingSettings, DrawingStats, MinimumDrawing } from '@/v5/store/drawings/drawings.types'; import api from './default'; export const addFavourite = (teamspace, projectId, drawingId): Promise> => ( @@ -37,6 +37,11 @@ export const fetchDrawingsStats = async (teamspace, projectId, drawingId): Promi return data; }; +export const fetchDrawingSettings = async (teamspace, projectId, drawingId): Promise => { + const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/drawings/${drawingId}`); + return data; +}; + export const fetchTypes = async (teamspace, projectId): Promise> => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/settings/drawingCategories`); return data; diff --git a/frontend/src/v5/store/drawings/drawings.redux.ts b/frontend/src/v5/store/drawings/drawings.redux.ts index 3c6f58b7be..b3745392fc 100644 --- a/frontend/src/v5/store/drawings/drawings.redux.ts +++ b/frontend/src/v5/store/drawings/drawings.redux.ts @@ -29,6 +29,7 @@ export const { Types: DrawingsTypes, Creators: DrawingsActions } = createActions setFavouriteSuccess: ['projectId', 'drawingId', 'isFavourite'], fetchDrawings: ['teamspace', 'projectId'], fetchDrawingsSuccess: ['projectId', 'drawings'], + fetchDrawingSettings: ['teamspace', 'projectId', 'drawingId'], fetchDrawingStats: ['teamspace', 'projectId', 'drawingId'], fetchDrawingStatsSuccess: ['projectId', 'drawingId', 'stats'], fetchCalibration: ['teamspace', 'projectId', 'drawingId'], @@ -116,6 +117,7 @@ export type RemoveFavouriteAction = Action<'REMOVE_FAVOURITE'> & TeamspaceProjec export type SetFavouriteSuccessAction = Action<'SET_FAVOURITE_SUCCESS'> & ProjectAndDrawingId & { isFavourite: boolean }; export type FetchDrawingsAction = Action<'FETCH_DRAWINGS'> & TeamspaceAndProjectId; export type FetchDrawingsSuccessAction = Action<'FETCH_DRAWINGS_SUCCESS'> & ProjectId & { drawings: IDrawing[] }; +export type FetchDrawingSettingsAction = Action<'FETCH_DRAWING_SETTINGS'> & TeamspaceProjectAndDrawingId; export type FetchDrawingStatsAction = Action<'FETCH_DRAWING_STATS'> & TeamspaceProjectAndDrawingId; export type FetchDrawingStatsSuccessAction = Action<'FETCH_DRAWING_STATS_SUCCESS'> & ProjectAndDrawingId & { stats: DrawingStats }; export type FetchCalibrationAction = Action<'FETCH_CALIBRATION'> & TeamspaceProjectAndDrawingId; @@ -137,6 +139,7 @@ export interface IDrawingsActionCreators { setFavouriteSuccess: (projectId: string, drawingId: string, isFavourite: boolean) => SetFavouriteSuccessAction; fetchDrawings: (teamspace: string, projectId: string) => FetchDrawingsAction; fetchDrawingsSuccess: (projectId: string, drawings: Partial[]) => FetchDrawingsSuccessAction; + fetchDrawingSettings: (teamspace: string, projectId: string, drawingId: string) => FetchDrawingSettingsAction; fetchDrawingStats: (teamspace: string, projectId: string, drawingId: string) => FetchDrawingStatsAction; fetchDrawingStatsSuccess: (projectId: string, drawingId: string, stats: DrawingStats) => FetchDrawingStatsSuccessAction; fetchCalibration: (teamspace: string, projectId: string, drawingId: string) => FetchCalibrationAction; diff --git a/frontend/src/v5/store/drawings/drawings.sagas.ts b/frontend/src/v5/store/drawings/drawings.sagas.ts index 45d1f14612..c8c6dc7dc8 100644 --- a/frontend/src/v5/store/drawings/drawings.sagas.ts +++ b/frontend/src/v5/store/drawings/drawings.sagas.ts @@ -16,7 +16,7 @@ */ import { all, put, select, takeEvery, takeLatest } from 'redux-saga/effects'; -import { AddFavouriteAction, DeleteDrawingAction, RemoveFavouriteAction, CreateDrawingAction, DrawingsActions, DrawingsTypes, FetchTypesAction, FetchDrawingStatsAction, FetchDrawingsAction, UpdateDrawingAction, FetchCalibrationAction, UpdateCalibrationAction, ApproveCalibrationAction } from './drawings.redux'; +import { AddFavouriteAction, DeleteDrawingAction, RemoveFavouriteAction, CreateDrawingAction, DrawingsActions, DrawingsTypes, FetchTypesAction, FetchDrawingStatsAction, FetchDrawingsAction, UpdateDrawingAction, FetchCalibrationAction, UpdateCalibrationAction, ApproveCalibrationAction, FetchDrawingSettingsAction } from './drawings.redux'; import * as API from '@/v5/services/api'; import { formatMessage } from '@/v5/services/intl'; import { DialogsActions } from '../dialogs/dialogs.redux'; @@ -93,6 +93,18 @@ export function* fetchCalibration({ teamspace, projectId, drawingId }: FetchCali } } +export function* fetchDrawingSettings({ teamspace, projectId, drawingId }: FetchDrawingSettingsAction) { + try { + const data = yield API.Drawings.fetchDrawingSettings(teamspace, projectId, drawingId); + yield put(DrawingsActions.updateDrawingSuccess(projectId, drawingId, data)); + } catch (error) { + yield put(DialogsActions.open('alert', { + currentActions: formatMessage({ id: 'drawings.fetchSettings.error', defaultMessage: 'trying to fetch drawing settings' }), + error, + })); + } +} + export function* updateCalibration({ teamspace, projectId, drawingId, calibration }: UpdateCalibrationAction) { try { const revision = yield select(selectLatestActiveRevision, drawingId); @@ -188,6 +200,7 @@ export default function* DrawingsSaga() { yield takeLatest(DrawingsTypes.ADD_FAVOURITE, addFavourites); yield takeLatest(DrawingsTypes.REMOVE_FAVOURITE, removeFavourites); yield takeEvery(DrawingsTypes.FETCH_DRAWINGS, fetchDrawings); + yield takeEvery(DrawingsTypes.FETCH_DRAWING_SETTINGS, fetchDrawingSettings); yield takeEvery(DrawingsTypes.FETCH_DRAWING_STATS, fetchDrawingStats); yield takeEvery(DrawingsTypes.FETCH_CALIBRATION, fetchCalibration); yield takeEvery(DrawingsTypes.UPDATE_CALIBRATION, updateCalibration); diff --git a/frontend/src/v5/store/drawings/drawings.types.ts b/frontend/src/v5/store/drawings/drawings.types.ts index 44c8474890..cb0986cf54 100644 --- a/frontend/src/v5/store/drawings/drawings.types.ts +++ b/frontend/src/v5/store/drawings/drawings.types.ts @@ -50,7 +50,6 @@ export interface DrawingStats { }; number: string, calibrationStatus?: CalibrationStatus, - calibration: Calibration, type: string, status: UploadStatus, errorReason?: { @@ -60,11 +59,22 @@ export interface DrawingStats { desc?: string; } +type DrawingSettingsCalibration = Omit; + +export interface DrawingSettings { + name: string, + number: string, + type: string, + desc: string, + calibration: DrawingSettingsCalibration, +} + export interface IDrawing extends MinimumDrawing, Partial> { lastUpdated?: Date; latestRevision?: string; revisionsCount: number; hasStatsPending?: boolean; + calibration: Calibration; } export type NewDrawing = { @@ -73,5 +83,5 @@ export type NewDrawing = { type: string; number: string; desc?: string; - calibration: Omit; + calibration: DrawingSettingsCalibration; }; diff --git a/frontend/src/v5/store/drawings/revisions/drawingRevisions.helpers.ts b/frontend/src/v5/store/drawings/revisions/drawingRevisions.helpers.ts index 2fb1bb35f7..a132d2394a 100644 --- a/frontend/src/v5/store/drawings/revisions/drawingRevisions.helpers.ts +++ b/frontend/src/v5/store/drawings/revisions/drawingRevisions.helpers.ts @@ -35,10 +35,7 @@ export const createDrawingFromRevisionBody = (body: CreateDrawingRevisionBody): number: body.drawingNumber, type: body.drawingType, desc: body.drawingDesc, - calibration: { - verticalRange: body.calibration.verticalRange, - units: body.calibration.units, - }, + calibration: body.calibration, }); export const createFormDataFromRevisionBody = (body: CreateDrawingRevisionBody) => { diff --git a/frontend/src/v5/ui/components/viewer/drawingViewer/viewer2D.component.tsx b/frontend/src/v5/ui/components/viewer/drawingViewer/viewer2D.component.tsx index 39ac9f6541..418534aef9 100644 --- a/frontend/src/v5/ui/components/viewer/drawingViewer/viewer2D.component.tsx +++ b/frontend/src/v5/ui/components/viewer/drawingViewer/viewer2D.component.tsx @@ -133,6 +133,8 @@ export const Viewer2D = () => { useEffect(() => { if (hasCalibration) { DrawingsActionsDispatchers.fetchCalibration(teamspace, project, drawingId); + } else { + DrawingsActionsDispatchers.fetchDrawingSettings(teamspace, project, drawingId); } }, [hasCalibration, revisionId]); diff --git a/frontend/src/v5/ui/routes/dashboard/projects/calibration/calibration.helpers.ts b/frontend/src/v5/ui/routes/dashboard/projects/calibration/calibration.helpers.ts index 0d6d19d83e..f7da4f3aac 100644 --- a/frontend/src/v5/ui/routes/dashboard/projects/calibration/calibration.helpers.ts +++ b/frontend/src/v5/ui/routes/dashboard/projects/calibration/calibration.helpers.ts @@ -16,9 +16,14 @@ */ import { Matrix3, Vector2 } from 'three'; -import { Coord2D, Vector2D, Vector3D } from './calibration.types'; +import { Coord2D, Vector1D, Vector2D, Vector3D } from './calibration.types'; import { isNumber } from 'lodash'; +export const DEFAULT_SETTINGS_CALIBRATION = { + units: 'mm', + verticalRange: [0, 1] as Vector1D, +}; + export const UNITS_CONVERSION_FACTORS_TO_METRES = { 'm': 1, 'dm': 10, diff --git a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/createDrawingDialog.component.tsx b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/createDrawingDialog.component.tsx index 668477d383..5b385b1b89 100644 --- a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/createDrawingDialog.component.tsx +++ b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/createDrawingDialog.component.tsx @@ -22,12 +22,13 @@ import { ProjectsHooksSelectors, TeamspacesHooksSelectors } from '@/v5/services/ import { DrawingsActionsDispatchers } from '@/v5/services/actionsDispatchers'; import { IFormInput, useDrawingForm } from './drawingsDialogs.hooks'; import { DrawingForm } from './drawingForm.component'; +import { DEFAULT_SETTINGS_CALIBRATION } from '../../calibration/calibration.helpers'; export const CreateDrawingDialog = ({ open, onClickClose }) => { const teamspace = TeamspacesHooksSelectors.selectCurrentTeamspace(); const project = ProjectsHooksSelectors.selectCurrentProject(); - const { onSubmitError, formData } = useDrawingForm(); + const { onSubmitError, formData } = useDrawingForm({ calibration: DEFAULT_SETTINGS_CALIBRATION } as any); const { handleSubmit, formState } = formData; const onSubmit: SubmitHandler = async (body) => { diff --git a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/drawingForm.component.tsx b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/drawingForm.component.tsx index 5af10292f9..65e6e01438 100644 --- a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/drawingForm.component.tsx +++ b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/drawingForm.component.tsx @@ -106,7 +106,6 @@ export const DrawingForm = ({ formData, drawing }:Props) => { name="calibration.verticalRange.0" label={formatMessage({ id: 'drawings.form.bottomExtent', defaultMessage: 'Bottom Extent' })} formError={errors.calibration?.verticalRange?.[0]} - defaultValue={0} required /> { label={formatMessage({ id: 'drawings.form.topExtent', defaultMessage: 'Top Extent' })} formError={errors.calibration?.verticalRange?.[1]} required - defaultValue={1} /> {MODEL_UNITS.map(({ value, name }) => ( diff --git a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/editDrawingDialog.component.tsx b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/editDrawingDialog.component.tsx index eebcd34d81..fee34e4b5a 100644 --- a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/editDrawingDialog.component.tsx +++ b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingDialogs/editDrawingDialog.component.tsx @@ -18,10 +18,9 @@ import { formatMessage } from '@/v5/services/intl'; import { SubmitHandler } from 'react-hook-form'; import { FormModal } from '@controls/formModal/formModal.component'; -import { ProjectsHooksSelectors, TeamspacesHooksSelectors } from '@/v5/services/selectorsHooks'; +import { DrawingsHooksSelectors, ProjectsHooksSelectors, TeamspacesHooksSelectors } from '@/v5/services/selectorsHooks'; import { DrawingsActionsDispatchers } from '@/v5/services/actionsDispatchers'; import { IFormInput, useDrawingForm } from './drawingsDialogs.hooks'; -import { IDrawing } from '@/v5/store/drawings/drawings.types'; import { dirtyValuesChanged } from '@/v5/helpers/form.helper'; import { pick } from 'lodash'; import { DrawingForm } from './drawingForm.component'; @@ -31,12 +30,13 @@ import { Loader } from '@/v4/routes/components/loader/loader.component'; interface Props { open: boolean; onClickClose: () => void; - drawing: IDrawing + drawingId: string } -export const EditDrawingDialog = ({ open, onClickClose, drawing }:Props) => { +export const EditDrawingDialog = ({ open, onClickClose, drawingId }:Props) => { const teamspace = TeamspacesHooksSelectors.selectCurrentTeamspace(); const project = ProjectsHooksSelectors.selectCurrentProject(); + const drawing = DrawingsHooksSelectors.selectDrawingById(drawingId); const { onSubmitError, formData } = useDrawingForm(drawing); const { handleSubmit, formState } = formData; @@ -44,8 +44,8 @@ export const EditDrawingDialog = ({ open, onClickClose, drawing }:Props) => { const onSubmit: SubmitHandler = async (body) => { try { await new Promise((accept, reject) => { - const updatedDrawingData = pick(body, ['name', 'number', 'type', 'desc']); - DrawingsActionsDispatchers.updateDrawing(teamspace, project, drawing._id, updatedDrawingData, accept, reject); + const updatedDrawingData = pick(body, Object.keys(formState.dirtyFields)); + DrawingsActionsDispatchers.updateDrawing(teamspace, project, drawingId, updatedDrawingData, accept, reject); }); onClickClose(); } catch (err) { @@ -54,9 +54,15 @@ export const EditDrawingDialog = ({ open, onClickClose, drawing }:Props) => { }; useEffect(() => { - DrawingsActionsDispatchers.fetchCalibration(teamspace, project, drawing._id); + DrawingsActionsDispatchers.fetchDrawingSettings( + teamspace, + project, + drawingId, + ); }, []); + useEffect(() => { formData.reset(drawing); }, [JSON.stringify(drawing)]); + return ( { confirmLabel={formatMessage({ id: 'drawings.edit.ok', defaultMessage: 'Save Drawing' })} maxWidth="sm" {...formState} - isValid={dirtyValuesChanged(formData, drawing) && formState.isValid} + isValid={dirtyValuesChanged(formData, drawingId) && formState.isValid} > {drawing.calibration.units ? diff --git a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingsList/drawingsListItem/drawingsEllipsisMenu/drawingsEllipsisMenu.component.tsx b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingsList/drawingsListItem/drawingsEllipsisMenu/drawingsEllipsisMenu.component.tsx index 546fae3e5a..643117f02a 100644 --- a/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingsList/drawingsListItem/drawingsEllipsisMenu/drawingsEllipsisMenu.component.tsx +++ b/frontend/src/v5/ui/routes/dashboard/projects/drawings/drawingsList/drawingsListItem/drawingsEllipsisMenu/drawingsEllipsisMenu.component.tsx @@ -40,12 +40,12 @@ export const DrawingsEllipsisMenu = ({ }: DrawingsEllipsisMenuProps) => { const { teamspace, project } = useParams(); const isProjectAdmin = ProjectsHooksSelectors.selectIsProjectAdmin(); - const hasCollaboratorAccess = DrawingsHooksSelectors.selectHasCollaboratorAccess(drawing._id); + const drawingId = drawing._id; + const hasCollaboratorAccess = DrawingsHooksSelectors.selectHasCollaboratorAccess(drawingId); - const onCalibrateClick = () => DialogsActionsDispatchers.open(SelectModelForCalibration, { drawingId: drawing._id }); + const onCalibrateClick = () => DialogsActionsDispatchers.open(SelectModelForCalibration, { drawingId }); - - const onClickSettings = () => DialogsActionsDispatchers.open(EditDrawingDialog, { drawing }); + const onClickSettings = () => DialogsActionsDispatchers.open(EditDrawingDialog, { drawingId }); const onClickDelete = () => DialogsActionsDispatchers.open('delete', { name: drawing.name, @@ -53,7 +53,7 @@ export const DrawingsEllipsisMenu = ({ (accept, reject) => DrawingsActionsDispatchers.deleteDrawing( teamspace, project, - drawing._id, + drawingId, accept, reject, ), @@ -87,7 +87,7 @@ export const DrawingsEllipsisMenu = ({ title={formatMessage(selected ? { id: 'drawings.ellipsisMenu.hideRevisions', defaultMessage: 'Hide Revisions' } : { id: 'drawings.ellipsisMenu.viewRevisions', defaultMessage: 'View Revisions' })} - onClick={() => onSelectOrToggleItem(drawing._id)} + onClick={() => onSelectOrToggleItem(drawingId)} /> )} uploadToDrawing(drawing._id)} + onClick={() => uploadToDrawing(drawingId)} hidden={!hasCollaboratorAccess} />