So entwickeln Sie ein DocSpace-Plugin: vollständiges Schritt-für-Schritt-Tutorial
In einer Welt, in der Geschwindigkeit und Zusammenarbeit alles sind, müssen Produktivitätstools mithalten. Die DocSpace-Plugins bieten eine moderne Möglichkeit, die Verwaltung und Interaktion von Dokumenten zu verbessern. In dieser Anleitung zeigen wir Ihnen anhand von Beispielen, wie Sie Ihr eigenes DocSpace-Plugin erstellen.
Über das ONLYOFFICE DocSpace Plugins SDK
Das ONLYOFFICE DocSpace Plugins SDK ist ein auf TypeScript-Engines basierendes npm-Paket, das Schnittstellen bietet, mit denen Sie eigene Plugins erstellen und in das DocSpace-Portal einbetten können. Der Plugin-Entwicklungszyklus umfasst Planung, Entwicklung, Test und Nutzung.
Um die Verwendung unseres Plugins SDK zu veranschaulichen, haben wir ein Repository mit Plugin-Beispielen erstellt. Lassen Sie uns anhand unserer Plugin-Beispiele den gesamten Prozess der Plugin-Entwicklung genauer betrachten.
Planung
Definieren Sie den Zweck des Plugins, überlegen Sie, wo Sie darauf zugreifen und welche Drittanbieterdienste Sie anbinden möchten.
Schritt 1: Installieren Sie alle benötigten Pakete und Programme
- ONLYOFFICE DocSpace lokal
- @onlyoffice/docspace-plugin-sdk npm-Paket
Um das @onlyoffice/docspace-plugin-sdk npm-Paket global zu installieren, verwenden Sie den folgenden Befehl:
npm i -g @onlyoffice/docspace-plugin-sdk
Schritt 2. Gestalten Sie die Funktionsweise Ihres Plugins
Wählen Sie den Dienst, mit dem Sie Ihrem DocSpace die benötigten Funktionen hinzufügen können.
In unseren Plugin-Beispielen verwenden wir beispielsweise:
- AssemblyAI zur Konvertierung von Sprache aus Audio- und Videodateien in Text;
- ConvertAPI zur Konvertierung von Dokumenten, Tabellen, Präsentationen und Formularen in PDF;
- Draw.io zum Erstellen, Bearbeiten und Einfügen professioneller Diagramme.
Hinweis! Bitte stellen Sie sicher, dass die Servicedokumentation verfügbar ist. Überprüfen Sie die Lizenz, die Verfügbarkeit von API-Methoden usw. Für einige Dienste benötigt der Nutzer einen API-Schlüssel, um das Plugin nutzen zu können.
Überlegen Sie, wo das Plugin implementiert werden soll, wie die Plugin-Struktur aussehen soll und wie der Nutzer mit den Plugin-Komponenten interagieren soll. Erstellen Sie basierend auf diesen Informationen eine Liste der benötigten Plugin-Typen und -Elemente. Weitere Informationen finden Sie in den Abschnitten zu Plugin-Typen und Plugin-Elementen der Plugins SDK-Dokumentation.
Für das Spracherkennungs-Plugin verwenden wir beispielsweise die folgenden Plugin-Schnittstellen:
- IPlugin. Erforderlich für jedes Plugin. Enthält die Plugin-Variable PluginStatus, mit der das Plugin in den DocSpace eingebettet wird.
- ApiPlugin. Erforderlich, da wir einen Drittanbieterdienst implementieren.
- ISettingsPlugin und ISettings. Dient zum Hinzufügen eines Einstellungsblocks für die Plugin-Konfiguration. Nutzer greifen über Einstellungen -> Integration -> Plugins auf diesen Block zu, um die Plugin-Parameter anzupassen.
- IContextMenuPlugin und IContextMenuItem. Dient zum Implementieren einer Kontextmenüaktion. Im Spracherkennungs-Plugin ist es für Video- und Audiodateien verfügbar und ermöglicht Nutzern die Konvertierung von Inhalten in Text.
Die Liste der Schnittstellen kann länger sein. Beispielsweise im draw\.io-Plugin:
- IMainButtonPlugin und IMainButtonItem. Dient zur Implementierung der Hauptschaltflächenaktion. Im draw\.io-Plugin verwenden wir die Menüelemente Aktionsschaltfläche -> Weitere im Bereich Meine Dokumente oder im ausgewählten Raum, um draw\.io-Diagramme zu erstellen.
- IFilePlugin und IFileItem. Dient zur Interaktion mit den angegebenen Dateitypen. In diesem Fall mit den .drawio-Dateien.
Überlegen Sie sich die Struktur des Plugins. Alle benötigten Dateien werden hier beschrieben. Alles Weitere können Sie nach Belieben organisieren. Beispielsweise platzieren wir im Plugin draw\.io den Code für jeden Plugin-Typ in separaten Ordnern, während dieser Code im Plugin Sprache-zu-Text im Ordner src abgelegt wird.
Wählen Sie einen Namen für Ihr Plugin und schreiben Sie eine Beschreibung dafür.
Entwicklung
Nachdem alle Vorbereitungen abgeschlossen sind, können Sie mit der Entwicklung Ihres Plugins beginnen.
Schritt 1: Plugin-Vorlage erstellen
Erstellen Sie eine Plugin-Vorlage und konfigurieren Sie deren Einstellungen. Diese werden in den DocSpace-Plugin-Einstellungen angezeigt:
Um eine Plugin-Vorlage zu erstellen, öffnen Sie das Terminal und führen Sie den folgenden npx-Befehl aus:
npx create-docspace-plugin
Wenn der Befehl npx nicht verfügbar ist, installieren Sie das NPM-Paket @onlyoffice/docspace-plugin-sdk global mit dem folgenden Befehl:
npm i -g @onlyoffice/docspace-plugin-sdk
Konfigurieren Sie das Plugin im Terminal, indem Sie die Einstellungen im Dialogfeld festlegen. Alle Einstellungen werden hier beschrieben.
Für das Spracherkennungs-Plugin können Sie die folgenden Werte verwenden:
Sie können alle angegebenen Parameter später in der Datei package.json ändern.
Sie können auch in jedem Projekt ein Plugin erstellen, indem Sie das npm-Paket @onlyoffice/docspace-plugin-sdk als Abhängigkeit hinzufügen und alle erforderlichen Felder in der Datei package.json angeben.
Schritt 2. Plugin-Einstiegspunkt konfigurieren
Der Plugin-Einstiegspunkt index.ts wird bei der Vorlagenerstellung automatisch im Ordner src erstellt. Diese Datei ist erforderlich.
Diese Datei enthält alle grundlegenden Methoden der im vorherigen Schritt ausgewählten Plugin-Typen. Sie können diese Datei jederzeit ändern.
Wenn Sie selbst ein Plugin ohne Vorlage für den Plugin-Einstiegspunkt erstellen, können Sie den Code aus unseren vorgefertigten Plugin-Beispielen verwenden. Er funktioniert einwandfrei.
Schritt 3. Plugin-Symbole hinzufügen
Erstellen Sie den Ordner assets im Stamm-Plugin-Ordner und fügen Sie dort alle Plugin-Symbole hinzu. Anzahl und Größe der Symbole hängen von den implementierten Plugin-Typen ab. Für das Spracherkennungs-Plugin benötigen wir folgende Symbole:
- Der Standard-Plugin-Typ erfordert ein logo-Bild. Es entspricht dem Logo-Parameter aus der Datei package.json. Das Logo wird in den DocSpace-Plugin-Einstellungen angezeigt. Die erforderliche Symbolgröße beträgt 48 x 48 Pixel. Andernfalls wird es auf diese Größe komprimiert.
- Das Kontextmenü des Plugins verwendet ein Symbol (icon) auf der Schaltfläche In Text konvertieren. Die erforderliche Symbolgröße beträgt 16 x 16 Pixel. Andernfalls wird das Symbol auf diese Größe komprimiert.
Dieses Symbol kann auch als Hauptschaltflächensymbol verwendet werden. Im Plugin draw\.io wird beispielsweise dasselbe Symbol für das Kontextmenü und das Hauptschaltflächenmenü verwendet.
Das draw\.io-Plugin verwendet außerdem das spezifische Dateisymbol neben den .drawio-Dateien, die mit dem Datei-Plugin-Typ erstellt werden. Die bevorzugte Symbolgröße für das Tabellenformat beträgt 32 x 32 Pixel.
Schritt 4. Die Oberflächenelemente des Plugins konfigurieren
Das draw\.io-Plugin enthält beispielsweise zwei Haupt-UI-Elemente: das modale Fenster und den Diagrammeditor. Erstellen Sie die Dateien zur Konfiguration der einzelnen Elemente. Sie können diese Dateien bequem in einem separaten DrawIO-Ordner ablegen.
Konfigurieren Sie in der Datei Dialog.ts die Einstellungen für das modale Fenster. Geben Sie die IFrame-UI-Komponente an, mit der die draw\.io-Website in ein modales Fenster eingebettet wird:
export const frameProps: IFrame = {
width: "100%",
height: "100%",
name: "test-drawio",
src: "",
}
Erstellen Sie den IBox-Container, um den Iframe hinzuzufügen:
const body: IBox = {
widthProp: "100%",
heightProp: "100%",
children: [
{
component: Components.iFrame,
props: frameProps,
},
],
}
Konfigurieren Sie die Eigenschaften des modalen Fensters:
export const drawIoModalDialogProps: IModalDialog = {
dialogHeader: "",
dialogBody: body,
displayType: ModalDisplayType.modal,
fullScreen: true,
onClose: () => {
const message: IMessage = {
actions: [Actions.closeModal],
}
return message
},
onLoad: async () => {
return {
newDialogHeader: drawIoModalDialogProps.dialogHeader || "",
newDialogBody: drawIoModalDialogProps.dialogBody,
}
},
autoMaxHeight: true,
autoMaxWidth: true,
Konfigurieren Sie in der Datei Editor.ts den Diagrammeditor. Erstellen Sie die Funktion DiagramEditor mit den folgenden Parametern:
Parameter | Typ | Beispiel | Beschreibung |
ui | string | “default” | Definiert das UI-Design des Editors. |
dark | string | “auto” | Definiert das dunkle Design des Editors. |
off | boolean | false | Gibt an, ob der Offline-Modus aktiv ist oder nicht. |
lib | boolean | false | Gibt an, ob die Bibliotheken aktiviert sind oder nicht. |
lang | string | “auto” | Definiert die Sprache des Editors. |
url | string | `https://embed.diagrams.net` | Definiert die URL zum Editor. |
showSaveButton | boolean | true | Gibt an, ob die Schaltfläche Speichern im Editor angezeigt wird. |
Geben Sie dann Methoden zum Arbeiten mit Diagrammen an:
Methode | Beschreibung |
startEditing | Startet den Editor mit den angegebenen Daten. |
getData | Gibt die Daten des Diagramms zurück. |
getTitle | Gibt den Titel des Diagramms zurück. |
getFormat | Gibt das Format des Diagramms zurück. |
getFrameId | Gibt die Frame-ID des Editors zurück. |
getFrameUrl | Gibt die URL zum Iframe zurück. |
handleMessage | Verarbeitet die angegebene Nachricht. |
initializeEditor | Sendet die Lademeldung an den Editor. |
save | Speichert die angegebenen Daten. |
Schritt 5. Plugin-Typen erstellen
Nachdem das Standard-Plugin fertig ist, können Sie mit der Entwicklung weiterer Plugin-Typen beginnen.
Jeder Plugin-Typ verfügt über spezifische Plugin-Elemente. Definieren Sie das Kontextmenüelement (context menu item), das angezeigt wird, wenn Sie mit der rechten Maustaste auf Audio- oder Videodateien klicken:
export const contextMenuItem: IContextMenuItem = {
key: "speech-to-text-context-menu-item",
label: "Convert to text",
icon: "speech-to-text-16.png",
onClick: assemblyAI.speechToText,
fileType: [FilesType.video],
withActiveItem: true,
}
Sie können weitere Plugin-Typen hinzufügen. Beispielsweise kann das Plugin draw\.io über das Hauptmenü aufgerufen werden. Daher müssen wir das Hauptelement der Schaltfläche (main button item) angeben:
const mainButtonItem: IMainButtonItem = {
key: "draw-io-main-button-item",
label: "Draw.io",
icon: "drawio.png",
onClick: (id: number) => {
drawIo.setCurrentFolderId(id)
const message: IMessage = {
actions: [Actions.showCreateDialogModal],
createDialogProps: {
title: "Create diagram",
startValue: "New diagram",
visible: true,
isCreateDialog: true,
extension: ".drawio",
onSave: async (e: any, value: string) => {
await drawIo.createNewFile(value)
},
onCancel: (e: any) => {
drawIo.setCurrentFolderId(null)
},
onClose: (e: any) => {
drawIo.setCurrentFolderId(null)
},
},
}
return message
},
// items: [createItem],
}
Wenn Sie auf das Hauptschaltflächenelement klicken, wird das modale Fenster angezeigt, in dem Sie den Namen des Diagramms eingeben und eine leere .drawio-Datei öffnen können.
Für das draw\.io-Plugin müssen Sie außerdem den Datei-Plugin-Typ konfigurieren, der beim Öffnen der jeweiligen .drawio-Datei aktiviert wird:
Definieren Sie das Dateielement (file item), das als Datei mit der entsprechenden Erweiterung (.drawio) und dem entsprechenden Symbol dargestellt wird:
export const drawIoItem: IFileItem = {
extension: ".drawio",
fileTypeName: "Diagram",
fileRowIcon: "drawio-32.svg",
fileTileIcon: "drawio-32.svg",
devices: [Devices.desktop],
onClick,
}
Definieren Sie das onClick-Ereignis, das die Methode editDiagram jedes Mal ausführt, wenn die .drawio-Datei geöffnet wird:
const onClick = async (item: File) => {
return await drawIo.editDiagram(item.id)
}
Schritt 6. Plugin-Typ für Einstellungen erstellen
Konfigurieren Sie den Plugin-Typ für Einstellungen, um Benutzern die Administratoreinstellungen zur Verfügung zu stellen.
Erstellen Sie einen Container für die Plugin-Einstellungen:
const descriptionText: TextGroup = {
component: Components.text,
props: {
text: "To generate API token visit https://www.assemblyai.com",
color: "#A3A9AE",
fontSize: "12px",
fontWeight: 400,
lineHeight: "16px",
},
}
const descGroup: BoxGroup = {
component: Components.box,
props: {children: [descriptionText]},
}
const parentBox: IBox = {
displayProp: "flex",
flexDirection: "column",
// marginProp: "16px 0 0 0",
children: [tokenGroup, descGroup],
}
Geben Sie in der Einstellungsbeschreibung an, dass für die Nutzung des Plugins ein API-Token generiert werden muss.
Konfigurieren Sie die Administratoreinstellungen mit dem Objekt ISettings:
const adminSettings: ISettings = {
settings: parentBox,
saveButton: userButtonComponent,
onLoad: async () => {
assemblyAI.fetchAPIToken()
tokenInput.value = assemblyAI.apiToken
if (!assemblyAI.apiToken) {
return {
settings: parentBox,
}
}
plugin.setAdminPluginSettings(adminSettings)
return {settings: parentBox}
}
Geben Sie das onLoad-Ereignis an, das definiert, welche Plugin-Einstellungen beim Laden des Einstellungsblocks angezeigt werden.
Jedes Einstellungselement wird in separaten Dateien (Schaltflächen, Token) festgelegt.
Schritt 7. Haupt-Plugin-Codedatei erstellen
Erstellen Sie im Ordner src eine Datei mit dem Haupt-Plugin-Code. Diese Datei ist erforderlich. Informationen zum Schreiben dieses Codes finden Sie in der Dokumentation eines Drittanbieterdienstes.
Sehen wir uns an, wie die Datei AssemblyAI.ts im Detail aufgebaut ist:
Definieren Sie die AssemblyAI-Klasse mit allen erforderlichen Variablen und Methoden:
- Variablen und ihre Beschreibung:
apiURL
Definiert die API-URL.
apiURL = ""
currentFileId
Definiert die aktuelle Datei-ID.
const currentFileId: numbernull | number = null
apiToken
Definiert das API-Token.
apiToken = ""
- Methoden und ihre Beschreibung
createAPIUrl
Erstellt die API-URL.
createAPIUrl = () => {
const api = plugin.getAPI()
this.apiURL = api.origin.replace(/\/+$/, "")
const params = [api.proxy, api.prefix]
if (this.apiURL) {
for (const part of params) {
if (!part) {
continue
}
const newPart = part.trim().replace(/^\/+/, "")
if (newPart) {
if (this.apiURL.length !== 0 && this.apiURL[this.apiURL.length - 1] === "/") {
this.apiURL += newPart
} else {
this.apiURL += `/${newPart}`
}
}
}
}
}
setAPIUrl
Legt die API-URL fest.
setAPIUrl = (url: string) => {
this.apiURL = url
}
getAPIUrl
Gibt die API-URL zurück.
getAPIUrl = () => {
return this.apiURL
}
setAPIToken
Legt das API-Token fest.
setAPIToken = (apiToken: string) => {
this.apiToken = apiToken
}
getAPIToken
Gibt das API-Token zurück.
getAPIToken = () => {
return this.apiToken
}
fetchAPIToken
Holt das API-Token.
fetchAPIToken = async () => {
const apiToken = localStorage.getItem("speech-to-text-api-token")
if (!apiToken) {
return
}
this.setAPIToken(apiToken)
plugin.updateStatus(PluginStatus.active)
}
saveAPIToken
Speichert das API-Token.
saveAPIToken = (apiToken: string) => {
localStorage.setItem("speech-to-text-api-token", apiToken)
let status
if (apiToken) {
status = PluginStatus.active
} else {
status = PluginStatus.hide
}
plugin.updateStatus(status)
}
setCurrentFileId
Legt die ID auf die aktuelle Datei fest.
setCurrentFileId = (id: number | null) => {
this.currentFileId = id
}
uploadFile
Lädt eine Datei hoch, die transkribiert wird.
uploadFile = async (apiToken: string, path: string, data: Blob) => {
console.log(`Uploading file: ${path}`)
const url = "https://api.assemblyai.com/v2/upload"
try {
const response = await fetch(url, {
method: "POST",
body: data,
headers: {
"Content-Type": "application/octet-stream",
"Authorization": apiToken,
},
})
if (response.status === 200) {
const responseData = await response.json()
return responseData["upload_url"]
}
console.error(`Error: ${response.status} - ${response.statusText}`)
return null
} catch (error) {
console.error(`Error: ${error}`)
return null
}
}
transcribeAudio
Transkribiert die Audiodatei.
transcribeAudio = async (apiToken: string, audioUrl: string) => {
console.log("Transcribing audio... This might take a moment.")
const headers = {
"authorization": apiToken,
"content-type": "application/json",
}
const response = await fetch("https://api.assemblyai.com/v2/transcript", {
method: "POST",
body: JSON.stringify({audioUrl}),
headers,
})
const responseData = await response.json()
const transcriptId = responseData.id
const pollingEndpoint = `https://api.assemblyai.com/v2/transcript/${transcriptId}`
while (true) {
const pollingResponse = await fetch(pollingEndpoint, {headers})
const transcriptionResult = await pollingResponse.json()
if (transcriptionResult.status === "completed") {
return transcriptionResult
} else if (transcriptionResult.status === "error") {
throw new Error(`Transcription failed: ${transcriptionResult.error}`)
} else {
await new Promise((resolve) => {
setTimeout(resolve, 3000)
})
}
}
}
speechToText
Implementiert die Plugin-Funktionalität.
speechToText = async (id: number) => {
if (!this.apiToken) {
return
}
this.setCurrentFileId(null)
if (!this.apiURL) {
this.createAPIUrl()
}
const response = await fetch(`${this.apiURL}/files/file/${id}`)
const data = await response.json()
const {viewUrl, title, folderId, fileExst} = data.response
const file = await fetch(viewUrl)
const fileBlob = await file.blob()
const uploadUrl = await this.uploadFile(this.apiToken, viewUrl, fileBlob)
const transcript = await this.transcribeAudio(this.apiToken, uploadUrl)
const blob = new Blob([transcript.text], {
type: "text/plain;charset=UTF-8",
})
const newFile = new File([blob], "blob", {
type: "",
lastModified: Date.now(),
})
const formData = new FormData()
formData.append("file", newFile)
const newTitle = `${title.replaceAll(fileExst, "")} text`
try {
const sessionRes = await fetch(
`${this.apiURL}/files/${folderId}/upload/create_session`,
{
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify({
createOn: new Date(),
fileName: `${newTitle}.txt`,
fileSize: newFile.size,
relativePath: "",
}),
},
)
const response = await sessionRes.json()
const sessionData = response.response.data
const data = await fetch(`${sessionData.location}`, {
method: "POST",
body: formData,
})
const jsonData = await data.json()
const {id: fileId} = jsonData.data
return fileId
} catch (e) {
console.log(e)
}
return {
actions: [Actions.showToast],
toastProps: [{type: ToastType.success, title: ""}],
} as IMessage
}
Deklarieren Sie die AssemblyAI-Klasseninstanz:
const assemblyAI = new AssemblyAI()
Exportieren Sie die erstellte Plugin-Instanz:
export default assemblyAI
Testen
Um die Funktionalität des Plugins zu überprüfen und mögliche Fehler zu beheben, testen Sie das Plugin:
- Erstellen Sie das vorbereitete Plugin gemäß den Anweisungen hier.
Der Ordner dist wird im Stammordner des Plugins erstellt und das Plugin-Archiv darin abgelegt. Dieses Archiv enthält das fertige Plugin, das in das DocSpace-Portal hochgeladen werden kann.
- Laden Sie Ihr Plugin in das DocSpace-Portal hoch und testen Sie dessen Aussehen und Funktionalität gründlich.
Hinweis: Sie können Ihre eigenen Plugins nur in der Server-Version von DocSpace hochladen.
Sollten Fehler auftreten, korrigieren Sie den Quellcode Ihres Plugins und wiederholen Sie den Erstellungs- und Testvorgang.
Nachdem Ihr Plugin getestet wurde und ordnungsgemäß funktioniert, können Sie es zur DocSpace-Serverversion hinzufügen und verwenden.
Das DocSpace-Plugin bietet einen leistungsstarken und benutzerfreundlichen Ansatz für Dokumentenverwaltung und Zusammenarbeit. Durch die Integration in die bevorzugten Plattformen der Nutzer beseitigt es häufige Hindernisse und verbessert die Produktivität in verschiedenen Arbeitsabläufen. Bei Fragen zu DocSpace-Plugins wenden Sie sich gerne an unsere Entwickler im ONLYOFFICE-Forum (Registrierung erforderlich). Sie können auch eine Funktion anfordern oder einen Fehler melden, indem Sie ein Problem auf GitHub posten oder Ihre DocSpace-Plugins mit uns und anderen Nutzern teilen. Viel Erfolg bei Ihren Erkundungsbemühungen!
Erstellen Sie Ihr kostenloses ONLYOFFICE-Konto
Öffnen und bearbeiten Sie gemeinsam Dokumente, Tabellen, Folien, Formulare und PDF-Dateien online.