Skip to content

Commit

Permalink
V2 settings teams (Profil, Members, Appearance View) (#4350)
Browse files Browse the repository at this point in the history
* add team profile

* first version for team members page

* finish up design of member list item

* fix dialog buttons

* add missing seats and upgrading information

* add v2 dialog for changing role

* finish basic version of member's schedule

* remove modalContainer

* design fixes team profile page

* show only team info to non admins

* allow all member to check availabilities

* make time available heading sticky

* add dropdown for mobile view

* create team appearance view

* finish appearance page

* use settings layout and add danger zone for member

* add fallback logo

* Add teams to sidebar and fix UI

* add team invitations

* Clean up

* code clean up

* add impersontation and disable autofocus on calendar

* improve team info

* refactor teaminvitelist code and fix leaving a team

* add team pages to settings shell

* add link to create new team

* small fixes

* clean up comments

* V2 Multi-select (Team Select) (#4324)

* --init

* design improved

* further fine tuning

* more fixes

* removed extra JSX tag

* added story

* NIT

* revert to use of CheckedTeamSelect

* Removes comments

Co-authored-by: Peer Richelsen <peeroke@gmail.com>

* fix: toggle alligment (#4361)

* fix: add checked tranform for switch (#4357)

* fixed input size on mobile, fixed settings (#4360)

* fix image uploader button in safari

* code clean up

* fixing type errors

* Moved v2 team components to features

Adds deprecation notices

* Update SettingsLayout.tsx

* Migrated to features and build fixes

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
  • Loading branch information
8 people authored Sep 12, 2022
1 parent 50f63ef commit 7e917cd
Show file tree
Hide file tree
Showing 36 changed files with 1,917 additions and 31 deletions.
1 change: 1 addition & 0 deletions apps/web/components/ImageUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ function CropContainer({
);
}

/** @deprecated Use `packages/ui/v2/core/ImageUploader.tsx` */
export default function ImageUploader({
target,
id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { User } from "@calcom/prisma/client";
import { trpc } from "@calcom/trpc/react";
import { Button, showToast, TextArea } from "@calcom/ui/v2";
import ImageUploader from "@calcom/ui/v2/core/ImageUploader";

import { AvatarSSR } from "@components/ui/AvatarSSR";
import ImageUploader from "@components/v2/settings/ImageUploader";

interface IUserProfile {
user?: User;
Expand Down
1 change: 1 addition & 0 deletions apps/web/components/team/DisableTeamImpersonation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { trpc } from "@calcom/trpc/react";
import Badge from "@calcom/ui/Badge";
import Button from "@calcom/ui/Button";

/** @deprecated Use `packages/features/ee/teams/components/DisableTeamImpersonation.tsx` */
const DisableTeamImpersonation = ({ teamId, memberId }: { teamId: number; memberId: number }) => {
const { t } = useLocale();

Expand Down
1 change: 1 addition & 0 deletions apps/web/components/team/MemberChangeRoleModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type MembershipRoleOption = {
value: MembershipRole;
};

/** @deprecated Use `packages/features/ee/teams/components/MemberChangeRoleModal.tsx` */
export default function MemberChangeRoleModal(props: {
isOpen: boolean;
currentMember: MembershipRole;
Expand Down
1 change: 1 addition & 0 deletions apps/web/components/team/MemberInvitationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type MembershipRoleOption = {

const _options: MembershipRoleOption[] = [{ value: "MEMBER" }, { value: "ADMIN" }, { value: "OWNER" }];

/** @deprecated Use `packages/features/ee/teams/components/MemberInvitationModal.tsx` */
export default function MemberInvitationModal(props: MemberInvitationModalProps) {
const [errorMessage, setErrorMessage] = useState("");
const { t, i18n } = useLocale();
Expand Down
1 change: 1 addition & 0 deletions apps/web/components/team/MemberListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface Props {
member: inferQueryOutput<"viewer.teams.get">["members"][number];
}

/** @deprecated Use `packages/features/ee/teams/components/MemberListItem.tsx` */
export default function MemberListItem(props: Props) {
const { t } = useLocale();

Expand Down
1 change: 1 addition & 0 deletions apps/web/components/team/TeamPill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface Props {
color?: PillColor;
}

/** @deprecated Use `packages/features/ee/teams/components/TeamPill.tsx` */
export default function TeamPill(props: Props) {
return (
<div
Expand Down
1 change: 1 addition & 0 deletions apps/web/components/team/UpgradeToFlexibleProModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface Props {
teamId: number;
}

/** @deprecated Use `packages/features/ee/teams/components/UpgradeToFlexibleProModal.tsx` */
export function UpgradeToFlexibleProModal(props: Props) {
const { t } = useLocale();
const [errorMessage, setErrorMessage] = useState<string | null>(null);
Expand Down
1 change: 1 addition & 0 deletions apps/web/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const V2_WHITELIST = [
"/settings/developer/api-keys",
"/settings/my-account",
"/settings/security",
"/settings/teams",
"/availability",
"/bookings",
"/event-types",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/pages/v2/settings/my-account/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Alert } from "@calcom/ui/Alert";
import Avatar from "@calcom/ui/v2/core/Avatar";
import { Button } from "@calcom/ui/v2/core/Button";
import { Dialog, DialogContent, DialogTrigger } from "@calcom/ui/v2/core/Dialog";
import ImageUploader from "@calcom/ui/v2/core/ImageUploader";
import Meta from "@calcom/ui/v2/core/Meta";
import { Form, Label, TextField, PasswordField } from "@calcom/ui/v2/core/form/fields";
import { getLayout } from "@calcom/ui/v2/core/layouts/SettingsLayout";
Expand All @@ -23,7 +24,6 @@ import showToast from "@calcom/ui/v2/core/notifications";
import { inferSSRProps } from "@lib/types/inferSSRProps";

import TwoFactor from "@components/auth/TwoFactor";
import ImageUploader from "@components/v2/settings/ImageUploader";

interface DeleteAccountValues {
totpCode: string;
Expand Down
1 change: 1 addition & 0 deletions apps/web/pages/v2/settings/teams/[id]/appearance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "@calcom/features/ee/teams/pages/team-appearance-view";
1 change: 1 addition & 0 deletions apps/web/pages/v2/settings/teams/[id]/members.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "@calcom/features/ee/teams/pages/team-members-view";
1 change: 1 addition & 0 deletions apps/web/pages/v2/settings/teams/[id]/profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "@calcom/features/ee/teams/pages/team-profile-view";
22 changes: 17 additions & 5 deletions apps/web/public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -481,12 +481,12 @@
"leave": "Leave",
"profile": "Profile",
"my_team_url": "My team URL",
"team_name": "Team name",
"team_name": "Team Name",
"your_team_name": "Your team name",
"team_updated_successfully": "Team updated successfully",
"your_team_updated_successfully": "Your team has been updated successfully.",
"about": "About",
"team_description": "A few sentences about your team. This will appear on your team's URL page.",
"team_description": "A few sentences about your team. This will appear on your team's url page.",
"members": "Members",
"member": "Member",
"owner": "Owner",
Expand All @@ -498,9 +498,9 @@
"invite_new_member": "Invite a new member",
"invite_new_team_member": "Invite someone to your team.",
"change_member_role": "Change team member role",
"disable_cal_branding": "Disable Cal.com branding",
"disable_cal_branding": "Disable Cal branding",
"disable_cal_branding_description": "Hide all Cal.com branding from your public pages.",
"danger_zone": "Danger Zone",
"danger_zone": "Danger zone",
"back": "Back",
"cancel": "Cancel",
"cancel_all_remaining": "Cancel all remaining",
Expand Down Expand Up @@ -877,7 +877,7 @@
"impersonate": "Impersonate",
"user_impersonation_heading": "User Impersonation",
"user_impersonation_description": "Allows our support team to temporarily sign in as you to help us quickly resolve any issues you report to us.",
"team_impersonation_description": "Allows your team admins to temporarily sign in as you.",
"team_impersonation_description": "Allows your team members to temporarily sign in as you.",
"impersonate_user_tip": "All uses of this feature is audited.",
"impersonating_user_warning": "Impersonating username \"{{user}}\".",
"impersonating_stop_instructions": "<0>Click Here to stop</0>.",
Expand Down Expand Up @@ -1171,6 +1171,11 @@
"for_a_maximum_of": "For a maximum of",
"event_one": "event",
"event_other": "events",
"profile_team_description": "Manage settings for your team profile",
"members_team_description": "Users that are in the group. Apes together strong!",
"team_url": "Team URL",
"delete_team": "Delete Team",
"team_members": "Team members",
"more": "More",
"more_page_footer": "We view the mobile application as an extension of the web application. If you are performing any complication actions, please refer back to the web application.",
"workflow_example_1": "Send email reminder 24 hours before event starts to host",
Expand All @@ -1184,6 +1189,13 @@
"connect_calendar_later": "I'll connect my calendar later",
"set_my_availability_later": "I'll set my availability later",
"problem_saving_user_profile": "There was a problem saving your data. Please try again or reach out to customer support.",
"purchase_missing_seats": "Purchase missing seats",
"slot_length": "Slot length",
"booking_appearance": "Booking Appearance",
"appearance_team_description": "Manage settings for your team's booking appearance",
"only_owner_change": "Only the owner of this team can make changes to the team's booking ",
"team_disable_cal_branding_description": "Removes any Cal related brandings, i.e. 'Powered by Cal'",
"invited_by_team": "{{teamName}} has invited you to join their team as a {{role}}",
"token_invalid_expired": "Token is either invalid or expired.",
"routing_forms_description": "You can see all forms and routes you have created here.",
"add_new_form": "Add new form",
Expand Down
63 changes: 63 additions & 0 deletions packages/features/ee/teams/components/DisableTeamImpersonation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { showToast, Switch } from "@calcom/ui/v2/core";

const DisableTeamImpersonation = ({
teamId,
memberId,
disabled,
}: {
teamId: number;
memberId: number;
disabled: boolean;
}) => {
const { t } = useLocale();

const utils = trpc.useContext();

const query = trpc.useQuery(["viewer.teams.getMembershipbyUser", { teamId, memberId }]);

const mutation = trpc.useMutation("viewer.teams.updateMembership", {
onSuccess: async () => {
showToast(t("your_user_profile_updated_successfully"), "success");
await utils.invalidateQueries(["viewer.teams.getMembershipbyUser"]);
},
async onSettled() {
await utils.invalidateQueries(["viewer.public.i18n"]);
},
});
if (query.isLoading) return <></>;

return (
<>
<div className="flex flex-col justify-between sm:flex-row">
<div>
<div className="flex flex-row items-center">
<h2
className={classNames(
"font-cal mb-0.5 text-sm font-semibold leading-6",
disabled ? "text-gray-400 " : "text-gray-900 "
)}>
{t("user_impersonation_heading")}
</h2>
</div>
<p className={classNames("text-sm leading-5 ", disabled ? "text-gray-300" : "text-gray-600")}>
{t("team_impersonation_description")}
</p>
</div>
<div className="mt-5 sm:mt-0 sm:self-center">
<Switch
disabled={disabled}
defaultChecked={query.data?.disableImpersonation}
onCheckedChange={(isChecked) => {
mutation.mutate({ teamId, memberId, disableImpersonation: isChecked });
}}
/>
</div>
</div>
</>
);
};

export default DisableTeamImpersonation;
113 changes: 113 additions & 0 deletions packages/features/ee/teams/components/MemberChangeRoleModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { MembershipRole } from "@prisma/client";
import { SyntheticEvent, useMemo, useState } from "react";

import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { Button, Dialog, DialogContent, Select } from "@calcom/ui/v2";

type MembershipRoleOption = {
label: string;
value: MembershipRole;
};

export default function MemberChangeRoleModal(props: {
isOpen: boolean;
currentMember: MembershipRole;
memberId: number;
teamId: number;
initialRole: MembershipRole;
onExit: () => void;
}) {
const { t } = useLocale();

const options = useMemo(() => {
return [
{
label: t("member"),
value: MembershipRole.MEMBER,
},
{
label: t("admin"),
value: MembershipRole.ADMIN,
},
{
label: t("owner"),
value: MembershipRole.OWNER,
},
].filter(({ value }) => value !== MembershipRole.OWNER || props.currentMember === MembershipRole.OWNER);
}, [t, props.currentMember]);

const [role, setRole] = useState<MembershipRoleOption>(
options.find((option) => option.value === props.initialRole) || {
label: t("member"),
value: MembershipRole.MEMBER,
}
);
const [errorMessage, setErrorMessage] = useState("");
const utils = trpc.useContext();

const changeRoleMutation = trpc.useMutation("viewer.teams.changeMemberRole", {
async onSuccess() {
await utils.invalidateQueries(["viewer.teams.get"]);
props.onExit();
},
async onError(err) {
setErrorMessage(err.message);
},
});

function changeRole(e: SyntheticEvent) {
e.preventDefault();

changeRoleMutation.mutate({
teamId: props.teamId,
memberId: props.memberId,
role: role.value,
});
}
return (
<Dialog open={props.isOpen} onOpenChange={props.onExit}>
<DialogContent type="creation" useOwnActionButtons size="md">
<>
<div className="mb-4 sm:flex sm:items-start">
<div className="text-center sm:text-left">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title">
{t("change_member_role")}
</h3>
</div>
</div>
<form onSubmit={changeRole}>
<div className="mb-4">
<label className="mb-2 block text-sm font-medium tracking-wide text-gray-700" htmlFor="role">
{t("role")}
</label>
{/*<option value="OWNER">{t("owner")}</option> - needs dialog to confirm change of ownership */}
<Select
isSearchable={false}
options={options}
value={role}
onChange={(option) => option && setRole(option)}
id="role"
className="mt-1 block w-full rounded-md border-gray-300 text-sm"
/>
</div>
{errorMessage && (
<p className="text-sm text-red-700">
<span className="font-bold">Error: </span>
{errorMessage}
</p>
)}
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<Button type="submit" color="primary" className="ltr:ml-2 rtl:mr-2">
{t("save")}
</Button>
<Button type="button" color="secondary" onClick={props.onExit}>
{t("cancel")}
</Button>
</div>
</form>
</>
</DialogContent>
</Dialog>
);
}
Loading

0 comments on commit 7e917cd

Please sign in to comment.