From 0806734adf1f75d5f942c6ff5c2bfc8970304828 Mon Sep 17 00:00:00 2001 From: olehp Date: Thu, 15 Feb 2024 23:16:19 +0200 Subject: [PATCH 1/7] Added new navigation --- src/utils/historyManage.ts | 136 +++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/utils/historyManage.ts diff --git a/src/utils/historyManage.ts b/src/utils/historyManage.ts new file mode 100644 index 000000000..3cdbbd36c --- /dev/null +++ b/src/utils/historyManage.ts @@ -0,0 +1,136 @@ +import { TabData } from "../components/Navigation/types"; +import { Environment, Scope } from "../components/common/App/types"; + +const MAX_STEPS = 15; + +export interface HistoryStep { + scope: Scope; + environment: Environment; + tab: TabData; +} + +export interface HistoryData { + steps: HistoryStep[]; + currentStepIndex: number; +} + +interface Node { + next: Node | null; + previous: Node | null; + value: T; +} + +export class HistoryManage { + private head: Node | null = null; + private tail: Node | null = null; + + private current: Node | null = null; + private itemsCount = 0; + private currentIndex = 0; + + constructor(data: HistoryData) { + this.init(data.steps, data.currentStepIndex); + } + + push(step: HistoryStep) { + const newNode: Node = { + value: step, + previous: this.tail, + next: null + }; + + if (this.current != this.tail) { + this.tail = this.current; + this.itemsCount = this.itemsCount - (this.itemsCount - this.currentIndex); + } + + if (this.tail) { + this.tail.next = newNode; + } + + if (!this.head) { + this.head = newNode; + } + + this.tail = newNode; + this.current = newNode; + this.currentIndex++; + + if (this.itemsCount === MAX_STEPS && this.head?.next) { + this.head = this.head.next; + } else { + this.itemsCount++; + } + } + + back() { + if (!this.current?.previous) { + return null; + } + + this.current = this.current.previous; + this.currentIndex--; + return this.getCurrent(); + } + + forward() { + if (!this.current?.next) { + return null; + } + + this.current = this.current.next; + this.currentIndex++; + return this.getCurrent(); + } + + getLast() { + return this.tail?.value; + } + + getCurrent() { + return this.current?.value; + } + + updateCurrent(newValue: HistoryStep) { + if (this.current) { + this.current.value = newValue; + } + } + + getHistoryData() { + const steps = []; + let step = this.head; + while (step) { + steps.push(step); + step = step.next; + } + + return { + steps, + currentStepIndex: this.currentIndex + }; + } + + private init(steps: HistoryStep[], selectedStep: number) { + if (!steps.length) { + return; + } + + let currentIndex = 0; + + let localCurrent = null; + do { + this.push(steps[currentIndex]); + + if (selectedStep === currentIndex) { + localCurrent = this.current; + } + + currentIndex++; + } while (currentIndex < steps.length); + + this.itemsCount = steps.length; + this.currentIndex = selectedStep; + this.current = localCurrent; + } +} From 572388838a2bd1998fd091004b45ea80cdf98c2f Mon Sep 17 00:00:00 2001 From: olehp Date: Thu, 15 Feb 2024 23:16:47 +0200 Subject: [PATCH 2/7] raname --- src/utils/historyManage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/historyManage.ts b/src/utils/historyManage.ts index 3cdbbd36c..370480f00 100644 --- a/src/utils/historyManage.ts +++ b/src/utils/historyManage.ts @@ -20,7 +20,7 @@ interface Node { value: T; } -export class HistoryManage { +export class HistoryManager { private head: Node | null = null; private tail: Node | null = null; From b90779d8fe19164101d3b7a1d4d7aa79d7ee521e Mon Sep 17 00:00:00 2001 From: olehp Date: Fri, 16 Feb 2024 02:55:26 +0200 Subject: [PATCH 3/7] inital naviagtion --- src/actions.ts | 3 +- .../ScopeNavigation.stories.tsx | 28 ++++++ .../Navigation/ScopeNavigation/index.tsx | 94 +++++++++++++++++++ .../Navigation/ScopeNavigation/styles.ts | 14 +++ .../Navigation/ScopeNavigation/types.ts | 0 src/components/Navigation/index.tsx | 2 + .../{historyManage.ts => historyManager.ts} | 41 ++++++-- src/utils/useHistoryManager.ts | 55 +++++++++++ 8 files changed, 227 insertions(+), 10 deletions(-) create mode 100644 src/components/Navigation/ScopeNavigation/ScopeNavigation.stories.tsx create mode 100644 src/components/Navigation/ScopeNavigation/index.tsx create mode 100644 src/components/Navigation/ScopeNavigation/styles.ts create mode 100644 src/components/Navigation/ScopeNavigation/types.ts rename src/utils/{historyManage.ts => historyManager.ts} (76%) create mode 100644 src/utils/useHistoryManager.ts diff --git a/src/actions.ts b/src/actions.ts index 9c9a6c9b0..42fc125d2 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -33,5 +33,6 @@ export const actions = addPrefix(ACTION_PREFIX, { SET_FROM_PERSISTENCE: "SET_FROM_PERSISTENCE", OPEN_DASHBOARD: "OPEN_DASHBOARD", OPEN_INSTALLATION_WIZARD: "OPEN_INSTALLATION_WIZARD", - SET_SCOPE: "SET_SCOPE" + SET_SCOPE: "SET_SCOPE", + SET_STATE: "SET_STATE" }); diff --git a/src/components/Navigation/ScopeNavigation/ScopeNavigation.stories.tsx b/src/components/Navigation/ScopeNavigation/ScopeNavigation.stories.tsx new file mode 100644 index 000000000..03f7c0f7b --- /dev/null +++ b/src/components/Navigation/ScopeNavigation/ScopeNavigation.stories.tsx @@ -0,0 +1,28 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import { ScopeNavigation } from "."; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Navigation/ScopeNavigation", + component: ScopeNavigation, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: "fullscreen" + } +}; + +export default meta; + +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Default: Story = { + args: {} +}; + +export const Disabled: Story = { + args: { + isDisabled: true + } +}; diff --git a/src/components/Navigation/ScopeNavigation/index.tsx b/src/components/Navigation/ScopeNavigation/index.tsx new file mode 100644 index 000000000..2b69d71c8 --- /dev/null +++ b/src/components/Navigation/ScopeNavigation/index.tsx @@ -0,0 +1,94 @@ +import { useContext, useEffect, useState } from "react"; +import { actions } from "../../../actions"; +import { dispatcher } from "../../../dispatcher"; +import { HistoryManager } from "../../../utils/historyManager"; +import { ConfigContext } from "../../common/App/ConfigContext"; +import { Scope } from "../../common/App/types"; +import { actions as globalActions } from "./../actions"; +import * as s from "./styles"; + +const sendMessage = (scope: Scope) => { + window.sendMessageToDigma({ + action: globalActions.CHANGE_SCOPE, + payload: { + ...scope + } + }); +}; + +export const ScopeNavigation = () => { + const [historyManager, setHistoryManager] = useState( + new HistoryManager() + ); + const { environment } = useContext(ConfigContext); + + useEffect(() => { + const handleSetScope = (data: unknown) => { + console.log("new scope recieved " + JSON.stringify(data)); + + const newScope = data as Scope; + const currentScope = historyManager.getCurrent()?.scope; + if ( + !currentScope || + currentScope.span?.spanCodeObjectId !== newScope.span?.spanCodeObjectId + ) { + historyManager.push({ + environment: environment || null, + scope: newScope, + tab: null + }); + } + console.log("state " + JSON.stringify(historyManager.getHistoryData())); + }; + + dispatcher.addActionListener(actions.SET_SCOPE, handleSetScope); + + return () => { + dispatcher.removeActionListener(actions.SET_SCOPE, handleSetScope); + }; + }, []); + + const handleBackClick = () => { + console.log("back " + JSON.stringify(historyManager.getHistoryData())); + + historyManager.back(); + const nextScope = historyManager.getCurrent()?.scope; + if (nextScope) { + sendMessage(nextScope); + } + + console.log( + "after back " + JSON.stringify(historyManager.getHistoryData()) + ); + }; + + const handleFowradClick = () => { + console.log("next " + JSON.stringify(historyManager.getHistoryData())); + historyManager.forward(); + const nextScope = historyManager.getCurrent()?.scope; + if (nextScope) { + sendMessage(nextScope); + } + + console.log( + "next after " + JSON.stringify(historyManager.getHistoryData()) + ); + }; + + return ( + <> + + {"<"} + + + {">"} + + + ); +}; diff --git a/src/components/Navigation/ScopeNavigation/styles.ts b/src/components/Navigation/ScopeNavigation/styles.ts new file mode 100644 index 000000000..549940deb --- /dev/null +++ b/src/components/Navigation/ScopeNavigation/styles.ts @@ -0,0 +1,14 @@ +import styled from "styled-components"; + +export const NavigationButton = styled.button` + height: 28px; + width: 28px; + + &:not([disabled]) { + border: none; + } + + &:disabled { + color: ${({ theme }) => theme.colors.v3.icon.disabled}; + } +`; diff --git a/src/components/Navigation/ScopeNavigation/types.ts b/src/components/Navigation/ScopeNavigation/types.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/Navigation/index.tsx b/src/components/Navigation/index.tsx index 4ab5e7d07..3e952524e 100644 --- a/src/components/Navigation/index.tsx +++ b/src/components/Navigation/index.tsx @@ -10,6 +10,7 @@ import { AsyncActionResultData } from "../InstallationWizard/types"; import { ConfigContext } from "../common/App/ConfigContext"; import { CodeDetails, Scope } from "../common/App/types"; import { CodeButtonMenu } from "./CodeButtonMenu"; +import { ScopeNavigation } from "./ScopeNavigation"; import { TargetButtonMenu } from "./TargetButtonMenu"; import { actions } from "./actions"; import * as s from "./styles"; @@ -356,6 +357,7 @@ export const Navigation = () => { return ( +