feat: add membership creation date to Organization Member List table (CAL-5406) (#21008)
* feat: add membership creation date to Organization Member List table (CAL-5406)
This reverts commit 5aaca2b7aa.
* fill createdAt
This commit is contained in:
@@ -24,7 +24,12 @@ import { membershipCreateBodySchema, schemaMembershipPublic } from "~/lib/valida
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const data = membershipCreateBodySchema.parse(req.body);
|
||||
const args: Prisma.MembershipCreateArgs = { data };
|
||||
const args: Prisma.MembershipCreateArgs = {
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
...data,
|
||||
},
|
||||
};
|
||||
|
||||
await checkPermissions(req);
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ export class MembershipsRepository {
|
||||
async createMembership(teamId: number, userId: number, role: MembershipRole, accepted: boolean) {
|
||||
const membership = await this.dbRead.prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
role,
|
||||
teamId,
|
||||
userId,
|
||||
|
||||
+5
-1
@@ -69,7 +69,11 @@ export class OrganizationsTeamsMembershipsRepository {
|
||||
|
||||
async createOrgTeamMembership(teamId: number, data: CreateOrgTeamMembershipDto) {
|
||||
return this.dbWrite.prisma.membership.create({
|
||||
data: { ...data, teamId: teamId },
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
...data,
|
||||
teamId: teamId,
|
||||
},
|
||||
include: { user: { select: MembershipUserSelect } },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@ export class TeamsMembershipsRepository {
|
||||
|
||||
async createTeamMembership(teamId: number, data: CreateTeamMembershipInput) {
|
||||
return this.dbWrite.prisma.membership.create({
|
||||
data: { ...data, teamId: teamId },
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
...data,
|
||||
teamId: teamId,
|
||||
},
|
||||
include: { user: { select: MembershipUserSelect } },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export class MembershipRepositoryFixture {
|
||||
}
|
||||
|
||||
async create(data: Prisma.MembershipCreateInput) {
|
||||
return this.prismaWriteClient.membership.create({ data });
|
||||
return this.prismaWriteClient.membership.create({ data: { createdAt: new Date(), ...data } });
|
||||
}
|
||||
|
||||
async delete(membershipId: Membership["id"]) {
|
||||
@@ -30,7 +30,7 @@ export class MembershipRepositoryFixture {
|
||||
|
||||
async addUserToOrg(user: User, org: Team, role: MembershipRole, accepted: boolean) {
|
||||
const membership = await this.prismaWriteClient.membership.create({
|
||||
data: { teamId: org.id, userId: user.id, role, accepted },
|
||||
data: { createdAt: new Date(), teamId: org.id, userId: user.id, role, accepted },
|
||||
});
|
||||
await this.prismaWriteClient.user.update({ where: { id: user.id }, data: { organizationId: org.id } });
|
||||
return membership;
|
||||
|
||||
@@ -227,6 +227,7 @@ const createTeamAndAddUser = async (
|
||||
const { role = MembershipRole.OWNER, id: userId } = user;
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId: team.id,
|
||||
userId,
|
||||
role: role,
|
||||
@@ -566,6 +567,7 @@ export const createUsersFixture = (
|
||||
// Add teammates to the team
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId: team.id,
|
||||
userId: teamUser.id,
|
||||
role: MembershipRole.MEMBER,
|
||||
|
||||
@@ -660,9 +660,7 @@ test.describe("Out of office", () => {
|
||||
await page.locator('[data-testid="add-filter-button"]').click();
|
||||
await page.locator('[data-testid="add-filter-item-dateRange"]').click();
|
||||
await expect(
|
||||
page
|
||||
.locator('[data-testid="filter-popover-trigger-dateRange"] span', { hasText: "Last 7 Days" })
|
||||
.nth(0)
|
||||
page.locator('[data-testid="filter-popover-trigger-dateRange"]', { hasText: "Last 7 Days" }).first()
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
|
||||
@@ -3107,6 +3107,9 @@
|
||||
"enable_delegation_credential_description": "Grant Cal.com automatic access to the calendars of all organization members by enabling delegation credential.",
|
||||
"disable_delegation_credential": "Disable Delegation Credential",
|
||||
"disable_delegation_credential_description": "Once delegation credential is disabled, organization members who haven’t connected their calendars will need to do so manually.",
|
||||
"last_active": "Last Active",
|
||||
"member_since": "Member Since",
|
||||
"last_updated": "Last Updated",
|
||||
"salesforce_on_cancel_write_to_event": "On cancelled booking, write to event record instead of deleting event",
|
||||
"salesforce_on_every_cancellation": "On every cancellation",
|
||||
"report_issue": "Report issue",
|
||||
|
||||
@@ -68,6 +68,8 @@ describe("generate Csv for Org Users Table", () => {
|
||||
teams: [],
|
||||
attributes: [],
|
||||
lastActiveAt: "",
|
||||
createdAt: null,
|
||||
updatedAt: null,
|
||||
};
|
||||
|
||||
it("should throw if no headers", () => {
|
||||
|
||||
@@ -30,6 +30,7 @@ export function ActiveFilters<TData>({ table }: ActiveFiltersProps<TData>) {
|
||||
key={column.id}
|
||||
column={column}
|
||||
options={column.dateRangeOptions}
|
||||
showColumnName
|
||||
showClearButton
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useState, useEffect, useCallback } from "react";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import { Badge } from "@calcom/ui/components/badge";
|
||||
import { Button, buttonClasses } from "@calcom/ui/components/button";
|
||||
import {
|
||||
Command,
|
||||
@@ -35,14 +36,21 @@ import { useFilterPopoverOpen } from "./useFilterPopoverOpen";
|
||||
type DateRangeFilterProps = {
|
||||
column: Extract<FilterableColumn, { type: ColumnFilterType.DATE_RANGE }>;
|
||||
options?: DateRangeFilterOptions;
|
||||
showColumnName?: boolean;
|
||||
showClearButton?: boolean;
|
||||
};
|
||||
|
||||
export const DateRangeFilter = ({ column, options, showClearButton = false }: DateRangeFilterProps) => {
|
||||
export const DateRangeFilter = ({
|
||||
column,
|
||||
options,
|
||||
showColumnName = false,
|
||||
showClearButton = false,
|
||||
}: DateRangeFilterProps) => {
|
||||
const { open, onOpenChange } = useFilterPopoverOpen(column.id);
|
||||
const filterValue = useFilterValue(column.id, ZDateRangeFilterValue);
|
||||
const { updateFilter, removeFilter } = useDataTable();
|
||||
const range = options?.range ?? "past";
|
||||
const endOfDay = options?.endOfDay ?? false;
|
||||
const forceCustom = range === "custom";
|
||||
const forcePast = range === "past";
|
||||
|
||||
@@ -73,13 +81,13 @@ export const DateRangeFilter = ({ column, options, showClearButton = false }: Da
|
||||
type: ColumnFilterType.DATE_RANGE,
|
||||
data: {
|
||||
startDate: startDate.toDate().toISOString(),
|
||||
endDate: endDate.toDate().toISOString(),
|
||||
endDate: (endOfDay ? endDate.endOf("day") : endDate).toDate().toISOString(),
|
||||
preset: preset.value,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
[column.id]
|
||||
[column.id, endOfDay]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -137,6 +145,10 @@ export const DateRangeFilter = ({ column, options, showClearButton = false }: Da
|
||||
customButtonLabel = `${format(startDate.toDate(), "LLL dd, y")} - ?`;
|
||||
}
|
||||
|
||||
const selectedValue = isCustomPreset
|
||||
? customButtonLabel
|
||||
: t(selectedPreset.labelKey, selectedPreset.i18nOptions);
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={onOpenChange}>
|
||||
<PopoverTrigger asChild>
|
||||
@@ -146,8 +158,15 @@ export const DateRangeFilter = ({ column, options, showClearButton = false }: Da
|
||||
StartIcon="calendar-range"
|
||||
EndIcon="chevron-down"
|
||||
data-testid={`filter-popover-trigger-${column.id}`}>
|
||||
{!isCustomPreset && <span>{t(selectedPreset.labelKey, selectedPreset.i18nOptions)}</span>}
|
||||
{isCustomPreset && <span>{customButtonLabel}</span>}
|
||||
{showColumnName && (
|
||||
<>
|
||||
<span>{column.title}</span>
|
||||
<Badge variant="gray" className="ml-2">
|
||||
{selectedValue}
|
||||
</Badge>
|
||||
</>
|
||||
)}
|
||||
{!showColumnName && <span>{selectedValue}</span>}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex w-fit p-0" align="end">
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
isMultiSelectFilterValue,
|
||||
isTextFilterValue,
|
||||
isNumberFilterValue,
|
||||
isDateRangeFilterValue,
|
||||
} from "./utils";
|
||||
|
||||
type MakeWhereClauseProps = {
|
||||
@@ -154,6 +155,19 @@ export function makeWhereClause(props: MakeWhereClauseProps) {
|
||||
default:
|
||||
throw new Error(`Invalid operator for number filter: ${operator}`);
|
||||
}
|
||||
} else if (isDateRangeFilterValue(filterValue)) {
|
||||
const { startDate, endDate } = filterValue.data;
|
||||
if (!startDate || !endDate) {
|
||||
throw new Error(`Invalid date range filter: ${JSON.stringify({ columnName, startDate, endDate })}`);
|
||||
}
|
||||
|
||||
return {
|
||||
[columnName]: {
|
||||
...jsonPathObj,
|
||||
gte: startDate,
|
||||
lte: endDate,
|
||||
},
|
||||
};
|
||||
}
|
||||
throw new Error(`Invalid filter type: ${JSON.stringify({ columnName, filterValue })}`);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,8 @@ export const ZFilterValue = z.union([
|
||||
]);
|
||||
|
||||
export type DateRangeFilterOptions = {
|
||||
range: "past" | "custom";
|
||||
range?: "past" | "custom";
|
||||
endOfDay?: boolean;
|
||||
};
|
||||
|
||||
export type TextFilterOptions = {
|
||||
|
||||
@@ -126,6 +126,7 @@ const handleGroupEvents = async (event: DirectorySyncEvent, organizationId: numb
|
||||
});
|
||||
await prisma.membership.createMany({
|
||||
data: newUsers.map((user) => ({
|
||||
createdAt: new Date(),
|
||||
userId: user.id,
|
||||
teamId: group.teamId,
|
||||
role: MembershipRole.MEMBER,
|
||||
@@ -163,12 +164,14 @@ const handleGroupEvents = async (event: DirectorySyncEvent, organizationId: numb
|
||||
.map((user) => {
|
||||
return [
|
||||
{
|
||||
createdAt: new Date(),
|
||||
userId: user.id,
|
||||
teamId: group.teamId,
|
||||
role: MembershipRole.MEMBER,
|
||||
accepted: true,
|
||||
},
|
||||
{
|
||||
createdAt: new Date(),
|
||||
userId: user.id,
|
||||
teamId: organizationId,
|
||||
role: MembershipRole.MEMBER,
|
||||
|
||||
@@ -138,6 +138,7 @@ async function createOnboardingEligibleUserAndOnboarding(data: {
|
||||
async function createTestMembership(data: { userId: number; teamId: number; role?: MembershipRole }) {
|
||||
return prismock.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
userId: data.userId,
|
||||
teamId: data.teamId,
|
||||
role: data.role || MembershipRole.MEMBER,
|
||||
|
||||
@@ -131,7 +131,7 @@ function UserListTableContent({ oAuthClientId }: PlatformManagedUsersTableProps)
|
||||
enableHiding: false,
|
||||
size: 200,
|
||||
header: () => {
|
||||
return `Managed Users`;
|
||||
return t("managed_users");
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
if (isPending) {
|
||||
@@ -166,7 +166,7 @@ function UserListTableContent({ oAuthClientId }: PlatformManagedUsersTableProps)
|
||||
{
|
||||
id: "role",
|
||||
accessorFn: (data) => data.role,
|
||||
header: "Role",
|
||||
header: t("role"),
|
||||
size: 100,
|
||||
cell: ({ row, table }) => {
|
||||
if (isPending) {
|
||||
@@ -188,7 +188,7 @@ function UserListTableContent({ oAuthClientId }: PlatformManagedUsersTableProps)
|
||||
{
|
||||
id: "teams",
|
||||
accessorFn: (data) => data.teams.map((team) => team.name),
|
||||
header: "Teams",
|
||||
header: t("teams"),
|
||||
size: 140,
|
||||
cell: ({ row, table }) => {
|
||||
if (isPending) {
|
||||
|
||||
@@ -74,6 +74,8 @@ const initalColumnVisibility = {
|
||||
member: true,
|
||||
role: true,
|
||||
teams: true,
|
||||
createdAt: false,
|
||||
updatedAt: false,
|
||||
actions: true,
|
||||
};
|
||||
|
||||
@@ -366,9 +368,52 @@ function UserListTableContent() {
|
||||
...generateAttributeColumns(),
|
||||
{
|
||||
id: "lastActiveAt",
|
||||
header: "Last Active",
|
||||
accessorKey: "lastActiveAt",
|
||||
header: t("last_active"),
|
||||
enableSorting: false,
|
||||
enableColumnFilter: true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.DATE_RANGE,
|
||||
dateRangeOptions: {
|
||||
endOfDay: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
cell: ({ row }) => <div>{row.original.lastActiveAt}</div>,
|
||||
},
|
||||
{
|
||||
id: "createdAt",
|
||||
accessorKey: "createdAt",
|
||||
header: t("member_since"),
|
||||
enableSorting: false,
|
||||
enableColumnFilter: true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.DATE_RANGE,
|
||||
dateRangeOptions: {
|
||||
endOfDay: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
cell: ({ row }) => <div>{row.original.createdAt || ""}</div>,
|
||||
},
|
||||
{
|
||||
id: "updatedAt",
|
||||
accessorKey: "updatedAt",
|
||||
header: t("last_updated"),
|
||||
enableSorting: false,
|
||||
enableColumnFilter: true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.DATE_RANGE,
|
||||
dateRangeOptions: {
|
||||
endOfDay: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
cell: ({ row }) => <div>{row.original.updatedAt || ""}</div>,
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
enableHiding: false,
|
||||
|
||||
@@ -15,6 +15,7 @@ type IMembership = {
|
||||
userId: number;
|
||||
accepted: boolean;
|
||||
role: MembershipRole;
|
||||
createdAt?: Date;
|
||||
};
|
||||
|
||||
const membershipSelect = Prisma.validator<Prisma.MembershipSelect>()({
|
||||
@@ -71,13 +72,19 @@ const getWhereForfindAllByUpId = async (upId: string, where?: Prisma.MembershipW
|
||||
export class MembershipRepository {
|
||||
static async create(data: IMembership) {
|
||||
return await prisma.membership.create({
|
||||
data,
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
static async createMany(data: IMembership[]) {
|
||||
return await prisma.membership.createMany({
|
||||
data,
|
||||
data: data.map((item) => ({
|
||||
createdAt: new Date(),
|
||||
...item,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ export class OrganizationRepository {
|
||||
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
userId: owner.id,
|
||||
role: MembershipRole.OWNER,
|
||||
accepted: true,
|
||||
@@ -102,6 +103,7 @@ export class OrganizationRepository {
|
||||
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
userId: ownerInDb.id,
|
||||
role: MembershipRole.OWNER,
|
||||
accepted: true,
|
||||
|
||||
@@ -250,6 +250,7 @@ export class TeamRepository {
|
||||
try {
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId: verificationToken.teamId,
|
||||
userId: userId,
|
||||
role: MembershipRole.MEMBER,
|
||||
|
||||
@@ -54,6 +54,7 @@ async function createMockUserWithMembership({ orgId }: { orgId: number }) {
|
||||
});
|
||||
const membership = await prismock.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
role: MembershipRole.MEMBER,
|
||||
disableImpersonation: false,
|
||||
accepted: true,
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "Membership" ADD COLUMN "createdAt" TIMESTAMP(3),
|
||||
ADD COLUMN "updatedAt" TIMESTAMP(3);
|
||||
@@ -549,6 +549,8 @@ model Membership {
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
disableImpersonation Boolean @default(false)
|
||||
AttributeToUser AttributeToUser[]
|
||||
createdAt DateTime?
|
||||
updatedAt DateTime? @updatedAt
|
||||
|
||||
@@unique([userId, teamId])
|
||||
@@index([teamId])
|
||||
|
||||
@@ -188,6 +188,8 @@ async function main() {
|
||||
userId: member.user.id,
|
||||
role: member.role,
|
||||
accepted: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -424,6 +426,8 @@ async function createPerformanceData() {
|
||||
userId: memberId.id,
|
||||
role: "MEMBER",
|
||||
accepted: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})),
|
||||
});
|
||||
|
||||
|
||||
@@ -255,6 +255,7 @@ export async function createTeamAndAddUsers(
|
||||
const { role = MembershipRole.OWNER, id, username } = user;
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId: team.id,
|
||||
userId: id,
|
||||
role: role,
|
||||
|
||||
@@ -122,6 +122,7 @@ const createTeam = async (team: Prisma.TeamCreateInput) => {
|
||||
const associateUserAndOrg = async ({ teamId, userId, role, username }: AssociateUserAndOrgProps) => {
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId,
|
||||
userId,
|
||||
role: role as MembershipRole,
|
||||
@@ -250,6 +251,7 @@ async function createTeamAndAddUsers(
|
||||
const { role = MembershipRole.OWNER, id, username } = user;
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId: team.id,
|
||||
userId: id,
|
||||
role: role,
|
||||
@@ -567,6 +569,7 @@ async function createOrganizationAndAddMembersAndTeams({
|
||||
}
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId: team.id,
|
||||
userId: member.id,
|
||||
role: role,
|
||||
|
||||
@@ -83,6 +83,15 @@ export const listMembersHandler = async ({ ctx, input }: GetOptions) => {
|
||||
const teamFilter = filters.find((filter) => filter.id === "teams") as
|
||||
| TypedColumnFilter<ColumnFilterType.MULTI_SELECT>
|
||||
| undefined;
|
||||
const lastActiveAtFilter = filters.find((filter) => filter.id === "lastActiveAt") as
|
||||
| TypedColumnFilter<ColumnFilterType.DATE_RANGE>
|
||||
| undefined;
|
||||
const createdAtFilter = filters.find((filter) => filter.id === "createdAt") as
|
||||
| TypedColumnFilter<ColumnFilterType.DATE_RANGE>
|
||||
| undefined;
|
||||
const updatedAtFilter = filters.find((filter) => filter.id === "updatedAt") as
|
||||
| TypedColumnFilter<ColumnFilterType.DATE_RANGE>
|
||||
| undefined;
|
||||
|
||||
const whereClause: Prisma.MembershipWhereInput = {
|
||||
user: {
|
||||
@@ -97,6 +106,11 @@ export const listMembersHandler = async ({ ctx, input }: GetOptions) => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
...(lastActiveAtFilter &&
|
||||
makeWhereClause({
|
||||
columnName: "lastActiveAt",
|
||||
filterValue: lastActiveAtFilter.value,
|
||||
})),
|
||||
},
|
||||
teamId: organizationId,
|
||||
...(searchTerm && {
|
||||
@@ -112,10 +126,27 @@ export const listMembersHandler = async ({ ctx, input }: GetOptions) => {
|
||||
columnName: "role",
|
||||
filterValue: roleFilter.value,
|
||||
})),
|
||||
...(createdAtFilter &&
|
||||
makeWhereClause({
|
||||
columnName: "createdAt",
|
||||
filterValue: createdAtFilter.value,
|
||||
})),
|
||||
...(updatedAtFilter &&
|
||||
makeWhereClause({
|
||||
columnName: "updatedAt",
|
||||
filterValue: updatedAtFilter.value,
|
||||
})),
|
||||
};
|
||||
|
||||
const attributeFilters: Prisma.MembershipWhereInput["AttributeToUser"][] = filters
|
||||
.filter((filter) => filter.id !== "role" && filter.id !== "teams")
|
||||
.filter(
|
||||
(filter) =>
|
||||
filter.id !== "role" &&
|
||||
filter.id !== "teams" &&
|
||||
filter.id !== "lastActiveAt" &&
|
||||
filter.id !== "createdAt" &&
|
||||
filter.id !== "updatedAt"
|
||||
)
|
||||
.map((filter) => {
|
||||
if (filter.value.type === ColumnFilterType.MULTI_SELECT && isAllString(filter.value.data)) {
|
||||
const attributeOptionValues: string[] = [];
|
||||
@@ -163,6 +194,8 @@ export const listMembersHandler = async ({ ctx, input }: GetOptions) => {
|
||||
id: true,
|
||||
role: true,
|
||||
accepted: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
@@ -249,6 +282,20 @@ export const listMembersHandler = async ({ ctx, input }: GetOptions) => {
|
||||
.format(membership.user.lastActiveAt)
|
||||
.toLowerCase()
|
||||
: null,
|
||||
createdAt: membership.createdAt
|
||||
? new Intl.DateTimeFormat(ctx.user.locale, {
|
||||
timeZone: ctx.user.timeZone,
|
||||
})
|
||||
.format(membership.createdAt)
|
||||
.toLowerCase()
|
||||
: null,
|
||||
updatedAt: membership.updatedAt
|
||||
? new Intl.DateTimeFormat(ctx.user.locale, {
|
||||
timeZone: ctx.user.timeZone,
|
||||
})
|
||||
.format(membership.updatedAt)
|
||||
.toLowerCase()
|
||||
: null,
|
||||
avatarUrl: user.avatarUrl,
|
||||
teams: user.teams
|
||||
.filter((team) => team.team.id !== organizationId) // In this context we dont want to return the org team
|
||||
|
||||
@@ -65,6 +65,7 @@ export const addMembersToTeams = async ({ user, input }: AddBulkToTeamProps) =>
|
||||
const userMembership = usersInOrganization.find((membership) => membership.userId === userId);
|
||||
const accepted = userMembership && userMembership.accepted;
|
||||
return {
|
||||
createdAt: new Date(),
|
||||
userId,
|
||||
teamId,
|
||||
role: MembershipRole.MEMBER,
|
||||
|
||||
@@ -376,6 +376,7 @@ export async function createNewUsersConnectToOrgIfExists({
|
||||
if (parentId) {
|
||||
await tx.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
teamId: parentId,
|
||||
userId: createdUser.id,
|
||||
role: MembershipRole.MEMBER,
|
||||
@@ -413,8 +414,10 @@ export async function createMemberships({
|
||||
data: invitees.flatMap((invitee) => {
|
||||
const organizationRole = invitee?.teams?.[0]?.role;
|
||||
const data = [];
|
||||
const createdAt = new Date();
|
||||
// membership for the team
|
||||
data.push({
|
||||
createdAt,
|
||||
teamId,
|
||||
userId: invitee.id,
|
||||
accepted,
|
||||
@@ -424,6 +427,7 @@ export async function createMemberships({
|
||||
// membership for the org
|
||||
if (parentId && invitee.needToCreateOrgMembership) {
|
||||
data.push({
|
||||
createdAt,
|
||||
accepted,
|
||||
teamId: parentId,
|
||||
userId: invitee.id,
|
||||
@@ -866,6 +870,7 @@ export async function handleExistingUsersInvites({
|
||||
|
||||
await prisma.membership.create({
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
userId: user.id,
|
||||
teamId: team.id,
|
||||
accepted: shouldAutoAccept,
|
||||
|
||||
Reference in New Issue
Block a user