feat: hooked scripts into the blogmark pipeline
This commit is contained in:
@@ -6,6 +6,11 @@ import { openSingletonToolTab } from './navigation/tabPolicy';
|
||||
import { persistSiteValidationReport } from './navigation/siteValidationPersistence';
|
||||
import { executeActivityClick } from './navigation/activityExecution';
|
||||
import { handleBlogmarkCreatedEvent } from './navigation/blogmarkHandling';
|
||||
import {
|
||||
buildBlogmarkTransformOutputEntries,
|
||||
buildBlogmarkTransformToastNotifications,
|
||||
parseBlogmarkCreatedEventPayload,
|
||||
} from './navigation/blogmarkTransformOutput';
|
||||
import { createDeferredEventGate } from './navigation/deferredEventGate';
|
||||
import { createAndFocusPost } from './navigation/postCreation';
|
||||
import { ensureRendererPicoThemeStylesheet, getRendererPicoTheme } from './utils/picoTheme';
|
||||
@@ -34,6 +39,7 @@ const App: React.FC = () => {
|
||||
setPicoTheme,
|
||||
openTab,
|
||||
restoreTabState,
|
||||
appendPanelOutputEntry,
|
||||
} = useAppStore();
|
||||
const blogmarkEventGateRef = useRef(createDeferredEventGate<PostData>());
|
||||
|
||||
@@ -239,12 +245,46 @@ const App: React.FC = () => {
|
||||
);
|
||||
|
||||
unsubscribers.push(
|
||||
window.electronAPI?.on('blogmark:created', (post: unknown) => {
|
||||
const created = post as PostData;
|
||||
window.electronAPI?.on('blogmark:created', (payload: unknown) => {
|
||||
const parsedPayload = parseBlogmarkCreatedEventPayload(payload);
|
||||
if (!parsedPayload) {
|
||||
return;
|
||||
}
|
||||
|
||||
const created = parsedPayload.post as PostData;
|
||||
if (!created?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const outputEntries = buildBlogmarkTransformOutputEntries(parsedPayload.transform, tr);
|
||||
const toastNotifications = buildBlogmarkTransformToastNotifications(parsedPayload.transform, tr);
|
||||
|
||||
toastNotifications.forEach((notification) => {
|
||||
if (notification.kind === 'error') {
|
||||
showToast.error(notification.message);
|
||||
return;
|
||||
}
|
||||
|
||||
showToast.success(notification.message);
|
||||
});
|
||||
|
||||
if (outputEntries.length > 0) {
|
||||
const createdAt = new Date().toISOString();
|
||||
outputEntries.forEach((entry, index) => {
|
||||
appendPanelOutputEntry({
|
||||
id: `blogmark-transform-${Date.now()}-${index}`,
|
||||
createdAt,
|
||||
message: entry.message,
|
||||
kind: entry.kind,
|
||||
});
|
||||
});
|
||||
|
||||
useAppStore.setState({
|
||||
panelVisible: true,
|
||||
panelActiveTab: 'output',
|
||||
});
|
||||
}
|
||||
|
||||
blogmarkEventGateRef.current.push(created, processBlogmarkCreated);
|
||||
}) || (() => {})
|
||||
);
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
"tasks.triggerTitle": "{running} laufend, {pending} ausstehend",
|
||||
"app.taskCompleted": "Aufgabe abgeschlossen: {message}",
|
||||
"app.taskFailed": "Aufgabe fehlgeschlagen: {message}",
|
||||
"app.blogmark.transforms.summary": "Blogmark-Transformationen: {applied} angewendet, {failed} fehlgeschlagen",
|
||||
"app.blogmark.transforms.appliedList": "Angewendete Skripte: {scripts}",
|
||||
"app.blogmark.transforms.failed": "Transformation fehlgeschlagen ({script}): {message}",
|
||||
"app.blogmark.transforms.toast": "Skript-Toast: {message}",
|
||||
"app.blogmark.transforms.errorToast": "Blogmark-Transformationsfehler: {count}",
|
||||
"app.databaseRebuildFailed": "Datenbank-Neuaufbau fehlgeschlagen",
|
||||
"app.textReindexFailed": "Text-Neuindizierung fehlgeschlagen",
|
||||
"app.sitemapGenerationFailed": "Sitemap-Erstellung fehlgeschlagen",
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
"tasks.triggerTitle": "{running} running, {pending} pending",
|
||||
"app.taskCompleted": "Task completed: {message}",
|
||||
"app.taskFailed": "Task failed: {message}",
|
||||
"app.blogmark.transforms.summary": "Blogmark transforms: {applied} applied, {failed} failed",
|
||||
"app.blogmark.transforms.appliedList": "Applied scripts: {scripts}",
|
||||
"app.blogmark.transforms.failed": "Transform failed ({script}): {message}",
|
||||
"app.blogmark.transforms.toast": "Script toast: {message}",
|
||||
"app.blogmark.transforms.errorToast": "Blogmark transform errors: {count}",
|
||||
"app.databaseRebuildFailed": "Database rebuild failed",
|
||||
"app.textReindexFailed": "Text reindex failed",
|
||||
"app.sitemapGenerationFailed": "Sitemap generation failed",
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
"tasks.triggerTitle": "{running} en ejecución, {pending} pendiente",
|
||||
"app.taskCompleted": "Tarea completada: {message}",
|
||||
"app.taskFailed": "Tarea fallida: {message}",
|
||||
"app.blogmark.transforms.summary": "Transformaciones de blogmark: {applied} aplicadas, {failed} fallidas",
|
||||
"app.blogmark.transforms.appliedList": "Scripts aplicados: {scripts}",
|
||||
"app.blogmark.transforms.failed": "Transformación fallida ({script}): {message}",
|
||||
"app.blogmark.transforms.toast": "Toast del script: {message}",
|
||||
"app.blogmark.transforms.errorToast": "Errores de transformación de blogmark: {count}",
|
||||
"app.databaseRebuildFailed": "La reconstrucción de la base de datos falló",
|
||||
"app.textReindexFailed": "La reindexación de texto falló",
|
||||
"app.sitemapGenerationFailed": "La generación del sitemap falló",
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
"tasks.triggerTitle": "{running} en cours, {pending} en attente",
|
||||
"app.taskCompleted": "Tâche terminée : {message}",
|
||||
"app.taskFailed": "Échec de la tâche : {message}",
|
||||
"app.blogmark.transforms.summary": "Transformations blogmark : {applied} appliquées, {failed} en échec",
|
||||
"app.blogmark.transforms.appliedList": "Scripts appliqués : {scripts}",
|
||||
"app.blogmark.transforms.failed": "Échec de transformation ({script}) : {message}",
|
||||
"app.blogmark.transforms.toast": "Toast du script : {message}",
|
||||
"app.blogmark.transforms.errorToast": "Erreurs de transformation blogmark : {count}",
|
||||
"app.databaseRebuildFailed": "Échec de la reconstruction de la base de données",
|
||||
"app.textReindexFailed": "Échec de la réindexation du texte",
|
||||
"app.sitemapGenerationFailed": "Échec de la génération du sitemap",
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
"tasks.triggerTitle": "{running} in esecuzione, {pending} in attesa",
|
||||
"app.taskCompleted": "Attività completata: {message}",
|
||||
"app.taskFailed": "Attività non riuscita: {message}",
|
||||
"app.blogmark.transforms.summary": "Trasformazioni blogmark: {applied} applicate, {failed} non riuscite",
|
||||
"app.blogmark.transforms.appliedList": "Script applicati: {scripts}",
|
||||
"app.blogmark.transforms.failed": "Trasformazione non riuscita ({script}): {message}",
|
||||
"app.blogmark.transforms.toast": "Toast script: {message}",
|
||||
"app.blogmark.transforms.errorToast": "Errori di trasformazione blogmark: {count}",
|
||||
"app.databaseRebuildFailed": "Ricostruzione database non riuscita",
|
||||
"app.textReindexFailed": "Reindicizzazione testo non riuscita",
|
||||
"app.sitemapGenerationFailed": "Generazione sitemap non riuscita",
|
||||
|
||||
168
src/renderer/navigation/blogmarkTransformOutput.ts
Normal file
168
src/renderer/navigation/blogmarkTransformOutput.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import type { PanelOutputEntry, PostData } from '../store';
|
||||
|
||||
export interface BlogmarkTransformDebugError {
|
||||
scriptId: string;
|
||||
scriptSlug: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface BlogmarkTransformDebugInfo {
|
||||
appliedScriptIds: string[];
|
||||
errors: BlogmarkTransformDebugError[];
|
||||
toasts: string[];
|
||||
}
|
||||
|
||||
export interface BlogmarkTransformToastNotification {
|
||||
kind: 'success' | 'error';
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface BlogmarkCreatedEventPayload {
|
||||
post: PostData;
|
||||
transform?: BlogmarkTransformDebugInfo;
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function parseTransformDebugInfo(value: unknown): BlogmarkTransformDebugInfo | undefined {
|
||||
if (!isRecord(value)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const appliedScriptIds = Array.isArray(value.appliedScriptIds)
|
||||
? value.appliedScriptIds.filter((item): item is string => typeof item === 'string')
|
||||
: [];
|
||||
|
||||
const errors = Array.isArray(value.errors)
|
||||
? value.errors
|
||||
.map((entry) => {
|
||||
if (!isRecord(entry)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const scriptId = typeof entry.scriptId === 'string' ? entry.scriptId : '';
|
||||
const scriptSlug = typeof entry.scriptSlug === 'string' ? entry.scriptSlug : '';
|
||||
const message = typeof entry.message === 'string' ? entry.message : '';
|
||||
|
||||
if (!scriptId || !scriptSlug || !message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
scriptId,
|
||||
scriptSlug,
|
||||
message,
|
||||
};
|
||||
})
|
||||
.filter((item): item is BlogmarkTransformDebugError => item !== null)
|
||||
: [];
|
||||
|
||||
const toasts = Array.isArray(value.toasts)
|
||||
? value.toasts
|
||||
.map((entry) => (typeof entry === 'string' ? entry.trim() : ''))
|
||||
.filter((entry) => entry.length > 0)
|
||||
: [];
|
||||
|
||||
if (appliedScriptIds.length === 0 && errors.length === 0 && toasts.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
appliedScriptIds,
|
||||
errors,
|
||||
toasts,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseBlogmarkCreatedEventPayload(payload: unknown): BlogmarkCreatedEventPayload | null {
|
||||
if (!isRecord(payload)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isRecord(payload.post)) {
|
||||
return {
|
||||
post: payload.post as PostData,
|
||||
transform: parseTransformDebugInfo(payload.transform),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
post: payload as PostData,
|
||||
transform: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildBlogmarkTransformOutputEntries(
|
||||
transform: BlogmarkTransformDebugInfo | undefined,
|
||||
t: (key: string, values?: Record<string, string | number>) => string,
|
||||
): Array<Omit<PanelOutputEntry, 'id' | 'createdAt'>> {
|
||||
if (!transform) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const entries: Array<Omit<PanelOutputEntry, 'id' | 'createdAt'>> = [];
|
||||
entries.push({
|
||||
kind: 'result',
|
||||
message: t('app.blogmark.transforms.summary', {
|
||||
applied: transform.appliedScriptIds.length,
|
||||
failed: transform.errors.length,
|
||||
}),
|
||||
});
|
||||
|
||||
if (transform.appliedScriptIds.length > 0) {
|
||||
entries.push({
|
||||
kind: 'result',
|
||||
message: t('app.blogmark.transforms.appliedList', {
|
||||
scripts: transform.appliedScriptIds.join(', '),
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
for (const toastMessage of transform.toasts) {
|
||||
entries.push({
|
||||
kind: 'result',
|
||||
message: t('app.blogmark.transforms.toast', {
|
||||
message: toastMessage,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
for (const error of transform.errors) {
|
||||
entries.push({
|
||||
kind: 'error',
|
||||
message: t('app.blogmark.transforms.failed', {
|
||||
script: error.scriptSlug,
|
||||
message: error.message,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
export function buildBlogmarkTransformToastNotifications(
|
||||
transform: BlogmarkTransformDebugInfo | undefined,
|
||||
t: (key: string, values?: Record<string, string | number>) => string,
|
||||
): BlogmarkTransformToastNotification[] {
|
||||
if (!transform) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const notifications: BlogmarkTransformToastNotification[] = transform.toasts.map((message) => ({
|
||||
kind: 'success',
|
||||
message,
|
||||
}));
|
||||
|
||||
if (transform.errors.length > 0) {
|
||||
notifications.push({
|
||||
kind: 'error',
|
||||
message: t('app.blogmark.transforms.errorToast', {
|
||||
count: transform.errors.length,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return notifications;
|
||||
}
|
||||
Reference in New Issue
Block a user