Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions apps/space/core/components/issues/filters/selection.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
import React, { useState } from "react";
import { observer } from "mobx-react";
import { Search } from "lucide-react";
import { CloseIcon } from "@plane/propel/icons";
import { CloseIcon, SearchIcon } from "@plane/propel/icons";
// types
import type { IIssueFilterOptions, TIssueFilterKeys } from "@/types/issue";
// local imports
import { FilterPriority } from "./priority";
import { FilterState } from "./state";

type Props = {
filters: IIssueFilterOptions;
handleFilters: (key: keyof IIssueFilterOptions, value: string | string[]) => void;
layoutDisplayFiltersOptions: TIssueFilterKeys[];
};

export const FilterSelection = observer(function FilterSelection(props: Props) {
const { filters, handleFilters, layoutDisplayFiltersOptions } = props;

const [filtersSearchQuery, setFiltersSearchQuery] = useState("");

const isFilterEnabled = (filter: keyof IIssueFilterOptions) => layoutDisplayFiltersOptions.includes(filter);

return (
<div className="flex h-full w-full flex-col overflow-hidden">
<div className="bg-custom-background-100 p-2.5 pb-0">
<div className="flex items-center gap-1.5 rounded border-[0.5px] border-custom-border-200 bg-custom-background-90 px-1.5 py-1 text-xs">
<Search className="text-custom-text-400" size={12} strokeWidth={2} />
<SearchIcon className="text-custom-text-400" width="12" height="12" strokeWidth={2} />
<input
type="text"
className="w-full bg-custom-background-90 outline-none placeholder:text-custom-text-400"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useCallback, useRef, useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { Plus, Search } from "lucide-react";
import { Plus } from "lucide-react";
import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { EmptyStateCompact } from "@plane/propel/empty-state";
import { SearchIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Tooltip } from "@plane/propel/tooltip";
import { copyUrlToClipboard, orderJoinedProjects } from "@plane/utils";
Expand All @@ -18,7 +18,6 @@ import { useProject } from "@/hooks/store/use-project";
import { useUserPermissions } from "@/hooks/store/user";
import type { TProject } from "@/plane-web/types";
import { ExtendedSidebarWrapper } from "./extended-sidebar-wrapper";

export const ExtendedProjectSidebar = observer(function ExtendedProjectSidebar() {
// refs
const extendedProjectSidebarRef = useRef<HTMLDivElement | null>(null);
Expand All @@ -32,26 +31,21 @@ export const ExtendedProjectSidebar = observer(function ExtendedProjectSidebar()
const { isExtendedProjectSidebarOpened, toggleExtendedProjectSidebar } = useAppTheme();
const { getPartialProjectById, joinedProjectIds: joinedProjects, updateProjectView } = useProject();
const { allowPermissions } = useUserPermissions();

const handleOnProjectDrop = (
sourceId: string | undefined,
destinationId: string | undefined,
shouldDropAtEnd: boolean
) => {
if (!sourceId || !destinationId || !workspaceSlug) return;
if (sourceId === destinationId) return;

const joinedProjectsList: TProject[] = [];
joinedProjects.map((projectId) => {
const projectDetails = getPartialProjectById(projectId);
if (projectDetails) joinedProjectsList.push(projectDetails);
});

const sourceIndex = joinedProjects.indexOf(sourceId);
const destinationIndex = shouldDropAtEnd ? joinedProjects.length : joinedProjects.indexOf(destinationId);

if (joinedProjectsList.length <= 0) return;

const updatedSortOrder = orderJoinedProjects(sourceIndex, destinationIndex, sourceId, joinedProjectsList);
if (updatedSortOrder != undefined)
updateProjectView(workspaceSlug.toString(), sourceId, { sort_order: updatedSortOrder }).catch(() => {
Expand All @@ -62,22 +56,18 @@ export const ExtendedProjectSidebar = observer(function ExtendedProjectSidebar()
});
});
};

// filter projects based on search query
const filteredProjects = joinedProjects.filter((projectId) => {
const project = getPartialProjectById(projectId);
if (!project) return false;
return project.name.toLowerCase().includes(searchQuery.toLowerCase()) || project.identifier.includes(searchQuery);
});

// auth
const isAuthorizedUser = allowPermissions(
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
EUserPermissionsLevel.WORKSPACE
);

const handleClose = useCallback(() => toggleExtendedProjectSidebar(false), [toggleExtendedProjectSidebar]);

const handleCopyText = (projectId: string) => {
copyUrlToClipboard(`${workspaceSlug}/projects/${projectId}/issues`).then(() => {
setToast({
Expand Down Expand Up @@ -123,7 +113,7 @@ export const ExtendedProjectSidebar = observer(function ExtendedProjectSidebar()
)}
</div>
<div className="ml-auto flex items-center gap-1.5 rounded-md border border-custom-border-200 bg-custom-background-100 px-2.5 py-1 w-full">
<Search className="h-3.5 w-3.5 text-custom-text-400" />
<SearchIcon className="h-3.5 w-3.5 text-custom-text-400" />
<input
className="w-full max-w-[234px] border-none bg-transparent text-sm outline-none placeholder:text-custom-text-400"
placeholder={t("search")}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
import React, { useState } from "react";
import { observer } from "mobx-react";
import { Search } from "lucide-react";
// plane imports
import { DEFAULT_GLOBAL_VIEWS_LIST } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { SearchIcon } from "@plane/propel/icons";
import { Input } from "@plane/ui";
// 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 flex-col h-full w-full overflow-hidden">
<div className="flex h-11 w-full items-center gap-2.5 px-5 py-3 overflow-hidden border-b border-custom-border-200">
<Search className="text-custom-text-200" size={14} strokeWidth={2} />
<SearchIcon className="text-custom-text-200" width="14" height="14" strokeWidth={2} />
<Input
className="w-full bg-transparent !p-0 text-xs leading-5 text-custom-text-200 placeholder:text-custom-text-400 focus:outline-none"
value={query}
Expand All @@ -46,5 +44,4 @@ function WorkspaceViewsPage() {
</>
);
}

export default observer(WorkspaceViewsPage);
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useState } from "react";
import { observer } from "mobx-react";
import { Search } from "lucide-react";
// types
import {
EUserPermissions,
Expand All @@ -10,6 +9,7 @@ import {
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { SearchIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IWorkspaceBulkInviteFormData } from "@plane/types";
import { cn } from "@plane/utils";
Expand All @@ -30,7 +30,6 @@ import { useUserPermissions } from "@/hooks/store/user";
import { BillingActionsButton } from "@/plane-web/components/workspace/billing/billing-actions-button";
import { SendWorkspaceInvitationModal } from "@/plane-web/components/workspace/members/invite-modal";
import type { Route } from "./+types/page";

function WorkspaceMembersSettingsPage({ params }: Route.ComponentProps) {
// states
const [inviteModal, setInviteModal] = useState(false);
Expand All @@ -44,27 +43,22 @@ function WorkspaceMembersSettingsPage({ params }: Route.ComponentProps) {
} = useMember();
const { currentWorkspace } = useWorkspace();
const { t } = useTranslation();

// derived values
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
const canPerformWorkspaceMemberActions = allowPermissions(
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
EUserPermissionsLevel.WORKSPACE
);

const handleWorkspaceInvite = async (data: IWorkspaceBulkInviteFormData) => {
try {
await inviteMembersToWorkspace(workspaceSlug, data);

setInviteModal(false);

captureSuccess({
eventName: MEMBER_TRACKER_EVENTS.invite,
payload: {
emails: data.emails.map((email) => email.email),
},
});

setToast({
type: TOAST_TYPE.SUCCESS,
title: "Success!",
Expand All @@ -79,39 +73,32 @@ function WorkspaceMembersSettingsPage({ params }: Route.ComponentProps) {
},
error: err,
});

setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: `${err.error ?? t("something_went_wrong_please_try_again")}`,
});

throw err;
}
};

// Handler for role filter updates
const handleRoleFilterUpdate = (role: string) => {
const currentFilters = filtersStore.filters;
const currentRoles = currentFilters?.roles || [];
const updatedRoles = currentRoles.includes(role) ? currentRoles.filter((r) => r !== role) : [...currentRoles, role];

filtersStore.updateFilters({
roles: updatedRoles.length > 0 ? updatedRoles : undefined,
});
};

// derived values
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Members` : undefined;
const appliedRoleFilters = filtersStore.filters?.roles || [];

// if user is not authorized to view this page
if (workspaceUserInfo && !canPerformWorkspaceMemberActions) {
return <NotAuthorizedView section="settings" className="h-auto" />;
}

return (
<SettingsContentWrapper size="lg">
<SettingsContentWrapper width="lg" height="lg">
<PageHead title={pageTitle} />
<SendWorkspaceInvitationModal
isOpen={inviteModal}
Expand All @@ -132,7 +119,7 @@ function WorkspaceMembersSettingsPage({ params }: Route.ComponentProps) {
</h4>
<div className="flex items-center gap-2">
<div className="flex items-center gap-1.5 rounded-md border border-custom-border-200 bg-custom-background-100 px-2.5 py-1.5">
<Search className="h-3.5 w-3.5 text-custom-text-400" />
<SearchIcon className="h-3.5 w-3.5 text-custom-text-400" />
<input
className="w-full max-w-[234px] border-none bg-transparent text-sm outline-none placeholder:text-custom-text-400"
placeholder={`${t("search")}...`}
Expand All @@ -149,7 +136,8 @@ function WorkspaceMembersSettingsPage({ params }: Route.ComponentProps) {
{canPerformWorkspaceAdminActions && (
<Button
variant="primary"
size="sm"
width="sm"
height="sm"
onClick={() => setInviteModal(true)}
data-ph-element={MEMBER_TRACKER_ELEMENTS.HEADER_ADD_BUTTON}
>
Expand All @@ -164,5 +152,4 @@ function WorkspaceMembersSettingsPage({ params }: Route.ComponentProps) {
</SettingsContentWrapper>
);
}

export default observer(WorkspaceMembersSettingsPage);
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { observer } from "mobx-react";
import { AlertOctagon, BarChart4, CircleDashed, Folder, Microscope, Search } from "lucide-react";
import { AlertOctagon, BarChart4, CircleDashed, Folder, Microscope } from "lucide-react";
// plane imports
import { MARKETING_PRICING_PAGE_LINK } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { getButtonStyling } from "@plane/propel/button";
import { SearchIcon } from "@plane/propel/icons";
import { ContentWrapper } from "@plane/ui";
import { cn } from "@plane/utils";
// assets
Expand All @@ -17,7 +18,6 @@ import ctaR2Light from "@/app/assets/workspace-active-cycles/cta-r-2-light.webp?
import { ProIcon } from "@/components/common/pro-icon";
// hooks
import { useUser } from "@/hooks/store/user";

export const WORKSPACE_ACTIVE_CYCLES_DETAILS = [
{
key: "10000_feet_view",
Expand Down Expand Up @@ -50,7 +50,7 @@ export const WORKSPACE_ACTIVE_CYCLES_DETAILS = [
key: "zoom_into_cycles_that_need_attention",
title: "Zoom into cycles that need attention. ",
description: "Investigate the state of any cycle that doesn’t conform to expectations in one click.",
icon: Search,
icon: SearchIcon,
},
{
key: "stay_ahead_of_blockers",
Expand All @@ -60,16 +60,13 @@ export const WORKSPACE_ACTIVE_CYCLES_DETAILS = [
icon: Microscope,
},
];

export const WorkspaceActiveCyclesUpgrade = observer(function WorkspaceActiveCyclesUpgrade() {
const { t } = useTranslation();
// store hooks
const {
userProfile: { data: userProfile },
} = useUser();

const isDarkMode = userProfile?.theme.theme === "dark";

return (
<ContentWrapper className="gap-10">
<div
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import { Command } from "cmdk";
import { Search } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
// components
import { SearchIcon } from "@plane/propel/icons";
import type { TPowerKContext } from "@/components/power-k/core/types";
// plane web imports
import { PowerKModalCommandItem } from "@/components/power-k/ui/modal/command-item";

export type TPowerKModalNoSearchResultsCommandProps = {
context: TPowerKContext;
searchTerm: string;
updateSearchTerm: (value: string) => void;
};

export function PowerKModalNoSearchResultsCommand(props: TPowerKModalNoSearchResultsCommandProps) {
const { updateSearchTerm } = props;
// translation
const { t } = useTranslation();

return (
<Command.Group>
<PowerKModalCommandItem
icon={Search}
icon={SearchIcon}
value="no-results"
label={
<p className="flex items-center gap-2">
Expand Down
Loading
Loading