Skip to content

Commit

Permalink
Add table of content selection and sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
subinasr authored and AdityaKhatri committed Sep 7, 2023
1 parent af828ba commit bd915a4
Show file tree
Hide file tree
Showing 22 changed files with 1,174 additions and 484 deletions.
15 changes: 13 additions & 2 deletions src/components/PillarSelectInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ const PILLARS = gql`
name
type
category1
category1Display
category2
category2Display
category3
category3Display
category4
category4Display
order
}
}
Expand All @@ -32,7 +36,12 @@ const PILLARS = gql`
type Pillar = NonNullable<NonNullable<NonNullable<PillarsQuery['private']>['projectScope']>['questionnaire']>['leafGroups'][number];

const pillarKeySelector = (data: Pillar) => data.id;
const pillarLabelSelector = (data: Pillar) => data.name;
const pillarLabelSelector = (data: Pillar) => {
if (data.type === 'MATRIX_1D') {
return data.category2Display ?? '';
}
return data.category4Display ?? '';
};

interface PillarProps<T>{
projectId: string;
Expand All @@ -41,6 +50,7 @@ interface PillarProps<T>{
value: string | null | undefined;
error: string | undefined;
onChange: (value: string | undefined, name: T) => void;
disabled?: boolean;
}

function PillarSelectInput<T extends string>(props: PillarProps<T>) {
Expand All @@ -51,6 +61,7 @@ function PillarSelectInput<T extends string>(props: PillarProps<T>) {
error,
onChange,
name,
disabled,
} = props;

const pillarsVariables = useMemo(() => {
Expand Down Expand Up @@ -89,7 +100,7 @@ function PillarSelectInput<T extends string>(props: PillarProps<T>) {
keySelector={pillarKeySelector}
labelSelector={pillarLabelSelector}
options={pillarsOptions}
disabled={pillarsLoading}
disabled={pillarsLoading || disabled}
/>
);
}
Expand Down
21 changes: 16 additions & 5 deletions src/components/TocList/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,29 @@

.group-item {
display: flex;
padding: var(--dui-spacing-small);
background-color: transparent;
padding: var(--dui-spacing-medium) var(--dui-spacing-small);
padding-right: 0;

.group-item {
border-left: var(--dui-width-separator-medium) solid var(--dui-color-separator);
}
.heading {
font-weight: var(--dui-font-weight-regular);
}

.header {
background-color: transparent;
.heading {
color: var(--text-color-dark);
}
}
.header-icons {
display: flex;
align-items: center;
padding-right: var(--dui-spacing-extra-small);
}

.heading {
font-weight: var(--dui-font-weight-regular);
}

.content {
display: flex;
flex-direction: column;
Expand Down
170 changes: 110 additions & 60 deletions src/components/TocList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,137 @@
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import {
GrDrag,
} from 'react-icons/gr';
import {
isNotDefined,
// isNotDefined,
_cs,
isDefined,
} from '@togglecorp/fujs';
import {
ExpandableContainer,
Container,
Checkbox,
QuickActionButton,
} from '@the-deep/deep-ui';
import SortableList, { Attributes, Listeners } from '#components/SortableList';
import {
TocItem,
getChildren,
} from '#utils/common';

import styles from './index.module.css';

type QuestionGroup = {
key: string;
parentKeys: string[];
label: string;
nodes: QuestionGroup[];
};

interface TocProps {
key: string;
itemKey: string;
mainIndex: number;
item: QuestionGroup;
item: TocItem;
attributes?: Attributes;
listeners?: Listeners;
onOrderedOptionsChange: (newVal: TocItem[] | undefined, index: number) => void;

selectedGroups: string[];
onOrderedOptionsChange: (newVal: QuestionGroup[] | undefined, index: number) => void;
onSelectedGroupsChange: React.Dispatch<React.SetStateAction<string[]>>;
onActiveTabChange: React.Dispatch<React.SetStateAction<string | undefined>>;
onSelectedGroupsChange: (newValue: boolean, id: string[]) => void;
// onActiveTabChange: React.Dispatch<React.SetStateAction<string | undefined>>;
}

function TocRenderer(props: TocProps) {
const {
key,
itemKey,
mainIndex,
item,
selectedGroups,
onOrderedOptionsChange,
onSelectedGroupsChange,
onActiveTabChange,
// onActiveTabChange,
attributes,
listeners,
} = props;

const handleGroupSelect = useCallback((val: boolean) => {
onSelectedGroupsChange((oldVal) => {
if (val) {
return ([...oldVal, key]);
}
const newVal = [...oldVal];
newVal.splice(oldVal.indexOf(key), 1);

return newVal;
});
onActiveTabChange((oldActiveTab) => {
if (isNotDefined(oldActiveTab) && val) {
return key;
}
if (!val && oldActiveTab === key) {
return undefined;
}
return oldActiveTab;
});
if (!item.leafNode) {
const childIds = getChildren(item);
onSelectedGroupsChange(val, childIds);
return;
}

onSelectedGroupsChange(val, [item.id]);
}, [
onActiveTabChange,
item,
onSelectedGroupsChange,
key,
]);

const nodeList = item.nodes;
const nodeList = item.leafNode ? [] : item.nodes;

const handleListChange = useCallback((newVal: QuestionGroup[] | undefined) => {
const handleListChange = useCallback((newVal: TocItem[] | undefined) => {
onOrderedOptionsChange(newVal, mainIndex);
}, [
mainIndex,
onOrderedOptionsChange,
]);

const childIds = getChildren(item);
const inputValue = item.leafNode
? selectedGroups.includes(item.id)
: childIds.every((g) => selectedGroups.includes(g));

const indeterminate = item.leafNode
? false
: childIds.some((g) => selectedGroups.includes(g));

if (item.leafNode) {
return (
<Container
className={styles.groupItem}
headerIcons={(
<div className={styles.headerIcons}>
<QuickActionButton
name={itemKey}
// FIXME: use translation
title="Drag"
variant="transparent"
// eslint-disable-next-line react/jsx-props-no-spreading
{...attributes}
// eslint-disable-next-line react/jsx-props-no-spreading
{...listeners}
>
<GrDrag />
</QuickActionButton>
<Checkbox
name={item.key}
// FIXME: We are only handling childre for now
value={inputValue}
indeterminate={inputValue ? false : indeterminate}
onChange={handleGroupSelect}
/>
</div>
)}
contentClassName={styles.content}
heading={item.label}
headingClassName={styles.heading}
headingSize="extraSmall"
spacing="none"
>
{isDefined(nodeList) && nodeList.length > 0 && (
// eslint-disable-next-line @typescript-eslint/no-use-before-define
<TocList
className={styles.nestedList}
orderedOptions={nodeList}
onOrderedOptionsChange={handleListChange}
selectedGroups={selectedGroups}
onSelectedGroupsChange={onSelectedGroupsChange}
// onActiveTabChange={onActiveTabChange}
/>
)}
</Container>
);
}
return (
<Container
<ExpandableContainer
className={styles.groupItem}
headerIcons={(
<div className={styles.headerIcons}>
<QuickActionButton
name={key}
name={itemKey}
// FIXME: use translation
title="Drag"
variant="transparent"
Expand All @@ -101,7 +144,9 @@ function TocRenderer(props: TocProps) {
</QuickActionButton>
<Checkbox
name={item.key}
value={selectedGroups.includes(key)}
// FIXME: We are only handling childre for now
value={inputValue}
indeterminate={inputValue ? false : indeterminate}
onChange={handleGroupSelect}
/>
</div>
Expand All @@ -110,7 +155,9 @@ function TocRenderer(props: TocProps) {
heading={item.label}
headingClassName={styles.heading}
headingSize="extraSmall"
headerClassName={styles.header}
spacing="none"
withoutBorder
>
{isDefined(nodeList) && nodeList.length > 0 && (
// eslint-disable-next-line @typescript-eslint/no-use-before-define
Expand All @@ -120,22 +167,22 @@ function TocRenderer(props: TocProps) {
onOrderedOptionsChange={handleListChange}
selectedGroups={selectedGroups}
onSelectedGroupsChange={onSelectedGroupsChange}
onActiveTabChange={onActiveTabChange}
// onActiveTabChange={onActiveTabChange}
/>
)}
</Container>
</ExpandableContainer>
);
}

const keySelector = (g: QuestionGroup) => g.key;
const keySelector = (g: TocItem) => g.key;

interface Props {
className?: string;
orderedOptions: QuestionGroup[] | undefined;
onOrderedOptionsChange: (newVal: QuestionGroup[] | undefined) => void;
orderedOptions: TocItem[] | undefined;
onOrderedOptionsChange: (newVal: TocItem[] | undefined) => void;
selectedGroups: string[];
onSelectedGroupsChange: React.Dispatch<React.SetStateAction<string[]>>;
onActiveTabChange: React.Dispatch<React.SetStateAction<string | undefined>>;
onSelectedGroupsChange: (newValue: boolean, id: string[]) => void;
// onActiveTabChange: React.Dispatch<React.SetStateAction<string | undefined>>;
}

function TocList(props: Props) {
Expand All @@ -145,44 +192,47 @@ function TocList(props: Props) {
onOrderedOptionsChange,
selectedGroups,
onSelectedGroupsChange,
onActiveTabChange,
// onActiveTabChange,
} = props;

const handleChildrenOrderChange = useCallback((
newValue: QuestionGroup[] | undefined,
newValue: TocItem[] | undefined,
parentIndex: number,
) => {
if (!newValue) {
return;
}
const newList = [...orderedOptions ?? []];
newList[parentIndex] = {
...newList[parentIndex],
nodes: newValue,
};
onOrderedOptionsChange(newList);
const node = orderedOptions?.[parentIndex];
if (node && !node.leafNode) {
const newList = [...orderedOptions];
newList[parentIndex] = {
...node,
nodes: newValue,
};
onOrderedOptionsChange(newList);
}
}, [
orderedOptions,
onOrderedOptionsChange,
]);

const tocRendererParams = useCallback((
key: string,
datum: QuestionGroup,
datum: TocItem,
mainIndex: number,
): TocProps => ({
onOrderedOptionsChange: handleChildrenOrderChange,
onSelectedGroupsChange,
onActiveTabChange,
// onActiveTabChange,
selectedGroups,
key,
itemKey: key,
mainIndex,
item: datum,
}), [
handleChildrenOrderChange,
selectedGroups,
onSelectedGroupsChange,
onActiveTabChange,
// onActiveTabChange,
]);

return (
Expand Down
Loading

0 comments on commit bd915a4

Please sign in to comment.