provide ics link
This commit is contained in:
parent
8c597fd68d
commit
91c3fde688
8 changed files with 155 additions and 4 deletions
88
package-lock.json
generated
88
package-lock.json
generated
|
@ -12,7 +12,9 @@
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^5.0.0-beta.3",
|
"express": "^5.0.0-beta.3",
|
||||||
|
"ics": "^3.8.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"ms": "^2.1.3",
|
"ms": "^2.1.3",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"node-schedule": "^2.1.1",
|
"node-schedule": "^2.1.1",
|
||||||
|
@ -1440,6 +1442,17 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ics": {
|
||||||
|
"version": "3.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ics/-/ics-3.8.1.tgz",
|
||||||
|
"integrity": "sha512-UqQlfkajfhrS4pUGQfGIJMYz/Jsl/ob3LqcfEhUmLbwumg+ZNkU0/6S734Vsjq3/FYNpEcZVKodLBoe+zBM69g==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"nanoid": "^3.1.23",
|
||||||
|
"runes2": "^1.1.2",
|
||||||
|
"yup": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ieee754": {
|
"node_modules/ieee754": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
@ -1742,6 +1755,15 @@
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/moment": {
|
||||||
|
"version": "2.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||||
|
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
@ -1777,6 +1799,24 @@
|
||||||
"thenify-all": "^1.0.0"
|
"thenify-all": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nanoid": {
|
||||||
|
"version": "3.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||||
|
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"nanoid": "bin/nanoid.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/napi-build-utils": {
|
"node_modules/napi-build-utils": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
||||||
|
@ -2014,6 +2054,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
},
|
},
|
||||||
|
"node_modules/property-expr": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/proxy-addr": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
|
@ -2159,6 +2205,12 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/runes2": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/runes2/-/runes2-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-LNPnEDPOOU4ehF71m5JoQyzT2yxwD6ZreFJ7MxZUAoMKNMY1XrAo60H1CUoX5ncSm0rIuKlqn9JZNRrRkNou2g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
@ -2657,6 +2709,12 @@
|
||||||
"node": ">=0.8"
|
"node": ">=0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-case": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/toidentifier": {
|
"node_modules/toidentifier": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
|
@ -2665,6 +2723,12 @@
|
||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/toposort": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ts-node": {
|
"node_modules/ts-node": {
|
||||||
"version": "10.7.0",
|
"version": "10.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
|
||||||
|
@ -2726,6 +2790,18 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/type-fest": {
|
||||||
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-is": {
|
"node_modules/type-is": {
|
||||||
"version": "1.6.18",
|
"version": "1.6.18",
|
||||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||||
|
@ -3120,6 +3196,18 @@
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yup": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"property-expr": "^2.0.5",
|
||||||
|
"tiny-case": "^1.0.3",
|
||||||
|
"toposort": "^2.0.2",
|
||||||
|
"type-fest": "^2.19.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^5.0.0-beta.3",
|
"express": "^5.0.0-beta.3",
|
||||||
|
"ics": "^3.8.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"ms": "^2.1.3",
|
"ms": "^2.1.3",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"node-schedule": "^2.1.1",
|
"node-schedule": "^2.1.1",
|
||||||
|
|
|
@ -43,6 +43,14 @@ export default abstract class CalendarCommandHandler {
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
static async update(updateCalendar: UpdateCalendarCommand): Promise<void> {
|
static async update(updateCalendar: UpdateCalendarCommand): Promise<void> {
|
||||||
|
let sequence = await dataSource
|
||||||
|
.getRepository(calendar)
|
||||||
|
.createQueryBuilder("calendar")
|
||||||
|
.where("id = :id", { id: updateCalendar.id })
|
||||||
|
.getOneOrFail()
|
||||||
|
.then((res) => {
|
||||||
|
return res.sequence;
|
||||||
|
});
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.update(calendar)
|
.update(calendar)
|
||||||
|
@ -58,6 +66,7 @@ export default abstract class CalendarCommandHandler {
|
||||||
.createQueryBuilder("type")
|
.createQueryBuilder("type")
|
||||||
.where("id = :id", { id: updateCalendar.typeId })
|
.where("id = :id", { id: updateCalendar.typeId })
|
||||||
.getOneOrFail(),
|
.getOneOrFail(),
|
||||||
|
sequence: sequence + 1,
|
||||||
})
|
})
|
||||||
.where("id = :id", { id: updateCalendar.id })
|
.where("id = :id", { id: updateCalendar.id })
|
||||||
.execute()
|
.execute()
|
||||||
|
|
|
@ -31,7 +31,7 @@ export async function getAllCalendarItems(req: Request, res: Response): Promise<
|
||||||
* @returns {Promise<*>}
|
* @returns {Promise<*>}
|
||||||
*/
|
*/
|
||||||
export async function getCalendarItemById(req: Request, res: Response): Promise<any> {
|
export async function getCalendarItemById(req: Request, res: Response): Promise<any> {
|
||||||
const id = parseInt(req.params.id);
|
const id = req.params.id;
|
||||||
let item = await CalendarService.getById(id);
|
let item = await CalendarService.getById(id);
|
||||||
|
|
||||||
res.json(CalendarFactory.mapToSingle(item));
|
res.json(CalendarFactory.mapToSingle(item));
|
||||||
|
|
|
@ -3,6 +3,8 @@ import CalendarFactory from "../factory/admin/calendar";
|
||||||
import CalendarService from "../service/calendarService";
|
import CalendarService from "../service/calendarService";
|
||||||
import CalendarTypeService from "../service/calendarTypeService";
|
import CalendarTypeService from "../service/calendarTypeService";
|
||||||
import { calendar } from "../entity/calendar";
|
import { calendar } from "../entity/calendar";
|
||||||
|
import { createEvents } from "ics";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description get all calendar items by types or nscdr
|
* @description get all calendar items by types or nscdr
|
||||||
|
@ -21,5 +23,49 @@ export async function getCalendarItemsByTypes(req: Request, res: Response): Prom
|
||||||
items = await CalendarService.getByTypeNSCDR();
|
items = await CalendarService.getByTypeNSCDR();
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(CalendarFactory.mapToBase(items));
|
moment()
|
||||||
|
.format("YYYY-M-D-H-m")
|
||||||
|
.split("-")
|
||||||
|
.map((a) => parseInt(a));
|
||||||
|
let events = createEvents(
|
||||||
|
items.map((i) => ({
|
||||||
|
calName: process.env.CLUB_NAME,
|
||||||
|
uid: i.id,
|
||||||
|
sequence: 1,
|
||||||
|
start: moment(i.starttime)
|
||||||
|
.format("YYYY-M-D-H-m")
|
||||||
|
.split("-")
|
||||||
|
.map((a) => parseInt(a)) as [number, number, number, number, number],
|
||||||
|
end: moment(i.endtime)
|
||||||
|
.format("YYYY-M-D-H-m")
|
||||||
|
.split("-")
|
||||||
|
.map((a) => parseInt(a)) as [number, number, number, number, number],
|
||||||
|
title: i.title,
|
||||||
|
description: i.content,
|
||||||
|
location: i.location,
|
||||||
|
categories: [i.type.type],
|
||||||
|
created: moment(i.createdAt)
|
||||||
|
.format("YYYY-M-D-H-m")
|
||||||
|
.split("-")
|
||||||
|
.map((a) => parseInt(a)) as [number, number, number, number, number],
|
||||||
|
lastModified: moment(i.updatedAt)
|
||||||
|
.format("YYYY-M-D-H-m")
|
||||||
|
.split("-")
|
||||||
|
.map((a) => parseInt(a)) as [number, number, number, number, number],
|
||||||
|
transp: "OPAQUE" as "OPAQUE",
|
||||||
|
url: "https://www.ff-merching.de",
|
||||||
|
alarms: [
|
||||||
|
{
|
||||||
|
action: "display",
|
||||||
|
description: "Erinnerung",
|
||||||
|
trigger: {
|
||||||
|
minutes: 30,
|
||||||
|
before: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
res.type("ics").send(events.value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import {
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
|
AfterUpdate,
|
||||||
|
BeforeUpdate,
|
||||||
} from "typeorm";
|
} from "typeorm";
|
||||||
import { calendarType } from "./calendarType";
|
import { calendarType } from "./calendarType";
|
||||||
|
|
||||||
|
@ -32,6 +34,9 @@ export class calendar {
|
||||||
@Column({ type: "boolean", default: false })
|
@Column({ type: "boolean", default: false })
|
||||||
allDay: boolean;
|
allDay: boolean;
|
||||||
|
|
||||||
|
@Column({ type: "int", default: 1 })
|
||||||
|
sequence: number;
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ export class Calendar1729947763295 implements MigrationInterface {
|
||||||
{ name: "content", type: "text", isNullable: true },
|
{ name: "content", type: "text", isNullable: true },
|
||||||
{ name: "allDay", type: "tinyint", isNullable: false, default: 0 },
|
{ name: "allDay", type: "tinyint", isNullable: false, default: 0 },
|
||||||
{ name: "location", type: "text", isNullable: true },
|
{ name: "location", type: "text", isNullable: true },
|
||||||
|
{ name: "sequence", type: variableType_int, default: 1 },
|
||||||
{ name: "createdAt", type: "datetime", precision: 6, isNullable: false, default: "CURRENT_TIMESTAMP(6)" },
|
{ name: "createdAt", type: "datetime", precision: 6, isNullable: false, default: "CURRENT_TIMESTAMP(6)" },
|
||||||
{
|
{
|
||||||
name: "updatedAt",
|
name: "updatedAt",
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default abstract class CalendarService {
|
||||||
* @description get calendar by id
|
* @description get calendar by id
|
||||||
* @returns {Promise<calendar>}
|
* @returns {Promise<calendar>}
|
||||||
*/
|
*/
|
||||||
static async getById(id: number): Promise<calendar> {
|
static async getById(id: string): Promise<calendar> {
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.getRepository(calendar)
|
.getRepository(calendar)
|
||||||
.createQueryBuilder("calendar")
|
.createQueryBuilder("calendar")
|
||||||
|
@ -68,7 +68,7 @@ export default abstract class CalendarService {
|
||||||
.getRepository(calendar)
|
.getRepository(calendar)
|
||||||
.createQueryBuilder("calendar")
|
.createQueryBuilder("calendar")
|
||||||
.leftJoinAndSelect("calendar.type", "type")
|
.leftJoinAndSelect("calendar.type", "type")
|
||||||
.where("type.nscdr = :nscdr)", { nscdr: true })
|
.where("type.nscdr = :nscdr", { nscdr: true })
|
||||||
.getMany()
|
.getMany()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
return res;
|
return res;
|
||||||
|
|
Loading…
Reference in a new issue