diff --git a/README.md b/README.md index 2564b4f8..5bb59e3b 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,10 @@ E.g., if it was used in a menu and the menu is red, the circle would be red. ### **WORK IN PROGRESS** --> ## Changelog +### **WORK IN PROGRESS** +* (foxriver76) prevent showing widget in group after it is already cut out +* (foxriver76) prevent usage of widgets which are not in group for calculating rulers on group view + ### 2.9.12 (2024-01-04) * (foxriver76) optimized copy/paste/cut in groups diff --git a/src/src/App.jsx b/src/src/App.jsx index 0cbc712a..59b5cd4b 100644 --- a/src/src/App.jsx +++ b/src/src/App.jsx @@ -468,9 +468,9 @@ class App extends Runtime { }; deleteWidgetsAction = async () => { - const project = JSON.parse(JSON.stringify(store.getState().visProject)); + const project = deepClone(store.getState().visProject); const widgets = project[this.state.selectedView].widgets; - this.state.selectedWidgets.forEach(selectedWidget => { + for (const selectedWidget of this.state.selectedWidgets) { if (widgets[selectedWidget].tpl === '_tplGroup') { widgets[selectedWidget].data.members.forEach(member => { delete widgets[member]; @@ -490,7 +490,7 @@ class App extends Runtime { } delete widgets[selectedWidget]; - }); + } this.setSelectedWidgets([]); await this.changeProject(project); }; @@ -546,21 +546,6 @@ class App extends Runtime { if (widget.groupid) { delete widgets[selectedWidget].groupid; delete widgets[selectedWidget].grouped; - delete widget._id; - } - - if (type === 'cut') { - if (widget.groupid) { - const group = project[this.state.selectedView].widgets[widget.groupid]; - - const pos = group.data.members.indexOf(selectedWidget); - - if (pos !== -1) { - group.data.members.splice(pos, 1); - } - } - - delete project[this.state.selectedView].widgets[selectedWidget]; } } }); @@ -576,8 +561,7 @@ class App extends Runtime { // deselect all widgets if (type === 'cut') { - await this.setSelectedWidgets([]); - await this.changeProject(project); + this.deleteWidgetsAction(); } }; diff --git a/src/src/Store.tsx b/src/src/Store.tsx index 2106a027..19bbe3d4 100644 --- a/src/src/Store.tsx +++ b/src/src/Store.tsx @@ -1,11 +1,14 @@ import { createReducer, configureStore, createAction, createSelector, } from '@reduxjs/toolkit'; -import type { View, Widget, Project } from '@/types'; +import type { + View, Project, AnyWidgetId, SingleWidgetId, SingleWidget, GroupWidget, GroupWidgetId, +} from '@/types'; export const updateProject = createAction('project/update'); -export const updateView = createAction<{viewId: string; data: View}>('view/update'); -export const updateWidget = createAction<{viewId: string; widgetId: string; data: Widget}>('widget/update'); +export const updateView = createAction<{ viewId: string; data: View }>('view/update'); +export const updateWidget = createAction<{ viewId: string; widgetId: SingleWidgetId; data: SingleWidget }>('widget/update'); +export const updateGroupWidget = createAction<{ viewId: string; widgetId: GroupWidgetId; data: GroupWidget }>('group/update'); export const recalculateFields = createAction('attributes/recalculate'); const initialState = { @@ -28,6 +31,10 @@ const reducer = createReducer( const { viewId, widgetId, data } = action.payload; state.visProject[viewId].widgets[widgetId] = data; }) + .addCase(updateGroupWidget, (state, action) => { + const { viewId, widgetId, data } = action.payload; + state.visProject[viewId].widgets[widgetId] = data; + }) .addCase(recalculateFields, (state, action) => { state.recalculateFields = action.payload; }); @@ -45,7 +52,7 @@ export const selectView = createSelector([ export const selectWidget = createSelector([ selectView, - (_state: StoreState, _viewName: string, wid: string) => wid, + (_state: StoreState, _viewName: string, wid: AnyWidgetId) => wid, ], (view, wid) => view.widgets[wid]); export const store = configureStore({ diff --git a/src/src/Toolbar/ViewsManager/ViewDialog.tsx b/src/src/Toolbar/ViewsManager/ViewDialog.tsx index 8cca833a..34ad18f6 100644 --- a/src/src/Toolbar/ViewsManager/ViewDialog.tsx +++ b/src/src/Toolbar/ViewsManager/ViewDialog.tsx @@ -18,7 +18,7 @@ import { } from '@/Utils/utils'; import { useFocus } from '@/Utils'; import IODialog from '@/Components/IODialog'; -import { Project } from '@/types'; +import { Project, SingleWidgetId } from '@/types'; interface ViewDialogProps { changeProject: (project: Project) => Promise; @@ -133,7 +133,7 @@ const ViewDialog = (props: ViewDialogProps) => { }); } else if (!widget.groupid) { const newWid = getNewWidgetId(project); - project[props.dialogName].widgets[newWid] = originalWidgets[wid]; + project[props.dialogName].widgets[newWid] = originalWidgets[wid as SingleWidgetId]; } } diff --git a/src/src/Toolbar/WidgetImportDialog.tsx b/src/src/Toolbar/WidgetImportDialog.tsx index 9c4d4c02..32d36c84 100644 --- a/src/src/Toolbar/WidgetImportDialog.tsx +++ b/src/src/Toolbar/WidgetImportDialog.tsx @@ -13,7 +13,9 @@ import { import { useFocus } from '@/Utils'; import { store } from '@/Store'; -import { GroupWidget, Project, Widget } from '@/types'; +import { + GroupWidget, GroupWidgetId, Project, Widget, +} from '@/types'; import CustomAceEditor from '../Components/CustomAceEditor'; interface WidgetImportDialogProps { @@ -21,7 +23,7 @@ interface WidgetImportDialogProps { onClose:() => void; themeType: string; selectedView: string; - selectedGroup: string; + selectedGroup: GroupWidgetId; } const WidgetImportDialog = (props: WidgetImportDialogProps) => { diff --git a/src/src/Utils/utils.tsx b/src/src/Utils/utils.tsx index 98a32eb9..77628087 100644 --- a/src/src/Utils/utils.tsx +++ b/src/src/Utils/utils.tsx @@ -4,7 +4,7 @@ import type { CSSProperties } from '@mui/styles'; import { store } from '@/Store'; import { - GroupWidget, Widget, Project, SingleWidget, + GroupWidget, Widget, Project, SingleWidget, SingleWidgetId, GroupWidgetId, AnyWidgetId, } from '@/types'; /** Default OID if no selected */ @@ -88,7 +88,7 @@ export function getNewWidgetIdNumber(isWidgetGroup: boolean, project: Project, o * @param offset offset, if multiple widgets are created and not yet in the project * @return {string} */ -export function getNewWidgetId(project: Project, offset = 0): string { +export function getNewWidgetId(project: Project, offset = 0): SingleWidgetId { const newKey = getNewWidgetIdNumber(false, project, offset); return `w${(newKey).toString().padStart(6, '0')}`; @@ -99,7 +99,7 @@ export function getNewWidgetId(project: Project, offset = 0): string { * @param project project to determine next group id for * @param offset offset, if multiple groups are created and not yet in the project */ -export function getNewGroupId(project: Project, offset = 0): string { +export function getNewGroupId(project: Project, offset = 0): GroupWidgetId { const newKey = getNewWidgetIdNumber(true, project, offset); return `g${newKey.toString().padStart(6, '0')}`; @@ -194,7 +194,7 @@ export function unsyncMultipleWidgets(project: Project): Project { for (const widgetId of Object.keys(view.widgets)) { if (widgetId.includes('_')) { - delete view.widgets[widgetId]; + delete view.widgets[widgetId as AnyWidgetId]; } } } diff --git a/src/src/Vis/visView.jsx b/src/src/Vis/visView.jsx index 8d12b864..31078d19 100644 --- a/src/src/Vis/visView.jsx +++ b/src/src/Vis/visView.jsx @@ -26,7 +26,7 @@ import { addClass, parseDimension } from './visUtils'; import VisNavigation from './visNavigation'; import { isVarFinite } from '../Utils/utils'; import VisWidgetsCatalog from './visWidgetsCatalog'; -import { recalculateFields, store } from '../Store'; +import { recalculateFields, selectView, store } from '../Store'; const generateClassNameEngine = createGenerateClassName({ productionPrefix: 'vis', @@ -428,7 +428,7 @@ class VisView extends React.Component { return; } - if (true || !isRelative) { + if (!isRelative) { this.refView.current.addEventListener('mousemove', this.onMouseWidgetMove); window.document.addEventListener('mouseup', this.onMouseWidgetUp); @@ -590,14 +590,15 @@ class VisView extends React.Component { const viewRect = this.refView.current.getBoundingClientRect(); - Object.keys(this.widgetsRefs).forEach(wid => { - const widgets = store.getState().visProject[this.props.view].widgets; + for (const wid of Object.keys(this.widgetsRefs)) { + const { widgets } = selectView(store.getState(), this.props.view); if (!this.props.selectedWidgets.includes(wid) && widgets[wid] && + ((this.props.selectedGroup && widgets[this.props.selectedGroup].data.members.includes(wid)) || !this.props.selectedGroup) && (!widgets[wid].grouped || this.props.selectedGroup) ) { if (!this.widgetsRefs[wid].refService.current) { - console.error('CHECK WHY!!!'); + console.error(`CHECK WHY!!! ${wid} has no refService.current`); } else { const boundingRect = this.widgetsRefs[wid].refService.current.getBoundingClientRect(); horizontals.push(Math.round(boundingRect.top)); @@ -606,12 +607,12 @@ class VisView extends React.Component { verticals.push(Math.round(boundingRect.right)); } } - }); + } const selectedHorizontals = []; const selectedVerticals = []; - this.props.selectedWidgets.forEach(wid => { - const widgets = store.getState().visProject[this.props.view].widgets; + for (const wid of this.props.selectedWidgets) { + const { widgets } = selectView(store.getState(), this.props.view); // check if not in group if (widgets[wid] && (!widgets[wid].grouped || this.props.selectedGroup)) { const boundingRect = this.widgetsRefs[wid].refService.current.getBoundingClientRect(); @@ -620,7 +621,8 @@ class VisView extends React.Component { selectedVerticals.push(Math.round(boundingRect.left)); selectedVerticals.push(Math.round(boundingRect.right)); } - }); + } + horizontals.forEach(horizontal => selectedHorizontals.forEach(selectedHorizontal => { if (Math.abs(horizontal - selectedHorizontal) <= 0.3) { rulers.push({ type: 'horizontal', value: horizontal - viewRect.top }); @@ -1459,12 +1461,14 @@ class VisView extends React.Component { if (listRelativeWidgetsOrder.length) { let columnIndex = 0; + listRelativeWidgetsOrder.forEach((id, index) => { const widget = store.getState().visProject[view].widgets[id]; // if newLine, start from the beginning if (widget.style.newLine) { columnIndex = 0; } + const w = VisView.getOneWidget(index, widget, { // custom attributes context: this.props.context, diff --git a/src/src/types.d.ts b/src/src/types.d.ts index a60b93b1..df9d050d 100644 --- a/src/src/types.d.ts +++ b/src/src/types.d.ts @@ -39,13 +39,20 @@ interface GroupWidget extends SingleWidget { export type Widget = SingleWidget | GroupWidget; +export type SingleWidgetId = `w${string}` +export type GroupWidgetId = `g${string}` +export type AnyWidgetId = SingleWidgetId | GroupWidgetId + export interface View { activeWidgets: string[]; filterList: string[]; rerender: boolean; settings: Record; /** Widgets on this view */ - widgets: Record; + widgets: { + [groupId: GroupWidgetId]: GroupWidget; + [widgetId: SingleWidgetId]: SingleWidget; + }; } export interface Project {