Skip to content

Commit

Permalink
Refactored to be more efficient. Added some code suggestions from #323
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelnogueiramov committed Sep 3, 2024
1 parent d070c24 commit 8aee46f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 72 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- [FP-2603](https://movai.atlassian.net/browse/FP-2603): Properties dropdown closing after edit - active tab change is being wrongfully triggered
- [QAP-4055](https://movai.atlassian.net/browse/QAP-4055): Forward test coverage for lib-ide
- [FP-2529](https://movai.atlassian.net/browse/FP-2529): Add data-testid to links. Added unit testing to BaseLink
- [FP-2787](https://movai.atlassian.net/browse/FP-2787): IDE - Topics - Can't open multiple Topics tabs

# 1.2.3

Expand All @@ -24,7 +25,7 @@

- [FP-2603](https://movai.atlassian.net/browse/FP-2603): Properties dropdown closing after edit
- [FP-2633](https://movai.atlassian.net/browse/FP-2633): Configuration Key not found error
- [FP-2655](https://movai.atlassian.net/browse/FP-2655): SCENE\_EDITOR-Old\_Values\_after\_selecting\_another\_entity
- [FP-2655](https://movai.atlassian.net/browse/FP-2655): SCENE_EDITOR-Old_Values_after_selecting_another_entity
- [FP-2657](https://movai.atlassian.net/browse/FP-2657): Users with only read permissions can change the scene
- [FP-2664](https://movai.atlassian.net/browse/FP-2664): Update react in all libs/apps
- [FP-2557](https://movai.atlassian.net/browse/FP-2557): Removing frontend callbacks from backend
Expand Down
98 changes: 41 additions & 57 deletions src/plugins/views/Tabs/hooks/useTabLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
DOCK_MODES,
PLUGINS
} from "../../../../utils/Constants";
import { getIconByScope, findNextIncrement } from "../../../../utils/Utils";
import { getIconByScope } from "../../../../utils/Utils";
import PluginManagerIDE from "../../../../engine/PluginManagerIDE/PluginManagerIDE";
import Workspace from "../../../../utils/Workspace";
import { getToolTabData } from "../../../../tools";
Expand All @@ -26,7 +26,7 @@ const useTabLayout = (props, dockRef) => {
const activeTabId = useRef(null);
const firstLoad = useRef(true);
const preventReloadNewDoc = useRef(false);
const tabsById = useRef(new Map());
const tabsByIdRef = useRef(new Map());
const [layout, setLayout] = useState({ ...DEFAULT_LAYOUT });
const { addTabToStack, removeTabFromStack, getNextTabFromStack } =
useTabStack(workspaceManager);
Expand All @@ -47,8 +47,8 @@ const useTabLayout = (props, dockRef) => {
if (!tab.extension) {
const toolName = tab.id;
const tabData = getToolTabData(tab, tab.tabProps);
tabsById.current.set(tabData.id, tabData);
workspaceManager.setTabs(tabsById.current);
tabsByIdRef.current.set(tabData.id, tabData);
workspaceManager.setTabs(tabsByIdRef.current);
addTabToStack(tabData, DOCK_POSITIONS.DOCK);
dockRef.current?.updateTab?.(toolName, tabData, false);
}
Expand Down Expand Up @@ -202,10 +202,10 @@ const useTabLayout = (props, dockRef) => {
const tabIndex = box.tabs.findIndex(_el => _el.id === prevTabId);
box.tabs[tabIndex] = tabData;
box.activeId = tabData.id;
tabsById.current.delete(prevTabId);
tabsById.current.set(tabData.id, tabData);
tabsByIdRef.current.delete(prevTabId);
tabsByIdRef.current.set(tabData.id, tabData);
addTabToStack(tabData, location);
workspaceManager.setTabs(tabsById.current);
workspaceManager.setTabs(tabsByIdRef.current);
workspaceManager.setLayout(newLayout);
}
return { newLayout, box };
Expand Down Expand Up @@ -331,7 +331,7 @@ const useTabLayout = (props, dockRef) => {
*/
const _onLayoutRemoveTab = useCallback(
(newLayout, tabId, forceClose) => {
const { name, scope, isNew, isDirty } = tabsById.current.get(tabId);
const { name, scope, isNew, isDirty } = tabsByIdRef.current.get(tabId);

if (isDirty && !forceClose) {
const document = { id: tabId, name, scope, isNew };
Expand All @@ -347,8 +347,8 @@ const useTabLayout = (props, dockRef) => {
}

// Remove tab and apply new layout
tabsById.current.delete(tabId);
workspaceManager.setTabs(tabsById.current);
tabsByIdRef.current.delete(tabId);
workspaceManager.setTabs(tabsByIdRef.current);
const dock = getDockFromTabId(tabId);
removeTabFromStack(tabId, dock);
applyLayout(newLayout);
Expand Down Expand Up @@ -415,13 +415,13 @@ const useTabLayout = (props, dockRef) => {
data => {
const { instance: model, value: isDirty } = data;
const tabId = model.getUrl();
const currentTabData = tabsById.current.get(tabId);
const currentTabData = tabsByIdRef.current.get(tabId);
const currentDirtyState = Boolean(currentTabData?.isDirty);
// Doesn't trigger update if dirty state didn't change
if (!currentTabData || currentDirtyState === isDirty) return;
// Set new dirty state
const newTabData = { ...currentTabData, isDirty: isDirty };
tabsById.current.set(tabId, newTabData);
tabsByIdRef.current.set(tabId, newTabData);
// Trigger tab update
if (!dockRef.current) return;
const currentTab = findTab(tabId);
Expand Down Expand Up @@ -519,50 +519,34 @@ const useTabLayout = (props, dockRef) => {
*/
const open = useCallback(
tabData => {
let newTabData = {...tabData};
const tabPosition = newTabData.dockPosition ?? getDefaultTabPosition();
const position = newTabData.position ?? {
const tabPosition = tabData.dockPosition ?? getDefaultTabPosition();
const position = tabData.position ?? {
h: 500,
w: 600,
x: 145,
y: 100,
z: 1
};

if(Object.hasOwn(newTabData, 'multiple')){
const thisTabIds = [...tabsById.current.values()]
.filter(tab => tab.scope === newTabData.scope)
.map(tab => tab.multiple);

const currentIncrement = findNextIncrement(thisTabIds);
newTabData.multiple = currentIncrement;

if(currentIncrement > 1) {
newTabData.id = `${newTabData.scope}_${currentIncrement}`;
newTabData.name = `${newTabData.name} ${currentIncrement}`;
newTabData.tabTitle = `${newTabData.tabTitle} ${currentIncrement}`;
}
}
emit(PLUGINS.TABS.ON.ACTIVE_TAB_CHANGE, { id: tabData.id });
addTabToStack(tabData, tabPosition);
tabsByIdRef.current.set(tabData.id, tabData);
workspaceManager.setTabs(tabsByIdRef.current);

emit(PLUGINS.TABS.ON.ACTIVE_TAB_CHANGE, { id: newTabData.id });
addTabToStack(newTabData, tabPosition);
tabsById.current.set(newTabData.id, newTabData);
workspaceManager.setTabs(tabsById.current);

const existingTab = findTab(newTabData.id);
const existingTab = findTab(tabData.id);

if (existingTab) {
focusExistingTab(newTabData.id);
focusExistingTab(tabData.id);
return;
}

// Update new open tab id
activeTabId.current = newTabData.id;
activeTabId.current = tabData.id;
// Set new layout
setLayout(prevState => {
const newState = { ...prevState };
if (newState[tabPosition].children.length === 0) {
newState[tabPosition].children = [{ ...position, tabs: [newTabData] }];
newState[tabPosition].children = [{ ...position, tabs: [tabData] }];

workspaceManager.setLayout(newState);
return { ...newState };
Expand All @@ -571,12 +555,12 @@ const useTabLayout = (props, dockRef) => {
if (tabPosition === DOCK_POSITIONS.FLOAT) {
newState[tabPosition].children.push({
...position,
tabs: [newTabData]
tabs: [tabData]
});
} else {
const firstContainer = _getFirstContainer(newState[tabPosition]);
firstContainer.tabs.push(newTabData);
firstContainer.activeId = newTabData.id;
firstContainer.tabs.push(tabData);
firstContainer.activeId = tabData.id;
}

workspaceManager.setLayout(newState);
Expand Down Expand Up @@ -640,7 +624,7 @@ const useTabLayout = (props, dockRef) => {
*/
const loadTab = useCallback(
data => {
const tabFromMemory = tabsById.current.get(data.id);
const tabFromMemory = tabsByIdRef.current.get(data.id);
if (!tabFromMemory && !data.content) return;

const {
Expand All @@ -652,11 +636,11 @@ const useTabLayout = (props, dockRef) => {
extension,
isDirty,
isNew,
multiple,
tabIncrement,
tabProps
} = tabFromMemory ?? data;

tabsById.current.set(id, {
tabsByIdRef.current.set(id, {
id,
scope,
name,
Expand All @@ -665,19 +649,19 @@ const useTabLayout = (props, dockRef) => {
extension,
isNew,
isDirty,
multiple,
tabIncrement,
tabProps
});
const tabData = {
id,
scope,
name,
tabTitle,
extension
const tabData = {
id,
scope,
name,
tabTitle,
extension
};
return {
id: id,
multiple,
tabIncrement,
title: _getCustomTab(tabData, _closeTab, isDirty),
content: content,
closable: true
Expand All @@ -696,7 +680,7 @@ const useTabLayout = (props, dockRef) => {
(newLayout, tabId, direction) => {
const isActuallyTabChange = activeTabId.current !== tabId;
const dock = getDockFromTabId(tabId);
const tabData = tabsById.current.get(tabId);
const tabData = tabsByIdRef.current.get(tabId);
let newActiveTabId = tabId;

// Attempt to close tab
Expand All @@ -717,7 +701,7 @@ const useTabLayout = (props, dockRef) => {
// Emit new active tab id
if (!tabId) return;

if(isActuallyTabChange){
if (isActuallyTabChange) {
activeTabId.current = newActiveTabId;
emit(PLUGINS.TABS.ON.ACTIVE_TAB_CHANGE, { id: newActiveTabId });
}
Expand Down Expand Up @@ -763,7 +747,7 @@ const useTabLayout = (props, dockRef) => {
* @returns {string} active tab id
*/
const getActiveTab = useCallback(() => {
return tabsById.current.get(activeTabId.current);
return tabsByIdRef.current.get(activeTabId.current);
}, []);

/**
Expand Down Expand Up @@ -839,7 +823,7 @@ const useTabLayout = (props, dockRef) => {

layoutActiveIdIsValid(lastLayout);

tabsById.current = lastTabs;
tabsByIdRef.current = lastTabs;
// Install current tabs plugins
lastTabs.forEach(tab => {
const { content, ...others } = tab;
Expand All @@ -849,7 +833,7 @@ const useTabLayout = (props, dockRef) => {
Promise.allSettled(tabs).then(_tabs => {
_tabs.forEach(tab => {
tab.status === "fulfilled" &&
tabsById.current.set(tab.value.id, tab.value);
tabsByIdRef.current.set(tab.value.id, tab.value);
});
setLayout(lastLayout);

Expand Down
2 changes: 1 addition & 1 deletion src/tools/NotInstalled/NotInstalled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const NotInstalled = props => {

export default NotInstalled;

export const getTabData = (id, name) => {
export const getNotInstalledTabData = (id, name) => {
const tabTitle = name || id;
return {
id: id,
Expand Down
7 changes: 4 additions & 3 deletions src/tools/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import PluginManagerIDE from "../engine/PluginManagerIDE/PluginManagerIDE";
import { getTabData } from "./NotInstalled/NotInstalled";
import { getNotInstalledTabData } from "./NotInstalled/NotInstalled";

const APP_TOOLS = {};

Expand All @@ -10,8 +10,9 @@ export const addTool = (name, tool) => {

export const getToolTabData = (tab, props = {}) => {
const { id, name, scope } = tab;
const notInstalledTab = getTabData(id, name);
const data = APP_TOOLS[scope]?.tabData ?? APP_TOOLS[id]?.tabData ?? notInstalledTab;
const notInstalledTab = getNotInstalledTabData(id, name);
const data =
APP_TOOLS[scope]?.tabData ?? APP_TOOLS[id]?.tabData ?? notInstalledTab;

// Sanitize tab data to avoid TypeError: Converting circular structure to JSON
if (!data.content) {
Expand Down
24 changes: 14 additions & 10 deletions src/utils/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,32 @@ export const defaultFunction = (name, logToConsole = true) => {
*/
export const uuidv4 = () => {
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
(+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
(
+c ^
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4)))
).toString(16)
);
}
};

/**
* Tries to find the next increment on an array of numbers
* @param {Number[]} numArray
* @param {Number[]} numArray
*/
export const findNextIncrement = (numArray) => {
if(!numArray || numArray.length < 2) return numArray[0] ? numArray[0] + 1 : 1;
export const findNextIncrement = numArray => {
if (!numArray || numArray.length < 2)
return numArray[0] ? numArray[0] + 1 : 1;

const max = Math.max(...numArray);
const min = Math.min(...numArray);
const min = 1;

for(let i=min; i<= max; i++) {
if(!numArray.includes(i)) {
return i;
for (let i = min; i <= max; i++) {
if (!numArray.includes(i)) {
return i;
}
}

return max + 1;
}
};

/**
* Returns a given icon with props in a method
Expand Down
20 changes: 20 additions & 0 deletions src/utils/generalFunctions.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { i18n } from "@mov-ai/mov-fe-lib-react";
import AppSettings from "../App/AppSettings";
import { PLUGINS } from "../utils/Constants";
import { findNextIncrement } from "./Utils";
import Workspace from "./Workspace";
import movaiIconWhite from "../Branding/movai-logo-white.png";
import { getHomeTab } from "../tools/HomeTab/HomeTab";
import { getShortcutsTab } from "../tools/AppShortcuts/AppShortcuts";
import { getToolTabData } from "../tools";

const workspaceManager = new Workspace();

//========================================================================================
/* *
* Private Methods *
Expand Down Expand Up @@ -74,6 +78,22 @@ export function aboutPopup(call, classes = {}) {
*/
export function openTool(call, scope = getHomeTab().scope, props = {}) {
const tabData = getToolTabData({ scope }, props);

if (Object.hasOwn(tabData, "tabIncrement")) {
const thisTabIds = [...workspaceManager.getTabs().values()]
.filter(tab => tab.scope === tabData.scope)
.map(tab => tab.tabIncrement);

const currentIncrement = findNextIncrement(thisTabIds);
tabData.tabIncrement = currentIncrement;

if (currentIncrement > 1) {
tabData.id = `${tabData.scope}_${currentIncrement}`;
tabData.name = `${tabData.name} ${currentIncrement}`;
tabData.tabTitle = `${tabData.tabTitle} ${currentIncrement}`;
}
}

call(PLUGINS.TABS.NAME, PLUGINS.TABS.CALL.OPEN, tabData);
}

Expand Down

0 comments on commit 8aee46f

Please sign in to comment.