Migrate availability schedule for everyone (#1179)
* wip * tmp mig * add cron api key to header * feels safer * Revert "wip" This reverts commit 15a8358661c6785ce9eedb93a473a8829f79d760. * test * add name * normalize dates * maybe works * test * fixz * maybe fix ci * deprecated * step 1 -- raw sql * seems to work * migration seems to work * br * fix comment * timouet * disconnect prisma test * test order * maybs * seems to work * tz * tweak Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
parent
bbf96a2e1d
commit
05fa1feab0
7 changed files with 1560 additions and 466 deletions
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
|
@ -2,6 +2,7 @@ name: Build
|
||||||
on: [push]
|
on: [push]
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
timeout-minutes: 5
|
||||||
name: Build on Node ${{ matrix.node }} and ${{ matrix.os }}
|
name: Build on Node ${{ matrix.node }} and ${{ matrix.os }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
|
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
|
@ -53,9 +53,9 @@ jobs:
|
||||||
path: ${{ github.workspace }}/.next/cache
|
path: ${{ github.workspace }}/.next/cache
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-nextjs
|
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-nextjs
|
||||||
|
|
||||||
- run: yarn test
|
|
||||||
- run: yarn prisma migrate deploy
|
- run: yarn prisma migrate deploy
|
||||||
- run: yarn db-seed
|
- run: yarn db-seed
|
||||||
|
- run: yarn test
|
||||||
- run: yarn build
|
- run: yarn build
|
||||||
- run: yarn start &
|
- run: yarn start &
|
||||||
- run: npx wait-port 3000 --timeout 10000
|
- run: npx wait-port 3000 --timeout 10000
|
||||||
|
|
|
@ -126,7 +126,7 @@
|
||||||
"eslint-plugin-react": "^7.27.1",
|
"eslint-plugin-react": "^7.27.1",
|
||||||
"eslint-plugin-react-hooks": "^4.3.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
"husky": "^7.0.1",
|
"husky": "^7.0.1",
|
||||||
"jest": "^27.2.2",
|
"jest": "^26.0.0",
|
||||||
"jest-playwright": "^0.0.1",
|
"jest-playwright": "^0.0.1",
|
||||||
"jest-playwright-preset": "^1.7.0",
|
"jest-playwright-preset": "^1.7.0",
|
||||||
"kont": "^0.5.1",
|
"kont": "^0.5.1",
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
"prisma": "^2.30.2",
|
"prisma": "^2.30.2",
|
||||||
"tailwindcss": "^2.2.19",
|
"tailwindcss": "^2.2.19",
|
||||||
"ts-jest": "^27.0.7",
|
"ts-jest": "^26.0.0",
|
||||||
"ts-node": "^10.2.1",
|
"ts-node": "^10.2.1",
|
||||||
"typescript": "^4.5.2"
|
"typescript": "^4.5.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
insert into "Availability" ("userId", "startTime", "endTime", "days")
|
||||||
|
select
|
||||||
|
id as "userId",
|
||||||
|
CAST(CONCAT(CAST(("startTime") AS text), ' minute')::interval AS time) as "startTime",
|
||||||
|
CAST(CONCAT(CAST(("endTime") AS text), ' minute')::interval AS time) as "endTime",
|
||||||
|
ARRAY [0,1,2,3,4,5,6]
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select
|
||||||
|
users.id,
|
||||||
|
users."startTime",
|
||||||
|
users."endTime",
|
||||||
|
users."timeZone",
|
||||||
|
count("Availability".id) as availability_count
|
||||||
|
from users
|
||||||
|
left join "Availability" on "Availability"."userId" = users.id
|
||||||
|
group by users.id
|
||||||
|
) usersWithAvailabilityNumber
|
||||||
|
where availability_count < 1
|
|
@ -81,8 +81,10 @@ model User {
|
||||||
avatar String?
|
avatar String?
|
||||||
timeZone String @default("Europe/London")
|
timeZone String @default("Europe/London")
|
||||||
weekStart String @default("Sunday")
|
weekStart String @default("Sunday")
|
||||||
|
// DEPRECATED - TO BE REMOVED
|
||||||
startTime Int @default(0)
|
startTime Int @default(0)
|
||||||
endTime Int @default(1440)
|
endTime Int @default(1440)
|
||||||
|
// </DEPRECATED>
|
||||||
bufferTime Int @default(0)
|
bufferTime Int @default(0)
|
||||||
hideBranding Boolean @default(false)
|
hideBranding Boolean @default(false)
|
||||||
theme String?
|
theme String?
|
||||||
|
|
219
test/tmpMigration.test.ts
Normal file
219
test/tmpMigration.test.ts
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import timezone from "dayjs/plugin/timezone";
|
||||||
|
import utc from "dayjs/plugin/utc";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
import prisma from "../lib/prisma";
|
||||||
|
import { randomString } from "../playwright/lib/testUtils";
|
||||||
|
|
||||||
|
dayjs.extend(utc);
|
||||||
|
dayjs.extend(timezone);
|
||||||
|
|
||||||
|
async function tmpMigration() {
|
||||||
|
// console.log(
|
||||||
|
// await prisma.$queryRaw(`
|
||||||
|
// select
|
||||||
|
// id as "userId",
|
||||||
|
// CAST(CONCAT(CAST(("startTime") AS text), ' minute')::interval AS time) as "startTime",
|
||||||
|
// CAST(CONCAT(CAST(("endTime") AS text), ' minute')::interval AS time) as "endTime",
|
||||||
|
// ARRAY [0,1,2,3,4,5,6]
|
||||||
|
// from
|
||||||
|
// (
|
||||||
|
// select
|
||||||
|
// users.id,
|
||||||
|
// users."startTime",
|
||||||
|
// users."endTime",
|
||||||
|
// users."timeZone",
|
||||||
|
// count("Availability".id) as availability_count
|
||||||
|
// from users
|
||||||
|
// left join "Availability" on "Availability"."userId" = users.id
|
||||||
|
// group by users.id
|
||||||
|
// ) usersWithAvailabilityNumber
|
||||||
|
// where availability_count < 1
|
||||||
|
// `)
|
||||||
|
// );
|
||||||
|
const MIGRATION_SQL = fs
|
||||||
|
.readFileSync(__dirname + "/../prisma/migrations/20211115182559_availability_issue/migration.sql")
|
||||||
|
.toString();
|
||||||
|
await prisma.$queryRaw(MIGRATION_SQL);
|
||||||
|
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
afterAll(async () => {
|
||||||
|
await prisma.$disconnect();
|
||||||
|
});
|
||||||
|
test("tmpMigration", async () => {
|
||||||
|
const ONE_MINUTE_BEFORE_MIDNIGHT = 1440 - 1;
|
||||||
|
// const unknownTimezoneUser = await prisma.user.create({
|
||||||
|
// data: {
|
||||||
|
// name: "unknownTimezoneUser",
|
||||||
|
// email: `${randomString()}@example.com`,
|
||||||
|
// startTime: 0, // midnight
|
||||||
|
// endTime: 1380, // midnight
|
||||||
|
// timeZone: null,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
const europeUser = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
name: "europeanUser0to1380",
|
||||||
|
email: `${randomString()}@example.com`,
|
||||||
|
startTime: 0, // midnight
|
||||||
|
endTime: 1380, // 23:00
|
||||||
|
timeZone: "Europe/London",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const americanUser = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
name: "americanUser0toONE_MINUTE_BEFORE_MIDNIGHT",
|
||||||
|
email: `${randomString()}@example.com`,
|
||||||
|
startTime: 0, // midnight
|
||||||
|
endTime: ONE_MINUTE_BEFORE_MIDNIGHT, // midnight
|
||||||
|
timeZone: "America/Los_Angeles",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const baseDate = dayjs.utc().set("hour", 0).set("minute", 0).set("second", 0).set("millisecond", 0);
|
||||||
|
|
||||||
|
const unaffectedUser = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: `${randomString()}@example.com`,
|
||||||
|
name: "unaffectedUser0toONE_MINUTE_BEFORE_MIDNIGHTu",
|
||||||
|
startTime: 0, // midnight
|
||||||
|
endTime: ONE_MINUTE_BEFORE_MIDNIGHT, // midnight
|
||||||
|
timeZone: "America/Los_Angeles",
|
||||||
|
availability: {
|
||||||
|
create: {
|
||||||
|
startTime: baseDate.add(9, "hour").toDate(),
|
||||||
|
endTime: baseDate.add(17, "hour").toDate(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const weirdUser = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: `${randomString()}@example.com`,
|
||||||
|
name: "weirdUser",
|
||||||
|
startTime: 54000,
|
||||||
|
endTime: 96000,
|
||||||
|
timeZone: "America/Los_Angeles",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await tmpMigration();
|
||||||
|
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
in: [
|
||||||
|
//
|
||||||
|
europeUser.id,
|
||||||
|
americanUser.id,
|
||||||
|
unaffectedUser.id,
|
||||||
|
weirdUser.id,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
startTime: true,
|
||||||
|
endTime: true,
|
||||||
|
timeZone: true,
|
||||||
|
availability: {
|
||||||
|
select: {
|
||||||
|
days: true,
|
||||||
|
date: true,
|
||||||
|
startTime: true,
|
||||||
|
endTime: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const usersWithNormalizedDates = JSON.parse(JSON.stringify(users));
|
||||||
|
|
||||||
|
expect(usersWithNormalizedDates).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"availability": Array [
|
||||||
|
Object {
|
||||||
|
"date": null,
|
||||||
|
"days": Array [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
],
|
||||||
|
"endTime": "1970-01-01T23:00:00.000Z",
|
||||||
|
"startTime": "1970-01-01T00:00:00.000Z",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"endTime": 1380,
|
||||||
|
"name": "europeanUser0to1380",
|
||||||
|
"startTime": 0,
|
||||||
|
"timeZone": "Europe/London",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"availability": Array [
|
||||||
|
Object {
|
||||||
|
"date": null,
|
||||||
|
"days": Array [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
],
|
||||||
|
"endTime": "1970-01-01T23:59:00.000Z",
|
||||||
|
"startTime": "1970-01-01T00:00:00.000Z",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"endTime": 1439,
|
||||||
|
"name": "americanUser0toONE_MINUTE_BEFORE_MIDNIGHT",
|
||||||
|
"startTime": 0,
|
||||||
|
"timeZone": "America/Los_Angeles",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"availability": Array [
|
||||||
|
Object {
|
||||||
|
"date": null,
|
||||||
|
"days": Array [],
|
||||||
|
"endTime": "1970-01-01T17:00:00.000Z",
|
||||||
|
"startTime": "1970-01-01T09:00:00.000Z",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"endTime": 1439,
|
||||||
|
"name": "unaffectedUser0toONE_MINUTE_BEFORE_MIDNIGHTu",
|
||||||
|
"startTime": 0,
|
||||||
|
"timeZone": "America/Los_Angeles",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"availability": Array [
|
||||||
|
Object {
|
||||||
|
"date": null,
|
||||||
|
"days": Array [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
],
|
||||||
|
"endTime": "1970-01-01T16:00:00.000Z",
|
||||||
|
"startTime": "1970-01-01T12:00:00.000Z",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"endTime": 96000,
|
||||||
|
"name": "weirdUser",
|
||||||
|
"startTime": 54000,
|
||||||
|
"timeZone": "America/Los_Angeles",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
Loading…
Reference in a new issue