Skip to content

Commit 422353b

Browse files
authored
update packages guides (#137)
1 parent 94ffc13 commit 422353b

File tree

5 files changed

+261
-223
lines changed

5 files changed

+261
-223
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<p align="center">
44
<img src="./docs/images/oer-finder-plugin-logo.png" width=250 />
55
</p>
6-
An Open Educational Resources (OER) discovery system built on Nostr and built on [AMB](https://dini-ag-kim.github.io/amb/draft/), providing:
6+
An Open Educational Resources (OER) discovery system built on Nostr and built on [AMB](https://dini-ag-kim.github.io/amb/latest/), providing:
77

88
1. **Proxy Service**: Forwards search queries to configurable source adapters and returns unified OER results via a public API. Supports searching an AMB Nostr relay, Openverse, ARASAAC, RPI-Virtuell, and more through an **extendable adapter system** - add your own adapters to integrate any external API.
99
2. **Source Adapters**: Pluggable adapters for OER sources (e.g., AMB relay, ARASAAC, Openverse) that integrate seamlessly with search results. The adapter plugin system makes it easy to add new sources.

docs/client-packages-angular.md

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Using OER Finder Plugin in Angular
22

3-
This guide covers Angular-specific integration. For component properties and events, see [Client Packages](./client-packages.md).
3+
This guide covers Angular-specific integration. For component properties, events, available adapters, key types, and operating modes, see [Client Packages](./client-packages.md).
44

55
## Installation
66

@@ -14,7 +14,23 @@ For additional installation details (pnpm overrides, etc.), see [Client Packages
1414

1515
## Angular Configuration
1616

17-
Angular requires `CUSTOM_ELEMENTS_SCHEMA` to recognize web component tags:
17+
Angular requires `CUSTOM_ELEMENTS_SCHEMA` to recognize web component tags.
18+
19+
**Standalone component (Angular 14+, recommended):**
20+
21+
```typescript
22+
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
23+
24+
@Component({
25+
selector: 'app-oer-finder',
26+
standalone: true,
27+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
28+
templateUrl: './oer-finder.component.html',
29+
})
30+
export class OerFinderComponent { /* ... */ }
31+
```
32+
33+
**NgModule-based component:**
1834

1935
```typescript
2036
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@@ -26,9 +42,9 @@ import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2642
export class OerFinderModule {}
2743
```
2844

29-
## Basic Usage
45+
## Basic Usage (Server-Proxy Mode)
3046

31-
The recommended pattern is to slot `<oer-list>` and `<oer-load-more>` inside `<oer-search>`.
47+
The recommended pattern is to slot `<oer-list>` and `<oer-load-more>` inside `<oer-search>`. Use `@ViewChild` with `ElementRef` to access the underlying web component elements. For the full list of component properties and events, see [Component Properties](./client-packages.md#component-properties).
3248

3349
### Component
3450

@@ -51,11 +67,13 @@ export class OerFinderComponent implements AfterViewInit {
5167
@ViewChild('listElement') listElement!: ElementRef;
5268
@ViewChild('loadMoreElement') loadMoreElement!: ElementRef;
5369

54-
// Configure available sources
70+
// Configure available sources (checked: true sets the pre-selected sources)
5571
sources: SourceConfig[] = [
56-
{ id: 'nostr-amb-relay', label: 'AMB Relay' },
72+
{ id: 'nostr-amb-relay', label: 'Nostr AMB Relay', checked: true },
5773
{ id: 'openverse', label: 'Openverse' },
5874
{ id: 'arasaac', label: 'ARASAAC' },
75+
{ id: 'rpi-virtuell', label: 'RPI-Virtuell' },
76+
{ id: 'wikimedia', label: 'Wikimedia Commons' },
5977
];
6078

6179
ngAfterViewInit(): void {
@@ -67,6 +85,13 @@ export class OerFinderComponent implements AfterViewInit {
6785
// Note: load-more events bubble up and are automatically
6886
// caught by oer-search to fetch the next page of results.
6987

88+
onSearchLoading(): void {
89+
const listEl = this.listElement.nativeElement;
90+
const loadMoreEl = this.loadMoreElement.nativeElement;
91+
listEl.loading = true;
92+
loadMoreEl.loading = true;
93+
}
94+
7095
onSearchResults(event: Event): void {
7196
const { data, meta } = (event as OerSearchResultEvent).detail;
7297
const listEl = this.listElement.nativeElement;
@@ -100,59 +125,83 @@ export class OerFinderComponent implements AfterViewInit {
100125

101126
onCardClick(event: Event): void {
102127
const { oer } = (event as OerCardClickEvent).detail;
103-
// Handle card click
128+
const url = oer.amb?.id;
129+
if (url) {
130+
window.open(String(url), '_blank', 'noopener,noreferrer');
131+
}
104132
}
105133
}
106134
```
107135

108136
### Template
109137

138+
Angular uses `(event-name)="handler($event)"` syntax for web component events:
139+
110140
```html
111141
<oer-search
112142
#searchElement
113143
api-url="https://your-api-url.com"
114-
language="de"
144+
language="en"
115145
page-size="20"
146+
(search-loading)="onSearchLoading()"
116147
(search-results)="onSearchResults($event)"
117148
(search-error)="onSearchError($event)"
118149
(search-cleared)="onSearchCleared()"
119150
>
120151
<oer-list
121152
#listElement
122-
language="de"
153+
language="en"
123154
(card-click)="onCardClick($event)"
124155
></oer-list>
125156
<oer-load-more
126157
#loadMoreElement
127-
language="de"
158+
language="en"
128159
></oer-load-more>
129160
</oer-search>
130161
```
131162

132-
## Configuring Sources
163+
## Direct Client Mode Example
133164

134-
Sources are configured using the `SourceConfig` type and must be set as a JS property (not an HTML attribute).
135-
Set the `sources` property in `ngAfterViewInit` as shown in the example above.
165+
The component code is identical to the [server-proxy example above](#basic-usage-server-proxy-mode) with two differences: adapters must be registered at startup, and the `api-url` attribute is omitted. For adapter details, see [Available Adapters](./client-packages.md#available-adapters).
166+
167+
**1. Register adapters once at your app entry point (e.g., `main.ts`):**
136168

137169
```typescript
138-
import type { SourceConfig } from '@edufeed-org/oer-finder-plugin';
170+
import { registerAllBuiltInAdapters } from '@edufeed-org/oer-finder-plugin/adapters';
171+
registerAllBuiltInAdapters();
172+
```
139173

140-
// Server-proxy mode sources (with api-url set)
141-
// Use checked: true to set the pre-selected sources
142-
const serverSources: SourceConfig[] = [
143-
{ id: 'nostr-amb-relay', label: 'AMB Relay', checked: true },
144-
{ id: 'openverse', label: 'Openverse' },
145-
{ id: 'arasaac', label: 'ARASAAC' },
146-
];
174+
**2. Provide `baseUrl` in the source config where required:**
147175

148-
// Direct client mode sources (without api-url)
149-
const directSources: SourceConfig[] = [
150-
{ id: 'openverse', label: 'Openverse' },
151-
{ id: 'arasaac', label: 'ARASAAC', checked: true },
176+
```typescript
177+
sources: SourceConfig[] = [
178+
{ id: 'openverse', label: 'Openverse', checked: true },
179+
{ id: 'arasaac', label: 'ARASAAC' },
180+
{ id: 'wikimedia', label: 'Wikimedia Commons' },
152181
{ id: 'nostr-amb-relay', label: 'Nostr AMB Relay', baseUrl: 'wss://amb-relay.edufeed.org' },
182+
{ id: 'rpi-virtuell', label: 'RPI-Virtuell' },
153183
];
154184
```
155185

186+
**3. Remove `api-url` from the template:**
187+
188+
```html
189+
<oer-search
190+
#searchElement
191+
language="en"
192+
page-size="20"
193+
(search-loading)="onSearchLoading()"
194+
(search-results)="onSearchResults($event)"
195+
(search-error)="onSearchError($event)"
196+
(search-cleared)="onSearchCleared()"
197+
>
198+
<oer-list #listElement language="en" (card-click)="onCardClick($event)"></oer-list>
199+
<oer-load-more #loadMoreElement language="en"></oer-load-more>
200+
</oer-search>
201+
```
202+
203+
All event handlers and component logic remain the same.
204+
156205
## Example
157206

158207
See the [TeamMapper integration PR](https://github.com/b310-digital/teammapper/pull/1081) for a real-world Angular example.

docs/client-packages-react.md

Lines changed: 16 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -14,63 +14,10 @@ The base plugin is a peer dependency of the React package. Both packages must be
1414

1515
## Operating Modes
1616

17-
The plugin supports two operating modes, determined by whether the `apiUrl` prop is provided:
17+
The plugin supports **server-proxy mode** (with `apiUrl` prop) and **direct client mode** (without `apiUrl`). For full details on each mode, adapter registration, and available adapters, see [Client Packages — Routing Modes](./client-packages.md#routing-modes) and [Available Adapters](./client-packages.md#available-adapters).
1818

19-
### Server-Proxy Mode (with `apiUrl`)
20-
21-
When `apiUrl` is set, all search requests are routed through your backend proxy. The server handles adapter logic, so **no adapter code is bundled into your client application**.
22-
23-
**Use this mode when:**
24-
- You have a deployed OER Proxy backend
25-
- You want to keep client bundle size small
26-
- You need server-side features like image proxying, rate limiting, or signed URLs
27-
28-
```tsx
29-
<OerSearch
30-
apiUrl="https://your-api-url.com"
31-
sources={SOURCES}
32-
// ...event handlers
33-
>
34-
```
35-
36-
No adapter registration is needed — just provide the `apiUrl` and configure your sources.
37-
38-
### Direct Client Mode (without `apiUrl`)
39-
40-
When `apiUrl` is **omitted**, adapters run directly in the browser. No backend server is required.
41-
42-
**Use this mode when:**
43-
- You want a serverless setup with no backend dependency
44-
- You are prototyping or building a static site
45-
- You want full client-side control over adapter behavior
46-
47-
You **must register adapters** before the component renders. Call the registration function once at your app's entry point. Import adapter registration functions directly from `@edufeed-org/oer-finder-plugin`:
48-
49-
```typescript
50-
// Register all built-in adapters
51-
import { registerAllBuiltInAdapters } from '@edufeed-org/oer-finder-plugin/adapters';
52-
registerAllBuiltInAdapters();
53-
```
54-
55-
Or register only the adapters you need:
56-
57-
```typescript
58-
import { registerOpenverseAdapter } from '@edufeed-org/oer-finder-plugin/adapter/openverse';
59-
import { registerArasaacAdapter } from '@edufeed-org/oer-finder-plugin/adapter/arasaac';
60-
registerOpenverseAdapter();
61-
registerArasaacAdapter();
62-
```
63-
64-
Then render `OerSearch` without `apiUrl`:
65-
66-
```tsx
67-
<OerSearch
68-
sources={SOURCES}
69-
// ...event handlers (no apiUrl prop)
70-
>
71-
```
72-
73-
Only registered adapters will be available — unregistered source IDs in the `sources` config are silently skipped.
19+
- **Server-proxy mode**: Set `apiUrl` — no adapter registration needed, no adapter code in your bundle.
20+
- **Direct client mode**: Omit `apiUrl` — register adapters at your app's entry point before the component renders. Import adapter registration functions from `@edufeed-org/oer-finder-plugin`.
7421

7522
## Basic Usage
7623

@@ -291,75 +238,35 @@ If you render `OerLoadMore` outside of `OerSearch`, the event will not bubble to
291238
|------|-------------------|-------------|
292239
| `onLoadMore` | `(event: CustomEvent<void>) => void` | Fired when the "Load more" button is clicked. When slotted inside `OerSearch`, this event bubbles up automatically to trigger the next page fetch — no manual handler needed. |
293240

294-
## Available Adapters
295-
296-
The following built-in adapters are available for direct client mode:
297-
298-
| Adapter ID | Source | Notes |
299-
|------------|--------|-------|
300-
| `openverse` | Openverse (Flickr, Wikimedia, etc.) | Images, license filter |
301-
| `arasaac` | ARASAAC pictograms API | Images only |
302-
| `nostr-amb-relay` | Nostr AMB relay (WebSocket) | Requires `baseUrl` with WebSocket URL(s) in `SourceConfig` |
303-
| `rpi-virtuell` | RPI-Virtuell Materialpool (GraphQL) | German educational resources |
304-
| `wikimedia` | Wikimedia Commons API | Images |
305-
306-
Register all at once or selectively — import adapter registration functions from `@edufeed-org/oer-finder-plugin`:
307-
308-
```typescript
309-
// All adapters
310-
import { registerAllBuiltInAdapters } from '@edufeed-org/oer-finder-plugin/adapters';
311-
registerAllBuiltInAdapters();
312-
313-
// Or selectively (better for tree-shaking)
314-
import { registerOpenverseAdapter } from '@edufeed-org/oer-finder-plugin/adapter/openverse';
315-
import { registerWikimediaAdapter } from '@edufeed-org/oer-finder-plugin/adapter/wikimedia';
316-
registerOpenverseAdapter();
317-
registerWikimediaAdapter();
318-
```
319-
320241
## Key Types
321242

322-
React components and UI-related types are importable from `@edufeed-org/oer-finder-plugin-react`:
243+
The React package (`@edufeed-org/oer-finder-plugin-react`) re-exports all shared types from the base plugin, so you can import everything from a single package. For the full list of shared types, see [Key Types](./client-packages.md#key-types).
323244

324245
```typescript
325246
import {
326-
// Components
247+
// React wrapper components
327248
OerSearch,
328249
OerList,
329250
OerCard,
330251
OerLoadMore,
331252

332-
// Event types
333-
type OerSearchResultEvent, // CustomEvent<{ data: OerItem[], meta: LoadMoreMeta }>
334-
type OerSearchResultDetail, // { data: OerItem[], meta: LoadMoreMeta }
335-
type OerCardClickEvent, // CustomEvent<{ oer: OerItem }>
336-
type OerCardClickDetail, // { oer: OerItem }
337-
338-
// Data types
339-
type OerItem, // Normalized AMB metadata for a single resource
340-
type OerMetadata, // Metadata structure on OerItem
341-
type OerListResponse, // Full list response shape from the API
342-
type LoadMoreMeta, // { total: number, shown: number, hasMore: boolean }
343-
type SourceConfig, // { id: string, label: string, baseUrl?: string, checked?: boolean }
344-
type SupportedLanguage, // 'en' | 'de'
345-
type SearchParams, // Search parameter structure
346-
type SourceOption, // Source option type for UI display
347-
348-
// Underlying web component types (for advanced use)
349-
type OerSearchElement, // <oer-search> element class
350-
type OerListElement, // <oer-list> element class
351-
type OerCardElement, // <oer-card> element class
352-
type LoadMoreElement, // <oer-load-more> element class
253+
// All shared types are re-exported (OerItem, SourceConfig, event types, etc.)
254+
type OerSearchResultEvent,
255+
type OerCardClickEvent,
256+
type OerItem,
257+
type LoadMoreMeta,
258+
type SourceConfig,
259+
// ... see Client Packages — Key Types for the complete list
353260
} from '@edufeed-org/oer-finder-plugin-react';
354261
```
355262

356-
Adapter registry API and adapter types are imported from `@edufeed-org/oer-finder-plugin`:
263+
Adapter registry API and adapter registration functions are imported from `@edufeed-org/oer-finder-plugin`:
357264

358265
```typescript
359266
import {
360-
registerAdapter, // Register a custom adapter factory
361-
getAdapterFactory, // Retrieve a registered adapter factory by ID
362-
type AdapterFactory, // Factory function type for custom adapters
267+
registerAdapter,
268+
getAdapterFactory,
269+
type AdapterFactory,
363270
} from '@edufeed-org/oer-finder-plugin';
364271
```
365272

0 commit comments

Comments
 (0)