(wip) - show repeating events in calendar (admin)
script to get jwt signature for Apple ID
This commit is contained in:
@ -1,67 +0,0 @@
|
||||
#!/bin/node
|
||||
# https://gist.githubusercontent.com/balazsorban44/09613175e7b37ec03f676dcefb7be5eb/raw/b0d31aa0c7f58e0088fdf59ec30cad1415a3475b/apple-gen-secret.mjs
|
||||
|
||||
import { SignJWT } from "jose"
|
||||
import { createPrivateKey } from "crypto"
|
||||
|
||||
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
||||
console.log(`
|
||||
Creates a JWT from the components found at Apple.
|
||||
By default, the JWT has a 6 months expiry date.
|
||||
Read more: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048
|
||||
|
||||
Usage:
|
||||
node apple.mjs [--kid] [--iss] [--private_key] [--sub] [--expires_in] [--exp]
|
||||
|
||||
Options:
|
||||
--help Print this help message
|
||||
--kid, --key_id The key id of the private key
|
||||
--iss, --team_id The Apple team ID
|
||||
--private_key The private key to use to sign the JWT. (Starts with -----BEGIN PRIVATE KEY-----)
|
||||
--sub, --client_id The client id to use in the JWT.
|
||||
--expires_in Number of seconds from now when the JWT should expire. Defaults to 6 months.
|
||||
--exp Future date in seconds when the JWT expires
|
||||
`)
|
||||
} else {
|
||||
const args = process.argv.slice(2).reduce((acc, arg, i) => {
|
||||
if (arg.match(/^--\w/)) {
|
||||
const key = arg.replace(/^--/, "").toLowerCase()
|
||||
acc[key] = process.argv[i + 3]
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
const {
|
||||
team_id,
|
||||
iss = team_id,
|
||||
|
||||
private_key,
|
||||
|
||||
client_id,
|
||||
sub = client_id,
|
||||
|
||||
key_id,
|
||||
kid = key_id,
|
||||
|
||||
expires_in = 86400 * 180,
|
||||
exp = Math.ceil(Date.now() / 1000) + expires_in,
|
||||
} = args
|
||||
|
||||
/**
|
||||
* How long is the secret valid in seconds.
|
||||
* @default 15780000
|
||||
*/
|
||||
const expiresAt = Math.ceil(Date.now() / 1000) + expires_in
|
||||
const expirationTime = exp ?? expiresAt
|
||||
console.log(`
|
||||
Apple client secret generated. Valid until: ${new Date(expirationTime * 1000)}
|
||||
|
||||
${await new SignJWT({})
|
||||
.setAudience("https://appleid.apple.com")
|
||||
.setIssuer(iss)
|
||||
.setIssuedAt()
|
||||
.setExpirationTime(expirationTime)
|
||||
.setSubject(sub)
|
||||
.setProtectedHeader({ alg: "ES256", kid })
|
||||
.sign(createPrivateKey(private_key.replace(/\\n/g, "\n")))}`)
|
||||
}
|
@ -298,7 +298,7 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
|
||||
return itemStart && itemEnd &&
|
||||
(slotStart.getTime() < itemEnd.getTime()) &&
|
||||
(slotEnd.getTime() > itemStart.getTime());
|
||||
(slotEnd.getTime() >= itemStart.getTime());
|
||||
});
|
||||
|
||||
slots.push({
|
||||
|
@ -17,7 +17,7 @@ import { MdToday } from 'react-icons/md';
|
||||
import { useSwipeable } from 'react-swipeable';
|
||||
import axiosInstance from '../../src/axiosSecure';
|
||||
// import { set, format, addDays } from 'date-fns';
|
||||
import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
|
||||
// import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
|
||||
import { filter } from 'jszip';
|
||||
import e from 'express';
|
||||
|
||||
@ -170,6 +170,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
};
|
||||
const filterEvents = (evts, publisherId, startdate) => {
|
||||
setDate(startdate); // Assuming setDate is a function that sets some state or context
|
||||
const filterHHmm = new Date(startdate).getHours() * 100 + new Date(startdate).getMinutes();
|
||||
|
||||
// Filter events based on the publisher ID and the start date/time
|
||||
const existingEvents = evts?.filter(event => {
|
||||
@ -177,15 +178,15 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
const isPublisherMatch = (event.publisher?.id || event.publisherId) === publisherId;
|
||||
|
||||
let isDateMatch;
|
||||
const eventDate = new Date(event.startTime);
|
||||
if (event.repeatWeekly && event.date) {
|
||||
// Compare only the time part
|
||||
const eventDate = new Date(event.startTime);
|
||||
const isSameHour = getHours(eventDate) === getHours(startdate);
|
||||
const isSameMinute = getMinutes(eventDate) === getMinutes(startdate);
|
||||
isDateMatch = isSameHour && isSameMinute;
|
||||
let evenStarttHHmm = eventDate.getHours() * 100 + eventDate.getMinutes();
|
||||
let eventEndHHmm = eventDate.getHours() * 100 + eventDate.getMinutes();
|
||||
isDateMatch = filterHHmm >= evenStarttHHmm && filterHHmm <= eventEndHHmm;
|
||||
} else if (event.date) {
|
||||
// Compare the full date
|
||||
isDateMatch = isSameDay(new Date(event.date), startdate);
|
||||
// Compare the full date. issameday is not working. do it manually
|
||||
isDateMatch = eventDate.setHours(0, 0, 0, 0) === new Date(startdate).setHours(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return isPublisherMatch && isDateMatch;
|
||||
@ -203,7 +204,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
maxTime.setHours(maxHour, 0, 0);
|
||||
const totalHours = maxHour - minHour;
|
||||
|
||||
const handleSelect = ({ start, end }) => {
|
||||
const handleSelect = ({ mode, start, end }) => {
|
||||
const startdate = typeof start === 'string' ? new Date(start) : start;
|
||||
const enddate = typeof end === 'string' ? new Date(end) : end;
|
||||
|
||||
@ -230,6 +231,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
setDate(start);
|
||||
|
||||
// get exising events for the selected date
|
||||
//ToDo: properly fix this. filterEvents does not return the expcted results
|
||||
let existingEvents = filterEvents(evts, publisherId, startdate);
|
||||
// if existingEvents is empty - create new with the selected range
|
||||
if (existingEvents.length === 0) {
|
||||
|
40
pages/api/auth/apple-token.ts
Normal file
40
pages/api/auth/apple-token.ts
Normal file
@ -0,0 +1,40 @@
|
||||
// pages/api/auth/apple-token.js
|
||||
import jwt from 'jsonwebtoken';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
const dotenv = require("dotenv");
|
||||
|
||||
|
||||
export default async function handler(req, res) {
|
||||
if (req.method === 'GET') {
|
||||
try {
|
||||
const appleKey = fs.readFileSync(path.resolve('./_deploy/appleKey.p8'), 'utf8');
|
||||
|
||||
const token = jwt.sign({}, appleKey, {
|
||||
algorithm: 'ES256',
|
||||
expiresIn: '180d',
|
||||
issuer: process.env.APPLE_TEAM_ID,
|
||||
header: {
|
||||
alg: 'ES256',
|
||||
kid: process.env.APPLE_KEY_ID,
|
||||
},
|
||||
audience: 'https://appleid.apple.com',
|
||||
subject: process.env.APPLE_ID,
|
||||
});
|
||||
|
||||
// Redirect to Apple's authentication page, or send the token to the client to do so
|
||||
console.log(token);
|
||||
res.status(200).send({
|
||||
message: 'Generated token for Apple Sign In',
|
||||
token: token
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error signing in with Apple:', error);
|
||||
res.status(500).send({ error: 'Failed to sign in with Apple' });
|
||||
}
|
||||
} else {
|
||||
// Handle any non-GET requests
|
||||
res.setHeader('Allow', ['GET']);
|
||||
res.status(405).end(`Method ${req.method} Not Allowed`);
|
||||
}
|
||||
}
|
@ -161,8 +161,9 @@ export default async function handler(req, res) {
|
||||
res.status(200).json(publishers);
|
||||
break;
|
||||
case "filterPublishersNew":
|
||||
let includeOldAvailabilities = common.parseBool(req.query.includeOldAvailabilities);
|
||||
let results = await filterPublishersNew_Available(req.query.select, day,
|
||||
common.parseBool(req.query.isExactTime), common.parseBool(req.query.isForTheMonth));
|
||||
common.parseBool(req.query.isExactTime), common.parseBool(req.query.isForTheMonth), includeOldAvailabilities);
|
||||
res.status(200).json(results);
|
||||
break;
|
||||
|
||||
@ -461,8 +462,8 @@ export async function getMonthlyStatistics(selectFields, filterDate) {
|
||||
}
|
||||
|
||||
|
||||
export async function filterPublishersNew_Available(selectFields, filterDate, isExactTime = false, isForTheMonth = false, isWithStats = true) {
|
||||
return data.filterPublishersNew(selectFields, filterDate, isExactTime, isForTheMonth, isWithStats);
|
||||
export async function filterPublishersNew_Available(selectFields, filterDate, isExactTime = false, isForTheMonth = false, isWithStats = true, includeOldAvailabilities = false) {
|
||||
return data.filterPublishersNew(selectFields, filterDate, isExactTime, isForTheMonth, isWithStats, includeOldAvailabilities);
|
||||
}
|
||||
|
||||
// availabilites filter:
|
||||
|
@ -76,15 +76,15 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
||||
const [modalPub, setModalPub] = useState(null);
|
||||
|
||||
// ------------------ no assignments checkbox ------------------
|
||||
const [isCheckboxChecked, setIsCheckboxChecked] = useState(false);
|
||||
const [filterShowWithoutAssignments, setFilterShowWithoutAssignments] = useState(false);
|
||||
const handleCheckboxChange = (event) => {
|
||||
setIsCheckboxChecked(!isCheckboxChecked); // Toggle the checkbox state
|
||||
setFilterShowWithoutAssignments(!filterShowWithoutAssignments); // Toggle the checkbox state
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("checkbox checked: " + isCheckboxChecked);
|
||||
console.log("checkbox checked: " + filterShowWithoutAssignments);
|
||||
handleCalDateChange(value); // Call handleCalDateChange whenever isCheckboxChecked changes
|
||||
}, [isCheckboxChecked]); // Dependency array
|
||||
}, [filterShowWithoutAssignments]); // Dependency array
|
||||
|
||||
const [selectedMonth, setSelectedMonth] = useState(new Date().getMonth());
|
||||
useEffect(() => {
|
||||
@ -99,7 +99,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
||||
var date = new Date(common.getDateFromDateTime(selectedDate));//ToDo: check if seting the timezone affects the selectedDate?!
|
||||
var dateStr = common.getISODateOnly(date);
|
||||
console.log("Setting date to '" + date.toLocaleDateString() + "' from '" + selectedDate.toLocaleDateString() + "'. ISO: " + date.toISOString(), "locale ISO:", common.getISODateOnly(date));
|
||||
if (isCheckboxChecked) {
|
||||
if (filterShowWithoutAssignments) {
|
||||
console.log(`getting unassigned publishers for ${common.getMonthName(date.getMonth())} ${date.getFullYear()}`);
|
||||
const { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=getUnassignedPublishers&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth`);
|
||||
setAvailablePubs(availablePubsForDate);
|
||||
@ -110,7 +110,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
||||
const { data: shiftsForDate } = await axiosInstance.get(`/api/?action=getShiftsForDay&date=${dateStr}`);
|
||||
setShifts(shiftsForDate);
|
||||
setIsPublished(shiftsForDate.some(shift => shift.isPublished));
|
||||
let { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=filterPublishersNew&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth`);
|
||||
let { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=filterPublishersNew&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth&includeOldAvailabilities=${filterShowWithoutAssignments}`);
|
||||
|
||||
availablePubsForDate.forEach(pub => {
|
||||
pub.canTransport = pub.availabilities.some(av =>
|
||||
@ -664,9 +664,10 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
||||
|
||||
<h2 className="text-lg font-semibold mb-4">Достъпни за този ден: <span className="text-blue-600">{availablePubs.length}</span></h2>
|
||||
<label className="toggle pb-3">
|
||||
<input type="checkbox" className="toggle-checkbox" onChange={handleCheckboxChange} />
|
||||
<input type="checkbox" className="toggle-checkbox" id="filterShowWithoutAssignments" onChange={handleCheckboxChange} />
|
||||
<span className="toggle-slider m-1">без назначения за месеца</span>
|
||||
|
||||
<input type="checkbox" className="toggle-checkbox" id="filterIncludeOldAvailabilities" onChange={handleCheckboxChange} />
|
||||
<span className="toggle-slider m-1">със стари предпочитания</span>
|
||||
</label>
|
||||
<ul className="w-full max-w-md">
|
||||
{Array.isArray(availablePubs) && availablePubs?.map((pub, index) => {
|
||||
@ -891,6 +892,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
||||
|
||||
import axiosServer from '../../../src/axiosServer';
|
||||
import { start } from 'repl';
|
||||
import { filter } from 'jszip';
|
||||
export const getServerSideProps = async (context) => {
|
||||
const axios = await axiosServer(context);
|
||||
// const baseUrl = common.getBaseUrl();
|
||||
|
@ -6,18 +6,11 @@ const levenshtein = require('fastest-levenshtein');
|
||||
|
||||
const fs = typeof window === 'undefined' ? require('fs') : undefined;
|
||||
const path = typeof window === 'undefined' ? require('path') : undefined;
|
||||
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const { PrismaClient, UserRole } = require('@prisma/client');
|
||||
const DayOfWeek = require("@prisma/client").DayOfWeek;
|
||||
|
||||
const winston = require('winston');
|
||||
// User and auth functions
|
||||
// import { getSession } from "next-auth/react";
|
||||
// import { UserRole } from "@prisma/client";
|
||||
//convert to es6 import
|
||||
const { getSession } = require("next-auth/react");
|
||||
const { UserRole } = require("@prisma/client");
|
||||
// const { set } = require('date-fns');
|
||||
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: 'info', // Set the default log level
|
||||
@ -334,6 +327,18 @@ exports.compareTimes = function (time1, time2) {
|
||||
const time2String = `${getHours(time2)}:${getMinutes(time2)}`;
|
||||
return time1String.localeCompare(time2String);
|
||||
};
|
||||
exports.normalizeTime = function (date, baseDate) {
|
||||
// return set(baseDate, {
|
||||
// hours: getHours(date),
|
||||
// minutes: getMinutes(date),
|
||||
// seconds: getSeconds(date),
|
||||
// milliseconds: 0
|
||||
// });
|
||||
//don't use date-fns
|
||||
let newDate = new Date(baseDate);
|
||||
newDate.setHours(date.getHours(), date.getMinutes(), date.getSeconds(), 0);
|
||||
return newDate;
|
||||
}
|
||||
|
||||
exports.getTimeRange = function (start, end) {
|
||||
start = new Date(start);
|
||||
|
@ -228,7 +228,7 @@ async function getAvailabilities(userId) {
|
||||
}
|
||||
|
||||
|
||||
async function filterPublishersNew(selectFields, filterDate, isExactTime = false, isForTheMonth = false, isWithStats = true) {
|
||||
async function filterPublishersNew(selectFields, filterDate, isExactTime = false, isForTheMonth = false, isWithStats = true, includeOldAvailabilities = false) {
|
||||
|
||||
filterDate = new Date(filterDate); // Convert to date object if not already
|
||||
|
||||
|
Reference in New Issue
Block a user