feat(guilds): a UO guild is a Team (Teams cutover 5/6) #16

Merged
whitlocktech merged 22 commits from edge into main 2026-08-19 09:02:40 +00:00
3 changed files with 25 additions and 6 deletions
Showing only changes of commit 9d0a197008 - Show all commits

View File

@@ -194,6 +194,14 @@ registry.registerExtension(ID, 'player.invite.accepted', InviteGameAccountStep)
// enough; on a core that knows nothing of Teams it simply stays empty. // enough; on a core that knows nothing of Teams it simply stays empty.
registry.declareModuleSlot(ID, 'uo.guild.detail') registry.declareModuleSlot(ID, 'uo.guild.detail')
// A SECOND place on the same page, for core's Team forum (TEAMS.md Part 5). Two
// declarations rather than one, because a slot holds one component and this module
// wants to decide where each of core's two contributions sits on its own page —
// the feed reads as part of the guild's story, the forum is a room you go into.
// Neither knows the other exists, and a core that fills only one leaves the other
// empty.
registry.declareModuleSlot(ID, 'uo.guild.forum')
// `module.json`'s `coreApi` range is checked by the loader before this file is // `module.json`'s `coreApi` range is checked by the loader before this file is
// ever served, so there is nothing to re-check here. It is logged because a // ever served, so there is nothing to re-check here. It is logged because a
// mismatch between the core that validated the manifest and the core that // mismatch between the core that validated the manifest and the core that

View File

@@ -102,6 +102,11 @@ export default function Guild() {
that does not fill it, or when there is nothing to show. The guild that does not fill it, or when there is nothing to show. The guild
is named in OUR terms — core maps its own Team from these two. */} is named in OUR terms — core maps its own Team from these two. */}
<Slot name="uo.guild.detail" externalId={String(id)} moduleId="uo" /> <Slot name="uo.guild.detail" externalId={String(id)} moduleId="uo" />
{/* And the Team forum, in its own place below the feed. Core resolves
who may read it — membership and manual grants are core's rules —
so this module renders the room and never its door policy. */}
<Slot name="uo.guild.forum" externalId={String(id)} moduleId="uo" />
</> </>
)} )}
</div> </div>

View File

@@ -209,16 +209,22 @@ it('registers under exactly one module id, matching the manifest', () => {
assert.deepEqual([...owners], [manifest.id]) assert.deepEqual([...owners], [manifest.id])
}) })
it('declares its own guild-detail slot, for core to fill', () => { it('declares its own guild slots, for core to fill', () => {
// The inverted direction (TEAMS.md Part 3). Teams are a core primitive with no // The inverted direction (TEAMS.md Part 3). Teams are a core primitive with no
// core page: core owns the activity feed and this module owns the word "guild", // core page: core owns the activity feed and the forum, this module owns the
// so this module declares the place and core puts the feed in it. // word "guild", so this module declares the places and core puts them in.
assert.deepEqual([...registered.declaredSlots], ['uo.guild.detail']) //
// TWO slots rather than one because a slot holds one component: stacking the
// feed and the forum into a single fill would take away this module's ability
// to place them separately on its own page.
assert.deepEqual([...registered.declaredSlots], ['uo.guild.detail', 'uo.guild.forum'])
}) })
it('the declared slot is rendered by the page that owns it', () => { it('every declared slot is rendered by the page that owns it', () => {
// A slot nothing renders is a slot core fills into the void. Asserted against // A slot nothing renders is a slot core fills into the void. Asserted against
// the source rather than the chunk, since the chunk is minified. // the source rather than the chunk, since the chunk is minified.
const page = fs.readFileSync(path.resolve(HERE, '..', 'src', 'routes', 'public', 'Guild.jsx'), 'utf8') const page = fs.readFileSync(path.resolve(HERE, '..', 'src', 'routes', 'public', 'Guild.jsx'), 'utf8')
assert.match(page, /name="uo\.guild\.detail"/) for (const name of registered.declaredSlots) {
assert.match(page, new RegExp(`name="${name.replace(/\./g, '\.')}"`))
}
}) })