Skip to content
Merged
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
75 changes: 75 additions & 0 deletions packages/i18n/src/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -1484,13 +1484,88 @@
},

"project_cycles": {
"add_cycle": "Add cycle",
"more_details": "More details",
"cycle": "Cycle",
"update_cycle": "Update cycle",
"create_cycle": "Create cycle",
"no_matching_cycles": "No matching cycles",
"remove_filters_to_see_all_cycles": "Remove the filters to see all cycles",
"remove_search_criteria_to_see_all_cycles": "Remove the search criteria to see all cycles",
"only_completed_cycles_can_be_archived": "Only completed cycles can be archived",
"active_cycle": {
"label" :"Active cycle",
"progress": "Progress",
"chart": "Burndown chart",
"priority_issue": "Priority issues",
"assignees": "Assignees",
"issue_burndown": "Issue burndown",
"ideal": "Ideal",
"current": "Current",
"labels": "Labels"
},
"upcoming_cycle": {
"label": "Upcoming cycle"
},
"completed_cycle": {
"label": "Completed cycle"
},
"status": {
"days_left": "Days left",
"completed": "Completed",
"yet_to_start": "Yet to start",
"in_progress": "In progress",
"draft": "Draft"
},
"action": {
"restore": {
"title": "Restore cycle",
"success": {
"title": "Cycle restored",
"description": "The cycle has been restored."
},
"failed": {
"title": "Cycle restore failed",
"description": "The cycle could not be restored. Please try again."
}
},
"favorite": {
"loading": "Adding cycle to favorites...",
"success": {
"description": "Cycle added to favorites.",
"title": "Success!"
},
"failed": {
"description": "Couldn't add the cycle to favorites. Please try again.",
"title": "Error!"
}
},
"unfavorite": {
"loading": "Removing cycle from favorites...",
"success": {
"description": "Cycle removed from favorites.",
"title": "Success!"
},
"failed": {
"description": "Couldn't remove the cycle from favorites. Please try again.",
"title": "Error!"
}
},
"update": {
"loading": "Updating cycle...",
"success": {
"description": "Cycle updated successfully.",
"title": "Success!"
},
"failed": {
"description": "Error updating the cycle. Please try again.",
"title": "Error!"
},
"error": {
"already_exists": "You already have a cycle on the given dates, if you want to create a draft cycle, you can do that by removing both the dates."
}
}
},
"empty_state": {
"general": {
"title": "Group and timebox your work in Cycles.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FC } from "react";
import { observer } from "mobx-react";
// ui
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Breadcrumbs, Button, ContrastIcon, Header } from "@plane/ui";
// components
import { BreadcrumbLink } from "@/components/common";
Expand All @@ -23,6 +24,7 @@ export const CyclesListHeader: FC = observer(() => {
const { setTrackElement } = useEventTracker();
const { allowPermissions } = useUserPermissions();
const { currentProjectDetails, loader } = useProject();
const { t } = useTranslation();

const canUserCreateCycle = allowPermissions(
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
Expand All @@ -36,7 +38,12 @@ export const CyclesListHeader: FC = observer(() => {
<ProjectBreadcrumb />
<Breadcrumbs.BreadcrumbItem
type="text"
link={<BreadcrumbLink label="Cycles" icon={<ContrastIcon className="h-4 w-4 text-custom-text-300" />} />}
link={
<BreadcrumbLink
label={t("cycle.label", { count: 2 })}
icon={<ContrastIcon className="h-4 w-4 text-custom-text-300" />}
/>
}
/>
</Breadcrumbs>
</Header.LeftItem>
Expand All @@ -51,7 +58,8 @@ export const CyclesListHeader: FC = observer(() => {
toggleCreateCycleModal(true);
}}
>
<div className="hidden sm:block">Add</div> Cycle
<div className="hidden sm:block">{t("add")}</div>
<div className="sm:hidden block">{t("add_cycle")}</div>
</Button>
</Header.RightItem>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const ProjectCyclesPage = observer(() => {
// derived values
const totalCycles = currentProjectCycleIds?.length ?? 0;
const project = projectId ? getProjectById(projectId?.toString()) : undefined;
const pageTitle = project?.name ? `${project?.name} - Cycles` : undefined;
const pageTitle = project?.name ? `${project?.name} - ${t("cycles.label", { count: 2 })}` : undefined;
const hasAdminLevelPermission = allowPermissions([EUserProjectRoles.ADMIN], EUserPermissionsLevel.PROJECT);
const hasMemberLevelPermission = allowPermissions(
[EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER],
Expand Down
2 changes: 1 addition & 1 deletion web/ce/components/cycles/active-cycle/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
{({ open }) => (
<>
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 cursor-pointer">
<CycleListGroupHeader title="Active cycle" type="current" isExpanded={open} />
<CycleListGroupHeader title={t("project_cycles.active_cycle.label")} type="current" isExpanded={open} />
</Disclosure.Button>
<Disclosure.Panel>{ActiveCyclesComponent}</Disclosure.Panel>
</>
Expand Down
8 changes: 5 additions & 3 deletions web/ce/components/cycles/analytics-sidebar/base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { FC, Fragment } from "react";
import { observer } from "mobx-react";
// plane ui
import { useTranslation } from "@plane/i18n";
import { TCycleEstimateType } from "@plane/types";
import { Loader } from "@plane/ui";
// components
Expand All @@ -23,6 +24,7 @@ export const SidebarChart: FC<ProgressChartProps> = observer((props) => {
// hooks
const { getEstimateTypeByCycleId, getCycleById, fetchCycleDetails, fetchArchivedCycleDetails, setEstimateType } =
useCycle();
const { t } = useTranslation();

// derived data
const cycleDetails = validateCycleSnapshot(getCycleById(cycleId));
Expand Down Expand Up @@ -66,11 +68,11 @@ export const SidebarChart: FC<ProgressChartProps> = observer((props) => {
<div className="relative flex items-center gap-2">
<div className="flex items-center justify-center gap-1 text-xs">
<span className="h-2.5 w-2.5 rounded-full bg-[#A9BBD0]" />
<span>Ideal</span>
<span>{t("ideal")}</span>
</div>
<div className="flex items-center justify-center gap-1 text-xs">
<span className="h-2.5 w-2.5 rounded-full bg-[#4C8FFF]" />
<span>Current</span>
<span>{t("current")}</span>
</div>
</div>
{cycleStartDate && cycleEndDate && completionChartDistributionData ? (
Expand All @@ -80,7 +82,7 @@ export const SidebarChart: FC<ProgressChartProps> = observer((props) => {
startDate={cycleStartDate}
endDate={cycleEndDate}
totalIssues={estimateType === "points" ? totalEstimatePoints : totalIssues}
plotTitle={estimateType === "points" ? "points" : "work items"}
plotTitle={estimateType === "points" ? t("points") : t("work_items")}
/>
</Fragment>
) : (
Expand Down
8 changes: 4 additions & 4 deletions web/core/components/cycles/active-cycle/cycle-stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
)
}
>
Priority work items
{t("project_cycles.active_cycle.priority_issue")}
</Tab>
<Tab
className={({ selected }) =>
Expand All @@ -139,7 +139,7 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
)
}
>
Assignees
{t("project_cycles.active_cycle.assignees")}
</Tab>
<Tab
className={({ selected }) =>
Expand All @@ -152,7 +152,7 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
)
}
>
Labels
{t("project_cycles.active_cycle.labels")}
</Tab>
</Tab.List>

Expand Down Expand Up @@ -289,7 +289,7 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
<div className="h-5 w-5 rounded-full border-2 border-custom-border-200 bg-custom-background-80">
<img src="/user.png" height="100%" width="100%" className="rounded-full" alt="User" />
</div>
<span>No assignee</span>
<span>{t("no_assignee")}</span>
</div>
}
completed={assignee.completed_issues}
Expand Down
8 changes: 5 additions & 3 deletions web/core/components/cycles/active-cycle/productivity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export const ActiveCycleProductivity: FC<ActiveCycleProductivityProps> = observe
<div className="flex flex-col min-h-[17rem] gap-5 px-3.5 py-4 bg-custom-background-100 border border-custom-border-200 rounded-lg">
<div className="relative flex items-center justify-between gap-4">
<Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle?.id}`}>
<h3 className="text-base text-custom-text-300 font-semibold">Issue burndown</h3>
<h3 className="text-base text-custom-text-300 font-semibold">
{t("project_cycles.active_cycle.issue_burndown")}
</h3>
</Link>
<EstimateTypeDropdown value={estimateType} onChange={onChange} cycleId={cycle.id} projectId={projectId} />
</div>
Expand All @@ -56,11 +58,11 @@ export const ActiveCycleProductivity: FC<ActiveCycleProductivityProps> = observe
<div className="flex items-center gap-3 text-custom-text-300">
<div className="flex items-center justify-center gap-1">
<span className="h-2 w-2 rounded-full bg-[#A9BBD0]" />
<span>Ideal</span>
<span>{t("project_cycles.active_cycle.ideal")}</span>
</div>
<div className="flex items-center justify-center gap-1">
<span className="h-2 w-2 rounded-full bg-[#4C8FFF]" />
<span>Current</span>
<span>{t("project_cycles.active_cycle.current")}</span>
</div>
</div>
{estimateType === "points" ? (
Expand Down
2 changes: 1 addition & 1 deletion web/core/components/cycles/active-cycle/progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const ActiveCycleProgress: FC<ActiveCycleProgressProps> = observer((props
<div className="flex flex-col min-h-[17rem] gap-5 py-4 px-3.5 bg-custom-background-100 border border-custom-border-200 rounded-lg">
<div className="flex flex-col gap-3">
<div className="flex items-center justify-between gap-4">
<h3 className="text-base text-custom-text-300 font-semibold">Progress</h3>
<h3 className="text-base text-custom-text-300 font-semibold">{t("project_cycles.active_cycle.progress")}</h3>
{cycle.total_issues > 0 && (
<span className="flex gap-1 text-sm text-custom-text-400 font-medium whitespace-nowrap rounded-sm px-3 py-1 ">
{`${cycle.completed_issues + cycle.cancelled_issues}/${cycle.total_issues - cycle.cancelled_issues} ${
Expand Down
10 changes: 8 additions & 2 deletions web/core/components/cycles/analytics-sidebar/issue-progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useSearchParams } from "next/navigation";
import { ChevronUp, ChevronDown } from "lucide-react";
import { Disclosure, Transition } from "@headlessui/react";
import { EIssueFilterType, EIssuesStoreType } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { ICycle, IIssueFilterOptions, TCyclePlotType, TProgressSnapshot } from "@plane/types";
// components
import { CycleProgressStats } from "@/components/cycles";
Expand Down Expand Up @@ -63,6 +64,7 @@ export const CycleAnalyticsProgress: FC<TCycleAnalyticsProgress> = observer((pro
const {
issuesFilter: { issueFilters, updateFilters },
} = useIssues(EIssuesStoreType.CYCLE);
const { t } = useTranslation();

// derived values
const cycleDetails = validateCycleSnapshot(getCycleById(cycleId));
Expand Down Expand Up @@ -138,7 +140,9 @@ export const CycleAnalyticsProgress: FC<TCycleAnalyticsProgress> = observer((pro
{isCycleDateValid ? (
<div className="relative w-full flex justify-between items-center gap-2">
<Disclosure.Button className="relative flex items-center gap-2 w-full">
<div className="font-medium text-custom-text-200 text-sm">Progress</div>
<div className="font-medium text-custom-text-200 text-sm">
{t("project_cycles.active_cycle.progress")}
</div>
</Disclosure.Button>
<Disclosure.Button className="ml-auto">
{open ? (
Expand All @@ -150,7 +154,9 @@ export const CycleAnalyticsProgress: FC<TCycleAnalyticsProgress> = observer((pro
</div>
) : (
<div className="relative w-full flex justify-between items-center gap-2">
<div className="font-medium text-custom-text-200 text-sm">Progress</div>
<div className="font-medium text-custom-text-200 text-sm">
{t("project_cycles.active_cycle.progress")}
</div>
</div>
)}

Expand Down
22 changes: 13 additions & 9 deletions web/core/components/cycles/analytics-sidebar/progress-stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FC } from "react";
import { observer } from "mobx-react";
import Image from "next/image";
import { Tab } from "@headlessui/react";
import { useTranslation } from "@plane/i18n";
import {
IIssueFilterOptions,
IIssueFilters,
Expand Down Expand Up @@ -73,6 +74,7 @@ type TStateStatComponent = {

export const AssigneeStatComponent = observer((props: TAssigneeStatComponent) => {
const { distribution, isEditable, filters, handleFiltersUpdate } = props;
const { t } = useTranslation();
return (
<div>
{distribution && distribution.length > 0 ? (
Expand Down Expand Up @@ -104,7 +106,7 @@ export const AssigneeStatComponent = observer((props: TAssigneeStatComponent) =>
<div className="h-4 w-4 rounded-full border-2 border-custom-border-200 bg-custom-background-80">
<img src="/user.png" height="100%" width="100%" className="rounded-full" alt="User" />
</div>
<span>No assignee</span>
<span>{t("no_assignee")}</span>
</div>
}
completed={assignee?.completed ?? 0}
Expand All @@ -117,7 +119,7 @@ export const AssigneeStatComponent = observer((props: TAssigneeStatComponent) =>
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-custom-background-80">
<Image src={emptyMembers} className="h-12 w-12" alt="empty members" />
</div>
<h6 className="text-base text-custom-text-300">No assignees yet</h6>
<h6 className="text-base text-custom-text-300">{t("no_assignee")}</h6>
</div>
)}
</div>
Expand All @@ -126,6 +128,7 @@ export const AssigneeStatComponent = observer((props: TAssigneeStatComponent) =>

export const LabelStatComponent = observer((props: TLabelStatComponent) => {
const { distribution, isEditable, filters, handleFiltersUpdate } = props;
const { t } = useTranslation();
return (
<div>
{distribution && distribution.length > 0 ? (
Expand All @@ -142,7 +145,7 @@ export const LabelStatComponent = observer((props: TLabelStatComponent) => {
backgroundColor: label.color ?? "transparent",
}}
/>
<span className="text-xs">{label.title ?? "No labels"}</span>
<span className="text-xs">{label.title ?? t("no_labels_yet")}</span>
</div>
}
completed={label.completed}
Expand All @@ -165,7 +168,7 @@ export const LabelStatComponent = observer((props: TLabelStatComponent) => {
backgroundColor: label.color ?? "transparent",
}}
/>
<span className="text-xs">{label.title ?? "No labels"}</span>
<span className="text-xs">{label.title ?? t("no_labels_yet")}</span>
</div>
}
completed={label.completed}
Expand All @@ -179,7 +182,7 @@ export const LabelStatComponent = observer((props: TLabelStatComponent) => {
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-custom-background-80">
<Image src={emptyLabel} className="h-12 w-12" alt="empty label" />
</div>
<h6 className="text-base text-custom-text-300">No labels yet</h6>
<h6 className="text-base text-custom-text-300">{t("no_labels_yet")}</h6>
</div>
)}
</div>
Expand Down Expand Up @@ -222,15 +225,15 @@ export const StateStatComponent = observer((props: TStateStatComponent) => {
const progressStats = [
{
key: "stat-states",
title: "States",
i18n_title: "common.states",
},
{
key: "stat-assignees",
title: "Assignees",
i18n_title: "common.assignees",
},
{
key: "stat-labels",
title: "Labels",
i18n_title: "common.labels",
},
];

Expand Down Expand Up @@ -267,6 +270,7 @@ export const CycleProgressStats: FC<TCycleProgressStats> = observer((props) => {
`cycle-analytics-tab-${cycleId}`,
"stat-assignees"
);
const { t } = useTranslation();
// derived values
const currentTabIndex = (tab: string): number => progressStats.findIndex((stat) => stat.key === tab);

Expand Down Expand Up @@ -337,7 +341,7 @@ export const CycleProgressStats: FC<TCycleProgressStats> = observer((props) => {
key={stat.key}
onClick={() => setCycleTab(stat.key)}
>
{stat.title}
{t(stat.i18n_title)}
</Tab>
))}
</Tab.List>
Expand Down
Loading
Loading