Make all articles public
This commit is contained in:
parent
92e96b9107
commit
555b200ec7
18 changed files with 24541 additions and 94 deletions
|
|
@ -1,111 +1,117 @@
|
||||||
import { Schema, model, Document, Types } from 'mongoose'
|
import { Schema, model, Document, Types } from "mongoose";
|
||||||
|
|
||||||
export interface IRevision {
|
export interface IRevision {
|
||||||
content: string
|
content: string;
|
||||||
author: Types.ObjectId
|
author: Types.ObjectId;
|
||||||
message: string
|
message: string;
|
||||||
createdAt: Date
|
createdAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IComment {
|
export interface IComment {
|
||||||
author: Types.ObjectId
|
author: Types.ObjectId;
|
||||||
content: string
|
content: string;
|
||||||
parentComment?: Types.ObjectId
|
parentComment?: Types.ObjectId;
|
||||||
createdAt: Date
|
createdAt: Date;
|
||||||
updatedAt: Date
|
updatedAt: Date;
|
||||||
resolved: boolean
|
resolved: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IArticle extends Document {
|
export interface IArticle extends Document {
|
||||||
slug: string
|
slug: string;
|
||||||
title: string
|
title: string;
|
||||||
description: string
|
description: string;
|
||||||
content: string // Current content in markdown
|
content: string; // Current content in markdown
|
||||||
category: string
|
category: string;
|
||||||
tags: string[]
|
tags: string[];
|
||||||
|
|
||||||
// Access control
|
// Access control
|
||||||
accessLevel: 'public' | 'member' | 'cohort' | 'admin'
|
accessLevel: "public" | "member" | "cohort" | "admin";
|
||||||
cohorts?: string[] // Specific cohorts if accessLevel is 'cohort'
|
cohorts?: string[]; // Specific cohorts if accessLevel is 'cohort'
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
author: Types.ObjectId
|
author: Types.ObjectId;
|
||||||
contributors: Types.ObjectId[]
|
contributors: Types.ObjectId[];
|
||||||
views: number
|
views: number;
|
||||||
likes: number
|
likes: number;
|
||||||
|
|
||||||
// Editing
|
// Editing
|
||||||
status: 'draft' | 'published' | 'archived'
|
status: "draft" | "published" | "archived";
|
||||||
lockedBy?: Types.ObjectId // If someone is currently editing
|
lockedBy?: Types.ObjectId; // If someone is currently editing
|
||||||
lockedAt?: Date
|
lockedAt?: Date;
|
||||||
|
|
||||||
// History
|
// History
|
||||||
revisions: IRevision[]
|
revisions: IRevision[];
|
||||||
comments: IComment[]
|
comments: IComment[];
|
||||||
|
|
||||||
// Timestamps
|
// Timestamps
|
||||||
createdAt: Date
|
createdAt: Date;
|
||||||
updatedAt: Date
|
updatedAt: Date;
|
||||||
publishedAt?: Date
|
publishedAt?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
const revisionSchema = new Schema<IRevision>({
|
const revisionSchema = new Schema<IRevision>({
|
||||||
content: { type: String, required: true },
|
content: { type: String, required: true },
|
||||||
author: { type: Schema.Types.ObjectId, ref: 'User', required: true },
|
author: { type: Schema.Types.ObjectId, ref: "User", required: true },
|
||||||
message: { type: String, required: true },
|
message: { type: String, required: true },
|
||||||
createdAt: { type: Date, default: Date.now }
|
createdAt: { type: Date, default: Date.now },
|
||||||
})
|
});
|
||||||
|
|
||||||
const commentSchema = new Schema<IComment>({
|
const commentSchema = new Schema<IComment>(
|
||||||
author: { type: Schema.Types.ObjectId, ref: 'User', required: true },
|
{
|
||||||
content: { type: String, required: true },
|
author: { type: Schema.Types.ObjectId, ref: "User", required: true },
|
||||||
parentComment: { type: Schema.Types.ObjectId, ref: 'Comment' },
|
content: { type: String, required: true },
|
||||||
resolved: { type: Boolean, default: false }
|
parentComment: { type: Schema.Types.ObjectId, ref: "Comment" },
|
||||||
}, {
|
resolved: { type: Boolean, default: false },
|
||||||
timestamps: true
|
|
||||||
})
|
|
||||||
|
|
||||||
const articleSchema = new Schema<IArticle>({
|
|
||||||
slug: { type: String, required: true, unique: true },
|
|
||||||
title: { type: String, required: true },
|
|
||||||
description: { type: String, required: true },
|
|
||||||
content: { type: String, required: true },
|
|
||||||
category: { type: String, required: true },
|
|
||||||
tags: [{ type: String }],
|
|
||||||
|
|
||||||
accessLevel: {
|
|
||||||
type: String,
|
|
||||||
enum: ['public', 'member', 'cohort', 'admin'],
|
|
||||||
default: 'member'
|
|
||||||
},
|
},
|
||||||
cohorts: [{ type: String }],
|
{
|
||||||
|
timestamps: true,
|
||||||
author: { type: Schema.Types.ObjectId, ref: 'User', required: true },
|
|
||||||
contributors: [{ type: Schema.Types.ObjectId, ref: 'User' }],
|
|
||||||
views: { type: Number, default: 0 },
|
|
||||||
likes: { type: Number, default: 0 },
|
|
||||||
|
|
||||||
status: {
|
|
||||||
type: String,
|
|
||||||
enum: ['draft', 'published', 'archived'],
|
|
||||||
default: 'draft'
|
|
||||||
},
|
},
|
||||||
lockedBy: { type: Schema.Types.ObjectId, ref: 'User' },
|
);
|
||||||
lockedAt: Date,
|
|
||||||
|
|
||||||
revisions: [revisionSchema],
|
const articleSchema = new Schema<IArticle>(
|
||||||
comments: [commentSchema],
|
{
|
||||||
|
slug: { type: String, required: true, unique: true },
|
||||||
|
title: { type: String, required: true },
|
||||||
|
description: { type: String, required: true },
|
||||||
|
content: { type: String, required: true },
|
||||||
|
category: { type: String, required: true },
|
||||||
|
tags: [{ type: String }],
|
||||||
|
|
||||||
publishedAt: Date
|
accessLevel: {
|
||||||
}, {
|
type: String,
|
||||||
timestamps: true
|
enum: ["public", "member", "cohort", "admin"],
|
||||||
})
|
default: "public",
|
||||||
|
},
|
||||||
|
cohorts: [{ type: String }],
|
||||||
|
|
||||||
|
author: { type: Schema.Types.ObjectId, ref: "User", required: true },
|
||||||
|
contributors: [{ type: Schema.Types.ObjectId, ref: "User" }],
|
||||||
|
views: { type: Number, default: 0 },
|
||||||
|
likes: { type: Number, default: 0 },
|
||||||
|
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
enum: ["draft", "published", "archived"],
|
||||||
|
default: "draft",
|
||||||
|
},
|
||||||
|
lockedBy: { type: Schema.Types.ObjectId, ref: "User" },
|
||||||
|
lockedAt: Date,
|
||||||
|
|
||||||
|
revisions: [revisionSchema],
|
||||||
|
comments: [commentSchema],
|
||||||
|
|
||||||
|
publishedAt: Date,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Indexes for better query performance
|
// Indexes for better query performance
|
||||||
articleSchema.index({ slug: 1 })
|
articleSchema.index({ slug: 1 });
|
||||||
articleSchema.index({ accessLevel: 1, status: 1 })
|
articleSchema.index({ accessLevel: 1, status: 1 });
|
||||||
articleSchema.index({ tags: 1 })
|
articleSchema.index({ tags: 1 });
|
||||||
articleSchema.index({ category: 1 })
|
articleSchema.index({ category: 1 });
|
||||||
articleSchema.index({ author: 1 })
|
articleSchema.index({ author: 1 });
|
||||||
|
|
||||||
export const Article = model<IArticle>('Article', articleSchema)
|
export const Article = model<IArticle>("Article", articleSchema);
|
||||||
|
|
|
||||||
24357
content/articles/.obsidian/plugins/global-search-and-replace/main.js
vendored
Normal file
24357
content/articles/.obsidian/plugins/global-search-and-replace/main.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
10
content/articles/.obsidian/plugins/global-search-and-replace/manifest.json
vendored
Normal file
10
content/articles/.obsidian/plugins/global-search-and-replace/manifest.json
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"id": "global-search-and-replace",
|
||||||
|
"name": "Global Search and Replace",
|
||||||
|
"version": "0.5.0",
|
||||||
|
"minAppVersion": "1.1.1",
|
||||||
|
"description": "Search and replace in all vault files",
|
||||||
|
"author": "Mahmoud Fawzy Khalil",
|
||||||
|
"authorUrl": "https://github.com/MahmoudFawzyKhalil/",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
||||||
74
content/articles/.obsidian/plugins/global-search-and-replace/styles.css
vendored
Normal file
74
content/articles/.obsidian/plugins/global-search-and-replace/styles.css
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
.snr-line-number {
|
||||||
|
font-size: var(--font-ui-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-suggestion-content {
|
||||||
|
/* Nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-suggestion-flair {
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-suggestion-aux {
|
||||||
|
max-width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-highlight {
|
||||||
|
color: var(--text-normal);
|
||||||
|
background-color: var(--text-highlight-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-input-button-wrapper {
|
||||||
|
/*margin-top: var(--size-4-2);*/
|
||||||
|
/*margin-bottom: var(--size-4-2);*/
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--size-4-4);
|
||||||
|
border-bottom: 1px solid var(--background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-input-button-wrapper > button {
|
||||||
|
margin-right: var(--size-4-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.is-phone .snr-input-button-wrapper > button {
|
||||||
|
margin-right: var(--size-4-4);
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-tablet .snr-input-button-wrapper > button {
|
||||||
|
margin-right: var(--size-4-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-input-icon-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid var(--background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-regex-button {
|
||||||
|
margin-right: var(--size-4-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-workspace-tab-header-inner {
|
||||||
|
padding: var(--size-4-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-workspace-tab-header-inner-icon-active {
|
||||||
|
background-color: var(--background-modifier-form-field);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snr-result-summary {
|
||||||
|
border-top: 1px solid var(--background-secondary);
|
||||||
|
user-select: none;
|
||||||
|
font-size: var(--font-ui-smaller);
|
||||||
|
color: var(--text-muted);
|
||||||
|
padding: var(--size-4-2);
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.227Z'
|
publishedAt: '2025-11-10T10:42:09.227Z'
|
||||||
---
|
---
|
||||||
# Actionable Steam metrics
|
# Actionable Steam metrics
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: A business plan is a critical document for impact-oriented studios.
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.221Z'
|
publishedAt: '2025-11-10T10:42:09.221Z'
|
||||||
---
|
---
|
||||||
# Business planning for impact
|
# Business planning for impact
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.229Z'
|
publishedAt: '2025-11-10T10:42:09.229Z'
|
||||||
---
|
---
|
||||||
# Fund your game with Canada Council
|
# Fund your game with Canada Council
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.229Z'
|
publishedAt: '2025-11-10T10:42:09.229Z'
|
||||||
---
|
---
|
||||||
# CMF Application Tips & Info
|
# CMF Application Tips & Info
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.230Z'
|
publishedAt: '2025-11-10T10:42:09.230Z'
|
||||||
---
|
---
|
||||||
# Rocket Adrift Tips for In-Person Expositions
|
# Rocket Adrift Tips for In-Person Expositions
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.227Z'
|
publishedAt: '2025-11-10T10:42:09.227Z'
|
||||||
---
|
---
|
||||||
# Summary: The Complete Game Discovery Toolkit
|
# Summary: The Complete Game Discovery Toolkit
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: Market Analysis
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.226Z'
|
publishedAt: '2025-11-10T10:42:09.226Z'
|
||||||
---
|
---
|
||||||
# Market Analysis
|
# Market Analysis
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: Pitching to Publishers
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.228Z'
|
publishedAt: '2025-11-10T10:42:09.228Z'
|
||||||
---
|
---
|
||||||
# Pitching to Publishers
|
# Pitching to Publishers
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.229Z'
|
publishedAt: '2025-11-10T10:42:09.229Z'
|
||||||
---
|
---
|
||||||
# Whitethorn Games Contract Review
|
# Whitethorn Games Contract Review
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: programs
|
category: programs
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.231Z'
|
publishedAt: '2025-11-10T10:42:09.231Z'
|
||||||
---
|
---
|
||||||
# Program Schedule
|
# Program Schedule
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: programs
|
category: programs
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.231Z'
|
publishedAt: '2025-11-10T10:42:09.231Z'
|
||||||
---
|
---
|
||||||
[Self-Assessment Document](https://docs.google.com/document/d/15og3YqFdMO3o3zr-fbYgwPHgbQnevbxZ7SVCcbjRhc8/edit?usp=drive_link) - go to the File menu and select _Make a Copy_.
|
[Self-Assessment Document](https://docs.google.com/document/d/15og3YqFdMO3o3zr-fbYgwPHgbQnevbxZ7SVCcbjRhc8/edit?usp=drive_link) - go to the File menu and select _Make a Copy_.
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: programs
|
category: programs
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.232Z'
|
publishedAt: '2025-11-10T10:42:09.232Z'
|
||||||
---
|
---
|
||||||
# Stages of Cooperative Development
|
# Stages of Cooperative Development
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: ''
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.223Z'
|
publishedAt: '2025-11-10T10:42:09.223Z'
|
||||||
---
|
---
|
||||||
# Choosing an impactful business structure
|
# Choosing an impactful business structure
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: 'TikTok Marketing Meeting: July 3, 2023'
|
||||||
category: strategy
|
category: strategy
|
||||||
tags: []
|
tags: []
|
||||||
accessLevel: member
|
accessLevel: member
|
||||||
author: Baby Ghosts Team
|
author: Baby Ghosts
|
||||||
publishedAt: '2025-11-10T10:42:09.230Z'
|
publishedAt: '2025-11-10T10:42:09.230Z'
|
||||||
---
|
---
|
||||||
# TikTok Marketing Meeting: July 3, 2023
|
# TikTok Marketing Meeting: July 3, 2023
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue