UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: редизайн drafts stickies profile home и settings-shell
This commit is contained in:
@@ -8,14 +8,13 @@ import { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// ui
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { DraftIcon } from "@plane/propel/icons";
|
||||
import { EIssuesStoreType } from "@plane/types";
|
||||
import { Breadcrumbs, Header } from "@plane/ui";
|
||||
// components
|
||||
import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
|
||||
import { CountChip } from "@/components/common/count-chip";
|
||||
import { AppHeaderPrimaryActionButton } from "@/components/core/app-header/primary-action-button";
|
||||
import { CreateUpdateIssueModal } from "@/components/issues/issue-modal/modal";
|
||||
|
||||
// hooks
|
||||
@@ -66,15 +65,12 @@ export const WorkspaceDraftHeader = observer(function WorkspaceDraftHeader() {
|
||||
|
||||
<Header.RightItem>
|
||||
{joinedProjectIds && joinedProjectIds.length > 0 && (
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
className="items-center gap-1"
|
||||
<AppHeaderPrimaryActionButton
|
||||
onClick={() => setIsDraftIssueModalOpen(true)}
|
||||
disabled={!isAuthorizedUser}
|
||||
>
|
||||
{t("workspace_draft_issues.draft_an_issue")}
|
||||
</Button>
|
||||
</AppHeaderPrimaryActionButton>
|
||||
)}
|
||||
</Header.RightItem>
|
||||
</Header>
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
*/
|
||||
|
||||
// components
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { PageHead } from "@/components/core/page-title";
|
||||
import { WorkspaceDraftIssuesRoot } from "@/components/issues/workspace-draft";
|
||||
import type { Route } from "./+types/page";
|
||||
|
||||
function WorkspaceDraftPage({ params }: Route.ComponentProps) {
|
||||
const { workspaceSlug } = params;
|
||||
const pageTitle = "Workspace Draft";
|
||||
const { t } = useTranslation();
|
||||
const pageTitle = t("sidebar.drafts");
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -41,7 +41,7 @@ export const WorkspaceDashboardHeader = observer(function WorkspaceDashboardHead
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
onClick={() => toggleWidgetSettings(true)}
|
||||
className="my-auto mb-0"
|
||||
className="nodedc-toolbar-pill my-auto mb-0"
|
||||
prependIcon={<Shapes />}
|
||||
>
|
||||
<div className="hidden sm:hidden md:block">{t("home.manage_widgets")}</div>
|
||||
|
||||
+6
-4
@@ -5,15 +5,16 @@
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// components
|
||||
import { PageHead } from "@/components/core/page-title";
|
||||
import { ProfileIssuesPage } from "@/components/profile/profile-issues";
|
||||
import type { Route } from "./+types/page";
|
||||
|
||||
const ProfilePageHeader = {
|
||||
assigned: "Profile - Assigned",
|
||||
created: "Profile - Created",
|
||||
subscribed: "Profile - Subscribed",
|
||||
assigned: "profile.tabs.assigned",
|
||||
created: "profile.tabs.created",
|
||||
subscribed: "profile.tabs.subscribed",
|
||||
};
|
||||
|
||||
function isValidProfileViewId(viewId: string): viewId is keyof typeof ProfilePageHeader {
|
||||
@@ -22,10 +23,11 @@ function isValidProfileViewId(viewId: string): viewId is keyof typeof ProfilePag
|
||||
|
||||
function ProfileIssuesTypePage({ params }: Route.ComponentProps) {
|
||||
const { profileViewId } = params;
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!isValidProfileViewId(profileViewId)) return null;
|
||||
|
||||
const header = ProfilePageHeader[profileViewId];
|
||||
const header = `${t("profile.page_label")} - ${t(ProfilePageHeader[profileViewId])}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
+6
-5
@@ -51,20 +51,21 @@ function ProfileActivityPage() {
|
||||
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
|
||||
EUserPermissionsLevel.WORKSPACE
|
||||
);
|
||||
const pageTitle = `${t("profile.page_label")} - ${t("profile.tabs.activity")}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHead title="Profile - Activity" />
|
||||
<div className="flex h-full w-full flex-col overflow-hidden py-5">
|
||||
<div className="flex items-center justify-between gap-2 px-5 md:px-9">
|
||||
<PageHead title={pageTitle} />
|
||||
<div className="nodedc-workspace-page-shell flex h-full w-full flex-col gap-5 overflow-hidden">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<h3 className="text-16 font-medium">{t("profile.stats.recent_activity.title")}</h3>
|
||||
{canDownloadActivity && <DownloadActivityButton />}
|
||||
</div>
|
||||
<div className="vertical-scrollbar flex scrollbar-md h-full flex-col overflow-y-auto px-5 md:px-9">
|
||||
<div className="vertical-scrollbar flex scrollbar-md h-full flex-col overflow-y-auto">
|
||||
{activityPages}
|
||||
{pageCount < totalPages && resultsCount !== 0 && (
|
||||
<div className="flex w-full items-center justify-center text-11">
|
||||
<Button variant="secondary" onClick={handleLoadMore}>
|
||||
<Button variant="secondary" size="lg" className="nodedc-toolbar-pill" onClick={handleLoadMore}>
|
||||
{t("common.load_more")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
+10
-10
@@ -20,7 +20,6 @@ import { ProfileIssuesFilter } from "@/components/profile/profile-issues-filter"
|
||||
// hooks
|
||||
import { useAppTheme } from "@/hooks/store/use-app-theme";
|
||||
import { useUser, useUserPermissions } from "@/hooks/store/user";
|
||||
import { Button } from "@plane/propel/button";
|
||||
|
||||
type TUserProfileHeader = {
|
||||
userProjectsData: IUserProfileProjectSegregation | undefined;
|
||||
@@ -75,8 +74,10 @@ export const UserProfileHeader = observer(function UserProfileHeader(props: TUse
|
||||
<SelectionDropdown
|
||||
placement="bottom-start"
|
||||
menuButton={
|
||||
<div className="flex items-center gap-2 rounded-md border border-subtle px-2 py-1.5">
|
||||
<span className="flex flex-grow justify-center text-13 text-secondary">{type}</span>
|
||||
<div className="nodedc-toolbar-pill flex items-center gap-2 px-3.5">
|
||||
<span className="flex flex-grow justify-center text-13 text-secondary">
|
||||
{type ? t(type) : t("profile.tabs.summary")}
|
||||
</span>
|
||||
<ChevronDownIcon className="h-4 w-4 text-placeholder" />
|
||||
</div>
|
||||
}
|
||||
@@ -89,16 +90,15 @@ export const UserProfileHeader = observer(function UserProfileHeader(props: TUse
|
||||
}))}
|
||||
/>
|
||||
<div className="shrink-0 md:hidden">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="lg"
|
||||
<button
|
||||
type="button"
|
||||
className="nodedc-toolbar-icon-button grid h-10 w-10 place-items-center rounded-full"
|
||||
onClick={() => {
|
||||
toggleProfileSidebar();
|
||||
}}
|
||||
appendIcon={
|
||||
<PanelRight className={!profileSidebarCollapsed ? "text-accent-primary" : "text-secondary"} />
|
||||
}
|
||||
></Button>
|
||||
>
|
||||
<PanelRight className={!profileSidebarCollapsed ? "text-accent-primary" : "text-secondary"} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Header.RightItem>
|
||||
|
||||
+13
-10
@@ -9,7 +9,6 @@ import { useParams, usePathname } from "next/navigation";
|
||||
// plane imports
|
||||
import { PROFILE_VIEWER_TAB, PROFILE_ADMINS_TAB } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Header, EHeaderVariant } from "@plane/ui";
|
||||
import { cn } from "@plane/utils";
|
||||
|
||||
type Props = {
|
||||
@@ -25,17 +24,21 @@ export function ProfileNavbar(props: Props) {
|
||||
const tabsList = isAuthorized ? [...PROFILE_VIEWER_TAB, ...PROFILE_ADMINS_TAB] : PROFILE_VIEWER_TAB;
|
||||
|
||||
return (
|
||||
<Header variant={EHeaderVariant.SECONDARY} showOnMobile={false}>
|
||||
<div className="flex items-center overflow-x-scroll">
|
||||
<div className="hidden border-b border-white/6 px-5 py-3 md:block md:px-9">
|
||||
<div className="flex items-center gap-2 overflow-x-auto">
|
||||
{tabsList.map((tab) => (
|
||||
<Link key={tab.route} href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}>
|
||||
<Link
|
||||
key={tab.route}
|
||||
href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}
|
||||
className={cn(
|
||||
"nodedc-toolbar-pill whitespace-nowrap px-4 text-13 font-medium",
|
||||
pathname === `/${workspaceSlug}/profile/${userId}${tab.selected}` ? "text-primary" : "text-secondary"
|
||||
)}
|
||||
data-active={pathname === `/${workspaceSlug}/profile/${userId}${tab.selected}` ? "true" : "false"}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
`flex border-b-2 p-4 text-13 font-medium whitespace-nowrap text-tertiary outline-none hover:text-primary ${
|
||||
pathname === `/${workspaceSlug}/profile/${userId}${tab.selected}`
|
||||
? "border-accent-strong text-accent-primary hover:text-accent-primary"
|
||||
: "border-transparent"
|
||||
}`
|
||||
"flex items-center justify-center"
|
||||
)}
|
||||
>
|
||||
{t(tab.i18n_label)}
|
||||
@@ -43,6 +46,6 @@ export function ProfileNavbar(props: Props) {
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Header>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ export default function ProfileOverviewPage({ params }: Route.ComponentProps) {
|
||||
return (
|
||||
<>
|
||||
<PageHead title={t("profile.page_label")} />
|
||||
<ContentWrapper className="space-y-7">
|
||||
<ContentWrapper className="nodedc-workspace-page-shell space-y-7">
|
||||
<ProfileStats userProfile={userProfile} />
|
||||
<ProfileWorkload stateDistribution={stateDistribution} />
|
||||
<div className="grid grid-cols-1 items-stretch gap-5 xl:grid-cols-2">
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { RecentStickyIcon } from "@plane/propel/icons";
|
||||
import { Breadcrumbs, Header } from "@plane/ui";
|
||||
// components
|
||||
import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
|
||||
import { AppHeaderPrimaryActionButton } from "@/components/core/app-header/primary-action-button";
|
||||
import { StickySearch } from "@/components/stickies/modal/search";
|
||||
import { useStickyOperations } from "@/components/stickies/sticky/use-operations";
|
||||
// hooks
|
||||
@@ -19,6 +20,7 @@ import { useSticky } from "@/hooks/use-stickies";
|
||||
|
||||
export const WorkspaceStickyHeader = observer(function WorkspaceStickyHeader() {
|
||||
const { workspaceSlug } = useParams();
|
||||
const { t } = useTranslation();
|
||||
// hooks
|
||||
const { creatingSticky, toggleShowNewSticky } = useSticky();
|
||||
const { stickyOperations } = useStickyOperations({ workspaceSlug: workspaceSlug?.toString() });
|
||||
@@ -32,7 +34,7 @@ export const WorkspaceStickyHeader = observer(function WorkspaceStickyHeader() {
|
||||
<Breadcrumbs.Item
|
||||
component={
|
||||
<BreadcrumbLink
|
||||
label={`Stickies`}
|
||||
label={t("sidebar.stickies")}
|
||||
icon={<RecentStickyIcon className="size-5 rotate-90 text-secondary" />}
|
||||
/>
|
||||
}
|
||||
@@ -43,17 +45,15 @@ export const WorkspaceStickyHeader = observer(function WorkspaceStickyHeader() {
|
||||
|
||||
<Header.RightItem>
|
||||
<StickySearch />
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
<AppHeaderPrimaryActionButton
|
||||
onClick={() => {
|
||||
toggleShowNewSticky(true);
|
||||
stickyOperations.create();
|
||||
}}
|
||||
loading={creatingSticky}
|
||||
>
|
||||
Add sticky
|
||||
</Button>
|
||||
{t("stickies.add")}
|
||||
</AppHeaderPrimaryActionButton>
|
||||
</Header.RightItem>
|
||||
</Header>
|
||||
</>
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
*/
|
||||
|
||||
// components
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { PageHead } from "@/components/core/page-title";
|
||||
import { StickiesInfinite } from "@/components/stickies/layout/stickies-infinite";
|
||||
|
||||
export default function WorkspaceStickiesPage() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHead title="Your stickies" />
|
||||
<PageHead title={t("sidebar.stickies")} />
|
||||
<div className="relative h-full w-full overflow-hidden overflow-y-auto">
|
||||
<div className="nodedc-workspace-page-shell h-full">
|
||||
<StickiesInfinite />
|
||||
|
||||
Reference in New Issue
Block a user