Skip to content

Commit f0bc2bd

Browse files
[WEB-5600] chore: project identifier char limit updated and table layout enhancements (#8263)
1 parent 7659997 commit f0bc2bd

File tree

23 files changed

+116
-109
lines changed

23 files changed

+116
-109
lines changed

apps/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,6 @@ const IssueRowDetails = observer(function IssueRowDetails(props: IssueRowDetails
239239

240240
const canSelectIssues = !disableUserActions && !selectionHelpers.isSelectionDisabled;
241241

242-
//TODO: add better logic. This is to have a min width for ID/Key based on the length of project identifier
243-
const keyMinWidth = displayProperties?.key
244-
? (getProjectIdentifierById(issueDetail.project_id)?.length ?? 0 + 5) * 7
245-
: 0;
246-
247242
const workItemLink = generateWorkItemLink({
248243
workspaceSlug: workspaceSlug?.toString(),
249244
projectId: issueDetail?.project_id,
@@ -255,11 +250,12 @@ const IssueRowDetails = observer(function IssueRowDetails(props: IssueRowDetails
255250

256251
return (
257252
<>
253+
{/* Single sticky column containing both identifier and workitem */}
258254
<td
259255
id={`issue-${issueId}`}
260256
ref={cellRef}
261257
tabIndex={0}
262-
className="relative md:sticky left-0 z-10 group/list-block bg-custom-background-100 min-w-60 max-w-[30vw]"
258+
className="relative md:sticky left-0 z-10 group/list-block bg-custom-background-100"
263259
>
264260
<ControlLink
265261
href={workItemLink}
@@ -278,7 +274,29 @@ const IssueRowDetails = observer(function IssueRowDetails(props: IssueRowDetails
278274
}
279275
)}
280276
>
281-
<div className="flex items-center gap-0.5 min-w-min py-2">
277+
{/* Identifier section - conditionally rendered */}
278+
{displayProperties?.key && (
279+
<div className="flex-shrink-0 flex items-center h-full min-w-24">
280+
<div className="relative flex cursor-pointer items-center text-xs hover:text-custom-text-100">
281+
{issueDetail.project_id && (
282+
<IssueIdentifier
283+
issueId={issueDetail.id}
284+
projectId={issueDetail.project_id}
285+
textContainerClassName="text-sm md:text-xs text-custom-text-300"
286+
displayProperties={displayProperties}
287+
/>
288+
)}
289+
</div>
290+
</div>
291+
)}
292+
293+
{/* Workitem section */}
294+
<div
295+
className={cn("flex items-center gap-0.5 py-2 flex-grow", {
296+
"min-w-[360px]": !displayProperties?.key,
297+
"min-w-60": displayProperties?.key,
298+
})}
299+
>
282300
{/* select checkbox */}
283301
{projectId && canSelectIssues && (
284302
<Tooltip
@@ -311,21 +329,6 @@ const IssueRowDetails = observer(function IssueRowDetails(props: IssueRowDetails
311329
{/* sub issues indentation */}
312330
{nestingLevel !== 0 && <div style={{ width: subIssueIndentation }} />}
313331

314-
{(displayProperties?.key || displayProperties?.issue_type) && (
315-
<div className="relative flex cursor-pointer items-center text-center text-xs hover:text-custom-text-100">
316-
<p className={`flex font-medium leading-7`} style={{ minWidth: `${keyMinWidth}px` }}>
317-
{issueDetail.project_id && (
318-
<IssueIdentifier
319-
issueId={issueDetail.id}
320-
projectId={issueDetail.project_id}
321-
textContainerClassName="text-sm md:text-xs text-custom-text-300"
322-
displayProperties={displayProperties}
323-
/>
324-
)}
325-
</p>
326-
</div>
327-
)}
328-
329332
{/* sub-issues chevron */}
330333
<div className="grid place-items-center size-4">
331334
{subIssuesCount > 0 && !isEpic && (
@@ -343,31 +346,31 @@ const IssueRowDetails = observer(function IssueRowDetails(props: IssueRowDetails
343346
</button>
344347
)}
345348
</div>
346-
</div>
347349

348-
<div className="flex items-center gap-2 justify-between h-full w-full truncate my-auto">
349-
<div className="w-full line-clamp-1 text-sm text-custom-text-100">
350-
<div className="w-full overflow-hidden">
351-
<Tooltip tooltipContent={issueDetail.name} isMobile={isMobile}>
352-
<div
353-
className="h-full w-full cursor-pointer truncate pr-4 text-left text-[0.825rem] text-custom-text-100 focus:outline-none"
354-
tabIndex={-1}
355-
>
356-
{issueDetail.name}
357-
</div>
358-
</Tooltip>
350+
<div className="flex items-center gap-2 justify-between h-full w-full truncate my-auto">
351+
<div className="w-full line-clamp-1 text-sm text-custom-text-100">
352+
<div className="w-full overflow-hidden">
353+
<Tooltip tooltipContent={issueDetail.name} isMobile={isMobile}>
354+
<div
355+
className="h-full w-full cursor-pointer truncate pr-4 text-left text-[0.825rem] text-custom-text-100 focus:outline-none"
356+
tabIndex={-1}
357+
>
358+
{issueDetail.name}
359+
</div>
360+
</Tooltip>
361+
</div>
362+
</div>
363+
<div
364+
className={`opacity-0 group-hover:opacity-100 transition-opacity ${isMenuActive ? "!opacity-100" : ""}`}
365+
onClick={(e) => e.stopPropagation()}
366+
>
367+
{quickActions({
368+
issue: issueDetail,
369+
parentRef: cellRef,
370+
customActionButton,
371+
portalElement: portalElement.current,
372+
})}
359373
</div>
360-
</div>
361-
<div
362-
className={`hidden group-hover:block ${isMenuActive ? "!block" : ""}`}
363-
onClick={(e) => e.stopPropagation()}
364-
>
365-
{quickActions({
366-
issue: issueDetail,
367-
parentRef: cellRef,
368-
customActionButton,
369-
portalElement: portalElement.current,
370-
})}
371374
</div>
372375
</div>
373376
</Row>

apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header.tsx

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { SPREADSHEET_SELECT_GROUP } from "@plane/constants";
55
// ui
66
import type { IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types";
77
// components
8-
import { Row } from "@plane/ui";
98
import { cn } from "@plane/utils";
109
import { MultipleSelectGroupAction } from "@/components/core/multiple-select";
1110
// hooks
@@ -44,27 +43,31 @@ export const SpreadsheetHeader = observer(function SpreadsheetHeader(props: Prop
4443
return (
4544
<thead className="sticky top-0 left-0 z-[12] border-b-[0.5px] border-custom-border-100">
4645
<tr>
46+
{/* Single header column containing both identifier and workitem */}
4747
<th
48-
className="group/list-header sticky min-w-60 left-0 z-[15] h-11 flex items-center gap-1 bg-custom-background-90 text-sm font-medium before:absolute before:h-full before:right-0 before:border-custom-border-100"
48+
className="group/list-header md:sticky min-w-60 left-0 z-[15] h-11 bg-custom-background-90 text-sm font-medium border-r-[0.5px] border-custom-border-100"
4949
tabIndex={-1}
5050
>
51-
<Row>
52-
{canSelectIssues && (
53-
<div className="flex-shrink-0 flex items-center w-3.5 mr-1 absolute left-1 py-[11px]">
54-
<MultipleSelectGroupAction
55-
className={cn(
56-
"size-3.5 opacity-0 pointer-events-none group-hover/list-header:opacity-100 group-hover/list-header:pointer-events-auto !outline-none",
57-
{
58-
"opacity-100 pointer-events-auto": !isGroupSelectionEmpty,
59-
}
60-
)}
61-
groupID={SPREADSHEET_SELECT_GROUP}
62-
selectionHelpers={selectionHelpers}
63-
/>
64-
</div>
65-
)}
66-
<span className="flex h-full w-full flex-grow items-center py-2.5">{`${isEpic ? "Epics" : "Work items"}`}</span>
67-
</Row>
51+
<div className="flex items-center gap-2 h-full w-full px-page-x">
52+
{/* Workitem header section */}
53+
<div className="flex items-center gap-1 flex-grow h-full py-2.5 min-w-80">
54+
{canSelectIssues && (
55+
<div className="flex-shrink-0 flex items-center w-3.5 mr-1">
56+
<MultipleSelectGroupAction
57+
className={cn(
58+
"size-3.5 opacity-0 pointer-events-none group-hover/list-header:opacity-100 group-hover/list-header:pointer-events-auto !outline-none",
59+
{
60+
"opacity-100 pointer-events-auto": !isGroupSelectionEmpty,
61+
}
62+
)}
63+
groupID={SPREADSHEET_SELECT_GROUP}
64+
selectionHelpers={selectionHelpers}
65+
/>
66+
</div>
67+
)}
68+
<span className="text-sm font-medium">{`${isEpic ? "Epics" : "Work items"}`}</span>
69+
</div>
70+
</div>
6871
</th>
6972

7073
{spreadsheetColumnsList.map((property) => (

apps/web/core/components/project/create/common-attributes.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function ProjectCommonAttributes(props: Props) {
3939
return;
4040
}
4141
if (e.target.value === "") setValue("identifier", "");
42-
else setValue("identifier", projectIdentifierSanitizer(e.target.value).substring(0, 5));
42+
else setValue("identifier", projectIdentifierSanitizer(e.target.value).substring(0, 10));
4343
onChange(e);
4444
handleFormOnChange?.();
4545
};
@@ -91,11 +91,11 @@ function ProjectCommonAttributes(props: Props) {
9191
/^[ÇŞĞIİÖÜA-Z0-9]+$/.test(value.toUpperCase()) || t("only_alphanumeric_non_latin_characters_allowed"),
9292
minLength: {
9393
value: 1,
94-
message: t("project_id_must_be_at_least_1_character"),
94+
message: t("project_id_min_char"),
9595
},
9696
maxLength: {
97-
value: 5,
98-
message: t("project_id_must_be_at_most_5_characters"),
97+
value: 10,
98+
message: t("project_id_max_char"),
9999
},
100100
}}
101101
render={({ field: { value, onChange } }) => (

apps/web/core/components/project/form.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ export function ProjectDetailsForm(props: IProjectDetailsForm) {
185185

186186
if (project.identifier !== formData.identifier)
187187
await projectService
188-
.checkProjectIdentifierAvailability(workspaceSlug as string, payload.identifier ?? "")
188+
.checkProjectIdentifierAvailability(workspaceSlug, payload.identifier ?? "")
189189
.then(async (res) => {
190190
if (res.exists) setError("identifier", { message: t("common.identifier_already_exists") });
191191
else await handleUpdateChange(payload);
@@ -338,7 +338,7 @@ export function ProjectDetailsForm(props: IProjectDetailsForm) {
338338
message: t("project_id_min_char"),
339339
},
340340
maxLength: {
341-
value: 5,
341+
value: 10,
342342
message: t("project_id_max_char"),
343343
},
344344
}}
@@ -359,7 +359,7 @@ export function ProjectDetailsForm(props: IProjectDetailsForm) {
359359
/>
360360
<Tooltip
361361
isMobile={isMobile}
362-
tooltipContent="Helps you identify work items in the project uniquely. Max 5 characters."
362+
tooltipContent={t("project_id_tooltip_content")}
363363
className="text-sm"
364364
position="right-start"
365365
>

packages/i18n/src/locales/cs/translations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,13 @@ export default {
337337
project_id_must_be_at_least_1_character: "ID projektu musí mít alespoň 1 znak",
338338
project_id_must_be_at_most_5_characters: "ID projektu může mít maximálně 5 znaků",
339339
project_id: "ID projektu",
340-
project_id_tooltip_content: "Pomáhá jednoznačně identifikovat pracovní položky v projektu. Max. 5 znaků.",
340+
project_id_tooltip_content: "Pomáhá jednoznačně identifikovat pracovní položky v projektu. Max. 10 znaků.",
341341
description_placeholder: "Popis",
342342
only_alphanumeric_non_latin_characters_allowed: "Jsou povoleny pouze alfanumerické a nelatinské znaky.",
343343
project_id_is_required: "ID projektu je povinné",
344344
project_id_allowed_char: "Jsou povoleny pouze alfanumerické a nelatinské znaky.",
345345
project_id_min_char: "ID projektu musí mít alespoň 1 znak",
346-
project_id_max_char: "ID projektu může mít maximálně 5 znaků",
346+
project_id_max_char: "ID projektu může mít maximálně 10 znaků",
347347
project_description_placeholder: "Zadejte popis projektu",
348348
select_network: "Vybrat síť",
349349
lead: "Vedoucí",

packages/i18n/src/locales/de/translations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,13 @@ export default {
344344
project_id_must_be_at_least_1_character: "Projekt-ID muss mindestens 1 Zeichen lang sein",
345345
project_id_must_be_at_most_5_characters: "Projekt-ID darf maximal 5 Zeichen lang sein",
346346
project_id: "Projekt-ID",
347-
project_id_tooltip_content: "Hilft, Arbeitselemente im Projekt eindeutig zu identifizieren. Max. 5 Zeichen.",
347+
project_id_tooltip_content: "Hilft, Arbeitselemente im Projekt eindeutig zu identifizieren. Max. 10 Zeichen.",
348348
description_placeholder: "Beschreibung",
349349
only_alphanumeric_non_latin_characters_allowed: "Es sind nur alphanumerische und nicht-lateinische Zeichen erlaubt.",
350350
project_id_is_required: "Projekt-ID ist erforderlich",
351351
project_id_allowed_char: "Es sind nur alphanumerische und nicht-lateinische Zeichen erlaubt.",
352352
project_id_min_char: "Projekt-ID muss mindestens 1 Zeichen lang sein",
353-
project_id_max_char: "Projekt-ID darf maximal 5 Zeichen lang sein",
353+
project_id_max_char: "Projekt-ID darf maximal 10 Zeichen lang sein",
354354
project_description_placeholder: "Geben Sie eine Projektbeschreibung ein",
355355
select_network: "Netzwerk auswählen",
356356
lead: "Leitung",

packages/i18n/src/locales/en/translations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,13 @@ export default {
172172
project_id_must_be_at_least_1_character: "Project ID must at least be of 1 character",
173173
project_id_must_be_at_most_5_characters: "Project ID must at most be of 5 characters",
174174
project_id: "Project ID",
175-
project_id_tooltip_content: "Helps you identify work items in the project uniquely. Max 5 characters.",
175+
project_id_tooltip_content: "Helps you identify work items in the project uniquely. Max 10 characters.",
176176
description_placeholder: "Description",
177177
only_alphanumeric_non_latin_characters_allowed: "Only Alphanumeric & Non-latin characters are allowed.",
178178
project_id_is_required: "Project ID is required",
179179
project_id_allowed_char: "Only Alphanumeric & Non-latin characters are allowed.",
180180
project_id_min_char: "Project ID must at least be of 1 character",
181-
project_id_max_char: "Project ID must at most be of 5 characters",
181+
project_id_max_char: "Project ID must at most be of 10 characters",
182182
project_description_placeholder: "Enter project description",
183183
select_network: "Select network",
184184
lead: "Lead",

packages/i18n/src/locales/es/translations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,13 +345,13 @@ export default {
345345
project_id_must_be_at_most_5_characters: "El ID del proyecto debe tener como máximo 5 caracteres",
346346
project_id: "ID del proyecto",
347347
project_id_tooltip_content:
348-
"Te ayuda a identificar elementos de trabajo en el proyecto de manera única. Máximo 5 caracteres.",
348+
"Te ayuda a identificar elementos de trabajo en el proyecto de manera única. Máximo 10 caracteres.",
349349
description_placeholder: "Descripción",
350350
only_alphanumeric_non_latin_characters_allowed: "Solo se permiten caracteres alfanuméricos y no latinos.",
351351
project_id_is_required: "El ID del proyecto es requerido",
352352
project_id_allowed_char: "Solo se permiten caracteres alfanuméricos y no latinos.",
353353
project_id_min_char: "El ID del proyecto debe tener al menos 1 carácter",
354-
project_id_max_char: "El ID del proyecto debe tener como máximo 5 caracteres",
354+
project_id_max_char: "El ID del proyecto debe tener como máximo 10 caracteres",
355355
project_description_placeholder: "Ingresa la descripción del proyecto",
356356
select_network: "Seleccionar red",
357357
lead: "Líder",

packages/i18n/src/locales/fr/translations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,13 @@ export default {
341341
project_id_must_be_at_most_5_characters: "L’ID du projet doit comporter au plus 5 caractères",
342342
project_id: "ID du projet",
343343
project_id_tooltip_content:
344-
"Vous aide à identifier de manière unique les éléments de travail dans le projet. Maximum 5 caractères.",
344+
"Vous aide à identifier de manière unique les éléments de travail dans le projet. Maximum 10 caractères.",
345345
description_placeholder: "Description",
346346
only_alphanumeric_non_latin_characters_allowed: "Seuls les caractères alphanumériques et non latins sont autorisés.",
347347
project_id_is_required: "L’ID du projet est requis",
348348
project_id_allowed_char: "Seuls les caractères alphanumériques et non latins sont autorisés.",
349349
project_id_min_char: "L’ID du projet doit comporter au moins 1 caractère",
350-
project_id_max_char: "LID du projet doit comporter au plus 5 caractères",
350+
project_id_max_char: "L'ID du projet doit comporter au plus 10 caractères",
351351
project_description_placeholder: "Entrez la description du projet",
352352
select_network: "Sélectionner le réseau",
353353
lead: "Responsable",

packages/i18n/src/locales/id/translations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,13 +340,13 @@ export default {
340340
project_id_must_be_at_most_5_characters: "ID proyek maksimal 5 karakter",
341341
project_id: "ID proyek",
342342
project_id_tooltip_content:
343-
"Membantu Anda mengidentifikasi item kerja dalam proyek secara unik. Maksimal 5 karakter.",
343+
"Membantu Anda mengidentifikasi item kerja dalam proyek secara unik. Maksimal 10 karakter.",
344344
description_placeholder: "Deskripsi",
345345
only_alphanumeric_non_latin_characters_allowed: "Hanya karakter alfanumerik & Non-latin yang diizinkan.",
346346
project_id_is_required: "ID proyek diperlukan",
347347
project_id_allowed_char: "Hanya karakter alfanumerik & Non-latin yang diizinkan.",
348348
project_id_min_char: "ID proyek harus minimal 1 karakter",
349-
project_id_max_char: "ID proyek maksimal 5 karakter",
349+
project_id_max_char: "ID proyek maksimal 10 karakter",
350350
project_description_placeholder: "Masukkan deskripsi proyek",
351351
select_network: "Pilih jaringan",
352352
lead: "Pemimpin",

0 commit comments

Comments
 (0)