Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Relations: Bugs in deleting many-to-many item #1662

Open
nickgieschen opened this issue Apr 22, 2024 · 8 comments
Open

[Bug]: Relations: Bugs in deleting many-to-many item #1662

nickgieschen opened this issue Apr 22, 2024 · 8 comments
Labels
bug Something isn't working

Comments

@nickgieschen
Copy link

nickgieschen commented Apr 22, 2024

Contact Details

nickgieschen3636 in the discord channel

What happened?

I am trying to remove one item from a many-to-many relation. However, when I delete just one item, it deletes all related entites. Also, the delete error message has weird wording.

Step 1: Delete one item

2024-04-22_10-22-16

Step 2: Confirm (with buggy message)

2024-04-22_10-22-52

Step 3: ALL items are deleted

2024-04-22_10-23-08

Bug prevalence

Always

AdminJS dependencies version

"@adminjs/design-system": "^4.1.1",
"@adminjs/fastify": "^4.1.2",
"@adminjs/relations": "^1.1.2",
"@adminjs/sql": "^2.2.1",

"adminjs": "^7.7.2",

What browsers do you see the problem on?

Chrome

Relevant log output

n/a

Relevant code that's giving you issues

n/a
@nickgieschen nickgieschen added the bug Something isn't working label Apr 22, 2024
@dziraf
Copy link
Contributor

dziraf commented Apr 22, 2024

Have you done any modifications to Keyword resource delete action? Can you share your configuration of relations feature and what's sent in the Network tab in the browser?

The modal should display two buttons unless configured differently:

  • Remove relation
  • Delete record

Remove relation removes the relation from the junction table while Delete record first removes the relation, then deletes the target record. I've looked at the source code and I don't see why it'd delete all records 🤔

@nickgieschen
Copy link
Author

nickgieschen commented Apr 22, 2024

Here you go. Haven't touched any delete actions.

{
    resource: db.table("tracks"),
    features: [
      owningRelationSettingsFeature({
        componentLoader,
        licenseKey: process.env.ADMINJS_REFERENCE_LICENSE!,
        relations: {
          genres: {
            type: RelationType.ManyToMany,
            junction: {
              joinKey: "track_id",
              inverseJoinKey: "genre_id",
              throughResourceId: "track_genres",
            },
            target: {
              resourceId: "genres",
            },
          },
          instruments: {
            type: RelationType.ManyToMany,
            junction: {
              joinKey: "track_id",
              inverseJoinKey: "mood_id",
              throughResourceId: "track_moods",
            },
            target: {
              resourceId: "moods",
            },
          },
          keywords: {
            type: RelationType.ManyToMany,
            junction: {
              joinKey: "track_id",
              inverseJoinKey: "keyword_id",
              throughResourceId: "track_keywords",
            },
            target: {
              resourceId: "keywords",
            },
            deleteOptions: {
                enableDeleteRelation: false,
                enableDeleteRelatedRecord: true
            }
          },
          moods: {
            type: RelationType.ManyToMany,
            junction: {
              joinKey: "track_id",
              inverseJoinKey: "mood_id",
              throughResourceId: "track_moods",
            },
            target: {
              resourceId: "moods",
            },
          },
        },
      }),
    ],
    options: {
      navigation: navigation,
      listProperties: ["id", "title"],
      actions: {
        bulkDelete: {
          isVisible: false,
        },
        show: {
          after: [sqlDurationToString],
        },
        edit: {
          before: [stringToSqlDuration],
          after: [sqlDurationToString],
        },
      },
      properties: {
        main_track_id: {
          type: "reference",
          components: {
            edit: components.ParentTrackEditComponent,
          },
        },
        track_relations: {
            type: "string",
            components: {
                show: components.TrackRelationsComponent,
            },
            position: Number.MAX_SAFE_INTEGER,
        },
      },
    },
  };

Uploading 0.0.0.0.har.gz…

@dziraf
Copy link
Contributor

dziraf commented Apr 22, 2024

I tried to reproduce it using the example from the documentation and @adminjs/sql but it looks to be working fine for me.

Screen.Recording.2024-04-22.at.22.37.38.mov

Could you share what's sent in the request in the browser's Network tab when you click the delete button?

@nickgieschen
Copy link
Author

nickgieschen commented Apr 23, 2024

A couple things:

  1. As of @adminjs/[email protected] the Remove relation button doesn't exist. I confirmed this in the source of both 1.1.1 and 1.1.2.

  2. In @adminjs/[email protected] when I click Remove relation all of the related entities are still deleted, instead of just the one I want deleted. Here's the network log:

{
  "log": {
    "version": "1.2",
    "creator": {
      "name": "WebInspector",
      "version": "537.36"
    },
    "pages": [
      {
        "startedDateTime": "2024-04-23T00:52:29.215Z",
        "id": "page_2",
        "title": "http://0.0.0.0:3000/admin/resources/tracks/records/0001e7f5-f30c-4c94-95c6-bd886db6d639/show?tab=instruments",
        "pageTimings": {
          "onContentLoad": 642.9910000006203,
          "onLoad": 891.6900000185706
        }
      }
    ],
    "entries": [
      {
        "_initiator": {
          "type": "script",
          "stack": {
            "callFrames": [
              {
                "functionName": "dispatchXhrRequest",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 6075,
                "columnNumber": 14
              },
              {
                "functionName": "xhr",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 5877,
                "columnNumber": 11
              },
              {
                "functionName": "dispatchRequest",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 6175,
                "columnNumber": 11
              },
              {
                "functionName": "request",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 6527,
                "columnNumber": 34
              },
              {
                "functionName": "wrap",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 3695,
                "columnNumber": 16
              },
              {
                "functionName": "recordAction",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 7067,
                "columnNumber": 41
              },
              {
                "functionName": "s",
                "scriptId": "244",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/components.bundle.js",
                "lineNumber": 10109,
                "columnNumber": 30
              },
              {
                "functionName": "onClick",
                "scriptId": "244",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/components.bundle.js",
                "lineNumber": 10139,
                "columnNumber": 26
              },
              {
                "functionName": "callCallback",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 24252,
                "columnNumber": 14
              },
              {
                "functionName": "invokeGuardedCallbackDev",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 24301,
                "columnNumber": 16
              },
              {
                "functionName": "invokeGuardedCallback",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 24365,
                "columnNumber": 31
              },
              {
                "functionName": "invokeGuardedCallbackAndCatchFirstError",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 24379,
                "columnNumber": 25
              },
              {
                "functionName": "executeDispatch",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 29127,
                "columnNumber": 3
              },
              {
                "functionName": "processDispatchQueueItemsInOrder",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 29159,
                "columnNumber": 7
              },
              {
                "functionName": "processDispatchQueue",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 29172,
                "columnNumber": 5
              },
              {
                "functionName": "dispatchEventsForPlugins",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 29183,
                "columnNumber": 3
              },
              {
                "functionName": "",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 29373,
                "columnNumber": 12
              },
              {
                "functionName": "batchedUpdates$1",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 46206,
                "columnNumber": 12
              },
              {
                "functionName": "batchedUpdates",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 24079,
                "columnNumber": 12
              },
              {
                "functionName": "dispatchEventForPluginEventSystem",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 29372,
                "columnNumber": 3
              },
              {
                "functionName": "dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 26551,
                "columnNumber": 5
              },
              {
                "functionName": "dispatchEvent",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 26543,
                "columnNumber": 5
              },
              {
                "functionName": "dispatchDiscreteEvent",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 26516,
                "columnNumber": 5
              }
            ]
          }
        },
        "_priority": "High",
        "_resourceType": "xhr",
        "cache": {},
        "connection": "113539",
        "pageref": "page_2",
        "request": {
          "method": "GET",
          "url": "http://0.0.0.0:3000/admin/api/resources/tracks/records/0001e7f5-f30c-4c94-95c6-bd886db6d639/deleteRelation?targetRecordId=fc409d53-76ce-4841-b53b-c0fc2adaa13b&relation=genres",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Accept",
              "value": "application/json, text/plain, */*"
            },
            {
              "name": "Accept-Encoding",
              "value": "gzip, deflate"
            },
            {
              "name": "Accept-Language",
              "value": "en-US,en"
            },
            {
              "name": "Connection",
              "value": "keep-alive"
            },
            {
              "name": "Host",
              "value": "0.0.0.0:3000"
            },
            {
              "name": "Referer",
              "value": "http://0.0.0.0:3000/admin/resources/tracks/records/0001e7f5-f30c-4c94-95c6-bd886db6d639/show?tab=genres"
            },
            {
              "name": "Sec-GPC",
              "value": "1"
            },
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
            }
          ],
          "queryString": [
            {
              "name": "targetRecordId",
              "value": "fc409d53-76ce-4841-b53b-c0fc2adaa13b"
            },
            {
              "name": "relation",
              "value": "genres"
            }
          ],
          "cookies": [],
          "headersSize": 573,
          "bodySize": 0
        },
        "response": {
          "status": 200,
          "statusText": "OK",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Connection",
              "value": "keep-alive"
            },
            {
              "name": "Date",
              "value": "Tue, 23 Apr 2024 00:52:50 GMT"
            },
            {
              "name": "Keep-Alive",
              "value": "timeout=72"
            },
            {
              "name": "access-control-allow-credentials",
              "value": "true"
            },
            {
              "name": "access-control-allow-origin",
              "value": "http://localhost:8080"
            },
            {
              "name": "content-length",
              "value": "11680"
            },
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            }
          ],
          "cookies": [],
          "content": {
            "size": 11680,
            "mimeType": "application/json",
            "compression": 0,
            "text": "{\"record\":{\"params\":{\"id\":\"0001e7f5-f30c-4c94-95c6-bd886db6d639\",\"album_id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"title\":\"Lights in the dark\",\"display_title\":\"Lights in the dark\",\"alternate_title\":\"Lights in the dark_Alt Mix No Piano\",\"description\":\"Beneath The Surface is a collection of tracks that combines mysterious synths and ominous sound design. Great for Documentary, Sci-Fi, Drama, Key a min\",\"track_number\":39,\"is_main\":false,\"main_track_number\":38,\"version\":\"Alt Mix No Piano\",\"duration.minutes\":2,\"bpm\":100,\"tempo\":\"Med Slow\",\"genre\":\"TENSION, Hybrid, Suspense, Sci-Fi, Drama, Score\",\"instrumentation\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"keywords\":\"Dystopia, Cyborg, Drama, Apocalypse, Intense, Pulsing, Imminent Danger, Mysterious, Looming, Ominous, Dark, Terrifying, Deranged, Industrial, Eerie, Frightening, Mystery, Action, Investigation, Anxiety, Space ship, Mars, Planets, Outer Space, Texture, ET, Distant, Anxious, Danger, Crime, City, Cyber, Ambient, Atmospheric, Synths, Film/TV, Run, Escape, Detective, Soothing, Soft\",\"code\":\"SSM0148_39\",\"composers\":\"Emilio Merone (PRS) 50% [184755142], Mauro Colavecchi (PRS) 50% [742926721]\",\"publishers\":\"SPACE AND SOUND MUSIC (SOCAN) 100%\",\"artists\":\"Emilio Merone, Mauro Colavecchi\",\"filename\":\"SSM0148_39_Lights in the dark_Alt Mix No Piano.wav\",\"mood\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"artist1_first_name\":null,\"artist1_middle_name\":null,\"artist1_last_name\":null,\"artist1_society\":null,\"artist1_ipi\":null,\"writer1_first_name\":\"Emilio\",\"writer1_middle_name\":null,\"writer1_last_name\":\"Merone\",\"writer1_capacity\":\"Composer\",\"writer1_society\":\"PRS\",\"writer1_ipi\":\"184755142\",\"writer1_territory\":\"WORLD\",\"writer1_owner_performance_share\":\"25.0000\",\"writer1_owner_mechanical_share\":\"0.0000\",\"writer1_collection_performance_share\":\"25.0000\",\"writer1_collection_mechanical_share\":\"0.0000\",\"writer1_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer2_first_name\":\"Mauro\",\"writer2_middle_name\":null,\"writer2_last_name\":\"Colavecchi\",\"writer2_capacity\":\"Composer\",\"writer2_society\":\"PRS\",\"writer2_ipi\":\"742926721\",\"writer2_territory\":\"WORLD\",\"writer2_owner_performance_share\":\"25.0000\",\"writer2_owner_mechanical_share\":\"0.0000\",\"writer2_collection_performance_share\":\"25.0000\",\"writer2_collection_mechanical_share\":\"0.0000\",\"writer2_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer3_first_name\":null,\"writer3_middle_name\":null,\"writer3_last_name\":null,\"writer3_capacity\":null,\"writer3_society\":null,\"writer3_ipi\":null,\"writer3_territory\":null,\"writer3_owner_performance_share\":null,\"writer3_owner_mechanical_share\":null,\"writer3_collection_performance_share\":null,\"writer3_collection_mechanical_share\":null,\"writer3_original_publisher\":null,\"writer4_first_name\":null,\"writer4_middle_name\":null,\"writer4_last_name\":null,\"writer4_capacity\":null,\"writer4_society\":null,\"writer4_ipi\":null,\"writer4_territory\":null,\"writer4_owner_performance_share\":null,\"writer4_owner_mechanical_share\":null,\"writer4_collection_performance_share\":null,\"writer4_collection_mechanical_share\":null,\"writer4_original_publisher\":null,\"publisher1_name\":\"SPACE AND SOUND MUSIC B\",\"publisher1_capacity\":\"Original Publisher\",\"publisher1_society\":\"SOCAN\",\"publisher1_ipi\":\"809010864\",\"publisher1_territory\":\"WORLD\",\"publisher1_owner_performance_share\":\"50.0000\",\"publisher1_owner_mechanical_share\":\"100.0000\",\"publisher1_collection_performance_share\":\"100.0000\",\"publisher1_collection_mechanical_share\":\"100.0000\",\"publisher1_original_publisher\":\"SPACE AND SOUND MUSIC B\",\"publisher2_name\":null,\"publisher2_capacity\":null,\"publisher2_society\":null,\"publisher2_ipi\":null,\"publisher2_territory\":null,\"publisher2_owner_performance_share\":null,\"publisher2_owner_mechanical_share\":null,\"publisher2_collection_performance_share\":null,\"publisher2_collection_mechanical_share\":null,\"publisher2_original_publisher\":null,\"isrc\":\"CBAWZ2107503\",\"iswc\":null,\"sgae_work_number\":null,\"gema_work_number\":null,\"main_track_id\":\"063880c5-0ab0-4c10-9915-f7deda5623ff\"},\"populated\":{\"album_id\":{\"params\":{\"id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"code\":\"SSM0148\",\"title\":\"Beneath The Surface\",\"display_title\":\"Beneath The Surface\",\"description\":\"Beneath The Surface is a collection of tracks that combines mysterious synths and ominous sound design. Great for Documentary, Sci-Fi, Drama \",\"styles\":\"TENSION, Hybrid, Suspense, Action, Drama, Score\",\"release_date\":\"2022-04-11T07:00:00.000Z\"},\"populated\":{},\"baseError\":null,\"errors\":{},\"id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"title\":\"Beneath The Surface\",\"recordActions\":[{\"name\":\"show\",\"actionType\":\"record\",\"icon\":\"Monitor\",\"label\":\"show\",\"resourceId\":\"albums\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"edit\",\"actionType\":\"record\",\"icon\":\"Edit\",\"label\":\"edit\",\"resourceId\":\"albums\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"delete\",\"actionType\":\"record\",\"icon\":\"Trash2\",\"label\":\"delete\",\"resourceId\":\"albums\",\"guard\":\"confirmDelete\",\"showFilter\":false,\"showResourceActions\":true,\"component\":false,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"danger\",\"parent\":null,\"hasHandler\":true,\"custom\":{}}],\"bulkActions\":[]},\"main_track_id\":{\"params\":{\"id\":\"063880c5-0ab0-4c10-9915-f7deda5623ff\",\"album_id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"title\":\"Lights in the dark\",\"display_title\":\"Lights in the dark\",\"alternate_title\":\"Lights in the dark_Full Mix\",\"description\":\"Beneath The Surface is a collection of tracks that combines mysterious synths and ominous sound design. Great for Documentary, Sci-Fi, Drama, Key a min\",\"track_number\":38,\"is_main\":true,\"main_track_number\":null,\"version\":\"Full Mix\",\"duration.minutes\":2,\"bpm\":100,\"tempo\":\"Med Slow\",\"genre\":\"TENSION, Hybrid, Suspense, Sci-Fi, Drama, Score\",\"instrumentation\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"keywords\":\"Dystopia, Cyborg, Drama, Apocalypse, Intense, Pulsing, Imminent Danger, Mysterious, Looming, Ominous, Dark, Terrifying, Deranged, Industrial, Eerie, Frightening, Mystery, Action, Investigation, Anxiety, Space ship, Mars, Planets, Outer Space, Texture, ET, Distant, Anxious, Danger, Crime, City, Cyber, Ambient, Atmospheric, Synths, Film/TV, Run, Escape, Detective, Soothing, Soft\",\"code\":\"SSM0148_38\",\"composers\":\"Emilio Merone (PRS) 50% [184755142], Mauro Colavecchi (PRS) 50% [742926721]\",\"publishers\":\"SPACE AND SOUND MUSIC (SOCAN) 100%\",\"artists\":\"Emilio Merone, Mauro Colavecchi\",\"filename\":\"SSM0148_38_Lights in the dark_Full Mix.wav\",\"mood\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"artist1_first_name\":null,\"artist1_middle_name\":null,\"artist1_last_name\":null,\"artist1_society\":null,\"artist1_ipi\":null,\"writer1_first_name\":\"Emilio\",\"writer1_middle_name\":null,\"writer1_last_name\":\"Merone\",\"writer1_capacity\":\"Composer\",\"writer1_society\":\"PRS\",\"writer1_ipi\":\"184755142\",\"writer1_territory\":\"WORLD\",\"writer1_owner_performance_share\":\"25.0000\",\"writer1_owner_mechanical_share\":\"0.0000\",\"writer1_collection_performance_share\":\"25.0000\",\"writer1_collection_mechanical_share\":\"0.0000\",\"writer1_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer2_first_name\":\"Mauro\",\"writer2_middle_name\":null,\"writer2_last_name\":\"Colavecchi\",\"writer2_capacity\":\"Composer\",\"writer2_society\":\"PRS\",\"writer2_ipi\":\"742926721\",\"writer2_territory\":\"WORLD\",\"writer2_owner_performance_share\":\"25.0000\",\"writer2_owner_mechanical_share\":\"0.0000\",\"writer2_collection_performance_share\":\"25.0000\",\"writer2_collection_mechanical_share\":\"0.0000\",\"writer2_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer3_first_name\":null,\"writer3_middle_name\":null,\"writer3_last_name\":null,\"writer3_capacity\":null,\"writer3_society\":null,\"writer3_ipi\":null,\"writer3_territory\":null,\"writer3_owner_performance_share\":null,\"writer3_owner_mechanical_share\":null,\"writer3_collection_performance_share\":null,\"writer3_collection_mechanical_share\":null,\"writer3_original_publisher\":null,\"writer4_first_name\":null,\"writer4_middle_name\":null,\"writer4_last_name\":null,\"writer4_capacity\":null,\"writer4_society\":null,\"writer4_ipi\":null,\"writer4_territory\":null,\"writer4_owner_performance_share\":null,\"writer4_owner_mechanical_share\":null,\"writer4_collection_performance_share\":null,\"writer4_collection_mechanical_share\":null,\"writer4_original_publisher\":null,\"publisher1_name\":\"SPACE AND SOUND MUSIC B\",\"publisher1_capacity\":\"Original Publisher\",\"publisher1_society\":\"SOCAN\",\"publisher1_ipi\":\"809010864\",\"publisher1_territory\":\"WORLD\",\"publisher1_owner_performance_share\":\"50.0000\",\"publisher1_owner_mechanical_share\":\"100.0000\",\"publisher1_collection_performance_share\":\"100.0000\",\"publisher1_collection_mechanical_share\":\"100.0000\",\"publisher1_original_publisher\":\"SPACE AND SOUND MUSIC B\",\"publisher2_name\":null,\"publisher2_capacity\":null,\"publisher2_society\":null,\"publisher2_ipi\":null,\"publisher2_territory\":null,\"publisher2_owner_performance_share\":null,\"publisher2_owner_mechanical_share\":null,\"publisher2_collection_performance_share\":null,\"publisher2_collection_mechanical_share\":null,\"publisher2_original_publisher\":null,\"isrc\":\"CBAWZ2107502\",\"iswc\":null,\"sgae_work_number\":null,\"gema_work_number\":null,\"main_track_id\":null},\"populated\":{},\"baseError\":null,\"errors\":{},\"id\":\"063880c5-0ab0-4c10-9915-f7deda5623ff\",\"title\":\"Lights in the dark\",\"recordActions\":[{\"name\":\"show\",\"actionType\":\"record\",\"icon\":\"Monitor\",\"label\":\"show\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"edit\",\"actionType\":\"record\",\"icon\":\"Edit\",\"label\":\"edit\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"delete\",\"actionType\":\"record\",\"icon\":\"Trash2\",\"label\":\"delete\",\"resourceId\":\"tracks\",\"guard\":\"confirmDelete\",\"showFilter\":false,\"showResourceActions\":true,\"component\":false,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"danger\",\"parent\":null,\"hasHandler\":true,\"custom\":{}}],\"bulkActions\":[]}},\"baseError\":null,\"errors\":{},\"id\":\"0001e7f5-f30c-4c94-95c6-bd886db6d639\",\"title\":\"Lights in the dark\",\"recordActions\":[{\"name\":\"show\",\"actionType\":\"record\",\"icon\":\"Monitor\",\"label\":\"show\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"edit\",\"actionType\":\"record\",\"icon\":\"Edit\",\"label\":\"edit\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"delete\",\"actionType\":\"record\",\"icon\":\"Trash2\",\"label\":\"delete\",\"resourceId\":\"tracks\",\"guard\":\"confirmDelete\",\"showFilter\":false,\"showResourceActions\":true,\"component\":false,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"danger\",\"parent\":null,\"hasHandler\":true,\"custom\":{}}],\"bulkActions\":[]},\"notice\":{\"type\":\"success\",\"message\":\"[@adminjs/relations]_relationSuccessfullyDeleted\",\"resourceId\":\"tracks\"}}"
          },
          "redirectURL": "",
          "headersSize": 266,
          "bodySize": 11680,
          "_transferSize": 11946,
          "_error": null
        },
        "serverIPAddress": "0.0.0.0",
        "startedDateTime": "2024-04-23T00:52:50.441Z",
        "time": 31.350000004749745,
        "timings": {
          "blocked": 0.9990000002589077,
          "dns": -1,
          "ssl": -1,
          "connect": -1,
          "send": 0.05099999999999999,
          "wait": 29.604000001700594,
          "receive": 0.6960000027902424,
          "_blocked_queueing": 0.7530000002589077
        }
      },
      {
        "_initiator": {
          "type": "script",
          "stack": {
            "callFrames": [
              {
                "functionName": "dispatchXhrRequest",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 6075,
                "columnNumber": 14
              },
              {
                "functionName": "xhr",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 5877,
                "columnNumber": 11
              },
              {
                "functionName": "dispatchRequest",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 6175,
                "columnNumber": 11
              },
              {
                "functionName": "request",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 6527,
                "columnNumber": 34
              },
              {
                "functionName": "wrap",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 3695,
                "columnNumber": 16
              },
              {
                "functionName": "recordAction",
                "scriptId": "245",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/app.bundle.js",
                "lineNumber": 7067,
                "columnNumber": 41
              },
              {
                "functionName": "",
                "scriptId": "244",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/components.bundle.js",
                "lineNumber": 9974,
                "columnNumber": 36
              },
              {
                "functionName": "commitHookEffectListMount",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 43227,
                "columnNumber": 26
              },
              {
                "functionName": "commitPassiveMountOnFiber",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 45003,
                "columnNumber": 13
              },
              {
                "functionName": "commitPassiveMountEffects_complete",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 44968,
                "columnNumber": 9
              },
              {
                "functionName": "commitPassiveMountEffects_begin",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 44955,
                "columnNumber": 7
              },
              {
                "functionName": "commitPassiveMountEffects",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 44943,
                "columnNumber": 3
              },
              {
                "functionName": "flushPassiveEffectsImpl",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 47104,
                "columnNumber": 3
              },
              {
                "functionName": "flushPassiveEffects",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 47049,
                "columnNumber": 14
              },
              {
                "functionName": "",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 46834,
                "columnNumber": 9
              },
              {
                "functionName": "workLoop",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 19716,
                "columnNumber": 35
              },
              {
                "functionName": "flushWork",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 19689,
                "columnNumber": 15
              },
              {
                "functionName": "performWorkUntilDeadline",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 19983,
                "columnNumber": 22
              },
              {
                "functionName": "queue$2.<computed>",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 7630,
                "columnNumber": 7
              },
              {
                "functionName": "run",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 7604,
                "columnNumber": 5
              },
              {
                "functionName": "eventListener",
                "scriptId": "246",
                "url": "http://0.0.0.0:3000/admin/frontend/assets/global.bundle.js",
                "lineNumber": 7615,
                "columnNumber": 3
              }
            ],
            "parentId": {
              "id": "86",
              "debuggerId": "2397735161316708382.3804226132821107084"
            }
          }
        },
        "_priority": "High",
        "_resourceType": "xhr",
        "cache": {},
        "connection": "113539",
        "pageref": "page_2",
        "request": {
          "method": "GET",
          "url": "http://0.0.0.0:3000/admin/api/resources/tracks/records/0001e7f5-f30c-4c94-95c6-bd886db6d639/findRelation?relation=genres",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Accept",
              "value": "application/json, text/plain, */*"
            },
            {
              "name": "Accept-Encoding",
              "value": "gzip, deflate"
            },
            {
              "name": "Accept-Language",
              "value": "en-US,en"
            },
            {
              "name": "Connection",
              "value": "keep-alive"
            },
            {
              "name": "Host",
              "value": "0.0.0.0:3000"
            },
            {
              "name": "Referer",
              "value": "http://0.0.0.0:3000/admin/resources/tracks/records/0001e7f5-f30c-4c94-95c6-bd886db6d639/show?tab=genres"
            },
            {
              "name": "Sec-GPC",
              "value": "1"
            },
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
            }
          ],
          "queryString": [
            {
              "name": "relation",
              "value": "genres"
            }
          ],
          "cookies": [],
          "headersSize": 519,
          "bodySize": 0
        },
        "response": {
          "status": 200,
          "statusText": "OK",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Connection",
              "value": "keep-alive"
            },
            {
              "name": "Date",
              "value": "Tue, 23 Apr 2024 00:52:50 GMT"
            },
            {
              "name": "Keep-Alive",
              "value": "timeout=72"
            },
            {
              "name": "access-control-allow-credentials",
              "value": "true"
            },
            {
              "name": "access-control-allow-origin",
              "value": "http://localhost:8080"
            },
            {
              "name": "content-length",
              "value": "11664"
            },
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            }
          ],
          "cookies": [],
          "content": {
            "size": 11664,
            "mimeType": "application/json",
            "compression": 0,
            "text": "{\"meta\":{\"total\":\"0\",\"perPage\":10,\"page\":1,\"sortBy\":\"genre_id\",\"direction\":\"desc\"},\"records\":[],\"record\":{\"params\":{\"id\":\"0001e7f5-f30c-4c94-95c6-bd886db6d639\",\"album_id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"title\":\"Lights in the dark\",\"display_title\":\"Lights in the dark\",\"alternate_title\":\"Lights in the dark_Alt Mix No Piano\",\"description\":\"Beneath The Surface is a collection of tracks that combines mysterious synths and ominous sound design. Great for Documentary, Sci-Fi, Drama, Key a min\",\"track_number\":39,\"is_main\":false,\"main_track_number\":38,\"version\":\"Alt Mix No Piano\",\"duration.minutes\":2,\"bpm\":100,\"tempo\":\"Med Slow\",\"genre\":\"TENSION, Hybrid, Suspense, Sci-Fi, Drama, Score\",\"instrumentation\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"keywords\":\"Dystopia, Cyborg, Drama, Apocalypse, Intense, Pulsing, Imminent Danger, Mysterious, Looming, Ominous, Dark, Terrifying, Deranged, Industrial, Eerie, Frightening, Mystery, Action, Investigation, Anxiety, Space ship, Mars, Planets, Outer Space, Texture, ET, Distant, Anxious, Danger, Crime, City, Cyber, Ambient, Atmospheric, Synths, Film/TV, Run, Escape, Detective, Soothing, Soft\",\"code\":\"SSM0148_39\",\"composers\":\"Emilio Merone (PRS) 50% [184755142], Mauro Colavecchi (PRS) 50% [742926721]\",\"publishers\":\"SPACE AND SOUND MUSIC (SOCAN) 100%\",\"artists\":\"Emilio Merone, Mauro Colavecchi\",\"filename\":\"SSM0148_39_Lights in the dark_Alt Mix No Piano.wav\",\"mood\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"artist1_first_name\":null,\"artist1_middle_name\":null,\"artist1_last_name\":null,\"artist1_society\":null,\"artist1_ipi\":null,\"writer1_first_name\":\"Emilio\",\"writer1_middle_name\":null,\"writer1_last_name\":\"Merone\",\"writer1_capacity\":\"Composer\",\"writer1_society\":\"PRS\",\"writer1_ipi\":\"184755142\",\"writer1_territory\":\"WORLD\",\"writer1_owner_performance_share\":\"25.0000\",\"writer1_owner_mechanical_share\":\"0.0000\",\"writer1_collection_performance_share\":\"25.0000\",\"writer1_collection_mechanical_share\":\"0.0000\",\"writer1_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer2_first_name\":\"Mauro\",\"writer2_middle_name\":null,\"writer2_last_name\":\"Colavecchi\",\"writer2_capacity\":\"Composer\",\"writer2_society\":\"PRS\",\"writer2_ipi\":\"742926721\",\"writer2_territory\":\"WORLD\",\"writer2_owner_performance_share\":\"25.0000\",\"writer2_owner_mechanical_share\":\"0.0000\",\"writer2_collection_performance_share\":\"25.0000\",\"writer2_collection_mechanical_share\":\"0.0000\",\"writer2_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer3_first_name\":null,\"writer3_middle_name\":null,\"writer3_last_name\":null,\"writer3_capacity\":null,\"writer3_society\":null,\"writer3_ipi\":null,\"writer3_territory\":null,\"writer3_owner_performance_share\":null,\"writer3_owner_mechanical_share\":null,\"writer3_collection_performance_share\":null,\"writer3_collection_mechanical_share\":null,\"writer3_original_publisher\":null,\"writer4_first_name\":null,\"writer4_middle_name\":null,\"writer4_last_name\":null,\"writer4_capacity\":null,\"writer4_society\":null,\"writer4_ipi\":null,\"writer4_territory\":null,\"writer4_owner_performance_share\":null,\"writer4_owner_mechanical_share\":null,\"writer4_collection_performance_share\":null,\"writer4_collection_mechanical_share\":null,\"writer4_original_publisher\":null,\"publisher1_name\":\"SPACE AND SOUND MUSIC B\",\"publisher1_capacity\":\"Original Publisher\",\"publisher1_society\":\"SOCAN\",\"publisher1_ipi\":\"809010864\",\"publisher1_territory\":\"WORLD\",\"publisher1_owner_performance_share\":\"50.0000\",\"publisher1_owner_mechanical_share\":\"100.0000\",\"publisher1_collection_performance_share\":\"100.0000\",\"publisher1_collection_mechanical_share\":\"100.0000\",\"publisher1_original_publisher\":\"SPACE AND SOUND MUSIC B\",\"publisher2_name\":null,\"publisher2_capacity\":null,\"publisher2_society\":null,\"publisher2_ipi\":null,\"publisher2_territory\":null,\"publisher2_owner_performance_share\":null,\"publisher2_owner_mechanical_share\":null,\"publisher2_collection_performance_share\":null,\"publisher2_collection_mechanical_share\":null,\"publisher2_original_publisher\":null,\"isrc\":\"CBAWZ2107503\",\"iswc\":null,\"sgae_work_number\":null,\"gema_work_number\":null,\"main_track_id\":\"063880c5-0ab0-4c10-9915-f7deda5623ff\"},\"populated\":{\"album_id\":{\"params\":{\"id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"code\":\"SSM0148\",\"title\":\"Beneath The Surface\",\"display_title\":\"Beneath The Surface\",\"description\":\"Beneath The Surface is a collection of tracks that combines mysterious synths and ominous sound design. Great for Documentary, Sci-Fi, Drama \",\"styles\":\"TENSION, Hybrid, Suspense, Action, Drama, Score\",\"release_date\":\"2022-04-11T07:00:00.000Z\"},\"populated\":{},\"baseError\":null,\"errors\":{},\"id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"title\":\"Beneath The Surface\",\"recordActions\":[{\"name\":\"show\",\"actionType\":\"record\",\"icon\":\"Monitor\",\"label\":\"show\",\"resourceId\":\"albums\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"edit\",\"actionType\":\"record\",\"icon\":\"Edit\",\"label\":\"edit\",\"resourceId\":\"albums\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"delete\",\"actionType\":\"record\",\"icon\":\"Trash2\",\"label\":\"delete\",\"resourceId\":\"albums\",\"guard\":\"confirmDelete\",\"showFilter\":false,\"showResourceActions\":true,\"component\":false,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"danger\",\"parent\":null,\"hasHandler\":true,\"custom\":{}}],\"bulkActions\":[]},\"main_track_id\":{\"params\":{\"id\":\"063880c5-0ab0-4c10-9915-f7deda5623ff\",\"album_id\":\"d8311ee4-c04d-4d21-a8b6-5e158f219c05\",\"title\":\"Lights in the dark\",\"display_title\":\"Lights in the dark\",\"alternate_title\":\"Lights in the dark_Full Mix\",\"description\":\"Beneath The Surface is a collection of tracks that combines mysterious synths and ominous sound design. Great for Documentary, Sci-Fi, Drama, Key a min\",\"track_number\":38,\"is_main\":true,\"main_track_number\":null,\"version\":\"Full Mix\",\"duration.minutes\":2,\"bpm\":100,\"tempo\":\"Med Slow\",\"genre\":\"TENSION, Hybrid, Suspense, Sci-Fi, Drama, Score\",\"instrumentation\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"keywords\":\"Dystopia, Cyborg, Drama, Apocalypse, Intense, Pulsing, Imminent Danger, Mysterious, Looming, Ominous, Dark, Terrifying, Deranged, Industrial, Eerie, Frightening, Mystery, Action, Investigation, Anxiety, Space ship, Mars, Planets, Outer Space, Texture, ET, Distant, Anxious, Danger, Crime, City, Cyber, Ambient, Atmospheric, Synths, Film/TV, Run, Escape, Detective, Soothing, Soft\",\"code\":\"SSM0148_38\",\"composers\":\"Emilio Merone (PRS) 50% [184755142], Mauro Colavecchi (PRS) 50% [742926721]\",\"publishers\":\"SPACE AND SOUND MUSIC (SOCAN) 100%\",\"artists\":\"Emilio Merone, Mauro Colavecchi\",\"filename\":\"SSM0148_38_Lights in the dark_Full Mix.wav\",\"mood\":\"Dark, Agressive, Moody, Pulsing, Menecing, Anxious\",\"artist1_first_name\":null,\"artist1_middle_name\":null,\"artist1_last_name\":null,\"artist1_society\":null,\"artist1_ipi\":null,\"writer1_first_name\":\"Emilio\",\"writer1_middle_name\":null,\"writer1_last_name\":\"Merone\",\"writer1_capacity\":\"Composer\",\"writer1_society\":\"PRS\",\"writer1_ipi\":\"184755142\",\"writer1_territory\":\"WORLD\",\"writer1_owner_performance_share\":\"25.0000\",\"writer1_owner_mechanical_share\":\"0.0000\",\"writer1_collection_performance_share\":\"25.0000\",\"writer1_collection_mechanical_share\":\"0.0000\",\"writer1_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer2_first_name\":\"Mauro\",\"writer2_middle_name\":null,\"writer2_last_name\":\"Colavecchi\",\"writer2_capacity\":\"Composer\",\"writer2_society\":\"PRS\",\"writer2_ipi\":\"742926721\",\"writer2_territory\":\"WORLD\",\"writer2_owner_performance_share\":\"25.0000\",\"writer2_owner_mechanical_share\":\"0.0000\",\"writer2_collection_performance_share\":\"25.0000\",\"writer2_collection_mechanical_share\":\"0.0000\",\"writer2_original_publisher\":\"SPACE AND SOUND MUSIC\",\"writer3_first_name\":null,\"writer3_middle_name\":null,\"writer3_last_name\":null,\"writer3_capacity\":null,\"writer3_society\":null,\"writer3_ipi\":null,\"writer3_territory\":null,\"writer3_owner_performance_share\":null,\"writer3_owner_mechanical_share\":null,\"writer3_collection_performance_share\":null,\"writer3_collection_mechanical_share\":null,\"writer3_original_publisher\":null,\"writer4_first_name\":null,\"writer4_middle_name\":null,\"writer4_last_name\":null,\"writer4_capacity\":null,\"writer4_society\":null,\"writer4_ipi\":null,\"writer4_territory\":null,\"writer4_owner_performance_share\":null,\"writer4_owner_mechanical_share\":null,\"writer4_collection_performance_share\":null,\"writer4_collection_mechanical_share\":null,\"writer4_original_publisher\":null,\"publisher1_name\":\"SPACE AND SOUND MUSIC B\",\"publisher1_capacity\":\"Original Publisher\",\"publisher1_society\":\"SOCAN\",\"publisher1_ipi\":\"809010864\",\"publisher1_territory\":\"WORLD\",\"publisher1_owner_performance_share\":\"50.0000\",\"publisher1_owner_mechanical_share\":\"100.0000\",\"publisher1_collection_performance_share\":\"100.0000\",\"publisher1_collection_mechanical_share\":\"100.0000\",\"publisher1_original_publisher\":\"SPACE AND SOUND MUSIC B\",\"publisher2_name\":null,\"publisher2_capacity\":null,\"publisher2_society\":null,\"publisher2_ipi\":null,\"publisher2_territory\":null,\"publisher2_owner_performance_share\":null,\"publisher2_owner_mechanical_share\":null,\"publisher2_collection_performance_share\":null,\"publisher2_collection_mechanical_share\":null,\"publisher2_original_publisher\":null,\"isrc\":\"CBAWZ2107502\",\"iswc\":null,\"sgae_work_number\":null,\"gema_work_number\":null,\"main_track_id\":null},\"populated\":{},\"baseError\":null,\"errors\":{},\"id\":\"063880c5-0ab0-4c10-9915-f7deda5623ff\",\"title\":\"Lights in the dark\",\"recordActions\":[{\"name\":\"show\",\"actionType\":\"record\",\"icon\":\"Monitor\",\"label\":\"show\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"edit\",\"actionType\":\"record\",\"icon\":\"Edit\",\"label\":\"edit\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"delete\",\"actionType\":\"record\",\"icon\":\"Trash2\",\"label\":\"delete\",\"resourceId\":\"tracks\",\"guard\":\"confirmDelete\",\"showFilter\":false,\"showResourceActions\":true,\"component\":false,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"danger\",\"parent\":null,\"hasHandler\":true,\"custom\":{}}],\"bulkActions\":[]}},\"baseError\":null,\"errors\":{},\"id\":\"0001e7f5-f30c-4c94-95c6-bd886db6d639\",\"title\":\"Lights in the dark\",\"recordActions\":[{\"name\":\"show\",\"actionType\":\"record\",\"icon\":\"Monitor\",\"label\":\"show\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"edit\",\"actionType\":\"record\",\"icon\":\"Edit\",\"label\":\"edit\",\"resourceId\":\"tracks\",\"guard\":\"\",\"showFilter\":false,\"showResourceActions\":true,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"default\",\"parent\":null,\"hasHandler\":true,\"custom\":{}},{\"name\":\"delete\",\"actionType\":\"record\",\"icon\":\"Trash2\",\"label\":\"delete\",\"resourceId\":\"tracks\",\"guard\":\"confirmDelete\",\"showFilter\":false,\"showResourceActions\":true,\"component\":false,\"showInDrawer\":false,\"hideActionHeader\":false,\"containerWidth\":1,\"layout\":null,\"variant\":\"danger\",\"parent\":null,\"hasHandler\":true,\"custom\":{}}],\"bulkActions\":[]}}"
          },
          "redirectURL": "",
          "headersSize": 266,
          "bodySize": 11664,
          "_transferSize": 11930,
          "_error": null
        },
        "serverIPAddress": "0.0.0.0",
        "startedDateTime": "2024-04-23T00:52:50.507Z",
        "time": 9.79199999710545,
        "timings": {
          "blocked": 0.8610000102277845,
          "dns": -1,
          "ssl": -1,
          "connect": -1,
          "send": 0.04400000000000001,
          "wait": 8.327000001024455,
          "receive": 0.5599999858532101,
          "_blocked_queueing": 0.6320000102277845
        }
      }
    ]
  }
}

@nickgieschen
Copy link
Author

nickgieschen commented Apr 23, 2024

The SQL is missing the where constraint for the related resource for a many-to-many. In other words, this will work with a many-to-one, but not many-to-many. When I click "Remove relation" Postgres logs:

2024-04-22 17:13:09.393 HST [6181] LOG: execute : delete from "public"."track_genres" where "track_id" = $1
2024-04-22 17:13:09.393 HST [6181] DETAIL: parameters: $1 = '0101355c-41c0-4b22-a379-636027de24a7'

However, it should be delete from "public"."track_genres" where "track_id" = $1 and "genre_id" = $2 since it's using a junction table.

This is confirmed in delete-relation.handler.js:

BaseResource.delete(BaseRecord.id()) has no where constraint for the related record.

@dziraf
Copy link
Contributor

dziraf commented Apr 23, 2024

@nickgieschen does your junction table have an explicit primary key or a composite key? AdminJS won't work without explicit keys. The delete relation handler first finds the junction record using both keys to confirm that it exists and extracts the ID from it and later runs junctionResource.delete(junctionRecord.id()). If your resource has got a composite key only, the .id() will return the value of the first key property only. As of now, the BaseResource.delete method only accepts a single id and no filters.

The need for an explicit PK is mentioned in @adminjs/relations documentation.

@nickgieschen
Copy link
Author

nickgieschen commented Apr 23, 2024

Yes, the junction tables all have a pkey. However, the primary key is a compose key. I see that it will not work with relations now. I think there is a problem with terminology, since a compose key can be a primary key.

Is there a way to override the actions's default behaviour, so I can still use relations with my current schema?

CREATE TABLE IF NOT EXISTS public.track_genres
(
    track_id uuid NOT NULL,
    genre_id uuid NOT NULL,
    is_primary boolean NOT NULL,
    CONSTRAINT track_genres_pkey PRIMARY KEY (track_id, genre_id),
    CONSTRAINT track_genres_genre_id_fkey FOREIGN KEY (genre_id)
        REFERENCES public.genres (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
        NOT VALID,
    CONSTRAINT track_genres_track_id_fkey FOREIGN KEY (track_id)
        REFERENCES public.tracks (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
        NOT VALID
)

TABLESPACE pg_default;

@dziraf
Copy link
Contributor

dziraf commented Apr 23, 2024

this is a composite key, as I wrote above it won't work since AJS doesn't support composite keys

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants