SCM-Manager – Frontend und Release für mein erstes Plugin
Im ersten Teil dieser Serie haben wir erklärt, warum und wie Plugins verwendet werden können, um die Grundfunktionalität des SCM-Managers zu erweitern, wie die grundlegende Architektur aussieht und wie Sie selbst entwickelte Plugins mit der Community teilen können. Im zweiten Teil haben wir das Backend für ein Plugin entwickelt. In diesem Teil zeigen wir Ihnen, wie Sie das Frontend erstellen, es mit dem Backend verbinden und das Plugin veröffentlichen.
Wir beginnen mit dem Frontend
Das SCM-Manager-Frontend ist in React mit Typescript-Unterstützung geschrieben. Wir verwenden auch Bibliotheken/Frameworks wie Bulma für das Styling und React Query für die Datensynchronisation. Das Ziel für unser Plugin ist es, die benutzerdefinierten Links global für den SCM-Manager zu konfigurieren und sie in der Fußzeile anzuzeigen.
Globale Konfiguration
Um die globale Konfiguration für die Links zu erstellen, fügen wir zunächst eine eigene Konfigurationsseite in den Administrationsbereich ein.
Dazu erstellen wir eine neue React-Komponente. Mit useState
halten wir die Daten unserer Eingabefelder fest. Mit benutzerdefinierten React-Hooks, die auf React Query basieren, können wir unsere Daten vom Server laden und unsere Anfragen wegschicken.
Ein großer Vorteil von React Query ist die stale while revalidate
-Prozedur, die zu einer Minimierung von Loading Spinners führt. Dies wird über Frontend-Caches realisiert, die nur dann Daten austauschen, wenn neue Daten eingetroffen sind. Die benutzerdefinierten Hooks verwalten die Ladezustände für uns. Wir verwenden lediglich ein boolesches Flag, um zu prüfen, ob die Daten fertig geladen sind.
Wenn Fehler auftauchen, zeigen wir diese in unserem Error Boundary in der UI an.
Wichtig: Sie müssen Ihre benötigten Komponenten nicht von Grund auf neu erstellen. Wir empfehlen die Verwendung der vom SCM-Manager bereitgestellten Komponenten und apis.
Aufbau
Wir werden eine Übersicht für unsere Konfiguration erstellen, die aus zwei Teilen besteht:
- Einer Tabelle mit allen erstellten Custom Links.
- Einem kleinen Formular zum Erstellen/Aktualisieren von benutzerdefinierten Links.
Unsere Tabelle besteht aus einer <Table/>
Komponente, die wir aus den UI-Komponenten des SCM-Managers erhalten.
Dann fügen wir einige Spalten hinzu, um unsere Daten und Funktionen anzuzeigen.
Direkt in die Tabelle tragen wir dann die Daten unserer Custom Links ein, die vom Server kommen.
Wenn noch keine Links angelegt wurden und die Tabelle leer ist, zeigen wir eine entsprechende Information an.
const CustomLinksTable: FC<{ customLinks: CustomLink[] }> = ({ customLinks }) => {
const [t] = useTranslation("plugins");
const { deleteLink, error: deleteError } = useDeleteCustomLink();
return (
<>
<Table data={customLinks} emptyMessage={t("scm-custom-links-plugin.form.table.empty")}>
<TextColumn header={t("scm-custom-links-plugin.form.table.name")} dataKey="name" />
<TextColumn header={t("scm-custom-links-plugin.form.table.url")} dataKey="url" />
<Column header={t("")}>
{(row: any) => (
<Icon
name="trash"
onClick={() => deleteLink((row._links.delete as Link).href)}
title={t("scm-custom-links-plugin.form.table.deleteLink")}
/>
)}
</Column>
</Table>
<ErrorNotification error={deleteError} />
</>
);
};
Übersetzungen und Styling
Nachdem wir unsere Konfigurationsseite strukturell aufgebaut haben, brauchen wir noch die Übersetzungen unserer Texte und den letzten Schliff mit CSS. Für die Übersetzungen verwenden wir I18Next von React und pflegen unsere Übersetzungen in einer JSON-Datei pro Sprache.
Das CSS kann mit verschiedenen Ansätzen gestylt werden. Wir bevorzugen Bulma als CSS-Framework und für spezielle Fälle verwenden wir gerne gestylte Komponenten. In unserem Fall sehen die Komponenten bereits gut aus und müssen nur noch harmonisch positioniert werden. Hierfür verwenden wir die Hilfsklassen von Bulma. Nun sollte unsere Konfigurationsseite gut aussehen und unsere funktionalen Anforderungen erfüllen.
Binden der Konfigurationsseite
Nachdem wir unsere Konfigurationsseite erstellt haben, müssen wir sie noch in die Verwaltungsnavigation integrieren. Dies geschieht mithilfe des Konfigurationsbinders aus ui-components
. Dieser Binder wurde speziell dafür entwickelt React-Komponenten als neue Konfigurationseinträge hinzuzufügen, in unserem Fall in die globale Administrationsnavigation, und auch um die Route zu binden.
Beispiel:
import { ConfigurationBinder as configurationBinder } from "@scm-manager/ui-components";
import GlobalConfig from "./GlobalConfig";
configurationBinder.bindGlobal(
"/custom-links", // the link where our new config page will be available
"scm-custom-links-plugin.settings.navLink", // the translation key for the navigation entry which must be translated in the plugins.json files
"customLinksConfig", // the linkname inside the index. If any user does not have this link (not permitted), this page will not be accessible to them.
GlobalConfig // our React component we want to render
);
Jetzt können wir bereits über die Benutzeroberfläche auf die Konfigurationsseite zugreifen und unsere benutzerdefinierten Links dort verwalten.
Erweiterungspunkte
Nachdem wir einige benutzerdefinierte Links hinzugefügt haben, möchten wir sie auch in der Fußzeile sehen.
Dazu müssen wir einen Custom-Links-Renderer erstellen,
der sie einfach vom Server anfordert und eine Linkliste rendert. Dieser Renderer muss nun in der Fußzeile verwendet werden, damit unsere Links dort erreicht werden können.
Für diesen Fall müssen wir unseren Renderer als Erweiterung gegen den passenden Erweiterungspunkt im Footer binden. Da die benutzerdefinierten Links in der Spalte “Information” angezeigt werden sollen, müssen wir den Erweiterungspunkt footer.information
benutzen.
const CustomLinksRenderer: FC<Props> = ({ links }) => {
const { data, isLoading } = useCustomLinks((links.customLinks as Link).href);
if (isLoading) {
return null;
}
return (
<>
{(data?._embedded?.customLinks as CustomLink[]).map(cl => (
<li>
<a href={cl.url} target="_blank">
{cl.name}
</a>
</li>
))}
</>
);
};
Der CustomLinkRenderer benutzt einen React Hook, welcher die Daten abruft und mithilfe von ReactQuery in unseren Frontend-Cache schreibt.
export const useCustomLinks = (link: string) => {
const { error, isLoading, data } = useQuery<HalRepresentation, Error>("custom-links", () =>
apiClient.get(link).then(res => res.json())
);
return {
error,
isLoading,
data
};
};
Anmerkungen:
- Sollte es derzeit keinen oder nicht den richtigen Erweiterungspunkt für Ihr Plugin geben, kontaktieren Sie bitte das SCM-Manager Team.
- Erweiterungspunkte sollten immer in der index.tsx Ihres Plugins eingebunden werden.
- Unser Beispiel ist recht einfach. Erweiterungspunkte können auch Props für alle gebundenen Erweiterungen bereitstellen, die Erweiterungen nach Name und Priorität sortieren oder über eine Prädikatsfunktion deaktiviert werden.
Beispiel:
import { binder } from "@scm-manager/ui-extensions";
import CustomLinksRenderer from "./CustomLinksRenderer";
binder.bind("footer.information", CustomLinksRenderer)
Wir können die benutzerdefinierten Links in unserer Fußzeile sehen und sobald ein Link geändert wird, wird die Fußzeile sofort aktualisiert.
Wie kann ich mein Plugin veröffentlichen?
Die erste Iteration des Plugins ist fertig. Es funktioniert wie erwartet und kann verwendet werden. Nun ist es Ihre Entscheidung ob Sie es für sich behalten wollen oder, wenn Sie denken, dass es anderen Mitgliedern der Community helfen könnte, es mit der Community teilen. Um es mit der Community zu teilen müssen Sie lediglich den Code Ihres Plugins auf einer öffentlichen Instanz wie GitHub bereitstellen und anschließend das SCM-Manager-Team kontaktieren. Wir werden dann Ihr Plugin reviewen und es in die SCM-Manager GitHub-Organisation einbinden. Sobald dies geschehen ist, werden wir es im offiziellen SCM-Manager Plugin Center veröffentlichen.
Abschließende Worte
Wir hoffen, wir konnten Ihnen einen Einblick in die Entwicklung von Plugins für den SCM-Manager geben. Dies war ein recht einfaches Beispiel, um Ihnen zu zeigen, wie ein Plugin aussehen kann. Wir haben bereits viel größere und komplexere Plugins, die Sie sich in der SCM-Manager GitHub Organisation ansehen können.
Wenn Sie sich noch nicht sicher sind, ob Sie ein eigenes Plugin erstellen können oder wie Sie Ihren Anwendungsfall am besten realisieren, kontaktieren Sie das SCM-Manager Team. Unsere Entwickler und UX-Spezialisten unterstützen Sie gerne bei der Entwicklung.
SCM-Manager
Der einfachste Weg Ihre Git-, Mercurial- and Subversion-Repositories zu teilen und zu verwalten.
Jetzt kennenlernen