Skip to content

Commit

Permalink
feat: implement dashboard endpoints (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
StructuralRealist authored Sep 6, 2023
1 parent ba34e3e commit 71ce307
Show file tree
Hide file tree
Showing 43 changed files with 653 additions and 701 deletions.
563 changes: 355 additions & 208 deletions package-lock.json

Large diffs are not rendered by default.

File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions packages/content-platform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Curator Content Platform

Plugin for turning Strapi into a full-featured content platform.

## Features

- Audit logs
- Dashboard (recently edited, user's drafts, etc.)
- Versioning
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@curatorjs/strapi",
"name": "@curatorjs/content-platform",
"version": "0.1.0",
"description": "Curator plugin for Strapi.",
"main": "strapi-server.js",
Expand All @@ -13,13 +13,13 @@
"ramda": "^0.29.0"
},
"devDependencies": {
"@strapi/typescript-utils": "4.13.1",
"@strapi/strapi": "^4.13.1",
"@strapi/typescript-utils": "4.13.3",
"@strapi/strapi": "^4.13.3",
"@types/ramda": "0.29.3",
"typescript": "5.2.2"
},
"peerDependencies": {
"@strapi/strapi": "^4.13.0"
"@strapi/strapi": "^4.13.3"
},
"author": "Devtastic <hi@devtastic.build>",
"maintainers": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ export default async function ({ strapi }: { strapi: Strapi }) {
*/
strapi.db.lifecycles.subscribe(async (event) => {
const config = strapi.plugin("curator").config("audit");
const included: string[] = Array.isArray(config?.included)
? config.included
const include: string[] = Array.isArray(config?.include)
? config.include
: [];
const excluded: string[] = Array.isArray(config?.excluded)
? config.excluded
const exclude: string[] = Array.isArray(config?.exclude)
? config.exclude
: [];
const uidMatch =
R.anyPass([
R.startsWith("api::"),
R.includes(R.__, included),
R.includes(R.__, include),
R.equals("plugin::curator.curator-secret"),
])(event.model?.uid ?? "") && !excluded.includes(event.model?.uid);
])(event.model?.uid ?? "") && !exclude.includes(event.model?.uid);

if (
config &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
export default {
default: {
/*
* Eiter a boolean to enable/disable or a configuration object:
* {
* include: ['plugin::my-plugin.my-content-type'],
* exclude: ['api::page.page']
* }
*/
audit: true,
},
validator(config: Record<string, any>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
description: "A log of an action of a user.",
},
options: {
draftAndPublished: false,
draftAndPublish: false,
},
pluginOptions: {
"content-type-builder": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
description: "A key-value with role-based access scope.",
},
options: {
draftAndPublished: false,
draftAndPublish: false,
},
pluginOptions: {
"content-type-builder": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Strapi } from "@strapi/strapi";

export default ({ strapi }: { strapi: Strapi }) => ({
index() {
return strapi.plugin("curator").service("dashboardService").getData();
},
});
7 changes: 7 additions & 0 deletions packages/content-platform/server/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import dashboardController from "./dashboard.controller";
import secretsController from "./secrets.controller";

export default {
secretsController,
dashboardController,
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Strapi } from "@strapi/strapi";

export default ({ strapi }: { strapi: Strapi }) => ({
find() {
index() {
return strapi.plugin("curator").service("secretsService").getSecrets();
},
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions packages/content-platform/server/policies/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {};
File renamed without changes.
14 changes: 14 additions & 0 deletions packages/content-platform/server/routes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default [
{
method: "GET",
path: "/secrets",
handler: "secretsController.index",
config: {},
},
{
method: "GET",
path: "/dashboard",
handler: "dashboardController.index",
config: {},
},
];
93 changes: 93 additions & 0 deletions packages/content-platform/server/services/dashboard.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Strapi } from "@strapi/strapi";
import * as R from "ramda";

export default ({ strapi }: { strapi: Strapi }) => ({
async getData() {
const ctx = strapi.requestContext.get();

const recent = await this.getRecent(ctx);
const drafts = await this.getDrafts(ctx);

return { recent, drafts };
},
/**
* Get recently created or updated items.
*/
async getRecent(ctx: any) {
const user = ctx.state.user;
const query = await strapi.entityService.findMany(
"plugin::curator.curator-audit-log",
{
sort: "updatedAt:DESC",
filters: {
subjectId: user.id,
objectUid: {
$startsWith: "api::",
},
action: ["update", "create"],
},
}
);

const distinct: Record<string, any>[] = R.uniqBy(
R.props(["objectId", "objectUid"]),
query as any[]
).slice(0, 5);

let results: any[] = [];

for await (const item of distinct) {
try {
const data = await strapi.entityService.findOne(
item.objectUid,
item.objectId
);

results = [
...results,
{ uid: item.objectUid, id: item.objectId, attributes: data ?? {} },
];
} catch (e) {
console.warn(e);
}
}

return results;
},

/**
* Get draft content created by the current user.
*/
async getDrafts(ctx: any) {
const user = ctx.state.user;

const modelsWithDraftState = Object.values(strapi.contentTypes)
.filter(R.path(["options", "draftAndPublish"]))
.map<string>(R.prop<string>("uid"));

let results: any[] = [];

for await (const uid of modelsWithDraftState) {
try {
const data = (await strapi.entityService.findMany(uid as any, {
sort: "updatedAt:DESC",
filters: {
createdBy: user.id,
publishedAt: {
$null: true,
},
},
})) as any[];

results = [
...results,
...data.map(({ id, ...attributes }) => ({ id, uid, attributes })),
];
} catch (e) {
console.warn(e);
}
}

return results.slice(0, 10);
},
});
7 changes: 7 additions & 0 deletions packages/content-platform/server/services/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import secretsService from "./secrets.service";
import dashboardService from "./dashboard.service";

export default {
secretsService,
dashboardService,
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 0 additions & 3 deletions packages/strapi/README.md

This file was deleted.

Loading

0 comments on commit 71ce307

Please sign in to comment.