From 1c8adef26341b443a31b7d49bf4a29b0d6a8284b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= Date: Tue, 16 Apr 2024 14:26:40 +0200 Subject: [PATCH] feat: grid view mode support --- package-lock.json | 18 ++++-- package.json | 3 +- src/media/extend/extendMediaBulkSelect.js | 78 +++++++++++++++++++++++ src/media/media-upload.tsx | 42 ++++++++++-- 4 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 src/media/extend/extendMediaBulkSelect.js diff --git a/package-lock.json b/package-lock.json index 1c7f794..b57fab7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "packages": { "": { "dependencies": { - "@wordpress/icons": "^9.46.0", "@wordpress/scripts": "^27.6.0", "ts-dom-utils": "^2.2.0" }, @@ -17,10 +16,12 @@ "@wordpress/components": "^27.3.0", "@wordpress/core-data": "^6.32.0", "@wordpress/data": "^9.25.0", + "@wordpress/dom-ready": "^3.55.0", "@wordpress/element": "^5.32.0", "@wordpress/hooks": "^3.55.0", "@wordpress/html-entities": "^3.55.0", "@wordpress/i18n": "^4.55.0", + "@wordpress/icons": "^9.46.0", "@wordpress/notices": "^4.23.0" } }, @@ -3984,7 +3985,8 @@ "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true }, "node_modules/@types/qs": { "version": "6.9.14", @@ -4000,6 +4002,7 @@ "version": "18.2.74", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.74.tgz", "integrity": "sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==", + "dev": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4009,6 +4012,7 @@ "version": "18.2.24", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.24.tgz", "integrity": "sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==", + "dev": true, "dependencies": { "@types/react": "*" } @@ -5194,6 +5198,7 @@ "version": "5.32.0", "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-5.32.0.tgz", "integrity": "sha512-tHphxNspSIw3UFZ7oRUc1UlmHnViDbiACmNqWyUoVfIOv/f9bKe1UMrPxLKaF3HoSmAkQuWcLJu+/k202a40xA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.16.0", "@types/react": "^18.0.21", @@ -5212,6 +5217,7 @@ "version": "2.55.0", "resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-2.55.0.tgz", "integrity": "sha512-usYRUHFAsTcO3RLUfnBr8CSA6fO9swi0rYHh0H+rX0bxVWnoDQQTdTkQ00FfyN8D44Y80CY9/pQLmtoeK3rLNA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.16.0" }, @@ -5347,6 +5353,7 @@ "version": "9.46.0", "resolved": "https://registry.npmjs.org/@wordpress/icons/-/icons-9.46.0.tgz", "integrity": "sha512-SsjZ2aw6FEYHW0pHVXWGRQibBY//9qvkrzGFNsnxPz9e7yUu+Nqt/1Hr2/J+5qGdCBZtTzDvCkAw5zf0LtEfwA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/element": "^5.32.0", @@ -5514,6 +5521,7 @@ "version": "3.53.0", "resolved": "https://registry.npmjs.org/@wordpress/primitives/-/primitives-3.53.0.tgz", "integrity": "sha512-2xKrD57w9b7WSUkK+GYzgAcHWGJ5PFLHqSUmUZ0O4nptIGFQqCC4ZxHEHzBCOseAjDilW4AFYUbOLcLuMcgFHA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/element": "^5.32.0", @@ -7104,7 +7112,8 @@ "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true }, "node_modules/clean-webpack-plugin": { "version": "3.0.0", @@ -7922,7 +7931,8 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true }, "node_modules/cwd": { "version": "0.10.0", diff --git a/package.json b/package.json index 7cb7afd..c4a131f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "format": "wp-scripts format" }, "dependencies": { - "@wordpress/icons": "^9.46.0", "@wordpress/scripts": "^27.6.0", "ts-dom-utils": "^2.2.0" }, @@ -19,10 +18,12 @@ "@wordpress/components": "^27.3.0", "@wordpress/core-data": "^6.32.0", "@wordpress/data": "^9.25.0", + "@wordpress/dom-ready": "^3.55.0", "@wordpress/element": "^5.32.0", "@wordpress/hooks": "^3.55.0", "@wordpress/html-entities": "^3.55.0", "@wordpress/i18n": "^4.55.0", + "@wordpress/icons": "^9.46.0", "@wordpress/notices": "^4.23.0" } } diff --git a/src/media/extend/extendMediaBulkSelect.js b/src/media/extend/extendMediaBulkSelect.js new file mode 100644 index 0000000..5fddf5b --- /dev/null +++ b/src/media/extend/extendMediaBulkSelect.js @@ -0,0 +1,78 @@ +import { __ } from "@wordpress/i18n"; + +/** + * @param {(selectedIds: number[]) => void} onButtonClick + */ +export default (onButtonClick) => { + const wp = window.wp; + + if (!wp?.media?.view) return; + + const AttachmentsBrowser = wp.media.view.AttachmentsBrowser; + const Button = wp.media.view.Button; + + const BulkGenerationButton = Button.extend({ + initialize: function () { + Button.prototype.initialize.apply(this, arguments); + this.controller.on("selection:toggle", this.toggleDisabled, this); + this.controller.on("select:activate", this.selectActivate, this); + this.controller.on("select:deactivate", this.selectDeactivate, this); + }, + + toggleDisabled: function () { + this.model.set( + "disabled", + !this.controller.state().get("selection").length, + ); + }, + + selectActivate: function () { + this.toggleDisabled(); + this.$el.removeClass("hidden"); + }, + + selectDeactivate: function () { + this.toggleDisabled(); + this.$el.addClass("hidden"); + }, + + render: function () { + Button.prototype.render.apply(this, arguments); + + if (this.controller.isModeActive("select")) { + this.selectActivate(); + } else { + this.selectDeactivate(); + } + + return this; + }, + + click: function () { + const selection = this.controller.state().get("selection"); + if (!selection.length) return; + + onButtonClick(selection.models.map((model) => model.id)); + }, + }); + + wp.media.view.AttachmentsBrowser = AttachmentsBrowser.extend({ + createToolbar: function () { + AttachmentsBrowser.prototype.createToolbar.apply(this, arguments); + + this.toolbar.set( + "bulkAltGenerate", + new BulkGenerationButton({ + style: "primary", + disabled: true, + text: __( + "Generate alternative text", + "alt-text-generator-gpt-vision", + ), + controller: this.controller, + priority: -75, + }).render(), + ); + }, + }); +}; diff --git a/src/media/media-upload.tsx b/src/media/media-upload.tsx index 9f9ed0e..4ad9d04 100644 --- a/src/media/media-upload.tsx +++ b/src/media/media-upload.tsx @@ -1,16 +1,35 @@ +import domReady from "@wordpress/dom-ready"; import { createRoot, useEffect, useState } from "@wordpress/element"; import { qs } from "ts-dom-utils"; import BulkGenerateModal from "../components/BulkGenerateModal"; import { BULK_ACTION_OPTION_VALUE } from "../constants"; - -const reactRoot = document.createElement("div"); -reactRoot.id = "acpl-bulk-generate-alts-app"; -document.body.appendChild(reactRoot); +import extendMediaBulkSelect from "./extend/extendMediaBulkSelect"; const App = () => { const [isModalOpen, setIsModalOpen] = useState(false); const [selectedMediaIds, setSelectedMediaIds] = useState([]); + // Grid mode + useEffect(() => { + const listener = (e: CustomEvent) => { + setSelectedMediaIds(e.detail); + setIsModalOpen(true); + }; + + document.addEventListener( + "triggerBulkAltGenerateModal", + listener as EventListener, + ); + + return () => { + document.removeEventListener( + "triggerBulkAltGenerateModal", + listener as EventListener, + ); + }; + }, []); + + // List mode useEffect(() => { const form = qs("form#posts-filter"); if (!form) return; @@ -43,4 +62,17 @@ const App = () => { ) : null; }; -createRoot(reactRoot).render(); +domReady(() => { + extendMediaBulkSelect((ids) => { + document.dispatchEvent( + new CustomEvent("triggerBulkAltGenerateModal", { + detail: ids, + }), + ); + }); + + const reactRoot = document.createElement("div"); + reactRoot.id = "acpl-bulk-generate-alts-app"; + document.body.appendChild(reactRoot); + createRoot(reactRoot).render(); +});