Skip to content

Commit

Permalink
Add indent settings for entry
Browse files Browse the repository at this point in the history
- Refactor list grouping
  • Loading branch information
tnagorra committed Sep 7, 2024
1 parent 37de554 commit 7f0425d
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 78 deletions.
21 changes: 12 additions & 9 deletions src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,13 @@ export function sortByAttributes<LIST_ITEM, ATTRIBUTE>(
attributes: ATTRIBUTE[],
sortFn: (a: LIST_ITEM, b: LIST_ITEM, attr: ATTRIBUTE) => number,
): LIST_ITEM[] {
if (attributes.length <= 0) {
return list;
}

const newList = [...list];
newList.sort(
(a, b) => {
let sortResult = 0;

for (let i = 0; i < attributes.length; i += 1) {
const currentSortResult = sortFn(
a,
Expand All @@ -236,20 +238,18 @@ export function sortByAttributes<LIST_ITEM, ATTRIBUTE>(
);

if (currentSortResult !== 0) {
sortResult = currentSortResult;
break;
return currentSortResult;
}
}

return sortResult;
return 0;
},
);

return newList;
}

type GroupedItem<LIST_ITEM, ATTRIBUTE> = {
key: string;
groupKey: string;
type: 'heading';
value: LIST_ITEM;
attribute: ATTRIBUTE;
Expand All @@ -265,19 +265,21 @@ export function groupListByAttributes<LIST_ITEM, ATTRIBUTE>(
list: LIST_ITEM[],
attributes: ATTRIBUTE[],
compareItemAttributes: (a: LIST_ITEM, b: LIST_ITEM, attribute: ATTRIBUTE) => boolean,
getGroupKey: (item: LIST_ITEM, attributes: ATTRIBUTE[]) => string,
): GroupedItem<LIST_ITEM, ATTRIBUTE>[] {
if (isNotDefined(list) || list.length === 0) {
return [];
}

const groupedItems = list.flatMap((listItem, listIndex) => {
if (listIndex === 0) {
const groupKey = getGroupKey(listItem, attributes);
const headings = attributes.map((attribute, i) => ({
type: 'heading' as const,
value: listItem,
attribute,
level: i,
key: `heading-${listIndex}-${i}`,
groupKey,
}));

return [
Expand Down Expand Up @@ -311,6 +313,7 @@ export function groupListByAttributes<LIST_ITEM, ATTRIBUTE>(
];
}

const groupKey = getGroupKey(listItem, attributes);
const headings = attributes.map((attribute, i) => {
if (i < attributeMismatchIndex) {
return undefined;
Expand All @@ -321,7 +324,7 @@ export function groupListByAttributes<LIST_ITEM, ATTRIBUTE>(
value: listItem,
attribute,
level: i,
key: `heading-${listIndex}-${i}`,
groupKey,
};
}).filter(isDefined);

Expand Down
1 change: 1 addition & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const defaultConfigValue: ConfigStorage = {
defaultTaskType: undefined,
defaultTaskStatus: 'DONE',
editingMode: 'normal',
indent: true,
compactTextArea: false,
checkboxForStatus: false,
startSidebarShown: window.innerWidth >= 900,
Expand Down
13 changes: 9 additions & 4 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export type WorkItemStatus = TimeEntryStatusEnum;
export type WorkItem = Omit<TimeEntryBulkCreateInput, 'clientId'> & { clientId: string };

export type DailyJournalAttributeKeys = 'project' | 'contract' | 'task' | 'status';
export interface DailyJournalAttributeOrder {
export interface DailyJournalAttribute {
key: DailyJournalAttributeKeys;
sortDirection: number;
}
Expand All @@ -36,13 +36,18 @@ export interface DailyJournalGrouping {
export type ConfigStorage = {
defaultTaskType: WorkItemType | undefined,
defaultTaskStatus: WorkItemStatus,

editingMode: EditingMode,

checkboxForStatus: boolean,
startSidebarShown: boolean,
endSidebarShown: boolean,
compactTextArea: boolean,
dailyJournalAttributeOrder: DailyJournalAttributeOrder[];
indent: boolean,

dailyJournalAttributeOrder: DailyJournalAttribute[];
dailyJournalGrouping: DailyJournalGrouping;

startSidebarShown: boolean,
endSidebarShown: boolean,
}

export interface GeneralEvent {
Expand Down
2 changes: 1 addition & 1 deletion src/views/DailyJournal/AddWorkItemDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function AddWorkItemDialog(props: Props) {
focusElementRef={titleInputRef}
>
<div>
Please select a task to add the workitems
Please select a task to add new entry
</div>
<TextInput
inputElementRef={titleInputRef}
Expand Down
2 changes: 1 addition & 1 deletion src/views/DailyJournal/AddWorkItemDialog/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
}

&:hover {
background-color: var(--color-background);
background-color: var(--color-tertiary);
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions src/views/DailyJournal/DayView/WorkItemRow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ function WorkItemRow(props: Props) {
onChange,
} = props;

console.log(workItem, contractId);

const { enums } = useContext(EnumsContext);
const { screen } = useContext(SizeContext);

Expand Down
133 changes: 76 additions & 57 deletions src/views/DailyJournal/DayView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
sortByAttributes,
} from '#utils/common';
import {
DailyJournalAttributeOrder,
DailyJournalAttribute,
EntriesAsList,
WorkItem,
} from '#utils/types';
Expand Down Expand Up @@ -71,9 +71,9 @@ function DayView(props: Props) {

const [storedConfig] = useLocalStorage('timur-config');

const getWorkItemAttribute = useCallback((
const getWorkItemLabelFromAttr = useCallback((
item: WorkItem,
attr: DailyJournalAttributeOrder,
attr: DailyJournalAttribute,
) => {
if (attr.key === 'status') {
return item.status;
Expand Down Expand Up @@ -102,6 +102,7 @@ function DayView(props: Props) {

const formattedDate = dateFormatter.format(new Date(selectedDate));
const formattedRelativeDate = useFormattedRelativeDate(selectedDate);

const totalHours = useMemo(
() => {
if (isDefined(workItems)) {
Expand All @@ -115,11 +116,13 @@ function DayView(props: Props) {

const {
dailyJournalAttributeOrder,
dailyJournalGrouping,
dailyJournalGrouping: {
groupLevel,
joinLevel,
},
indent,
} = storedConfig;

const { groupLevel, joinLevel } = dailyJournalGrouping;

const groupedItems = useMemo(() => {
if (isNotDefined(taskById) || isNotDefined(workItems)) {
return [];
Expand All @@ -130,8 +133,8 @@ function DayView(props: Props) {
dailyJournalAttributeOrder,
(a, b, attr) => (
compareString(
getWorkItemAttribute(a, attr),
getWorkItemAttribute(b, attr),
getWorkItemLabelFromAttr(a, attr),
getWorkItemLabelFromAttr(b, attr),
attr.sortDirection,
)
),
Expand All @@ -141,16 +144,20 @@ function DayView(props: Props) {
sortedWorkItems,
dailyJournalAttributeOrder.slice(0, groupLevel),
(a, b, attr) => {
const aValue = getWorkItemAttribute(a, attr);
const bValue = getWorkItemAttribute(b, attr);
const aValue = getWorkItemLabelFromAttr(a, attr);
const bValue = getWorkItemLabelFromAttr(b, attr);

return aValue === bValue;
},
(item, attrs) => {
const values = attrs.map((attr) => getWorkItemLabelFromAttr(item, attr)).join(';');
return values;
},
);
}, [
taskById,
workItems,
getWorkItemAttribute,
getWorkItemLabelFromAttr,
dailyJournalAttributeOrder,
groupLevel,
]);
Expand Down Expand Up @@ -185,75 +192,87 @@ function DayView(props: Props) {
<div className={styles.newGroup}>
{groupedItems.map((groupedItem) => {
if (groupedItem.type === 'heading') {
const levelDiff = groupLevel - joinLevel;

const headingText = getWorkItemAttribute(
groupedItem.value,
groupedItem.attribute,
);
// Main Heading
// NOTE: Need to add 1 as groupLevel and level starts from 1 and 0 resp.
if (groupedItem.level + 1 < (groupLevel - joinLevel + 1)) {
const headingText = getWorkItemLabelFromAttr(
groupedItem.value,
groupedItem.attribute,
);

if (groupedItem.level < levelDiff) {
const Heading = `h${bound(groupedItem.level + 2, 2, 4)}` as unknown as ElementType;

return (
<Heading
key={groupedItem.key}
key={`heading-${groupedItem.attribute.key}-of-${groupedItem.groupKey}`}
className={styles.nestedHeading}
>
<Indent level={groupedItem.level} />
{indent && <Indent level={groupedItem.level} />}
{headingText}
</Heading>
);
}

if (groupedItem.level < (groupLevel - 1)) {
return null;
// Sub Headings
// NOTE: We only need to show one subheading after the main headings
// NOTE: Need to add 1 as groupLevel and level starts from 1 and 0 resp.
if (groupedItem.level + 1 === groupLevel) {
return (
<h4
className={styles.joinedHeading}
key={`sub-heading-group-of-${groupedItem.groupKey}`}
>
{indent && (
<Indent
level={groupedItem.level - joinLevel + 1}
/>
)}
{dailyJournalAttributeOrder.map((attribute, i) => {
if (i >= groupLevel) {
return null;
}

const currentLabel = getWorkItemLabelFromAttr(
groupedItem.value,
attribute,
);

if (i < (groupLevel - joinLevel)) {
return null;
}

return (
<Fragment key={`subheading-${attribute.key}-of-${groupedItem.groupKey}`}>
{i > (groupLevel - joinLevel) && (
<div className={styles.separator} />
)}
<div>{currentLabel}</div>
</Fragment>
);
})}
</h4>
);
}

return (
<h4
className={styles.joinedHeading}
key={groupedItem.key}
>
<Indent level={groupedItem.level - joinLevel + 1} />
{dailyJournalAttributeOrder.map((attribute, i) => {
if (i >= groupLevel) {
return null;
}

const currentLabel = getWorkItemAttribute(
groupedItem.value,
attribute,
);

if (i < (groupLevel - joinLevel)) {
return null;
}

return (
<Fragment key={attribute.key}>
{i > (groupLevel - joinLevel) && (
<div className={styles.separator} />
)}
<div>{currentLabel}</div>
</Fragment>
);
})}
</h4>
);
return null;
}

const taskDetails = taskById?.[groupedItem.value.task];

if (!taskDetails) {
return null;
}

return (
<div className={styles.workItemContainer}>
<Indent level={groupedItem.level - joinLevel} />
<div
className={styles.workItemContainer}
key={groupedItem.value.clientId}
>
{indent && (
<Indent
level={groupedItem.level - joinLevel + 1}
/>
)}
<WorkItemRow
key={groupedItem.value.clientId}
className={styles.workItem}
workItem={groupedItem.value}
onClone={onWorkItemClone}
Expand Down
Loading

0 comments on commit 7f0425d

Please sign in to comment.