Add board feature

This commit is contained in:
julien vdb
2025-03-28 14:52:43 +01:00
parent 9d4ecb2733
commit c6d5936639
23 changed files with 3485 additions and 11 deletions

View File

@@ -1,12 +1,40 @@
export default [ export default [
'strapi::logger', "strapi::logger",
'strapi::errors', "strapi::errors",
'strapi::security', //'strapi::security',
'strapi::cors', {
'strapi::poweredBy', name: "strapi::security",
'strapi::query', config: {
'strapi::body', contentSecurityPolicy: {
'strapi::session', useDefaults: true,
'strapi::favicon', directives: {
'strapi::public', "connect-src": ["'self'", "https:"],
"img-src": [
"'self'",
"data:",
"blob:",
"market-assets.strapi.io",
"192.168.0.211:9000",
"beyonder.synology.me:9000",
],
"media-src": [
"'self'",
"data:",
"blob:",
"market-assets.strapi.io",
"192.168.0.211:9000",
"beyonder.synology.me:9000",
],
upgradeInsecureRequests: null,
},
},
},
},
"strapi::cors",
"strapi::poweredBy",
"strapi::query",
"strapi::body",
"strapi::session",
"strapi::favicon",
"strapi::public",
]; ];

View File

@@ -17,4 +17,26 @@ export default () => ({
}, },
}, },
}, },
upload: {
config: {
provider: "aws-s3",
providerOptions: {
//baseUrl: "http://192.168.0.211:9000/harmony",
baseUrl: "http://beyonder.synology.me:9000/harmony",
s3Options: {
credentials: {
accessKeyId: "admin",
secretAccessKey: "Apslxnap12bn23",
},
//endpoint: "http://192.168.0.211:9000",
endpoint: "http://beyonder.synology.me:9000",
region: "eu-west-3",
forcePathStyle: true,
params: {
Bucket: "harmony",
},
},
},
},
},
}); });

2891
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@
"@strapi/plugin-cloud": "5.8.1", "@strapi/plugin-cloud": "5.8.1",
"@strapi/plugin-users-permissions": "5.8.1", "@strapi/plugin-users-permissions": "5.8.1",
"@strapi/provider-email-nodemailer": "^5.9.0", "@strapi/provider-email-nodemailer": "^5.9.0",
"@strapi/provider-upload-aws-s3": "^5.11.0",
"@strapi/strapi": "5.8.1", "@strapi/strapi": "5.8.1",
"better-sqlite3": "11.3.0", "better-sqlite3": "11.3.0",
"pg": "^8.13.1", "pg": "^8.13.1",

View File

@@ -0,0 +1,59 @@
{
"kind": "collectionType",
"collectionName": "board_cards",
"info": {
"singularName": "board-card",
"pluralName": "board-cards",
"displayName": "BoardCard",
"description": ""
},
"options": {
"draftAndPublish": false
},
"pluginOptions": {},
"attributes": {
"title": {
"type": "string"
},
"description": {
"type": "text"
},
"order": {
"type": "integer"
},
"boardList": {
"type": "relation",
"relation": "manyToOne",
"target": "api::board-list.board-list",
"inversedBy": "cards"
},
"image": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images",
"files",
"videos",
"audios"
]
},
"type": {
"type": "enumeration",
"enum": [
"link",
"youtube",
"image",
"video",
"audio",
"pdf"
]
},
"url": {
"type": "string"
},
"imageUrl": {
"type": "string"
}
}
}

View File

@@ -0,0 +1,53 @@
/**
* board-card controller
*/
import { factories } from "@strapi/strapi";
export default factories.createCoreController(
"api::board-card.board-card",
({ strapi }) => ({
async delete(ctx) {
// some logic here
const response = await super.delete(ctx);
// some more logic
return response;
},
async create(ctx) {
ctx.request.body.data = JSON.parse(ctx.request.body.data);
switch (ctx.request.body.data.type) {
case "link":
case "image":
case "video":
case "audio":
case "pdf":
const files = Array.isArray(ctx.request.files.files)
? ctx.request.files.files[0]
: ctx.request.files.files;
const extension = files.originalFilename.match(/\.[0-9a-z]+$/i);
const payload = {
fileInfo: {
caption: "undefined",
alternativeText: ctx.request.body.data.title || "",
name: `${ctx.request.body.data.title}.${extension}`,
},
};
const asset = await strapi.services["plugin::upload.upload"].upload({
data: payload,
files,
});
ctx.request.body.data.image = asset[0].id;
break;
case "youtube":
const image = ctx.request.body.image;
ctx.request.body.data.imageUrl = image;
break;
}
const { data, meta } = await super.create(ctx);
return { data, meta };
},
})
);

View File

@@ -0,0 +1,7 @@
/**
* board-card router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::board-card.board-card');

View File

@@ -0,0 +1,7 @@
/**
* board-card service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::board-card.board-card');

View File

@@ -0,0 +1,34 @@
{
"kind": "collectionType",
"collectionName": "board_lists",
"info": {
"singularName": "board-list",
"pluralName": "board-lists",
"displayName": "BoardList",
"description": ""
},
"options": {
"draftAndPublish": false
},
"pluginOptions": {},
"attributes": {
"title": {
"type": "string"
},
"order": {
"type": "integer"
},
"board": {
"type": "relation",
"relation": "manyToOne",
"target": "api::board.board",
"inversedBy": "board_lists"
},
"cards": {
"type": "relation",
"relation": "oneToMany",
"target": "api::board-card.board-card",
"mappedBy": "boardList"
}
}
}

View File

@@ -0,0 +1,15 @@
/**
* board-list controller
*/
import { factories } from "@strapi/strapi";
export default factories.createCoreController(
"api::board-list.board-list",
({ strapi }) => ({
async update(ctx) {
console.log(ctx);
return super.update(ctx);
},
})
);

View File

@@ -0,0 +1,7 @@
/**
* board-list router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::board-list.board-list');

View File

@@ -0,0 +1,7 @@
/**
* board-list service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::board-list.board-list');

View File

@@ -0,0 +1,45 @@
{
"kind": "collectionType",
"collectionName": "boards",
"info": {
"singularName": "board",
"pluralName": "boards",
"displayName": "Board",
"description": ""
},
"options": {
"draftAndPublish": false
},
"pluginOptions": {},
"attributes": {
"title": {
"type": "string"
},
"image": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images",
"files",
"videos",
"audios"
]
},
"choral": {
"type": "relation",
"relation": "manyToOne",
"target": "api::choral.choral",
"inversedBy": "boards"
},
"unsplashImage": {
"type": "string"
},
"board_lists": {
"type": "relation",
"relation": "oneToMany",
"target": "api::board-list.board-list",
"mappedBy": "board"
}
}
}

View File

@@ -0,0 +1,18 @@
/**
* board controller
*/
import { factories } from "@strapi/strapi";
export default factories.createCoreController(
"api::board.board",
({ strapi }) => ({
async update(ctx) {
return super.update(ctx);
},
async find(ctx) {
console.log(ctx);
return super.find(ctx);
},
})
);

View File

@@ -0,0 +1,7 @@
/**
* board router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::board.board');

View File

@@ -0,0 +1,7 @@
/**
* board service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::board.board');

View File

@@ -0,0 +1,66 @@
{
"kind": "collectionType",
"collectionName": "chorals",
"info": {
"singularName": "choral",
"pluralName": "chorals",
"displayName": "Choral",
"description": ""
},
"options": {
"draftAndPublish": false
},
"pluginOptions": {},
"attributes": {
"name": {
"type": "string"
},
"cover": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images",
"files",
"videos",
"audios"
]
},
"country": {
"type": "string"
},
"address": {
"type": "string"
},
"city": {
"type": "string"
},
"postal": {
"type": "integer"
},
"owner": {
"type": "relation",
"relation": "oneToOne",
"target": "plugin::users-permissions.user",
"inversedBy": "choralOwner"
},
"admins": {
"type": "relation",
"relation": "manyToMany",
"target": "plugin::users-permissions.user",
"inversedBy": "choralAdmin"
},
"users": {
"type": "relation",
"relation": "manyToMany",
"target": "plugin::users-permissions.user",
"inversedBy": "chorals"
},
"boards": {
"type": "relation",
"relation": "oneToMany",
"target": "api::board.board",
"mappedBy": "choral"
}
}
}

View File

@@ -0,0 +1,7 @@
/**
* choral controller
*/
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::choral.choral');

View File

@@ -0,0 +1,7 @@
/**
* choral router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::choral.choral');

View File

@@ -0,0 +1,7 @@
/**
* choral service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::choral.choral');

View File

@@ -88,6 +88,24 @@
"nbSaved": { "nbSaved": {
"type": "integer", "type": "integer",
"default": 0 "default": 0
},
"choralOwner": {
"type": "relation",
"relation": "oneToOne",
"target": "api::choral.choral",
"mappedBy": "owner"
},
"choralAdmin": {
"type": "relation",
"relation": "manyToMany",
"target": "api::choral.choral",
"mappedBy": "admins"
},
"chorals": {
"type": "relation",
"relation": "manyToMany",
"target": "api::choral.choral",
"mappedBy": "users"
} }
} }
} }

View File

@@ -13,7 +13,8 @@
"noEmitOnError": true, "noEmitOnError": true,
"noImplicitThis": true, "noImplicitThis": true,
"outDir": "dist", "outDir": "dist",
"rootDir": "." "rootDir": ".",
"sourceMap": true
}, },
"include": [ "include": [
// Include root files // Include root files

View File

@@ -369,6 +369,159 @@ export interface AdminUser extends Struct.CollectionTypeSchema {
}; };
} }
export interface ApiBoardCardBoardCard extends Struct.CollectionTypeSchema {
collectionName: 'board_cards';
info: {
description: '';
displayName: 'BoardCard';
pluralName: 'board-cards';
singularName: 'board-card';
};
options: {
draftAndPublish: false;
};
attributes: {
boardList: Schema.Attribute.Relation<
'manyToOne',
'api::board-list.board-list'
>;
createdAt: Schema.Attribute.DateTime;
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
description: Schema.Attribute.Text;
image: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>;
imageUrl: Schema.Attribute.String;
locale: Schema.Attribute.String & Schema.Attribute.Private;
localizations: Schema.Attribute.Relation<
'oneToMany',
'api::board-card.board-card'
> &
Schema.Attribute.Private;
order: Schema.Attribute.Integer;
publishedAt: Schema.Attribute.DateTime;
title: Schema.Attribute.String;
type: Schema.Attribute.Enumeration<
['link', 'youtube', 'image', 'video', 'audio', 'pdf']
>;
updatedAt: Schema.Attribute.DateTime;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
url: Schema.Attribute.String;
};
}
export interface ApiBoardListBoardList extends Struct.CollectionTypeSchema {
collectionName: 'board_lists';
info: {
description: '';
displayName: 'BoardList';
pluralName: 'board-lists';
singularName: 'board-list';
};
options: {
draftAndPublish: false;
};
attributes: {
board: Schema.Attribute.Relation<'manyToOne', 'api::board.board'>;
cards: Schema.Attribute.Relation<'oneToMany', 'api::board-card.board-card'>;
createdAt: Schema.Attribute.DateTime;
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String & Schema.Attribute.Private;
localizations: Schema.Attribute.Relation<
'oneToMany',
'api::board-list.board-list'
> &
Schema.Attribute.Private;
order: Schema.Attribute.Integer;
publishedAt: Schema.Attribute.DateTime;
title: Schema.Attribute.String;
updatedAt: Schema.Attribute.DateTime;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
};
}
export interface ApiBoardBoard extends Struct.CollectionTypeSchema {
collectionName: 'boards';
info: {
description: '';
displayName: 'Board';
pluralName: 'boards';
singularName: 'board';
};
options: {
draftAndPublish: false;
};
attributes: {
board_lists: Schema.Attribute.Relation<
'oneToMany',
'api::board-list.board-list'
>;
choral: Schema.Attribute.Relation<'manyToOne', 'api::choral.choral'>;
createdAt: Schema.Attribute.DateTime;
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
image: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>;
locale: Schema.Attribute.String & Schema.Attribute.Private;
localizations: Schema.Attribute.Relation<'oneToMany', 'api::board.board'> &
Schema.Attribute.Private;
publishedAt: Schema.Attribute.DateTime;
title: Schema.Attribute.String;
unsplashImage: Schema.Attribute.String;
updatedAt: Schema.Attribute.DateTime;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
};
}
export interface ApiChoralChoral extends Struct.CollectionTypeSchema {
collectionName: 'chorals';
info: {
description: '';
displayName: 'Choral';
pluralName: 'chorals';
singularName: 'choral';
};
options: {
draftAndPublish: false;
};
attributes: {
address: Schema.Attribute.String;
admins: Schema.Attribute.Relation<
'manyToMany',
'plugin::users-permissions.user'
>;
boards: Schema.Attribute.Relation<'oneToMany', 'api::board.board'>;
city: Schema.Attribute.String;
country: Schema.Attribute.String;
cover: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>;
createdAt: Schema.Attribute.DateTime;
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String & Schema.Attribute.Private;
localizations: Schema.Attribute.Relation<
'oneToMany',
'api::choral.choral'
> &
Schema.Attribute.Private;
name: Schema.Attribute.String;
owner: Schema.Attribute.Relation<
'oneToOne',
'plugin::users-permissions.user'
>;
postal: Schema.Attribute.Integer;
publishedAt: Schema.Attribute.DateTime;
updatedAt: Schema.Attribute.DateTime;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
users: Schema.Attribute.Relation<
'manyToMany',
'plugin::users-permissions.user'
>;
};
}
export interface PluginContentReleasesRelease export interface PluginContentReleasesRelease
extends Struct.CollectionTypeSchema { extends Struct.CollectionTypeSchema {
collectionName: 'strapi_releases'; collectionName: 'strapi_releases';
@@ -828,6 +981,9 @@ export interface PluginUsersPermissionsUser
attributes: { attributes: {
avatar: Schema.Attribute.Media<'images'>; avatar: Schema.Attribute.Media<'images'>;
blocked: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>; blocked: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
choralAdmin: Schema.Attribute.Relation<'manyToMany', 'api::choral.choral'>;
choralOwner: Schema.Attribute.Relation<'oneToOne', 'api::choral.choral'>;
chorals: Schema.Attribute.Relation<'manyToMany', 'api::choral.choral'>;
confirmationToken: Schema.Attribute.String & Schema.Attribute.Private; confirmationToken: Schema.Attribute.String & Schema.Attribute.Private;
confirmed: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>; confirmed: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
createdAt: Schema.Attribute.DateTime; createdAt: Schema.Attribute.DateTime;
@@ -882,6 +1038,10 @@ declare module '@strapi/strapi' {
'admin::transfer-token': AdminTransferToken; 'admin::transfer-token': AdminTransferToken;
'admin::transfer-token-permission': AdminTransferTokenPermission; 'admin::transfer-token-permission': AdminTransferTokenPermission;
'admin::user': AdminUser; 'admin::user': AdminUser;
'api::board-card.board-card': ApiBoardCardBoardCard;
'api::board-list.board-list': ApiBoardListBoardList;
'api::board.board': ApiBoardBoard;
'api::choral.choral': ApiChoralChoral;
'plugin::content-releases.release': PluginContentReleasesRelease; 'plugin::content-releases.release': PluginContentReleasesRelease;
'plugin::content-releases.release-action': PluginContentReleasesReleaseAction; 'plugin::content-releases.release-action': PluginContentReleasesReleaseAction;
'plugin::i18n.locale': PluginI18NLocale; 'plugin::i18n.locale': PluginI18NLocale;