@meith/plugin-calendar 0.30.1 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,11 +34,18 @@ every signed-in member; guests never may.
34
34
 
35
35
  Removing an event is allowed to whoever added it, and to any organiser.
36
36
 
37
- This is a roster rather than a usergroup on purpose. `@meith/plugin-kit`
38
- gives a plugin no way to read a member's groups, and the board's own guard
39
- says why: group membership is the Authorizer's business, and a plugin never
40
- gets an `Actor` to ask with. A roster the plugin owns keeps the decision
41
- inside the plugin's own surface, where it belongs.
37
+ This is a roster rather than a usergroup, and the roster is what this plugin
38
+ ships with. It keeps the decision inside the plugin's own surface, where a
39
+ plugin never gets an `Actor` and cannot see a member's groups at large.
40
+
41
+ There is now an alternative for a board that would rather run its organisers
42
+ as a usergroup. `context.grants.holds(userId, groupKey)` reads whether a
43
+ member holds a group, but only one the operator has marked **"may be granted
44
+ by plugins"** — the same opt-in the write side needs, and the same privacy
45
+ line: every other group stays invisible. A board could mark an
46
+ `organisers` group grantable and ask `holds` instead of consulting the
47
+ roster. Doing that migration is not part of this plugin as shipped; the
48
+ roster remains the default, and the choice is the operator's.
42
49
 
43
50
  In the downloaded `.ics`, the event's own link becomes the calendar entry's
44
51
  `URL` — it is the one a reader wants to act on from their calendar app — and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meith/plugin-calendar",
3
- "version": "0.30.1",
3
+ "version": "0.32.0",
4
4
  "description": "A shared calendar: events the community can see, linked to the threads that discuss them.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,7 +20,7 @@
20
20
  "access": "public"
21
21
  },
22
22
  "dependencies": {
23
- "@meith/plugin-kit": "^0.30.1"
23
+ "@meith/plugin-kit": "^0.32.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "react": "^19.2.0"
@@ -20,7 +20,7 @@ export const calendarPlugin = definePlugin({
20
20
  key: 'calendar',
21
21
  name: en['calendar.definition.name'],
22
22
  nameKey: 'calendar.definition.name',
23
- version: '0.30.1',
23
+ version: '0.32.0',
24
24
  description: en['calendar.definition.description'],
25
25
  descriptionKey: 'calendar.definition.description',
26
26
  apiVersion: '0',
@@ -5,6 +5,10 @@ import en from '../messages/en.json'
5
5
  import { eventsForThread } from '../store'
6
6
  import { EventLink } from './event-link'
7
7
 
8
+ function translated(context: PluginRegionContext, key: keyof typeof en): string {
9
+ return context.t.has(key) ? context.t.t(key) : en[key]
10
+ }
11
+
8
12
  export async function ThreadEventCard(context: PluginRegionContext) {
9
13
  if (context.subjectId === null) return null
10
14
 
@@ -21,16 +25,16 @@ export async function ThreadEventCard(context: PluginRegionContext) {
21
25
  return (
22
26
  <section className="rounded-md border border-border bg-card p-3 text-sm" data-plugin="calendar">
23
27
  <p className="text-xs uppercase tracking-wide text-muted-foreground">
24
- {en['calendar.thread.card']}
28
+ {translated(context, 'calendar.thread.card')}
25
29
  </p>
26
30
  <p className="font-semibold">{event.title}</p>
27
31
  <p className="text-muted-foreground">
28
32
  <time dateTime={event.startsAt.toISOString()}>
29
- {formatRange(event.startsAt, event.endsAt)}
33
+ {formatRange(event.startsAt, event.endsAt, context.locale)}
30
34
  </time>
31
35
  {event.location !== '' && <span> · {event.location}</span>}
32
36
  </p>
33
- <EventLink event={event} label={en['calendar.event.linkFallback']} />
37
+ <EventLink event={event} label={translated(context, 'calendar.event.linkFallback')} />
34
38
  </section>
35
39
  )
36
40
  }