Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1722edbd36 | ||
|
|
e68ab3b123 | ||
|
|
cf16cd3ed2 | ||
|
|
f4bc7d2ea4 | ||
|
|
f5f7242f02 | ||
|
|
8f5ac26bb1 | ||
|
|
b983adb16a | ||
|
|
8ce018995a | ||
|
|
f11086e9f8 | ||
|
|
91f5d49cd4 | ||
|
|
55e1e0fa3d | ||
|
|
4a59841b02 | ||
|
|
74a9f3c19e | ||
|
|
89250422ea | ||
|
|
2f2f4dba60 | ||
|
|
b292cafe7b | ||
|
|
82053e0c7c | ||
|
|
860d173f0a | ||
|
|
5bc0e1265d | ||
|
|
e362c37ff3 | ||
|
|
4d53f327d9 | ||
|
|
61f436be2a | ||
|
|
d1a0fc6604 | ||
|
|
976013512c | ||
|
|
d9777a3011 | ||
|
|
7725adedc8 | ||
|
|
7269b3ea60 | ||
|
|
c168df4df0 | ||
|
|
be9b0fb9a8 | ||
|
|
c056cabbbd | ||
|
|
97630e8add | ||
|
|
a5443ccfbe | ||
|
|
6f2986e42e | ||
|
|
db345de99e | ||
|
|
bde40dceb3 | ||
|
|
1a86e7c506 | ||
|
|
9ed1624111 | ||
|
|
5dff1c6df0 | ||
|
|
706d7dff42 | ||
|
|
71443ef23d | ||
|
|
17201334b6 | ||
|
|
bc82ff4d21 | ||
|
|
71ae3f157a | ||
|
|
8784be067f | ||
|
|
84a2e55125 | ||
|
|
21e23f32ac | ||
|
|
33aa9420af | ||
|
|
ef0ba48f49 | ||
|
|
6e54c459a4 | ||
|
|
f5c16f0d6b | ||
|
|
105e7d3e28 | ||
|
|
21ef1900e9 | ||
|
|
f07b73dc79 | ||
|
|
d4b0516235 | ||
|
|
7bfad11ff9 | ||
|
|
d2f7a427d0 | ||
|
|
a910eb96ad | ||
|
|
c080458faa | ||
|
|
5c75cfc17f | ||
|
|
4280f556cb | ||
|
|
21368bb130 | ||
|
|
e9076c8e3e | ||
|
|
2471ee801b | ||
|
+6 |
9fc9876b3f | ||
|
|
34ca3bd22d | ||
|
|
bebe1dd7b4 | ||
|
|
fced9a6355 |
@@ -334,6 +334,8 @@ AB_TEST_BUCKET_PROBABILITY=50
|
||||
# whether we redirect to the future/event-types from event-types or not
|
||||
APP_ROUTER_EVENT_TYPES_ENABLED=0
|
||||
APP_ROUTER_SETTINGS_ADMIN_ENABLED=0
|
||||
APP_ROUTER_SETTINGS_PLATFORM_ENABLED=0
|
||||
APP_ROUTER_SETTINGS_ORG_ENABLED=0
|
||||
APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED=0
|
||||
APP_ROUTER_APPS_SLUG_ENABLED=0
|
||||
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0
|
||||
@@ -357,6 +359,10 @@ APP_ROUTER_AUTH_SAML_ENABLED=0
|
||||
APP_ROUTER_AUTH_ERROR_ENABLED=0
|
||||
APP_ROUTER_AUTH_PLATFORM_ENABLED=0
|
||||
APP_ROUTER_AUTH_OAUTH2_ENABLED=0
|
||||
APP_ROUTER_MORE_ENABLED=0
|
||||
APP_ROUTER_MAINTENANCE_ENABLED=0
|
||||
APP_ROUTER_UPGRADE_ENABLED=0
|
||||
APP_ROUTER_CONNECT_AND_JOIN_ENABLED=0
|
||||
|
||||
# disable setry server source maps
|
||||
SENTRY_DISABLE_SERVER_WEBPACK_PLUGIN=1
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report any issues with the platform
|
||||
title: ""
|
||||
labels: ["🐛 bug"]
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
Found a bug? Please fill out the sections below. 👍
|
||||
|
||||
### Issue Summary
|
||||
|
||||
A summary of the issue. This needs to be a clear detailed-rich summary.
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
1. (for example) Went to ...
|
||||
2. Clicked on...
|
||||
3. ...
|
||||
|
||||
Any other relevant information. For example, why do you consider this a bug and what did you expect to happen instead?
|
||||
|
||||
### Actual Results
|
||||
|
||||
- What's happening right now that is different from what is expected
|
||||
|
||||
### Expected Results
|
||||
|
||||
- This is an ideal result that the system should get after the tests are performed
|
||||
|
||||
### Technical details
|
||||
|
||||
- Browser version, screen recording, console logs, network requests: You can make a recording with [Bird Eats Bug](https://birdeatsbug.com/).
|
||||
- Node.js version
|
||||
- Anything else that you think could be an issue.
|
||||
|
||||
### Evidence
|
||||
|
||||
- How was this tested? This is quite mandatory in terms of bugs. Providing evidence of your testing with screenshots or/and videos is an amazing way to prove the bug and a troubleshooting chance to find the solution.
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Please make sure you have checked for any duplicate issues
|
||||
title: ""
|
||||
labels: ["🐛 bug"]
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
### Is your proposal related to a problem?
|
||||
|
||||
<!--
|
||||
Provide a clear and concise description of what the problem is.
|
||||
For example, "I'm always frustrated when..."
|
||||
-->
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### Describe the solution you'd like
|
||||
|
||||
<!--
|
||||
Provide a clear and concise description of what you want to happen.
|
||||
-->
|
||||
|
||||
(Describe your proposed solution here.)
|
||||
|
||||
### Describe alternatives you've considered
|
||||
|
||||
<!--
|
||||
Let us know about other solutions you've tried or researched.
|
||||
-->
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### Additional context
|
||||
|
||||
<!--
|
||||
Is there anything else you can add about the proposal?
|
||||
You might want to link to related issues here, if you haven't already.
|
||||
-->
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### Requirement/Document
|
||||
|
||||
<!--
|
||||
Is there any type of document that could support that feature?
|
||||
-->
|
||||
|
||||
(Share it here.)
|
||||
@@ -1,28 +0,0 @@
|
||||
name: PR Reviewed
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
label-pr:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Label PR as ready for E2E
|
||||
if: github.event.review.state == 'approved'
|
||||
uses: actions/github-script@v4
|
||||
with:
|
||||
script: |
|
||||
await github.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: process.env.labels.split(', '),
|
||||
})
|
||||
env:
|
||||
github_token: ${{ secrets.READY_FOR_E2E_PAT }}
|
||||
labels: 'ready-for-e2e'
|
||||
@@ -168,6 +168,7 @@ export const schemaEventTypeReadPublic = EventType.pick({
|
||||
metadata: jsonSchema.nullable(),
|
||||
customInputs: customInputSchema.array().optional(),
|
||||
link: z.string().optional(),
|
||||
hashedLink: z.object({ link: z.string() }).optional().nullable(),
|
||||
bookingFields: eventTypeBookingFields.optional().nullable(),
|
||||
})
|
||||
);
|
||||
|
||||
@@ -51,6 +51,7 @@ export async function getHandler(req: NextApiRequest) {
|
||||
where: { id },
|
||||
include: {
|
||||
customInputs: true,
|
||||
hashedLink: { select: { link: true } },
|
||||
team: { select: { slug: true } },
|
||||
hosts: { select: { userId: true, isFixed: true } },
|
||||
owner: { select: { username: true, id: true } },
|
||||
|
||||
@@ -56,6 +56,7 @@ async function getHandler(req: NextApiRequest) {
|
||||
},
|
||||
include: {
|
||||
customInputs: true,
|
||||
hashedLink: { select: { link: true } },
|
||||
team: { select: { slug: true } },
|
||||
hosts: { select: { userId: true, isFixed: true } },
|
||||
owner: { select: { username: true, id: true } },
|
||||
|
||||
@@ -215,6 +215,7 @@ const generateTeamCheckoutSession = async ({
|
||||
metadata: {
|
||||
pendingPaymentTeamId,
|
||||
ownerId,
|
||||
dubCustomerId: ownerId, // pass the userId during checkout creation for sales conversion tracking: https://d.to/conversions/stripe
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"dependencies": {
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.33",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.34",
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
|
||||
@@ -5,7 +5,8 @@ import { BadRequestException, UnauthorizedException } from "@nestjs/common";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
import { SUCCESS_STATUS, APPLE_CALENDAR_TYPE, APPLE_CALENDAR_ID } from "@calcom/platform-constants";
|
||||
import { symmetricEncrypt, CalendarService } from "@calcom/platform-libraries";
|
||||
import { symmetricEncrypt, CalendarService, symmetricDecrypt } from "@calcom/platform-libraries";
|
||||
import { Credential } from "@calcom/prisma/client";
|
||||
|
||||
@Injectable()
|
||||
export class AppleCalendarService implements CredentialSyncCalendarApp {
|
||||
@@ -61,26 +62,70 @@ export class AppleCalendarService implements CredentialSyncCalendarApp {
|
||||
if (username.length <= 1 || password.length <= 1)
|
||||
throw new BadRequestException(`Username or password cannot be empty`);
|
||||
|
||||
const data = {
|
||||
type: APPLE_CALENDAR_TYPE,
|
||||
key: symmetricEncrypt(
|
||||
JSON.stringify({ username, password }),
|
||||
process.env.CALENDSO_ENCRYPTION_KEY || ""
|
||||
),
|
||||
userId: userId,
|
||||
teamId: null,
|
||||
appId: APPLE_CALENDAR_ID,
|
||||
invalid: false,
|
||||
};
|
||||
const existingAppleCalendarCredentials = await this.credentialRepository.getAllUserCredentialsByTypeAndId(
|
||||
APPLE_CALENDAR_TYPE,
|
||||
userId
|
||||
);
|
||||
|
||||
let hasMatchingUsernameAndPassword = false;
|
||||
|
||||
if (existingAppleCalendarCredentials.length > 0) {
|
||||
const hasCalendarWithGivenCredentials = existingAppleCalendarCredentials.find(
|
||||
(calendarCredential: Credential) => {
|
||||
const decryptedKey = JSON.parse(
|
||||
symmetricDecrypt(calendarCredential.key as string, process.env.CALENDSO_ENCRYPTION_KEY || "")
|
||||
);
|
||||
|
||||
if (decryptedKey.username === username) {
|
||||
if (decryptedKey.password === password) {
|
||||
hasMatchingUsernameAndPassword = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!!hasCalendarWithGivenCredentials && hasMatchingUsernameAndPassword) {
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
};
|
||||
}
|
||||
|
||||
if (!!hasCalendarWithGivenCredentials && !hasMatchingUsernameAndPassword) {
|
||||
await this.credentialRepository.upsertAppCredential(
|
||||
APPLE_CALENDAR_TYPE,
|
||||
symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY || ""),
|
||||
userId,
|
||||
hasCalendarWithGivenCredentials.id
|
||||
);
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const data = {
|
||||
type: APPLE_CALENDAR_TYPE,
|
||||
key: symmetricEncrypt(
|
||||
JSON.stringify({ username, password }),
|
||||
process.env.CALENDSO_ENCRYPTION_KEY || ""
|
||||
),
|
||||
userId: userId,
|
||||
teamId: null,
|
||||
appId: APPLE_CALENDAR_ID,
|
||||
invalid: false,
|
||||
};
|
||||
|
||||
const dav = new CalendarService({
|
||||
id: 0,
|
||||
...data,
|
||||
user: { email: userEmail },
|
||||
});
|
||||
await dav?.listCalendars();
|
||||
await this.credentialRepository.createAppCredential(APPLE_CALENDAR_TYPE, data.key, userId);
|
||||
await this.credentialRepository.upsertAppCredential(APPLE_CALENDAR_TYPE, data.key, userId);
|
||||
} catch (reason) {
|
||||
throw new BadRequestException(`Could not add this apple calendar account: ${reason}`);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from "@/modules/credentials/credentials.repository";
|
||||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
||||
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
|
||||
import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository";
|
||||
import { UsersRepository } from "@/modules/users/users.repository";
|
||||
import {
|
||||
Injectable,
|
||||
@@ -15,9 +16,11 @@ import {
|
||||
} from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { User } from "@prisma/client";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { DateTime } from "luxon";
|
||||
import { z } from "zod";
|
||||
|
||||
import { APPS_TYPE_ID_MAPPING } from "@calcom/platform-constants";
|
||||
import { getConnectedDestinationCalendars, getBusyCalendarTimes } from "@calcom/platform-libraries";
|
||||
import { Calendar } from "@calcom/platform-types";
|
||||
import { PrismaClient } from "@calcom/prisma";
|
||||
@@ -33,7 +36,8 @@ export class CalendarsService {
|
||||
private readonly calendarsRepository: CalendarsRepository,
|
||||
private readonly dbRead: PrismaReadService,
|
||||
private readonly dbWrite: PrismaWriteService,
|
||||
private readonly config: ConfigService
|
||||
private readonly config: ConfigService,
|
||||
private readonly selectedCalendarsRepository: SelectedCalendarsRepository
|
||||
) {}
|
||||
|
||||
async getCalendars(userId: number) {
|
||||
@@ -145,4 +149,32 @@ export class CalendarsService {
|
||||
throw new NotFoundException("Calendar credentials not found");
|
||||
}
|
||||
}
|
||||
|
||||
async createAndLinkCalendarEntry(
|
||||
userId: number,
|
||||
externalId: string,
|
||||
key: Prisma.InputJsonValue,
|
||||
calendarType: keyof typeof APPS_TYPE_ID_MAPPING,
|
||||
credentialId?: number | null
|
||||
) {
|
||||
const credential = await this.credentialsRepository.upsertAppCredential(
|
||||
calendarType,
|
||||
key,
|
||||
userId,
|
||||
credentialId
|
||||
);
|
||||
|
||||
await this.selectedCalendarsRepository.upsertSelectedCalendar(
|
||||
externalId,
|
||||
credential.id,
|
||||
userId,
|
||||
calendarType
|
||||
);
|
||||
}
|
||||
|
||||
async checkCalendarCredentialValidity(userId: number, credentialId: number, type: string) {
|
||||
const credential = await this.credentialsRepository.getUserCredentialById(userId, credentialId, type);
|
||||
|
||||
return !credential?.invalid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,11 +131,6 @@ export class GoogleCalendarService implements OAuthCalendarApp {
|
||||
const token = await oAuth2Client.getToken(parsedCode);
|
||||
// Google oAuth Credentials are stored in token.tokens
|
||||
const key = token.tokens;
|
||||
const credential = await this.credentialRepository.createAppCredential(
|
||||
GOOGLE_CALENDAR_TYPE,
|
||||
key as Prisma.InputJsonValue,
|
||||
ownerId
|
||||
);
|
||||
|
||||
oAuth2Client.setCredentials(key);
|
||||
|
||||
@@ -149,10 +144,39 @@ export class GoogleCalendarService implements OAuthCalendarApp {
|
||||
const primaryCal = cals.data.items?.find((cal) => cal.primary);
|
||||
|
||||
if (primaryCal?.id) {
|
||||
await this.selectedCalendarsRepository.createSelectedCalendar(
|
||||
primaryCal.id,
|
||||
credential.id,
|
||||
const alreadyExistingSelectedCalendar = await this.selectedCalendarsRepository.getUserSelectedCalendar(
|
||||
ownerId,
|
||||
GOOGLE_CALENDAR_TYPE,
|
||||
primaryCal.id
|
||||
);
|
||||
|
||||
if (alreadyExistingSelectedCalendar) {
|
||||
const isCredentialValid = await this.calendarsService.checkCalendarCredentialValidity(
|
||||
ownerId,
|
||||
alreadyExistingSelectedCalendar.credentialId ?? 0,
|
||||
GOOGLE_CALENDAR_TYPE
|
||||
);
|
||||
|
||||
// user credential probably got expired in this case
|
||||
if (!isCredentialValid) {
|
||||
await this.calendarsService.createAndLinkCalendarEntry(
|
||||
ownerId,
|
||||
alreadyExistingSelectedCalendar.externalId,
|
||||
key as Prisma.InputJsonValue,
|
||||
GOOGLE_CALENDAR_TYPE,
|
||||
alreadyExistingSelectedCalendar.credentialId
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
url: redir || origin,
|
||||
};
|
||||
}
|
||||
|
||||
await this.calendarsService.createAndLinkCalendarEntry(
|
||||
ownerId,
|
||||
primaryCal.id,
|
||||
key as Prisma.InputJsonValue,
|
||||
GOOGLE_CALENDAR_TYPE
|
||||
);
|
||||
}
|
||||
|
||||
@@ -168,16 +168,39 @@ export class OutlookService implements OAuthCalendarApp {
|
||||
const defaultCalendar = await this.getDefaultCalendar(office365OAuthCredentials.access_token);
|
||||
|
||||
if (defaultCalendar?.id) {
|
||||
const credential = await this.credentialRepository.createAppCredential(
|
||||
const alreadyExistingSelectedCalendar = await this.selectedCalendarsRepository.getUserSelectedCalendar(
|
||||
ownerId,
|
||||
OFFICE_365_CALENDAR_TYPE,
|
||||
office365OAuthCredentials,
|
||||
ownerId
|
||||
defaultCalendar.id
|
||||
);
|
||||
|
||||
await this.selectedCalendarsRepository.createSelectedCalendar(
|
||||
defaultCalendar.id,
|
||||
credential.id,
|
||||
if (alreadyExistingSelectedCalendar) {
|
||||
const isCredentialValid = await this.calendarsService.checkCalendarCredentialValidity(
|
||||
ownerId,
|
||||
alreadyExistingSelectedCalendar.credentialId ?? 0,
|
||||
OFFICE_365_CALENDAR_TYPE
|
||||
);
|
||||
|
||||
// user credential probably got expired in this case
|
||||
if (!isCredentialValid) {
|
||||
await this.calendarsService.createAndLinkCalendarEntry(
|
||||
ownerId,
|
||||
alreadyExistingSelectedCalendar.externalId,
|
||||
office365OAuthCredentials,
|
||||
OFFICE_365_CALENDAR_TYPE,
|
||||
alreadyExistingSelectedCalendar.credentialId
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
url: redir || origin,
|
||||
};
|
||||
}
|
||||
|
||||
await this.calendarsService.createAndLinkCalendarEntry(
|
||||
ownerId,
|
||||
defaultCalendar.id,
|
||||
office365OAuthCredentials,
|
||||
OFFICE_365_CALENDAR_TYPE
|
||||
);
|
||||
}
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
import { ApiProperty as DocsProperty } from "@nestjs/swagger";
|
||||
import { Transform } from "class-transformer";
|
||||
import { IsString, IsBoolean, IsOptional, IsEnum, Matches } from "class-validator";
|
||||
|
||||
export enum TemplateType {
|
||||
CHECK_IN_APPOINTMENT = "CHECK_IN_APPOINTMENT",
|
||||
CUSTOM_TEMPLATE = "CUSTOM_TEMPLATE",
|
||||
}
|
||||
|
||||
export class CreatePhoneCallInput {
|
||||
@IsString()
|
||||
@Matches(/^\+[1-9]\d{1,14}$/, {
|
||||
message:
|
||||
"Invalid phone number format. Expected format: +<CountryCode><PhoneNumber> with no spaces or separators.",
|
||||
})
|
||||
@DocsProperty({ description: "Your phone number" })
|
||||
yourPhoneNumber!: string;
|
||||
|
||||
@IsString()
|
||||
@Matches(/^\+[1-9]\d{1,14}$/, {
|
||||
message:
|
||||
"Invalid phone number format. Expected format: +<CountryCode><PhoneNumber> with no spaces or separators.",
|
||||
})
|
||||
@DocsProperty({ description: "Number to call" })
|
||||
numberToCall!: string;
|
||||
|
||||
@IsString()
|
||||
@DocsProperty({ description: "CAL API Key" })
|
||||
calApiKey!: string;
|
||||
|
||||
@IsBoolean()
|
||||
@DocsProperty({ description: "Enabled status", default: true })
|
||||
enabled = true;
|
||||
|
||||
@IsEnum(TemplateType)
|
||||
@DocsProperty({ description: "Template type", enum: TemplateType })
|
||||
templateType: TemplateType = TemplateType.CUSTOM_TEMPLATE;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@DocsProperty({ description: "Scheduler name" })
|
||||
schedulerName?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Transform(({ value }) => (value ? value : undefined))
|
||||
@DocsProperty({ description: "Guest name" })
|
||||
guestName?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Transform(({ value }) => (value ? value : undefined))
|
||||
@DocsProperty({ description: "Guest email" })
|
||||
guestEmail?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Transform(({ value }) => (value ? value : undefined))
|
||||
@DocsProperty({ description: "Guest company" })
|
||||
guestCompany?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@DocsProperty({ description: "Begin message" })
|
||||
beginMessage?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@DocsProperty({ description: "General prompt" })
|
||||
generalPrompt?: string;
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { Type } from "class-transformer";
|
||||
import { IsEnum, IsString, ValidateNested } from "class-validator";
|
||||
|
||||
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
|
||||
|
||||
class Data {
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
callId!: string;
|
||||
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
agentId!: string;
|
||||
}
|
||||
|
||||
export class CreatePhoneCallOutput {
|
||||
@ApiProperty({ example: SUCCESS_STATUS, enum: [SUCCESS_STATUS, ERROR_STATUS] })
|
||||
@IsEnum([SUCCESS_STATUS, ERROR_STATUS])
|
||||
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
|
||||
|
||||
@ApiProperty({
|
||||
type: Data,
|
||||
})
|
||||
@ValidateNested()
|
||||
@Type(() => Data)
|
||||
data!: Data;
|
||||
}
|
||||
@@ -1,10 +1,20 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsEnum } from "class-validator";
|
||||
import { IsEnum, IsNumber, IsString } from "class-validator";
|
||||
|
||||
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
|
||||
|
||||
export class ProviderVerifyClientData {
|
||||
@IsString()
|
||||
clientId!: string;
|
||||
@IsNumber()
|
||||
organizationId!: number;
|
||||
@IsString()
|
||||
name!: string;
|
||||
}
|
||||
export class ProviderVerifyClientOutput {
|
||||
@ApiProperty({ example: SUCCESS_STATUS, enum: [SUCCESS_STATUS, ERROR_STATUS] })
|
||||
@IsEnum([SUCCESS_STATUS, ERROR_STATUS])
|
||||
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
|
||||
|
||||
data!: ProviderVerifyClientData;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ export class CalProviderController {
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data: {
|
||||
clientId: oAuthClient.id,
|
||||
organizationId: oAuthClient.organizationId,
|
||||
name: oAuthClient.name,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ import { APPS_TYPE_ID_MAPPING } from "@calcom/platform-constants";
|
||||
export class CredentialsRepository {
|
||||
constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {}
|
||||
|
||||
async createAppCredential(
|
||||
async upsertAppCredential(
|
||||
type: keyof typeof APPS_TYPE_ID_MAPPING,
|
||||
key: Prisma.InputJsonValue,
|
||||
userId: number
|
||||
userId: number,
|
||||
credentialId?: number | null
|
||||
) {
|
||||
const credential = await this.getByTypeAndUserId(type, userId);
|
||||
return this.dbWrite.prisma.credential.upsert({
|
||||
create: {
|
||||
type,
|
||||
@@ -27,7 +27,7 @@ export class CredentialsRepository {
|
||||
invalid: false,
|
||||
},
|
||||
where: {
|
||||
id: credential?.id ?? 0,
|
||||
id: credentialId ?? 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -36,6 +36,10 @@ export class CredentialsRepository {
|
||||
return this.dbWrite.prisma.credential.findFirst({ where: { type, userId } });
|
||||
}
|
||||
|
||||
getAllUserCredentialsByTypeAndId(type: string, userId: number) {
|
||||
return this.dbRead.prisma.credential.findMany({ where: { type, userId } });
|
||||
}
|
||||
|
||||
getUserCredentialsByIds(userId: number, credentialIds: number[]) {
|
||||
return this.dbRead.prisma.credential.findMany({
|
||||
where: {
|
||||
@@ -60,6 +64,30 @@ export class CredentialsRepository {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getUserCredentialById(userId: number, credentialId: number, type: string) {
|
||||
return await this.dbRead.prisma.credential.findUnique({
|
||||
where: {
|
||||
userId,
|
||||
type,
|
||||
id: credentialId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
type: true,
|
||||
key: true,
|
||||
userId: true,
|
||||
teamId: true,
|
||||
appId: true,
|
||||
invalid: true,
|
||||
user: {
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type CredentialsWithUserEmail = Awaited<
|
||||
|
||||
@@ -6,6 +6,7 @@ import { DestinationCalendarsController } from "@/modules/destination-calendars/
|
||||
import { DestinationCalendarsRepository } from "@/modules/destination-calendars/destination-calendars.repository";
|
||||
import { DestinationCalendarsService } from "@/modules/destination-calendars/services/destination-calendars.service";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository";
|
||||
import { UsersRepository } from "@/modules/users/users.repository";
|
||||
import { Module } from "@nestjs/common";
|
||||
|
||||
@@ -19,6 +20,7 @@ import { Module } from "@nestjs/common";
|
||||
UsersRepository,
|
||||
CredentialsRepository,
|
||||
AppsRepository,
|
||||
SelectedCalendarsRepository,
|
||||
],
|
||||
controllers: [DestinationCalendarsController],
|
||||
exports: [DestinationCalendarsRepository],
|
||||
|
||||
+28
-1
@@ -1,3 +1,5 @@
|
||||
import { CreatePhoneCallInput } from "@/ee/event-types/event-types_2024_06_14/inputs/create-phone-call.input";
|
||||
import { CreatePhoneCallOutput } from "@/ee/event-types/event-types_2024_06_14/outputs/create-phone-call.output";
|
||||
import { API_VERSIONS_VALUES } from "@/lib/api-versions";
|
||||
import { PlatformPlan } from "@/modules/auth/decorators/billing/platform-plan.decorator";
|
||||
import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator";
|
||||
@@ -33,6 +35,7 @@ import {
|
||||
import { ApiTags as DocsTags } from "@nestjs/swagger";
|
||||
|
||||
import { SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import { handleCreatePhoneCall } from "@calcom/platform-libraries";
|
||||
import {
|
||||
CreateTeamEventTypeInput_2024_06_14,
|
||||
GetTeamEventTypesQuery_2024_06_14,
|
||||
@@ -91,6 +94,30 @@ export class OrganizationsEventTypesController {
|
||||
};
|
||||
}
|
||||
|
||||
@Roles("TEAM_ADMIN")
|
||||
@Post("/teams/:teamId/event-types/:eventTypeId/create-phone-call")
|
||||
@UseGuards(ApiAuthGuard, IsOrgGuard, IsTeamInOrg, RolesGuard)
|
||||
async createPhoneCall(
|
||||
@Param("eventTypeId") eventTypeId: number,
|
||||
@Param("orgId", ParseIntPipe) orgId: number,
|
||||
@Body() body: CreatePhoneCallInput,
|
||||
@GetUser() user: UserWithProfile
|
||||
): Promise<CreatePhoneCallOutput> {
|
||||
const data = await handleCreatePhoneCall({
|
||||
user: {
|
||||
id: user.id,
|
||||
timeZone: user.timeZone,
|
||||
profile: { organization: { id: orgId } },
|
||||
},
|
||||
input: { ...body, eventTypeId },
|
||||
});
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
@UseGuards(IsOrgGuard, IsTeamInOrg, IsAdminAPIEnabledGuard)
|
||||
@Get("/teams/:teamId/event-types")
|
||||
async getTeamEventTypes(
|
||||
@@ -138,7 +165,7 @@ export class OrganizationsEventTypesController {
|
||||
@Patch("/teams/:teamId/event-types/:eventTypeId")
|
||||
async updateTeamEventType(
|
||||
@Param("teamId", ParseIntPipe) teamId: number,
|
||||
@Param("eventTypeId") eventTypeId: number,
|
||||
@Param("eventTypeId", ParseIntPipe) eventTypeId: number,
|
||||
@GetUser() user: UserWithProfile,
|
||||
@Body() bodyEventType: UpdateTeamEventTypeInput_2024_06_14
|
||||
): Promise<UpdateTeamEventTypeOutput> {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Injectable } from "@nestjs/common";
|
||||
export class SelectedCalendarsRepository {
|
||||
constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {}
|
||||
|
||||
createSelectedCalendar(externalId: string, credentialId: number, userId: number, integration: string) {
|
||||
upsertSelectedCalendar(externalId: string, credentialId: number, userId: number, integration: string) {
|
||||
return this.dbWrite.prisma.selectedCalendar.upsert({
|
||||
create: {
|
||||
userId,
|
||||
@@ -38,6 +38,18 @@ export class SelectedCalendarsRepository {
|
||||
});
|
||||
}
|
||||
|
||||
getUserSelectedCalendar(userId: number, integration: string, externalId: string) {
|
||||
return this.dbRead.prisma.selectedCalendar.findUnique({
|
||||
where: {
|
||||
userId_integration_externalId: {
|
||||
userId,
|
||||
externalId,
|
||||
integration,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async addUserSelectedCalendar(
|
||||
userId: number,
|
||||
integration: string,
|
||||
|
||||
@@ -68,7 +68,6 @@ export class UsersRepository {
|
||||
}
|
||||
|
||||
async findByIdWithProfile(userId: number): Promise<UserWithProfile | null> {
|
||||
console.log("findByIdWithProfile");
|
||||
return this.dbRead.prisma.user.findUnique({
|
||||
where: {
|
||||
id: userId,
|
||||
|
||||
@@ -1982,6 +1982,54 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/organizations/{orgId}/teams/{teamId}/event-types/{eventTypeId}/create-phone-call": {
|
||||
"post": {
|
||||
"operationId": "OrganizationsEventTypesController_createPhoneCall",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "eventTypeId",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "orgId",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreatePhoneCallInput"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreatePhoneCallOutput"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Organizations Event Types"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/organizations/{orgId}/teams/event-types": {
|
||||
"get": {
|
||||
"operationId": "OrganizationsEventTypesController_getTeamsEventTypes",
|
||||
@@ -3324,7 +3372,31 @@
|
||||
"/v2/calendars/busy-times": {
|
||||
"get": {
|
||||
"operationId": "CalendarsController_getBusyTimes",
|
||||
"parameters": [],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "loggedInUsersTz",
|
||||
"required": true,
|
||||
"in": "query",
|
||||
"description": "The timezone of the logged in user represented as a string",
|
||||
"example": "America/New_York",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "calendarsToLoad",
|
||||
"required": true,
|
||||
"in": "query",
|
||||
"description": "An array of Calendar objects representing the calendars to be loaded",
|
||||
"example": "[{ credentialId: \"1\", externalId: \"AQgtJE7RnHEeyisVq2ENs2gAAAgEGAAAACgtJE7RnHEeyisVq2ENs2gAAAhSDAAAA\" }, { credentialId: \"2\", externalId: \"AQM7RnHEeyisVq2ENs2gAAAhFDBBBBB\" }]",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
@@ -7794,6 +7866,90 @@
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"CreatePhoneCallInput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"yourPhoneNumber": {
|
||||
"type": "string",
|
||||
"pattern": "/^\\+[1-9]\\d{1,14}$/",
|
||||
"description": "Your phone number"
|
||||
},
|
||||
"numberToCall": {
|
||||
"type": "string",
|
||||
"pattern": "/^\\+[1-9]\\d{1,14}$/",
|
||||
"description": "Number to call"
|
||||
},
|
||||
"calApiKey": {
|
||||
"type": "string",
|
||||
"description": "CAL API Key"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "object",
|
||||
"default": true,
|
||||
"description": "Enabled status"
|
||||
},
|
||||
"templateType": {
|
||||
"default": "CUSTOM_TEMPLATE",
|
||||
"enum": [
|
||||
"CHECK_IN_APPOINTMENT",
|
||||
"CUSTOM_TEMPLATE"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Template type"
|
||||
},
|
||||
"schedulerName": {
|
||||
"type": "string",
|
||||
"description": "Scheduler name"
|
||||
},
|
||||
"guestName": {
|
||||
"type": "string",
|
||||
"description": "Guest name"
|
||||
},
|
||||
"guestEmail": {
|
||||
"type": "string",
|
||||
"description": "Guest email"
|
||||
},
|
||||
"guestCompany": {
|
||||
"type": "string",
|
||||
"description": "Guest company"
|
||||
},
|
||||
"beginMessage": {
|
||||
"type": "string",
|
||||
"description": "Begin message"
|
||||
},
|
||||
"generalPrompt": {
|
||||
"type": "string",
|
||||
"description": "General prompt"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"yourPhoneNumber",
|
||||
"numberToCall",
|
||||
"calApiKey",
|
||||
"enabled",
|
||||
"templateType"
|
||||
]
|
||||
},
|
||||
"CreatePhoneCallOutput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"example": "success",
|
||||
"enum": [
|
||||
"success",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/components/schemas/Data"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"GetTeamEventTypesOutput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -8636,7 +8792,8 @@
|
||||
"MEETING_STARTED",
|
||||
"RECORDING_READY",
|
||||
"INSTANT_MEETING",
|
||||
"RECORDING_TRANSCRIPTION_GENERATED"
|
||||
"RECORDING_TRANSCRIPTION_GENERATED",
|
||||
"OOO_CREATED"
|
||||
]
|
||||
},
|
||||
"active": {
|
||||
@@ -8709,7 +8866,8 @@
|
||||
"MEETING_STARTED",
|
||||
"RECORDING_READY",
|
||||
"INSTANT_MEETING",
|
||||
"RECORDING_TRANSCRIPTION_GENERATED"
|
||||
"RECORDING_TRANSCRIPTION_GENERATED",
|
||||
"OOO_CREATED"
|
||||
]
|
||||
},
|
||||
"active": {
|
||||
@@ -9313,6 +9471,25 @@
|
||||
"status"
|
||||
]
|
||||
},
|
||||
"ProviderVerifyClientData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"clientId": {
|
||||
"type": "string"
|
||||
},
|
||||
"organizationId": {
|
||||
"type": "number"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"clientId",
|
||||
"organizationId",
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"ProviderVerifyClientOutput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -9323,10 +9500,14 @@
|
||||
"success",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/components/schemas/ProviderVerifyClientData"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status"
|
||||
"status",
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"ProviderVerifyAccessTokenOutput": {
|
||||
@@ -10281,9 +10462,6 @@
|
||||
"rescheduleUid": {
|
||||
"type": "string"
|
||||
},
|
||||
"recurringEventId": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeZone": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -8,6 +8,8 @@ import { FUTURE_ROUTES_ENABLED_COOKIE_NAME, FUTURE_ROUTES_OVERRIDE_COOKIE_NAME }
|
||||
const ROUTES: [URLPattern, boolean][] = [
|
||||
["/event-types", process.env.APP_ROUTER_EVENT_TYPES_ENABLED === "1"] as const,
|
||||
["/settings/admin/:path*", process.env.APP_ROUTER_SETTINGS_ADMIN_ENABLED === "1"] as const,
|
||||
["/settings/platform/:path*", process.env.APP_ROUTER_SETTINGS_PLATFORM_ENABLED === "1"] as const,
|
||||
["/settings/organizations/:path*", process.env.APP_ROUTER_SETTINGS_ORG_ENABLED === "1"] as const,
|
||||
["/apps/installed/:category", process.env.APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED === "1"] as const,
|
||||
["/apps/:slug", process.env.APP_ROUTER_APPS_SLUG_ENABLED === "1"] as const,
|
||||
["/apps/:slug/setup", process.env.APP_ROUTER_APPS_SLUG_SETUP_ENABLED === "1"] as const,
|
||||
@@ -28,6 +30,10 @@ const ROUTES: [URLPattern, boolean][] = [
|
||||
["/bookings/:status", process.env.APP_ROUTER_BOOKINGS_STATUS_ENABLED === "1"] as const,
|
||||
["/video/:path*", process.env.APP_ROUTER_VIDEO_ENABLED === "1"] as const,
|
||||
["/teams", process.env.APP_ROUTER_TEAMS_ENABLED === "1"] as const,
|
||||
["/more", process.env.APP_ROUTER_MORE_ENABLED === "1"] as const,
|
||||
["/maintenance", process.env.APP_ROUTER_MAINTENANCE_ENABLED === "1"] as const,
|
||||
["/upgrade", process.env.APP_ROUTER_UPGRADE_ENABLED === "1"] as const,
|
||||
["/connect-and-join", process.env.APP_ROUTER_CONNECT_AND_JOIN_ENABLED === "1"] as const,
|
||||
["/availability", process.env.APP_ROUTER_AVAILABILITY_ENABLED === "1"] as const,
|
||||
].map(([pathname, enabled]) => [
|
||||
new URLPattern({
|
||||
|
||||
@@ -22,7 +22,7 @@ const create = async (locale: string, ns: string) => {
|
||||
return _i18n;
|
||||
};
|
||||
|
||||
const getFixedT = async (locale: string, ns: string) => {
|
||||
export const getFixedT = async (locale: string, ns = "common") => {
|
||||
const i18n = await create(locale, ns);
|
||||
|
||||
return i18n.getFixedT(locale, ns);
|
||||
|
||||
@@ -1,46 +1,17 @@
|
||||
import LegacyPage, { getLayout } from "@pages/apps/[slug]/[...pages]";
|
||||
import type { PageProps, SearchParams } from "app/_types";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { SearchParams } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import type { GetServerSidePropsResult } from "next";
|
||||
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { notFound } from "next/navigation";
|
||||
import z from "zod";
|
||||
|
||||
import { getAppWithMetadata } from "@calcom/app-store/_appRegistry";
|
||||
import RoutingFormsRoutingConfig, {
|
||||
serverSidePropsConfig,
|
||||
} from "@calcom/app-store/routing-forms/pages/app-routing.config";
|
||||
import TypeformRoutingConfig from "@calcom/app-store/typeform/pages/app-routing.config";
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { AppGetServerSideProps } from "@calcom/types/AppGetServerSideProps";
|
||||
|
||||
import type { AppProps } from "@lib/app-providers";
|
||||
import { getServerSideProps } from "@lib/apps/[slug]/[...pages]/getServerSideProps";
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
|
||||
import PageWrapper from "@components/PageWrapperAppDir";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
type AppPageType = {
|
||||
getServerSideProps: AppGetServerSideProps;
|
||||
// A component than can accept any properties
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
default: ((props: any) => JSX.Element) &
|
||||
Pick<AppProps["Component"], "isBookingPage" | "getLayout" | "PageWrapper">;
|
||||
};
|
||||
|
||||
type Found = {
|
||||
notFound: false;
|
||||
Component: AppPageType["default"];
|
||||
getServerSideProps: AppPageType["getServerSideProps"];
|
||||
};
|
||||
|
||||
const AppsRouting = {
|
||||
"routing-forms": RoutingFormsRoutingConfig,
|
||||
typeform: TypeformRoutingConfig,
|
||||
};
|
||||
import LegacyPage, { getLayout } from "~/apps/[slug]/[...pages]/pages-view";
|
||||
|
||||
const paramsSchema = z.object({
|
||||
slug: z.string(),
|
||||
@@ -60,127 +31,22 @@ export const generateMetadata = async ({
|
||||
return notFound();
|
||||
}
|
||||
|
||||
const mainPage = p.data.pages[0];
|
||||
|
||||
if (mainPage === "forms") {
|
||||
return await _generateMetadata(
|
||||
() => `Forms`,
|
||||
() => ""
|
||||
);
|
||||
}
|
||||
|
||||
const legacyContext = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const { form } = await getPageProps(legacyContext);
|
||||
const data = await getData(legacyContext);
|
||||
const form = "form" in data ? (data.form as { name?: string; description?: string }) : null;
|
||||
const formName = form?.name ?? "Forms";
|
||||
const formDescription = form?.description ?? "";
|
||||
|
||||
return await _generateMetadata(
|
||||
() => `${form.name}`,
|
||||
() => form.description
|
||||
() => formName,
|
||||
() => formDescription
|
||||
);
|
||||
};
|
||||
|
||||
function getRoute(appName: string, pages: string[]) {
|
||||
const routingConfig = AppsRouting[appName as keyof typeof AppsRouting] as Record<string, AppPageType>;
|
||||
const getData = withAppDirSsr<GetServerSidePropsResult<any>>(getServerSideProps);
|
||||
|
||||
if (!routingConfig) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const mainPage = pages[0];
|
||||
const appPage = routingConfig.layoutHandler || (routingConfig[mainPage] as AppPageType);
|
||||
|
||||
const getServerSidePropsHandler = serverSidePropsConfig[mainPage];
|
||||
|
||||
if (!appPage) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return {
|
||||
notFound: false,
|
||||
Component: appPage.default,
|
||||
...appPage,
|
||||
getServerSideProps: getServerSidePropsHandler,
|
||||
} as Found;
|
||||
}
|
||||
|
||||
const getPageProps = async ({ params, query, req }: GetServerSidePropsContext) => {
|
||||
const p = paramsSchema.safeParse(params);
|
||||
|
||||
if (!p.success) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
const { slug: appName, pages } = p.data;
|
||||
|
||||
const route = getRoute(appName, pages);
|
||||
|
||||
if (route.notFound) {
|
||||
return route;
|
||||
}
|
||||
|
||||
if (route.getServerSideProps) {
|
||||
// TODO: Document somewhere that right now it is just a convention that filename should have appPages in it's name.
|
||||
// appPages is actually hardcoded here and no matter the fileName the same variable would be used.
|
||||
// We can write some validation logic later on that ensures that [...appPages].tsx file exists
|
||||
params!.appPages = pages.slice(1);
|
||||
|
||||
const ctx = { req, params, query };
|
||||
|
||||
const session = await getServerSession({ req });
|
||||
const user = session?.user;
|
||||
const app = await getAppWithMetadata({ slug: appName });
|
||||
|
||||
if (!app) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const result = await route.getServerSideProps(
|
||||
{
|
||||
...ctx,
|
||||
params: {
|
||||
...ctx.params,
|
||||
appPages: pages.slice(1),
|
||||
},
|
||||
} as GetServerSidePropsContext<{
|
||||
slug: string;
|
||||
pages: string[];
|
||||
appPages: string[];
|
||||
}>,
|
||||
prisma,
|
||||
user,
|
||||
ssrInit
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
|
||||
if (result.notFound) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
if (result.redirect) {
|
||||
redirect(result.redirect.destination);
|
||||
}
|
||||
|
||||
return {
|
||||
appName,
|
||||
appUrl: app.simplePath || `/apps/${appName}`,
|
||||
...result.props,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
appName,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export default async function Page({ params, searchParams }: PageProps) {
|
||||
const h = headers();
|
||||
const nonce = h.get("x-nonce") ?? undefined;
|
||||
|
||||
const legacyContext = buildLegacyCtx(h, cookies(), params, searchParams);
|
||||
const props = await getPageProps(legacyContext);
|
||||
return (
|
||||
<PageWrapper getLayout={getLayout} requiresLicense={false} nonce={nonce} themeBasis={null} {...props}>
|
||||
<LegacyPage {...props} />
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
export default WithLayout({
|
||||
getLayout,
|
||||
getData,
|
||||
Page: LegacyPage,
|
||||
});
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import Page from "@pages/apps/[slug]/index";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { withAppDirSsg } from "app/WithAppDirSsg";
|
||||
import type { PageProps } from "app/_types";
|
||||
import type { PageProps as _PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import type { InferGetStaticPropsType } from "next";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { AppRepository } from "@calcom/lib/server/repository/app";
|
||||
|
||||
import { getStaticProps } from "@lib/apps/[slug]/getStaticProps";
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
|
||||
type Y = InferGetStaticPropsType<typeof getStaticProps>;
|
||||
const getData = withAppDirSsg<Y>(getStaticProps);
|
||||
import type { PageProps } from "~/apps/[slug]/slug-view";
|
||||
import Page from "~/apps/[slug]/slug-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const getData = withAppDirSsg<PageProps>(getStaticProps);
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
|
||||
const legacyContext = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const res = await getData(legacyContext);
|
||||
|
||||
@@ -27,7 +27,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
|
||||
export const generateStaticParams = async () => {
|
||||
try {
|
||||
const appStore = await prisma.app.findMany({ select: { slug: true } });
|
||||
const appStore = await AppRepository.findAppStore();
|
||||
return appStore.map(({ slug }) => ({ slug }));
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Prisma.PrismaClientInitializationError) {
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import Page from "@pages/apps/[slug]/setup";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { PageProps as _PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import type { InferGetServerSidePropsType } from "next";
|
||||
|
||||
import { getServerSideProps } from "@calcom/app-store/_pages/setup/_getServerSideProps";
|
||||
|
||||
export const generateMetadata = async ({ params }: { params: Record<string, string | string[]> }) => {
|
||||
import Page, { type PageProps } from "~/apps/[slug]/setup/setup-view";
|
||||
|
||||
export const generateMetadata = async ({ params }: _PageProps) => {
|
||||
return await _generateMetadata(
|
||||
() => `${params.slug}`,
|
||||
() => ""
|
||||
);
|
||||
};
|
||||
|
||||
type T = InferGetServerSidePropsType<typeof getServerSideProps>;
|
||||
|
||||
const getData = withAppDirSsr<T>(getServerSideProps);
|
||||
const getData = withAppDirSsr<PageProps>(getServerSideProps);
|
||||
|
||||
export default WithLayout({ getLayout: null, Page, getData });
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import CategoryPage, { type PageProps } from "@pages/apps/categories/[category]";
|
||||
import { withAppDirSsg } from "app/WithAppDirSsg";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { AppCategories } from "@calcom/prisma/enums";
|
||||
import { isPrismaAvailableCheck } from "@calcom/prisma/is-prisma-available-check";
|
||||
|
||||
import { getStaticProps } from "@lib/apps/categories/[category]/getStaticProps";
|
||||
|
||||
import CategoryPage, { type PageProps } from "~/apps/categories/[category]/category-view";
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
return await _generateMetadata(
|
||||
() => `${APP_NAME}`,
|
||||
() => ""
|
||||
() => "Apps Store",
|
||||
() => "Connecting people, technology and the workplace."
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import Page from "@pages/apps/categories/index";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getServerSideProps } from "@lib/apps/categories/getServerSideProps";
|
||||
|
||||
import Page from "~/apps/categories/categories-view";
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
return await _generateMetadata(
|
||||
() => `Categories`,
|
||||
() => ""
|
||||
() => "Apps Store",
|
||||
() => "Connecting people, technology and the workplace."
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { getServerSideProps } from "@lib/apps/installation/[[...step]]/getServerSideProps";
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
|
||||
import type { OnboardingPageProps } from "~/apps/installation/[[...step]]/step-view";
|
||||
import Page from "~/apps/installation/[[...step]]/step-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
|
||||
const { appMetadata } = await getData(legacyCtx);
|
||||
return await _generateMetadata(
|
||||
(t) => `${t("install")} ${appMetadata?.name ?? ""}`,
|
||||
() => ""
|
||||
);
|
||||
};
|
||||
|
||||
const getData = withAppDirSsr<OnboardingPageProps>(getServerSideProps);
|
||||
|
||||
export default WithLayout({ getLayout: null, getData, Page });
|
||||
@@ -1,17 +1,18 @@
|
||||
import Page from "@pages/apps/installed/[category]";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getServerSideProps } from "@lib/apps/installed/[category]/getServerSideProps";
|
||||
import { getServerSidePropsAppDir } from "@lib/apps/installed/[category]/getServerSideProps";
|
||||
|
||||
import Page from "~/apps/installed/[category]/installed-category-view";
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
return await _generateMetadata(
|
||||
(t) => `${t("installed_apps")}`,
|
||||
(t) => t("installed_apps"),
|
||||
(t) => t("manage_your_connected_apps")
|
||||
);
|
||||
};
|
||||
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
const getData = withAppDirSsr(getServerSidePropsAppDir);
|
||||
|
||||
export default WithLayout({ getLayout: null, getData, Page });
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
const Page = () => {
|
||||
redirect("/apps/installed/calendar");
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -1,18 +1,20 @@
|
||||
import AppsPage from "@pages/apps";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/MainLayoutAppDir";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
|
||||
import { getServerSideProps } from "@lib/apps/getServerSideProps";
|
||||
|
||||
import AppsPage, { LayoutWrapper } from "~/apps/apps-view";
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
return await _generateMetadata(
|
||||
() => `Apps | ${APP_NAME}`,
|
||||
() => ""
|
||||
(t) => t("app_store"),
|
||||
(t) => t("app_store_description")
|
||||
);
|
||||
};
|
||||
|
||||
export default WithLayout({ getLayout, getData: withAppDirSsr(getServerSideProps), Page: AppsPage });
|
||||
export default WithLayout({
|
||||
getLayout: LayoutWrapper,
|
||||
getData: withAppDirSsr(getServerSideProps),
|
||||
Page: AppsPage,
|
||||
});
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
|
||||
import PageWrapper from "@components/PageWrapperAppDir";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
import Logout from "~/auth/logout-view";
|
||||
@@ -20,7 +19,6 @@ export const generateMetadata = async () => {
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
// cookie will be cleared in `/apps/web/middleware.ts`
|
||||
const h = headers();
|
||||
const nonce = h.get("x-nonce") ?? undefined;
|
||||
const context = buildLegacyCtx(h, cookies(), params, searchParams);
|
||||
const ssr = await ssrInit(context);
|
||||
const props = {
|
||||
@@ -28,11 +26,7 @@ const Page = async ({ params, searchParams }: PageProps) => {
|
||||
query: context.query,
|
||||
};
|
||||
|
||||
return (
|
||||
<PageWrapper requiresLicense={false} getLayout={null} nonce={nonce} themeBasis={null}>
|
||||
<Logout {...props} />
|
||||
</PageWrapper>
|
||||
);
|
||||
return <Logout {...props} />;
|
||||
};
|
||||
|
||||
export default Page;
|
||||
export default WithLayout({ getLayout: null, ServerPage: Page })<"P">;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import { ScheduleRepository } from "@calcom/lib/server/repository/schedule";
|
||||
import { TravelScheduleRepository } from "@calcom/lib/server/repository/travelSchedule";
|
||||
import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
|
||||
import { AvailabilitySettingsWebWrapper } from "~/availability/[schedule]/schedule-view";
|
||||
|
||||
@@ -23,4 +27,46 @@ export const generateMetadata = async ({ params }: PageProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default WithLayout({ getLayout: null, Page: AvailabilitySettingsWebWrapper });
|
||||
const Page = async ({ params }: PageProps) => {
|
||||
if (params?.schedule) {
|
||||
notFound();
|
||||
}
|
||||
const scheduleId = Number(params.schedule);
|
||||
|
||||
const session = await getServerSessionForAppDir();
|
||||
const userId = session?.user?.id;
|
||||
if (!userId) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
let userData, schedule, travelSchedules;
|
||||
|
||||
try {
|
||||
userData = await UserRepository.getTimeZoneAndDefaultScheduleId({
|
||||
userId,
|
||||
});
|
||||
if (!userData?.timeZone || !userData?.defaultScheduleId) {
|
||||
throw new Error("timeZone and defaultScheduleId not found");
|
||||
}
|
||||
} catch (e) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
try {
|
||||
schedule = await ScheduleRepository.findDetailedScheduleById({
|
||||
scheduleId,
|
||||
isManagedEventType: false,
|
||||
userId,
|
||||
timeZone: userData.timeZone,
|
||||
defaultScheduleId: userData.defaultScheduleId,
|
||||
});
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
travelSchedules = await TravelScheduleRepository.findTravelSchedulesByUserId(userId);
|
||||
} catch (e) {}
|
||||
|
||||
return <AvailabilitySettingsWebWrapper scheduleFetched={schedule} travelSchedules={travelSchedules} />;
|
||||
};
|
||||
|
||||
export default WithLayout({ ServerPage: Page });
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import { OrganizationRepository } from "@calcom/lib/server/repository/organization";
|
||||
|
||||
import AvailabilityPage from "~/availability/availability-view";
|
||||
|
||||
@@ -10,4 +14,23 @@ export const generateMetadata = async () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default WithLayout({ getLayout: null, Page: AvailabilityPage });
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
const userId = session?.user?.id;
|
||||
const orgId = session?.user?.org?.id;
|
||||
if (!userId || !orgId) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
try {
|
||||
const currentOrg = await OrganizationRepository.findCurrentOrg({
|
||||
orgId,
|
||||
userId,
|
||||
});
|
||||
return <AvailabilityPage currentOrg={currentOrg} />;
|
||||
} catch {
|
||||
notFound();
|
||||
}
|
||||
};
|
||||
|
||||
export default WithLayout({ ServerPage: Page });
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import LegacyPage from "@pages/connect-and-join";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import LegacyPage from "~/connect-and-join/connect-and-join-view";
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
return await _generateMetadata(
|
||||
() => "Connect and Join",
|
||||
() => ""
|
||||
);
|
||||
};
|
||||
|
||||
export default WithLayout({ getLayout: null, Page: LegacyPage })<"P">;
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { Params, SearchParams } from "app/_types";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/event-types/[type]/getServerSideProps";
|
||||
import type { PageProps as EventTypePageProps } from "@lib/event-types/[type]/getServerSideProps";
|
||||
|
||||
import EventTypePageWrapper from "~/event-types/views/event-types-single-view";
|
||||
import { getServerSideProps } from "~/event-types/views/event-types-single-view.getServerSideProps";
|
||||
|
||||
export const generateMetadata = async ({
|
||||
params,
|
||||
searchParams,
|
||||
}: {
|
||||
params: Params;
|
||||
searchParams: SearchParams;
|
||||
}) => {
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const { eventType } = await getData(legacyCtx);
|
||||
|
||||
@@ -26,5 +21,5 @@ export const generateMetadata = async ({
|
||||
};
|
||||
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
export default WithLayout({ getLayout: null, getData, Page: EventTypePageWrapper })<"P">;
|
||||
const Page = (props: EventTypePageProps) => <EventTypePageWrapper {...props} isAppDir={true} />;
|
||||
export default WithLayout({ getLayout: null, getData, Page })<"P">;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import LegacyPage from "@pages/maintenance";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
|
||||
import LegacyPage from "~/maintenance/maintenance-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => `${t("under_maintenance")}`,
|
||||
(t) => t("under_maintenance"),
|
||||
(t) => t("under_maintenance_description", { appName: APP_NAME })
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import Page from "@pages/more";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import Page from "~/more/more-page-view";
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
return await _generateMetadata(
|
||||
() => "More",
|
||||
() => ""
|
||||
);
|
||||
};
|
||||
|
||||
export default WithLayout({ getLayout: null, Page })<"P">;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { PageProps as _PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import { headers, cookies } from "next/headers";
|
||||
|
||||
import { getLayout } from "@calcom/features/MainLayoutAppDir";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { EventRepository } from "@calcom/lib/server/repository/event";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps";
|
||||
|
||||
import type { PageProps } from "~/org/[orgSlug]/instant-meeting/team/[slug]/[type]/instant-meeting-view";
|
||||
import Page from "~/org/[orgSlug]/instant-meeting/team/[slug]/[type]/instant-meeting-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const { slug: eventSlug, user: username } = await getData(context);
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req, context.params?.orgSlug);
|
||||
|
||||
const org = isValidOrgDomain ? currentOrgDomain : null;
|
||||
|
||||
const event = await EventRepository.getPublicEvent({
|
||||
username,
|
||||
eventSlug,
|
||||
isTeamEvent: true,
|
||||
org,
|
||||
fromRedirectOfNonOrgLink: context.query.orgRedirection === "true",
|
||||
});
|
||||
|
||||
const profileName = event?.profile.name ?? "";
|
||||
const title = event?.title ?? "";
|
||||
|
||||
return await _generateMetadata(
|
||||
() => `${title} | ${profileName}`,
|
||||
() => `${title}`
|
||||
);
|
||||
};
|
||||
|
||||
const getData = withAppDirSsr<PageProps>(getServerSideProps);
|
||||
export default WithLayout({ getLayout, getData, Page })<"P">;
|
||||
@@ -1,17 +1,11 @@
|
||||
import { getServerSideProps } from "@pages/reschedule/[uid]";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { SearchParams } from "app/_types";
|
||||
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import withEmbedSsr from "@lib/withEmbedSsr";
|
||||
|
||||
type PageProps = Readonly<{
|
||||
params: Params;
|
||||
searchParams: SearchParams;
|
||||
}>;
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
await withAppDirSsr(withEmbedSsr(getServerSideProps))(legacyCtx);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { getServerSideProps } from "@pages/reschedule/[uid]";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { SearchParams } from "app/_types";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
|
||||
import { headers, cookies } from "next/headers";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
@@ -13,11 +12,6 @@ export const generateMetadata = async () =>
|
||||
() => ""
|
||||
);
|
||||
|
||||
type PageProps = Readonly<{
|
||||
params: Params;
|
||||
searchParams: SearchParams;
|
||||
}>;
|
||||
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { type SearchParams } from "app/_types";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { type GetServerSidePropsContext } from "next";
|
||||
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
import z from "zod";
|
||||
@@ -21,11 +20,6 @@ const getPageProps = async (context: GetServerSidePropsContext) => {
|
||||
return redirect(`/apps/routing-forms/${pages.length ? pages.join("/") : ""}`);
|
||||
};
|
||||
|
||||
type PageProps = Readonly<{
|
||||
params: Params;
|
||||
searchParams: SearchParams;
|
||||
}>;
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
await getPageProps(legacyCtx);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import AdminAppsList from "@calcom/features/apps/AdminAppsList";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("apps"),
|
||||
(t) => t("admin_apps_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader title={t("apps")} description={t("admin_apps_description")}>
|
||||
<div className="flex">
|
||||
<AdminAppsList
|
||||
baseURL="/settings/admin/apps"
|
||||
classNames={{
|
||||
appCategoryNavigationRoot: "overflow-x-scroll",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
+5
-1
@@ -1,5 +1,5 @@
|
||||
import Page from "@pages/settings/admin/apps/index";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
@@ -7,4 +7,8 @@ export const generateMetadata = async () =>
|
||||
(t) => t("admin_apps_description")
|
||||
);
|
||||
|
||||
const Page = () => {
|
||||
redirect("/[category]");
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,20 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import { FlagListingView } from "@calcom/features/flags/pages/flag-listing-view";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "Feature Flags",
|
||||
() => "Here you can toggle your Cal.com instance features."
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
return (
|
||||
<SettingsHeader title="Feature Flags" description="Here you can toggle your Cal.com instance features.">
|
||||
<FlagListingView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import ImpersonationView from "~/settings/admin/impersonation-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("admin"),
|
||||
(t) => t("impersonation")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
return (
|
||||
<SettingsHeader title={t("admin")} description={t("impersonation")}>
|
||||
<ImpersonationView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import LockedSMSView from "~/settings/admin/locked-sms-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "Locked SMS",
|
||||
() => "Lock or unlock SMS sending for users"
|
||||
);
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<SettingsHeader title="Locked SMS" description="Lock or unlock SMS sending for users">
|
||||
<LockedSMSView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import LegacyPage from "~/settings/admin/oauth-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "OAuth",
|
||||
() => "Add new OAuth Clients"
|
||||
);
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<SettingsHeader title="OAuth" description="Add new OAuth Clients">
|
||||
<LegacyPage />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,52 @@
|
||||
import { type Params } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { notFound } from "next/navigation";
|
||||
import { z } from "zod";
|
||||
|
||||
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
|
||||
import { OrgForm } from "@calcom/features/ee/organizations/pages/settings/admin/AdminOrgEditPage";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { OrganizationRepository } from "@calcom/lib/server/repository/organization";
|
||||
|
||||
const orgIdSchema = z.object({ id: z.coerce.number() });
|
||||
|
||||
export const generateMetadata = async ({ params }: { params: Params }) => {
|
||||
const input = orgIdSchema.safeParse(params);
|
||||
if (!input.success) {
|
||||
return await _generateMetadata(
|
||||
() => `Editing organization`,
|
||||
() => "Here you can edit an organization."
|
||||
);
|
||||
}
|
||||
|
||||
const org = await OrganizationRepository.adminFindById({ id: input.data.id });
|
||||
|
||||
return await _generateMetadata(
|
||||
() => `Editing organization: ${org.name}`,
|
||||
() => "Here you can edit an organization."
|
||||
);
|
||||
};
|
||||
|
||||
const Page = async ({ params }: { params: Params }) => {
|
||||
const input = orgIdSchema.safeParse(params);
|
||||
|
||||
if (!input.success) notFound();
|
||||
|
||||
try {
|
||||
const org = await OrganizationRepository.adminFindById({ id: input.data.id });
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={`Editing organization: ${org.name}`}
|
||||
description="Here you can edit an organization.">
|
||||
<LicenseRequired>
|
||||
<OrgForm org={org} />
|
||||
</LicenseRequired>
|
||||
</SettingsHeader>
|
||||
);
|
||||
} catch {
|
||||
notFound();
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,28 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
|
||||
import AdminOrgTable from "@calcom/features/ee/organizations/pages/settings/admin/AdminOrgPage";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("organizations"),
|
||||
(t) => t("orgs_page_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
return (
|
||||
<SettingsHeader title={t("organizations")} description={t("orgs_page_description")}>
|
||||
<LicenseRequired>
|
||||
<AdminOrgTable />
|
||||
</LicenseRequired>
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
+1
-1
@@ -10,4 +10,4 @@ export const generateMetadata = async () =>
|
||||
() => "admin_description"
|
||||
);
|
||||
|
||||
export default WithLayout({ getLayout, Page: LegacyPage })<"P">;
|
||||
export default WithLayout({ getServerLayout: getLayout, Page: LegacyPage })<"P">;
|
||||
@@ -0,0 +1,52 @@
|
||||
import { type Params } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { notFound } from "next/navigation";
|
||||
import { z } from "zod";
|
||||
|
||||
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
|
||||
import { UsersEditView } from "@calcom/features/ee/users/pages/users-edit-view";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
|
||||
const userIdSchema = z.object({ id: z.coerce.number() });
|
||||
|
||||
export const generateMetadata = async ({ params }: { params: Params }) => {
|
||||
const input = userIdSchema.safeParse(params);
|
||||
if (!input.success) {
|
||||
return await _generateMetadata(
|
||||
() => `Editing user`,
|
||||
() => "Here you can edit a current user."
|
||||
);
|
||||
}
|
||||
|
||||
const user = await UserRepository.adminFindById(input.data.id);
|
||||
|
||||
return await _generateMetadata(
|
||||
() => `Editing user: ${user.username}`,
|
||||
() => "Here you can edit a current user."
|
||||
);
|
||||
};
|
||||
|
||||
const Page = async ({ params }: { params: Params }) => {
|
||||
const input = userIdSchema.safeParse(params);
|
||||
|
||||
if (!input.success) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await UserRepository.adminFindById(input.data.id);
|
||||
|
||||
return (
|
||||
<SettingsHeader title="Editing user" description="Here you can edit a current user">
|
||||
<LicenseRequired>
|
||||
<UsersEditView user={user} />
|
||||
</LicenseRequired>
|
||||
</SettingsHeader>
|
||||
);
|
||||
} catch {
|
||||
notFound();
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,20 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import UsersAddView from "@calcom/features/ee/users/pages/users-add-view";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "Add new user",
|
||||
() => "Here you can add a new user."
|
||||
);
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<SettingsHeader title="Add new user" description="Here you can add a new user">
|
||||
<UsersAddView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import UsersListingView from "@calcom/features/ee/users/pages/users-listing-view";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { Button } from "@calcom/ui";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "Users",
|
||||
() => "A list of all the users in your account including their name, title, email and role."
|
||||
);
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<SettingsHeader
|
||||
title="Users"
|
||||
description="A list of all the users in your account including their name, title, email and role."
|
||||
CTA={
|
||||
<div className="mt-4 space-x-5 sm:ml-16 sm:mt-0 sm:flex-none">
|
||||
{/* TODO: Add import users functionality */}
|
||||
{/* <Button disabled>Import users</Button> */}
|
||||
<Button href="/settings/admin/users/add">Add user</Button>
|
||||
</div>
|
||||
}>
|
||||
<UsersListingView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
+1
-1
@@ -2,4 +2,4 @@ import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@components/auth/layouts/AdminLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getLayout })<"L">;
|
||||
export default WithLayout({ getServerLayout: getLayout })<"L">;
|
||||
@@ -0,0 +1,31 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import BillingView from "~/settings/billing/billing-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("billing"),
|
||||
(t) => t("manage_billing_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
// FIXME: Refactor me once next-auth endpoint is migrated to App Router
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("billing")}
|
||||
description={t("manage_billing_description")}
|
||||
borderInShellHeader={true}>
|
||||
<BillingView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,33 @@
|
||||
import { getFixedT, _generateMetadata } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
|
||||
import ApiKeysView from "~/settings/developer/api-keys-view";
|
||||
import NewApiKeyButton from "~/settings/developer/components/CreateApiKeyButton";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("api_keys"),
|
||||
(t) => t("create_first_api_key_description", { appName: APP_NAME })
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
// FIXME: Refactor me once next-auth endpoint is migrated to App Router
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("api_keys")}
|
||||
description={t("create_first_api_key_description", { appName: APP_NAME })}
|
||||
CTA={<NewApiKeyButton />}
|
||||
borderInShellHeader={true}>
|
||||
<ApiKeysView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { PageProps } from "app/_types";
|
||||
import { getFixedT, _generateMetadata } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { EditWebhookView } from "@calcom/features/webhooks/pages/webhook-edit-view";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { WebhookRepository } from "@calcom/lib/server/repository/webhook";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("webhooks"),
|
||||
(t) => t("add_webhook_description", { appName: APP_NAME })
|
||||
);
|
||||
|
||||
const Page = async ({ params }: PageProps) => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
const id = typeof params?.id === "string" ? params.id : undefined;
|
||||
|
||||
const webhook = await WebhookRepository.findByWebhookId(id);
|
||||
console.log("This is the webhook", webhook);
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("edit_webhook")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={true}
|
||||
backButton>
|
||||
<EditWebhookView webhook={webhook} />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { getFixedT, _generateMetadata } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { NewWebhookView } from "@calcom/features/webhooks/pages/webhook-new-view";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("webhooks"),
|
||||
(t) => t("add_webhook_description", { appName: APP_NAME })
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("add_webhook")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={true}
|
||||
backButton>
|
||||
<NewWebhookView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import { WebhooksViewAppDir } from "@calcom/features/webhooks/pages/webhooks-view";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("webhooks"),
|
||||
(t) => t("add_webhook_description", { appName: APP_NAME })
|
||||
);
|
||||
|
||||
const Page = () => {
|
||||
return <WebhooksViewAppDir />;
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout })<"L">;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import AppearancePage from "~/settings/my-account/appearance-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("appearance"),
|
||||
(t) => t("appearance_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader title={t("appearance")} description={t("appearance_description")}>
|
||||
<AppearancePage />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,40 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { Button } from "@calcom/ui";
|
||||
|
||||
import { CalendarListContainer } from "@components/apps/CalendarListContainer";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("calendars"),
|
||||
(t) => t("calendars_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
const AddCalendarButton = () => {
|
||||
return (
|
||||
<>
|
||||
<Button color="secondary" StartIcon="plus" href="/apps/categories/calendar">
|
||||
{t("add_calendar")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("calendars")}
|
||||
description={t("calendars_description")}
|
||||
CTA={<AddCalendarButton />}>
|
||||
<CalendarListContainer />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { Button } from "@calcom/ui";
|
||||
|
||||
import ConferencingView from "~/settings/my-account/conferencing-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("conferencing"),
|
||||
(t) => t("conferencing_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
const AddConferencingButton = () => {
|
||||
return (
|
||||
<Button color="secondary" StartIcon="plus" href="/apps/categories/conferencing">
|
||||
{t("add")}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("conferencing")}
|
||||
description={t("conferencing_description")}
|
||||
CTA={<AddConferencingButton />}
|
||||
borderInShellHeader={true}>
|
||||
<ConferencingView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import GeneralQueryView from "~/settings/my-account/general-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("general"),
|
||||
(t) => t("general_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
return (
|
||||
<SettingsHeader title={t("general")} description={t("general_description")} borderInShellHeader={true}>
|
||||
<GeneralQueryView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import CreateNewOutOfOfficeEntryButton from "@calcom/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton";
|
||||
import { OutOfOfficeEntriesList } from "@calcom/features/settings/outOfOffice/OutOfOfficeEntriesList";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("out_of_office"),
|
||||
(t) => t("out_of_office_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("out_of_office")}
|
||||
description={t("out_of_office_description")}
|
||||
CTA={<CreateNewOutOfOfficeEntryButton />}>
|
||||
<OutOfOfficeEntriesList />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
|
||||
import ProfileView from "~/settings/my-account/profile-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("profile"),
|
||||
(t) => t("profile_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("profile")}
|
||||
description={t("profile_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={true}>
|
||||
<ProfileView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,28 @@
|
||||
import { getFixedT, _generateMetadata } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import { AdminAPIView } from "@calcom/features/ee/organizations/pages/settings/admin-api";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => `${t("admin")} ${t("api_reference")}`,
|
||||
(t) => t("leverage_our_api")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={`${t("admin")} ${t("api_reference")}`}
|
||||
description={t("leverage_our_api")}
|
||||
borderInShellHeader={false}>
|
||||
<AdminAPIView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
@@ -0,0 +1,11 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import Page from "@calcom/ee/organizations/pages/settings/attributes/attributes-edit-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "Attribute",
|
||||
(t) => t("edit_attribute_description")
|
||||
);
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import Page from "@calcom/ee/organizations/pages/settings/attributes/attributes-create-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "Attribute",
|
||||
() => "Create an attribute for your team members"
|
||||
);
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import Page from "@calcom/ee/organizations/pages/settings/attributes/attributes-list-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("attributes"),
|
||||
(t) => t("attribute_meta_description")
|
||||
);
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
import Page from "@pages/settings/billing/index";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import Page from "~/settings/billing/billing-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("billing"),
|
||||
@@ -0,0 +1,24 @@
|
||||
import { _generateMetadata, getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import DirectorySyncTeamView from "@calcom/features/ee/dsync/page/team-dsync-view";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("directory_sync"),
|
||||
(t) => t("directory_sync_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader title={t("directory_sync")} description={t("directory_sync_description")}>
|
||||
<DirectorySyncTeamView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
@@ -0,0 +1,24 @@
|
||||
import { _generateMetadata, getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import PrivacyView from "@calcom/features/ee/organizations/pages/settings/privacy";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("privacy"),
|
||||
(t) => t("privacy_organization_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader title={t("privacy")} description={t("privacy_organization_description")}>
|
||||
<PrivacyView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
@@ -0,0 +1,5 @@
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
|
||||
|
||||
export default WithLayout({ getServerLayout: getLayout });
|
||||
@@ -0,0 +1,30 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import ProfileImpersonationViewWrapper from "~/settings/security/impersonation-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("impersonation"),
|
||||
(t) => t("impersonation_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("impersonation")}
|
||||
description={t("impersonation_description")}
|
||||
borderInShellHeader={true}>
|
||||
<ProfileImpersonationViewWrapper />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,27 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import PasswordViewWrapper from "~/settings/security/password-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("password"),
|
||||
(t) => t("password_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader title={t("password")} description={t("password_description")} borderInShellHeader={true}>
|
||||
<PasswordViewWrapper />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,29 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SAMLSSO from "@calcom/features/ee/sso/page/user-sso-view";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("sso_configuration"),
|
||||
(t) => t("sso_configuration_description")
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("sso_configuration")}
|
||||
description={t("sso_configuration_description")}
|
||||
borderInShellHeader={true}>
|
||||
<SAMLSSO />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,29 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { getFixedT } from "app/_utils";
|
||||
|
||||
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
|
||||
import TwoFactorAuthView from "~/settings/security/two-factor-auth-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("two_factor_auth"),
|
||||
(t) => t("add_an_extra_layer_of_security")
|
||||
);
|
||||
const Page = async () => {
|
||||
const session = await getServerSessionForAppDir();
|
||||
|
||||
const t = await getFixedT(session?.user.locale || "en");
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("2fa")}
|
||||
description={t("set_up_two_factor_authentication")}
|
||||
borderInShellHeader={true}>
|
||||
<TwoFactorAuthView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
import Page from "@pages/settings/billing/index";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import Page from "~/settings/billing/billing-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("billing"),
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user