From 5a9c2a1e0398a3e8ac3fe0bc852bdbf524bc88d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20M=C3=BCller?= Date: Wed, 5 Feb 2025 14:14:33 +0100 Subject: [PATCH 1/5] Added new localization for de-DE --- data/localizedData.json | 295 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) diff --git a/data/localizedData.json b/data/localizedData.json index ab3b183..e94a118 100644 --- a/data/localizedData.json +++ b/data/localizedData.json @@ -42,6 +42,301 @@ "description": "Was sind die wesentlichen Vorteile oder Einnahmequellen, die durch die API generiert werden?" } } + }, + "apiValuePropositionCanvas": { + "title": "API-Wertversprechen Canvas", + "purpose": "Berücksichtigt diese API die Aufgaben, Probleme (Pains) und Bedürfnisse (Gains) der API-Konsumenten?", + "howToUse": "Beschreiben Sie die Sichtweise des API-Konsumenten, beginnend mit seinen Aufgaben, dann seine Pains und Gains, und schließlich die API-Produkte und -Features.", + "sections": { + "tasks": { + "section": "Aufgaben", + "description": "Was wollen die API-Konsumenten erreichen?" + }, + "gainEnablingFeatures": { + "section": "Bedürfnissstillende Features", + "description": "Welche Features ermöglichen es API-Konsumenten ihre Bedürfnisse zu bedienen?" + }, + "painRelievingFeatures": { + "section": "Problembewältigende Features", + "description": "Welche Features ermöglichen es API-Konsumenten ihre Probleme zu überwinden?" + }, + "apiProducts": { + "section": "API-Produkte", + "description": "Welche API-Produkte und -Features eigenen sich für diese Aufgaben, Probleme und Bedürfnisse?" + } + } + }, + "businessImpactCanvas": { + "title": "Geschäftsauswirkung Canvas", + "purpose": "Was sind die potenziellen geschäftlichen Auswirkungen eines API-Ausfalls?", + "howToUse": "Berücksichtigen Sie die potenziellen Auswirkungen auf Verfügbarkeit, Sicherheit und Daten für jede API.", + "sections": { + "availabilityRisks": { + "section": "Verfügbarkeitsrisiken", + "description": "Was sind die potenziellen Risiken für die API-Verfügbarkeit?" + }, + "securityRisks": { + "section": "Sicherheitsrisiken", + "description": "Welche potenziellen Sicherheitsrisiken sind mit der API assoziiert?" + }, + "dataRisks": { + "section": "Datenrisiken", + "description": "Welche potenziellen Risiken bestehen für die Datenintegrität oder -Vertraulichkeit?" + }, + "mitigateAvailabilityRisks": { + "section": "Reduktion der Verfügbarkeitsrisiken", + "description": "Wie kann der API-Anbieter die Verfügbarkeitsrisiken reduzieren?" + }, + "mitigateSecurityRisks": { + "section": "Reduktion der Sicherheitsrisiken", + "description": "Wie kann der API-Anbieter die Sicherheitsrisiken reduzieren?" + }, + "mitigateDataRisks": { + "section": "Reduktion der Datenrisiken", + "description": "Wie kann der API-Anbieter die Datenrisiken reduzieren?" + } + } + }, + "capacityCanvas": { + "title": "Kapazität Canvas", + "purpose": "Wie viel Kapazität wird für den API-Konsum benötigt", + "howToUse": "Analysieren Sie die aktuellen und zukünftigen Kapazitätsanforderungen für jede API.", + "sections": { + "currentBusinessVolumes": { + "section": "Aktuelles Geschäftsvolumen", + "description": "Wie hoch sind das aktuelle Geschäftsvolumen und die Transaktionsraten?" + }, + "futureConsumptionTrends": { + "section": "Zukünftige Konsumtrends", + "description": "Was sind die erwarteten künftigen Konsumtrends?" + }, + "peakLoadAndAvailabilityRequirements": { + "section": "Spitzenlast- und Verfügbarkeitsanforderungen", + "description": "Was sind die Spitzenlast- und Verfügbarkeitsanforderungen?" + }, + "cachingStrategies": { + "section": "Caching-Strategien", + "description": "Welche Caching-Strategien können zur Performanceoptimierung eingesetzt werden?" + }, + "rateLimitingStrategies": { + "section": "Rate-Limiting-Strategien", + "description": "Welche Rate-Limiting-Strategien können zur Konsumsteuerung eingesetzt werden?" + }, + "scalingStrategies": { + "section": "Skalierungs-Strategien", + "description": "Welche Skalierungs-Strategien können eingesetzt werden, um das Wachstum zu unterstützen?" + } + } + }, + "customerJourneyCanvas": { + "title": "Customer Journey Canvas", + "purpose": "Wie interagieren die API-Konsumenten im Laufe der Zeit mit der API?", + "howToUse": "Erfassen Sie das Customer Journey für jede API, von der ersten Entdeckung bis zur aktuellen Nutzung.", + "sections": { + "customerDiscoversNeed": { + "section": "Kunde erkennt Bedarf", + "description": "Wie erkennt der Kunde den Bedarf an der API?" + }, + "persona": { + "section": "Persona", + "description": "Wie sieht der typische Kunde oder Nutzer der API aus?" + }, + "pains": { + "section": "Probleme", + "description": "Was sind die Probleme oder Herausforderungen des Kunden?" + }, + "journeySteps": { + "section": "Customer Journey Schritte", + "description": "Welche Schritte durchläuft der Kunde bei der Nutzung der API?" + }, + "customerNeedIsResolved": { + "section": "Kundenbedürfnis wird gelöst", + "description": "Wie wird das Bedürfnis des Kunden letztendlich gelöst?" + }, + "gains": { + "section": "Nutzen", + "description": "Welchen Gewinn oder Nutzen hat der Kunde?" + }, + "inputsOutputs": { + "section": "Inputs & Outputs", + "description": "Was sind die Inputs und Outputs bei jedem Schritt?" + }, + "interactionProcessingRules": { + "section": "Interaktions- und Verarbeitungsregeln", + "description": "Wie lauten die Interaktions- und Verarbeitungsregeln bei jedem Schritt?" + } + } + }, + "domainCanvas": { + "title": "Domäne Canvas", + "purpose": "Was sind die wesentlichen Entitäten und Geschäftsregeln im Zusammenhang mit der API?", + "howToUse": "Definieren Sie das Domänenmodell für jede API, einschließlich Entitäten, Attribute und Beziehungen.", + "sections": { + "selectedCustomerJourneySteps": { + "section": "Ausgewählte Customer Journey Schritte", + "description": "Welche Customer Journey Schritte sind für diese Domäne relevant?" + }, + "coreEntitiesAndBusinessMeaning": { + "section": "Grundlegende Entitäten & geschäftliche Bedeutung", + "description": "Welches sind die wesentlichen Entitäten und ihre Bedeutung für das Geschäft?" + }, + "attributesAndBusinessImportance": { + "section": "Attribute & geschäftliche Wichtigkeit", + "description": "Welches sind die Schlüsselattribute der einzelnen Entitäten und ihre geschäftliche Wichtigkeit?" + }, + "relationshipsBetweenEntities": { + "section": "Beziehungen zwischen Entitäten", + "description": "Welche Beziehungen bestehen zwischen den Entitäten?" + }, + "businessComplianceAndIntegrityRules": { + "section": "Geschäfts-, Compliance- und Integritätsregeln", + "description": "Welche Geschäfts-, Compliance- und Integritätsregeln gelten für die Entitäten?" + }, + "securityAndPrivacyConsiderations": { + "section": "Überlegungen zu Sicherheit und Datenschutz", + "description": "Welche Überlegungen zur Sicherheit und zum Datenschutz gibt es im Zusammenhang mit den Entitäten?" + } + } + }, + "eventCanvas": { + "title": "Event Canvas", + "purpose": "Welche Events sind für die API relevant, und wie werden sie verarbeitet?", + "howToUse": "Definieren Sie die Events, ihre Trigger und die Verarbeitungslogik für jede API.", + "sections": { + "userTaskTrigger": { + "section": "Nutzeraufgabe / Trigger", + "description": "Welche Nutzeraktion oder welches System-Event löst diese Eventoperation aus?" + }, + "inputEventPayload": { + "section": "Input / Event-Payload", + "description": "Welche Daten sind in der eingehenden Event-Payload enthalten? Geben Sie die Schlüsselattribute an." + }, + "processingLogic": { + "section": "Verarbeitung / Logik", + "description": "Beschreiben Sie die Backend-Verarbeitungslogik, inklusive Validierungen, Transformationen, oder Routing-Entscheidungen." + }, + "outputEventResult": { + "section": "Output / Event-Ergebnis", + "description": "Welches Event oder welche Bestätigungsmeldung wird erzeugt? Geben Sie die Attribute des Output-Payloads an." + } + } + }, + "interactionCanvas": { + "title": "Interaktion Canvas", + "purpose": "Welche verschiedenen Interaktionsarten werden von der API unterstützt?", + "howToUse": "Definieren Sie die CRUD-, abfrage-, befehlsgesteuerten und eventgesteuerten Interaktionen für jede API.", + "sections": { + "crudInteractions": { + "section": "CRUD Interaktionen", + "description": "Welche CRUD-Interaktionen (Create, Read, Update, Delete) werden von der API unterstützt?" + }, + "crudInputOutputModels": { + "section": "CRUD Input- & Output-Modelle", + "description": "Was sind die Input- und Output-Modelle für die CRUD-Interaktionen?" + }, + "crudProcessingValidation": { + "section": "CRUD Verarbeitung & Validierung", + "description": "Wie sehen die Verarbeitungs- und Validierungsregeln für die CRUD-Interaktionen aus?" + }, + "queryDrivenInteractions": { + "section": "Abfragegesteuerte Interaktionen", + "description": "Welche abfragegesteuerten Interaktionen werden von der API unterstützt?" + }, + "queryDrivenInputOutputModels": { + "section": "Abfragegesteuerte Input- & Output-Modelle", + "description": "Was sind die Input- und Output-Modelle für die abfragegesteuerten Interaktionen" + }, + "queryDrivenProcessingValidation": { + "section": "Abfragegesteuerte Verarbeitung & Validierung", + "description": "Wie sehen die Verarbeitungs- und Validierungsregeln für die abfragegesteuerten Interaktionen aus?" + }, + "commandDrivenInteractions": { + "section": "Befehlsgesteuerte Interaktionen", + "description": "Welche befehlsgesteuerten Interaktionen werden von der API unterstützt?" + }, + "commandDrivenInputOutputModels": { + "section": "Befehlsgesteuerte Input- & Output-Modelle", + "description": "Was sind die Input- und Output-Modelle für die befehlsgesteuerten Interaktionen?" + }, + "commandDrivenProcessingValidation": { + "section": "Befehlsgesteuerte Verarbeitung & Validierung", + "description": "Wie sehen die Verarbeitungs- und Validierungsregeln für die befehlsgesteuerten Interaktionen aus?" + }, + "eventDrivenInteractions": { + "section": "Eventgesteuerte Interaktionen", + "description": "Welche eventgesteuerten Interaktionen werden von der API unterstützt?" + }, + "eventDrivenInputOutputModels": { + "section": "Eventgesteuerte Input- & Output-Modelle", + "description": "Was sind die Input- und Output-Modelle für die eventgesteuerten Interaktionen?" + }, + "eventDrivenProcessingValidation": { + "section": "Eventgesteuerte Verarbeitung & Validierung", + "description": "Wie sehen die Verarbeitungs- und Validierungsregeln für die eventgesteuerten Interaktionen aus?" + } + } + }, + "locationsCanvas": { + "title": "Standorte Canvas", + "purpose": "Was sind die relevanten Standorte und ihre Merkmale?", + "howToUse": "Definieren Sie die Standorte, ihre Entfernungen und ihre Endpunkte für jede API.", + "sections": { + "locationGroups": { + "section": "Standortgruppen", + "description": "Welches sind die relevanten Standortgruppen?" + }, + "locationGroupCharacteristics": { + "section": "Standortgruppenmerkmale", + "description": "Was sind die Merkmale der Standortgruppen?" + }, + "locations": { + "section": "Standorte", + "description": "Welches sind die relevanten Standorte innerhalb jeder Gruppe?" + }, + "locationCharacteristics": { + "section": "Standortmerkmale", + "description": "Was sind die Merkmale der Standorte?" + }, + "locationDistances": { + "section": "Standortentfernungen", + "description": "Wie groß sind die Entfernungen zwischen den Standorten?" + }, + "locationDistanceCharacteristics": { + "section": "Standort-Entfernungsmerkmale", + "description": "Was sind die Merkmale der Standortentfernungen?" + }, + "locationEndpoints": { + "section": "Standort-Endpunkte", + "description": "Welche Endpunkte sind mit den Standorten assoziiert?" + }, + "locationEndpointCharacteristics": { + "section": "Standort-Endpunktemerkmale", + "description": "Was sind die Merkmale der Standort-Endpunkte?" + } + } + }, + "restCanvas": { + "title": "REST Canvas", + "purpose": "Wie kann die API nach RESTful-Prinzipien gestaltet werden?", + "howToUse": "Definieren Sie die API-Ressourcen, HTTP-Methoden und Beispielanfragen und -antworten.", + "sections": { + "apiResources": { + "section": "API-Ressourcen", + "description": "Was sind die Schlüsselressourcen, die von der API bereitgestellt werden?" + }, + "apiResourceModel": { + "section": "API-Ressourcenmodell", + "description": "Wie sieht die Struktur des API-Ressourcenmodells aus?" + }, + "apiVerbs": { + "section": "HTTP-Methoden der API", + "description": "Welche HTTP-Methoden werden für die Interaktion mit den API-Ressourcen verwendet?" + }, + "apiVerbExample": { + "section": "HTTP-Methoden-Beispiel", + "description": "Geben Sie für jede HTTP-Methode ein Beispiel für eine API-Anfrage und -Antwort an." + } + } } }, "en-US": { From 0df736fa24b4987e9772b20b3050d7c277d90fa0 Mon Sep 17 00:00:00 2001 From: Daniel Kocot Date: Sun, 23 Feb 2025 00:11:47 +0100 Subject: [PATCH 2/5] clean up and polishing of localizedData.json --- data/localizedData.json | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/data/localizedData.json b/data/localizedData.json index e94a118..372d93d 100644 --- a/data/localizedData.json +++ b/data/localizedData.json @@ -1,9 +1,9 @@ { "de-DE": { "apiBusinessModelCanvas": { - "title": "API-Geschäftsmodell Canvas", + "title": "API Business Model Canvas", "purpose": "Wie praktikabel und wiederverwendbar wird diese API sein? Haben wir einen Business Case aus Kosten-Nutzen-Sicht?", - "howToUse": "Fassen Sie das Wertversprechen einer API aus dem API-Wertversprechen-Canvas zusammen und folgen Sie dann der nummerierten Reihenfolge.", + "howToUse": "Fassen Sie das Wertversprechen einer API aus dem API Value Proposition Canvas zusammen und folgen Sie dann der nummerierten Reihenfolge.", "sections": { "keyPartners": { "section": "Schlüsselpartner", @@ -18,7 +18,7 @@ "description": "Welche einzigartigen strategischen Vermögenswerte muss der API-Anbieter erwerben oder aufbauen?" }, "apiValueProposition": { - "section": "API-Wertversprechen", + "section": "Wertversprechen der API", "description": "Welchen Wert bietet die API den API-Konsumenten?" }, "developerRelations": { @@ -30,7 +30,7 @@ "description": "Über welche Mechanismen interagieren API-Konsumenten mit der API?" }, "apiConsumerSegments": { - "section": "API-Konsumentensegmente", + "section": "Konsumenten der API", "description": "Wer sind die Zielgruppen für die API?" }, "costs": { @@ -44,7 +44,7 @@ } }, "apiValuePropositionCanvas": { - "title": "API-Wertversprechen Canvas", + "title": "API Value Proposition Canvas", "purpose": "Berücksichtigt diese API die Aufgaben, Probleme (Pains) und Bedürfnisse (Gains) der API-Konsumenten?", "howToUse": "Beschreiben Sie die Sichtweise des API-Konsumenten, beginnend mit seinen Aufgaben, dann seine Pains und Gains, und schließlich die API-Produkte und -Features.", "sections": { @@ -53,11 +53,11 @@ "description": "Was wollen die API-Konsumenten erreichen?" }, "gainEnablingFeatures": { - "section": "Bedürfnissstillende Features", + "section": "Nutzenstiftende Features", "description": "Welche Features ermöglichen es API-Konsumenten ihre Bedürfnisse zu bedienen?" }, "painRelievingFeatures": { - "section": "Problembewältigende Features", + "section": "Problemlösende Features", "description": "Welche Features ermöglichen es API-Konsumenten ihre Probleme zu überwinden?" }, "apiProducts": { @@ -67,12 +67,12 @@ } }, "businessImpactCanvas": { - "title": "Geschäftsauswirkung Canvas", - "purpose": "Was sind die potenziellen geschäftlichen Auswirkungen eines API-Ausfalls?", + "title": "Business Impact Canvas", + "purpose": "Was sind die potenziellen geschäftlichen Auswirkungen eines Ausfalls einer API?", "howToUse": "Berücksichtigen Sie die potenziellen Auswirkungen auf Verfügbarkeit, Sicherheit und Daten für jede API.", "sections": { "availabilityRisks": { - "section": "Verfügbarkeitsrisiken", + "section": "Risiken der Verfügbarkeit", "description": "Was sind die potenziellen Risiken für die API-Verfügbarkeit?" }, "securityRisks": { @@ -84,8 +84,8 @@ "description": "Welche potenziellen Risiken bestehen für die Datenintegrität oder -Vertraulichkeit?" }, "mitigateAvailabilityRisks": { - "section": "Reduktion der Verfügbarkeitsrisiken", - "description": "Wie kann der API-Anbieter die Verfügbarkeitsrisiken reduzieren?" + "section": "Reduzierung von Risiken der Verfügbarkeit", + "description": "Wie kann der API-Anbieter die Risiken der Verfügbarkeit reduzieren?" }, "mitigateSecurityRisks": { "section": "Reduktion der Sicherheitsrisiken", @@ -98,8 +98,8 @@ } }, "capacityCanvas": { - "title": "Kapazität Canvas", - "purpose": "Wie viel Kapazität wird für den API-Konsum benötigt", + "title": "Capacity Canvas", + "purpose": "Welche Anforderungen ergeben sich, um den Konsum der API zu gewährleisten?", "howToUse": "Analysieren Sie die aktuellen und zukünftigen Kapazitätsanforderungen für jede API.", "sections": { "currentBusinessVolumes": { @@ -123,8 +123,8 @@ "description": "Welche Rate-Limiting-Strategien können zur Konsumsteuerung eingesetzt werden?" }, "scalingStrategies": { - "section": "Skalierungs-Strategien", - "description": "Welche Skalierungs-Strategien können eingesetzt werden, um das Wachstum zu unterstützen?" + "section": "Strategien zur Skalierung", + "description": "Welche Strategien zur Skalierung können eingesetzt werden, um das Wachstum zu unterstützen?" } } }, @@ -168,7 +168,7 @@ } }, "domainCanvas": { - "title": "Domäne Canvas", + "title": "Domain Canvas", "purpose": "Was sind die wesentlichen Entitäten und Geschäftsregeln im Zusammenhang mit der API?", "howToUse": "Definieren Sie das Domänenmodell für jede API, einschließlich Entitäten, Attribute und Beziehungen.", "sections": { @@ -222,7 +222,7 @@ } }, "interactionCanvas": { - "title": "Interaktion Canvas", + "title": "Interaction Canvas", "purpose": "Welche verschiedenen Interaktionsarten werden von der API unterstützt?", "howToUse": "Definieren Sie die CRUD-, abfrage-, befehlsgesteuerten und eventgesteuerten Interaktionen für jede API.", "sections": { @@ -277,7 +277,7 @@ } }, "locationsCanvas": { - "title": "Standorte Canvas", + "title": "Location Canvas", "purpose": "Was sind die relevanten Standorte und ihre Merkmale?", "howToUse": "Definieren Sie die Standorte, ihre Entfernungen und ihre Endpunkte für jede API.", "sections": { From eb4d7bbdbfe42e51fc1a7ce26629791df0265912 Mon Sep 17 00:00:00 2001 From: Daniel Kocot Date: Sun, 23 Feb 2025 00:13:01 +0100 Subject: [PATCH 3/5] added german descriptions for localizedData --- scripts/canvasCreatorUI.js | 383 ++++++++++++++++++++++++++++++++----- 1 file changed, 335 insertions(+), 48 deletions(-) diff --git a/scripts/canvasCreatorUI.js b/scripts/canvasCreatorUI.js index 8217279..64f3178 100644 --- a/scripts/canvasCreatorUI.js +++ b/scripts/canvasCreatorUI.js @@ -549,57 +549,344 @@ const canvasData = { const localizedData = { "de-DE": { apiBusinessModelCanvas: { - title: "API-Geschäftsmodell Canvas", - purpose: - "Wie praktikabel und wiederverwendbar wird diese API sein? Haben wir einen Business Case aus Kosten-Nutzen-Sicht?", - howToUse: - "Fassen Sie das Wertversprechen einer API aus dem API-Wertversprechen-Canvas zusammen und folgen Sie dann der nummerierten Reihenfolge.", - sections: { - keyPartners: { - section: "Schlüsselpartner", - description: "Wer sind die wichtigsten beteiligten Stakeholder?", - }, - keyActivities: { - section: "Schlüsselaktivitäten", - description: - "Was sind die wichtigsten Maßnahmen, die der API-Anbieter ergreifen muss, um erfolgreich zu arbeiten?", - }, - keyResources: { - section: "Schlüsselressourcen", - description: - "Welche einzigartigen strategischen Vermögenswerte muss der API-Anbieter erwerben oder aufbauen?", - }, - apiValueProposition: { - section: "API-Wertversprechen", - description: "Welchen Wert bietet die API den API-Konsumenten?", - }, - developerRelations: { - section: "Entwicklerbeziehungen", - description: - "Wie erreicht und unterstützt der API-Anbieter API-Konsumenten?", - }, - channels: { - section: "Kanäle", - description: - "Über welche Mechanismen interagieren API-Konsumenten mit der API?", - }, - apiConsumerSegments: { - section: "API-Konsumentensegmente", - description: "Wer sind die Zielgruppen für die API?", - }, - costs: { - section: "Kosten", - description: - "Was sind die wesentlichen Kosten für die Erstellung, Bereitstellung und den Betrieb der API?", - }, - benefits: { - section: "Vorteile", - description: - "Was sind die wesentlichen Vorteile oder Einnahmequellen, die durch die API generiert werden?", - }, + title: "API Business Model Canvas", + purpose: "Wie praktikabel und wiederverwendbar wird diese API sein? Haben wir einen Business Case aus Kosten-Nutzen-Sicht?", + howToUse: "Fassen Sie das Wertversprechen einer API aus dem API Value Proposition Canvas zusammen und folgen Sie dann der nummerierten Reihenfolge.", + sections: { + keyPartners : { + section: "Schlüsselpartner", + description: "Wer sind die wichtigsten beteiligten Stakeholder?" + }, + keyActivities: { + section: "Schlüsselaktivitäten", + description: "Was sind die wichtigsten Maßnahmen, die der API-Anbieter ergreifen muss, um erfolgreich zu arbeiten?" + }, + keyResources: { + section: "Schlüsselressourcen", + description: "Welche einzigartigen strategischen Vermögenswerte muss der API-Anbieter erwerben oder aufbauen?" + }, + apiValueProposition: { + section: "Wertversprechen der API", + description: "Welchen Wert bietet die API den API-Konsumenten?" + }, + developerRelations: { + section: "Entwicklerbeziehungen", + description: "Wie erreicht und unterstützt der API-Anbieter API-Konsumenten?" + }, + channels: { + section: "Kanäle", + description: "Über welche Mechanismen interagieren API-Konsumenten mit der API?" + }, + apiConsumerSegments: { + section: "Konsumenten der API", + description: "Wer sind die Zielgruppen für die API?" + }, + costs: { + section: "Kosten", + description: "Was sind die wesentlichen Kosten für die Erstellung, Bereitstellung und den Betrieb der API?" + }, + benefits: { + section: "Vorteile", + description: "Was sind die wesentlichen Vorteile oder Einnahmequellen, die durch die API generiert werden?" + } + } + }, + apiValuePropositionCanvas: { + title: "API Value Proposition Canvas", + purpose: "Berücksichtigt diese API die Aufgaben, Probleme (Pains) und Bedürfnisse (Gains) der API-Konsumenten?", + howToUse: "Beschreiben Sie die Sichtweise des API-Konsumenten, beginnend mit seinen Aufgaben, dann seine Pains und Gains, und schließlich die API-Produkte und -Features.", + sections: { + tasks: { + section: "Aufgaben", + description: "Was wollen die API-Konsumenten erreichen?" + }, + gainEnablingFeatures: { + section: "Nutzenstiftende Features", + description: "Welche Features ermöglichen es API-Konsumenten ihre Bedürfnisse zu bedienen?" + }, + painRelievingFeatures: { + section: "Problemlösende Features", + description: "Welche Features ermöglichen es API-Konsumenten ihre Probleme zu überwinden?" + }, + apiProducts: { + section: "API-Produkte", + description: "Welche API-Produkte und -Features eigenen sich für diese Aufgaben, Probleme und Bedürfnisse?" + } + } + }, + businessImpactCanvas: { + title: "Business Impact Canvas", + purpose: "Was sind die potenziellen geschäftlichen Auswirkungen eines Ausfalls einer API?", + howToUse: "Berücksichtigen Sie die potenziellen Auswirkungen auf Verfügbarkeit, Sicherheit und Daten für jede API.", + sections: { + availabilityRisks: { + section: "Risiken der Verfügbarkeit", + description: "Was sind die potenziellen Risiken für die API-Verfügbarkeit?" + }, + securityRisks: { + section: "Sicherheitsrisiken", + description: "Welche potenziellen Sicherheitsrisiken sind mit der API assoziiert?" + }, + dataRisks: { + section: "Datenrisiken", + description: "Welche potenziellen Risiken bestehen für die Datenintegrität oder -Vertraulichkeit?" + }, + mitigateAvailabilityRisks: { + section: "Reduzierung von Risiken der Verfügbarkeit", + description: "Wie kann der API-Anbieter die Risiken der Verfügbarkeit reduzieren?" + }, + mitigateSecurityRisks: { + section: "Reduktion der Sicherheitsrisiken", + description: "Wie kann der API-Anbieter die Sicherheitsrisiken reduzieren?" + }, + mitigateDataRisks: { + section: "Reduktion der Datenrisiken", + description: "Wie kann der API-Anbieter die Datenrisiken reduzieren?" + } + } + }, + capacityCanvas: { + title: "Capacity Canvas", + purpose: "Welche Anforderungen ergeben sich, um den Konsum der API zu gewährleisten?", + howToUse: "Analysieren Sie die aktuellen und zukünftigen Kapazitätsanforderungen für jede API.", + sections: { + currentBusinessVolumes: { + section: "Aktuelles Geschäftsvolumen", + description: "Wie hoch sind das aktuelle Geschäftsvolumen und die Transaktionsraten?" + }, + futureConsumptionTrends: { + section: "Zukünftige Konsumtrends", + description: "Was sind die erwarteten künftigen Konsumtrends?" + }, + peakLoadAndAvailabilityRequirements: { + section: "Spitzenlast- und Verfügbarkeitsanforderungen", + description: "Was sind die Spitzenlast- und Verfügbarkeitsanforderungen?" + }, + cachingStrategies: { + section: "Caching-Strategien", + description: "Welche Caching-Strategien können zur Performanceoptimierung eingesetzt werden?" + }, + rateLimitingStrategies: { + section: "Rate-Limiting-Strategien", + description: "Welche Rate-Limiting-Strategien können zur Konsumsteuerung eingesetzt werden?" + }, + scalingStrategies: { + section: "Strategien zur Skalierung", + description: "Welche Strategien zur Skalierung können eingesetzt werden, um das Wachstum zu unterstützen?" + } + } + }, + customerJourneyCanvas: { + title: "Customer Journey Canvas", + purpose: "Wie interagieren die API-Konsumenten im Laufe der Zeit mit der API?", + howToUse: "Erfassen Sie das Customer Journey für jede API, von der ersten Entdeckung bis zur aktuellen Nutzung.", + sections: { + customerDiscoversNeed: { + section: "Kunde erkennt Bedarf", + description: "Wie erkennt der Kunde den Bedarf an der API?" + }, + persona: { + section: "Persona", + description: "Wie sieht der typische Kunde oder Nutzer der API aus?" + }, + pains: { + section: "Probleme", + description: "Was sind die Probleme oder Herausforderungen des Kunden?" + }, + journeySteps: { + section: "Customer Journey Schritte", + description: "Welche Schritte durchläuft der Kunde bei der Nutzung der API?" + }, + customerNeedIsResolved: { + section: "Kundenbedürfnis wird gelöst", + description: "Wie wird das Bedürfnis des Kunden letztendlich gelöst?" + }, + gains: { + section: "Nutzen", + description: "Welchen Gewinn oder Nutzen hat der Kunde?" + }, + inputsOutputs: { + section: "Inputs & Outputs", + description: "Was sind die Inputs und Outputs bei jedem Schritt?" + }, + interactionProcessingRules: { + section: "Interaktions- und Verarbeitungsregeln", + description: "Wie lauten die Interaktions- und Verarbeitungsregeln bei jedem Schritt?" + } + } + }, + domainCanvas: { + title: "Domain Canvas", + purpose: "Was sind die wesentlichen Entitäten und Geschäftsregeln im Zusammenhang mit der API?", + howToUse: "Definieren Sie das Domänenmodell für jede API, einschließlich Entitäten, Attribute und Beziehungen.", + sections: { + selectedCustomerJourneySteps: { + section: "Ausgewählte Customer Journey Schritte", + description: "Welche Customer Journey Schritte sind für diese Domäne relevant?" + }, + coreEntitiesAndBusinessMeaning: { + section: "Grundlegende Entitäten & geschäftliche Bedeutung", + description: "Welches sind die wesentlichen Entitäten und ihre Bedeutung für das Geschäft?" + }, + attributesAndBusinessImportance: { + section: "Attribute & geschäftliche Wichtigkeit", + description: "Welches sind die Schlüsselattribute der einzelnen Entitäten und ihre geschäftliche Wichtigkeit?" + }, + relationshipsBetweenEntities: { + section: "Beziehungen zwischen Entitäten", + description: "Welche Beziehungen bestehen zwischen den Entitäten?" + }, + businessComplianceAndIntegrityRules: { + section: "Geschäfts-, Compliance- und Integritätsregeln", + description: "Welche Geschäfts-, Compliance- und Integritätsregeln gelten für die Entitäten?" + }, + securityAndPrivacyConsiderations: { + section: "Überlegungen zu Sicherheit und Datenschutz", + description: "Welche Überlegungen zur Sicherheit und zum Datenschutz gibt es im Zusammenhang mit den Entitäten?" + } + } + }, + eventCanvas: { + title: "Event Canvas", + purpose: "Welche Events sind für die API relevant, und wie werden sie verarbeitet?", + howToUse: "Definieren Sie die Events, ihre Trigger und die Verarbeitungslogik für jede API.", + sections: { + userTaskTrigger: { + section: "Nutzeraufgabe / Trigger", + description: "Welche Nutzeraktion oder welches System-Event löst diese Eventoperation aus?" + }, + inputEventPayload: { + section: "Input / Event-Payload", + description: "Welche Daten sind in der eingehenden Event-Payload enthalten? Geben Sie die Schlüsselattribute an." + }, + processingLogic: { + section: "Verarbeitung / Logik", + description: "Beschreiben Sie die Backend-Verarbeitungslogik, inklusive Validierungen, Transformationen, oder Routing-Entscheidungen." + }, + outputEventResult: { + section: "Output / Event-Ergebnis", + description: "Welches Event oder welche Bestätigungsmeldung wird erzeugt? Geben Sie die Attribute des Output-Payloads an." + } + } + }, + interactionCanvas: { + title: "Interaction Canvas", + purpose: "Welche verschiedenen Interaktionsarten werden von der API unterstützt?", + howToUse: "Definieren Sie die CRUD-, abfrage-, befehlsgesteuerten und eventgesteuerten Interaktionen für jede API.", + sections: { + crudInteractions: { + section: "CRUD Interaktionen", + description: "Welche CRUD-Interaktionen (Create, Read, Update, Delete) werden von der API unterstützt?" + }, + crudInputOutputModels: { + section: "CRUD Input- & Output-Modelle", + description: "Was sind die Input- und Output-Modelle für die CRUD-Interaktionen?" + }, + crudProcessingValidation: { + section: "CRUD Verarbeitung & Validierung", + description: "Wie sehen die Verarbeitungs- und Validierungsregeln für die CRUD-Interaktionen aus?" + }, + queryDrivenInteractions: { + section: "Abfragegesteuerte Interaktionen", + description: "Welche abfragegesteuerten Interaktionen werden von der API unterstützt?" + }, + queryDrivenInputOutputModels: { + section: "Abfragegesteuerte Input- & Output-Modelle", + description: "Was sind die Input- und Output-Modelle für die abfragegesteuerten Interaktionen" + }, + queryDrivenProcessingValidation: { + section: "Abfragegesteuerte Verarbeitung & Validierung", + description: "Wie sehen die Verarbeitungs- und Validierungsregeln für die abfragegesteuerten Interaktionen aus?" + }, + commandDrivenInteractions: { + section: "Befehlsgesteuerte Interaktionen", + description: "Welche befehlsgesteuerten Interaktionen werden von der API unterstützt?" + }, + commandDrivenInputOutputModels: { + section: "Befehlsgesteuerte Input- & Output-Modelle", + description: "Was sind die Input- und Output-Modelle für die befehlsgesteuerten Interaktionen?" + }, + commandDrivenProcessingValidation: { + section: "Befehlsgesteuerte Verarbeitung & Validierung", + description: "Wie sehen die Verarbeitungs- und Validierungsregeln für die befehlsgesteuerten Interaktionen aus?" + }, + eventDrivenInteractions: { + section: "Eventgesteuerte Interaktionen", + description: "Welche eventgesteuerten Interaktionen werden von der API unterstützt?" + }, + eventDrivenInputOutputModels: { + section: "Eventgesteuerte Input- & Output-Modelle", + description: "Was sind die Input- und Output-Modelle für die eventgesteuerten Interaktionen?" + }, + eventDrivenProcessingValidation: { + section: "Eventgesteuerte Verarbeitung & Validierung", + description: "Wie sehen die Verarbeitungs- und Validierungsregeln für die eventgesteuerten Interaktionen aus?" + } + } + }, + locationsCanvas: { + title: "Location Canvas", + purpose: "Was sind die relevanten Standorte und ihre Merkmale?", + howToUse: "Definieren Sie die Standorte, ihre Entfernungen und ihre Endpunkte für jede API.", + sections: { + locationGroups: { + section: "Standortgruppen", + description: "Welches sind die relevanten Standortgruppen?" + }, + locationGroupCharacteristics: { + section: "Standortgruppenmerkmale", + description: "Was sind die Merkmale der Standortgruppen?" + }, + locations: { + section: "Standorte", + description: "Welches sind die relevanten Standorte innerhalb jeder Gruppe?" + }, + locationCharacteristics: { + section: "Standortmerkmale", + description: "Was sind die Merkmale der Standorte?" + }, + locationDistances: { + section: "Standortentfernungen", + description: "Wie groß sind die Entfernungen zwischen den Standorten?" + }, + locationDistanceCharacteristics: { + section: "Standort-Entfernungsmerkmale", + description: "Was sind die Merkmale der Standortentfernungen?" + }, + locationEndpoints: { + section: "Standort-Endpunkte", + description: "Welche Endpunkte sind mit den Standorten assoziiert?" + }, + locationEndpointCharacteristics: { + section: "Standort-Endpunktemerkmale", + description: "Was sind die Merkmale der Standort-Endpunkte?" + } + } + }, + restCanvas: { + title: "REST Canvas", + purpose: "Wie kann die API nach RESTful-Prinzipien gestaltet werden?", + howToUse: "Definieren Sie die API-Ressourcen, HTTP-Methoden und Beispielanfragen und -antworten.", + sections: { + apiResources: { + section: "API-Ressourcen", + description: "Was sind die Schlüsselressourcen, die von der API bereitgestellt werden?" + }, + apiResourceModel: { + section: "API-Ressourcenmodell", + description: "Wie sieht die Struktur des API-Ressourcenmodells aus?" + }, + apiVerbs: { + "section": "HTTP-Methoden der API", + "description": "Welche HTTP-Methoden werden für die Interaktion mit den API-Ressourcen verwendet?" + }, + apiVerbExample: { + section: "HTTP-Methoden-Beispiel", + description: "Geben Sie für jede HTTP-Methode ein Beispiel für eine API-Anfrage und -Antwort an." }, }, }, + }, "en-US": { apiBusinessModelCanvas: { title: "API Business Model Canvas", From a446f74a3deb0f995e853a7a71997f9ad5103536 Mon Sep 17 00:00:00 2001 From: Daniel Kocot Date: Sun, 23 Feb 2025 00:20:27 +0100 Subject: [PATCH 4/5] remove v1.5 with v1.6 --- canvasCreatorUI.v1_5.min.js | 2 +- canvasCreatorUI.v1_6.min.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 canvasCreatorUI.v1_6.min.js diff --git a/canvasCreatorUI.v1_5.min.js b/canvasCreatorUI.v1_5.min.js index 957376c..920c19b 100644 --- a/canvasCreatorUI.v1_5.min.js +++ b/canvasCreatorUI.v1_5.min.js @@ -1 +1 @@ -const canvasData={apiBusinessModelCanvas:{id:"apiBusinessModelCanvas",layout:{columns:5,rows:3},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Alexander Osterwalder","Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"keyPartners",gridPosition:{column:0,row:0,colSpan:1,rowSpan:2},fillOrder:7},{id:"keyActivities",gridPosition:{column:1,row:0,colSpan:1,rowSpan:1},fillOrder:6},{id:"keyResources",gridPosition:{column:1,row:1,colSpan:1,rowSpan:1},fillOrder:5},{id:"apiValueProposition",gridPosition:{column:2,row:0,colSpan:1,rowSpan:2},fillOrder:1,highlight:!0},{id:"developerRelations",gridPosition:{column:3,row:0,colSpan:1,rowSpan:1},fillOrder:3},{id:"channels",gridPosition:{column:3,row:1,colSpan:1,rowSpan:1},fillOrder:4},{id:"apiConsumerSegments",gridPosition:{column:4,row:0,colSpan:1,rowSpan:2},fillOrder:2},{id:"costs",gridPosition:{column:0,row:2,colSpan:2.5,rowSpan:1},fillOrder:9},{id:"benefits",gridPosition:{column:2.5,row:2,colSpan:2.5,rowSpan:1},fillOrder:8}]},apiValuePropositionCanvas:{id:"apiValuePropositionCanvas",layout:{columns:4,rows:3},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Alexander Osterwalder","Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"tasks",gridPosition:{column:0,row:0,colSpan:4,rowSpan:1},fillOrder:1,highlight:!0,journeySteps:!0},{id:"gainEnablingFeatures",gridPosition:{column:0,row:1,colSpan:2,rowSpan:1},fillOrder:2},{id:"painRelievingFeatures",gridPosition:{column:2,row:1,colSpan:2,rowSpan:1},fillOrder:3},{id:"apiProducts",gridPosition:{column:0,row:2,colSpan:4,rowSpan:1},fillOrder:4}]},businessImpactCanvas:{id:"businessImpactCanvas",layout:{columns:3,rows:2},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"availabilityRisks",gridPosition:{column:0,row:0,colSpan:1,rowSpan:1},fillOrder:1,highlight:!0},{id:"securityRisks",gridPosition:{column:1,row:0,colSpan:1,rowSpan:1},fillOrder:3,highlight:!0},{id:"dataRisks",gridPosition:{column:2,row:0,colSpan:1,rowSpan:1},fillOrder:5,highlight:!0},{id:"mitigateAvailabilityRisks",gridPosition:{column:0,row:1,colSpan:1,rowSpan:1},fillOrder:2},{id:"mitigateSecurityRisks",gridPosition:{column:1,row:1,colSpan:1,rowSpan:1},fillOrder:4},{id:"mitigateDataRisks",gridPosition:{column:2,row:1,colSpan:1,rowSpan:1},fillOrder:6}]},capacityCanvas:{id:"capacityCanvas",layout:{columns:3,rows:3},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"currentBusinessVolumes",gridPosition:{column:0,row:0,colSpan:1,rowSpan:1},fillOrder:1,highlight:!0},{id:"futureConsumptionTrends",gridPosition:{column:1,row:0,colSpan:2,rowSpan:1},fillOrder:2},{id:"peakLoadAndAvailabilityRequirements",gridPosition:{column:0,row:1,colSpan:3,rowSpan:1},fillOrder:3},{id:"cachingStrategies",gridPosition:{column:0,row:2,colSpan:1,rowSpan:1},fillOrder:4},{id:"rateLimitingStrategies",gridPosition:{column:1,row:2,colSpan:1,rowSpan:1},fillOrder:5},{id:"scalingStrategies",gridPosition:{column:2,row:2,colSpan:1,rowSpan:1},fillOrder:6}]},customerJourneyCanvas:{id:"customerJourneyCanvas",layout:{columns:5,rows:4},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"customerDiscoversNeed",gridPosition:{column:0,row:0,colSpan:1,rowSpan:1},fillOrder:2},{id:"persona",gridPosition:{column:1,row:0,colSpan:3,rowSpan:1},fillOrder:1,highlight:!0},{id:"pains",gridPosition:{column:0,row:1,colSpan:1,rowSpan:2},fillOrder:5},{id:"journeySteps",gridPosition:{column:1,row:1,colSpan:3,rowSpan:2},fillOrder:4,journeySteps:!0},{id:"customerNeedIsResolved",gridPosition:{column:4,row:0,colSpan:1,rowSpan:1},fillOrder:3},{id:"gains",gridPosition:{column:4,row:1,colSpan:1,rowSpan:2},fillOrder:6},{id:"inputsOutputs",gridPosition:{column:.5,row:3,colSpan:2,rowSpan:1},fillOrder:7},{id:"interactionProcessingRules",gridPosition:{column:2.5,row:3,colSpan:2,rowSpan:1},fillOrder:8}]},domainCanvas:{id:"domainCanvas",layout:{columns:2,rows:4},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"selectedCustomerJourneySteps",gridPosition:{column:0,row:0,colSpan:2,rowSpan:1},fillOrder:1,highlight:!0,journeySteps:!0},{id:"coreEntitiesAndBusinessMeaning",gridPosition:{column:0,row:1,colSpan:1,rowSpan:1},fillOrder:2},{id:"attributesAndBusinessImportance",gridPosition:{column:1,row:1,colSpan:1,rowSpan:2},fillOrder:3},{id:"relationshipsBetweenEntities",gridPosition:{column:0,row:2,colSpan:1,rowSpan:1},fillOrder:4},{id:"businessComplianceAndIntegrityRules",gridPosition:{column:0,row:3,colSpan:1,rowSpan:1},fillOrder:5},{id:"securityAndPrivacyConsiderations",gridPosition:{column:1,row:3,colSpan:1,rowSpan:1},fillOrder:6}]},eventCanvas:{id:"eventCanvas",layout:{columns:4,rows:3},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"userTaskTrigger",gridPosition:{column:0,row:0,colSpan:1,rowSpan:1},fillOrder:1,highlight:!0},{id:"inputEventPayload",gridPosition:{column:0,row:1,colSpan:1,rowSpan:2},fillOrder:2},{id:"processingLogic",gridPosition:{column:1,row:1,colSpan:2,rowSpan:2},fillOrder:3},{id:"outputEventResult",gridPosition:{column:3,row:1,colSpan:1,rowSpan:2},fillOrder:4}]},interactionCanvas:{id:"interactionCanvas",layout:{columns:4,rows:3},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"crudInteractions",gridPosition:{column:0,row:0,colSpan:1,rowSpan:1},fillOrder:1,highlight:!0},{id:"crudInputOutputModels",gridPosition:{column:0,row:1,colSpan:1,rowSpan:1},fillOrder:2},{id:"crudProcessingValidation",gridPosition:{column:0,row:2,colSpan:1,rowSpan:1},fillOrder:3},{id:"queryDrivenInteractions",gridPosition:{column:1,row:0,colSpan:1,rowSpan:1},fillOrder:4,highlight:!0},{id:"queryDrivenInputOutputModels",gridPosition:{column:1,row:1,colSpan:1,rowSpan:1},fillOrder:5},{id:"queryDrivenProcessingValidation",gridPosition:{column:1,row:2,colSpan:1,rowSpan:1},fillOrder:6},{id:"commandDrivenInteractions",gridPosition:{column:2,row:0,colSpan:1,rowSpan:1},fillOrder:7,highlight:!0},{id:"commandDrivenInputOutputModels",gridPosition:{column:2,row:1,colSpan:1,rowSpan:1},fillOrder:8},{id:"commandDrivenProcessingValidation",gridPosition:{column:2,row:2,colSpan:1,rowSpan:1},fillOrder:9},{id:"eventDrivenInteractions",gridPosition:{column:3,row:0,colSpan:1,rowSpan:1},fillOrder:10,highlight:!0},{id:"eventDrivenInputOutputModels",gridPosition:{column:3,row:1,colSpan:1,rowSpan:1},fillOrder:11},{id:"eventDrivenProcessingValidation",gridPosition:{column:3,row:2,colSpan:1,rowSpan:1},fillOrder:12}]},locationsCanvas:{id:"locationsCanvas",layout:{columns:4,rows:2},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"locationGroups",gridPosition:{column:0,row:0,colSpan:1,rowSpan:1},fillOrder:1,highlight:!0},{id:"locationGroupCharacteristics",gridPosition:{column:0,row:1,colSpan:1,rowSpan:1},fillOrder:2},{id:"locations",gridPosition:{column:1,row:0,colSpan:1,rowSpan:1},fillOrder:3,highlight:!0},{id:"locationCharacteristics",gridPosition:{column:1,row:1,colSpan:1,rowSpan:1},fillOrder:4},{id:"locationDistances",gridPosition:{column:2,row:0,colSpan:1,rowSpan:1},fillOrder:5},{id:"locationDistanceCharacteristics",gridPosition:{column:2,row:1,colSpan:1,rowSpan:1},fillOrder:6},{id:"locationEndpoints",gridPosition:{column:3,row:0,colSpan:1,rowSpan:1},fillOrder:7},{id:"locationEndpointCharacteristics",gridPosition:{column:3,row:1,colSpan:1,rowSpan:1},fillOrder:8}]},restCanvas:{id:"restCanvas",layout:{columns:4,rows:3},metadata:{source:"APIOps Cycles",license:"CC-BY-SA 4.0",authors:["Osaango Ltd"],website:"www.apiopscycles.com"},sections:[{id:"apiResources",gridPosition:{column:0,row:0,colSpan:1,rowSpan:1},fillOrder:1,highlight:!0},{id:"apiResourceModel",gridPosition:{column:0,row:1,colSpan:1,rowSpan:2},fillOrder:2},{id:"apiVerbs",gridPosition:{column:1,row:0,colSpan:1,rowSpan:1},fillOrder:3,highlight:!0},{id:"apiVerbExample",gridPosition:{column:1,row:1,colSpan:3,rowSpan:2},fillOrder:4}]}},localizedData={"de-DE":{apiBusinessModelCanvas:{title:"API-Geschäftsmodell Canvas",purpose:"Wie praktikabel und wiederverwendbar wird diese API sein? Haben wir einen Business Case aus Kosten-Nutzen-Sicht?",howToUse:"Fassen Sie das Wertversprechen einer API aus dem API-Wertversprechen-Canvas zusammen und folgen Sie dann der nummerierten Reihenfolge.",sections:{keyPartners:{section:"Schlüsselpartner",description:"Wer sind die wichtigsten beteiligten Stakeholder?"},keyActivities:{section:"Schlüsselaktivitäten",description:"Was sind die wichtigsten Maßnahmen, die der API-Anbieter ergreifen muss, um erfolgreich zu arbeiten?"},keyResources:{section:"Schlüsselressourcen",description:"Welche einzigartigen strategischen Vermögenswerte muss der API-Anbieter erwerben oder aufbauen?"},apiValueProposition:{section:"API-Wertversprechen",description:"Welchen Wert bietet die API den API-Konsumenten?"},developerRelations:{section:"Entwicklerbeziehungen",description:"Wie erreicht und unterstützt der API-Anbieter API-Konsumenten?"},channels:{section:"Kanäle",description:"Über welche Mechanismen interagieren API-Konsumenten mit der API?"},apiConsumerSegments:{section:"API-Konsumentensegmente",description:"Wer sind die Zielgruppen für die API?"},costs:{section:"Kosten",description:"Was sind die wesentlichen Kosten für die Erstellung, Bereitstellung und den Betrieb der API?"},benefits:{section:"Vorteile",description:"Was sind die wesentlichen Vorteile oder Einnahmequellen, die durch die API generiert werden?"}}}},"en-US":{apiBusinessModelCanvas:{title:"API Business Model Canvas",purpose:"How feasible and reusable will this API be? Do we have a business case from a cost - benefit point of view?",howToUse:"Summarize the value proposition of one API from the API Value Proposition Canvas, then follow the numbered sequence.",sections:{keyPartners:{section:"Key Partners",description:"Who are the key stakeholders involved?"},keyActivities:{section:"Key Activities",description:"What are the most important actions the API provider must take to operate successfully?"},keyResources:{section:"Key Resources",description:"What unique strategic assets must the API provider acquire or build?"},apiValueProposition:{section:"API Value Proposition",description:"What value does the API offer to API consumers?"},developerRelations:{section:"Developer Relations",description:"How does the API provider reach and support API consumers?"},channels:{section:"Channels",description:"Through which mechanisms do API consumers interact with the API?"},apiConsumerSegments:{section:"API Consumer Segments",description:"Who are the target audiences for the API?"},costs:{section:"Costs",description:"What are the significant costs involved in building, deploying, and operating the API?"},benefits:{section:"Benefits",description:"What are the significant benefits or revenue streams generated by the API?"}}},apiValuePropositionCanvas:{title:"API Value Proposition Canvas",purpose:"Does this API address the jobs, pains, and gains of API consumers?",howToUse:"Describe the API consumer's perspective, starting with their tasks, then their pains and gains, and finally the API's products and features.",sections:{tasks:{section:"Tasks",description:"What are the API consumers trying to achieve?"},gainEnablingFeatures:{section:"Gain Enabling Features",description:"What features enable API consumers to achieve gains?"},painRelievingFeatures:{section:"Pain Relieving Features",description:"What features help API consumers overcome pains?"},apiProducts:{section:"API Products",description:"What API products and features address the tasks, pains, and gains?"}}},businessImpactCanvas:{title:"Business Impact Canvas",purpose:"What are the potential business impacts of API failure?",howToUse:"Consider the potential impact on availability, security, and data for each API.",sections:{availabilityRisks:{section:"Availability Risks",description:"What are the potential risks to API availability?"},securityRisks:{section:"Security Risks",description:"What are the potential security risks associated with the API?"},dataRisks:{section:"Data Risks",description:"What are the potential risks to data integrity or confidentiality?"},mitigateAvailabilityRisks:{section:"Mitigate Availability Risks",description:"How can the API provider mitigate the availability risks?"},mitigateSecurityRisks:{section:"Mitigate Security Risks",description:"How can the API provider mitigate the security risks?"},mitigateDataRisks:{section:"Mitigate Data Risks",description:"How can the API provider mitigate the data risks?"}}},capacityCanvas:{title:"Capacity Canvas",purpose:"How much capacity is needed to support API consumption?",howToUse:"Analyze the current and future capacity requirements for each API.",sections:{currentBusinessVolumes:{section:"Current Business Volumes",description:"What are the current business volumes and transaction rates?"},futureConsumptionTrends:{section:"Future Consumption Trends",description:"What are the anticipated future consumption trends?"},peakLoadAndAvailabilityRequirements:{section:"Peak Load and Availability Requirements",description:"What are the peak load and availability requirements?"},cachingStrategies:{section:"Caching Strategies",description:"What caching strategies can be used to optimize performance?"},rateLimitingStrategies:{section:"Rate Limiting Strategies",description:"What rate limiting strategies can be used to manage consumption?"},scalingStrategies:{section:"Scaling Strategies",description:"What scaling strategies can be used to accommodate growth?"}}},customerJourneyCanvas:{title:"Customer Journey Canvas",purpose:"How do API consumers interact with the API over time?",howToUse:"Map the customer journey for each API, from initial discovery to ongoing use.",sections:{customerDiscoversNeed:{section:"Customer Discovers Need",description:"How does the customer discover the need for the API?"},persona:{section:"Persona",description:"Who is the typical customer or user of the API?"},pains:{section:"Pains",description:"What are the customer's pain points or challenges?"},journeySteps:{section:"Journey Steps",description:"What are the steps the customer takes in their journey?"},customerNeedIsResolved:{section:"Customer Need Is Resolved",description:"How is the customer's need ultimately resolved?"},gains:{section:"Gains",description:"What are the customer's gains or benefits?"},inputsOutputs:{section:"Inputs & Outputs",description:"What are the inputs and outputs at each step?"},interactionProcessingRules:{section:"Interaction & Processing Rules",description:"What are the interaction and processing rules at each step?"}}},domainCanvas:{title:"Domain Canvas",purpose:"What are the core entities and business rules related to the API?",howToUse:"Define the domain model for each API, including entities, attributes, and relationships.",sections:{selectedCustomerJourneySteps:{section:"Selected Customer Journey Steps",description:"Which customer journey steps are relevant to this domain?"},coreEntitiesAndBusinessMeaning:{section:"Core Entities & Business Meaning",description:"What are the core entities and their business meaning?"},attributesAndBusinessImportance:{section:"Attributes & Business Importance",description:"What are the key attributes of each entity and their business importance?"},relationshipsBetweenEntities:{section:"Relationships Between Entities",description:"What are the relationships between the entities?"},businessComplianceAndIntegrityRules:{section:"Business, Compliance & Integrity Rules",description:"What are the business, compliance, and integrity rules related to the entities?"},securityAndPrivacyConsiderations:{section:"Security & Privacy Considerations",description:"What are the security and privacy considerations related to the entities?"}}},eventCanvas:{title:"Event Canvas",purpose:"What events are relevant to the API, and how are they processed?",howToUse:"Define the events, their triggers, and the processing logic for each API.",sections:{userTaskTrigger:{section:"User Task / Trigger",description:"What user action or system event triggers this event operation?"},inputEventPayload:{section:"Input / Event Payload",description:"What data is included in the incoming event payload? Specify key attributes."},processingLogic:{section:"Processing / Logic",description:"Describe the backend processing logic, including validations, transformations, or routing decisions."},outputEventResult:{section:"Output / Event Result",description:"What resulting event or acknowledgment is produced? Include attributes of the output payload."}}},interactionCanvas:{title:"Interaction Canvas",purpose:"What are the different types of interactions supported by the API?",howToUse:"Define the CRUD, query-driven, command-driven, and event-driven interactions for each API.",sections:{crudInteractions:{section:"CRUD Interactions",description:"What are the CRUD (Create, Read, Update, Delete) interactions supported by the API?"},crudInputOutputModels:{section:"CRUD Input & Output Models",description:"What are the input and output models for the CRUD interactions?"},crudProcessingValidation:{section:"CRUD Processing & Validation",description:"What are the processing and validation rules for the CRUD interactions?"},queryDrivenInteractions:{section:"Query-Driven Interactions",description:"What are the query-driven interactions supported by the API?"},queryDrivenInputOutputModels:{section:"Query-Driven Input & Output Models",description:"What are the input and output models for the query-driven interactions?"},queryDrivenProcessingValidation:{section:"Query-Driven Processing & Validation",description:"What are the processing and validation rules for the query-driven interactions?"},commandDrivenInteractions:{section:"Command-Driven Interactions",description:"What are the command-driven interactions supported by the API?"},commandDrivenInputOutputModels:{section:"Command-Driven Input & Output Models",description:"What are the input and output models for the command-driven interactions?"},commandDrivenProcessingValidation:{section:"Command-Driven Processing & Validation",description:"What are the processing and validation rules for the command-driven interactions?"},eventDrivenInteractions:{section:"Event-Driven Interactions",description:"What are the event-driven interactions supported by the API?"},eventDrivenInputOutputModels:{section:"Event-Driven Input & Output Models",description:"What are the input and output models for the event-driven interactions?"},eventDrivenProcessingValidation:{section:"Event-Driven Processing & Validation",description:"What are the processing and validation rules for the event-driven interactions?"}}},locationsCanvas:{title:"Locations Canvas",purpose:"What are the relevant locations and their characteristics?",howToUse:"Define the locations, their distances, and their endpoints for each API.",sections:{locationGroups:{section:"Location Groups",description:"What are the relevant location groups?"},locationGroupCharacteristics:{section:"Location Group Characteristics",description:"What are the characteristics of the location groups?"},locations:{section:"Locations",description:"What are the relevant locations within each group?"},locationCharacteristics:{section:"Location Characteristics",description:"What are the characteristics of the locations?"},locationDistances:{section:"Location Distances",description:"What are the distances between the locations?"},locationDistanceCharacteristics:{section:"Location Distance Characteristics",description:"What are the characteristics of the location distances?"},locationEndpoints:{section:"Location Endpoints",description:"What are the endpoints associated with the locations?"},locationEndpointCharacteristics:{section:"Location Endpoint Characteristics",description:"What are the characteristics of the location endpoints?"}}},restCanvas:{title:"REST Canvas",purpose:"How can the API be designed using RESTful principles?",howToUse:"Define the API resources, verbs, and example requests and responses.",sections:{apiResources:{section:"API Resources",description:"What are the key resources exposed by the API?"},apiResourceModel:{section:"API Resource Model",description:"What is the structure of the API resource model?"},apiVerbs:{section:"API Verbs",description:"What HTTP verbs are used to interact with the API resources?"},apiVerbExample:{section:"API Verb Example",description:"Provide an example of an API request and response for each verb."}}}}};let currentColor=defaultStyles.stickyNoteColor,selectedNote=null;function loadCanvasData(e){return canvasData[e]}function populateLocaleSelector(){const i=document.getElementById("locale");var e=Object.keys(localizedData),t=document.createElement("option");t.value="",t.text="Select Locale",i.add(t),e.forEach(e=>{var t=document.createElement("option");t.value=e,t.text=e,i.add(t)})}function populateCanvasSelector(i){const o=document.getElementById("canvas");o.innerHTML="",Object.keys(localizedData[i]).forEach(e=>{var t=document.createElement("option");t.value=e,t.text=localizedData[i][e].title,o.add(t)})}document.getElementById("locale").addEventListener("change",e=>{e=e.target.value,document.getElementById("canvasSelector").style.display="block",populateCanvasSelector(e),e=document.getElementById("canvas").value;e&&(document.getElementById("canvasCreator").style.display="flex")},{once:!0}),document.querySelectorAll(".canvas-tools").forEach(e=>{e.addEventListener("touchstart",function(e){e.preventDefault(),this.click()},{passive:!1})}),document.getElementById("canvas").addEventListener("change",e=>{loadCanvas(document.getElementById("locale").value,e.target.value)},{once:!0});let canvasDataForId=null,contentData={};function loadCanvas(e,t){if(!(canvasDataForId=canvasData[t]))return void console.error("Canvas data not found for canvasId: "+t);contentData={templateId:t,locale:e,metadata:{source:"",license:"",authors:[],website:""},sections:canvasDataForId.sections?canvasDataForId.sections.map(e=>({sectionId:e.id,stickyNotes:[]})):[]};let f=d3.select("svg");const r=s=>{f.selectAll(".sticky-note").remove(),s&&s.sections&&(s.sections.forEach(i=>{var e=s.templateId;const o=canvasData[e].sections.find(e=>e.id===i.sectionId);i.stickyNotes&&0`sticky-note-${i.sectionId}-`+t).attr("transform",e=>{var t=(e.position.y||0)+0*(o.gridPosition.row+1);return`translate(${e.position.x||0},${t})`})).on("click touchstart",function(e,t){e.stopPropagation(),e.preventDefault(),selectedNote=t}),e.append("rect").attr("x",0).attr("y",0).attr("width",defaultStyles.stickyNoteSize).attr("height",defaultStyles.stickyNoteSize).attr("fill",e=>e.color||defaultStyles.stickyNoteColor).attr("stroke",defaultStyles.stickyNoteBorderColor).attr("rx",3).attr("ry",3),e.append("text").attr("x",5).attr("y",15).attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+"px").attr("fill",defaultStyles.contentFontColor).each(function(e){e.content=a(f,e.content);var t=e.content.split("\n");for(let e=0;e{i.node().focus()},0),i.on("focus",function(){this.value=t.content.replace(/\n{2,}/g,"\n")}).on("blur",function(e,t){var i;i=validateInput(sanitizeInput(this.value)),t.content=a(f,i),o.select("text").selectAll("tspan").remove(),d3.select(this.parentNode).remove(),r(s)})}))}),f.selectAll(".sticky-note").call(d3.drag().on("start",function(e,t){d3.select(this).attr("originalPosition",{x:t.position.x,y:t.position.y})}).on("drag",function(e,t){t.position.x=e.x,t.position.y=e.y,d3.select(this).attr("transform",`translate(${t.position.x},${t.position.y})`)}).on("end",function(e,t){})),f.on("contextmenu",function(e){e.preventDefault();var t=e.offsetX,i=e.offsetY;let o=null;for(let e=0;e=a.position.x&&t<=a.position.x+defaultStyles.stickyNoteSize&&i>=a.position.y&&i<=a.position.y+defaultStyles.stickyNoteSize){o=a;break}}if(o)break}o&&confirm("Are you sure you want to delete this sticky note?")&&((e=s.sections.find(e=>e.stickyNotes.includes(o))).stickyNotes=e.stickyNotes.filter(e=>e!==o),r(s))}))};function a(n,e){e=e.replace(/\n{2,}/g,"\n").split(" ");let a="";const s=[];return e.forEach(e=>{var t=a+e+" ",i=n.append("text").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+"px").text(t),o=i.node().getComputedTextLength();i.remove(),a=o>defaultStyles.maxLineWidth?(s.push(a),e+" "):t}),s.push(a),s.join("\n")}{var s=canvasDataForId,l=contentData;t=localizedData,d3.select("svg").remove();const y=Math.floor((defaultStyles.width-s.layout.columns*defaultStyles.padding)/s.layout.columns),S=Math.floor((defaultStyles.height-defaultStyles.headerHeight-defaultStyles.footerHeight-4*defaultStyles.padding)/s.layout.rows),d=l.locale||defaultStyles.defaultLocale,v=(e=l.templateId,t[d][e]);function n(){f.selectAll("text.footer").remove(),f.append("text").attr("class","footer").attr("x",defaultStyles.width/2).attr("y",defaultStyles.height-defaultStyles.footerHeight-2*defaultStyles.padding).attr("text-anchor","middle").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize).attr("fill",defaultStyles.fontColor).html(`Content by: ${l?.metadata?.source} | ${l?.metadata?.license} | ${l?.metadata?.authors} | ${l?.metadata?.website}`)}0===Object.keys(l).length&&(l.templateId=s.id,l.locale=d,l.metadata={source:"",license:"",authors:[],website:""},l.sections=s.sections.map(e=>({sectionId:e.id,stickyNotes:[]}))),(async(e,t,i=0,o,n=defaultStyles.headerHeight+2*defaultStyles.padding,a=defaultStyles.headerHeight+2*defaultStyles.padding)=>{try{var s=await fetch(e);if(!s.ok)throw new Error("Failed to fetch the logo SVG");var r=await s.text();t.append("g").attr("transform",`translate(${i}, ${o}) scale(${n/100}, ${a/100})`).html(r)}catch(e){}})("/img/apiops-cycles-logo2025-blue.svg",f=d3.select("#canvasCreator").append("svg").attr("width",defaultStyles.width+2*defaultStyles.padding).attr("height",defaultStyles.height).style("background-color",defaultStyles.backgroundColor),defaultStyles.padding,defaultStyles.padding/2,defaultStyles.padding,defaultStyles.padding),f.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",2*defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+4+"px").attr("font-weight","bold").attr("fill",defaultStyles.fontColor).text(v.title),f.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",defaultStyles.headerHeight-3*defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+2+"px").attr("fill",defaultStyles.fontColor).text(v.purpose),f.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",defaultStyles.headerHeight-defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+2+"px").attr("fill",defaultStyles.fontColor).text(v.howToUse),f.append("text").attr("x",defaultStyles.width/2).attr("y",defaultStyles.height-defaultStyles.footerHeight).attr("text-anchor","middle").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize).attr("fill",defaultStyles.fontColor).html(`Template by: ${s.metadata.source} | ${s.metadata.license} | ${s.metadata.authors} | ${s.metadata.website}`),s.sections.forEach((e,t)=>{var i=e.id,i=v.sections[i];const a=e.gridPosition.column*y+2*defaultStyles.padding,s=e.gridPosition.row*S+defaultStyles.headerHeight;var o=e.gridPosition.colSpan*y,n=e.gridPosition.rowSpan*S;const r={...defaultStyles,...e.style};if(f.append("rect").attr("x",a).attr("y",s).attr("width",o).attr("height",n).attr("fill",r.sectionColor).attr("stroke",r.borderColor).attr("rx",r.cornerRadius).attr("ry",r.cornerRadius).attr("stroke-width",r.lineSize),e.highlight&&f.append("rect").attr("x",a).attr("y",s).attr("width",o).attr("height",n).attr("fill",r.highlightColor).attr("stroke",r.borderColor).attr("rx",r.cornerRadius).attr("ry",r.cornerRadius).attr("stroke-width",2*r.lineSize),e.journeySteps){const h=["","","","",""];n=h.length;const m=Math.max(o/n-2*r.padding,r.stickyNoteSize),g=r.stickyNoteSize;f.append("defs").append("marker").attr("id","arrowhead").attr("markerWidth",4).attr("markerHeight",7).attr("refX",5).attr("refY",3.5).attr("orient","auto").append("polygon").attr("points","0 0, 5 3.5, 0 7").attr("fill",r.borderColor),h.forEach((e,t)=>{var i=a+t*(m+2*r.stickyNoteSpacing),o=i+m/2,n=s+r.stickyNoteSize;f.append("rect").attr("x",i).attr("y",s+r.stickyNoteSize/2+2*r.stickyNoteSpacing).attr("width",m).attr("height",g).attr("fill","#fff").attr("stroke",r.borderColor).attr("stroke-width",r.lineSize).attr("stroke-dasharray",3*r.lineSize).attr("rx",r.cornerRadius/2).attr("ry",r.cornerRadius/2),t{var t=l+e+" ",i=p.append("text").attr("font-family",r.fontFamily).attr("font-size",r.fontSize+"px").attr("fill",r.fontColor).attr("x",a+r.padding).attr("y",s+r.padding+r.circleRadius+2*r.padding+c*d).text(t);i.node().getComputedTextLength()>u?(i.remove(),f.append("text").attr("x",a+r.padding).attr("y",s+r.padding+r.circleRadius+2*r.padding+c*d).attr("font-family",defaultStyles.fontFamily).attr("font-size",r.fontSize+"px").attr("fill",r.fontColor).text(l),l=e+" ",c++):(i.remove(),l=t)}),f.append("text").attr("x",a+r.padding).attr("y",s+r.padding+r.circleRadius+2*r.padding+c*d).attr("font-family",r.fontFamily).attr("font-size",r.fontSize+"px").attr("fill",r.fontColor).text(l)}),f.append("defs").append("filter").attr("id","shadow").append("feDropShadow").attr("dx",3).attr("dy",3).attr("stdDeviation",2).attr("flood-color",defaultStyles.shadowColor),(t=document.getElementById("exportButton")).dataset.listenerAttached||(t.addEventListener("click",e=>{var t={templateId:s.id,metadata:{...l.metadata,date:(new Date).toISOString()},sections:l.sections.map(e=>({sectionId:e.sectionId,stickyNotes:e.stickyNotes.map(e=>({content:e.content.replace(/\n/g,""),position:e.position,size:e.size,color:e.color}))}))},t=JSON.stringify(t,null,2),i=document.createElement("a"),t=(i.href="data:application/json;charset=utf-8,"+encodeURIComponent(t),""+l.metadata.source+l.templateId+`_${d}.json`);i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i)}),t.dataset.listenerAttached=!0),(e=document.getElementById("importButton")).dataset.listenerAttached||(e.addEventListener("click",e=>{e.stopPropagation();e=document.createElement("input");e.type="file",e.accept=".json",e.onchange=e=>{var e=e.target.files[0],t=new FileReader;t.onload=e=>{e=JSON.parse(e.target.result);s.id=e.templateId,l.metadata=e.metadata,document.getElementById("source").value=e.metadata.source,document.getElementById("license").value=e.metadata.license,document.getElementById("authors").value=e.metadata.authors.join(","),document.getElementById("website").value=e.metadata.website,l.sections=e.sections.map((t,e)=>{const i=s.sections.find(e=>e.id===t.sectionId);let o=3*defaultStyles.stickyNoteSpacing,n=defaultStyles.stickyNoteSize;return{sectionId:t.sectionId,stickyNotes:t.stickyNotes.map(e=>{var t={content:validateInput(a(f,e.content.trim())),size:e.size||defaultStyles.stickyNoteSize,color:e.color||defaultStyles.stickyNoteColor};return e.position?t.position=e.position:(t.position={x:i.gridPosition.column*y+o,y:i.gridPosition.row*S+defaultStyles.headerHeight+n},(o+=defaultStyles.stickyNoteSize+defaultStyles.stickyNoteSpacing)+defaultStyles.stickyNoteSize>i.gridPosition.colSpan*y&&(o=2*defaultStyles.stickyNoteSpacing,n+=defaultStyles.stickyNoteSize+defaultStyles.stickyNoteSpacing)),t})}}),(f=d3.select("svg")).node().innerHTML=f.node().innerHTML,r(l),n()},t.readAsText(e)},e.click()}),e.dataset.listenerAttached=!0),(t=document.getElementById("exportSVGButton")).dataset.listenerAttached||(t.addEventListener("click",e=>{var t=f.node(),t=(new XMLSerializer).serializeToString(t),t=new Blob([t],{type:"image/svg+xml;charset=utf-8"}),i=document.createElement("a"),t=(i.href=URL.createObjectURL(t),""+l.metadata.source+l.templateId+`_${d}.svg`);i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i)}),t.dataset.listenerAttached=!0),document.querySelectorAll(".colorSwatch").forEach(e=>{e.addEventListener("click",()=>{currentColor=e.dataset.color,selectedNote&&(selectedNote.color=currentColor,r(l),selectedNote=null)})}),document.getElementById("metadataButton").addEventListener("click",()=>{document.getElementById("metadataForm").style.display="block"}),document.getElementById("saveMetadata").addEventListener("click",()=>{l.metadata={source:document.getElementById("source").value,license:document.getElementById("license").value,authors:document.getElementById("authors").value.split(","),website:document.getElementById("website").value},document.getElementById("metadataForm").style.display="none",n()});let i=0,o=0;function c(e,t){let o,n;"mouse"===t?(o=e.offsetX-defaultStyles.stickyNoteSize/2,n=e.offsetY-defaultStyles.stickyNoteSize/2):"touch"===t&&(t=e.changedTouches[0],e=f.node().getBoundingClientRect(),o=t.clientX-e.left-defaultStyles.stickyNoteSize/2,n=t.clientY-e.top-defaultStyles.stickyNoteSize/2);const i=s.sections.find(e=>{var t,i,e={x:e.gridPosition.column*y+2*defaultStyles.padding,y:e.gridPosition.row*S+defaultStyles.headerHeight,width:e.gridPosition.colSpan*y,height:e.gridPosition.rowSpan*S};return t=o+defaultStyles.stickyNoteSize/2,i=n+defaultStyles.stickyNoteSize/2,t>=(e=e).x&&t<=e.x+e.width&&i>=e.y&&i<=e.y+e.height});i&&(l.sections.find(e=>e.sectionId===i.id).stickyNotes.push({content:sanitizeInput("Double-click on text to edit. Click and select color "),position:{x:o,y:n},size:defaultStyles.stickyNoteSize,color:currentColor}),r(l))}f.on("click touchend",function(e){e.preventDefault();var{}=function(e){let t,i;var o,n=f.node().getBoundingClientRect();return i=e.type.startsWith("touch")?(o=e.changedTouches[0],t=o.clientX-n.left,o.clientY-n.top):(t=e.clientX-n.left,e.clientY-n.top),{x:t,y:i}}(e),t=(new Date).getTime();"touchend"===e.type?(t-i<300&&c(e,"touch"),i=t):(t-o<300&&c(e,"mouse"),o=t)}),r(l)}}let hasStickyNotes=!1;function checkForUnsavedChanges(e){var t;if(contentData&&contentData.sections&&(hasStickyNotes=contentData.sections.some(e=>0{var e=e.target.value,t=(document.getElementById("canvasSelector").style.display="block",populateCanvasSelector(e),document.getElementById("canvas").value);t&&loadCanvas(e,t)}),document.getElementById("canvas").addEventListener("change",e=>{loadCanvas(document.getElementById("locale").value,e.target.value)}),populateLocaleSelector();const localeSelector=document.getElementById("locale"),canvasSelector=document.getElementById("canvas");function handleSelectorFocus(e){if(contentData&&contentData.sections&&(hasStickyNotes=contentData.sections.some(e=>0{e.stickyNotes=[]}),loadCanvas(localeSelector.value,canvasSelector.value),!1;e.target.blur()}}function sanitizeInput(e){return e.replace(/)<[^<]*)*<\/script>/gi,"")}function validateInput(e){return 200{var t=document.createElement("option");t.value=e,t.text=e,i.add(t)})}function populateCanvasSelector(i){const o=document.getElementById("canvas");o.innerHTML="",Object.keys(localizedData[i]).forEach(e=>{var t=document.createElement("option");t.value=e,t.text=localizedData[i][e].title,o.add(t)})}document.getElementById("locale").addEventListener("change",e=>{e=e.target.value,document.getElementById("canvasSelector").style.display="block",populateCanvasSelector(e),e=document.getElementById("canvas").value;e&&(document.getElementById("canvasCreator").style.display="flex")},{once:!0}),document.querySelectorAll(".canvas-tools").forEach(e=>{e.addEventListener("touchstart",function(e){e.preventDefault(),this.click()},{passive:!1})}),document.getElementById("canvas").addEventListener("change",e=>{loadCanvas(document.getElementById("locale").value,e.target.value)},{once:!0});let canvasDataForId=null,contentData={};function loadCanvas(e,t){if(!(canvasDataForId=canvasData[t]))return void console.error("Canvas data not found for canvasId: "+t);contentData={templateId:t,locale:e,metadata:{source:"",license:"",authors:[],website:""},sections:canvasDataForId.sections?canvasDataForId.sections.map(e=>({sectionId:e.id,stickyNotes:[]})):[]};let f=d3.select("svg");const r=s=>{f.selectAll(".sticky-note").remove(),s&&s.sections&&(s.sections.forEach(i=>{var e=s.templateId;const o=canvasData[e].sections.find(e=>e.id===i.sectionId);i.stickyNotes&&0`sticky-note-${i.sectionId}-`+t).attr("transform",e=>{var t=(e.position.y||0)+0*(o.gridPosition.row+1);return`translate(${e.position.x||0},${t})`})).on("click touchstart",function(e,t){e.stopPropagation(),e.preventDefault(),selectedNote=t}),e.append("rect").attr("x",0).attr("y",0).attr("width",defaultStyles.stickyNoteSize).attr("height",defaultStyles.stickyNoteSize).attr("fill",e=>e.color||defaultStyles.stickyNoteColor).attr("stroke",defaultStyles.stickyNoteBorderColor).attr("rx",3).attr("ry",3),e.append("text").attr("x",5).attr("y",15).attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+"px").attr("fill",defaultStyles.contentFontColor).each(function(e){e.content=a(f,e.content);var t=e.content.split("\n");for(let e=0;e{i.node().focus()},0),i.on("focus",function(){this.value=t.content.replace(/\n{2,}/g,"\n")}).on("blur",function(e,t){var i;i=validateInput(sanitizeInput(this.value)),t.content=a(f,i),o.select("text").selectAll("tspan").remove(),d3.select(this.parentNode).remove(),r(s)})}))}),f.selectAll(".sticky-note").call(d3.drag().on("start",function(e,t){d3.select(this).attr("originalPosition",{x:t.position.x,y:t.position.y})}).on("drag",function(e,t){t.position.x=e.x,t.position.y=e.y,d3.select(this).attr("transform",`translate(${t.position.x},${t.position.y})`)}).on("end",function(e,t){})),f.on("contextmenu",function(e){e.preventDefault();var t=e.offsetX,i=e.offsetY;let o=null;for(let e=0;e=a.position.x&&t<=a.position.x+defaultStyles.stickyNoteSize&&i>=a.position.y&&i<=a.position.y+defaultStyles.stickyNoteSize){o=a;break}}if(o)break}o&&confirm("Are you sure you want to delete this sticky note?")&&((e=s.sections.find(e=>e.stickyNotes.includes(o))).stickyNotes=e.stickyNotes.filter(e=>e!==o),r(s))}))};function a(n,e){e=e.replace(/\n{2,}/g,"\n").split(" ");let a="";const s=[];return e.forEach(e=>{var t=a+e+" ",i=n.append("text").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+"px").text(t),o=i.node().getComputedTextLength();i.remove(),a=o>defaultStyles.maxLineWidth?(s.push(a),e+" "):t}),s.push(a),s.join("\n")}{var s=canvasDataForId,l=contentData;t=localizedData,d3.select("svg").remove();const y=Math.floor((defaultStyles.width-s.layout.columns*defaultStyles.padding)/s.layout.columns),S=Math.floor((defaultStyles.height-defaultStyles.headerHeight-defaultStyles.footerHeight-4*defaultStyles.padding)/s.layout.rows),d=l.locale||defaultStyles.defaultLocale,v=(e=l.templateId,t[d][e]);function n(){f.selectAll("text.footer").remove(),f.append("text").attr("class","footer").attr("x",defaultStyles.width/2).attr("y",defaultStyles.height-defaultStyles.footerHeight-2*defaultStyles.padding).attr("text-anchor","middle").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize).attr("fill",defaultStyles.fontColor).html(`Content by: ${l?.metadata?.source} | ${l?.metadata?.license} | ${l?.metadata?.authors} | ${l?.metadata?.website}`)}0===Object.keys(l).length&&(l.templateId=s.id,l.locale=d,l.metadata={source:"",license:"",authors:[],website:""},l.sections=s.sections.map(e=>({sectionId:e.id,stickyNotes:[]}))),(async(e,t,i=0,o,n=defaultStyles.headerHeight+2*defaultStyles.padding,a=defaultStyles.headerHeight+2*defaultStyles.padding)=>{try{var s=await fetch(e);if(!s.ok)throw new Error("Failed to fetch the logo SVG");var r=await s.text();t.append("g").attr("transform",`translate(${i}, ${o}) scale(${n/100}, ${a/100})`).html(r)}catch(e){}})("/img/apiops-cycles-logo2025-blue.svg",f=d3.select("#canvasCreator").append("svg").attr("width",defaultStyles.width+2*defaultStyles.padding).attr("height",defaultStyles.height).style("background-color",defaultStyles.backgroundColor),defaultStyles.padding,defaultStyles.padding/2,defaultStyles.padding,defaultStyles.padding),f.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",2*defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+4+"px").attr("font-weight","bold").attr("fill",defaultStyles.fontColor).text(v.title),f.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",defaultStyles.headerHeight-3*defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+2+"px").attr("fill",defaultStyles.fontColor).text(v.purpose),f.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",defaultStyles.headerHeight-defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+2+"px").attr("fill",defaultStyles.fontColor).text(v.howToUse),f.append("text").attr("x",defaultStyles.width/2).attr("y",defaultStyles.height-defaultStyles.footerHeight).attr("text-anchor","middle").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize).attr("fill",defaultStyles.fontColor).html(`Template by: ${s.metadata.source} | ${s.metadata.license} | ${s.metadata.authors} | ${s.metadata.website}`),s.sections.forEach((e,t)=>{var i=e.id,i=v.sections[i];const a=e.gridPosition.column*y+2*defaultStyles.padding,s=e.gridPosition.row*S+defaultStyles.headerHeight;var o=e.gridPosition.colSpan*y,n=e.gridPosition.rowSpan*S;const r={...defaultStyles,...e.style};if(f.append("rect").attr("x",a).attr("y",s).attr("width",o).attr("height",n).attr("fill",r.sectionColor).attr("stroke",r.borderColor).attr("rx",r.cornerRadius).attr("ry",r.cornerRadius).attr("stroke-width",r.lineSize),e.highlight&&f.append("rect").attr("x",a).attr("y",s).attr("width",o).attr("height",n).attr("fill",r.highlightColor).attr("stroke",r.borderColor).attr("rx",r.cornerRadius).attr("ry",r.cornerRadius).attr("stroke-width",2*r.lineSize),e.journeySteps){const h=["","","","",""];n=h.length;const m=Math.max(o/n-2*r.padding,r.stickyNoteSize),g=r.stickyNoteSize;f.append("defs").append("marker").attr("id","arrowhead").attr("markerWidth",4).attr("markerHeight",7).attr("refX",5).attr("refY",3.5).attr("orient","auto").append("polygon").attr("points","0 0, 5 3.5, 0 7").attr("fill",r.borderColor),h.forEach((e,t)=>{var i=a+t*(m+2*r.stickyNoteSpacing),o=i+m/2,n=s+r.stickyNoteSize;f.append("rect").attr("x",i).attr("y",s+r.stickyNoteSize/2+2*r.stickyNoteSpacing).attr("width",m).attr("height",g).attr("fill","#fff").attr("stroke",r.borderColor).attr("stroke-width",r.lineSize).attr("stroke-dasharray",3*r.lineSize).attr("rx",r.cornerRadius/2).attr("ry",r.cornerRadius/2),t{var t=l+e+" ",i=p.append("text").attr("font-family",r.fontFamily).attr("font-size",r.fontSize+"px").attr("fill",r.fontColor).attr("x",a+r.padding).attr("y",s+r.padding+r.circleRadius+2*r.padding+c*d).text(t);i.node().getComputedTextLength()>u?(i.remove(),f.append("text").attr("x",a+r.padding).attr("y",s+r.padding+r.circleRadius+2*r.padding+c*d).attr("font-family",defaultStyles.fontFamily).attr("font-size",r.fontSize+"px").attr("fill",r.fontColor).text(l),l=e+" ",c++):(i.remove(),l=t)}),f.append("text").attr("x",a+r.padding).attr("y",s+r.padding+r.circleRadius+2*r.padding+c*d).attr("font-family",r.fontFamily).attr("font-size",r.fontSize+"px").attr("fill",r.fontColor).text(l)}),f.append("defs").append("filter").attr("id","shadow").append("feDropShadow").attr("dx",3).attr("dy",3).attr("stdDeviation",2).attr("flood-color",defaultStyles.shadowColor),(t=document.getElementById("exportButton")).dataset.listenerAttached||(t.addEventListener("click",e=>{var t={templateId:s.id,metadata:{...l.metadata,date:(new Date).toISOString()},sections:l.sections.map(e=>({sectionId:e.sectionId,stickyNotes:e.stickyNotes.map(e=>({content:e.content.replace(/\n/g,""),position:e.position,size:e.size,color:e.color}))}))},t=JSON.stringify(t,null,2),i=document.createElement("a"),t=(i.href="data:application/json;charset=utf-8,"+encodeURIComponent(t),""+l.metadata.source+l.templateId+`_${d}.json`);i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i)}),t.dataset.listenerAttached=!0),(e=document.getElementById("importButton")).dataset.listenerAttached||(e.addEventListener("click",e=>{e.stopPropagation();e=document.createElement("input");e.type="file",e.accept=".json",e.onchange=e=>{var e=e.target.files[0],t=new FileReader;t.onload=e=>{e=JSON.parse(e.target.result);s.id=e.templateId,l.metadata=e.metadata,document.getElementById("source").value=e.metadata.source,document.getElementById("license").value=e.metadata.license,document.getElementById("authors").value=e.metadata.authors.join(","),document.getElementById("website").value=e.metadata.website,l.sections=e.sections.map((t,e)=>{const i=s.sections.find(e=>e.id===t.sectionId);let o=3*defaultStyles.stickyNoteSpacing,n=defaultStyles.stickyNoteSize;return{sectionId:t.sectionId,stickyNotes:t.stickyNotes.map(e=>{var t={content:validateInput(a(f,e.content.trim())),size:e.size||defaultStyles.stickyNoteSize,color:e.color||defaultStyles.stickyNoteColor};return e.position?t.position=e.position:(t.position={x:i.gridPosition.column*y+o,y:i.gridPosition.row*S+defaultStyles.headerHeight+n},(o+=defaultStyles.stickyNoteSize+defaultStyles.stickyNoteSpacing)+defaultStyles.stickyNoteSize>i.gridPosition.colSpan*y&&(o=2*defaultStyles.stickyNoteSpacing,n+=defaultStyles.stickyNoteSize+defaultStyles.stickyNoteSpacing)),t})}}),(f=d3.select("svg")).node().innerHTML=f.node().innerHTML,r(l),n()},t.readAsText(e)},e.click()}),e.dataset.listenerAttached=!0),(t=document.getElementById("exportSVGButton")).dataset.listenerAttached||(t.addEventListener("click",e=>{var t=f.node(),t=(new XMLSerializer).serializeToString(t),t=new Blob([t],{type:"image/svg+xml;charset=utf-8"}),i=document.createElement("a"),t=(i.href=URL.createObjectURL(t),""+l.metadata.source+l.templateId+`_${d}.svg`);i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i)}),t.dataset.listenerAttached=!0),document.querySelectorAll(".colorSwatch").forEach(e=>{e.addEventListener("click",()=>{currentColor=e.dataset.color,selectedNote&&(selectedNote.color=currentColor,r(l),selectedNote=null)})}),document.getElementById("metadataButton").addEventListener("click",()=>{document.getElementById("metadataForm").style.display="block"}),document.getElementById("saveMetadata").addEventListener("click",()=>{l.metadata={source:document.getElementById("source").value,license:document.getElementById("license").value,authors:document.getElementById("authors").value.split(","),website:document.getElementById("website").value},document.getElementById("metadataForm").style.display="none",n()});let i=0,o=0;function c(e,t){let o,n;"mouse"===t?(o=e.offsetX-defaultStyles.stickyNoteSize/2,n=e.offsetY-defaultStyles.stickyNoteSize/2):"touch"===t&&(t=e.changedTouches[0],e=f.node().getBoundingClientRect(),o=t.clientX-e.left-defaultStyles.stickyNoteSize/2,n=t.clientY-e.top-defaultStyles.stickyNoteSize/2);const i=s.sections.find(e=>{var t,i,e={x:e.gridPosition.column*y+2*defaultStyles.padding,y:e.gridPosition.row*S+defaultStyles.headerHeight,width:e.gridPosition.colSpan*y,height:e.gridPosition.rowSpan*S};return t=o+defaultStyles.stickyNoteSize/2,i=n+defaultStyles.stickyNoteSize/2,t>=(e=e).x&&t<=e.x+e.width&&i>=e.y&&i<=e.y+e.height});i&&(l.sections.find(e=>e.sectionId===i.id).stickyNotes.push({content:sanitizeInput("Double-click on text to edit. Click and select color "),position:{x:o,y:n},size:defaultStyles.stickyNoteSize,color:currentColor}),r(l))}f.on("click touchend",function(e){e.preventDefault();var{}=function(e){let t,i;var o,n=f.node().getBoundingClientRect();return i=e.type.startsWith("touch")?(o=e.changedTouches[0],t=o.clientX-n.left,o.clientY-n.top):(t=e.clientX-n.left,e.clientY-n.top),{x:t,y:i}}(e),t=(new Date).getTime();"touchend"===e.type?(t-i<300&&c(e,"touch"),i=t):(t-o<300&&c(e,"mouse"),o=t)}),r(l)}}let hasStickyNotes=!1;function checkForUnsavedChanges(e){var t;if(contentData&&contentData.sections&&(hasStickyNotes=contentData.sections.some(e=>0{var e=e.target.value,t=(document.getElementById("canvasSelector").style.display="block",populateCanvasSelector(e),document.getElementById("canvas").value);t&&loadCanvas(e,t)}),document.getElementById("canvas").addEventListener("change",e=>{loadCanvas(document.getElementById("locale").value,e.target.value)}),populateLocaleSelector();const localeSelector=document.getElementById("locale"),canvasSelector=document.getElementById("canvas");function handleSelectorFocus(e){if(contentData&&contentData.sections&&(hasStickyNotes=contentData.sections.some(e=>0{e.stickyNotes=[]}),loadCanvas(localeSelector.value,canvasSelector.value),!1;e.target.blur()}}function sanitizeInput(e){return e.replace(/)<[^<]*)*<\/script>/gi,"")}function validateInput(e){return 200{const n=document.createElement("option");n.value=t,n.text=t,e.add(n)}))}function populateCanvasSelector(e){const t=document.getElementById("canvas");t.innerHTML="";Object.keys(localizedData[e]).forEach((n=>{const i=document.createElement("option");i.value=n,i.text=localizedData[e][n].title,t.add(i)}))}document.getElementById("locale").addEventListener("change",(e=>{const t=e.target.value;document.getElementById("canvasSelector").style.display="block",populateCanvasSelector(t);document.getElementById("canvas").value&&(document.getElementById("canvasCreator").style.display="flex")}),{once:!0}),document.querySelectorAll(".canvas-tools").forEach((e=>{e.addEventListener("touchstart",(function(e){e.preventDefault(),this.click()}),{passive:!1})})),document.getElementById("canvas").addEventListener("change",(e=>{loadCanvas(document.getElementById("locale").value,e.target.value)}),{once:!0});let canvasDataForId=null,contentData={};function loadCanvas(e,t){if(canvasDataForId=canvasData[t],!canvasDataForId)return;contentData={templateId:t,locale:e,metadata:{source:"",license:"",authors:[],website:""},sections:canvasDataForId.sections?canvasDataForId.sections.map((e=>({sectionId:e.id,stickyNotes:[]}))):[]};let n=d3.select("svg");const i=e=>{n.selectAll(".sticky-note").remove(),e&&e.sections&&(e.sections.forEach((t=>{const s=e.templateId,a=canvasData[s].sections.find((e=>e.id===t.sectionId));if(t.stickyNotes&&t.stickyNotes.length>0){const s=n.selectAll(`.sticky-note-${t.sectionId}`).data(t.stickyNotes).enter().append("g").attr("class",`sticky-note sticky-note-${t.sectionId}`).attr("id",((e,n)=>`sticky-note-${t.sectionId}-${n}`)).attr("transform",(e=>{const t=(e.position.y||0)+0*(a.gridPosition.row+1);return`translate(${e.position.x||0},${t})`}));s.on("click touchstart",(function(e,t){e.stopPropagation(),e.preventDefault(),selectedNote=t})),s.append("rect").attr("x",0).attr("y",0).attr("width",defaultStyles.stickyNoteSize).attr("height",defaultStyles.stickyNoteSize).attr("fill",(e=>e.color||defaultStyles.stickyNoteColor)).attr("stroke",defaultStyles.stickyNoteBorderColor).attr("rx",3).attr("ry",3),s.append("text").attr("x",5).attr("y",15).attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+"px").attr("fill",defaultStyles.contentFontColor).each((function(e){e.content=o(n,e.content);const t=e.content.split("\n");for(let e=0;e{r.node().focus()}),0),r.on("focus",(function(){this.value=s.content.replace(/\n{2,}/g,"\n")})).on("blur",(function(t,s){let r=this.value;r=sanitizeInput(r),r=validateInput(r),s.content=o(n,r),a.select("text").selectAll("tspan").remove(),d3.select(this.parentNode).remove(),i(e)}))}))}})),n.selectAll(".sticky-note").call(d3.drag().on("start",(function(e,t){d3.select(this).attr("originalPosition",{x:t.position.x,y:t.position.y})})).on("drag",(function(e,t){t.position.x=e.x,t.position.y=e.y,d3.select(this).attr("transform",`translate(${t.position.x},${t.position.y})`)})).on("end",(function(e,t){}))),n.on("contextmenu",(function(t){t.preventDefault();const n=t.offsetX,o=t.offsetY;let s=null;for(let t=0;t=t.position.x&&n<=t.position.x+defaultStyles.stickyNoteSize&&o>=t.position.y&&o<=t.position.y+defaultStyles.stickyNoteSize){s=t;break}}if(s)break}if(s&&confirm("Are you sure you want to delete this sticky note?")){const t=e.sections.find((e=>e.stickyNotes.includes(s)));t.stickyNotes=t.stickyNotes.filter((e=>e!==s)),i(e)}})))};function o(e,t){const n=t.replace(/\n{2,}/g,"\n").split(" ");let i="";const o=[];return n.forEach((t=>{const n=i+t+" ",s=e.append("text").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+"px").text(n),a=s.node().getComputedTextLength();s.remove(),a>defaultStyles.maxLineWidth?(o.push(i),i=t+" "):i=n})),o.push(i),o.join("\n")}((e,t,s)=>{d3.select("svg").remove();const a=Math.floor((defaultStyles.width-e.layout.columns*defaultStyles.padding)/e.layout.columns),r=Math.floor((defaultStyles.height-defaultStyles.headerHeight-defaultStyles.footerHeight-4*defaultStyles.padding)/e.layout.rows),c=t.locale||defaultStyles.defaultLocale,d=t.templateId,l=s[c][d];0===Object.keys(t).length&&(t.templateId=e.id,t.locale=c,t.metadata={source:"",license:"",authors:[],website:""},t.sections=e.sections.map((e=>({sectionId:e.id,stickyNotes:[]})))),n=d3.select("#canvasCreator").append("svg").attr("width",defaultStyles.width+2*defaultStyles.padding).attr("height",defaultStyles.height).style("background-color",defaultStyles.backgroundColor);(async(e,t,n=0,i=0,o=defaultStyles.headerHeight+2*defaultStyles.padding,s=defaultStyles.headerHeight+2*defaultStyles.padding)=>{try{const a=await fetch(e);if(!a.ok)throw new Error("Failed to fetch the logo SVG");const r=await a.text();t.append("g").attr("transform",`translate(${n}, ${i}) scale(${o/100}, ${s/100})`).html(r)}catch(e){}})("/img/apiops-cycles-logo2025-blue.svg",n,defaultStyles.padding,defaultStyles.padding/2,defaultStyles.padding,defaultStyles.padding),n.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",2*defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+4+"px").attr("font-weight","bold").attr("fill",defaultStyles.fontColor).text(l.title),n.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",defaultStyles.headerHeight-3*defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+2+"px").attr("fill",defaultStyles.fontColor).text(l.purpose),n.append("text").attr("x",defaultStyles.headerHeight+2*defaultStyles.padding).attr("y",defaultStyles.headerHeight-defaultStyles.padding).attr("text-anchor","start").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize+2+"px").attr("fill",defaultStyles.fontColor).text(l.howToUse),n.append("text").attr("x",defaultStyles.width/2).attr("y",defaultStyles.height-defaultStyles.footerHeight).attr("text-anchor","middle").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize).attr("fill",defaultStyles.fontColor).html(`Template by: ${e.metadata.source} | ${e.metadata.license} | ${e.metadata.authors} | ${e.metadata.website}`),e.sections.forEach(((e,t)=>{const i=e.id,o=l.sections[i],s=e.gridPosition.column*a+2*defaultStyles.padding,c=e.gridPosition.row*r+defaultStyles.headerHeight,d=e.gridPosition.colSpan*a,u=e.gridPosition.rowSpan*r,p={...defaultStyles,...e.style};if(n.append("rect").attr("x",s).attr("y",c).attr("width",d).attr("height",u).attr("fill",p.sectionColor).attr("stroke",p.borderColor).attr("rx",p.cornerRadius).attr("ry",p.cornerRadius).attr("stroke-width",p.lineSize),e.highlight&&n.append("rect").attr("x",s).attr("y",c).attr("width",d).attr("height",u).attr("fill",p.highlightColor).attr("stroke",p.borderColor).attr("rx",p.cornerRadius).attr("ry",p.cornerRadius).attr("stroke-width",2*p.lineSize),e.journeySteps){const e=["","","","",""],t=e.length,i=Math.max(d/t-2*p.padding,p.stickyNoteSize),o=p.stickyNoteSize,a=0;n.append("defs").append("marker").attr("id","arrowhead").attr("markerWidth",4).attr("markerHeight",7).attr("refX",5).attr("refY",3.5).attr("orient","auto").append("polygon").attr("points","0 0, 5 3.5, 0 7").attr("fill",p.borderColor),e.forEach(((t,r)=>{const d=s+r*(i+2*p.stickyNoteSpacing),l=d+i/2,u=c+p.stickyNoteSize;if(n.append("rect").attr("x",d).attr("y",c+p.stickyNoteSize/2+2*p.stickyNoteSpacing).attr("width",i).attr("height",o).attr("fill","#fff").attr("stroke",p.borderColor).attr("stroke-width",p.lineSize).attr("stroke-dasharray",3*p.lineSize).attr("rx",p.cornerRadius/2).attr("ry",p.cornerRadius/2),r{const t=g+e+" ",i=S.append("text").attr("font-family",p.fontFamily).attr("font-size",p.fontSize+"px").attr("fill",p.fontColor).attr("x",s+p.padding).attr("y",c+p.padding+p.circleRadius+2*p.padding+m*f).text(t);i.node().getComputedTextLength()>y?(i.remove(),n.append("text").attr("x",s+p.padding).attr("y",c+p.padding+p.circleRadius+2*p.padding+m*f).attr("font-family",defaultStyles.fontFamily).attr("font-size",p.fontSize+"px").attr("fill",p.fontColor).text(g),g=e+" ",m++):(i.remove(),g=t)})),n.append("text").attr("x",s+p.padding).attr("y",c+p.padding+p.circleRadius+2*p.padding+m*f).attr("font-family",p.fontFamily).attr("font-size",p.fontSize+"px").attr("fill",p.fontColor).text(g)}));function u(){n.selectAll("text.footer").remove(),n.append("text").attr("class","footer").attr("x",defaultStyles.width/2).attr("y",defaultStyles.height-defaultStyles.footerHeight-2*defaultStyles.padding).attr("text-anchor","middle").attr("font-family",defaultStyles.fontFamily).attr("font-size",defaultStyles.fontSize).attr("fill",defaultStyles.fontColor).html(`Content by: ${t?.metadata?.source} | ${t?.metadata?.license} | ${t?.metadata?.authors} | ${t?.metadata?.website}`)}n.append("defs").append("filter").attr("id","shadow").append("feDropShadow").attr("dx",3).attr("dy",3).attr("stdDeviation",2).attr("flood-color",defaultStyles.shadowColor);const p=document.getElementById("exportButton");p.dataset.listenerAttached||(p.addEventListener("click",(n=>{const i={templateId:e.id,metadata:{...t.metadata,date:(new Date).toISOString()},sections:t.sections.map((e=>({sectionId:e.sectionId,stickyNotes:e.stickyNotes.map((e=>({content:e.content.replace(/\n/g,""),position:e.position,size:e.size,color:e.color})))})))},o=JSON.stringify(i,null,2),s=document.createElement("a");s.href="data:application/json;charset=utf-8,"+encodeURIComponent(o);const a=`${t.metadata.source}${t.templateId}_${c}.json`;s.download=a,document.body.appendChild(s),s.click(),document.body.removeChild(s)})),p.dataset.listenerAttached=!0);const h=document.getElementById("importButton");h.dataset.listenerAttached||(h.addEventListener("click",(s=>{s.stopPropagation();const c=document.createElement("input");c.type="file",c.accept=".json",c.onchange=s=>{const c=s.target.files[0],d=new FileReader;d.onload=s=>{const c=JSON.parse(s.target.result);e.id=c.templateId,t.metadata=c.metadata,document.getElementById("source").value=c.metadata.source,document.getElementById("license").value=c.metadata.license,document.getElementById("authors").value=c.metadata.authors.join(","),document.getElementById("website").value=c.metadata.website,t.sections=c.sections.map(((t,i)=>{const s=e.sections.find((e=>e.id===t.sectionId));let c=3*defaultStyles.stickyNoteSpacing,d=defaultStyles.stickyNoteSize;return{sectionId:t.sectionId,stickyNotes:t.stickyNotes.map((e=>{const t={content:validateInput(o(n,e.content.trim())),size:e.size||defaultStyles.stickyNoteSize,color:e.color||defaultStyles.stickyNoteColor};return e.position?t.position=e.position:(t.position={x:s.gridPosition.column*a+c,y:s.gridPosition.row*r+defaultStyles.headerHeight+d},c+=defaultStyles.stickyNoteSize+defaultStyles.stickyNoteSpacing,c+defaultStyles.stickyNoteSize>s.gridPosition.colSpan*a&&(c=2*defaultStyles.stickyNoteSpacing,d+=defaultStyles.stickyNoteSize+defaultStyles.stickyNoteSpacing)),t}))}})),n=d3.select("svg"),n.node().innerHTML=n.node().innerHTML,i(t),u()},d.readAsText(c)},c.click()})),h.dataset.listenerAttached=!0);const g=document.getElementById("exportSVGButton");g.dataset.listenerAttached||(g.addEventListener("click",(e=>{const i=n.node(),o=(new XMLSerializer).serializeToString(i),s=new Blob([o],{type:"image/svg+xml;charset=utf-8"}),a=document.createElement("a");a.href=URL.createObjectURL(s);const r=`${t.metadata.source}${t.templateId}_${c}.svg`;a.download=r,document.body.appendChild(a),a.click(),document.body.removeChild(a)})),g.dataset.listenerAttached=!0);document.querySelectorAll(".colorSwatch").forEach((e=>{e.addEventListener("click",(()=>{currentColor=e.dataset.color,selectedNote&&(selectedNote.color=currentColor,i(t),selectedNote=null)}))})),document.getElementById("metadataButton").addEventListener("click",(()=>{document.getElementById("metadataForm").style.display="block"})),document.getElementById("saveMetadata").addEventListener("click",(()=>{t.metadata={source:document.getElementById("source").value,license:document.getElementById("license").value,authors:document.getElementById("authors").value.split(","),website:document.getElementById("website").value},document.getElementById("metadataForm").style.display="none",u()}));let m=0,f=0;function y(o,s){let c,d;if("mouse"===s)c=o.offsetX-defaultStyles.stickyNoteSize/2,d=o.offsetY-defaultStyles.stickyNoteSize/2;else if("touch"===s){const e=o.changedTouches[0],t=n.node().getBoundingClientRect();c=e.clientX-t.left-defaultStyles.stickyNoteSize/2,d=e.clientY-t.top-defaultStyles.stickyNoteSize/2}const l=e.sections.find((e=>{const t={x:e.gridPosition.column*a+2*defaultStyles.padding,y:e.gridPosition.row*r+defaultStyles.headerHeight,width:e.gridPosition.colSpan*a,height:e.gridPosition.rowSpan*r};return function(e,t,n){return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height}(c+defaultStyles.stickyNoteSize/2,d+defaultStyles.stickyNoteSize/2,t)}));if(l){t.sections.find((e=>e.sectionId===l.id)).stickyNotes.push({content:sanitizeInput("Double-click on text to edit. Click and select color "),position:{x:c,y:d},size:defaultStyles.stickyNoteSize,color:currentColor}),i(t)}}n.on("click touchend",(function(e){e.preventDefault();const{x:t,y:i}=function(e){let t,i;const o=n.node().getBoundingClientRect();if(e.type.startsWith("touch")){const n=e.changedTouches[0];t=n.clientX-o.left,i=n.clientY-o.top}else t=e.clientX-o.left,i=e.clientY-o.top;return{x:t,y:i}}(e),o=(new Date).getTime();"touchend"===e.type?(o-m<300&&y(e,"touch"),m=o):(o-f<300&&y(e,"mouse"),f=o)})),i(t)})(canvasDataForId,contentData,localizedData)}let hasStickyNotes=!1;function checkForUnsavedChanges(e){if(contentData&&contentData.sections&&(hasStickyNotes=contentData.sections.some((e=>e.stickyNotes.length>0)),hasStickyNotes)){const t="You have unsaved changes. Are you sure you want to leave this page?";return e.preventDefault(),e.returnValue=t,t}}window.addEventListener("beforeunload",checkForUnsavedChanges),document.getElementById("locale").addEventListener("change",(e=>{const t=e.target.value;document.getElementById("canvasSelector").style.display="block",populateCanvasSelector(t);const n=document.getElementById("canvas").value;n&&loadCanvas(t,n)})),document.getElementById("canvas").addEventListener("change",(e=>{loadCanvas(document.getElementById("locale").value,e.target.value)})),populateLocaleSelector();const localeSelector=document.getElementById("locale"),canvasSelector=document.getElementById("canvas");function handleSelectorFocus(e){if(contentData&&contentData.sections&&(hasStickyNotes=contentData.sections.some((e=>e.stickyNotes.length>0)),hasStickyNotes)){if(confirm("Are you sure you want to remove sticky notes and change canvas?")){contentData.sections.forEach((e=>{e.stickyNotes=[]}));return loadCanvas(localeSelector.value,canvasSelector.value),!1}e.target.blur()}}function sanitizeInput(e){return e.replace(/)<[^<]*)*<\/script>/gi,"")}function validateInput(e){return e.length>200?e.substring(0,200):e}localeSelector.addEventListener("focus",handleSelectorFocus),canvasSelector.addEventListener("focus",handleSelectorFocus); \ No newline at end of file From 4c6411dd93883ae03a188a546aeed329c828b883 Mon Sep 17 00:00:00 2001 From: Daniel Kocot Date: Sun, 23 Feb 2025 00:20:55 +0100 Subject: [PATCH 5/5] added v1_6 --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 55630ad..262188b 100644 --- a/index.html +++ b/index.html @@ -151,6 +151,6 @@

Content Metadata

document.getElementById("mySidenav").style.width = "0" } - +