0
Fork 0
mirror of https://github.com/penpot/penpot-plugins.git synced 2025-01-06 14:50:21 -05:00

feat: update-file example

This commit is contained in:
Juanfran 2024-02-28 12:54:37 +01:00
parent c93a49e7f2
commit 03456dd483
8 changed files with 180 additions and 22 deletions

View file

@ -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 {
<span class="help">Need the .env file and run "start:rpc-api"</span>
</p>
<p>
<button type="button" data-appearance="primary" class="remove-obj">Remove obj</button>
<span class="help">Need the .env file and run "start:rpc-api"</span>
</p>
<p>
<button type="button" data-appearance="primary" data-variant="destructive" class="act-close-plugin">Close plugin</button>
</p>
@ -85,6 +104,29 @@ export class AppElement extends HTMLElement {
});
});
const removeAction = this.querySelector<HTMLElement>('.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' }, '*');
}
}

View file

@ -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) => {

View file

@ -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);
});
});
}

View file

@ -14,7 +14,7 @@ Get state:
penpot.ui.getFileState();
// file page state
penpot.ui.getFileState();
penpot.ui.getPageState();
// selection id
penpot.ui.getSelection();

View file

@ -25,18 +25,21 @@ window.addEventListener('message', (event) => {
}
});
export function triggerEvent<T>(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<unknown>) => {
on<T extends keyof EventsMap>(
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<unknown>);
eventListeners.set(type, listeners);
},
off: (type: string, fn: () => void) => {
off<T extends keyof EventsMap>(
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: () => {

View file

@ -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: <T>(callback: (message: T) => void) => void;
};
log: (message: string) => void;
log: (...data: any[]) => void;
setTimeout: (callback: () => void, time: number) => void;
closePlugin: () => void;
on: <T extends keyof EventsMap>(
type: T,
callback: (event: EventsMap[T]) => void
) => void;
off: (type: string, callback: () => void) => void;
getFileState: () => any;
getPageState: () => any;
off: <T extends keyof EventsMap>(
type: T,
callback: (event: EventsMap[T]) => void
) => void;
getFileState: () => File;
getPageState: () => Page;
getSelection: () => any;
}

13
package-lock.json generated
View file

@ -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",

View file

@ -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"
}
}