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:
ssmucny 2023-05-22 22:09:12 -04:00
parent 5abbcf6cd4
commit b7c7e4d32d
5 changed files with 106 additions and 12 deletions

View File

@ -3,13 +3,13 @@ import { DI } from '@/di-symbols.js';
import type { EventsRepository, NotesRepository } from '@/models/index.js';
import type { Config } from '@/config.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 { ApLoggerService } from '../ApLoggerService.js';
import { ApResolverService } from '../ApResolverService.js';
import type { Resolver } from '../ApResolverService.js';
import type { IObject } from '../type.js';
import { bindThis } from '@/decorators.js';
import { IEvent } from '@/models/entities/Event.js';
@Injectable()
export class ApEventService {
@ -32,8 +32,8 @@ export class ApEventService {
}
@bindThis
public async extractEventFromNote(source: string | IObject, resolver?: Resolver): Promise<IEvent> {
if (resolver == null) resolver = this.apResolverService.createResolver();
public async extractEventFromNote(source: string | IObject, resolverParam?: Resolver): Promise<IEvent> {
const resolver = resolverParam ?? this.apResolverService.createResolver();
const note = await resolver.resolve(source);

View File

@ -35,13 +35,13 @@ export class Event {
public title: string;
@Column('jsonb', {
default: {
default: {
'@context': 'https://schema.org/',
'@type': 'Event',
},
comment: 'metadata object describing the event. Follows https://schema.org/Event',
})
public metadata: unknown;
public metadata: EventSchema;
//#region Denormalized fields
@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 = {
start: Date;
end: Date | null
title: string;
metadata: Record<string, string>;
metadata: EventSchema;
}

View File

@ -67,7 +67,7 @@ export const paramDef = {
},
} as const;
function notAlphaNumeric(s: string) {
function notAlphaNumeric(s: string): boolean {
return null !== s.match(/[^\w]/);
}

View File

@ -15,9 +15,66 @@
<MkTime :time="note.event!.end" mode="detail"/>
</dd>
</template>
<template v-for="[key, value] of Object.entries(note.event!.detail)" :key="key">
<dt :class="$style.key">{{ key }}</dt>
<dd :class="$style.value">{{ value }}</dd>
<template v-if="note.event!.metadata.doorTime">
<dt :class="$style.key">{{ "Door Time" }}</dt>
<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>
</dl>
</div>

View File

@ -515,7 +515,7 @@ export type Endpoints = {
sinceDate?: number;
untilDate?: number;
sortBy?: 'startDate' | 'craetedAt';
filters?: { key: string, values: (string | null)[] }[];
filters?: { key: string[], values: (string | null)[] }[];
}; res: Note[]; };
'notes/reactions': { req: { noteId: Note['id']; type?: string | null; limit?: number; }; res: NoteReaction[]; };
'notes/reactions/create': { req: { noteId: Note['id']; reaction: string; }; res: null; };