diff --git a/apps/test-app/index.html b/apps/test-app/index.html index f106c8bee..d79070870 100644 --- a/apps/test-app/index.html +++ b/apps/test-app/index.html @@ -1,8 +1,9 @@ - - - - -
- - \ No newline at end of file + + + + + +
+ + diff --git a/apps/test-app/src/index.tsx b/apps/test-app/src/index.tsx index dfc143a1e..e05ddffa3 100644 --- a/apps/test-app/src/index.tsx +++ b/apps/test-app/src/index.tsx @@ -4,7 +4,15 @@ import { gridModule } from '@equinor/workspace-fusion/grid-module'; import { GroupingOption } from '@equinor/workspace-garden'; import React from 'react'; import { createRoot } from 'react-dom/client'; +import { createGlobalStyle } from 'styled-components'; +const GlobalStyle = createGlobalStyle` + body { + margin: 0; + padding: 0; + font-family: Equinor; + } +`; export function App() { return ( @@ -182,4 +190,10 @@ export function App() { const container = document.getElementById('root')!; const root = createRoot(container); // createRoot(container!) if you use TypeScript -root.render(); + +root.render( + <> + + + +); diff --git a/packages/workspace-fusion/package.json b/packages/workspace-fusion/package.json index 1ca4efe5d..d47e6df67 100644 --- a/packages/workspace-fusion/package.json +++ b/packages/workspace-fusion/package.json @@ -1,6 +1,6 @@ { "name": "@equinor/workspace-fusion", - "version": "5.2.2", + "version": "5.3.2", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/workspace-fusion/src/modules/garden/components/GroupingSelector.tsx b/packages/workspace-fusion/src/modules/garden/components/GroupingSelector.tsx index bbab6c24b..69752a1f3 100644 --- a/packages/workspace-fusion/src/modules/garden/components/GroupingSelector.tsx +++ b/packages/workspace-fusion/src/modules/garden/components/GroupingSelector.tsx @@ -1,10 +1,9 @@ -import { Autocomplete, Radio } from '@equinor/eds-core-react'; +import { Autocomplete, Divider, Radio } from '@equinor/eds-core-react'; import { FilterState } from '@equinor/workspace-filter'; import { GardenDataSource, GroupingOption } from '@equinor/workspace-garden'; import { useQuery } from '@tanstack/react-query'; import { useRef } from 'react'; import styled from 'styled-components'; -import { useOutsideClick } from '../../../lib/hooks/useGardenPopoverOutsideClick'; type GroupingSelectorProps = { dataSource: GardenDataSource; @@ -15,9 +14,6 @@ type GroupingSelectorProps = { dateVariant: string | null; onChangeTimeInterval: (timeInterval: string | null) => void; onChangeDateVarient: (dateVariant: string | null) => void; - popoverRef: React.MutableRefObject; - iconRef: React.MutableRefObject; - close: VoidFunction; }; export function GroupingSelector({ @@ -29,9 +25,6 @@ export function GroupingSelector({ onChangeTimeInterval, onChangeDateVarient, groupingKeys, - iconRef, - popoverRef, - close, }: GroupingSelectorProps): JSX.Element | null { const { data } = useQuery(['garden', ...groupingKeys, timeInterval, dateVariant, context], { refetchOnWindowFocus: false, @@ -44,14 +37,6 @@ export function GroupingSelector({ const selectorRef = useRef(null); - useOutsideClick( - () => { - close(); - }, - popoverRef, - iconRef - ); - const setGardenKey = (key: string) => { const foundGroupingOption = data?.allGroupingOptions.find((option) => option.groupingKey === key); if (!foundGroupingOption) { @@ -88,58 +73,75 @@ export function GroupingSelector({ } return ( - - option.groupingKey)} - label={'Column headers'} - hideClearButton - multiple={false} - selectedOptions={[groupingKeys[0]]} - onOptionsChange={(changes) => handleGardenKeyChange(changes.selectedItems[0])} - /> - {data.allGroupingOptions.map( - (groupingOption) => + <> + Groups + + + option.groupingKey)} + label={'Group by'} + hideClearButton + multiple={false} + selectedOptions={[groupingKeys[0]]} + onOptionsChange={(changes) => handleGardenKeyChange(changes.selectedItems[0])} + /> + handleExistingSelectionChange(changes.selectedItems[0])} + /> + + + {data.allGroupingOptions.map((groupingOption) => { + // Check if dateVariant or timeInterval is defined + const hasDateVariant = !!groupingOption.dateVariant; + const hasTimeInterval = !!groupingOption.timeInterval; + + if (!hasDateVariant && !hasTimeInterval) return null; + + return ( groupingOption.groupingKey === groupingKeys[0] && ( - - - {groupingOption.timeInterval && - groupingOption.timeInterval.map((dim) => ( - onChangeTimeInterval(e.target.value)} - /> - ))} - - - {groupingOption.dateVariant && - groupingOption.dateVariant.map((typ) => ( - onChangeDateVarient(e.target.value)} - /> - ))} - - + <> + Views + + + Date Fields: + + {hasDateVariant && + groupingOption.dateVariant?.map((typ) => ( + onChangeDateVarient(e.target.value)} + /> + ))} + + Time Intervals: + + {hasTimeInterval && + groupingOption.timeInterval?.map((dim) => ( + onChangeTimeInterval(e.target.value)} + /> + ))} + + + ) - )} - - handleExistingSelectionChange(changes.selectedItems[0])} - /> - + ); + })} + ); } @@ -150,10 +152,18 @@ export const StyledAutoCompleteWrapper = styled.div` gap: 1em; `; +export const StyledGroupHeader = styled.div` + font-weight: 500px; + padding-top: 2rem; +`; +export const StyledSubGroupHeader = styled.div` + padding-left: 1rem; + padding-top: 1rem; +`; export const RadioWrapper = styled.div` display: flex; - align-items: center; - flex-direction: row; + align-items: start; + flex-direction: column; gap: 1em; `; diff --git a/packages/workspace-fusion/src/modules/garden/components/workspace-header/GardenViewSettings.tsx b/packages/workspace-fusion/src/modules/garden/components/workspace-header/GardenViewSettings.tsx deleted file mode 100644 index 300ed6bb0..000000000 --- a/packages/workspace-fusion/src/modules/garden/components/workspace-header/GardenViewSettings.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { Icon, Popover, CircularProgress } from '@equinor/eds-core-react'; -import { tokens } from '@equinor/eds-tokens'; -import { close, more_vertical } from '@equinor/eds-icons'; -import { FilterState } from '@equinor/workspace-filter'; - -import { useState, useRef, useEffect, Suspense } from 'react'; -import { createPortal } from 'react-dom'; -import { BehaviorSubject, distinctUntilChanged } from 'rxjs'; -import styled from 'styled-components'; -import { GroupingSelector } from '../GroupingSelector'; -import { GardenConfig } from '../../../../lib/integrations/garden'; -import { GardenMetaRequest } from '@equinor/workspace-garden'; - -Icon.add({ close, more_vertical }); - -type GroupState = Required; - -type GardenPopoverItemProps = { - anchor: HTMLElement; - groupingKeys$: BehaviorSubject; - filterState: FilterState; - config: GardenConfig; - setGroupingKeys: (keys: string[]) => void; - onChangeTimeInterval: (timeInterval: string | null) => void; - onChangeDateVariant: (dateVariant: string | null) => void; -}; -export const GardenPopoverItem = ({ - anchor, - groupingKeys$, - onChangeTimeInterval, - onChangeDateVariant, - setGroupingKeys, - config, - filterState, -}: GardenPopoverItemProps) => { - const [isOpen, setIsOpen] = useState(false); - const pRef = useRef(null); - const [groupState, setGroupState] = useState(groupingKeys$.value); - const popoverRef = useRef(null); - - useEffect(() => { - const sub = groupingKeys$.pipe(distinctUntilChanged()).subscribe((r) => { - setGroupState(r); - }); - return () => sub.unsubscribe(); - }, [groupingKeys$]); - - return ( - <> - setIsOpen((s) => !s)} - /> - {createPortal( - - - - Garden settings - setIsOpen(false)} - /> - - - - }> - setIsOpen(false)} - popoverRef={popoverRef} - groupingKeys={groupState.groupingKeys} - setGroupingKeys={setGroupingKeys} - timeInterval={groupState.timeInterval} - onChangeTimeInterval={onChangeTimeInterval} - dateVariant={groupState.dateVariant} - onChangeDateVarient={onChangeDateVariant} - context={filterState} - dataSource={config} - /> - - - , - anchor - )} - - ); -}; - -const StyledPopoverHeaderLine = styled.div` - display: flex; - width: 100%; - justify-content: space-between; - align-items: center; -`; - -const GroupingSelectorLoading = () => { - return ( - - - - ); -}; - -export const StyledLoadingWrapper = styled.div` - display: flex; - align-items: center; - flex-direction: column; - gap: 1em; - width: 268px; - height: 300px; - justify-content: center; -`; diff --git a/packages/workspace-fusion/src/modules/garden/components/wrapper/GardenWrapper.tsx b/packages/workspace-fusion/src/modules/garden/components/wrapper/GardenWrapper.tsx index eff869d63..f2d88178a 100644 --- a/packages/workspace-fusion/src/modules/garden/components/wrapper/GardenWrapper.tsx +++ b/packages/workspace-fusion/src/modules/garden/components/wrapper/GardenWrapper.tsx @@ -1,15 +1,15 @@ +import { Button, Icon } from '@equinor/eds-core-react'; +import { arrow_back_ios, arrow_forward_ios } from '@equinor/eds-icons'; import { FilterState, useFilterContext } from '@equinor/workspace-filter'; import { Garden } from '@equinor/workspace-garden'; import { useEffect, useRef, useState } from 'react'; -import { GardenConfig } from '../../../../lib/integrations/garden'; -import { GetIdentifier } from '../../../../lib/types/configuration'; -import { HeaderIcon, useWorkspaceHeaderComponents } from '../../../../lib'; -import { Icon } from '@equinor/eds-core-react'; -import { more_vertical } from '@equinor/eds-icons'; import { BehaviorSubject } from 'rxjs'; -import { GardenPopoverItem } from '../workspace-header/GardenViewSettings'; +import styled from 'styled-components'; import { useWorkspace } from '../../../../lib/hooks'; -Icon.add({ more_vertical }); +import { GardenConfig } from '../../../../lib/integrations/garden'; +import { GetIdentifier } from '../../../../lib/types/configuration'; +import { GroupingSelector } from '../GroupingSelector'; +Icon.add({ arrow_back_ios, arrow_forward_ios }); type GardenWrapperProps, TFilter = undefined> = { config: GardenConfig; @@ -22,13 +22,14 @@ export const GardenWrapper = , TFilte }: GardenWrapperProps) => { const { filterState } = useFilterContext(); const { selectItem } = useWorkspace(); + const [groupingKeys, setGroupingKeys] = useState(config.initialGrouping); + const [toggle, setToggle] = useState(false); const [timeInterval, updateTimeInterval] = useState(config.initialTimeInterval ?? null); const onChangetimeInterval = (timeInterval: string | null) => { updateTimeInterval(timeInterval); }; - const [dateVariant, updateDateVariant] = useState(config.initialDateVariant ?? null); const onChangeDateVariant = (dateVariant: string | null) => { updateDateVariant(dateVariant); @@ -37,47 +38,13 @@ export const GardenWrapper = , TFilte const groupingKeys$ = useRef(new BehaviorSubject({ groupingKeys, timeInterval, dateVariant })); useEffect(() => { - /** - * You might not need an effect - * Yes you do! - */ groupingKeys$.current.next({ groupingKeys, timeInterval, dateVariant }); }, [groupingKeys, timeInterval, dateVariant]); - const { setIcons } = useWorkspaceHeaderComponents(); - - useEffect(() => { - const icon: HeaderIcon = { - Icon: ({ anchor }) => ( - } - filterState={filterState} - anchor={anchor} - groupingKeys$={groupingKeys$.current} - setGroupingKeys={setGroupingKeys} - onChangeTimeInterval={onChangetimeInterval} - onChangeDateVariant={onChangeDateVariant} - /> - ), - name: 'garden-grouping', - placement: 'right', - type: 'button', - }; - setIcons((s) => [...s, icon]); - - return () => { - setIcons((s) => s.filter((y) => y.name !== icon.name)); - }; - - /** - * Dep array should contain grouping keys but that would result in the popover closing everytime you change the key, have to pass as observable to prevent this behaviour - */ - }, []); - const { selection } = useWorkspace(); return ( -
+
dataSource={{ ...config }} context={filterState as TFilter} @@ -95,6 +62,57 @@ export const GardenWrapper = , TFilte }, }} /> + + {toggle ? ( + <> +
+ +

View Settings

+
+ } + /> + + ) : ( + <> + + View Settings + + )} +
); }; + +type StyledAnimatedDivProps = { + expanded: boolean; +}; + +const StyledAnimatedDiv = styled.div` + width: ${(props) => (props.expanded ? '300px' : '45px')}; + box-shadow: -2px 0px 5px rgba(0, 0, 0, 0.1); + margin-left: 10px; + padding: 10px; + transition: width 0.1s ease; + overflow: hidden; +`; +const VerticalText = styled.div` + transform: rotate(90deg); + white-space: nowrap; + display: flex; + align-items: center; + margin-top: 3rem; + justify-content: center; + font-size: 16px; +`;