Skip to content

Commit

Permalink
Document Component: Column Order DragNDrop #680
Browse files Browse the repository at this point in the history
  • Loading branch information
ComLock committed Dec 20, 2022
1 parent 6eecba8 commit ecde52b
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 152 deletions.
24 changes: 13 additions & 11 deletions src/main/resources/assets/react/document/Documents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@ import {
} from 'semantic-ui-react';
import {TypedReactJson} from '../search/TypedReactJson';
import {HoverPopup} from '../components/HoverPopup';
import DragAndDropableHeaderCell from './DragAndDropableHeaderCell';
import {
COLUMN_NAME_COLLECTION,
COLUMN_NAME_DOCUMENT_TYPE,
COLUMN_NAME_LANGUAGE,
COLUMN_NAME_ID,
COLUMN_NAME_JSON,
SELECTED_COLUMNS_DEFAULT
} from './constants';
import DragAndDropableHeaderCell from './DragAndDropableHeaderCell';
import {
FRAGMENT_SIZE_DEFAULT,
POST_TAG,
PRE_TAG,
SELECTED_COLUMNS_DEFAULT,
useDocumentsState
} from './useDocumentsState';

Expand Down Expand Up @@ -125,7 +127,7 @@ export function Documents({
queryDocuments,
searchedString, // setSearchedString,
selectedCollections, setSelectedCollections,
selectedColumnsState, persistSelectedColumns,
selectedColumnsState, setSelectedColumnsState,
selectedDocumentTypes, setSelectedDocumentTypes,
start, setStart,
} = useDocumentsState({
Expand Down Expand Up @@ -328,7 +330,7 @@ export function Documents({
{value}
) => {
const newSelectedColumns = value as string[];
persistSelectedColumns(newSelectedColumns);
setSelectedColumnsState(newSelectedColumns);
queryDocuments({
collectionsFilter: selectedCollections,
documentsTypesFilter: selectedDocumentTypes,
Expand Down Expand Up @@ -532,16 +534,16 @@ export function Documents({
? 'Document'
: columnName
}
key={i}
id={columnName}
index={i}
key={`column-${columnName}`}
onDrop={({
fromIndex,
toIndex
fromId,
toId
}) => handleDroppedColumn({
fromIndex,
selectedColumns: selectedColumnsState,
toIndex
fromId,
toId
})}
index={i}
/>)}
{/*columnOptions
.filter(({value}) => selectedColumns.includes(value as string))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {


interface Item {
id: number
id: string
}


Expand Down Expand Up @@ -36,21 +36,22 @@ function Overlay({color}: {color: string}) {

export default function DragAndDropableHeaderCell(
props: StrictTableHeaderCellProps & {
id: string
index: number
onDrop: ({
fromIndex,
toIndex
fromId,
toId
}: {
fromIndex: number
toIndex: number
fromId: string
toId: string
}) => void
style?: React.CSSProperties // "missing" from StrictTableHeaderCellProps
}
) {
const {
children,
content,
index,
id: idProp,
onDrop = () => {/* default no-op dummy just in case */},
style = {},
...tableHeaderCellPropsExceptChildrenOrContentOrStyle
Expand All @@ -61,20 +62,22 @@ export default function DragAndDropableHeaderCell(
}>(() => ({
type: 'HeaderCell',
// canDrag: (monitor)=> {
// console.debug('on canDrag monitor', monitor, 'index', index);
// console.debug('on canDrag monitor', monitor);
// return true;
// },
collect: monitor => ({
isDragging: !!monitor.isDragging(),
}),
// end: (item, monitor) => {
// console.debug('on drag end item', item, 'monitor', monitor, 'index', index);
// console.debug('on drag end item', item, 'monitor', monitor);
// },
// isDragging: (monitor) => {
// console.debug('on isDragging monitor', monitor, 'index', index);
// console.debug('on isDragging monitor', monitor);
// return true;
// },
item: { id: index },
item: {
id: idProp,
},
// options: {
// dropEffect: 'copy',
// // dropEffect: 'move',
Expand All @@ -86,7 +89,13 @@ export default function DragAndDropableHeaderCell(
// offsetX: 0,
// offsetY: 0,
// },
}));
}),
// A dependency array used for memoization.
// This behaves like the built-in useMemoReact hook.
// The default value is an empty array for function spec,
// and an array containing the spec for an object spec.
// []
);
// console.debug('dragProps', dragProps);
const { isDragging } = dragProps;

Expand All @@ -97,30 +106,41 @@ export default function DragAndDropableHeaderCell(
() => ({
accept: 'HeaderCell',
canDrop: (item/*, monitor*/) => {
// console.debug('on canDrop item', item, 'monitor', monitor, 'index', index);
const {id} = item;
return id !== index;
// console.debug('on canDrop item', item, 'idProp', idProp);
// console.debug('on canDrop monitor', monitor);
const {
id,
} = item;
return id !== idProp;
},
drop: (item/*, monitor*/) => {
// console.debug('on drop item', item, 'monitor', monitor, 'index', index);
const {id} = item; // The dropped item
// index is the target index
// console.debug('on drop item', item, 'idProp', idProp);
// console.debug('on drop monitor', monitor);
const {
id,
} = item; // The dropped item
onDrop({
fromIndex: id,
toIndex: index
fromId: id,
toId: idProp
});
},
collect: (monitor) => ({
canDrop: !!monitor.canDrop(),
isOver: !!monitor.isOver(),
}),
// hover: (item, monitor) => {
// console.debug('on hover item', item, 'monitor', monitor, 'index', index);
// console.debug('on hover item', item, 'monitor', monitor);
// },
item: { id: index },
item: {
id: idProp,
},
// options: {}
}),
[index]
// A dependency array used for memoization.
// This behaves like the built-in useMemoReact hook.
// The default value is an empty array for function spec,
// and an array containing the spec for an object spec.
// []
);
// console.debug('dropProps', dropProps);
const { canDrop, isOver } = dropProps;
Expand All @@ -135,7 +155,7 @@ export default function DragAndDropableHeaderCell(
style={{
...style,
cursor: 'grabbing',
opacity: 0,
opacity: 0.5,
}}
>
{
Expand Down
12 changes: 12 additions & 0 deletions src/main/resources/assets/react/document/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const COLUMN_NAME_COLLECTION = '_collection';
export const COLUMN_NAME_DOCUMENT_TYPE = '_documentType';
export const COLUMN_NAME_ID = '_id';
export const COLUMN_NAME_JSON = '_json';
export const COLUMN_NAME_LANGUAGE = '_language';
export const SELECTED_COLUMNS_DEFAULT = [
COLUMN_NAME_JSON,
COLUMN_NAME_ID,
COLUMN_NAME_COLLECTION,
COLUMN_NAME_DOCUMENT_TYPE,
COLUMN_NAME_LANGUAGE,
] as const;
40 changes: 40 additions & 0 deletions src/main/resources/assets/react/document/getColumns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type {JSONResponse} from '../../../services/graphQL/fetchers/index.d';

type GetProfileResponse = JSONResponse<{
getProfile: {
documents: {
columns: string[]|string
}
}
}>


import {forceArray} from '@enonic/js-utils';
import * as gql from 'gql-query-builder';
import {SELECTED_COLUMNS_DEFAULT} from './constants';


export async function getColumns({
servicesBaseUrl
}: {
servicesBaseUrl: string
}) {
return fetch(`${servicesBaseUrl}/graphQL`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(gql.query({
operation: 'getProfile'
}))
})
.then(res => res.json() as GetProfileResponse)
.then(object => {
// console.log('object', object);
const {
documents: {
columns = [...SELECTED_COLUMNS_DEFAULT] // When there is no profile, use defaults, deref to avoid type issues
} = {}
} = object.data.getProfile || {};
// console.log('columns', columns);
return forceArray(columns);
});
}
63 changes: 63 additions & 0 deletions src/main/resources/assets/react/document/persistColumns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type {JSONResponse} from '../../../services/graphQL/fetchers/index.d';

type ModifyProfileResponse = JSONResponse<{
modifyProfile: {
columns?: string[]
}
}>

import fastDeepEqual from 'fast-deep-equal/react';
import * as gql from 'gql-query-builder';


export async function persistColumns({
columns: columnsParam,
getColumns,
servicesBaseUrl
}: {
columns: string[]
getColumns: ({servicesBaseUrl}: {servicesBaseUrl: string}) => Promise<string[]>
servicesBaseUrl: string
}) {
return getColumns({servicesBaseUrl}).then(prevColumns => {
if (fastDeepEqual(columnsParam, prevColumns)) {
// console.debug('columns unchanged', prevColumns);
return prevColumns;
} else {
// console.debug('columns changed', columnsParam, 'prev', prevColumns);
return fetch(`${servicesBaseUrl}/graphQL`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(gql.mutation({
operation: 'modifyProfile',
variables: {
object: {
list: false,
required: true,
type: 'JSON',
value: {
columns: columnsParam
}
},
scope: {
list: false,
required: true,
type: 'String',
value: 'documents'
}
}
}))
})
.then(res => res.json() as ModifyProfileResponse)
.then((object) => {
// console.log('object', object);
const {
columns// = SELECTED_COLUMNS_DEFAULT // This will reset to default when all columns are removed
} = object.data.modifyProfile;
return columns;
});
}
});


}
Loading

0 comments on commit ecde52b

Please sign in to comment.