Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ jobs:
yarn tsc
./startRunStop.sh
- name: Archive UI test results
if: always()
uses: actions/upload-artifact@v4
with:
name: ui-build-results
path: frontendtests/output
- name: Download all workflow run artifacts
if: always()
uses: actions/download-artifact@v4
1 change: 1 addition & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion application/backend/configureApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function handle404(req: Request, res: Response): void {
res.redirect("/");
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars, no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
function handle500(error: any, req: Request, res: Response, next: NextFunction): void {
const status = error.status || 500;
res.status(status);
Expand Down
5 changes: 5 additions & 0 deletions application/backend/lib/persistence/sqlitePersistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export function execWithTry(command: string) {
}
}

process.on("SIGINT", () => {
console.log("SHUTDOWN ON SIGINT (db)"); // eslint-disable-line no-console
db.close();
});

class Persistence {
private collectionName: string;
private history: string;
Expand Down
1 change: 0 additions & 1 deletion application/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
"compile": "yarn sass && yarn tsc",
"deploy": "yarn compile",
"tsc": "../node_modules/typescript/bin/tsc",
"eslint": "../node_modules/.bin/eslint lib/**/*.ts rest/**/*.ts *.ts",
"clean-ts": "rm -rf lib/**/*.js || rm -rf rest/*.js || rm -rf configure.js || rm -rf configureApp.js || rm -rf initWinston.js || rm -rf start.js || :",
"sass": "../node_modules/.bin/sass --silence-deprecation=color-functions,mixed-decls,import,global-builtin sass/jc-backoffice.scss static/stylesheets/screen.css --no-source-map"
}
Expand Down
19 changes: 18 additions & 1 deletion application/backend/rest/programmheft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,28 @@ import store from "../lib/programmheft/kalenderstore.js";
import { resToJson } from "../lib/commons/replies.js";
import { checkOrgateam } from "./checkAccessHandlers.js";
import User from "jc-shared/user/user.js";
import userstore from "../lib/users/userstore.js";

const app = express();

function migrateToNewStructure(alleKalender: Kalender[], currentUser: User) {
const allUsers = userstore.allUsers();
allUsers.push(new User({ id: "booking", name: "Booking Team", email: "booking@jazzclub.de" }));
alleKalender.forEach((kalender) => {
if (!kalender.migrated) {
kalender.events.forEach((event) => {
event.enhance(allUsers);
});
kalender.migrated = true;
store.saveKalender(kalender, currentUser);
}
});
}

app.get("/programmheft/alle", [checkOrgateam], (req: Request, res: Response) => {
resToJson(res, store.alleKalender());
const alleKalender = store.alleKalender();
migrateToNewStructure(alleKalender, req.user as User);
resToJson(res, alleKalender);
});

app.get("/programmheft/:year/:month", [checkOrgateam], (req: Request, res: Response) => {
Expand Down
4 changes: 4 additions & 0 deletions application/backend/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ export function start() {
export function stop() {
server.close();
}
process.on("SIGINT", () => {
console.log("SHUTDOWN ON SIGINT (express)"); // eslint-disable-line no-console
server.close();
});
1 change: 0 additions & 1 deletion application/batchjobs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"test": "../node_modules/.bin/vitest --run",
"compile": "../node_modules/typescript/bin/tsc",
"deploy": "yarn compile",
"eslint": "../node_modules/.bin/eslint **/*.ts",
"clean-ts": "rm -f src/*.js || rm -f test/**/*.js || :"
}
}
2 changes: 0 additions & 2 deletions application/batchjobs/src/gigAndRentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ export function byDateRangeInAscendingOrder({
}: {
from: DatumUhrzeit;
to: DatumUhrzeit;
// eslint-disable-next-line no-unused-vars
konzerteFilter?: (ver: Konzert) => boolean;
// eslint-disable-next-line no-unused-vars
vermietungenFilter?: (ver: Vermietung) => boolean;
}) {
const alwaysTrue = () => true;
Expand Down
69 changes: 65 additions & 4 deletions application/batchjobs/src/sendMailsForProgrammheft.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,66 @@
import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js";
import { EmailEvent } from "jc-shared/programmheft/kalender.js";
import { Event } from "jc-shared/programmheft/Event.js";

import store from "jc-backend/lib/programmheft/kalenderstore.js";
import mailtransport from "jc-backend/lib/mailsender/mailtransport.js";
import MailMessage from "jc-shared/mail/mailMessage.js";
import User from "jc-shared/user/user.js";

export class EmailEvent {
event: Event;

constructor(event: Event) {
this.event = event;
}

private get datumUhrzeitToSend(): DatumUhrzeit {
return this.start.minus({ tage: this.event.emailOffset });
}

shouldSendOn(datumUhrzeit: DatumUhrzeit): boolean {
return Math.abs(this.datumUhrzeitToSend.differenzInTagen(datumUhrzeit)) === 0;
}

get start(): DatumUhrzeit {
return DatumUhrzeit.forISOString(this.event.start);
}

private selectedUsers(allUsers: User[]) {
return allUsers.filter((user) => {
return this.event.users.includes(user.id);
});
}

email(allUsers?: User[]): string[] {
if (!allUsers || !this.event.users.length) {
return (this.event.email ?? "").split(/[, ]+/).map((each) => each.trim());
} else {
return this.selectedUsers(allUsers).map((user) => user.email);
}
}

names(allUsers?: User[]): string {
if (!allUsers || !this.event.users.length) {
return this.event.wer ?? "";
} else {
return this.selectedUsers(allUsers)
.map((user) => user.name)
.join(", ");
}
}

body(allUsers?: User[]): string {
return `Hallo ${this.names(allUsers)},

hier eine automatische Erinnerungsmail:
${this.event.was}

Vielen Dank für Deine Arbeit und Unterstützung,
Damit alles reibungslos klappt, sollte dies bis zum ${this.start.tagMonatJahrLang} erledigt sein.

Danke & keep swingin'`;
}
}

async function sendMail(eventsForToday: EmailEvent[]) {
const messages = eventsForToday.map((e) => {
Expand All @@ -17,12 +74,16 @@ async function sendMail(eventsForToday: EmailEvent[]) {
return Promise.all(messages.map(mailtransport.sendMail));
}

export function eventsToSend(aDatumUhrzeit: DatumUhrzeit, events?: Event[]): EmailEvent[] {
const result = (events ?? []).filter((e) => !!e.email).map((e) => new EmailEvent(e));
return result.filter((e) => e.shouldSendOn(aDatumUhrzeit));
}

export async function remindForProgrammheft(now: DatumUhrzeit = new DatumUhrzeit()) {
const current = store.getCurrentKalender(now);
const next = store.getNextKalender(now);
if (!current || !next) {
if (!current && !next) {
return;
}
const events = [current, next].reduce((previous: EmailEvent[], current) => previous.concat(current.eventsToSend(now)), []);
return sendMail(events);
return sendMail(eventsToSend(now, current?.events).concat(eventsToSend(now, next?.events)));
}
7 changes: 1 addition & 6 deletions application/batchjobs/src/sendMailsNightlyPhotoAndFluegel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,7 @@ ${stuffToSend
return mailtransport.sendMail(message);
}

async function checkForFilter(
// eslint-disable-next-line no-unused-vars
filterFunction: (ver: Veranstaltung) => boolean,
variables: SendMailVariables,
now: DatumUhrzeit,
) {
async function checkForFilter(filterFunction: (ver: Veranstaltung) => boolean, variables: SendMailVariables, now: DatumUhrzeit) {
if (now.wochentag !== 0) {
// Sonntag
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import "jc-backend/configure.js";
import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js";
import kalenderstore from "jc-backend/lib/programmheft/kalenderstore.js";
import Kalender from "jc-shared/programmheft/kalender.js";
import { Event } from "jc-shared/programmheft/Event.js";
import mailtransport from "jc-backend/lib/mailsender/mailtransport.js";
import { remindForProgrammheft } from "../../src/sendMailsForProgrammheft.js";
import { EmailEvent, eventsToSend, remindForProgrammheft } from "../../src/sendMailsForProgrammheft.js";
import User from "jc-shared/user/user";

const sinon = sin.createSandbox();

Expand Down Expand Up @@ -60,4 +62,132 @@ Putzen`);
await remindForProgrammheft(april13 as DatumUhrzeit);
sinon.assert.notCalled(mailcheck);
});

describe("kalender creates correct content for sending (old Kalender Format)", () => {
const kalender = new Kalender({
id: "2020/12",
text: `Was | Anrede | Farbe | Wann | Email | Tage vorher
Irgendwas | Irgendwer | Green | 11.12.2020 |
Irgendwas | Irgendwer | Green | 13.12.2020 | andreas@andreas.as | 14
`,
});
const sendeDatum = DatumUhrzeit.forISOString("2020-11-29");

it("und berücksichtigt den Offset", () => {
const emailEvents = eventsToSend(sendeDatum, kalender.events);
expect(emailEvents).to.have.length(1);

const emailEvent = emailEvents[0];
expect(emailEvent.event).to.eql({
start: "2020-12-12T23:00:00.000Z",
farbe: "Green",
users: [],
email: "andreas@andreas.as",
emailOffset: 14,
was: "Irgendwas",
wer: "Irgendwer",
});
expect(emailEvent.email()).to.eql(["andreas@andreas.as"]);
expect(emailEvent.body()).to.eql(
`Hallo Irgendwer,

hier eine automatische Erinnerungsmail:
Irgendwas

Vielen Dank für Deine Arbeit und Unterstützung,
Damit alles reibungslos klappt, sollte dies bis zum 13. Dezember 2020 erledigt sein.

Danke & keep swingin'`,
);
});

it("parses new style filled text correctly (email und offset)", () => {
const event = kalender.events[1];
expect(event.start).to.eql("2020-12-12T23:00:00.000Z");
expect(event.title).to.eql("Irgendwas (Irgendwer)");
expect(event.farbe).to.eql("Green");
expect(event.email).to.eql("andreas@andreas.as");
expect(event.emailOffset).to.eql(14);

const nov29 = DatumUhrzeit.forGermanStringOrNow("29.11.20", "01:13");
expect(new EmailEvent(event).shouldSendOn(nov29)).toBeTruthy();
});
});

describe("kalender creates correct content for sending (new Kalender Format)", () => {
const events = [
{ users: [], start: "2020-12-10T23:00:00.000Z", farbe: "Green", email: "", emailOffset: 7, was: "Irgendwas", wer: "Irgendwer" },
{
users: [],
start: "2020-12-12T23:00:00.000Z",
farbe: "Green",
email: "andreas@andreas.as",
emailOffset: 14,
was: "Irgendwas",
wer: "Irgendwer",
},
];
const kalender = new Kalender({
id: "2020/12",
text: "",
events,
});
const sendeDatum = DatumUhrzeit.forISOString("2020-11-29");

it("und berücksichtigt den Offset", () => {
const emailEvents = eventsToSend(sendeDatum, kalender.events);
expect(emailEvents).to.have.length(1);

const emailEvent = emailEvents[0];
expect(emailEvent.event).to.eql({
start: "2020-12-12T23:00:00.000Z",
farbe: "Green",
users: [],
email: "andreas@andreas.as",
emailOffset: 14,
was: "Irgendwas",
wer: "Irgendwer",
});
expect(emailEvent.email()).to.eql(["andreas@andreas.as"]);
expect(emailEvent.body()).to.eql(
`Hallo Irgendwer,

hier eine automatische Erinnerungsmail:
Irgendwas

Vielen Dank für Deine Arbeit und Unterstützung,
Damit alles reibungslos klappt, sollte dies bis zum 13. Dezember 2020 erledigt sein.

Danke & keep swingin'`,
);
});
});

it("handles events with users correctly", () => {
const allUsers = [new User({ id: "jott", name: "Andreas", email: "andreas@andreas.new" })];
const event = new Event({
users: ["jott"],
start: "2020-12-12T23:00:00.000Z",
farbe: "Green",
email: "andreas@andreas.as",
emailOffset: 14,
was: "Irgendwas",
wer: "Irgendwer",
});

const emailEvent = new EmailEvent(event);

expect(emailEvent.email(allUsers)).to.eql(["andreas@andreas.new"]);
expect(emailEvent.body(allUsers)).to.eql(
`Hallo Andreas,

hier eine automatische Erinnerungsmail:
Irgendwas

Vielen Dank für Deine Arbeit und Unterstützung,
Damit alles reibungslos klappt, sollte dies bis zum 13. Dezember 2020 erledigt sein.

Danke & keep swingin'`,
);
});
});
2 changes: 0 additions & 2 deletions application/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ export default tseslint.config(
"no-console": "error",
"no-sync": "error",
"no-process-exit": "error",
"no-unused-vars": "error",
eqeqeq: "error",
"react-refresh/only-export-components": "error",
},
plugins: { prettier, "react-refresh": reactRefresh },
files: ["**/*.ts", "**/*.tsx"],
ignores: ["node_modules"],
},
{
files: ["**/*.{js,jsx,mjs,cjs,ts,tsx}"],
Expand Down
2 changes: 1 addition & 1 deletion application/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"deploy": "yarn workspaces foreach --all -p run deploy",
"develop": "yarn compile && cd vue && yarn dev",
"dev": "cd vue && yarn dev",
"eslint": "yarn workspaces foreach --all -p run eslint",
"eslint": "./node_modules/.bin/eslint **/*.ts* --no-warn-ignored",
"start": "node start",
"test": "yarn workspaces foreach --all -p run test",
"clean-all-modules": "rm -rf node_modules backend/node_modules batchjobs/node_modules shared/node_modules vue/node_modules"
Expand Down
1 change: 0 additions & 1 deletion application/rider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"scripts": {
"dev": "vite --port 1969",
"deploy": "vite build",
"eslint": "../node_modules/.bin/eslint src/**/*.ts*",
"serve": "rm -rf ../backend/static/rider && vite preview --port 1969"
},
"dependencies": {
Expand Down
4 changes: 4 additions & 0 deletions application/shared/commons/DatumUhrzeit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ export default class DatumUhrzeit {
return Math.trunc(this.value.diff(other.value, "day"));
}

differenzInMonaten(other: DatumUhrzeit): number {
return Math.trunc(this.value.diff(other.value, "month"));
}

moveByDifferenceDays(newDate: Dayjs) {
const diff = new DatumUhrzeit(newDate).setUhrzeit(8, 0).differenzInTagen(this.setUhrzeit(8, 0));
return this.plus({ tage: diff }).value;
Expand Down
Loading