snapshot of https://github.com/makeplane/plane.git @ d868349a55de79979eb8b98701bf1702c67ad634 (2026-09-15)
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:14:58 +05:00
commit 23059a1de3
5252 changed files with 573834 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { useState } from "react";
import { observer } from "mobx-react";
// plane imports
import { DEFAULT_GLOBAL_VIEWS_LIST } from "@plane/constants";
// components
import { PageHead } from "@/components/core/page-title";
import { AllIssueLayoutRoot } from "@/components/issues/issue-layouts/roots/all-issue-layout-root";
// hooks
import { useWorkspace } from "@/hooks/store/use-workspace";
import type { Route } from "./+types/page";
function GlobalViewIssuesPage({ params }: Route.ComponentProps) {
// router
const { globalViewId } = params;
// store hooks
const { currentWorkspace } = useWorkspace();
// states
const [isLoading, setIsLoading] = useState(false);
// derived values
const defaultView = DEFAULT_GLOBAL_VIEWS_LIST.find((view) => view.key === globalViewId);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace?.name} - All Views` : undefined;
// handlers
const toggleLoading = (value: boolean) => setIsLoading(value);
return (
<>
<PageHead title={pageTitle} />
<AllIssueLayoutRoot isDefaultView={!!defaultView} isLoading={isLoading} toggleLoading={toggleLoading} />
</>
);
}
export default observer(GlobalViewIssuesPage);

View File

@@ -0,0 +1,161 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { useCallback, useMemo, useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE, DEFAULT_GLOBAL_VIEWS_LIST } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { ViewsOutline } from "@makeplane/propel/icons";
import type { IIssueDisplayFilterOptions, IIssueDisplayProperties, ICustomSearchSelectOption } from "@plane/types";
import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types";
import { Breadcrumbs, Header, BreadcrumbNavigationSearchDropdown } from "@plane/ui";
// components
import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
import { SwitcherLabel } from "@/components/common/switcher-label";
import { DisplayFiltersSelection, FiltersDropdown } from "@/components/issues/issue-layouts/filters";
import { WorkItemFiltersToggle } from "@/components/work-item-filters/filters-toggle";
import { DefaultWorkspaceViewQuickActions } from "@/components/workspace/views/default-view-quick-action";
import { CreateUpdateWorkspaceViewModal } from "@/components/workspace/views/modal";
import { WorkspaceViewQuickActions } from "@/components/workspace/views/quick-action";
// hooks
import { useGlobalView } from "@/hooks/store/use-global-view";
import { useIssues } from "@/hooks/store/use-issues";
import { useAppRouter } from "@/hooks/use-app-router";
export const GlobalIssuesHeader = observer(function GlobalIssuesHeader() {
// states
const [createViewModal, setCreateViewModal] = useState(false);
// router
const router = useAppRouter();
const { workspaceSlug, globalViewId: routerGlobalViewId } = useParams();
const globalViewId = routerGlobalViewId ? routerGlobalViewId.toString() : undefined;
// store hooks
const {
issuesFilter: { filters, updateFilters },
} = useIssues(EIssuesStoreType.GLOBAL);
const { getViewDetailsById, currentWorkspaceViews } = useGlobalView();
const { t } = useTranslation();
const issueFilters = globalViewId ? filters[globalViewId.toString()] : undefined;
const activeLayout = issueFilters?.displayFilters?.layout;
const viewDetails = globalViewId ? getViewDetailsById(globalViewId) : undefined;
const handleDisplayFilters = useCallback(
(updatedDisplayFilter: Partial<IIssueDisplayFilterOptions>) => {
if (!workspaceSlug || !globalViewId) return;
updateFilters(
workspaceSlug.toString(),
undefined,
EIssueFilterType.DISPLAY_FILTERS,
updatedDisplayFilter,
globalViewId
);
},
[workspaceSlug, updateFilters, globalViewId]
);
const handleDisplayProperties = useCallback(
(property: Partial<IIssueDisplayProperties>) => {
if (!workspaceSlug || !globalViewId) return;
updateFilters(workspaceSlug.toString(), undefined, EIssueFilterType.DISPLAY_PROPERTIES, property, globalViewId);
},
[workspaceSlug, updateFilters, globalViewId]
);
const isLocked = viewDetails?.is_locked;
const isDefaultView = DEFAULT_GLOBAL_VIEWS_LIST.find((view) => view.key === globalViewId);
const defaultViewDetails = DEFAULT_GLOBAL_VIEWS_LIST.find((view) => view.key === globalViewId);
const defaultOptions = DEFAULT_GLOBAL_VIEWS_LIST.map((view) => ({
value: view.key,
query: view.key,
content: <SwitcherLabel name={t(view.i18n_label)} LabelIcon={ViewsOutline} />,
}));
const workspaceOptions = (currentWorkspaceViews || []).map((view) => {
const _view = getViewDetailsById(view);
if (!_view) return;
return {
value: _view.id,
query: _view.name,
content: <SwitcherLabel name={_view.name} LabelIcon={ViewsOutline} />,
};
});
const switcherOptions = [...defaultOptions, ...workspaceOptions].filter(
(option) => option !== undefined
) as ICustomSearchSelectOption[];
const currentLayoutFilters = useMemo(() => {
const layout = activeLayout ?? EIssueLayoutTypes.SPREADSHEET;
return ISSUE_DISPLAY_FILTERS_BY_PAGE.my_issues.layoutOptions[layout];
}, [activeLayout]);
return (
<>
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
<Header>
<Header.LeftItem>
<Breadcrumbs>
<Breadcrumbs.Item
component={
<BreadcrumbLink label={t("views")} icon={<ViewsOutline className="h-4 w-4 text-tertiary" />} />
}
/>
<Breadcrumbs.Item
component={
<BreadcrumbNavigationSearchDropdown
selectedItem={globalViewId?.toString() || ""}
navigationItems={switcherOptions}
onChange={(value: string) => {
router.push(`/${workspaceSlug}/workspace-views/${value}`);
}}
title={viewDetails?.name ?? t(defaultViewDetails?.i18n_label ?? "")}
icon={
<Breadcrumbs.Icon>
<ViewsOutline className="size-4 flex-shrink-0 text-tertiary" />
</Breadcrumbs.Icon>
}
isLast
/>
}
isLast
/>
</Breadcrumbs>
</Header.LeftItem>
<Header.RightItem className="items-center">
{globalViewId && <WorkItemFiltersToggle entityType={EIssuesStoreType.GLOBAL} entityId={globalViewId} />}
{!isLocked && (
<FiltersDropdown title={t("common.display")} placement="bottom-end">
<DisplayFiltersSelection
layoutDisplayFiltersOptions={currentLayoutFilters}
displayFilters={issueFilters?.displayFilters ?? {}}
handleDisplayFiltersUpdate={handleDisplayFilters}
displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties}
/>
</FiltersDropdown>
)}
<Button variant="primary" size="lg" onClick={() => setCreateViewModal(true)}>
{t("workspace_views.add_view")}
</Button>
<div className="hidden md:block">
{viewDetails && <WorkspaceViewQuickActions workspaceSlug={workspaceSlug?.toString()} view={viewDetails} />}
{isDefaultView && defaultViewDetails && (
<DefaultWorkspaceViewQuickActions workspaceSlug={workspaceSlug?.toString()} view={defaultViewDetails} />
)}
</div>
</Header.RightItem>
</Header>
</>
);
});

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { Outlet } from "react-router";
import { AppHeader } from "@/components/core/app-header";
import { ContentWrapper } from "@/components/core/content-wrapper";
import { GlobalIssuesHeader } from "./header";
export default function GlobalIssuesLayout() {
return (
<>
<AppHeader header={<GlobalIssuesHeader />} />
<ContentWrapper>
<Outlet />
</ContentWrapper>
</>
);
}

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React, { useState } from "react";
import { observer } from "mobx-react";
// plane imports
import { Input, InputGroup } from "@makeplane/propel/components/input";
import { DEFAULT_GLOBAL_VIEWS_LIST } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { SearchOutline } from "@makeplane/propel/icons";
// components
import { PageHead } from "@/components/core/page-title";
import { GlobalDefaultViewListItem } from "@/components/workspace/views/default-view-list-item";
import { GlobalViewsList } from "@/components/workspace/views/views-list";
// hooks
import { useWorkspace } from "@/hooks/store/use-workspace";
function WorkspaceViewsPage() {
const [query, setQuery] = useState("");
// store
const { currentWorkspace } = useWorkspace();
const { t } = useTranslation();
// derived values
const pageTitle = currentWorkspace?.name ? `${currentWorkspace?.name} - All Views` : undefined;
return (
<>
<PageHead title={pageTitle} />
<div className="flex h-full w-full flex-col overflow-hidden">
<div className="flex h-11 w-full items-center overflow-hidden border-b border-subtle px-5 py-3">
<InputGroup size="2xl">
<SearchOutline className="text-secondary" width={14} height={14} />
<Input
size="2xl"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search"
aria-label="Search"
/>
</InputGroup>
</div>
<div className="vertical-scrollbar scrollbar-lg flex h-full w-full flex-col">
{DEFAULT_GLOBAL_VIEWS_LIST.filter((v) => t(v.i18n_label).toLowerCase().includes(query.toLowerCase())).map(
(option) => (
<GlobalDefaultViewListItem key={option.key} view={option} />
)
)}
<GlobalViewsList searchQuery={query} />
</div>
</div>
</>
);
}
export default observer(WorkspaceViewsPage);