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:
parent
c93a49e7f2
commit
03456dd483
8 changed files with 180 additions and 22 deletions
|
@ -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' }, '*');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ Get state:
|
|||
penpot.ui.getFileState();
|
||||
|
||||
// file page state
|
||||
penpot.ui.getFileState();
|
||||
penpot.ui.getPageState();
|
||||
|
||||
// selection id
|
||||
penpot.ui.getSelection();
|
||||
|
|
|
@ -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: () => {
|
||||
|
|
26
libs/plugins-runtime/src/lib/index.d.ts
vendored
26
libs/plugins-runtime/src/lib/index.d.ts
vendored
|
@ -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
13
package-lock.json
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue