Skip to content

Commit 4bd5f0e

Browse files
authored
feat(canisters): allow canister names up to 64 characters (#8013)
# Motivation The backend accepts canister names up to 64 characters since #8012. The frontend still validates against the old 24-character limit. A 64-character name can also be one long word, so the detail page and the top-up confirm screen need a wrap rule for it. # Changes - Raised `MAX_CANISTER_NAME_LENGTH` from 24 to 64. - Updated the `error__canister.name_too_long` message to state 64 characters. - Added `overflow-wrap: anywhere` to the canister heading title, the heading subtitle, and the name on the cycles confirm screen. - Updated the tests that hardcoded the old limit in names and messages. --- Prev. #8012
1 parent 0a8f4b4 commit 4bd5f0e

12 files changed

Lines changed: 44 additions & 10 deletions

File tree

frontend/src/lib/api/canisters.api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export const attachCanister = async ({
104104
if (isNameTooLong(name)) {
105105
throw new CanisterNameTooLongError("error__canister.name_too_long", {
106106
$name: name,
107+
$max: String(MAX_CANISTER_NAME_LENGTH),
107108
});
108109
}
109110

@@ -133,6 +134,7 @@ export const renameCanister = async ({
133134
if (isNameTooLong(name)) {
134135
throw new CanisterNameTooLongError("error__canister.name_too_long", {
135136
$name: name,
137+
$max: String(MAX_CANISTER_NAME_LENGTH),
136138
});
137139
}
138140

@@ -235,6 +237,7 @@ export const createCanister = async ({
235237
if (isNameTooLong(name)) {
236238
throw new CanisterNameTooLongError("error__canister.name_too_long", {
237239
$name: name,
240+
$max: String(MAX_CANISTER_NAME_LENGTH),
238241
});
239242
}
240243

frontend/src/lib/canisters/nns-dapp/nns-dapp.canister.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import type {
3838
RenameSubAccountResponse,
3939
SubAccountDetails,
4040
} from "$lib/canisters/nns-dapp/nns-dapp.types";
41+
import { MAX_CANISTER_NAME_LENGTH } from "$lib/constants/canisters.constants";
4142
import { toNullable } from "@dfinity/utils";
4243
import { AccountIdentifier } from "@icp-sdk/canisters/ledger/icp";
4344
import { Actor } from "@icp-sdk/core/agent";
@@ -255,6 +256,7 @@ export class NNSDappCanister {
255256
if ("NameTooLong" in response) {
256257
throw new CanisterNameTooLongError("error__canister.name_too_long", {
257258
$name: name,
259+
$max: String(MAX_CANISTER_NAME_LENGTH),
258260
});
259261
}
260262
if ("CanisterLimitExceeded" in response) {
@@ -286,6 +288,7 @@ export class NNSDappCanister {
286288
if ("NameTooLong" in response) {
287289
throw new CanisterNameTooLongError("error__canister.name_too_long", {
288290
$name: name,
291+
$max: String(MAX_CANISTER_NAME_LENGTH),
289292
});
290293
}
291294
if ("CanisterNotFound" in response) {

frontend/src/lib/components/canister-detail/CanisterHeadingTitle.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
// Needed if the canister id is very long for mobile and uses multiple lines.
4444
text-align: center;
4545
margin: 0;
46+
// A canister name can be one long word without spaces.
47+
overflow-wrap: anywhere;
4648
}
4749
4850
.skeleton {

frontend/src/lib/components/canister-detail/CanisterPageHeading.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
/>
2222
<svelte:fragment slot="subtitle">
2323
{#if canister.name.length > 0 && isController}
24-
<HeadingSubtitle testId="subtitle">{canister.name}</HeadingSubtitle>
24+
<HeadingSubtitle testId="subtitle" breakLongWords
25+
>{canister.name}</HeadingSubtitle
26+
>
2527
{/if}
2628
</svelte:fragment>
2729
<svelte:fragment slot="tags">

frontend/src/lib/components/canisters/ConfirmCyclesCanister.svelte

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
{#if nonNullish(name) && name !== ""}
3333
<KeyValuePair>
3434
{#snippet key()}<span>{$i18n.canisters.name}</span>{/snippet}
35-
{#snippet value()}<span>{name}</span>{/snippet}
35+
{#snippet value()}<span class="canister-name">{name}</span>{/snippet}
3636
</KeyValuePair>
3737
{/if}
3838
<p class="conversion">
@@ -86,6 +86,12 @@
8686
@include fonts.h3;
8787
}
8888
89+
.canister-name {
90+
// A canister name can be one long word without spaces.
91+
overflow-wrap: anywhere;
92+
text-align: right;
93+
}
94+
8995
.conversion {
9096
display: flex;
9197
align-items: baseline;
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
<script lang="ts">
22
export let testId: string | undefined = undefined;
3+
// Opt in when the subtitle can be one long word without spaces.
4+
export let breakLongWords = false;
35
</script>
46

5-
<h4 data-tid={testId} class="description"><slot /></h4>
7+
<h4
8+
data-tid={testId}
9+
class="description"
10+
class:break-long-words={breakLongWords}
11+
>
12+
<slot />
13+
</h4>
614

715
<style lang="scss">
816
h4 {
917
margin: 0;
1018
font-weight: normal;
19+
20+
&.break-long-words {
21+
overflow-wrap: anywhere;
22+
}
1123
}
1224
</style>

frontend/src/lib/constants/canisters.constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ export const NEW_CANISTER_MIN_T_CYCLES = 2;
77
export const SYNC_CYCLES_TIMER_INTERVAL = SECONDS_IN_MINUTE * 1000; // 1 minute
88

99
// Constraint coming from the backend
10-
export const MAX_CANISTER_NAME_LENGTH = 24;
10+
export const MAX_CANISTER_NAME_LENGTH = 64;

frontend/src/lib/i18n/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@
11281128
"error__canister": {
11291129
"already_attached": "Canister ($canisterId) is already linked",
11301130
"name_taken": "The name $name is already in use. Names must be unique.",
1131-
"name_too_long": "The name $name is too long (max. 24 characters). Please, choose a shorter name.",
1131+
"name_too_long": "The name $name is too long (max. $max characters). Please, choose a shorter name.",
11321132
"limit_exceeded": "The limit of canisters that can be linked has been exceeded.",
11331133
"unlink_not_found": "Error unlinking, canister ($canisterId) not found.",
11341134
"unknown_link": "Error linking canister.",

frontend/src/tests/lib/api/canisters.api.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ describe("canisters-api", () => {
121121
await expect(call).rejects.toThrowError(
122122
new CanisterNameTooLongError("error__canister.name_too_long", {
123123
$name: longName,
124+
$max: String(MAX_CANISTER_NAME_LENGTH),
124125
})
125126
);
126127
expect(mockNNSDappCanister.attachCanister).not.toBeCalled();
@@ -150,6 +151,7 @@ describe("canisters-api", () => {
150151
await expect(call).rejects.toThrowError(
151152
new CanisterNameTooLongError("error__canister.name_too_long", {
152153
$name: longName,
154+
$max: String(MAX_CANISTER_NAME_LENGTH),
153155
})
154156
);
155157
expect(mockNNSDappCanister.renameCanister).not.toBeCalled();
@@ -352,6 +354,7 @@ describe("canisters-api", () => {
352354
await expect(call).rejects.toThrowError(
353355
new CanisterNameTooLongError("error__canister.name_too_long", {
354356
$name: longName,
357+
$max: String(MAX_CANISTER_NAME_LENGTH),
355358
})
356359
);
357360
expect(mockCmcCanister.notifyCreateCanister).not.toBeCalled();

frontend/src/tests/lib/modals/canisters/LinkCanisterModal.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ describe("LinkCanisterModal", () => {
133133
nameInputElement && (await fireEvent.blur(nameInputElement));
134134

135135
expect(
136-
queryByText("Canister name too long. Maximum of 24 characters allowed.")
136+
queryByText(
137+
`Canister name too long. Maximum of ${MAX_CANISTER_NAME_LENGTH} characters allowed.`
138+
)
137139
).toBeInTheDocument();
138140
expect(
139141
queryByTestId("link-canister-button")?.hasAttribute("disabled")

0 commit comments

Comments
 (0)