feat: reordering documents in collection (#1722)

* tweaking effect details

* wrap work on this feature

* adds correct color to drop cursor

* simplify logic for early return

* much better comment so Tom doesn't fire me

* feat: Allow changing sort order of collections

* refactor: Move validation to model
feat: Make custom order the default (in prep for dnd)

* feat: Add sort choice to edit collection modal
fix: Improved styling of generic InputSelect

* fix: Vertical space left after removing previous collection description

* chore: Tweak language, menu contents, add auto-disclosure on sub menus

* only show drop-to-reorder cursor when sort is set to manual

Co-authored-by: Tom Moor <tom.moor@gmail.com>
This commit is contained in:
Nan Yu
2020-12-31 12:51:12 -08:00
committed by GitHub
parent ba61091c4c
commit 2cc45187e6
22 changed files with 435 additions and 109 deletions

View File

@@ -1,5 +1,5 @@
// @flow
import { find, concat, remove, uniq } from "lodash";
import { find, findIndex, concat, remove, uniq } from "lodash";
import randomstring from "randomstring";
import slug from "slug";
import { DataTypes, sequelize } from "../sequelize";
@@ -24,6 +24,27 @@ const Collection = sequelize.define(
private: DataTypes.BOOLEAN,
maintainerApprovalRequired: DataTypes.BOOLEAN,
documentStructure: DataTypes.JSONB,
sort: {
type: DataTypes.JSONB,
validate: {
isSort(value) {
if (
typeof value !== "object" ||
!value.direction ||
!value.field ||
Object.keys(value).length !== 2
) {
throw new Error("Sort must be an object with field,direction");
}
if (!["asc", "desc"].includes(value.direction)) {
throw new Error("Sort direction must be one of asc,desc");
}
if (!["title", "index"].includes(value.field)) {
throw new Error("Sort field must be one of title,index");
}
},
},
},
},
{
tableName: "collections",
@@ -41,6 +62,11 @@ const Collection = sequelize.define(
}
);
Collection.DEFAULT_SORT = {
field: "index",
direction: "asc",
};
Collection.addHook("beforeSave", async (model) => {
if (model.icon === "collection") {
model.icon = null;
@@ -350,7 +376,7 @@ Collection.prototype.removeDocumentInStructure = async function (
const match = find(children, { id });
if (match) {
if (!returnValue) returnValue = match;
if (!returnValue) returnValue = [match, findIndex(children, { id })];
remove(children, { id });
}

View File

@@ -145,6 +145,7 @@ Team.prototype.provisionFirstCollection = async function (userId) {
"This collection is a quick guide to what Outline is all about. Feel free to delete this collection once your team is up to speed with the basics!",
teamId: this.id,
creatorId: userId,
sort: Collection.DEFAULT_SORT,
});
// For the first collection we go ahead and create some intitial documents to get