From 9ed0922e8c422ac196ceaceda85eb8acf4b3e033 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Wed, 5 Jan 2022 14:24:22 -0700 Subject: [PATCH] GH-2007 Use VisiblePropertyIds for view property order (#2010) * update for views to use viewPropertyIds for order * build fixes Co-authored-by: Mattermod --- .../src/components/calendar/fullCalendar.tsx | 2 +- webapp/src/components/gallery/gallery.tsx | 4 ++- webapp/src/components/kanban/kanban.tsx | 3 +- .../src/components/table/tableHeaderMenu.tsx | 10 ++++-- webapp/src/components/table/tableHeaders.tsx | 16 +++++----- webapp/src/components/table/tableRow.tsx | 12 ++++--- webapp/src/mutator.ts | 31 +++++++++++++++++-- 7 files changed, 58 insertions(+), 20 deletions(-) diff --git a/webapp/src/components/calendar/fullCalendar.tsx b/webapp/src/components/calendar/fullCalendar.tsx index f82d8985d..f4139d691 100644 --- a/webapp/src/components/calendar/fullCalendar.tsx +++ b/webapp/src/components/calendar/fullCalendar.tsx @@ -66,7 +66,7 @@ const CalendarFullView = (props: Props): JSX.Element|null => { const isSelectable = !readonly const visiblePropertyTemplates = useMemo(() => ( - board.fields.cardProperties.filter((template: IPropertyTemplate) => activeView.fields.visiblePropertyIds.includes(template.id)) + activeView.fields.visiblePropertyIds.map((id) => board.fields.cardProperties.find((t) => t.id === id)).filter((i) => i) as IPropertyTemplate[] ), [board.fields.cardProperties, activeView.fields.visiblePropertyIds]) let {initialDate} = props diff --git a/webapp/src/components/gallery/gallery.tsx b/webapp/src/components/gallery/gallery.tsx index 692895f3c..582d91f37 100644 --- a/webapp/src/components/gallery/gallery.tsx +++ b/webapp/src/components/gallery/gallery.tsx @@ -25,7 +25,9 @@ type Props = { const Gallery = (props: Props): JSX.Element => { const {activeView, board, cards} = props - const visiblePropertyTemplates = board.fields.cardProperties.filter((template: IPropertyTemplate) => activeView.fields.visiblePropertyIds.includes(template.id)) + + const visiblePropertyTemplates = + activeView.fields.visiblePropertyIds.map((id) => board.fields.cardProperties.find((t) => t.id === id)).filter((i) => i) as IPropertyTemplate[] const isManualSort = activeView.fields.sortOptions.length === 0 const onDropToCard = (srcCard: Card, dstCard: Card) => { diff --git a/webapp/src/components/kanban/kanban.tsx b/webapp/src/components/kanban/kanban.tsx index 1346a3f3a..4dff4a13d 100644 --- a/webapp/src/components/kanban/kanban.tsx +++ b/webapp/src/components/kanban/kanban.tsx @@ -48,7 +48,8 @@ const Kanban = (props: Props) => { const propertyValues = groupByProperty.options || [] Utils.log(`${propertyValues.length} propertyValues`) - const visiblePropertyTemplates = board.fields.cardProperties.filter((template: IPropertyTemplate) => activeView.fields.visiblePropertyIds.includes(template.id)) + const visiblePropertyTemplates = + activeView.fields.visiblePropertyIds.map((id) => board.fields.cardProperties.find((t) => t.id === id)).filter((i) => i) as IPropertyTemplate[] const isManualSort = activeView.fields.sortOptions.length === 0 const propertyNameChanged = useCallback(async (option: IPropertyOption, text: string): Promise => { diff --git a/webapp/src/components/table/tableHeaderMenu.tsx b/webapp/src/components/table/tableHeaderMenu.tsx index f4eb51994..fb454ee44 100644 --- a/webapp/src/components/table/tableHeaderMenu.tsx +++ b/webapp/src/components/table/tableHeaderMenu.tsx @@ -5,7 +5,7 @@ import React, {FC} from 'react' import {useIntl} from 'react-intl' import {Constants} from '../../constants' -import {Board, IPropertyTemplate} from '../../blocks/board' +import {Board} from '../../blocks/board' import {BoardView} from '../../blocks/boardView' import {Card} from '../../blocks/card' import mutator from '../../mutator' @@ -42,7 +42,9 @@ const TableHeaderMenu: FC = (props: Props): JSX.Element => { // eslint-disable-next-line no-warning-comments // TODO: Handle name column } else { - const index = board.fields.cardProperties.findIndex((o: IPropertyTemplate) => o.id === templateId) + const index = activeView.fields.visiblePropertyIds.findIndex((i) => i === templateId) + + // const index = board.fields.cardProperties.findIndex((o: IPropertyTemplate) => o.id === templateId) mutator.insertPropertyTemplate(board, activeView, index) } }} @@ -55,7 +57,9 @@ const TableHeaderMenu: FC = (props: Props): JSX.Element => { // eslint-disable-next-line no-warning-comments // TODO: Handle title column } else { - const index = board.fields.cardProperties.findIndex((o: IPropertyTemplate) => o.id === templateId) + 1 + const index = activeView.fields.visiblePropertyIds.findIndex((i) => i === templateId) + 1 + + // const index = board.fields.cardProperties.findIndex((o: IPropertyTemplate) => o.id === templateId) + 1 mutator.insertPropertyTemplate(board, activeView, index) } }} diff --git a/webapp/src/components/table/tableHeaders.tsx b/webapp/src/components/table/tableHeaders.tsx index 98e67e8c6..76a121691 100644 --- a/webapp/src/components/table/tableHeaders.tsx +++ b/webapp/src/components/table/tableHeaders.tsx @@ -1,6 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useCallback} from 'react' +import React, {useCallback, useMemo} from 'react' import {FormattedMessage, useIntl} from 'react-intl' @@ -108,13 +108,17 @@ const TableHeaders = (props: Props): JSX.Element => { mutator.updateBlock(newView, activeView, 'autosize column') }, [activeView, board, cards]) + const visiblePropertyTemplates = useMemo(() => ( + activeView.fields.visiblePropertyIds.map((id) => board.fields.cardProperties.find((t) => t.id === id)).filter((i) => i) as IPropertyTemplate[] + ), [board.fields.cardProperties, activeView.fields.visiblePropertyIds]) + const onDropToColumn = useCallback(async (template: IPropertyTemplate, container: IPropertyTemplate) => { Utils.log(`ondrop. Source column: ${template.name}, dest column: ${container.name}`) // Move template to new index - const destIndex = container ? board.fields.cardProperties.indexOf(container) : 0 - await mutator.changePropertyTemplateOrder(board, template, destIndex >= 0 ? destIndex : 0) - }, [board]) + const destIndex = container ? activeView.fields.visiblePropertyIds.indexOf(container.id) : 0 + await mutator.changeViewVisiblePropertiesOrder(activeView, template, destIndex >= 0 ? destIndex : 0) + }, [activeView.fields.visiblePropertyIds]) const titleSortOption = activeView.fields.sortOptions?.find((o) => o.propertyId === Constants.titleColumnId) let titleSorted: 'up' | 'down' | 'none' = 'none' @@ -147,14 +151,12 @@ const TableHeaders = (props: Props): JSX.Element => { /> {/* Table header row */} - - {board.fields.cardProperties.filter((template: IPropertyTemplate) => activeView.fields.visiblePropertyIds.includes(template.id)).map((template: IPropertyTemplate) => { + {visiblePropertyTemplates.map((template) => { let sorted: 'up' | 'down' | 'none' = 'none' const sortOption = activeView.fields.sortOptions.find((o: ISortOption) => o.propertyId === template.id) if (sortOption) { sorted = sortOption.reversed ? 'down' : 'up' } - return ( { } }, []) + const visiblePropertyTemplates = useMemo(() => ( + activeView.fields.visiblePropertyIds.map((id) => board.fields.cardProperties.find((t) => t.id === id)).filter((i) => i) as IPropertyTemplate[] + ), [board.fields.cardProperties, activeView.fields.visiblePropertyIds]) + let className = props.isSelected ? 'TableRow octo-table-row selected' : 'TableRow octo-table-row' if (isOver) { className += ' dragover' @@ -121,8 +125,7 @@ const TableRow = React.memo((props: Props) => { {/* Columns, one per property */} - - {board.fields.cardProperties.filter((template: IPropertyTemplate) => activeView.fields.visiblePropertyIds.includes(template.id)).map((template: IPropertyTemplate) => { + {visiblePropertyTemplates.map((template) => { if (!columnRefs.get(template.id)) { columnRefs.set(template.id, React.createRef()) } @@ -142,7 +145,8 @@ const TableRow = React.memo((props: Props) => { propertyTemplate={template} showEmptyPlaceholder={false} /> - ) + + ) })} ) diff --git a/webapp/src/mutator.ts b/webapp/src/mutator.ts index 19b6b7ee8..325a53439 100644 --- a/webapp/src/mutator.ts +++ b/webapp/src/mutator.ts @@ -262,8 +262,9 @@ class Mutator { const oldBlocks: Block[] = [board] const newBoard = createBoard(board) - const startIndex = (index >= 0) ? index : board.fields.cardProperties.length - newBoard.fields.cardProperties.splice(startIndex, 0, newTemplate) + + // insert at end of board.fields.cardProperties + newBoard.fields.cardProperties.push(newTemplate) const changedBlocks: Block[] = [newBoard] let description = 'add property' @@ -272,7 +273,10 @@ class Mutator { oldBlocks.push(activeView) const newActiveView = createBoardView(activeView) - newActiveView.fields.visiblePropertyIds.push(newTemplate.id) + + // insert in proper location in activeview.fields.visiblePropetyIds + const viewIndex = index > 0 ? index : activeView.fields.visiblePropertyIds.length + newActiveView.fields.visiblePropertyIds.splice(viewIndex, 0, newTemplate.id) changedBlocks.push(newActiveView) description = 'add column' @@ -559,6 +563,27 @@ class Mutator { ) } + async changeViewVisiblePropertiesOrder(view: BoardView, template: IPropertyTemplate, destIndex: number, description = 'change property order'): Promise { + const oldVisiblePropertyIds = view.fields.visiblePropertyIds + const newOrder = oldVisiblePropertyIds.slice() + + const srcIndex = oldVisiblePropertyIds.indexOf(template.id) + Utils.log(`srcIndex: ${srcIndex}, destIndex: ${destIndex}`) + + newOrder.splice(destIndex, 0, newOrder.splice(srcIndex, 1)[0]) + + await undoManager.perform( + async () => { + await octoClient.patchBlock(view.id, {updatedFields: {visiblePropertyIds: newOrder}}) + }, + async () => { + await octoClient.patchBlock(view.id, {updatedFields: {visiblePropertyIds: oldVisiblePropertyIds}}) + }, + description, + this.undoGroupId, + ) + } + async changeViewVisibleProperties(viewId: string, oldVisiblePropertyIds: string[], visiblePropertyIds: string[], description = 'show / hide property'): Promise { await undoManager.perform( async () => {