Textnachrichten
Textnachrichten ermöglichen einen simplen Chat - dies ist eher ein PoC und die Basis für weitere, unterrichtsrelevante Interaktionsmöglichkeiten.
<DynamicDocumentRoots id="732a4df4-26b0-4809-a71b-70d20ccd21a8" />
Technischer Hintergrund
Die DocumentRoot
wird verwendet, um in MDX-Dokumenten bspw. Antworten User-Basiert abzuspeichern - es ist das Elternelement für alle Antworten und jede User:in kann dann ein eigenes Document
hinzufügen. Über die DocumentRoot
werden auch die Berechtigungen festgelegt.
Für interaktive Anwendung (wie einen (Gruppen)-Chat), die nicht ganze Klassen betreffen, braucht es dynamisch generierte DocumentRoots
. Um diese dynamischen DocumentRoots
wiederzufinden, wird ein Dokument DynamicDocumentRoots
erzeugt und in diesem die DocumentRoots
abgespeichert. Das mentale Modell dazu: Es werden Räume erzeugt, die von einer DocumentRoot
verwaltet werden, die Raum-Logik entspricht dann jedoch direkt der DocumentRoot
-Logik. Dadurch funktionieren sowohl "Live-Änderungen" wie auch die Berechtigungen.
Jeder Raum hat einen Namen und eine Raum-Typ (bspw. für den Chat ist dies text_messages
).
Ein mögliches Beispiel für die Struktur der Daten des DynamicDocumentRoots
:
{
"documentRoots": [
{
"id": "dbc4e980-51d9-4036-b8f5-c26d07fa6dd9",
"name": "FooBar",
"type": "text_messages"
},
{
"id": "c35f8a75-a0a7-4a82-8e7f-da53e8e4f9b4",
"name": "🧁🍰🎂",
"type": "text_messages"
}
]
}
id
- Die eindeutige ID des dynamischen
DocumentRoot
name
- Der Namen des Raums. Dieser wird bspw. im Chat angezeigt.
type
- Der Typ des Raums. Dieser bestimmt, welche Komponenten und welche Logik für den Raum verwendet wird.
Bei der Erstellung eines dynamic_document_roots
werden die Berechtigungen auf access=RO_DocumentRoot
und sharedAccess=RW_DocumentRoot
gesetzt - was vernünftige Standards sind. Allerdings kann dadurch nicht direkt ein Dokument erzeugt und hinzugefügt werden, da auch für ADmins die Berechtigungen nur RO
sind.
Lösung
Eine Admin-Gruppe muss in der API bspw. als ENV-Variable hinterlegt werden und diese Gruppe wird standardmässig zu jeder DocumentRoot
mit RW_GroupPermission
hinzugefügt.
Installation
src/plugins/plugin-dynamic-routes
src/models/DynamicDocumentRoots.ts
src/models/DynamicDocumentRoot.ts
src/components/Rooms
src/components/documents/DynamicDocumentRoots
export enum DocumentType {
/* ... */
TextMessage = 'text_message',
DynamicDocumentRoot = 'dynamic_document_root',
DynamicDocumentRoots = 'dynamic_document_roots'
}
export interface TextMessageData {
text: string;
}
export interface DynamicDocumentRootData {
/** such a document is never created - it's only the document root that is needed */
}
export enum RoomType {
Messages = 'text_messages'
}
export interface DynamicDocumentRoot {
id: string;
name: string;
type: RoomType;
}
export interface DynamicDocumentRootsData {
documentRoots: DynamicDocumentRoot[];
}
export interface TypeDataMapping {
/* ... */
[DocumentType.TextMessage]: TextMessageData;
[DocumentType.DynamicDocumentRoot]: DynamicDocumentRootData;
[DocumentType.DynamicDocumentRoots]: DynamicDocumentRootsData;
}
export interface TypeModelMapping {
/* ... */
[DocumentType.TextMessage]: TextMessage;
[DocumentType.DynamicDocumentRoot]: DynamicDocumentRootModel;
[DocumentType.DynamicDocumentRoots]: DynamicDocumentRoots;
}
export type DocumentTypes =
/* ... */
| TextMessage
| DynamicDocumentRootModel
| DynamicDocumentRoots
export function CreateDocumentModel(data: DocumentProps<DocumentType>, store: DocumentStore): DocumentTypes {
switch (data.type) {
/* ... */
case DocumentType.TextMessage:
return new TextMessage(data as DocumentProps<DocumentType.TextMessage>, store);
case DocumentType.DynamicDocumentRoot:
return new DynamicDocumentRootModel(
data as DocumentProps<DocumentType.DynamicDocumentRoot>,
store
);
case DocumentType.DynamicDocumentRoots:
return new DynamicDocumentRoots(data as DocumentProps<DocumentType.DynamicDocumentRoots>, store);
}
}
/**
* Records that should be created when a IoEvent.NEW_RECORD event is received.
*/
const RecordsToCreate = new Set<DocumentType>([DocumentType.DynamicDocumentRoots, DocumentType.TextMessage /* ... */]);
/* ... */
docusaurus.config.ts
Die Landing-Page für die Räume /rooms/<documentRootId>/<dynamicDocumentRootId>
muss im Docusaurus Router registriert werden.
import dynamicRouterPlugin, { Config as DynamicRouteConfig} from './src/plugins/plugin-dynamic-routes';
const config: Config = {
plugins: [
[
dynamicRouterPlugin,
{
routes: [
{
path: '/rooms/',
component: '@tdev-components/Rooms',
}
]
} satisfies DynamicRouteConfig
],
]
}