Tagasi ülevaate juurde

Tere, maailm: OpenIntegrationi õpetus

Meie juhend kõigile, kes soovivad leida viisi oma integratsioonide näitamiseks oma OpenPaperis.

Selle lühikese juhendiga tahame teile näidata, kui lihtne on kirjutada iseseisev OpenIntegration‑laiendus, et seda seejärel paperlesspaper‑rakenduses integratsiooni‑pistikprogrammina kasutada.

Kõik, mida selleks vajate on mõned teadmised HTML/CSS‑ist ja Dockeriga töötamisest ning server või pilve‑instants valitud pakkuja juures. Oluline on ainult see, et server oleks mingil domeenil ja kehtiva SSL‑sertifikaadiga internetist kättesaadav. Tõelisteks testideks soovitame muidugi meie OpenPaper7 või OpenPaperL.

Alustame!

Bildschirmfoto 2026-04-27 um 09

Siin on meie põhiline struktuur. Vajame Dockerfile'i, et hiljem oma integratsioon Docker‑konteinerisse pakkida. Kuna OpenIntegration nõuab HTML‑failide ja config.json veebiserveri kaudu Paperlesspaper‑rakendusele tagastamist, valisime veebiserveriks NGINXi — seetõttu on meil nginx.conf. Meie loodav Docker‑image põhineb seega nginx:alpine'il.

Kaustas /src asuvad kaks OpenIntegrationi jaoks hädavajalikku faili: config.json ja index.html

Failis config.json saab määrata teie OpenIntegrationi metaandmed: nimi, kirjeldus ja versiooninumber. Lisaks konfigureeritakse siin seaded, mida integratsiooni kasutaja hiljem ise saab määrata. Meie näites on see ainult tekstiväli nime sisestamiseks.

Siin on meie

json
{
  "name": "This one is a basic Hello-World example, which greets you with your name",
  "version": "1.0.0",
  "description": "A simple plugin that displays a greeting message based on the user's name.",
  "nativeSettings": {
    "orientation": "portrait"
  },
  "formSchema": {
    "type": "object",
    "properties": {
      "name": {
        "type": "string",
        "description": "The name of the user to greet.",
        "default": "OpenPaper-Lover"
      }
    }
  },
  "renderPage": "./index.html"
}

Väärtuse nativeSettings all saate edastada pildiraami seadeid, näiteks et teie integratsioon töötab ainult portreerežiimis. formSchema‑osa määratleb meie teksti sisestusvälja. Oluline on määrata renderPage — see on suhteline tee teie serveri domeeni sees, kus asub fail, mis tagastab pildiraami pildi. Me piirdume siin lihtsa tekstiväljaga nimega: "name". Kes tahab rohkem teada, millised sisendväljade võimalused on, võib siin vaadata liidese tüübikirjeldust.

Meie index.html vaja on meil ainult järgmist HTML‑põhistruktuuri:

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Openintegration: Hello World</title>
  </head>
  <body>
    <div id="website-has-loading-element" class="hidden-marker"></div>
    <main class="screen">
      <section>
        <h2 class="subtitle">Hello</h2>
        <h1 class="title" id="name">World</h1>
        <h4 id="clock">00:00</h4>
      </section>
    </main>
  </body>
</html>

Siin ei juhtu palju, välja arvatud see, et kuvatakse Hello World. Der <div id="website-has-loading-element" class="hidden-marker"></div> näitab meie renderdusserverile, et veebileht on täielikult laaditud alles siis, kui lehel on id="website-has-loaded" id.

Kui kasutate oma integratsioonis asünkroonseid päringuid või suuri graafikaid, võib see vajalik olla. Meie renderdusserver lõpetab muidu mõne sekundi pärast iseseisvalt ja renderdab ainult selle, mis selleks ajaks laaditud on. Võite kogu asja brauseris üle vaadata, nii näete umbes, kuidas see teie OpenPaperil lõppkokkuvõttes välja näeks.

See peaks praegu umbes selline välja nägema:

Das erste html wird auf dem Rahmen angezeigtdesign-htmlDas erste html wird auf dem Rahmen angezeigt

Kuna tahame seda veidi ilusamaks muuta, peame HTML‑päisesse lisama natuke CSSi:

html
<style>
      :root {
        color-scheme: light dark;
      }
      * {
        box-sizing: border-box;
      }

      html,
      body {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        font-family:
          ui-sans-serif,
          system-ui,
          -apple-system,
          BlinkMacSystemFont,
          "Segoe UI",
          sans-serif;
        background: #fff;
        color: #000;
      }

      .screen {
        width: 100vw;
        height: 100vh;
        padding: 1.3em;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .title {
        font-size: clamp(1rem, 1.4vw + 0.8rem, 2rem);
        font-weight: 600;
        text-align: center;
        margin: 0 0 0.2rem 0;
      }

      .subtitle {
        font-size: clamp(0.9rem, 0.9vw + 0.6rem, 1.3rem);
        opacity: 0.75;
        text-align: center;
        margin: 0 0 0.2rem 0;
      }

      #clock {
        font-size: clamp(0.5rem, 0.5vw + 0.2rem, 0.8rem);
        opacity: 0.25;
        text-align: center;
        margin: 5rem 0 0.2rem 0;
      }

      .hidden-marker {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
      }
    </style>

Parem, kas pole?

Jetzt mit Formatierungformatted-design-1Jetzt mit Formatierung

Ainult väike JavaScript on veel vaja. Tahame kuvada Hello "nimi sätetest", mitte ainult "World". Lisaks lisame väikese renderdamise kellaaja, mis on mõistlik kontrollimaks, kas pilt pärast koodi muudatusi on juba uuendunud. Järgmist koodiplokki vajate seega oma lähtekoodi lõpus (enne sulguvat body‑sildi):

html
<script>
    // live clock
    const clockElement = document.getElementById("clock");
    const now = new Date();
    const hh = String(now.getHours()).padStart(2, "0");
    const mm = String(now.getMinutes()).padStart(2, "0");
    clockElement.textContent = `${hh}:${mm}`;

    // mark page loaded
    const markLoaded = function () {
      const markerLoaded = document.createElement("div");
      markerLoaded.id = "website-has-loaded";
      document.body.appendChild(markerLoaded);
    };


    // Handling Settings Page Updates
    window.addEventListener("message", (event) => {
      const data = event.data;
      const payload = data.data || {};
      if (data.type === "INIT" && data.cmd === "message") {
        if (payload.meta?.pluginSettings?.name) {
          document.getElementById("name").textContent =
            payload.meta?.pluginSettings?.name;
        }
        markLoaded();
      }
    });
  </script>

Nagu meie Dokumentation kirjeldab, lisame lehele sündmuste kuulaja, mis kuulab message‑sündmust. Kuna siin vahetatakse mitmeid sõnumeid rakenduse ja integratsiooni vahel, huvitavad meid ainult sõnumid, millel on type="INIT" ja cmd=="message" omad. Varem config.jsonis loodud nimeväli (name) leiame vastuvõetud JS‑objektist aadressilt payload.meta?.pluginSettings?.name; . Leitud stringi kirjutame nüüd meie HTML‑pealkirja, mille ID on name.

Selleks, et teatada renderdusmootorile, et oleme laadimise ja andmete kuvamisega valmis, kutsutakse funktsioon markLoaded välja. See lisab dokumendi lõppu ühe div elemendi id‑ga website-had-loaded. Valmis!

Kui soovite oma integratsiooni nüüd Docker‑hostis kättesaadavaks teha, võite lihtsalt kasutada järgmist Dockerfile'i:

dockerfile
FROM nginx:alpine
# Remove default nginx config and content
RUN rm /etc/nginx/conf.d/default.conf && \
    rm -rf /usr/share/nginx/html/*
# Copy optimized nginx config
COPY nginx.conf /etc/nginx/nginx.conf
# Copy static files
COPY src/ /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Nagu näete, kopeerime nginx.conf Docker‑image'i. See on samuti üsna lihtne. Siin tuleb ainult jälgida, et CORS‑päised oleksid õigesti seatud:

plaintext
worker_processes auto;
events {
    worker_connections 1024;
}
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    server {
        listen 80;
        server_name _;
        add_header Access-Control-Allow-Origin "*" always;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Authorization, Content-Type, Accept, Origin, X-Requested-With" always;
        root /usr/share/nginx/html;
        index index.html;
        location / {
            if ($request_method = OPTIONS) {
                return 204;
            }
            try_files $uri $uri/ =404;
        }
    }
}

Seda Access-Control-Allow-Origin peab olema seatud nii, et vähemalt web.paperlesspaper.de, api.paperlesspaper.de, capacitor://localhost (iOS‑i jaoks) ja http://localhost (Androidi jaoks) lubatud. Me lubame näites lihtsuse mõttes kõiki URL‑e.


Kuidas lisada oma integratsioon paperlesspaper‑rakendusse? Väga lihtne:

  • Avage rakenduses raamatukogu ja klõpsake "Neues Bild"
  • Loendist valige "Integrations Plugin"
Bildschirmfoto 2026-05-04 um 11

Ilmunud seadistuslehele peate nüüd sisestama lingi oma konfiguratsioonimanifestile (config.json sisestama).

Meie näitedomeeni helloworld.paperlesspaper.de puhul oleks see:

Bildschirmfoto 2026-05-04 um 12

Pärast integratsiooni konfiguratsiooni URL‑i sisestamist ja nupule "Laden" klõpsamist ilmub sisestusväli name. Siin saate nüüd sisestada soovitud nime, mis seejärel OpenPaperil kuvatakse.

Pärast klõpsu "Weiter" ja soovitud raami valimist järgmises dialoogis on teie integratsioon aktiivne. Soovitud kuva ilmub OpenPaperile pärast järgmist värskamisintervalli.

See on kõik! Täieliku lähtekoodi leiate Openintegration-HelloWorld-Github-Repository.

Head katsetamist! Küsimused ja kommentaarid saatke aadressile support@paperlesspaper.de