From 41790ea1c18ef90fb62f2b3cdfde41f1fd2062b6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 4 May 2021 21:15:57 +0900 Subject: [PATCH] Ad (#7495) * wip * Update ad.vue * Update default.widgets.vue * wip * Create 1620019354680-ad.ts * wip * Update ads.vue * wip * Update ad.vue --- locales/ja-JP.yml | 7 + migration/1620019354680-ad.ts | 18 +++ package.json | 1 - src/client/components/date-separated-list.vue | 22 ++- src/client/components/global/ad.vue | 142 ++++++++++++++++++ src/client/components/index.ts | 4 +- src/client/components/notes.vue | 2 +- src/client/pages/gallery/post.vue | 1 + src/client/pages/instance/ads.vue | 125 +++++++++++++++ src/client/pages/instance/index.vue | 2 + src/client/pages/page.vue | 1 + src/client/scripts/paging.ts | 8 +- src/client/style.scss | 2 + src/client/ui/chat/date-separated-list.vue | 6 +- src/client/ui/default.widgets.vue | 1 + src/db/postgre.ts | 2 + src/models/entities/ad.ts | 53 +++++++ src/models/index.ts | 2 + src/models/repositories/note.ts | 11 +- src/server/api/endpoints/admin/ad/create.ts | 45 ++++++ src/server/api/endpoints/admin/ad/delete.ts | 34 +++++ src/server/api/endpoints/admin/ad/list.ts | 36 +++++ src/server/api/endpoints/admin/ad/update.ts | 59 ++++++++ src/server/api/endpoints/meta.ts | 39 ++++- 24 files changed, 596 insertions(+), 27 deletions(-) create mode 100644 migration/1620019354680-ad.ts create mode 100644 src/client/components/global/ad.vue create mode 100644 src/client/pages/instance/ads.vue create mode 100644 src/models/entities/ad.ts create mode 100644 src/server/api/endpoints/admin/ad/create.ts create mode 100644 src/server/api/endpoints/admin/ad/delete.ts create mode 100644 src/server/api/endpoints/admin/ad/list.ts create mode 100644 src/server/api/endpoints/admin/ad/update.ts diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 5a3f40a6d..0f786a6b1 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -748,6 +748,13 @@ gallery: "ギャラリー" recentPosts: "最近の投稿" popularPosts: "人気の投稿" shareWithNote: "ノートで共有" +ads: "広告" +expiration: "期限" +memo: "メモ" +priority: "優先度" +high: "高" +middle: "中" +low: "低" emailNotConfiguredWarning: "メールアドレスの設定がされていません。" _forgotPassword: diff --git a/migration/1620019354680-ad.ts b/migration/1620019354680-ad.ts new file mode 100644 index 000000000..27fb99f18 --- /dev/null +++ b/migration/1620019354680-ad.ts @@ -0,0 +1,18 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ad1620019354680 implements MigrationInterface { + name = 'ad1620019354680' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "ad" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, "place" character varying(32) NOT NULL, "priority" character varying(32) NOT NULL, "url" character varying(1024) NOT NULL, "imageUrl" character varying(1024) NOT NULL, "memo" character varying(8192) NOT NULL, CONSTRAINT "PK_0193d5ef09746e88e9ea92c634d" PRIMARY KEY ("id")); COMMENT ON COLUMN "ad"."createdAt" IS 'The created date of the Ad.'; COMMENT ON COLUMN "ad"."expiresAt" IS 'The expired date of the Ad.'`); + await queryRunner.query(`CREATE INDEX "IDX_1129c2ef687fc272df040bafaa" ON "ad" ("createdAt") `); + await queryRunner.query(`CREATE INDEX "IDX_2da24ce20ad209f1d9dc032457" ON "ad" ("expiresAt") `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_2da24ce20ad209f1d9dc032457"`); + await queryRunner.query(`DROP INDEX "IDX_1129c2ef687fc272df040bafaa"`); + await queryRunner.query(`DROP TABLE "ad"`); + } + +} diff --git a/package.json b/package.json index 25ebacaa7..9a1437366 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "resolutions": { "chokidar": "^3.3.1", "constantinople": "^4.0.1", - "gulp/gulp-cli/yargs/yargs-parser": "5.0.0-security.0", "jsonld/rdf-canonize/node-forge": "0.10.0", "lodash": "^4.17.20" }, diff --git a/src/client/components/date-separated-list.vue b/src/client/components/date-separated-list.vue index 2a861adb0..d458a0eeb 100644 --- a/src/client/components/date-separated-list.vue +++ b/src/client/components/date-separated-list.vue @@ -1,5 +1,6 @@ + + diff --git a/src/client/components/index.ts b/src/client/components/index.ts index 0630ed3d8..8b914c5ee 100644 --- a/src/client/components/index.ts +++ b/src/client/components/index.ts @@ -12,8 +12,10 @@ import url from './global/url.vue'; import i18n from './global/i18n'; import loading from './global/loading.vue'; import error from './global/error.vue'; +import ad from './global/ad.vue'; export default function(app: App) { + app.component('I18n', i18n); app.component('Mfm', mfm); app.component('MkA', a); app.component('MkAcct', acct); @@ -25,5 +27,5 @@ export default function(app: App) { app.component('MkUrl', url); app.component('MkLoading', loading); app.component('MkError', error); - app.component('I18n', i18n); + app.component('MkAd', ad); } diff --git a/src/client/components/notes.vue b/src/client/components/notes.vue index 675748d54..e90102921 100644 --- a/src/client/components/notes.vue +++ b/src/client/components/notes.vue @@ -17,7 +17,7 @@ - + diff --git a/src/client/pages/gallery/post.vue b/src/client/pages/gallery/post.vue index 703506a78..50f81376e 100644 --- a/src/client/pages/gallery/post.vue +++ b/src/client/pages/gallery/post.vue @@ -33,6 +33,7 @@ + diff --git a/src/client/pages/instance/ads.vue b/src/client/pages/instance/ads.vue new file mode 100644 index 000000000..4297e56c3 --- /dev/null +++ b/src/client/pages/instance/ads.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/src/client/pages/instance/index.vue b/src/client/pages/instance/index.vue index 5972a02de..974c4345b 100644 --- a/src/client/pages/instance/index.vue +++ b/src/client/pages/instance/index.vue @@ -23,6 +23,7 @@ {{ $ts.jobQueue }} {{ $ts.files }} {{ $ts.announcements }} + {{ $ts.ads }} {{ $ts.abuseReports }} @@ -102,6 +103,7 @@ export default defineComponent({ case 'queue': return defineAsyncComponent(() => import('./queue.vue')); case 'files': return defineAsyncComponent(() => import('./files.vue')); case 'announcements': return defineAsyncComponent(() => import('./announcements.vue')); + case 'ads': return defineAsyncComponent(() => import('./ads.vue')); case 'database': return defineAsyncComponent(() => import('./database.vue')); case 'abuses': return defineAsyncComponent(() => import('./abuses.vue')); case 'settings': return defineAsyncComponent(() => import('./settings.vue')); diff --git a/src/client/pages/page.vue b/src/client/pages/page.vue index 6ee3ee8d2..4e237c218 100644 --- a/src/client/pages/page.vue +++ b/src/client/pages/page.vue @@ -45,6 +45,7 @@
{{ $ts.createdAt }}:
{{ $ts.updatedAt }}:
+ diff --git a/src/client/scripts/paging.ts b/src/client/scripts/paging.ts index 2e49f1a64..bcb0d7f2b 100644 --- a/src/client/scripts/paging.ts +++ b/src/client/scripts/paging.ts @@ -91,8 +91,10 @@ export default (opts) => ({ ...params, limit: this.pagination.noPaging ? (this.pagination.limit || 10) : (this.pagination.limit || 10) + 1, }).then(items => { - for (const item of items) { + for (let i = 0; i < items.length; i++) { + const item = items[i]; markRaw(item); + if (i === 3) item._shouldInsertAd_ = true; } if (!this.pagination.noPaging && (items.length > (this.pagination.limit || 10))) { items.pop(); @@ -128,8 +130,10 @@ export default (opts) => ({ untilId: this.pagination.reversed ? this.items[0].id : this.items[this.items.length - 1].id, }), }).then(items => { - for (const item of items) { + for (let i = 0; i < items.length; i++) { + const item = items[i]; markRaw(item); + if (i === 10) item._shouldInsertAd_ = true; } if (items.length > SECOND_FETCH_LIMIT) { items.pop(); diff --git a/src/client/style.scss b/src/client/style.scss index 523ab1303..39bf6ef2d 100644 --- a/src/client/style.scss +++ b/src/client/style.scss @@ -11,6 +11,8 @@ @media (max-width: 500px) { --margin: var(--marginHalf); } + + //--ad: rgb(255 169 0 / 10%); } ::selection { diff --git a/src/client/ui/chat/date-separated-list.vue b/src/client/ui/chat/date-separated-list.vue index b073a38eb..bc7fc91d3 100644 --- a/src/client/ui/chat/date-separated-list.vue +++ b/src/client/ui/chat/date-separated-list.vue @@ -42,11 +42,7 @@ export default defineComponent({ if ( i != this.items.length - 1 && - new Date(item.createdAt).getDate() != new Date(this.items[i + 1].createdAt).getDate() && - !item._prId_ && - !this.items[i + 1]._prId_ && - !item._featuredId_ && - !this.items[i + 1]._featuredId_ + new Date(item.createdAt).getDate() != new Date(this.items[i + 1].createdAt).getDate() ) { const separator = h('div', { class: 'separator', diff --git a/src/client/ui/default.widgets.vue b/src/client/ui/default.widgets.vue index cabd83937..0dd073409 100644 --- a/src/client/ui/default.widgets.vue +++ b/src/client/ui/default.widgets.vue @@ -1,6 +1,7 @@