Add Event schema to metadata
- add types from https://schema.org/Event - updated MkEvent to display new fields - minor refactoring
This commit is contained in:
parent
5abbcf6cd4
commit
b7c7e4d32d
|
@ -3,13 +3,13 @@ import { DI } from '@/di-symbols.js';
|
||||||
import type { EventsRepository, NotesRepository } from '@/models/index.js';
|
import type { EventsRepository, NotesRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import { IEvent } from '@/models/entities/Event.js';
|
||||||
import { isEvent } from '../type.js';
|
import { isEvent } from '../type.js';
|
||||||
import { ApLoggerService } from '../ApLoggerService.js';
|
import { ApLoggerService } from '../ApLoggerService.js';
|
||||||
import { ApResolverService } from '../ApResolverService.js';
|
import { ApResolverService } from '../ApResolverService.js';
|
||||||
import type { Resolver } from '../ApResolverService.js';
|
import type { Resolver } from '../ApResolverService.js';
|
||||||
import type { IObject } from '../type.js';
|
import type { IObject } from '../type.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
|
||||||
import { IEvent } from '@/models/entities/Event.js';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApEventService {
|
export class ApEventService {
|
||||||
|
@ -32,8 +32,8 @@ export class ApEventService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async extractEventFromNote(source: string | IObject, resolver?: Resolver): Promise<IEvent> {
|
public async extractEventFromNote(source: string | IObject, resolverParam?: Resolver): Promise<IEvent> {
|
||||||
if (resolver == null) resolver = this.apResolverService.createResolver();
|
const resolver = resolverParam ?? this.apResolverService.createResolver();
|
||||||
|
|
||||||
const note = await resolver.resolve(source);
|
const note = await resolver.resolve(source);
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ export class Event {
|
||||||
},
|
},
|
||||||
comment: 'metadata object describing the event. Follows https://schema.org/Event',
|
comment: 'metadata object describing the event. Follows https://schema.org/Event',
|
||||||
})
|
})
|
||||||
public metadata: unknown;
|
public metadata: EventSchema;
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Column('enum', {
|
@Column('enum', {
|
||||||
|
@ -74,9 +74,46 @@ export class Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type EventSchema = {
|
||||||
|
'@context': 'https://schema.org';
|
||||||
|
'@type': 'Event';
|
||||||
|
name?: string;
|
||||||
|
url?: string;
|
||||||
|
description?: string;
|
||||||
|
audience?: {
|
||||||
|
'@type': 'Audience';
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
doorTime?: string;
|
||||||
|
startDate?: string;
|
||||||
|
endDate?: string;
|
||||||
|
eventStatus?: 'https://schema.org/EventCancelled' | 'https://schema.org/EventMovedOnline' | 'https://schema.org/EventPostponed' | 'https://schema.org/EventRescheduled' | 'https://schema.org/EventScheduled';
|
||||||
|
inLanguage?: string;
|
||||||
|
isAccessibleForFree?: boolean;
|
||||||
|
keywords?: string;
|
||||||
|
location?: string;
|
||||||
|
offers?: {
|
||||||
|
'@type': 'Offer';
|
||||||
|
price?: string;
|
||||||
|
priceCurrency?: string;
|
||||||
|
availabilityStarts?: string;
|
||||||
|
availabilityEnds?: string;
|
||||||
|
url?: string;
|
||||||
|
};
|
||||||
|
organizer?: {
|
||||||
|
name: string;
|
||||||
|
sameAs?: string; // ie. URL to website/social
|
||||||
|
};
|
||||||
|
performer?: {
|
||||||
|
name: string;
|
||||||
|
sameAs?: string; // ie. URL to website/social
|
||||||
|
}[];
|
||||||
|
typicalAgeRange?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type IEvent = {
|
export type IEvent = {
|
||||||
start: Date;
|
start: Date;
|
||||||
end: Date | null
|
end: Date | null
|
||||||
title: string;
|
title: string;
|
||||||
metadata: Record<string, string>;
|
metadata: EventSchema;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ export const paramDef = {
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
function notAlphaNumeric(s: string) {
|
function notAlphaNumeric(s: string): boolean {
|
||||||
return null !== s.match(/[^\w]/);
|
return null !== s.match(/[^\w]/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,66 @@
|
||||||
<MkTime :time="note.event!.end" mode="detail"/>
|
<MkTime :time="note.event!.end" mode="detail"/>
|
||||||
</dd>
|
</dd>
|
||||||
</template>
|
</template>
|
||||||
<template v-for="[key, value] of Object.entries(note.event!.detail)" :key="key">
|
<template v-if="note.event!.metadata.doorTime">
|
||||||
<dt :class="$style.key">{{ key }}</dt>
|
<dt :class="$style.key">{{ "Door Time" }}</dt>
|
||||||
<dd :class="$style.value">{{ value }}</dd>
|
<dd :class="$style.value">{{ note.event!.metadata.doorTime }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.location">
|
||||||
|
<dt :class="$style.key">{{ "Location" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.location }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.url">
|
||||||
|
<dt :class="$style.key">{{ "URL" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.url }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.organizer">
|
||||||
|
<dt :class="$style.key">{{ "Organizer" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.organizer.name }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.audience">
|
||||||
|
<dt :class="$style.key">{{ "Audience" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.audience.name }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.inLanguage">
|
||||||
|
<dt :class="$style.key">{{ "Language" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.inLanguage }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.typicalAgeRange">
|
||||||
|
<dt :class="$style.key">{{ "Ages" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.typicalAgeRange }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.performer">
|
||||||
|
<dt :class="$style.key">{{ "Performers" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.performer.join(', ') }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.offers?.url">
|
||||||
|
<dt :class="$style.key">{{ "Tickets" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.url }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.isAccessibleForFree">
|
||||||
|
<dt :class="$style.key">{{ "Free" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ "Yes" }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.offers?.price">
|
||||||
|
<dt :class="$style.key">{{ "Price" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.offers.price }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.offers?.url">
|
||||||
|
<dt :class="$style.key">{{ "Tickets Available" }}</dt>
|
||||||
|
<dd :class="$style.value">
|
||||||
|
{{ [
|
||||||
|
(note.event!.metadata.offers.availabilityStarts ? 'From ' + note.event!.metadata.offers.availabilityStarts : ''),
|
||||||
|
(note.event!.metadata.offers.availabilityEnds ? 'Until ' + note.event!.metadata.offers.availabilityEnds : '')]
|
||||||
|
.join(' ') }}
|
||||||
|
</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.offers?.url">
|
||||||
|
<dt :class="$style.key">{{ "Tickets" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.url }}</dd>
|
||||||
|
</template>
|
||||||
|
<template v-if="note.event!.metadata.keywords">
|
||||||
|
<dt :class="$style.key">{{ "Keywords" }}</dt>
|
||||||
|
<dd :class="$style.value">{{ note.event!.metadata.keywords }}</dd>
|
||||||
</template>
|
</template>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -515,7 +515,7 @@ export type Endpoints = {
|
||||||
sinceDate?: number;
|
sinceDate?: number;
|
||||||
untilDate?: number;
|
untilDate?: number;
|
||||||
sortBy?: 'startDate' | 'craetedAt';
|
sortBy?: 'startDate' | 'craetedAt';
|
||||||
filters?: { key: string, values: (string | null)[] }[];
|
filters?: { key: string[], values: (string | null)[] }[];
|
||||||
}; res: Note[]; };
|
}; res: Note[]; };
|
||||||
'notes/reactions': { req: { noteId: Note['id']; type?: string | null; limit?: number; }; res: NoteReaction[]; };
|
'notes/reactions': { req: { noteId: Note['id']; type?: string | null; limit?: number; }; res: NoteReaction[]; };
|
||||||
'notes/reactions/create': { req: { noteId: Note['id']; reaction: string; }; res: null; };
|
'notes/reactions/create': { req: { noteId: Note['id']; reaction: string; }; res: null; };
|
||||||
|
|
Loading…
Reference in New Issue