am Beispiel von
Bachelorarbeit
Jonas Thelemann
20.01.2022
Code
Dritter
Design
+
2014
2016
2018
2020
2022
Gründung NAHhaft
Idee
Antragsphase
Gründung, Beta
Logistik-Marktplatz
Dashboard
Betriebsprofil
Marktplatz
Frontend
React
Webkomponenten
Webkomponenten
Stencil
Webkomponenten
Stencil
Bit
Webkomponenten
Stencil
Bit
const nearbuyPluginMuesliIndex: NearbuyPluginOptions = {
id: "muesli-index",
name: {
de: "Muesli-Index", en: "Muesli Index"
},
description: {
en: "Calculates the 'Muesli index', representing the availability of ingredients
required for a yummy muesli. Requests for missing ingredients can be added
with one click."
},
version: packageJson.version,
versionNearbuyCompatibility: packageJson.peerDependencies.nearbuy,
url: new URL("http://localhost:3001"),
iconPngBase64: "iVBORw0KGgoAAAA...",
entryPoints: {
dashboard: [{
dashlet: [{
contentUrl: "https://nearbuy_muesli-index.jonas-thelemann.de/",
}],
}],
plugin: {
contentUrl: "http://localhost:3001/",
},
},
}
1/2 Konfiguration von Keycloak
2/2 Erweiterung der Anfragevalidierung im Backend
val userinfo = parseUserinfo(String(Base64.getDecoder().decode(xUserinfoEncoded)))
this.scopes.addAll(userinfo.scope.split(" "))
val annotationScope =
"${annotation.clazz.name.lowercase()}-${annotation.action.name.lowercase()}"
if (!(requestContext.securityContext as NearbuySecurityContext).hasScope(annotationScope)) {
abort(requestContext)
}
@Allowed(READ, COMPANY, "{companyId}")
<Button
onClick={(): void => this.props.
onClose()}
/>
<Button
onClick={(): void => this.saveOffer()}
color="primary"
variant="contained"
disabled={...}
/>
<NbButton
onNbButtonEvent={(): void =>
this.props.onClose()
}
secondary
/>
<NbButton
onNbButtonEvent={(): void =>
this.saveOffer()
}
disabled={...}
/>
React
Einbindung in Webanwendungen
Buttons
import { applyPolyfills, defineCustomElements }
from "@dargmuesli/nearbuy-web-components/loader"
Vue.config.ignoredElements = [[/nb-\w+/]
applyPolyfills().then(() => {
defineCustomElements()
})
{
hydratePath: ’@dargmuesli/nearbuy-web-components/hydrate’,
lib: ’@dargmuesli/nearbuy-web-components’,
loaderPath: ’@dargmuesli/nearbuy-web-components/loader’,
prefix: ’nb-’,
},
Vue
Nuxt
Einbindung in Webanwendungen
@Prop() secondary: boolean = false;
@Prop() disabled: boolean = false;
@Prop({ attribute: ’first-last’ }) name: Name = {
first: ’Max’,
last: ’Mustermann’
};
@Event() nbButtonEvent: EventEmitter<string>;
render() {
return <button
class={[
"font-medium leading-7 px-4 py-1 rounded-full text-sm uppercase",
...(this.secondary ? ["nb-secondary"] : []),
...(this.disabled ? ["nb-disabled"] : [])
].join(’ ’)}
onClick={() => this.nbButtonEvent.emit(this.getText())}
part="nb-button"
type="button"
>
<slot>{this.getText()}</slot>
</button>;
}
Erzeugung mit Stencil
Plug-in-Marktplatz
Visualisierung im Frontend
Plug-in-Oberfläche
Visualisierung im Frontend
button {
background-color: var(--primary-color, #92BE9B);
font-family: ’Quicksand’, sans-serif;
@apply font-bold shadow-md text-white;
}
body.theme-muesli-index nb-button[secondary]::part(nb-button):hover {
background-color: rgba(72 111 80 / 4%);
}
CSS Custom Property
CSS Shadow Parts
Semantic
Semantic
Periodic
Semantic
Periodic
Deprecation
https://api.nearbuy-food.de/v1/public/companies
Istio
Istio
Flagger
Istio
Flagger
OPA
✅
✅
✅
✅
✅
Quarkus
Frontend
React
Backend
Quarkus
Frontend
React
Backend
Kubernetes
Orchestrierung
Persistenz im Backend
CREATE TABLE plugin_installation (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
plugin_id TEXT NOT NULL,
owner_person UUID REFERENCES person ON DELETE CASCADE,
owner_company UUID REFERENCES company ON DELETE CASCADE,
date_installed TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
UNIQUE (plugin_id, owner_person),
UNIQUE (plugin_id, owner_company),
CONSTRAINT either_person_or_company CHECK (num_nonnulls(owner_person, owner_company) = 1)
)
PostgreSQL