feat(product,dashboard): Allow re-ordering images (#10187)

* migration

* fix snapshot

* primarykey

* init work on dnd

* progress

* dnd

* undo changes

* undo changes

* undo changes

* undo changes

* fix firefox issue

* lint

* lint

* lint

* add changeset

* undo changes to product module

* set activator node

* init work on service layer

* alternative

* switch to OneToMany

* add tests

* progress

* update migration

* update approach and remove all references to images in product.ts tests

* handle delete images on empty array

* fix config and order type

* update changeset

* rm flag

* export type and fix type in test

* fix type

---------

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Kasper Fabricius Kristensen
2024-11-25 09:03:10 +01:00
committed by GitHub
co-authored by Oli Juhl
parent b12408dbd8
commit 1659c9be5d
32 changed files with 1257 additions and 617 deletions
@@ -268,93 +268,6 @@
"checks": [],
"foreignKeys": {}
},
{
"columns": {
"id": {
"name": "id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"url": {
"name": "url",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"created_at": {
"name": "created_at",
"type": "timestamptz",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"updated_at": {
"name": "updated_at",
"type": "timestamptz",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"deleted_at": {
"name": "deleted_at",
"type": "timestamptz",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"length": 6,
"mappedType": "datetime"
}
},
"name": "image",
"schema": "public",
"indexes": [
{
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_image_deleted_at",
"primary": false,
"unique": false
},
{
"keyName": "image_pkey",
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
}
],
"checks": [],
"foreignKeys": {}
},
{
"columns": {
"id": {
@@ -1033,6 +946,126 @@
}
}
},
{
"columns": {
"id": {
"name": "id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"url": {
"name": "url",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"created_at": {
"name": "created_at",
"type": "timestamptz",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"updated_at": {
"name": "updated_at",
"type": "timestamptz",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"deleted_at": {
"name": "deleted_at",
"type": "timestamptz",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"length": 6,
"mappedType": "datetime"
},
"rank": {
"name": "rank",
"type": "integer",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"default": "0",
"mappedType": "integer"
},
"product_id": {
"name": "product_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
}
},
"name": "image",
"schema": "public",
"indexes": [
{
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_image_deleted_at",
"primary": false,
"unique": false
},
{
"keyName": "image_pkey",
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
}
],
"checks": [],
"foreignKeys": {
"image_product_id_foreign": {
"constraintName": "image_product_id_foreign",
"columnNames": [
"product_id"
],
"localTableName": "public.image",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product",
"deleteRule": "cascade",
"updateRule": "cascade"
}
}
},
{
"columns": {
"product_id": {
@@ -1098,71 +1131,6 @@
}
}
},
{
"columns": {
"product_id": {
"name": "product_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"image_id": {
"name": "image_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
}
},
"name": "product_images",
"schema": "public",
"indexes": [
{
"keyName": "product_images_pkey",
"columnNames": [
"product_id",
"image_id"
],
"composite": true,
"primary": true,
"unique": true
}
],
"checks": [],
"foreignKeys": {
"product_images_product_id_foreign": {
"constraintName": "product_images_product_id_foreign",
"columnNames": [
"product_id"
],
"localTableName": "public.product_images",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product",
"deleteRule": "cascade",
"updateRule": "cascade"
},
"product_images_image_id_foreign": {
"constraintName": "product_images_image_id_foreign",
"columnNames": [
"image_id"
],
"localTableName": "public.product_images",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.image",
"deleteRule": "cascade",
"updateRule": "cascade"
}
}
},
{
"columns": {
"product_id": {
@@ -0,0 +1,45 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20241122120331 extends Migration {
async up(): Promise<void> {
this.addSql('alter table if exists "image" add column if not exists "rank" integer not null default 0, add column if not exists "product_id" text not null;');
// Migrate existing relationships
this.addSql(`
update "image" i
set product_id = pi.product_id,
rank = (
select count(*)
from product_images pi2
where pi2.product_id = pi.product_id
and pi2.image_id <= pi.image_id
) - 1
from "product_images" pi
where pi.image_id = i.id;
`);
this.addSql('alter table if exists "image" add constraint "image_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;');
this.addSql('drop table if exists "product_images" cascade;');
}
async down(): Promise<void> {
this.addSql('create table if not exists "product_images" ("product_id" text not null, "image_id" text not null, constraint "product_images_pkey" primary key ("product_id", "image_id"));');
// Migrate relationships back to join table
this.addSql(`
insert into "product_images" (product_id, image_id)
select product_id, id
from "image"
where product_id is not null;
`);
this.addSql('alter table if exists "product_images" add constraint "product_images_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_images" add constraint "product_images_image_id_foreign" foreign key ("image_id") references "image" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "image" drop constraint if exists "image_product_id_foreign";');
this.addSql('alter table if exists "image" drop column if exists "rank";');
this.addSql('alter table if exists "image" drop column if exists "product_id";');
}
}