More things
This commit is contained in:
87
backend/src/models/EditProposal.js
Normal file
87
backend/src/models/EditProposal.js
Normal file
@@ -0,0 +1,87 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
export const PROPOSAL_STATUSES = ["pending", "approved", "rejected"];
|
||||
|
||||
/* When a member saves the wiki the change does not land on it: it is held here
|
||||
as a request for an admin to approve or reject. A request changes a page that
|
||||
exists (`kind: "edit"`), or asks for one that does not yet (`kind: "create"`)
|
||||
— an article, or a new language version of an existing one — and carries no
|
||||
article until an admin's approval writes it. One pending request per article
|
||||
and account — saving again while one waits revises it rather than stacking a
|
||||
second copy, and the same draft a create editor holds revises itself the same
|
||||
way. The account's name is kept beside its id so a request stays readable
|
||||
after the account itself is closed. */
|
||||
|
||||
export const PROPOSAL_KINDS = ["edit", "create"];
|
||||
|
||||
const editProposalSchema = new mongoose.Schema(
|
||||
{
|
||||
// Whether the request rewrites a page or asks for a new one to exist.
|
||||
kind: {
|
||||
type: String,
|
||||
enum: {
|
||||
values: PROPOSAL_KINDS,
|
||||
message: `Kind is one of: ${PROPOSAL_KINDS.join(", ")}.`,
|
||||
},
|
||||
default: "edit",
|
||||
},
|
||||
// The document the request wants to change, by id rather than slug: a
|
||||
// retitle moves the slug out from under it. Null while the page is only
|
||||
// being asked for; approval fills it in, so a decided request still names
|
||||
// the article it brought about.
|
||||
article: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Article",
|
||||
default: null,
|
||||
index: true,
|
||||
},
|
||||
// What a create asks the new page to be: the address it wants (the title
|
||||
// slugified, or `<identity>-<language>` for a translation — the address is
|
||||
// what tells one draft from another while both wait), and the identity of
|
||||
// the article it joins as a version, if it translates one.
|
||||
slug: { type: String, default: null, lowercase: true, trim: true },
|
||||
baseSlug: { type: String, default: null, lowercase: true, trim: true },
|
||||
// The text the editor was looking at — the other half of every diff on the
|
||||
// dashboard, and how a reviewer spots an article that moved underneath.
|
||||
// Empty for a creation: the page it asks for has nothing written on it.
|
||||
base: {
|
||||
title: { type: String, default: "" },
|
||||
content: { type: String, default: "" },
|
||||
tags: { type: [String], default: [] },
|
||||
},
|
||||
// The whole state being proposed, so approving is one application, not a patch
|
||||
title: {
|
||||
type: String,
|
||||
required: [true, "Title is required"],
|
||||
trim: true,
|
||||
},
|
||||
content: { type: String, default: "" },
|
||||
tags: { type: [String], default: [] },
|
||||
language: { type: String, default: "en", lowercase: true, trim: true },
|
||||
status: {
|
||||
type: String,
|
||||
enum: {
|
||||
values: PROPOSAL_STATUSES,
|
||||
message: `Status is one of: ${PROPOSAL_STATUSES.join(", ")}.`,
|
||||
},
|
||||
default: "pending",
|
||||
index: true,
|
||||
},
|
||||
createdBy: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
|
||||
createdByUsername: { type: String, default: "" },
|
||||
decidedBy: { type: mongoose.Schema.Types.ObjectId, ref: "User", default: null },
|
||||
decidedByUsername: { type: String, default: "" },
|
||||
decidedAt: { type: Date, default: null },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
// who has what waiting on which article — the filter the upsert saves through
|
||||
editProposalSchema.index({ article: 1, createdBy: 1, status: 1 });
|
||||
// ... and which address, for a request that names no article yet: the slug it
|
||||
// asks for tells one member's waiting drafts apart from another's
|
||||
editProposalSchema.index({ createdBy: 1, status: 1, kind: 1, slug: 1 });
|
||||
|
||||
const EditProposal = mongoose.model("EditProposal", editProposalSchema);
|
||||
|
||||
export default EditProposal;
|
||||
Reference in New Issue
Block a user