Skip to content

Commit

Permalink
Merge pull request #1541 from zetkin/issue-1039/view-column-order-per…
Browse files Browse the repository at this point in the history
…istence

Persistence of view column ordering.
  • Loading branch information
richardolsson authored Oct 1, 2023
2 parents a167606 + 4891b76 commit 13ca881
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 4 deletions.
26 changes: 26 additions & 0 deletions src/features/views/components/ViewDataTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
} from 'utils/types/zetkin';

import messageIds from 'features/views/l10n/messageIds';
import useDebounce from 'utils/hooks/useDebounce';

declare module '@mui/x-data-grid-pro' {
interface ColumnMenuPropsOverrides {
Expand Down Expand Up @@ -314,6 +315,27 @@ const ViewDataTable: FunctionComponent<ViewDataTableProps> = ({
width: 50,
};

const debouncedUpdateColumnOrder = useDebounce((order: number[]) => {
return model.updateColumnOrder(order);
}, 1000);

const moveColumn = (field: string, targetIndex: number) => {
// The column index is offset by 2 compared to the API (avatar and checkbox)
targetIndex -= 2;
const columnId = colIdFromFieldName(field);
const origIndex = columns.findIndex((col) => col.id == columnId);
const columnOrder = columns.map((col) => col.id);

// Remove column and place it in new location
columnOrder.splice(origIndex, 1);
const newColumnOrder = [
...columnOrder.slice(0, targetIndex),
columnId,
...columnOrder.slice(targetIndex),
];
debouncedUpdateColumnOrder(newColumnOrder);
};

const unConfiguredGridColumns = [
avatarColumn,
...columns.map((col) => ({
Expand All @@ -329,6 +351,7 @@ const ViewDataTable: FunctionComponent<ViewDataTableProps> = ({
...columnTypes[col.type].getColDef(col, accessLevel),
})),
];

const { columns: gridColumns, setColumnWidth } =
useConfigurableDataGridColumns('viewInstances', unConfiguredGridColumns);

Expand Down Expand Up @@ -457,6 +480,9 @@ const ViewDataTable: FunctionComponent<ViewDataTableProps> = ({
}
}
}}
onColumnOrderChange={(params) => {
moveColumn(params.column.field, params.targetIndex);
}}
onColumnResize={(params) => {
setColumnWidth(params.colDef.field, params.width);
}}
Expand Down
4 changes: 4 additions & 0 deletions src/features/views/models/ViewDataModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export default class ViewDataModel extends ModelBase {
return this._repo.updateColumn(this._orgId, this._viewId, columnId, data);
}

updateColumnOrder(columnOrder: number[]): Promise<void> {
return this._repo.updateColumnOrder(this._orgId, this._viewId, columnOrder);
}

updateContentQuery(query: Pick<ZetkinQuery, 'filter_spec'>) {
return this._repo.updateViewContentQuery(this._orgId, this._viewId, query);
}
Expand Down
13 changes: 13 additions & 0 deletions src/features/views/repos/ViewDataRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
cellUpdated,
columnAdded,
columnDeleted,
columnOrderUpdated,
columnsLoad,
columnsLoaded,
columnUpdated,
Expand Down Expand Up @@ -174,6 +175,18 @@ export default class ViewDataRepo {
this._store.dispatch(columnUpdated([viewId, column]));
}

async updateColumnOrder(
orgId: number,
viewId: number,
columnOrder: number[]
) {
await this._apiClient.patch<{ order: number[] }>(
`/api/orgs/${orgId}/people/views/${viewId}/column_order`,
{ order: columnOrder }
);
this._store.dispatch(columnOrderUpdated([viewId, columnOrder]));
}

updateView(
orgId: number,
viewId: number,
Expand Down
50 changes: 46 additions & 4 deletions src/features/views/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Call } from 'features/callAssignments/apiTypes';
import { callUpdated } from 'features/callAssignments/store';
import columnTypes from './components/ViewDataTable/columnTypes';
import { DeleteFolderReport } from './rpc/deleteFolder';
import notEmpty from 'utils/notEmpty';
import { ViewTreeData } from 'pages/api/views/tree';
import { ZetkinObjectAccess } from 'core/api/types';
import {
Expand Down Expand Up @@ -152,12 +153,10 @@ const viewsSlice = createSlice({
}
},
columnAdded: (state, action: PayloadAction<[number, ZetkinViewColumn]>) => {
const [viewId, column] = action.payload;
const [viewId] = action.payload;
const colList = state.columnsByViewId[viewId];
if (colList) {
colList.items = colList.items.concat([
remoteItem(column.id, { data: column }),
]);
colList.isStale = true;
const rowList = state.rowsByViewId[viewId];

if (rowList) {
Expand All @@ -180,6 +179,48 @@ const viewsSlice = createSlice({
}
}
},
columnOrderUpdated: (state, action: PayloadAction<[number, number[]]>) => {
const [viewId, columnOrder] = action.payload;
// Re-arrange columns
const colList = state.columnsByViewId[viewId];
if (colList) {
const newColListItems = columnOrder
.map((colId) => {
const col = colList.items.find((col) => col.id == colId);
if (col) {
return col;
} else {
colList.isStale = true;
}
})
.filter(notEmpty);

// Re-arrange columns of data-rows
const rowList = state.rowsByViewId[viewId];
if (rowList) {
const newRowListItems = rowList.items.map((row) => {
if (row.data) {
return {
...row,
data: {
content: columnOrder.map((colId) => {
const idx = colList.items.findIndex(
(col) => col.id == colId
)!;
return row.data?.content[idx];
}),
id: row.data.id,
},
};
} else {
return row;
}
});
state.columnsByViewId[viewId].items = newColListItems;
state.rowsByViewId[viewId].items = newRowListItems;
}
}
},
columnUpdated: (
state,
action: PayloadAction<[number, ZetkinViewColumn]>
Expand Down Expand Up @@ -484,6 +525,7 @@ export const {
cellUpdated,
columnAdded,
columnDeleted,
columnOrderUpdated,
columnUpdated,
columnsLoad,
columnsLoaded,
Expand Down

0 comments on commit 13ca881

Please sign in to comment.