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:
co-authored by
Oli Juhl
parent
b12408dbd8
commit
1659c9be5d
@@ -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";');
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user