Skip to content

Commit

Permalink
composition compare fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
luvkapur committed Apr 19, 2023
1 parent 204b89c commit 42b98c0
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,45 +1,49 @@
.dropdownContainer {
.toolbar {
display: flex;
background-color: var(--bit-bg-heaviest, #ededed);
padding: 8px;
}

.leftDropdown {
.left,
.right {
display: flex;
flex: 1;
padding: 16px;
}

.rightDropdown {
display: flex;
flex: 1;
padding: 16px 16px 16px 0px;
padding: 8px;
background-color: #fff;
align-items: center;
justify-content: space-between;
}

.mainContainer {
display: flex;
height: 100%;
min-height: 80vh;
}

.subContainerLeft {
flex: 1;
background-color: #ededed;
padding: 16px;
}

.subContainerRight {
flex: 1;
background-color: #ededed;
padding: 16px 16px 16px 0px;
}

.subView {
height: 100%;
background-color: white;
overflow-y: scroll;
overflow-y: auto;
}

.loader {
display: flex;
align-items: center;
height: 100%;
}

.widgets {
display: flex;
}

.dropdown {
display: flex;
}
127 changes: 84 additions & 43 deletions scopes/compositions/ui/composition-compare/composition-compare.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,92 @@
/* eslint-disable react/prop-types */
import { useComponentCompare } from '@teambit/component.ui.component-compare.context';
import { CompositionContent, CompositionContentProps, EmptyStateSlot } from '@teambit/compositions';
import { CompositionContextProvider } from '@teambit/compositions.ui.hooks.use-composition';
import { CompareSplitLayoutPreset } from '@teambit/component.ui.component-compare.layouts.compare-split-layout-preset';
import {
useCompareQueryParam,
useUpdatedUrlFromQuery,
} from '@teambit/component.ui.component-compare.hooks.use-component-compare-url';
import { ComponentModel } from '@teambit/component';
import { CompareSplitLayoutPreset } from '@teambit/component.ui.component-compare.layouts.compare-split-layout-preset';
import { RoundLoader } from '@teambit/design.ui.round-loader';
import queryString from 'query-string';
import React, { useMemo, useState } from 'react';
import styles from './composition-compare.module.scss';
import { CompositionDropdown } from './composition-dropdown';

import styles from './composition-compare.module.scss';

export type CompositionCompareProps = {
emptyState?: EmptyStateSlot;
Widgets?: {
Right?: React.ReactNode;
Left?: React.ReactNode;
};
PreviewView?: React.ComponentType<CompositionContentProps>;
};

export function CompositionCompare(props: CompositionCompareProps) {
const { emptyState, PreviewView = CompositionContent } = props;
const { emptyState, PreviewView = CompositionContent, Widgets } = props;

const component = useComponentCompare();
const componentCompareContext = useComponentCompare();

const base = component?.base;
const compare = component?.compare;
const { base, compare, baseContext, compareContext } = componentCompareContext || {};

const baseCompositions = base?.model.compositions;
const compareCompositions = compare?.model.compositions;

const selectedCompositionBaseFile = useCompareQueryParam('compositionBaseFile');
const selectedCompositionCompareFile = useCompareQueryParam('compositionCompareFile');

const baseState = baseContext?.state?.preview;
const compareState = compareContext?.state?.preview;
const baseHooks = baseContext?.hooks?.preview;
const compareHooks = compareContext?.hooks?.preview;
const selectedBaseFromState = baseState?.id;
const selectedCompareFromState = compareState?.id;

const selectedBaseCompositionId = selectedBaseFromState || selectedCompositionBaseFile;
const selectedCompositionCompareId = selectedCompareFromState || selectedCompositionCompareFile;

const selectedBaseComp =
(selectedCompositionBaseFile &&
(selectedBaseCompositionId &&
baseCompositions &&
baseCompositions.find((c) => c.identifier === selectedCompositionBaseFile)) ||
baseCompositions.find((c) => {
return c.identifier === selectedBaseCompositionId;
})) ||
(baseCompositions && baseCompositions[0]);

const selectedCompareComp =
(selectedCompositionCompareFile &&
(selectedCompositionCompareId &&
compareCompositions &&
compareCompositions.find((c) => c.identifier === selectedCompositionCompareFile)) ||
compareCompositions.find((c) => {
return c.identifier === selectedCompositionCompareId;
})) ||
(compareCompositions && compareCompositions[0]);

const baseCompositionDropdownSource =
baseCompositions?.map((c) => {
const href = useUpdatedUrlFromQuery({
compositionBaseFile: c.identifier,
compositionCompareFile: selectedCompareComp?.identifier,
});

return { id: c.identifier, label: c.displayName, value: href };
const href = !baseState?.controlled
? useUpdatedUrlFromQuery({
compositionBaseFile: c.identifier,
compositionCompareFile: selectedCompareComp?.identifier,
})
: useUpdatedUrlFromQuery({});
const onClick = baseState?.controlled ? baseHooks?.onClick : undefined;

return { id: c.identifier, label: c.displayName, href, onClick };
}) || [];

const compareCompositionDropdownSource =
compareCompositions?.map((c) => {
const href = useUpdatedUrlFromQuery({
compositionBaseFile: selectedBaseComp?.identifier,
compositionCompareFile: c.identifier,
});
return { id: c.identifier, label: c.displayName, value: href };
const href = !compareState?.controlled
? useUpdatedUrlFromQuery({
compositionBaseFile: selectedBaseComp?.identifier,
compositionCompareFile: c.identifier,
})
: useUpdatedUrlFromQuery({});
const onClick = compareState?.controlled ? compareHooks?.onClick : undefined;

return { id: c.identifier, label: c.displayName, href, onClick };
}) || [];

const [baseCompositionParams, setBaseCompositionParams] = useState<Record<string, any>>({});
Expand All @@ -81,72 +109,85 @@ export function CompositionCompare(props: CompositionCompareProps) {
};

const BaseLayout = useMemo(() => {
if (component?.base === undefined) {
if (base === undefined) {
return <></>;
}
const baseCompModel = base.model;

return (
<div className={styles.subView}>
<CompositionContextProvider queryParams={baseCompositionParams} setQueryParams={setBaseCompositionParams}>
<PreviewView
emptyState={emptyState}
component={component?.base.model}
component={baseCompModel}
selected={selectedBaseComp}
queryParams={baseCompQueryParams}
/>
</CompositionContextProvider>
</div>
);
}, [component?.base, selectedBaseComp]);
}, [base, selectedBaseComp]);

const CompareLayout = useMemo(() => {
if (component?.compare === undefined) {
if (compare === undefined) {
return <></>;
}
const compareCompModel = compare.model;

return (
<div className={styles.subView}>
<CompositionContextProvider queryParams={compareCompositionParams} setQueryParams={setCompareCompositionParams}>
<PreviewView
emptyState={emptyState}
component={component.compare.model}
component={compareCompModel}
selected={selectedCompareComp}
queryParams={compareCompQueryParams}
/>
</CompositionContextProvider>
</div>
);
}, [component?.compare, selectedCompareComp]);
}, [compare, selectedCompareComp]);

function CompositionDropdowns() {
if (baseCompositionDropdownSource.length < 0 && compareCompositionDropdownSource.length < 0) {
return <></>;
const CompositionToolbar = () => {
if (!base && !compare) {
return null;
}

return (
<div className={styles.dropdownContainer}>
<div className={styles.leftDropdown}>
{baseCompositionDropdownSource.length > 0 && (
<CompositionDropdown dropdownItems={baseCompositionDropdownSource} selected={selectedBaseDropdown} />
)}
</div>
<div className={styles.rightDropdown}>
{compareCompositionDropdownSource.length > 0 && (
<CompositionDropdown dropdownItems={compareCompositionDropdownSource} selected={selectedCompareDropdown} />
)}
<div className={styles.toolbar}>
{base && (
<div className={styles.left}>
<div className={styles.dropdown}>
{baseCompositionDropdownSource.length > 0 && (
<CompositionDropdown dropdownItems={baseCompositionDropdownSource} selected={selectedBaseDropdown} />
)}
</div>
<div className={styles.widgets}>{Widgets?.Left}</div>
</div>
)}
<div className={styles.right}>
<div className={styles.dropdown}>
{compareCompositionDropdownSource.length > 0 && (
<CompositionDropdown
dropdownItems={compareCompositionDropdownSource}
selected={selectedCompareDropdown}
/>
)}
</div>
<div className={styles.widgets}>{Widgets?.Right}</div>
</div>
</div>
);
}
};

return (
<>
{component?.loading && (
{componentCompareContext?.loading && (
<div className={styles.loader}>
<RoundLoader />
</div>
)}
<CompositionDropdowns />
<CompositionToolbar />
<CompareSplitLayoutPreset base={BaseLayout} compare={CompareLayout} />
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useEffect, useRef } from 'react';
import { MenuLinkItem } from '@teambit/design.ui.surfaces.menu.link-item';
import { Icon } from '@teambit/evangelist.elements.icon';
import { Dropdown } from '@teambit/evangelist.surfaces.dropdown';
import React, { useEffect, useRef } from 'react';

import styles from './composition-dropdown.module.scss';

export type DropdownItem = { id: string; label: string; value: string };
export type DropdownItem = { id: string; label: string; href?: string; onClick?: (id: string, e) => void };

export type CompositionDropdownProps = {
selected?: Omit<DropdownItem, 'value'>;
Expand All @@ -13,6 +14,7 @@ export type CompositionDropdownProps = {

export function CompositionDropdown(props: CompositionDropdownProps) {
const { selected, dropdownItems: data } = props;
const key = (item: DropdownItem) => `${item.id}-${item.href}`;

return (
<Dropdown
Expand All @@ -25,7 +27,7 @@ export function CompositionDropdown(props: CompositionDropdownProps) {
}
>
{data.map((item) => {
return <MenuItem key={item.id} current={item} selected={selected} />;
return <MenuItem key={key(item)} current={item} selected={selected} />;
})}
</Dropdown>
);
Expand All @@ -41,15 +43,18 @@ function MenuItem(props: MenuItemProps) {

const isCurrent = selected?.id === current.id;
const currentVersionRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (isCurrent) {
currentVersionRef.current?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
}
}, [isCurrent]);

const onClick = (!!current.onClick && ((e) => current.onClick?.(current.id, e))) || undefined;

return (
<div ref={currentVersionRef}>
<MenuLinkItem active={current.id === selected?.id} href={current.value}>
<div ref={currentVersionRef} key={`${current.href}-container`}>
<MenuLinkItem key={current.href} active={current.id === selected?.id} href={current.href} onClick={onClick}>
<div>{current.label}</div>
</MenuLinkItem>
</div>
Expand Down

0 comments on commit 42b98c0

Please sign in to comment.