Skip to content

Commit 9dbff6b

Browse files
Merge branch 'preview' of github.com:makeplane/plane into chore-attachment-icon-revamp
2 parents f477fc7 + 68fd246 commit 9dbff6b

File tree

73 files changed

+5261
-746
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+5261
-746
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,5 @@ dev-editor
102102
storybook-static
103103

104104
CLAUDE.md
105+
106+
temp/

apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(list)/page.tsx

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useParams } from "next/navigation";
66
// plane imports
77
import { EUserPermissionsLevel, CYCLE_TRACKER_ELEMENTS } from "@plane/constants";
88
import { useTranslation } from "@plane/i18n";
9+
import { EmptyStateDetailed } from "@plane/propel/empty-state";
910
import type { TCycleFilters } from "@plane/types";
1011
import { EUserProjectRoles } from "@plane/types";
1112
// components
@@ -15,7 +16,6 @@ import { PageHead } from "@/components/core/page-title";
1516
import { CycleAppliedFiltersList } from "@/components/cycles/applied-filters";
1617
import { CyclesView } from "@/components/cycles/cycles-view";
1718
import { CycleCreateUpdateModal } from "@/components/cycles/modal";
18-
import { ComicBoxButton } from "@/components/empty-state/comic-box-button";
1919
import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
2020
import { CycleModuleListLayoutLoader } from "@/components/ui/loader/cycle-module-list-loader";
2121
// hooks
@@ -96,22 +96,19 @@ const ProjectCyclesPage = observer(() => {
9696
/>
9797
{totalCycles === 0 ? (
9898
<div className="h-full place-items-center">
99-
<DetailedEmptyState
100-
title={t("project_cycles.empty_state.general.title")}
101-
description={t("project_cycles.empty_state.general.description")}
102-
assetPath={resolvedPath}
103-
customPrimaryButton={
104-
<ComicBoxButton
105-
label={t("project_cycles.empty_state.general.primary_button.text")}
106-
title={t("project_cycles.empty_state.general.primary_button.comic.title")}
107-
description={t("project_cycles.empty_state.general.primary_button.comic.description")}
108-
data-ph-element={CYCLE_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON}
109-
onClick={() => {
110-
setCreateModal(true);
111-
}}
112-
disabled={!hasMemberLevelPermission}
113-
/>
114-
}
99+
<EmptyStateDetailed
100+
assetKey="cycle"
101+
title={t("project.cycles.title")}
102+
description={t("project.cycles.description")}
103+
actions={[
104+
{
105+
label: t("project.cycles.cta_primary"),
106+
onClick: () => setCreateModal(true),
107+
variant: "primary",
108+
disabled: !hasMemberLevelPermission,
109+
"data-ph-element": CYCLE_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON,
110+
},
111+
]}
115112
/>
116113
</div>
117114
) : (

apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,17 @@ import useSWR from "swr";
77
import { PROFILE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
88
import { useTranslation } from "@plane/i18n";
99
// component
10+
import { EmptyStateCompact } from "@plane/propel/empty-state";
1011
import { APITokenService } from "@plane/services";
1112
import { CreateApiTokenModal } from "@/components/api-token/modal/create-token-modal";
1213
import { ApiTokenListItem } from "@/components/api-token/token-list-item";
1314
import { PageHead } from "@/components/core/page-title";
14-
import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
1515
import { SettingsHeading } from "@/components/settings/heading";
1616
import { APITokenSettingsLoader } from "@/components/ui/loader/settings/api-token";
1717
import { API_TOKENS_LIST } from "@/constants/fetch-keys";
1818
// store hooks
1919
import { captureClick } from "@/helpers/event-tracker.helper";
2020
import { useWorkspace } from "@/hooks/store/use-workspace";
21-
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
2221

2322
const apiTokenService = new APITokenService();
2423

@@ -30,8 +29,6 @@ const ApiTokensPage = observer(() => {
3029
const { t } = useTranslation();
3130
// store hooks
3231
const { currentWorkspace } = useWorkspace();
33-
// derived values
34-
const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/workspace-settings/api-tokens" });
3532

3633
const { data: tokens } = useSWR(API_TOKENS_LIST, () => apiTokenService.list());
3734

@@ -70,7 +67,7 @@ const ApiTokensPage = observer(() => {
7067
</div>
7168
</>
7269
) : (
73-
<div className="flex h-full w-full flex-col">
70+
<div className="flex h-full w-full flex-col py-">
7471
<SettingsHeading
7572
title={t("account_settings.api_tokens.heading")}
7673
description={t("account_settings.api_tokens.description")}
@@ -84,24 +81,26 @@ const ApiTokensPage = observer(() => {
8481
},
8582
}}
8683
/>
87-
<div className="h-full w-full flex items-center justify-center">
88-
<DetailedEmptyState
89-
title=""
90-
description=""
91-
assetPath={resolvedPath}
92-
className="w-full !p-0 justify-center mx-auto"
93-
size="md"
94-
primaryButton={{
95-
text: t("workspace_settings.settings.api_tokens.add_token"),
84+
85+
<EmptyStateCompact
86+
assetKey="token"
87+
assetClassName="size-20"
88+
title={t("settings.tokens.title")}
89+
description={t("settings.tokens.description")}
90+
actions={[
91+
{
92+
label: t("settings.tokens.cta_primary"),
9693
onClick: () => {
9794
captureClick({
9895
elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.EMPTY_STATE_ADD_PAT_BUTTON,
9996
});
10097
setIsCreateTokenModalOpen(true);
10198
},
102-
}}
103-
/>
104-
</div>
99+
},
100+
]}
101+
align="start"
102+
rootClassName="py-20"
103+
/>
105104
</div>
106105
)}
107106
</section>

apps/web/ce/store/issue/issue-details/activity.store.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,11 @@ export class IssueActivityStore implements IIssueActivityStore {
112112
comments.forEach((commentId) => {
113113
const comment = currentStore.comment.getCommentById(commentId);
114114
if (!comment) return;
115+
const commentTimestamp = comment.edited_at ?? comment.updated_at ?? comment.created_at;
115116
activityComments.push({
116117
id: comment.id,
117118
activity_type: EActivityFilterType.COMMENT,
118-
created_at: comment.created_at,
119+
created_at: commentTimestamp,
119120
});
120121
});
121122

apps/web/core/components/analytics/insight-table/data-table.tsx

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,16 @@ import {
1414
getFacetedRowModel,
1515
getFacetedUniqueValues,
1616
getFilteredRowModel,
17-
getPaginationRowModel,
1817
getSortedRowModel,
1918
useReactTable,
2019
} from "@tanstack/react-table";
2120
import { Search, X } from "lucide-react";
2221
// plane package imports
2322
import { useTranslation } from "@plane/i18n";
23+
import { EmptyStateCompact } from "@plane/propel/empty-state";
2424
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@plane/propel/table";
2525
import { cn } from "@plane/utils";
2626
// plane web components
27-
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
28-
import AnalyticsEmptyState from "../empty-state";
2927

3028
interface DataTableProps<TData, TValue> {
3129
columns: ColumnDef<TData, TValue>[];
@@ -42,7 +40,6 @@ export function DataTable<TData, TValue>({ columns, data, searchPlaceholder, act
4240
const { t } = useTranslation();
4341
const inputRef = React.useRef<HTMLInputElement>(null);
4442
const [isSearchOpen, setIsSearchOpen] = React.useState(false);
45-
const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-table" });
4643

4744
const table = useReactTable({
4845
data,
@@ -156,14 +153,12 @@ export function DataTable<TData, TValue>({ columns, data, searchPlaceholder, act
156153
) : (
157154
<TableRow>
158155
<TableCell colSpan={columns.length} className="p-0">
159-
<div className="flex h-[350px] w-full items-center justify-center border border-custom-border-100 ">
160-
<AnalyticsEmptyState
161-
title={t("workspace_analytics.empty_state.customized_insights.title")}
162-
description={t("workspace_analytics.empty_state.customized_insights.description")}
163-
className="border-0"
164-
assetPath={resolvedPath}
165-
/>
166-
</div>
156+
<EmptyStateCompact
157+
assetKey="unknown"
158+
assetClassName="size-20"
159+
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
160+
title={t("workspace.analytics_work_items.title")}
161+
/>
167162
</TableCell>
168163
</TableRow>
169164
)}

apps/web/core/components/analytics/overview/project-insights.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import { useParams } from "next/navigation";
44
import useSWR from "swr";
55
// plane package imports
66
import { useTranslation } from "@plane/i18n";
7+
import { EmptyStateCompact } from "@plane/propel/empty-state";
78
import type { TChartData } from "@plane/types";
89
// hooks
910
import { useAnalytics } from "@/hooks/store/use-analytics";
1011
// services
11-
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
1212
import { AnalyticsService } from "@/services/analytics.service";
1313
// plane web components
1414
import AnalyticsSectionWrapper from "../analytics-section-wrapper";
15-
import AnalyticsEmptyState from "../empty-state";
1615
import { ProjectInsightsLoader } from "../loaders";
1716

1817
const RadarChart = dynamic(() =>
@@ -29,7 +28,6 @@ const ProjectInsights = observer(() => {
2928
const workspaceSlug = params.workspaceSlug.toString();
3029
const { selectedDuration, selectedDurationLabel, selectedProjects, selectedCycle, selectedModule, isPeekView } =
3130
useAnalytics();
32-
const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-chart-radar" });
3331

3432
const { data: projectInsightsData, isLoading: isLoadingProjectInsight } = useSWR(
3533
`radar-chart-project-insights-${workspaceSlug}-${selectedDuration}-${selectedProjects}-${selectedCycle}-${selectedModule}-${isPeekView}`,
@@ -56,11 +54,11 @@ const ProjectInsights = observer(() => {
5654
{isLoadingProjectInsight ? (
5755
<ProjectInsightsLoader />
5856
) : projectInsightsData && projectInsightsData?.length == 0 ? (
59-
<AnalyticsEmptyState
60-
title={t("workspace_analytics.empty_state.project_insights.title")}
61-
description={t("workspace_analytics.empty_state.project_insights.description")}
62-
className="h-[300px]"
63-
assetPath={resolvedPath}
57+
<EmptyStateCompact
58+
assetKey="unknown"
59+
assetClassName="size-20"
60+
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
61+
title={t("workspace.analytics_work_items.title")}
6462
/>
6563
) : (
6664
<div className="gap-8 lg:flex">

apps/web/core/components/analytics/work-items/created-vs-resolved.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@ import useSWR from "swr";
55
// plane package imports
66
import { useTranslation } from "@plane/i18n";
77
import { AreaChart } from "@plane/propel/charts/area-chart";
8+
import { EmptyStateCompact } from "@plane/propel/empty-state";
89
import type { IChartResponse, TChartData } from "@plane/types";
910
import { renderFormattedDate } from "@plane/utils";
1011
// hooks
1112
import { useAnalytics } from "@/hooks/store/use-analytics";
1213
// services
13-
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
1414
import { AnalyticsService } from "@/services/analytics.service";
1515
// plane web components
1616
import AnalyticsSectionWrapper from "../analytics-section-wrapper";
17-
import AnalyticsEmptyState from "../empty-state";
1817
import { ChartLoader } from "../loaders";
1918

2019
const analyticsService = new AnalyticsService();
@@ -31,7 +30,6 @@ const CreatedVsResolved = observer(() => {
3130
const params = useParams();
3231
const { t } = useTranslation();
3332
const workspaceSlug = params.workspaceSlug.toString();
34-
const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-chart-area" });
3533
const { data: createdVsResolvedData, isLoading: isCreatedVsResolvedLoading } = useSWR(
3634
`created-vs-resolved-${workspaceSlug}-${selectedDuration}-${selectedProjects}-${selectedCycle}-${selectedModule}-${isPeekView}-${isEpic}`,
3735
() =>
@@ -121,11 +119,11 @@ const CreatedVsResolved = observer(() => {
121119
}}
122120
/>
123121
) : (
124-
<AnalyticsEmptyState
125-
title={t("workspace_analytics.empty_state.created_vs_resolved.title")}
126-
description={t("workspace_analytics.empty_state.created_vs_resolved.description")}
127-
className="h-[350px]"
128-
assetPath={resolvedPath}
122+
<EmptyStateCompact
123+
assetKey="unknown"
124+
assetClassName="size-20"
125+
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
126+
title={t("workspace.analytics_work_items.title")}
129127
/>
130128
)}
131129
</AnalyticsSectionWrapper>

apps/web/core/components/analytics/work-items/priority-chart.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES, CHART_COLOR_PALETTES,
1111
import { useTranslation } from "@plane/i18n";
1212
import { Button } from "@plane/propel/button";
1313
import { BarChart } from "@plane/propel/charts/bar-chart";
14+
import { EmptyStateCompact } from "@plane/propel/empty-state";
1415
import type { TBarItem, TChart, TChartDatum, ChartXAxisProperty, ChartYAxisMetric } from "@plane/types";
1516
// plane web components
1617
import { generateExtendedColors, parseChartData } from "@/components/chart/utils";
1718
// hooks
1819
import { useAnalytics } from "@/hooks/store/use-analytics";
1920
import { useProjectState } from "@/hooks/store/use-project-state";
20-
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
2121
import { AnalyticsService } from "@/services/analytics.service";
22-
import AnalyticsEmptyState from "../empty-state";
2322
import { exportCSV } from "../export";
2423
import { DataTable } from "../insight-table/data-table";
2524
import { ChartLoader } from "../loaders";
@@ -46,7 +45,6 @@ const analyticsService = new AnalyticsService();
4645
const PriorityChart = observer((props: Props) => {
4746
const { x_axis, y_axis, group_by } = props;
4847
const { t } = useTranslation();
49-
const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-chart-bar" });
5048
// store hooks
5149
const { selectedDuration, selectedProjects, selectedCycle, selectedModule, isPeekView, isEpic } = useAnalytics();
5250
const { workspaceStates } = useProjectState();
@@ -232,11 +230,11 @@ const PriorityChart = observer((props: Props) => {
232230
/>
233231
</>
234232
) : (
235-
<AnalyticsEmptyState
236-
title={t("workspace_analytics.empty_state.customized_insights.title")}
237-
description={t("workspace_analytics.empty_state.customized_insights.description")}
238-
className="h-[350px]"
239-
assetPath={resolvedPath}
233+
<EmptyStateCompact
234+
assetKey="unknown"
235+
assetClassName="size-20"
236+
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
237+
title={t("workspace.analytics_work_items.title")}
240238
/>
241239
)}
242240
</div>

apps/web/core/components/estimates/root.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import useSWR from "swr";
55
// plane imports
66
import { useTranslation } from "@plane/i18n";
77
// hooks
8+
import { EmptyStateCompact } from "@plane/propel/empty-state";
89
import { useProjectEstimates } from "@/hooks/store/estimates";
910
import { useProject } from "@/hooks/store/use-project";
1011
// plane web components
@@ -13,7 +14,6 @@ import { UpdateEstimateModal } from "@/plane-web/components/estimates";
1314
import { SettingsHeading } from "../settings/heading";
1415
import { CreateEstimateModal } from "./create/modal";
1516
import { DeleteEstimateModal } from "./delete/modal";
16-
import { EstimateEmptyScreen } from "./empty-screen";
1717
import { EstimateDisableSwitch } from "./estimate-disable-switch";
1818
import { EstimateList } from "./estimate-list";
1919
import { EstimateLoaderScreen } from "./loader-screen";
@@ -76,7 +76,20 @@ export const EstimateRoot: FC<TEstimateRoot> = observer((props) => {
7676
/>
7777
</div>
7878
) : (
79-
<EstimateEmptyScreen onButtonClick={() => setIsEstimateCreateModalOpen(true)} />
79+
<EmptyStateCompact
80+
assetKey="estimate"
81+
assetClassName="size-20"
82+
title={t("settings.estimates.title")}
83+
description={t("settings.estimates.description")}
84+
actions={[
85+
{
86+
label: t("settings.estimates.cta_primary"),
87+
onClick: () => setIsEstimateCreateModalOpen(true),
88+
},
89+
]}
90+
align="start"
91+
rootClassName="py-20"
92+
/>
8093
)}
8194

8295
{/* archived estimates section */}
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
import { Link2 } from "lucide-react";
21
import { useTranslation } from "@plane/i18n";
2+
import { EmptyStateCompact } from "@plane/propel/empty-state";
33

44
export const LinksEmptyState = () => {
55
const { t } = useTranslation();
66
return (
7-
<div className="min-h-[110px] flex w-full justify-center py-6 bg-custom-border-100 rounded">
8-
<div className="m-auto flex gap-2">
9-
<Link2 size={30} className="text-custom-text-400/40 -rotate-45" />
10-
<div className="text-custom-text-400 text-sm text-center my-auto">{t("home.quick_links.empty")}</div>
11-
</div>
7+
<div className="flex items-center justify-center py-10 bg-custom-background-90 w-full">
8+
<EmptyStateCompact
9+
assetKey="link"
10+
assetClassName="w-20 h-20"
11+
title={t("workspace.home_widget_quick_links.title")}
12+
/>
1213
</div>
1314
);
1415
};

0 commit comments

Comments
 (0)