Introduce group basic federation, event new page and notifications

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2020-02-18 08:57:00 +01:00
parent 300ef8f245
commit 4144e9ffd0
416 changed files with 32220 additions and 16750 deletions

View File

@@ -1,18 +1,18 @@
import { IPicture } from '@/types/picture.model';
import { IPicture } from "@/types/picture.model";
export enum ActorType {
PERSON = 'PERSON',
APPLICATION = 'APPLICATION',
GROUP = 'GROUP',
ORGANISATION = 'ORGANISATION',
SERVICE = 'SERVICE',
PERSON = "PERSON",
APPLICATION = "APPLICATION",
GROUP = "GROUP",
ORGANISATION = "ORGANISATION",
SERVICE = "SERVICE",
}
export interface IActor {
id?: number;
id?: string;
url: string;
name: string;
domain: string|null;
domain: string | null;
summary: string;
preferredUsername: string;
suspended: boolean;
@@ -22,18 +22,27 @@ export interface IActor {
}
export class Actor implements IActor {
id?: number;
id?: string;
avatar: IPicture | null = null;
banner: IPicture | null = null;
domain: string | null = null;
name: string = '';
preferredUsername: string = '';
summary: string = '';
suspended: boolean = false;
url: string = '';
name = "";
preferredUsername = "";
summary = "";
suspended = false;
url = "";
type: ActorType = ActorType.PERSON;
constructor (hash: IActor | {} = {}) {
constructor(hash: IActor | {} = {}) {
Object.assign(this, hash);
}
@@ -42,11 +51,18 @@ export class Actor implements IActor {
}
usernameWithDomain(): string {
const domain = this.domain ? `@${this.domain}` : '';
const domain = this.domain ? `@${this.domain}` : "";
return `@${this.preferredUsername}${domain}`;
}
public displayName(): string {
return this.name != null && this.name !== '' ? this.name : this.usernameWithDomain();
return this.name != null && this.name !== "" ? this.name : this.usernameWithDomain();
}
}
export function usernameWithDomain(actor: IActor): string {
if (actor.domain) {
return `${actor.preferredUsername}@${actor.domain}`;
}
return actor.preferredUsername;
}

View File

@@ -1,4 +1,4 @@
import { IActor } from '@/types/actor/actor.model';
import { IActor } from "@/types/actor/actor.model";
export interface IFollower {
id?: string;

View File

@@ -1,32 +1,56 @@
import { Actor, IActor } from '@/types/actor/actor.model';
import { Actor, ActorType, IActor } from "./actor.model";
import { Paginate } from "../paginate";
import { IResource } from "../resource";
import { ITodoList } from "../todos";
import { IEvent } from "../event.model";
import { IConversation } from "../conversations";
import { IPerson } from "./person.model";
export enum MemberRole {
PENDING,
MEMBER,
MODERATOR,
ADMIN,
NOT_APPROVED = "NOT_APPROVED",
INVITED = "INVITED",
MEMBER = "MEMBER",
MODERATOR = "MODERATOR",
ADMINISTRATOR = "ADMINISTRATOR",
CREATOR = "CREATOR",
REJECTED = "REJECTED",
}
export interface IGroup extends IActor {
members: IMember[];
members: Paginate<IMember>;
resources: Paginate<IResource>;
todoLists: Paginate<ITodoList>;
conversations: Paginate<IConversation>;
organizedEvents: Paginate<IEvent>;
}
export interface IMember {
id?: string;
role: MemberRole;
parent: IGroup;
actor: IActor;
invitedBy?: IPerson;
}
export class Group extends Actor implements IGroup {
members: IMember[] = [];
members: Paginate<IMember> = { elements: [], total: 0 };
resources: Paginate<IResource> = { elements: [], total: 0 };
todoLists: Paginate<ITodoList> = { elements: [], total: 0 };
conversations: Paginate<IConversation> = { elements: [], total: 0 };
organizedEvents!: Paginate<IEvent>;
constructor(hash: IGroup | {} = {}) {
super(hash);
this.type = ActorType.GROUP;
this.patch(hash);
}
patch (hash: any) {
patch(hash: any) {
Object.assign(this, hash);
}
}

View File

@@ -1,3 +1,3 @@
export * from './actor.model';
export * from './group.model';
export * from './person.model';
export * from "./actor.model";
export * from "./group.model";
export * from "./person.model";

View File

@@ -1,6 +1,8 @@
import { ICurrentUser } from '@/types/current-user.model';
import { IEvent, IParticipant } from '@/types/event.model';
import { Actor, IActor } from '@/types/actor/actor.model';
import { ICurrentUser } from "../current-user.model";
import { IEvent, IParticipant } from "../event.model";
import { Actor, IActor } from "./actor.model";
import { Paginate } from "../paginate";
import { IMember } from "./group.model";
export interface IFeedToken {
token: string;
@@ -12,20 +14,25 @@ export interface IPerson extends IActor {
feedTokens: IFeedToken[];
goingToEvents: IEvent[];
participations: IParticipant[];
memberships: Paginate<IMember>;
}
export class Person extends Actor implements IPerson {
feedTokens: IFeedToken[] = [];
goingToEvents: IEvent[] = [];
participations: IParticipant[] = [];
memberships!: Paginate<IMember>;
constructor(hash: IPerson | {} = {}) {
super(hash);
this.patch(hash);
}
patch (hash: any) {
patch(hash: any) {
Object.assign(this, hash);
}
}

View File

@@ -1,4 +1,4 @@
import poiIcons from '@/utils/poiIcons';
import { poiIcons, IPOIIcon } from "@/utils/poiIcons";
export interface IAddress {
id?: string;
@@ -15,19 +15,29 @@ export interface IAddress {
}
export class Address implements IAddress {
country: string = '';
description: string = '';
locality: string = '';
postalCode: string = '';
region: string = '';
street: string = '';
type: string = '';
id?: string = '';
originId?: string = '';
url?: string = '';
geom?: string = '';
country = "";
constructor(hash?) {
description = "";
locality = "";
postalCode = "";
region = "";
street = "";
type = "";
id?: string = "";
originId?: string = "";
url?: string = "";
geom?: string = "";
constructor(hash?: IAddress) {
if (!hash) return;
this.id = hash.id;
@@ -44,36 +54,40 @@ export class Address implements IAddress {
}
get poiInfos() {
/* generate name corresponding to poi type */
let name = '';
let alternativeName = '';
let poiIcon = poiIcons.default;
/* generate name corresponding to poi type */
let name = "";
let alternativeName = "";
let poiIcon: IPOIIcon = poiIcons.default;
// Google Maps doesn't have a type
if (this.type == null && this.description === this.street) this.type = 'house';
if (this.type == null && this.description === this.street) this.type = "house";
switch (this.type) {
case 'house':
case "house":
name = this.description;
alternativeName = [this.postalCode, this.locality, this.country].filter(zone => zone).join(', ');
alternativeName = [this.postalCode, this.locality, this.country]
.filter((zone) => zone)
.join(", ");
poiIcon = poiIcons.defaultAddress;
break;
case 'street':
case 'secondary':
case "street":
case "secondary":
name = this.description;
alternativeName = [this.postalCode, this.locality, this.country].filter(zone => zone).join(', ');
alternativeName = [this.postalCode, this.locality, this.country]
.filter((zone) => zone)
.join(", ");
poiIcon = poiIcons.defaultStreet;
break;
case 'zone':
case 'city':
case 'administrative':
case "zone":
case "city":
case "administrative":
name = this.postalCode ? `${this.description} (${this.postalCode})` : this.description;
alternativeName = [this.region, this.country].filter(zone => zone).join(', ');
alternativeName = [this.region, this.country].filter((zone) => zone).join(", ");
poiIcon = poiIcons.defaultAdministrative;
break;
default:
// POI
name = this.description;
alternativeName = '';
alternativeName = "";
if (this.street && this.street.trim()) {
alternativeName = `${this.street}`;
if (this.locality) {
@@ -97,11 +111,11 @@ export class Address implements IAddress {
return `${name}, ${alternativeName}`;
}
get iconForPOI() {
get iconForPOI(): IPOIIcon {
if (this.type == null) {
return poiIcons.default;
}
const type = this.type.split(':').pop() || '';
const type = this.type.split(":").pop() || "";
if (poiIcons[type]) return poiIcons[type];
return poiIcons.default;
}

View File

@@ -1,4 +1,4 @@
import { IEvent } from '@/types/event.model';
import { IEvent } from "@/types/event.model";
export interface IDashboard {
lastPublicEventPublished: IEvent;
@@ -9,9 +9,9 @@ export interface IDashboard {
}
export enum InstanceTermsType {
DEFAULT = 'DEFAULT',
URL = 'URL',
CUSTOM = 'CUSTOM',
DEFAULT = "DEFAULT",
URL = "URL",
CUSTOM = "CUSTOM",
}
export interface IAdminSettings {
@@ -19,6 +19,6 @@ export interface IAdminSettings {
instanceDescription: string;
instanceTerms: string;
instanceTermsType: InstanceTermsType;
instanceTermsUrl: string|null;
instanceTermsUrl: string | null;
registrationsOpen: boolean;
}

View File

@@ -1,6 +1,8 @@
import { ServerError, ServerParseError } from 'apollo-link-http-common';
import { ServerError, ServerParseError } from "apollo-link-http-common";
function isServerError(err: Error | ServerError | ServerParseError | undefined): err is ServerError {
function isServerError(
err: Error | ServerError | ServerParseError | undefined
): err is ServerError {
return !!err && (err as ServerError).statusCode !== undefined;
}

View File

@@ -1,5 +1,5 @@
import { Actor, IActor } from '@/types/actor';
import { EventModel, IEvent } from '@/types/event.model';
import { Actor, IActor } from "@/types/actor";
import { EventModel, IEvent } from "@/types/event.model";
export interface IComment {
id?: string;
@@ -19,18 +19,30 @@ export interface IComment {
export class CommentModel implements IComment {
actor: IActor = new Actor();
id?: string;
text: string = '';
local: boolean = true;
text = "";
local = true;
url?: string;
uuid?: string;
inReplyToComment?: IComment = undefined;
originComment?: IComment = undefined;
replies: IComment[] = [];
event?: IEvent = undefined;
updatedAt?: Date = undefined;
deletedAt?: Date = undefined;
totalReplies: number = 0;
totalReplies = 0;
constructor(hash?: IComment) {
if (!hash) return;
@@ -48,5 +60,4 @@ export class CommentModel implements IComment {
this.deletedAt = hash.deletedAt;
this.totalReplies = hash.totalReplies;
}
}

View File

@@ -1,4 +1,5 @@
import { InstanceTermsType } from '@/types/admin.model';
import { InstanceTermsType } from "./admin.model";
import { IProvider } from "./resource";
export interface IConfig {
name: string;
@@ -20,31 +21,31 @@ export interface IConfig {
email: {
enabled: boolean;
confirmationRequired: boolean;
},
};
captcha: {
enabled: boolean;
},
}
}
};
};
};
eventCreation: {
allowed: boolean;
validation: {
email: {
enabled: boolean;
confirmationRequired: boolean;
},
};
captcha: {
enabled: boolean,
},
}
}
actorId,
enabled: boolean;
};
};
};
actorId: string;
};
maps: {
tiles: {
endpoint: string;
attribution: string|null;
},
attribution: string | null;
};
};
geocoding: {
provider: string;
@@ -55,4 +56,6 @@ export interface IConfig {
type: InstanceTermsType;
url: string;
};
resourceProviders: IProvider[];
timezones: string[];
}

View File

@@ -0,0 +1,13 @@
import { IActor, IPerson } from "@/types/actor";
import { IComment } from "@/types/comment.model";
import { Paginate } from "@/types/paginate";
export interface IConversation {
id: string;
title: string;
slug: string;
creator: IPerson;
actor: IActor;
lastComment: IComment;
comments: Paginate<IComment>;
}

View File

@@ -1,10 +1,11 @@
import { IEvent, IParticipant } from '@/types/event.model';
import { IPerson } from '@/types/actor/person.model';
import { IEvent, IParticipant } from "@/types/event.model";
import { IPerson } from "@/types/actor/person.model";
import { Paginate } from "./paginate";
export enum ICurrentUserRole {
USER = 'USER',
MODERATOR = 'MODERATOR',
ADMINISTRATOR = 'ADMINISTRATOR',
USER = "USER",
MODERATOR = "MODERATOR",
ADMINISTRATOR = "ADMINISTRATOR",
}
export interface ICurrentUser {
@@ -12,7 +13,15 @@ export interface ICurrentUser {
email: string;
isLoggedIn: boolean;
role: ICurrentUserRole;
participations: IParticipant[];
participations: Paginate<IParticipant>;
defaultActor: IPerson;
drafts: IEvent[];
settings: IUserSettings;
}
export interface IUserSettings {
timezone: string;
notificationOnDay: string;
notificationEachWeek: string;
notificationBeforeEvent: string;
}

View File

@@ -1,4 +1,4 @@
export enum ErrorCode {
UNKNOWN = 'unknown',
REGISTRATION_CLOSED = 'registration_closed',
UNKNOWN = "unknown",
REGISTRATION_CLOSED = "registration_closed",
}

View File

@@ -1,51 +1,51 @@
import { Actor, IActor, IPerson } from './actor';
import { Address, IAddress } from '@/types/address.model';
import { ITag } from '@/types/tag.model';
import { IPicture } from '@/types/picture.model';
import { IComment } from '@/types/comment.model';
import { Paginate } from '@/types/paginate';
import { Address, IAddress } from "@/types/address.model";
import { ITag } from "@/types/tag.model";
import { IPicture } from "@/types/picture.model";
import { IComment } from "@/types/comment.model";
import { Paginate } from "@/types/paginate";
import { Actor, Group, IActor, IPerson } from "./actor";
export enum EventStatus {
TENTATIVE = 'TENTATIVE',
CONFIRMED = 'CONFIRMED',
CANCELLED = 'CANCELLED',
TENTATIVE = "TENTATIVE",
CONFIRMED = "CONFIRMED",
CANCELLED = "CANCELLED",
}
export enum EventVisibility {
PUBLIC = 'PUBLIC',
UNLISTED = 'UNLISTED',
RESTRICTED = 'RESTRICTED',
PRIVATE = 'PRIVATE',
PUBLIC = "PUBLIC",
UNLISTED = "UNLISTED",
RESTRICTED = "RESTRICTED",
PRIVATE = "PRIVATE",
}
export enum EventJoinOptions {
FREE = 'FREE',
RESTRICTED = 'RESTRICTED',
INVITE = 'INVITE',
FREE = "FREE",
RESTRICTED = "RESTRICTED",
INVITE = "INVITE",
}
export enum EventVisibilityJoinOptions {
PUBLIC = 'PUBLIC',
LINK = 'LINK',
LIMITED = 'LIMITED',
PUBLIC = "PUBLIC",
LINK = "LINK",
LIMITED = "LIMITED",
}
export enum ParticipantRole {
NOT_APPROVED = 'NOT_APPROVED',
NOT_CONFIRMED = 'NOT_CONFIRMED',
REJECTED = 'REJECTED',
PARTICIPANT = 'PARTICIPANT',
MODERATOR = 'MODERATOR',
ADMINISTRATOR = 'ADMINISTRATOR',
CREATOR = 'CREATOR',
NOT_APPROVED = "NOT_APPROVED",
NOT_CONFIRMED = "NOT_CONFIRMED",
REJECTED = "REJECTED",
PARTICIPANT = "PARTICIPANT",
MODERATOR = "MODERATOR",
ADMINISTRATOR = "ADMINISTRATOR",
CREATOR = "CREATOR",
}
export enum Category {
BUSINESS = 'business',
CONFERENCE = 'conference',
BIRTHDAY = 'birthday',
DEMONSTRATION = 'demonstration',
MEETING = 'meeting',
BUSINESS = "business",
CONFERENCE = "conference",
BIRTHDAY = "birthday",
DEMONSTRATION = "demonstration",
MEETING = "meeting",
}
export interface IEventCardOptions {
@@ -60,16 +60,21 @@ export interface IParticipant {
role: ParticipantRole;
actor: IActor;
event: IEvent;
metadata: { cancellationToken?: string, message?: string };
metadata: { cancellationToken?: string; message?: string };
insertedAt?: Date;
}
export class Participant implements IParticipant {
id?: string;
event!: IEvent;
actor!: IActor;
role: ParticipantRole = ParticipantRole.NOT_APPROVED;
metadata = {};
insertedAt?: Date;
constructor(hash?: IParticipant) {
@@ -97,9 +102,9 @@ export interface IParticipationCondition {
}
export enum CommentModeration {
ALLOW_ALL = 'ALLOW_ALL',
MODERATED = 'MODERATED',
CLOSED = 'CLOSED',
ALLOW_ALL = "ALLOW_ALL",
MODERATED = "MODERATED",
CLOSED = "CLOSED",
}
export interface IEventParticipantStats {
@@ -134,7 +139,7 @@ export interface IEvent {
picture: IPicture | null;
organizerActor?: IActor;
attributedTo: IActor;
attributedTo?: IActor;
participantStats: IEventParticipantStats;
participants: Paginate<IParticipant>;
@@ -148,7 +153,7 @@ export interface IEvent {
tags: ITag[];
options: IEventOptions;
toEditJSON();
toEditJSON(): IEventEditJSON;
}
export interface IEventOptions {
@@ -156,6 +161,7 @@ export interface IEventOptions {
remainingAttendeeCapacity: number;
showRemainingAttendeeCapacity: boolean;
anonymousParticipation: boolean;
hideOrganizerWhenGroupEvent: boolean;
offers: IOffer[];
participationConditions: IParticipationCondition[];
attendees: string[];
@@ -168,16 +174,29 @@ export interface IEventOptions {
export class EventOptions implements IEventOptions {
maximumAttendeeCapacity = 0;
remainingAttendeeCapacity = 0;
showRemainingAttendeeCapacity = false;
anonymousParticipation = false;
hideOrganizerWhenGroupEvent = false;
offers: IOffer[] = [];
participationConditions: IParticipationCondition[] = [];
attendees: string[] = [];
program = '';
program = "";
commentModeration = CommentModeration.ALLOW_ALL;
showParticipationPrice = false;
showStartTime = true;
showEndTime = true;
}
@@ -185,39 +204,64 @@ export class EventModel implements IEvent {
id?: string;
beginsOn = new Date();
endsOn: Date | null = new Date();
title = '';
url = '';
uuid = '';
slug = '';
description = '';
title = "";
url = "";
uuid = "";
slug = "";
description = "";
local = true;
onlineAddress: string | undefined = '';
phoneAddress: string | undefined = '';
onlineAddress: string | undefined = "";
phoneAddress: string | undefined = "";
physicalAddress?: IAddress;
picture: IPicture | null = null;
visibility = EventVisibility.PUBLIC;
category: Category | null = Category.MEETING;
joinOptions = EventJoinOptions.FREE;
status = EventStatus.CONFIRMED;
draft = true;
publishAt = new Date();
participantStats = { notApproved: 0, notConfirmed: 0, rejected: 0, participant: 0, moderator: 0, administrator: 0, creator: 0, going: 0 };
participantStats = {
notApproved: 0,
notConfirmed: 0,
rejected: 0,
participant: 0,
moderator: 0,
administrator: 0,
creator: 0,
going: 0,
};
participants!: Paginate<IParticipant>;
relatedEvents: IEvent[] = [];
comments: IComment[] = [];
attributedTo = new Actor();
attributedTo?: IActor = new Actor();
organizerActor?: IActor = new Actor();
tags: ITag[] = [];
options: IEventOptions = new EventOptions();
constructor(hash?: IEvent) {
@@ -246,7 +290,7 @@ export class EventModel implements IEvent {
this.picture = hash.picture;
this.organizerActor = new Actor(hash.organizerActor);
this.attributedTo = new Actor(hash.attributedTo);
this.attributedTo = new Group(hash.attributedTo);
this.participants = hash.participants;
this.relatedEvents = hash.relatedEvents;
@@ -260,7 +304,7 @@ export class EventModel implements IEvent {
if (hash.options) this.options = hash.options;
}
toEditJSON() {
toEditJSON(): IEventEditJSON {
return {
id: this.id,
title: this.title,
@@ -271,13 +315,35 @@ export class EventModel implements IEvent {
visibility: this.visibility,
joinOptions: this.joinOptions,
draft: this.draft,
tags: this.tags.map(t => t.title),
tags: this.tags.map((t) => t.title),
picture: this.picture,
onlineAddress: this.onlineAddress,
phoneAddress: this.phoneAddress,
category: this.category,
physicalAddress: this.physicalAddress,
options: this.options,
// organizerActorId: this.organizerActor && this.organizerActor.id ? this.organizerActor.id : null,
attributedToId: this.attributedTo && this.attributedTo.id ? this.attributedTo.id : null,
};
}
}
interface IEventEditJSON {
id?: string;
title: string;
description: string;
category: Category | null;
beginsOn: string;
endsOn: string | null;
status: EventStatus;
visibility: EventVisibility;
joinOptions: EventJoinOptions;
draft: boolean;
picture: IPicture | { pictureId: string } | null;
attributedToId: string | null;
onlineAddress?: string;
phoneAddress?: string;
physicalAddress?: IAddress;
tags: string[];
options: IEventOptions;
}

View File

@@ -1,9 +1,9 @@
export enum LoginErrorCode {
NEED_TO_LOGIN = 'rouge',
NEED_TO_LOGIN = "rouge",
}
export enum LoginError {
USER_NOT_CONFIRMED = 'User account not confirmed',
USER_DOES_NOT_EXIST = 'No user with this email was found',
USER_EMAIL_PASSWORD_INVALID = 'Impossible to authenticate, either your email or password are invalid.',
USER_NOT_CONFIRMED = "User account not confirmed",
USER_DOES_NOT_EXIST = "No user with this email was found",
USER_EMAIL_PASSWORD_INVALID = "Impossible to authenticate, either your email or password are invalid.",
}

View File

@@ -1,4 +1,4 @@
import { ICurrentUser } from '@/types/current-user.model';
import { ICurrentUser } from "@/types/current-user.model";
export interface IToken {
accessToken: string;

View File

@@ -1,11 +1,11 @@
import { IActor, IPerson } from '@/types/actor';
import { IEvent } from '@/types/event.model';
import { IComment } from '@/types/comment.model';
import { IActor, IPerson } from "@/types/actor";
import { IEvent } from "@/types/event.model";
import { IComment } from "@/types/comment.model";
export enum ReportStatusEnum {
OPEN = 'OPEN',
CLOSED = 'CLOSED',
RESOLVED = 'RESOLVED',
OPEN = "OPEN",
CLOSED = "CLOSED",
RESOLVED = "RESOLVED",
}
export interface IReport extends IActionLogObject {
@@ -21,7 +21,7 @@ export interface IReport extends IActionLogObject {
status: ReportStatusEnum;
}
export interface IReportNote extends IActionLogObject{
export interface IReportNote extends IActionLogObject {
id: string;
content: string;
moderator: IActor;
@@ -32,18 +32,18 @@ export interface IActionLogObject {
}
export enum ActionLogAction {
NOTE_CREATION = 'NOTE_CREATION',
NOTE_DELETION = 'NOTE_DELETION',
REPORT_UPDATE_CLOSED = 'REPORT_UPDATE_CLOSED',
REPORT_UPDATE_OPENED = 'REPORT_UPDATE_OPENED',
REPORT_UPDATE_RESOLVED = 'REPORT_UPDATE_RESOLVED',
EVENT_DELETION = 'EVENT_DELETION',
COMMENT_DELETION = 'COMMENT_DELETION',
NOTE_CREATION = "NOTE_CREATION",
NOTE_DELETION = "NOTE_DELETION",
REPORT_UPDATE_CLOSED = "REPORT_UPDATE_CLOSED",
REPORT_UPDATE_OPENED = "REPORT_UPDATE_OPENED",
REPORT_UPDATE_RESOLVED = "REPORT_UPDATE_RESOLVED",
EVENT_DELETION = "EVENT_DELETION",
COMMENT_DELETION = "COMMENT_DELETION",
}
export interface IActionLog {
id: string;
object: IReport|IReportNote|IEvent;
object: IReport | IReportNote | IEvent;
actor: IActor;
action: ActionLogAction;
insertedAt: Date;

46
js/src/types/resource.ts Normal file
View File

@@ -0,0 +1,46 @@
import { Paginate } from "@/types/paginate";
import { IActor } from "@/types/actor";
export interface IResource {
id?: string;
title: string;
summary?: string;
actor?: IActor;
url?: string;
resourceUrl: string;
path?: string;
children: Paginate<IResource>;
parent?: IResource;
metadata: IResourceMetadata;
insertedAt?: Date;
updatedAt?: Date;
creator?: IActor;
type?: string;
}
export interface IResourceMetadata {
title?: string;
description?: string;
imageRemoteUrl?: string;
height?: number;
width?: number;
type?: string;
authorName?: string;
authorUrl?: string;
providerName?: string;
providerUrl?: string;
html?: string;
faviconUrl?: string;
}
export const mapServiceTypeToIcon: object = {
pad: "file-document-outline",
calc: "google-spreadsheet",
visio: "webcam",
};
export interface IProvider {
type: string;
endpoint: string;
software: string;
}

View File

@@ -1,5 +1,5 @@
import { IGroup, IPerson } from '@/types/actor';
import { IEvent } from '@/types/event.model';
import { IGroup, IPerson } from "@/types/actor";
import { IEvent } from "@/types/event.model";
export interface SearchEvent {
total: number;

View File

@@ -1,4 +1,4 @@
import { Route } from 'vue-router';
import { Route } from "vue-router";
export interface ISettingMenuSection {
title: string;

19
js/src/types/todos.ts Normal file
View File

@@ -0,0 +1,19 @@
import { Paginate } from "@/types/paginate";
import { IActor, IPerson } from "@/types/actor";
export interface ITodoList {
id: string;
title: string;
todos: Paginate<ITodo>;
actor?: IActor;
}
export interface ITodo {
id?: string;
title: string;
status: boolean;
dueDate?: Date;
creator?: IActor;
assignedTo?: IPerson;
todoList?: ITodoList;
}