Van statisch naar dynamisch, een tools page verhaal

Na een 5-jarig bestaan van de interne JIDOKA Tools-pagina werd het tijd om deze eens in een nieuw jasje te steken. De Tools-pagina werd uitgewerkt om een verzamelplaats te maken voor alle tools die we binnen JIDOKA gebruiken. Tools zoals onze interne CV app, timesheet apps, Jira, Confluence enzovoort krijgen een plaatsje binnen deze pagina. In het begin viel de lay-out tamelijk mee aangezien we nog niet veel tools gebruikten, maar in de loop van de jaren werd deze pagina verder uitgebreid met nieuwe tools, waardoor het overzicht wat verloren ging. Het doel van deze redesign is dat we naar de toekomst toe heel flexibel en gemakkelijk nieuwe tools kunnen toevoegen / verwijderen zonder al te veel aan deze pagina aan te passen.

Tijd voor een makeover

Naast het verloren overzicht was het design volledig outdated, en zelfs niet responsief op mobiele toestellen. Hier moest dringend verandering in komen zodat onze collega’s op hun smartphone gemakkelijk een interne tool kunnen terugvinden.

Het nieuw design moest fris, flexibel en binnen de huisstijl van JIDOKA passen. Dat laatste was op zich geen probleem omdat we al verschillende interne tools in een JIDOKA jasje gestoken hebben. Waar we rekening mee moesten houden binnen het design, was dat de data vanuit een andere plaats opgehaald werd. Zo konden we niet te veel custom aanpassingen uitvoeren aan bepaalde elementen, zoals bijvoorbeeld het vergroten/verkleinen van een logo, het aanpassen van teksten in font-size enz. Belangrijk was dus om één bepaalde styling door te trekken naar elk element.

De keuze was uiteindelijk simpel: een flexibel grid systeem waarbij elk element dezelfde styling moest hebben, ongeacht de grootte van het logo of de lengte van de naam van de tool. Bij het voorbeeld hieronder werd er bijvoorbeeld al rekening gehouden om user details op te halen via Keycloak, tools te verdelen per categorie en filters toe te passen.

Voorbeeld design

Het nieuw jasje aankleden

Uiteindelijk hebben we wat toegevingen moeten doen en hebben we de tools pagina gefaseerd geüpdatet. Tijdens de eerste fase hebben we ervoor gezorgd dat we alle tools eenvoudig en flexibel kunnen tonen op de pagina. De onderverdeling in categorieën en filters lieten we nog even achterwege.

Op het vlak van uitwerking hebben we de bestaande infrastructuur hergebruikt. Het was niet meteen nodig om er een frontend framework tegenaan te gooien voor een onepager. In dit geval werd er opnieuw een statische html pagina uitgewerkt, maar grondig opgeschoond. 

Een neat trick voor het uitwerken van een CSS grid zonder dat je mediaqueries moet toevoegen om het aantal columns te bepalen per breakpoint, is om binnen je grid-template-colums te spelen met auto-fill.

.tools {
 &__container {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(245px, 1fr));
   grid-gap: 20px;
 }
}

Door minmax(245px, 1fr) toe te voegen zal je CSS grid ervoor zorgen dat er automatisch columns gegenereerd worden, zolang er minstens 245px plaats is om een column toe te voegen. De auto-fill attribuut zal ervoor zorgen dat de volledige container aangevuld wordt  met columns zolang er voldoende plaats is. Zo heb je in feite met één lijn code meteen een responsive grid systeem gemaakt zonder dat je specifieke breakpoint moet invullen. Op mobile zal je bijvoorbeeld maar één column zien met alle tools onder elkaar.

Voorbeeld frontend oplossing

Tenslotte werd er een eenvoudige search functie geschreven. Omdat er steeds nieuwe tools toegevoegd zullen worden, wordt het wat moeilijker om je tool zo binnen de pagina terug te vinden. Omdat er achterliggend ook een beschrijving van de tool meegegeven wordt (maar niet getoond wordt), kan je met de search field zowel achter de naam als beschrijving zoeken. 

searchField.addEventListener('keyup', (e) => {
   const searchString = e.target.value.toLowerCase();
 
   const filteredTools = tools.filter((tool) => {
       return (
           tool.name.toLowerCase().includes(searchString) ||
           tool.description.toLowerCase().includes(searchString)
       );
   });
   displayTools(filteredTools);
});

const displayTools = (tools) => {
   toolsContainer.innerHTML = tools
       .map((tool) => {
           return `
           <a href="${tool.link}" class="tools__block">
               <div style="background: ${displayColor(tool.category)}" class="tools__image">
                   <img src="assets/images/${tool.name.split(" ").join("-").toLowerCase()}.png" alt="${tool.name} logo" class="tools__logo">
               </div>
               <div class="tools__name">
                   ${tool.name}
               </div>
           </a>
       `;
       })
       .join('');
};

Behind the scenes

Het idee achter de vernieuwing van de Tools-pagina was om niet alleen de verouderde frontend een nieuwe look te geven, maar ook om alles wat achter de schermen draait te verbeteren. We hebben van de gelegenheid gebruik gemaakt om gebieden als beveiliging, efficiëntie en stabiliteit van de app een boost te geven. Een deel van die verbeteringen komen van het feit dat de app nu gehost wordt op een Kubernetes-cluster. De redenering achter deze stap is om gebruik te maken van de reeds geconfigureerde oplossingen voor monitoring, logging en security.

KISS

Toen we een solide omgeving gevonden hadden, waarin de tool kon opereren, moesten we nog steeds de interne werking van de Tools-pagina uitvinden. Dit waren de vereisten waarmee we rekening moesten houden:

  • De uiteindelijke oplossing moet lichtgewicht zijn
  • Mag alleen de benodigde dependencies bevatten
  • Zorg voor zo min mogelijk technische beperkingen
  • KISS

De gemiddelde ontwikkelaar die dit leest, kan alleen maar dromen van deze vereisten. Wees gerust, deze bestaan ​​in feite in werkelijkheid. Uitgaande van deze aanwijzingen zijn we begonnen met het onderzoeken van een oplossing om de gegevens van de Tools-pagina op te slaan. Storage persistence was van hoog belang en als we een bestaande setup konden hergebruiken, zou dat nog meer bonuspunten opleveren. We kwamen Quickbase tegen. Waarschijnlijk niet de meest sexy oplossing die er is, maar het bevat wel alles wat we nodig hebben. Een low-level applicatieplatform dat een eenvoudige relationele database aanbiedt, klaar voor gebruik. We hebben snel een duidelijke structuur voor de tool data gedefinieerd en binnen enkele minuten hadden we een gegevensbron die klaar was om te testen.

Gravitee uitgelegd, soort van …

Omdat de gegevens in Quickbase niet vaak opgevraagd moeten worden, hebben we ervoor gekozen om de app zo te ontwikkelen dat deze een API-call naar Quickbase uitvoert om de benodigde gegevens op te halen. Naderhand worden deze gegevens gebruikt om de juiste toolselectie in de frontend te genereren. Deze aanpak zorgde ervoor dat we enkele vragen begonnen te stellen over security. Hier komt Gravitee aan te pas. Gravitee is een open-source API-beheerplatform dat een groot aantal functies bevat om API’s te beveiligen en te publiceren. Sommige van onze andere interne JIDOKA-tools maken gebruik van Gravitee, dus we wisten al het een en ander over het integreren ervan in onze huidige setup. Een cruciaal onderdeel van interactie met de Quickbase API, is het doorgeven van 2 specifieke headers. Een daarvan is de Quickbase Realm Hostname-header, terwijl de andere de Authorization-header is die een Quickbase User-token bevat.

Deze gegevens zijn vrij gevoelig, dus met het gebruik van een Gravitee API-beleid hebben we een structuur gedefinieerd die deze headers op requests aan de Gravitee API, toevoegt en doorgeeft aan de Quickbase API.

Nadat alles was ingesteld, hebben we de flow van het Quickbase-request gewijzigd om een ​​kleine omweg te maken via Gravitee en eureka! We hebben goud gevonden, we kregen een response van Quickbase met alle tools die we eerder hadden gedefinieerd, alleen de structuur van de reactie was op zijn zachtst gezegd rommelig.

Voorbeeld JSON array

Het extraheren van de benodigde tool data uit deze JSON zou een beetje pijnlijk zijn, gelukkig kon Gravitee ons hier ook helpen. Door het JSON naar JSON-transformatiebeleid op de Quickbase-response te gebruiken, konden we de JSON naar onze wens vormen met behulp van de JOLT-library. Een snelle lezing van de documentatie in combinatie met wat sleutelen, resulteerde in een JOLT-specificatie die onze rommelige response zou omvormen tot een prachtige JSON-array.

Voorbeeld verbeterde JSON array

Je zou denken dat we hier het eindspel hebben bereikt, maar we hebben besloten om nog een stap verder te gaan.

Hier bij JIDOKA houden wij van automatisering. We zijn er zo dol op dat zelfs de naam JIDOKA “Automatisering met een menselijke touch” betekent. Dit project kon niet worden uitgebracht zonder enige automatisering in het spel, toch?

If you like pina coladas

Het toevoegen of bewerken van bestaande tools in Quickbase werd al snel een beetje vervelend. Er moest iets zijn dat we konden gebruiken om onze tool data dynamisch te synchroniseren met Quickbase. Toen trof het ons, de meeste van onze tools draaien op Kubernetes. Als we een oplossing konden vinden om de bestaande tool data uit Kubernetes te extraheren en deze om te zetten in een Quickbase-query request, zouden we de tool data automatisch met Quickbase kunnen synchroniseren. Het enige wat nog resteerde, was om achterover te leunen en alles te zien ontvouwen terwijl we nipten aan piña colada’s.

Na wat Groovy & Kubectl-magie, zijn we erin geslaagd om enkele Jenkins jobs op te zetten om een ​​tool toe te voegen, een tool te verwijderen en alle tools te synchroniseren met Quickbase. Kubectl wordt achter de schermen gebruikt om tool data zoals namen, beschrijvingen en categorieën te extraheren. Deze tool gegevens worden opgeslagen met behulp van annotaties en labels op bestaande Kubernetes-deployments.

Tool gegevens worden opgeslagen met behulp van annotaties en labels op bestaande Kubernetes-deployments

De tool gegevens werden vervolgens gebruikt om een ​​query request naar Quickbase op te stellen om de tools indien nodig te “upserten”. Dezelfde logica werd gebruikt om een tool toe te voegen en te verwijderen, alleen haalden we hier de gegevens op van de Jenkins-parameters die de gebruiker opgaf en stuurden we daarna de juiste query request.

Dit project leek op het eerste gezicht misschien vrij eenvoudig, maar het bleek een avontuur op zich te zijn. De verschillende oplossingen en tweaks dwongen ons om onze verbeeldingskracht tot zijn limieten te testen, maar het resulteerde uiteindelijk in een interessante kleine tool.

Wat brengt de toekomst?

Zoals eerder vermeld, werken we deze tools pagina in fases uit. Eén van de volgende stappen is om onze interne Keycloak aan deze pagina te koppelen. Hierdoor worden alle tools afgeschermd achter onze persoonlijke login, en kan je makkelijker binnen een tool inloggen aangezien je eerder ingelogd bent bij het betreden van deze pagina. 

Ten slotte zullen we bekijken of deze pagina in een Electron-app omgezet kan worden. Zo heeft iedere medewerker een desktop app waarmee ze meteen toegang hebben tot elke tool! 

Later meer!

Event sourcing in een legacy systeem – Deel 1 – Context is koning

Lees meer
event-sourcing background

Lancering van een gloednieuwe website

Lees meer
Launching a Brand-New Website

Pardon? Een PWA?

Lees meer