diff --git a/src/lib/db/suggest-change-store.ts b/src/lib/db/suggest-change-store.ts index 4553ab2b49..f778a92f3f 100644 --- a/src/lib/db/suggest-change-store.ts +++ b/src/lib/db/suggest-change-store.ts @@ -15,29 +15,29 @@ const T = { SUGGEST_CHANGE_SET: 'suggest_change_set', }; -interface ISuggestChangesetInsert { +interface ISuggestChangesetRow { id: number; + state: SuggestChangesetState; environment: string; - state?: string; - project?: string; - created_by?: number; - created_at?: Date; + project: string; + created_at: Date; + created_by: number; + changeSetUsername: string; + changeSetAvatar: string; + changeId: number; + changeFeature: string; + changeAction: SuggestChangeAction; + changePayload: any; + changeCreatedAt: Date; + changeCreatedBy: number; + changeCreatedByUsername: string; + changeCreatedByAvatar: string; } -interface ISuggestChangeInsert { - id: number; - action: SuggestChangeAction; - feature: string; - payload?: unknown; - created_by?: number; - created_at?: Date; -} - -interface ISuggestChangesetRow extends ISuggestChangesetInsert { - changes?: ISuggestChange[]; -} - -const suggestChangeRowReducer = (acc, suggestChangeRow) => { +const suggestChangeRowReducer = ( + acc: Record, + suggestChangeRow: ISuggestChangesetRow, +): Record => { const { changeId, changeAction, @@ -199,7 +199,7 @@ export class SuggestChangeStore implements ISuggestChangeStore { userId: number, ): Promise => { const [{ id }] = await this.db(T.SUGGEST_CHANGE_SET) - .insert({ + .insert({ environment: suggestChangeSet.environment, state: suggestChangeSet.state, project: suggestChangeSet.project, @@ -207,26 +207,31 @@ export class SuggestChangeStore implements ISuggestChangeStore { }) .returning('id'); - suggestChangeSet.changes.forEach((change) => { - this.addChangeToSet(change, id, userId); + suggestChangeSet.features.forEach((feature) => { + feature.changes.forEach((change) => { + this.addChangeToSet(change, feature.name, id, userId); + }); }); return this.get(id); }; addChangeToSet = async ( - change: PartialSome, + change: ISuggestChange, + feature: string, changeSetID: number, userId: number, ): Promise => { await this.db(T.SUGGEST_CHANGE) - .insert({ + .insert({ action: change.action, - feature: change.feature, + feature: feature, payload: change.payload, suggest_change_set_id: changeSetID, created_by: userId, }) + .onConflict(['action', 'suggest_change_set_id', 'feature']) + .merge() .returning('id'); }; @@ -234,6 +239,10 @@ export class SuggestChangeStore implements ISuggestChangeStore { return this.db(T.SUGGEST_CHANGE_SET).where({ id }).del(); }; + deleteChange = (id: number): Promise => { + return this.db(T.SUGGEST_CHANGE).where({ id }).del(); + }; + deleteAll = (): Promise => { return this.db(T.SUGGEST_CHANGE_SET).del(); }; @@ -247,8 +256,10 @@ export class SuggestChangeStore implements ISuggestChangeStore { return result.rows[0].present; }; - mapRows = (rows?: any[]): ISuggestChangeset[] => { - const suggestChangeSets = rows.reduce(suggestChangeRowReducer, {}); + mapRows = (rows?: ISuggestChangesetRow[]): ISuggestChangeset[] => { + const suggestChangeSets = rows.reduce< + Record + >(suggestChangeRowReducer, {}); return Object.values(suggestChangeSets); }; diff --git a/src/lib/types/model.ts b/src/lib/types/model.ts index 606685f51c..44de43849a 100644 --- a/src/lib/types/model.ts +++ b/src/lib/types/model.ts @@ -373,13 +373,17 @@ export interface ISuggestChangeset { environment: string; createdBy: Pick; createdAt: Date; + features: ISuggestChangeFeature[]; +} + +export interface ISuggestChangeFeature { + name: string; changes: ISuggestChange[]; } export interface ISuggestChange { id?: number; action: SuggestChangeAction; - feature: string; payload: any; createdBy?: Pick; createdAt?: Date; diff --git a/src/lib/types/stores/suggest-change-store.ts b/src/lib/types/stores/suggest-change-store.ts index 025bfa131c..f50deefa6b 100644 --- a/src/lib/types/stores/suggest-change-store.ts +++ b/src/lib/types/stores/suggest-change-store.ts @@ -17,12 +17,15 @@ export interface ISuggestChangeStore extends Store { addChangeToSet( change: PartialSome, + feature: string, changeSetID: number, userId: number, ): Promise; get(id: number): Promise; + deleteChange(changeId: number): Promise; + updateState( id: number, state: SuggestChangesetState, diff --git a/src/migrations/20221810114644-add-suggest-changes-table.js b/src/migrations/20221810114644-add-suggest-changes-table.js index 058e71e8f3..1b4450afbd 100644 --- a/src/migrations/20221810114644-add-suggest-changes-table.js +++ b/src/migrations/20221810114644-add-suggest-changes-table.js @@ -19,7 +19,8 @@ CREATE TABLE IF NOT EXISTS suggest_change ( payload jsonb not null default '[]'::jsonb, created_by integer not null references users (id) ON DELETE CASCADE, created_at timestamp default now(), - suggest_change_set_id integer NOT NULL REFERENCES suggest_change_set(id) ON DELETE CASCADE + suggest_change_set_id integer NOT NULL REFERENCES suggest_change_set(id) ON DELETE CASCADE, + UNIQUE (feature, action, suggest_change_set_id) ); `, callback, diff --git a/src/test/fixtures/fake-suggest-change-store.ts b/src/test/fixtures/fake-suggest-change-store.ts index 8a348dddbe..313ab7d9fe 100644 --- a/src/test/fixtures/fake-suggest-change-store.ts +++ b/src/test/fixtures/fake-suggest-change-store.ts @@ -23,15 +23,26 @@ export default class FakeSuggestChangeStore implements ISuggestChangeStore { return Promise.resolve(undefined); } + // eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars + async deleteChange(id: number): Promise { + return Promise.resolve(undefined); + } + addChangeToSet( change: PartialSome, + feature: string, changeSetID: number, userId: number, ): Promise { const changeSet = this.suggestChanges.find((s) => s.id === changeSetID); - changeSet.changes.push({ - createdBy: { id: userId, username: '', imageUrl: '' }, - ...change, + changeSet.features.push({ + name: feature, + changes: [ + { + createdBy: { id: userId, username: '', imageUrl: '' }, + ...change, + }, + ], }); return Promise.resolve(); }