@sanity/orderable-document-list 0.0.8 → 1.0.0-v3-studio.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +142 -48
- package/lib/index.d.ts +38 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +849 -30
- package/lib/index.js.map +1 -1
- package/lib/index.modern.js +840 -0
- package/lib/index.modern.js.map +1 -0
- package/package.json +56 -22
- package/src/{Document.js → Document.tsx} +30 -27
- package/src/{DocumentListQuery.js → DocumentListQuery.tsx} +29 -18
- package/src/{DocumentListWrapper.js → DocumentListWrapper.tsx} +29 -21
- package/src/DraggableList.tsx +304 -0
- package/src/{Feedback.js → Feedback.tsx} +2 -7
- package/src/OrderableContext.ts +7 -0
- package/src/{OrderableDocumentList.js → OrderableDocumentList.tsx} +25 -10
- package/src/desk-structure/globalClientWorkaround.ts +33 -0
- package/src/desk-structure/{orderableDocumentListDeskItem.js → orderableDocumentListDeskItem.ts} +27 -11
- package/src/fields/orderRankField.ts +45 -0
- package/src/fields/{orderRankOrdering.js → orderRankOrdering.ts} +0 -0
- package/src/helpers/client.ts +13 -0
- package/src/helpers/constants.ts +1 -0
- package/src/helpers/{initialRank.js → initialRank.ts} +2 -2
- package/src/helpers/{reorderDocuments.js → reorderDocuments.ts} +33 -44
- package/src/helpers/{resetOrder.js → resetOrder.ts} +3 -8
- package/src/index.ts +9 -0
- package/.babelrc +0 -3
- package/.eslintignore +0 -1
- package/.eslintrc.js +0 -50
- package/lib/Document.js +0 -101
- package/lib/Document.js.map +0 -1
- package/lib/DocumentListQuery.js +0 -155
- package/lib/DocumentListQuery.js.map +0 -1
- package/lib/DocumentListWrapper.js +0 -97
- package/lib/DocumentListWrapper.js.map +0 -1
- package/lib/DraggableList.js +0 -314
- package/lib/DraggableList.js.map +0 -1
- package/lib/Feedback.js +0 -31
- package/lib/Feedback.js.map +0 -1
- package/lib/OrderableContext.js +0 -15
- package/lib/OrderableContext.js.map +0 -1
- package/lib/OrderableDocumentList.js +0 -99
- package/lib/OrderableDocumentList.js.map +0 -1
- package/lib/desk-structure/orderableDocumentListDeskItem.js +0 -52
- package/lib/desk-structure/orderableDocumentListDeskItem.js.map +0 -1
- package/lib/fields/orderRankField.js +0 -64
- package/lib/fields/orderRankField.js.map +0 -1
- package/lib/fields/orderRankOrdering.js +0 -19
- package/lib/fields/orderRankOrdering.js.map +0 -1
- package/lib/helpers/constants.js +0 -9
- package/lib/helpers/constants.js.map +0 -1
- package/lib/helpers/initialRank.js +0 -18
- package/lib/helpers/initialRank.js.map +0 -1
- package/lib/helpers/reorderDocuments.js +0 -133
- package/lib/helpers/reorderDocuments.js.map +0 -1
- package/lib/helpers/resetOrder.js +0 -62
- package/lib/helpers/resetOrder.js.map +0 -1
- package/sanity.json +0 -7
- package/src/DraggableList.js +0 -276
- package/src/OrderableContext.js +0 -3
- package/src/fields/orderRankField.js +0 -35
- package/src/helpers/constants.js +0 -1
- package/src/index.js +0 -5
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"orderRankField.js","names":["client","sanityClient","withConfig","apiVersion","orderRankField","config","type","Error","title","readOnly","hidden","name","ORDER_FIELD_NAME","initialValue","lastDocOrderRank","fetch","order"],"sources":["../../src/fields/orderRankField.js"],"sourcesContent":["import sanityClient from 'part:@sanity/base/client'\nimport {ORDER_FIELD_NAME} from '../helpers/constants'\nimport initialRank from '../helpers/initialRank'\n\nconst client = sanityClient.withConfig({apiVersion: `2021-05-19`})\n\nexport const orderRankField = (config = {}) => {\n if (!config?.type) {\n throw new Error(\n `\n \"type\" not defined in orderRankField parameter object. \n Example: orderRankField({type: 'category'})\n `\n )\n }\n\n const {type} = config\n\n return {\n title: 'Order Rank',\n readOnly: true,\n hidden: true,\n ...config,\n name: ORDER_FIELD_NAME,\n type: 'string',\n initialValue: async () => {\n const lastDocOrderRank = await client.fetch(\n `*[_type == $type]|order(@[$order] desc)[0][$order]`,\n {type, order: ORDER_FIELD_NAME}\n )\n\n return initialRank(lastDocOrderRank)\n },\n }\n}\n"],"mappings":";;;;;;;AAAA;;AACA;;AACA;;;;;;;;;;;;;;AAEA,IAAMA,MAAM,GAAGC,gBAAaC,UAAb,CAAwB;EAACC,UAAU;AAAX,CAAxB,CAAf;;AAEO,IAAMC,cAAc,GAAG,SAAjBA,cAAiB,GAAiB;EAAA,IAAhBC,MAAgB,uEAAP,EAAO;;EAC7C,IAAI,EAACA,MAAD,aAACA,MAAD,eAACA,MAAM,CAAEC,IAAT,CAAJ,EAAmB;IACjB,MAAM,IAAIC,KAAJ,gIAAN;EAMD;;EAED,IAAOD,IAAP,GAAeD,MAAf,CAAOC,IAAP;EAEA;IACEE,KAAK,EAAE,YADT;IAEEC,QAAQ,EAAE,IAFZ;IAGEC,MAAM,EAAE;EAHV,GAIKL,MAJL;IAKEM,IAAI,EAAEC,2BALR;IAMEN,IAAI,EAAE,QANR;IAOEO,YAAY;MAAA,sCAAE,aAAY;QACxB,IAAMC,gBAAgB,SAASd,MAAM,CAACe,KAAP,uDAE7B;UAACT,IAAD;UAAOU,KAAK,EAAEJ;QAAd,CAF6B,CAA/B;QAKA,OAAO,0BAAYE,gBAAZ,CAAP;MACD,CAPW;;MAAA;QAAA;MAAA;;MAAA;IAAA;EAPd;AAgBD,CA5BM"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.orderRankOrdering = void 0;
|
|
7
|
-
|
|
8
|
-
var _constants = require("../helpers/constants");
|
|
9
|
-
|
|
10
|
-
var orderRankOrdering = {
|
|
11
|
-
title: 'Ordered',
|
|
12
|
-
name: 'ordered',
|
|
13
|
-
by: [{
|
|
14
|
-
field: _constants.ORDER_FIELD_NAME,
|
|
15
|
-
direction: 'asc'
|
|
16
|
-
}]
|
|
17
|
-
};
|
|
18
|
-
exports.orderRankOrdering = orderRankOrdering;
|
|
19
|
-
//# sourceMappingURL=orderRankOrdering.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"orderRankOrdering.js","names":["orderRankOrdering","title","name","by","field","ORDER_FIELD_NAME","direction"],"sources":["../../src/fields/orderRankOrdering.js"],"sourcesContent":["import {ORDER_FIELD_NAME} from '../helpers/constants'\n\nexport const orderRankOrdering = {\n title: 'Ordered',\n name: 'ordered',\n by: [{field: ORDER_FIELD_NAME, direction: 'asc'}],\n}\n"],"mappings":";;;;;;;AAAA;;AAEO,IAAMA,iBAAiB,GAAG;EAC/BC,KAAK,EAAE,SADwB;EAE/BC,IAAI,EAAE,SAFyB;EAG/BC,EAAE,EAAE,CAAC;IAACC,KAAK,EAAEC,2BAAR;IAA0BC,SAAS,EAAE;EAArC,CAAD;AAH2B,CAA1B"}
|
package/lib/helpers/constants.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":["ORDER_FIELD_NAME"],"sources":["../../src/helpers/constants.js"],"sourcesContent":["export const ORDER_FIELD_NAME = `orderRank`\n"],"mappings":";;;;;;AAAO,IAAMA,gBAAgB,cAAtB"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = initialRank;
|
|
7
|
-
|
|
8
|
-
var _lexorank = require("lexorank");
|
|
9
|
-
|
|
10
|
-
// Use in initial value field by passing in the rank value of the last document
|
|
11
|
-
// If not value passed, generate a sensibly low rank
|
|
12
|
-
function initialRank() {
|
|
13
|
-
var lastRankValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
|
|
14
|
-
var lastRank = lastRankValue ? _lexorank.LexoRank.parse(lastRankValue) : _lexorank.LexoRank.min();
|
|
15
|
-
var nextRank = lastRank.genNext().genNext();
|
|
16
|
-
return nextRank.value;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=initialRank.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"initialRank.js","names":["initialRank","lastRankValue","lastRank","LexoRank","parse","min","nextRank","genNext","value"],"sources":["../../src/helpers/initialRank.js"],"sourcesContent":["import {LexoRank} from 'lexorank'\n\n// Use in initial value field by passing in the rank value of the last document\n// If not value passed, generate a sensibly low rank\nexport default function initialRank(lastRankValue = ``) {\n const lastRank = lastRankValue ? LexoRank.parse(lastRankValue) : LexoRank.min()\n const nextRank = lastRank.genNext().genNext()\n\n return nextRank.value\n}\n"],"mappings":";;;;;;;AAAA;;AAEA;AACA;AACe,SAASA,WAAT,GAAyC;EAAA,IAApBC,aAAoB;EACtD,IAAMC,QAAQ,GAAGD,aAAa,GAAGE,mBAASC,KAAT,CAAeH,aAAf,CAAH,GAAmCE,mBAASE,GAAT,EAAjE;EACA,IAAMC,QAAQ,GAAGJ,QAAQ,CAACK,OAAT,GAAmBA,OAAnB,EAAjB;EAEA,OAAOD,QAAQ,CAACE,KAAhB;AACD"}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.reorderDocuments = void 0;
|
|
7
|
-
|
|
8
|
-
var _lexorank = require("lexorank");
|
|
9
|
-
|
|
10
|
-
var _constants = require("./constants");
|
|
11
|
-
|
|
12
|
-
function lexicographicalSort(a, b) {
|
|
13
|
-
if (a[_constants.ORDER_FIELD_NAME] < b[_constants.ORDER_FIELD_NAME]) {
|
|
14
|
-
return -1;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (a[_constants.ORDER_FIELD_NAME] > b[_constants.ORDER_FIELD_NAME]) {
|
|
18
|
-
return 1;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return 0;
|
|
22
|
-
} // In lieu of actual *tests*, this is a table
|
|
23
|
-
// to visualise the new order which if correct, shows:
|
|
24
|
-
// 1. The `before` field (or start of the list)
|
|
25
|
-
// 2. The inserted fields, in order
|
|
26
|
-
// 3. The `after` document (or end of the list)
|
|
27
|
-
// eslint-disable-next-line no-unused-vars
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
function createManifest(_ref) {
|
|
31
|
-
var _entities, _entities2;
|
|
32
|
-
|
|
33
|
-
var entities = _ref.entities,
|
|
34
|
-
selectedItems = _ref.selectedItems,
|
|
35
|
-
isMovingUp = _ref.isMovingUp,
|
|
36
|
-
curIndex = _ref.curIndex,
|
|
37
|
-
nextIndex = _ref.nextIndex,
|
|
38
|
-
prevIndex = _ref.prevIndex;
|
|
39
|
-
var table = [{
|
|
40
|
-
name: "Before",
|
|
41
|
-
title: curIndex === 0 ? "<<Start of List>>" : (_entities = entities[isMovingUp ? prevIndex : curIndex]) === null || _entities === void 0 ? void 0 : _entities.title,
|
|
42
|
-
order: curIndex === 0 ? "000" : entities[isMovingUp ? prevIndex : curIndex][_constants.ORDER_FIELD_NAME]
|
|
43
|
-
}, ...selectedItems.map((item, itemIndex) => ({
|
|
44
|
-
name: itemIndex,
|
|
45
|
-
title: item === null || item === void 0 ? void 0 : item.title,
|
|
46
|
-
order: item[_constants.ORDER_FIELD_NAME]
|
|
47
|
-
})), {
|
|
48
|
-
name: "After",
|
|
49
|
-
title: curIndex === entities.length - 1 ? "<<End of List>>" : (_entities2 = entities[isMovingUp ? curIndex : nextIndex]) === null || _entities2 === void 0 ? void 0 : _entities2.title,
|
|
50
|
-
order: curIndex === entities.length - 1 ? "zzz" : entities[isMovingUp ? curIndex : nextIndex][_constants.ORDER_FIELD_NAME]
|
|
51
|
-
}];
|
|
52
|
-
return table.sort(lexicographicalSort);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
var reorderDocuments = _ref2 => {
|
|
56
|
-
var entities = _ref2.entities,
|
|
57
|
-
selectedIds = _ref2.selectedIds,
|
|
58
|
-
source = _ref2.source,
|
|
59
|
-
destination = _ref2.destination,
|
|
60
|
-
_ref2$debug = _ref2.debug,
|
|
61
|
-
debug = _ref2$debug === void 0 ? false : _ref2$debug;
|
|
62
|
-
var startIndex = source.index;
|
|
63
|
-
var endIndex = destination.index;
|
|
64
|
-
var isMovingUp = startIndex > endIndex;
|
|
65
|
-
var selectedItems = entities.filter(item => selectedIds.includes(item._id));
|
|
66
|
-
var message = ["Moved", selectedItems.length === 1 ? "1 Document" : "".concat(selectedItems.length, " Documents"), isMovingUp ? "up" : "down", "from position", "".concat(startIndex + 1, " to ").concat(endIndex + 1)].join(' ');
|
|
67
|
-
|
|
68
|
-
var _entities$reduce = entities.reduce((acc, cur, curIndex) => {
|
|
69
|
-
// Selected items get spread in below, so skip them here
|
|
70
|
-
if (selectedIds.includes(cur._id)) {
|
|
71
|
-
return {
|
|
72
|
-
all: acc.all,
|
|
73
|
-
selected: acc.selected
|
|
74
|
-
};
|
|
75
|
-
} // Drop seleced items in
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Drop seleced items in
|
|
79
|
-
if (curIndex === endIndex) {
|
|
80
|
-
var _entities$prevIndex, _entities$prevIndex2, _entities$nextIndex, _entities$nextIndex2;
|
|
81
|
-
|
|
82
|
-
var prevIndex = curIndex - 1;
|
|
83
|
-
var prevRank = (_entities$prevIndex = entities[prevIndex]) !== null && _entities$prevIndex !== void 0 && _entities$prevIndex[_constants.ORDER_FIELD_NAME] ? _lexorank.LexoRank.parse((_entities$prevIndex2 = entities[prevIndex]) === null || _entities$prevIndex2 === void 0 ? void 0 : _entities$prevIndex2[_constants.ORDER_FIELD_NAME]) : _lexorank.LexoRank.min();
|
|
84
|
-
|
|
85
|
-
var curRank = _lexorank.LexoRank.parse(entities[curIndex][_constants.ORDER_FIELD_NAME]);
|
|
86
|
-
|
|
87
|
-
var nextIndex = curIndex + 1;
|
|
88
|
-
var nextRank = (_entities$nextIndex = entities[nextIndex]) !== null && _entities$nextIndex !== void 0 && _entities$nextIndex[_constants.ORDER_FIELD_NAME] ? _lexorank.LexoRank.parse((_entities$nextIndex2 = entities[nextIndex]) === null || _entities$nextIndex2 === void 0 ? void 0 : _entities$nextIndex2[_constants.ORDER_FIELD_NAME]) : _lexorank.LexoRank.max();
|
|
89
|
-
var betweenRank = isMovingUp ? prevRank.between(curRank) : curRank.between(nextRank); // For each selected item, assign a new orderRank between now and next
|
|
90
|
-
|
|
91
|
-
// For each selected item, assign a new orderRank between now and next
|
|
92
|
-
for (var selectedIndex = 0; selectedIndex < selectedItems.length; selectedIndex += 1) {
|
|
93
|
-
selectedItems[selectedIndex][_constants.ORDER_FIELD_NAME] = betweenRank.value;
|
|
94
|
-
betweenRank = isMovingUp ? betweenRank.between(curRank) : betweenRank.between(nextRank);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
// The `all` array gets sorted by order field later anyway
|
|
99
|
-
// so that this probably isn't necessary ¯\_(ツ)_/¯
|
|
100
|
-
all: isMovingUp ? [...acc.all, ...selectedItems, cur] : [...acc.all, cur, ...selectedItems],
|
|
101
|
-
selected: selectedItems
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
all: [...acc.all, cur],
|
|
107
|
-
selected: acc.selected
|
|
108
|
-
};
|
|
109
|
-
}, {
|
|
110
|
-
all: [],
|
|
111
|
-
selected: []
|
|
112
|
-
}),
|
|
113
|
-
all = _entities$reduce.all,
|
|
114
|
-
selected = _entities$reduce.selected;
|
|
115
|
-
|
|
116
|
-
var patches = selected.map(doc => {
|
|
117
|
-
return [doc._id, {
|
|
118
|
-
set: {
|
|
119
|
-
[_constants.ORDER_FIELD_NAME]: doc[_constants.ORDER_FIELD_NAME]
|
|
120
|
-
}
|
|
121
|
-
}];
|
|
122
|
-
}); // Safety-check to make sure everything is in order
|
|
123
|
-
|
|
124
|
-
var allSorted = all.sort(lexicographicalSort);
|
|
125
|
-
return {
|
|
126
|
-
newOrder: allSorted,
|
|
127
|
-
patches,
|
|
128
|
-
message
|
|
129
|
-
};
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
exports.reorderDocuments = reorderDocuments;
|
|
133
|
-
//# sourceMappingURL=reorderDocuments.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reorderDocuments.js","names":["lexicographicalSort","a","b","ORDER_FIELD_NAME","createManifest","entities","selectedItems","isMovingUp","curIndex","nextIndex","prevIndex","table","name","title","order","map","item","itemIndex","length","sort","reorderDocuments","selectedIds","source","destination","debug","startIndex","index","endIndex","filter","includes","_id","message","join","reduce","acc","cur","all","selected","prevRank","LexoRank","parse","min","curRank","nextRank","max","betweenRank","between","selectedIndex","value","patches","doc","set","allSorted","newOrder"],"sources":["../../src/helpers/reorderDocuments.js"],"sourcesContent":["import {LexoRank} from 'lexorank'\nimport {ORDER_FIELD_NAME} from './constants'\n\nfunction lexicographicalSort(a, b) {\n if (a[ORDER_FIELD_NAME] < b[ORDER_FIELD_NAME]) {\n return -1\n }\n if (a[ORDER_FIELD_NAME] > b[ORDER_FIELD_NAME]) {\n return 1\n }\n return 0\n}\n\n// In lieu of actual *tests*, this is a table\n// to visualise the new order which if correct, shows:\n// 1. The `before` field (or start of the list)\n// 2. The inserted fields, in order\n// 3. The `after` document (or end of the list)\n// eslint-disable-next-line no-unused-vars\nfunction createManifest({entities, selectedItems, isMovingUp, curIndex, nextIndex, prevIndex}) {\n const table = [\n {\n name: `Before`,\n title:\n curIndex === 0 ? `<<Start of List>>` : entities[isMovingUp ? prevIndex : curIndex]?.title,\n order: curIndex === 0 ? `000` : entities[isMovingUp ? prevIndex : curIndex][ORDER_FIELD_NAME],\n },\n ...selectedItems.map((item, itemIndex) => ({\n name: itemIndex,\n title: item?.title,\n order: item[ORDER_FIELD_NAME],\n })),\n {\n name: `After`,\n title:\n curIndex === entities.length - 1\n ? `<<End of List>>`\n : entities[isMovingUp ? curIndex : nextIndex]?.title,\n order:\n curIndex === entities.length - 1\n ? `zzz`\n : entities[isMovingUp ? curIndex : nextIndex][ORDER_FIELD_NAME],\n },\n ]\n\n return table.sort(lexicographicalSort)\n}\n\nexport const reorderDocuments = ({entities, selectedIds, source, destination, debug = false}) => {\n const startIndex = source.index\n const endIndex = destination.index\n const isMovingUp = startIndex > endIndex\n const selectedItems = entities.filter((item) => selectedIds.includes(item._id))\n const message = [\n `Moved`,\n selectedItems.length === 1 ? `1 Document` : `${selectedItems.length} Documents`,\n isMovingUp ? `up` : `down`,\n `from position`,\n `${startIndex + 1} to ${endIndex + 1}`,\n ].join(' ')\n\n const {all, selected} = entities.reduce(\n (acc, cur, curIndex) => {\n // Selected items get spread in below, so skip them here\n if (selectedIds.includes(cur._id)) {\n return {all: acc.all, selected: acc.selected}\n }\n\n // Drop seleced items in\n if (curIndex === endIndex) {\n const prevIndex = curIndex - 1\n const prevRank = entities[prevIndex]?.[ORDER_FIELD_NAME]\n ? LexoRank.parse(entities[prevIndex]?.[ORDER_FIELD_NAME])\n : LexoRank.min()\n\n const curRank = LexoRank.parse(entities[curIndex][ORDER_FIELD_NAME])\n\n const nextIndex = curIndex + 1\n const nextRank = entities[nextIndex]?.[ORDER_FIELD_NAME]\n ? LexoRank.parse(entities[nextIndex]?.[ORDER_FIELD_NAME])\n : LexoRank.max()\n\n let betweenRank = isMovingUp ? prevRank.between(curRank) : curRank.between(nextRank)\n\n // For each selected item, assign a new orderRank between now and next\n for (let selectedIndex = 0; selectedIndex < selectedItems.length; selectedIndex += 1) {\n selectedItems[selectedIndex][ORDER_FIELD_NAME] = betweenRank.value\n betweenRank = isMovingUp ? betweenRank.between(curRank) : betweenRank.between(nextRank)\n }\n\n return {\n // The `all` array gets sorted by order field later anyway\n // so that this probably isn't necessary ¯\\_(ツ)_/¯\n all: isMovingUp\n ? [...acc.all, ...selectedItems, cur]\n : [...acc.all, cur, ...selectedItems],\n selected: selectedItems,\n }\n }\n\n return {all: [...acc.all, cur], selected: acc.selected}\n },\n {all: [], selected: []}\n )\n\n const patches = selected.map((doc) => {\n return [\n doc._id,\n {\n set: {\n [ORDER_FIELD_NAME]: doc[ORDER_FIELD_NAME],\n },\n },\n ]\n })\n\n // Safety-check to make sure everything is in order\n const allSorted = all.sort(lexicographicalSort)\n\n return {newOrder: allSorted, patches, message}\n}\n"],"mappings":"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"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.resetOrder = resetOrder;
|
|
7
|
-
|
|
8
|
-
var _lexorank = require("lexorank");
|
|
9
|
-
|
|
10
|
-
var _client = _interopRequireDefault(require("part:@sanity/base/client"));
|
|
11
|
-
|
|
12
|
-
var _constants = require("./constants");
|
|
13
|
-
|
|
14
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
17
|
-
|
|
18
|
-
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
19
|
-
|
|
20
|
-
var client = _client.default.withConfig({
|
|
21
|
-
apiVersion: '2021-09-01'
|
|
22
|
-
}); // Function to wipe and re-do ordering with LexoRank
|
|
23
|
-
// Will at least attempt to start with the current order
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
function resetOrder() {
|
|
27
|
-
return _resetOrder.apply(this, arguments);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function _resetOrder() {
|
|
31
|
-
_resetOrder = _asyncToGenerator(function* () {
|
|
32
|
-
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
|
|
33
|
-
var query = "*[_type == $type]|order(@[$order] asc)._id";
|
|
34
|
-
var queryParams = {
|
|
35
|
-
type,
|
|
36
|
-
order: _constants.ORDER_FIELD_NAME
|
|
37
|
-
};
|
|
38
|
-
var documents = yield client.fetch(query, queryParams);
|
|
39
|
-
|
|
40
|
-
if (!documents.length) {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
var transaction = client.transaction();
|
|
45
|
-
|
|
46
|
-
var aLexoRank = _lexorank.LexoRank.min();
|
|
47
|
-
|
|
48
|
-
for (var index = 0; index < documents.length; index += 1) {
|
|
49
|
-
// Generate next rank before even the first document so there's room to move!
|
|
50
|
-
aLexoRank = aLexoRank.genNext().genNext();
|
|
51
|
-
transaction.patch(documents[index], {
|
|
52
|
-
set: {
|
|
53
|
-
[_constants.ORDER_FIELD_NAME]: aLexoRank.value
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return transaction.commit().then(update => update).catch(err => err);
|
|
59
|
-
});
|
|
60
|
-
return _resetOrder.apply(this, arguments);
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=resetOrder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resetOrder.js","names":["client","sanityClient","withConfig","apiVersion","resetOrder","type","query","queryParams","order","ORDER_FIELD_NAME","documents","fetch","length","transaction","aLexoRank","LexoRank","min","index","genNext","patch","set","value","commit","then","update","catch","err"],"sources":["../../src/helpers/resetOrder.js"],"sourcesContent":["import {LexoRank} from 'lexorank'\nimport sanityClient from 'part:@sanity/base/client'\nimport {ORDER_FIELD_NAME} from './constants'\n\nconst client = sanityClient.withConfig({\n apiVersion: '2021-09-01',\n})\n\n// Function to wipe and re-do ordering with LexoRank\n// Will at least attempt to start with the current order\nexport async function resetOrder(type = ``) {\n const query = `*[_type == $type]|order(@[$order] asc)._id`\n const queryParams = {type, order: ORDER_FIELD_NAME}\n const documents = await client.fetch(query, queryParams)\n\n if (!documents.length) {\n return null\n }\n\n const transaction = client.transaction()\n let aLexoRank = LexoRank.min()\n\n for (let index = 0; index < documents.length; index += 1) {\n // Generate next rank before even the first document so there's room to move!\n aLexoRank = aLexoRank.genNext().genNext()\n\n transaction.patch(documents[index], {\n set: {[ORDER_FIELD_NAME]: aLexoRank.value},\n })\n }\n\n return transaction\n .commit()\n .then((update) => update)\n .catch((err) => err)\n}\n"],"mappings":";;;;;;;AAAA;;AACA;;AACA;;;;;;;;AAEA,IAAMA,MAAM,GAAGC,gBAAaC,UAAb,CAAwB;EACrCC,UAAU,EAAE;AADyB,CAAxB,CAAf,C,CAIA;AACA;;;SACsBC,U;;;;;kCAAf,aAAqC;IAAA,IAAXC,IAAW;IAC1C,IAAMC,KAAK,+CAAX;IACA,IAAMC,WAAW,GAAG;MAACF,IAAD;MAAOG,KAAK,EAAEC;IAAd,CAApB;IACA,IAAMC,SAAS,SAASV,MAAM,CAACW,KAAP,CAAaL,KAAb,EAAoBC,WAApB,CAAxB;;IAEA,IAAI,CAACG,SAAS,CAACE,MAAf,EAAuB;MACrB,OAAO,IAAP;IACD;;IAED,IAAMC,WAAW,GAAGb,MAAM,CAACa,WAAP,EAApB;;IACA,IAAIC,SAAS,GAAGC,mBAASC,GAAT,EAAhB;;IAEA,KAAK,IAAIC,KAAK,GAAG,CAAjB,EAAoBA,KAAK,GAAGP,SAAS,CAACE,MAAtC,EAA8CK,KAAK,IAAI,CAAvD,EAA0D;MACxD;MACAH,SAAS,GAAGA,SAAS,CAACI,OAAV,GAAoBA,OAApB,EAAZ;MAEAL,WAAW,CAACM,KAAZ,CAAkBT,SAAS,CAACO,KAAD,CAA3B,EAAoC;QAClCG,GAAG,EAAE;UAAC,CAACX,2BAAD,GAAoBK,SAAS,CAACO;QAA/B;MAD6B,CAApC;IAGD;;IAED,OAAOR,WAAW,CACfS,MADI,GAEJC,IAFI,CAEEC,MAAD,IAAYA,MAFb,EAGJC,KAHI,CAGGC,GAAD,IAASA,GAHX,CAAP;EAID,C"}
|
package/sanity.json
DELETED
package/src/DraggableList.js
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types'
|
|
2
|
-
import React, {useMemo, useState, useEffect} from 'react'
|
|
3
|
-
import {DragDropContext, Droppable, Draggable} from 'react-beautiful-dnd'
|
|
4
|
-
import {usePaneRouter} from '@sanity/desk-tool'
|
|
5
|
-
import {Box, Card, useToast} from '@sanity/ui'
|
|
6
|
-
import sanityClient from 'part:@sanity/base/client'
|
|
7
|
-
|
|
8
|
-
import Document from './Document'
|
|
9
|
-
import {reorderDocuments} from './helpers/reorderDocuments'
|
|
10
|
-
import {ORDER_FIELD_NAME} from './helpers/constants'
|
|
11
|
-
|
|
12
|
-
const client = sanityClient.withConfig({
|
|
13
|
-
apiVersion: '2021-09-01',
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
const getItemStyle = (draggableStyle, itemIsUpdating) => ({
|
|
17
|
-
userSelect: 'none',
|
|
18
|
-
transition: `opacity 500ms ease-in-out`,
|
|
19
|
-
opacity: itemIsUpdating ? 0.2 : 1,
|
|
20
|
-
pointerEvents: itemIsUpdating ? `none` : undefined,
|
|
21
|
-
...draggableStyle,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
const cardTone = (settings) => {
|
|
25
|
-
const {isDuplicate, isGhosting, isDragging, isSelected} = settings
|
|
26
|
-
|
|
27
|
-
if (isGhosting) return `transparent`
|
|
28
|
-
if (isDragging || isSelected) return `primary`
|
|
29
|
-
if (isDuplicate) return `caution`
|
|
30
|
-
|
|
31
|
-
return undefined
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default function DraggableList({data, type, listIsUpdating, setListIsUpdating}) {
|
|
35
|
-
const toast = useToast()
|
|
36
|
-
const router = usePaneRouter()
|
|
37
|
-
const {navigateIntent} = router
|
|
38
|
-
|
|
39
|
-
// Maintains local state order before transaction completes
|
|
40
|
-
const [orderedData, setOrderedData] = useState(data)
|
|
41
|
-
|
|
42
|
-
// Update local state when documents change from an outside source
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
if (!listIsUpdating) setOrderedData(data)
|
|
45
|
-
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
|
46
|
-
}, [data])
|
|
47
|
-
|
|
48
|
-
const [draggingId, setDraggingId] = useState(``)
|
|
49
|
-
const [selectedIds, setSelectedIds] = useState([])
|
|
50
|
-
|
|
51
|
-
const clearSelected = () => setSelectedIds([])
|
|
52
|
-
|
|
53
|
-
const handleSelect = (clickedId, index, nativeEvent) => {
|
|
54
|
-
const isSelected = selectedIds.includes(clickedId)
|
|
55
|
-
const selectMultiple = nativeEvent.shiftKey
|
|
56
|
-
const isUsingWindows = navigator.appVersion.indexOf('Win') !== -1
|
|
57
|
-
const selectAdditional = isUsingWindows ? nativeEvent.ctrlKey : nativeEvent.metaKey
|
|
58
|
-
|
|
59
|
-
let updatedIds = []
|
|
60
|
-
|
|
61
|
-
// No modifier keys pressed during click:
|
|
62
|
-
// - update selected to just this one
|
|
63
|
-
// - open document
|
|
64
|
-
if (!selectMultiple && !selectAdditional) {
|
|
65
|
-
navigateIntent('edit', {id: clickedId, type})
|
|
66
|
-
return setSelectedIds([clickedId])
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Shift key was held, add id's between last selected and this one
|
|
70
|
-
// ...before adding this one
|
|
71
|
-
if (selectMultiple && !isSelected) {
|
|
72
|
-
const lastSelectedId = selectedIds.at(-1)
|
|
73
|
-
const lastSelectedIndex = orderedData.findIndex((item) => item._id === lastSelectedId)
|
|
74
|
-
|
|
75
|
-
const firstSelected = index < lastSelectedIndex ? index : lastSelectedIndex
|
|
76
|
-
const lastSelected = index > lastSelectedIndex ? index : lastSelectedIndex
|
|
77
|
-
|
|
78
|
-
const betweenIds = orderedData
|
|
79
|
-
.filter((item, itemIndex) => itemIndex > firstSelected && itemIndex < lastSelected)
|
|
80
|
-
.map((item) => item._id)
|
|
81
|
-
|
|
82
|
-
updatedIds = [...selectedIds, ...betweenIds, clickedId]
|
|
83
|
-
} else if (isSelected) {
|
|
84
|
-
// Toggle off a single id
|
|
85
|
-
updatedIds = selectedIds.filter((id) => id !== clickedId)
|
|
86
|
-
} else {
|
|
87
|
-
// Toggle on a single id
|
|
88
|
-
updatedIds = [...selectedIds, clickedId]
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return setSelectedIds(updatedIds)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const transactPatches = async (patches, message) => {
|
|
95
|
-
const transaction = client.transaction()
|
|
96
|
-
|
|
97
|
-
patches.forEach((patchArgs) => transaction.patch(...patchArgs))
|
|
98
|
-
|
|
99
|
-
await transaction
|
|
100
|
-
.commit()
|
|
101
|
-
.then((updated) => {
|
|
102
|
-
clearSelected()
|
|
103
|
-
setDraggingId(``)
|
|
104
|
-
setListIsUpdating(false)
|
|
105
|
-
toast.push({
|
|
106
|
-
title: `${
|
|
107
|
-
updated.results.length === 1 ? `1 Document` : `${updated.results.length} Documents`
|
|
108
|
-
} Reordered`,
|
|
109
|
-
status: `success`,
|
|
110
|
-
description: message,
|
|
111
|
-
})
|
|
112
|
-
})
|
|
113
|
-
.catch(() => {
|
|
114
|
-
setDraggingId(``)
|
|
115
|
-
setListIsUpdating(false)
|
|
116
|
-
toast.push({
|
|
117
|
-
title: `Reordering failed`,
|
|
118
|
-
status: `critical`,
|
|
119
|
-
})
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const handleDragEnd = (result, entities) => {
|
|
124
|
-
setDraggingId(``)
|
|
125
|
-
|
|
126
|
-
const {source, destination, draggableId} = result ?? {}
|
|
127
|
-
|
|
128
|
-
// Don't do anything if nothing changed
|
|
129
|
-
if (source.index === destination.index) return
|
|
130
|
-
|
|
131
|
-
// Don't do anything if we don't have the entitites
|
|
132
|
-
if (!entities?.length) return
|
|
133
|
-
|
|
134
|
-
// A document can be dragged without being one-of-many-selected
|
|
135
|
-
const effectedIds = selectedIds?.length ? selectedIds : [draggableId]
|
|
136
|
-
|
|
137
|
-
// Don't do anything if we don't have ids to effect
|
|
138
|
-
if (!effectedIds?.length) return
|
|
139
|
-
|
|
140
|
-
// Update state to update styles + prevent data refetching
|
|
141
|
-
setListIsUpdating(true)
|
|
142
|
-
setSelectedIds(effectedIds)
|
|
143
|
-
|
|
144
|
-
const {newOrder, patches, message} = reorderDocuments({
|
|
145
|
-
entities,
|
|
146
|
-
selectedIds: effectedIds,
|
|
147
|
-
source,
|
|
148
|
-
destination,
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
// Update local state
|
|
152
|
-
if (newOrder?.length) {
|
|
153
|
-
setOrderedData(newOrder)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Transact new order patches
|
|
157
|
-
if (patches?.length) {
|
|
158
|
-
transactPatches(patches, message)
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const handleDragStart = (start) => {
|
|
163
|
-
const id = start.draggableId
|
|
164
|
-
const selected = selectedIds.includes(id)
|
|
165
|
-
|
|
166
|
-
// if dragging an item that is not selected - unselect all items
|
|
167
|
-
if (!selected) clearSelected()
|
|
168
|
-
|
|
169
|
-
setDraggingId(id)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Move one document up or down one place, by fake invoking the drag function
|
|
173
|
-
const incrementIndex = (shiftFrom, shiftTo, id, entities) => {
|
|
174
|
-
const result = {
|
|
175
|
-
draggableId: id,
|
|
176
|
-
source: {index: shiftFrom},
|
|
177
|
-
destination: {index: shiftTo},
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return handleDragEnd(result, entities)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const onWindowKeyDown = (event) => {
|
|
184
|
-
if (event.key === 'Escape') {
|
|
185
|
-
clearSelected()
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
useEffect(() => {
|
|
190
|
-
window.addEventListener('keydown', onWindowKeyDown)
|
|
191
|
-
|
|
192
|
-
return () => {
|
|
193
|
-
window.removeEventListener('keydown', onWindowKeyDown)
|
|
194
|
-
}
|
|
195
|
-
}, [])
|
|
196
|
-
|
|
197
|
-
// Find all items with duplicate order field
|
|
198
|
-
const duplicateOrders = useMemo(() => {
|
|
199
|
-
if (!orderedData.length) return []
|
|
200
|
-
|
|
201
|
-
const orderField = orderedData.map((item) => item[ORDER_FIELD_NAME])
|
|
202
|
-
|
|
203
|
-
return orderField.filter((item, index) => orderField.indexOf(item) !== index)
|
|
204
|
-
}, [orderedData])
|
|
205
|
-
|
|
206
|
-
return (
|
|
207
|
-
<DragDropContext
|
|
208
|
-
onDragStart={handleDragStart}
|
|
209
|
-
onDragEnd={(result) => handleDragEnd(result, orderedData)}
|
|
210
|
-
>
|
|
211
|
-
<Droppable droppableId="documentSortZone">
|
|
212
|
-
{(provided, snapshot) => (
|
|
213
|
-
<div {...provided.droppableProps} ref={provided.innerRef}>
|
|
214
|
-
{orderedData.map((item, index) => (
|
|
215
|
-
<Draggable
|
|
216
|
-
key={`${item._id}-${item[ORDER_FIELD_NAME]}`}
|
|
217
|
-
draggableId={item._id}
|
|
218
|
-
index={index}
|
|
219
|
-
// onClick={(event) => handleDraggableClick(event, provided, snapshot)}
|
|
220
|
-
>
|
|
221
|
-
{(innerProvided, innerSnapshot) => {
|
|
222
|
-
const isSelected = selectedIds.includes(item._id)
|
|
223
|
-
const isDragging = innerSnapshot.isDragging
|
|
224
|
-
const isGhosting = Boolean(!isDragging && draggingId && isSelected)
|
|
225
|
-
const isUpdating = listIsUpdating && isSelected
|
|
226
|
-
const isDisabled = Boolean(!item[ORDER_FIELD_NAME])
|
|
227
|
-
const isDuplicate = duplicateOrders.includes(item[ORDER_FIELD_NAME])
|
|
228
|
-
const tone = cardTone({isDuplicate, isGhosting, isDragging, isSelected})
|
|
229
|
-
|
|
230
|
-
return (
|
|
231
|
-
<div
|
|
232
|
-
ref={innerProvided.innerRef}
|
|
233
|
-
{...innerProvided.draggableProps}
|
|
234
|
-
{...innerProvided.dragHandleProps}
|
|
235
|
-
style={
|
|
236
|
-
isDisabled
|
|
237
|
-
? {opacity: 0.2, pointerEvents: `none`}
|
|
238
|
-
: getItemStyle(innerProvided.draggableProps.style, isUpdating, isGhosting)
|
|
239
|
-
}
|
|
240
|
-
>
|
|
241
|
-
<Box paddingBottom={1}>
|
|
242
|
-
<Card tone={tone} shadow={isDragging ? `2` : undefined} radius={2}>
|
|
243
|
-
<Document
|
|
244
|
-
doc={item}
|
|
245
|
-
entities={orderedData}
|
|
246
|
-
handleSelect={handleSelect}
|
|
247
|
-
increment={incrementIndex}
|
|
248
|
-
index={index}
|
|
249
|
-
isFirst={index === 0}
|
|
250
|
-
isLast={index === orderedData.length - 1}
|
|
251
|
-
/>
|
|
252
|
-
</Card>
|
|
253
|
-
</Box>
|
|
254
|
-
</div>
|
|
255
|
-
)
|
|
256
|
-
}}
|
|
257
|
-
</Draggable>
|
|
258
|
-
))}
|
|
259
|
-
{provided.placeholder}
|
|
260
|
-
</div>
|
|
261
|
-
)}
|
|
262
|
-
</Droppable>
|
|
263
|
-
</DragDropContext>
|
|
264
|
-
)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
DraggableList.propTypes = {
|
|
268
|
-
data: PropTypes.arrayOf(
|
|
269
|
-
PropTypes.shape({
|
|
270
|
-
_id: PropTypes.string,
|
|
271
|
-
}).isRequired
|
|
272
|
-
).isRequired,
|
|
273
|
-
type: PropTypes.string.isRequired,
|
|
274
|
-
listIsUpdating: PropTypes.bool.isRequired,
|
|
275
|
-
setListIsUpdating: PropTypes.func.isRequired,
|
|
276
|
-
}
|
package/src/OrderableContext.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import sanityClient from 'part:@sanity/base/client'
|
|
2
|
-
import {ORDER_FIELD_NAME} from '../helpers/constants'
|
|
3
|
-
import initialRank from '../helpers/initialRank'
|
|
4
|
-
|
|
5
|
-
const client = sanityClient.withConfig({apiVersion: `2021-05-19`})
|
|
6
|
-
|
|
7
|
-
export const orderRankField = (config = {}) => {
|
|
8
|
-
if (!config?.type) {
|
|
9
|
-
throw new Error(
|
|
10
|
-
`
|
|
11
|
-
"type" not defined in orderRankField parameter object.
|
|
12
|
-
Example: orderRankField({type: 'category'})
|
|
13
|
-
`
|
|
14
|
-
)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const {type} = config
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
title: 'Order Rank',
|
|
21
|
-
readOnly: true,
|
|
22
|
-
hidden: true,
|
|
23
|
-
...config,
|
|
24
|
-
name: ORDER_FIELD_NAME,
|
|
25
|
-
type: 'string',
|
|
26
|
-
initialValue: async () => {
|
|
27
|
-
const lastDocOrderRank = await client.fetch(
|
|
28
|
-
`*[_type == $type]|order(@[$order] desc)[0][$order]`,
|
|
29
|
-
{type, order: ORDER_FIELD_NAME}
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
return initialRank(lastDocOrderRank)
|
|
33
|
-
},
|
|
34
|
-
}
|
|
35
|
-
}
|
package/src/helpers/constants.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const ORDER_FIELD_NAME = `orderRank`
|
package/src/index.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import {orderRankField} from './fields/orderRankField'
|
|
2
|
-
import {orderRankOrdering} from './fields/orderRankOrdering'
|
|
3
|
-
import {orderableDocumentListDeskItem} from './desk-structure/orderableDocumentListDeskItem'
|
|
4
|
-
|
|
5
|
-
export {orderRankField, orderRankOrdering, orderableDocumentListDeskItem}
|