NextGraph integration (WIP), broker banner, and feature-based architecture
- Add NextGraph data layer with @ng-org/orm, SHEX shapes (Event, UserProfile, Participation), session management, and FestipodDataContext with dual-mode operation (connected via NextGraph or local seed data) - Add BrokerBanner and NgStatus components showing connection status - Refactor to feature-based architecture: organize code by business domain (event, user, home, auth, workshop, meeting, notification) instead of technical layer. Modules only import from shared/, never from each other - Collocate BDD features and step definitions with their modules: event-specific steps in event/steps/, user steps in user/steps/, shared generic steps remain in shared/steps/ - Set up multi-layer BDD structure (frontend/backend/e2e steps per module) - Add project documentation (AGENTS.md, .project/knowledge/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import type { Schema } from "@ng-org/shex-orm";
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* festipodShapesSchema: Schema for festipodShapes
|
||||
* =============================================================================
|
||||
*/
|
||||
export const festipodShapesSchema: Schema = {
|
||||
"http://festipod.org/Event": {
|
||||
iri: "http://festipod.org/Event",
|
||||
predicates: [
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
literals: ["http://festipod.org/Event"],
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/title",
|
||||
readablePredicate: "title",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/description",
|
||||
readablePredicate: "description",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/date",
|
||||
readablePredicate: "date",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/location",
|
||||
readablePredicate: "location",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "number" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/distance",
|
||||
readablePredicate: "distance",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "number" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/participantCount",
|
||||
readablePredicate: "participantCount",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/coverImage",
|
||||
readablePredicate: "coverImage",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/hostName",
|
||||
readablePredicate: "hostName",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/hostInitials",
|
||||
readablePredicate: "hostInitials",
|
||||
},
|
||||
],
|
||||
},
|
||||
"http://festipod.org/UserProfile": {
|
||||
iri: "http://festipod.org/UserProfile",
|
||||
predicates: [
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
literals: ["http://festipod.org/UserProfile"],
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/name",
|
||||
readablePredicate: "name",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/initials",
|
||||
readablePredicate: "initials",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/username",
|
||||
readablePredicate: "username",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/role",
|
||||
readablePredicate: "role",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "boolean" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/isPublic",
|
||||
readablePredicate: "isPublic",
|
||||
},
|
||||
],
|
||||
},
|
||||
"http://festipod.org/Participation": {
|
||||
iri: "http://festipod.org/Participation",
|
||||
predicates: [
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
literals: ["http://festipod.org/Participation"],
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "iri" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/event",
|
||||
readablePredicate: "event",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "iri" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/user",
|
||||
readablePredicate: "user",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "boolean" }],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/isConfirmed",
|
||||
readablePredicate: "isConfirmed",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { ShapeType } from "@ng-org/shex-orm";
|
||||
import { festipodShapesSchema } from "./festipodShapes.schema";
|
||||
import type { FpEvent, FpUserProfile, FpParticipation } from "./festipodShapes.typings";
|
||||
|
||||
// ShapeTypes for festipodShapes
|
||||
export const FpEventShapeType: ShapeType<FpEvent> = {
|
||||
schema: festipodShapesSchema,
|
||||
shape: "http://festipod.org/Event",
|
||||
};
|
||||
export const FpUserProfileShapeType: ShapeType<FpUserProfile> = {
|
||||
schema: festipodShapesSchema,
|
||||
shape: "http://festipod.org/UserProfile",
|
||||
};
|
||||
export const FpParticipationShapeType: ShapeType<FpParticipation> = {
|
||||
schema: festipodShapesSchema,
|
||||
shape: "http://festipod.org/Participation",
|
||||
};
|
||||
@@ -0,0 +1,163 @@
|
||||
export type IRI = string;
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* Typescript Typings for festipodShapes
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Event Type
|
||||
*/
|
||||
export interface FpEvent {
|
||||
/**
|
||||
* The graph IRI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
* The subject IRI.
|
||||
*/
|
||||
readonly "@id": IRI;
|
||||
/**
|
||||
* Original IRI: http://www.w3.org/1999/02/22-rdf-syntax-ns#type
|
||||
*/
|
||||
"@type": "http://festipod.org/Event";
|
||||
/**
|
||||
* The title of the event
|
||||
*
|
||||
* Original IRI: http://festipod.org/title
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* A description of the event
|
||||
*
|
||||
* Original IRI: http://festipod.org/description
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* The display date of the event (e.g. 'Lun. 16 - Ven. 20 fév.')
|
||||
*
|
||||
* Original IRI: http://festipod.org/date
|
||||
*/
|
||||
date: string;
|
||||
/**
|
||||
* The location of the event
|
||||
*
|
||||
* Original IRI: http://festipod.org/location
|
||||
*/
|
||||
location: string;
|
||||
/**
|
||||
* Distance in km from the user
|
||||
*
|
||||
* Original IRI: http://festipod.org/distance
|
||||
*/
|
||||
distance?: number;
|
||||
/**
|
||||
* Number of participants
|
||||
*
|
||||
* Original IRI: http://festipod.org/participantCount
|
||||
*/
|
||||
participantCount: number;
|
||||
/**
|
||||
* URL of the cover image
|
||||
*
|
||||
* Original IRI: http://festipod.org/coverImage
|
||||
*/
|
||||
coverImage?: string;
|
||||
/**
|
||||
* Name of the event host or relay
|
||||
*
|
||||
* Original IRI: http://festipod.org/hostName
|
||||
*/
|
||||
hostName?: string;
|
||||
/**
|
||||
* Initials of the event host
|
||||
*
|
||||
* Original IRI: http://festipod.org/hostInitials
|
||||
*/
|
||||
hostInitials?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* UserProfile Type
|
||||
*/
|
||||
export interface FpUserProfile {
|
||||
/**
|
||||
* The graph IRI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
* The subject IRI.
|
||||
*/
|
||||
readonly "@id": IRI;
|
||||
/**
|
||||
* Original IRI: http://www.w3.org/1999/02/22-rdf-syntax-ns#type
|
||||
*/
|
||||
"@type": "http://festipod.org/UserProfile";
|
||||
/**
|
||||
* Full name of the user
|
||||
*
|
||||
* Original IRI: http://festipod.org/name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Initials for avatar display
|
||||
*
|
||||
* Original IRI: http://festipod.org/initials
|
||||
*/
|
||||
initials: string;
|
||||
/**
|
||||
* Username handle (e.g. @mariedupont)
|
||||
*
|
||||
* Original IRI: http://festipod.org/username
|
||||
*/
|
||||
username: string;
|
||||
/**
|
||||
* Role or title of the user
|
||||
*
|
||||
* Original IRI: http://festipod.org/role
|
||||
*/
|
||||
role?: string;
|
||||
/**
|
||||
* Whether the profile is public
|
||||
*
|
||||
* Original IRI: http://festipod.org/isPublic
|
||||
*/
|
||||
isPublic?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Participation Type
|
||||
*/
|
||||
export interface FpParticipation {
|
||||
/**
|
||||
* The graph IRI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
* The subject IRI.
|
||||
*/
|
||||
readonly "@id": IRI;
|
||||
/**
|
||||
* Original IRI: http://www.w3.org/1999/02/22-rdf-syntax-ns#type
|
||||
*/
|
||||
"@type": "http://festipod.org/Participation";
|
||||
/**
|
||||
* Reference to the event
|
||||
*
|
||||
* Original IRI: http://festipod.org/event
|
||||
*/
|
||||
event: IRI;
|
||||
/**
|
||||
* Reference to the user
|
||||
*
|
||||
* Original IRI: http://festipod.org/user
|
||||
*/
|
||||
user: IRI;
|
||||
/**
|
||||
* Whether the participation is confirmed
|
||||
*
|
||||
* Original IRI: http://festipod.org/isConfirmed
|
||||
*/
|
||||
isConfirmed: boolean;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
PREFIX fp: <http://festipod.org/>
|
||||
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
|
||||
fp:Event {
|
||||
a [fp:Event] ;
|
||||
fp:title xsd:string
|
||||
// rdfs:comment "The title of the event" ;
|
||||
fp:description xsd:string ?
|
||||
// rdfs:comment "A description of the event" ;
|
||||
fp:date xsd:string
|
||||
// rdfs:comment "The display date of the event (e.g. 'Lun. 16 - Ven. 20 fév.')" ;
|
||||
fp:location xsd:string
|
||||
// rdfs:comment "The location of the event" ;
|
||||
fp:distance xsd:float ?
|
||||
// rdfs:comment "Distance in km from the user" ;
|
||||
fp:participantCount xsd:integer
|
||||
// rdfs:comment "Number of participants" ;
|
||||
fp:coverImage xsd:string ?
|
||||
// rdfs:comment "URL of the cover image" ;
|
||||
fp:hostName xsd:string ?
|
||||
// rdfs:comment "Name of the event host or relay" ;
|
||||
fp:hostInitials xsd:string ?
|
||||
// rdfs:comment "Initials of the event host" ;
|
||||
}
|
||||
|
||||
fp:UserProfile {
|
||||
a [fp:UserProfile] ;
|
||||
fp:name xsd:string
|
||||
// rdfs:comment "Full name of the user" ;
|
||||
fp:initials xsd:string
|
||||
// rdfs:comment "Initials for avatar display" ;
|
||||
fp:username xsd:string
|
||||
// rdfs:comment "Username handle (e.g. @mariedupont)" ;
|
||||
fp:role xsd:string ?
|
||||
// rdfs:comment "Role or title of the user" ;
|
||||
fp:isPublic xsd:boolean ?
|
||||
// rdfs:comment "Whether the profile is public" ;
|
||||
}
|
||||
|
||||
fp:Participation {
|
||||
a [fp:Participation] ;
|
||||
fp:event IRI
|
||||
// rdfs:comment "Reference to the event" ;
|
||||
fp:user IRI
|
||||
// rdfs:comment "Reference to the user" ;
|
||||
fp:isConfirmed xsd:boolean
|
||||
// rdfs:comment "Whether the participation is confirmed" ;
|
||||
}
|
||||
Reference in New Issue
Block a user