From 03456dd483a44fbd8c2da9c82103b46bc00c9ca3 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Wed, 28 Feb 2024 12:54:37 +0100 Subject: [PATCH] feat: update-file example --- apps/example-plugin/src/app/app.element.ts | 50 +++++++++++++++++-- apps/example-plugin/src/plugin.ts | 27 ++++++++++- apps/rpc-api/src/app/routes/root.ts | 56 ++++++++++++++++++++++ docs/plugin-usage.md | 2 +- libs/plugins-runtime/src/lib/api/index.ts | 27 +++++++---- libs/plugins-runtime/src/lib/index.d.ts | 26 +++++++--- package-lock.json | 13 +++++ package.json | 1 + 8 files changed, 180 insertions(+), 22 deletions(-) diff --git a/apps/example-plugin/src/app/app.element.ts b/apps/example-plugin/src/app/app.element.ts index 31e6a2b..c0ab4cd 100644 --- a/apps/example-plugin/src/app/app.element.ts +++ b/apps/example-plugin/src/app/app.element.ts @@ -3,9 +3,16 @@ import './app.element.css'; export class AppElement extends HTMLElement { public static observedAttributes = []; + #selection = ''; + #pageId = ''; + #fileId = ''; + #revn = 0; + + refreshPage(pageId: string, name: string) { + console.log('refreshPage', pageId, name); - refreshPageName(name: string) { const projectName = document.getElementById('project-name'); + this.#pageId = pageId; if (projectName) { projectName.innerText = name; @@ -13,10 +20,12 @@ export class AppElement extends HTMLElement { } refreshSelectionId(selection: string) { + this.#selection = selection; + const selectionId = document.getElementById('selection-id'); if (selectionId) { - selectionId.innerText = selection; + selectionId.innerText = this.#selection; } } @@ -24,12 +33,17 @@ export class AppElement extends HTMLElement { window.addEventListener('message', (event) => { if (event.data.type === 'pingpong') { console.log('iframe', event.data.content); + } else if (event.data.type === 'file') { + this.#fileId = event.data.content.id; + this.#revn = event.data.content.revn; } else if (event.data.type === 'page') { - this.refreshPageName(event.data.content); + this.refreshPage(event.data.content.id, event.data.content.name); } else if (event.data.type === 'selection') { this.refreshSelectionId(event.data.content); } else if (event.data.type === 'init') { - this.refreshPageName(event.data.content.name); + this.#fileId = event.data.content.fileId; + this.#revn = event.data.content.revn; + this.refreshPage(event.data.content.pageId, event.data.content.name); this.refreshSelectionId(event.data.content.selection); } }); @@ -51,6 +65,11 @@ export class AppElement extends HTMLElement { Need the .env file and run "start:rpc-api"

+

+ + Need the .env file and run "start:rpc-api" +

+

@@ -85,6 +104,29 @@ export class AppElement extends HTMLElement { }); }); + const removeAction = this.querySelector('.remove-obj'); + + removeAction?.addEventListener('click', () => { + fetch('http://localhost:3000/delete-object', { + method: 'DELETE', + body: JSON.stringify({ + fileId: this.#fileId, + revn: this.#revn, + pageId: this.#pageId, + objectId: this.#selection, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then((response) => { + return response.json(); + }) + .then((data) => { + console.log(data); + }); + }); + parent.postMessage({ content: 'ready' }, '*'); } } diff --git a/apps/example-plugin/src/plugin.ts b/apps/example-plugin/src/plugin.ts index 495fd62..a88600d 100644 --- a/apps/example-plugin/src/plugin.ts +++ b/apps/example-plugin/src/plugin.ts @@ -12,10 +12,16 @@ penpot.ui.onMessage<{ content: string }>((message) => { } else if (message.content === 'close') { penpot.closePlugin(); } else if (message.content === 'ready') { + const pageState = penpot.getPageState(); + const fileState = penpot.getFileState(); + penpot.ui.sendMessage({ type: 'init', content: { - name: penpot.getPageState().name, + name: pageState.name, + pageId: pageState.id, + fileId: fileState.id, + revn: fileState.revn, selection: penpot.getSelection(), }, }); @@ -23,7 +29,24 @@ penpot.ui.onMessage<{ content: string }>((message) => { }); penpot.on('pagechange', (page) => { - penpot.ui.sendMessage({ type: 'page', content: page.name }); + penpot.ui.sendMessage({ + type: 'page', + content: { + name: page.name, + id: page.id, + }, + }); +}); + +penpot.on('filechange', (file) => { + penpot.ui.sendMessage({ + type: 'file', + content: { + name: file.name, + id: file.id, + revn: file.revn, + }, + }); }); penpot.on('selectionchange', (id) => { diff --git a/apps/rpc-api/src/app/routes/root.ts b/apps/rpc-api/src/app/routes/root.ts index aa15da3..1a09169 100644 --- a/apps/rpc-api/src/app/routes/root.ts +++ b/apps/rpc-api/src/app/routes/root.ts @@ -1,9 +1,11 @@ import { FastifyInstance } from 'fastify'; +import { v4 } from 'uuid'; const token = process.env.ACCESS_TOKEN; export default async function (fastify: FastifyInstance) { const apiUrl = process.env.API_URL; + const fakeSessionId = v4(); fastify.get('/get-profile', function () { return fetch(`${apiUrl}/get-profile`, { @@ -17,4 +19,58 @@ export default async function (fastify: FastifyInstance) { console.error('Error:', error); }); }); + + fastify.delete<{ + Body: { + fileId: string; + revn: number; + pageId: string; + objectId: string; + }; + }>('/delete-object', function (request, reply) { + const payload = { + '~:id': `~u${request.body.fileId}`, + '~:revn': request.body.revn, + '~:session-id': `~u${fakeSessionId}`, + '~:changes': [ + { + '~:type': '~:del-obj', + '~:page-id': `~u${request.body.pageId}`, + '~:ignore-touched': false, + '~:id': `~u${request.body.objectId}`, + }, + ], + '~:features': { + '~#set': [ + 'layout/grid', + 'styles/v2', + 'fdata/pointer-map', + 'fdata/objects-map', + 'fdata/shape-data-type', + ], + }, + }; + + console.log('Payload:', payload); + + return fetch( + `http://localhost:3449/api/rpc/command/update-file?id=${request.body.fileId}`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/transit+json', + Authorization: `Token ${token}`, + }, + body: JSON.stringify(payload), + } + ) + .then((response) => response.json()) + .then((data) => { + console.log('Success:', data); + reply.send(data); + }) + .catch((error) => { + console.error('Error:', error); + }); + }); } diff --git a/docs/plugin-usage.md b/docs/plugin-usage.md index bc4d892..b9f66db 100644 --- a/docs/plugin-usage.md +++ b/docs/plugin-usage.md @@ -14,7 +14,7 @@ Get state: penpot.ui.getFileState(); // file page state -penpot.ui.getFileState(); +penpot.ui.getPageState(); // selection id penpot.ui.getSelection(); diff --git a/libs/plugins-runtime/src/lib/api/index.ts b/libs/plugins-runtime/src/lib/api/index.ts index 79159c0..9d8b44d 100644 --- a/libs/plugins-runtime/src/lib/api/index.ts +++ b/libs/plugins-runtime/src/lib/api/index.ts @@ -25,18 +25,21 @@ window.addEventListener('message', (event) => { } }); -export function triggerEvent(type: string, message: T) { +export function triggerEvent( + type: keyof EventsMap, + message: EventsMap[keyof EventsMap] +) { const listeners = eventListeners.get(type) || []; listeners.forEach((listener) => listener(message)); } -export function setPageState(page: unknown) { +export function setPageState(page: Page) { pageState = page; triggerEvent('pagechange', page); } -export function setFileState(file: unknown) { +export function setFileState(file: File) { fileState = file; triggerEvent('filechange', file); @@ -92,25 +95,31 @@ export function createApi() { setTimeout(callback, time); }), closePlugin, - on: (type: string, fn: Callback) => { + on( + type: T, + callback: (event: EventsMap[T]) => void + ): void { // z.function alter fn, so can't use it here z.enum(validEvents).parse(type); - z.function().parse(fn); + z.function().parse(callback); const listeners = eventListeners.get(type) || []; - listeners.push(fn); + listeners.push(callback as Callback); eventListeners.set(type, listeners); }, - off: (type: string, fn: () => void) => { + off( + type: T, + callback: (event: EventsMap[T]) => void + ): void { z.enum(validEvents).parse(type); - z.function().parse(fn); + z.function().parse(callback); const listeners = eventListeners.get(type) || []; eventListeners.set( type, - listeners.filter((listener) => listener !== fn) + listeners.filter((listener) => listener !== callback) ); }, getFileState: () => { diff --git a/libs/plugins-runtime/src/lib/index.d.ts b/libs/plugins-runtime/src/lib/index.d.ts index f9dafcc..ec38ba4 100644 --- a/libs/plugins-runtime/src/lib/index.d.ts +++ b/libs/plugins-runtime/src/lib/index.d.ts @@ -1,8 +1,19 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +interface Page { + name: string; + id: string; +} + +interface File { + name: string; + id: string; + revn: number; +} + interface EventsMap { - pagechange: { name: string }; - filechange: any; + pagechange: Page; + filechange: File; selectionchange: string; } @@ -16,16 +27,19 @@ interface Penpot { sendMessage: (message: unknown) => void; onMessage: (callback: (message: T) => void) => void; }; - log: (message: string) => void; + log: (...data: any[]) => void; setTimeout: (callback: () => void, time: number) => void; closePlugin: () => void; on: ( type: T, callback: (event: EventsMap[T]) => void ) => void; - off: (type: string, callback: () => void) => void; - getFileState: () => any; - getPageState: () => any; + off: ( + type: T, + callback: (event: EventsMap[T]) => void + ) => void; + getFileState: () => File; + getPageState: () => Page; getSelection: () => any; } diff --git a/package-lock.json b/package-lock.json index fc66bbb..12f487b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "fastify-plugin": "~4.5.0", "ses": "^1.1.0", "tslib": "^2.3.0", + "uuid": "^9.0.1", "zod": "^3.22.4" }, "devDependencies": { @@ -11982,6 +11983,18 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index 7c37cbf..bde2027 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "fastify-plugin": "~4.5.0", "ses": "^1.1.0", "tslib": "^2.3.0", + "uuid": "^9.0.1", "zod": "^3.22.4" } }