Skip to content

Commit 6c6baa0

Browse files
committed
frontend: Sanitize Projects' names as we type
Signed-off-by: Joaquim Rocha <joaquim.rocha@microsoft.com>
1 parent 1797e0d commit 6c6baa0

File tree

14 files changed

+62
-23
lines changed

14 files changed

+62
-23
lines changed

frontend/src/components/project/NewProjectPopup.tsx

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function ProjectFromExistingNamespace({ onBack }: { onBack: () => void }) {
105105
const { t } = useTranslation();
106106
const history = useHistory();
107107

108-
const [name, setName] = useState('');
108+
const [projectName, setProjectName] = useState('');
109109
const [selectedClusters, setSelectedClusters] = useState<string[]>([]);
110110
const [selectedNamespace, setSelectedNamespace] = useState<string>();
111111
const [typedNamespace, setTypedNamespace] = useState('');
@@ -118,7 +118,8 @@ function ProjectFromExistingNamespace({ onBack }: { onBack: () => void }) {
118118
clusters: selectedClusters,
119119
});
120120

121-
const isReadyToCreate = selectedClusters.length && (selectedNamespace || typedNamespace) && name;
121+
const isReadyToCreate =
122+
selectedClusters.length && (selectedNamespace || typedNamespace) && projectName;
122123

123124
/**
124125
* Creates or updates namespaces for the proejct
@@ -133,7 +134,7 @@ function ProjectFromExistingNamespace({ onBack }: { onBack: () => void }) {
133134
await maybeExistingNamespace.patch({
134135
metadata: {
135136
labels: {
136-
[PROJECT_ID_LABEL]: toKubernetesName(name),
137+
[PROJECT_ID_LABEL]: projectName,
137138
},
138139
},
139140
});
@@ -145,15 +146,15 @@ function ProjectFromExistingNamespace({ onBack }: { onBack: () => void }) {
145146
metadata: {
146147
name: toKubernetesName(typedNamespace),
147148
labels: {
148-
[PROJECT_ID_LABEL]: toKubernetesName(name),
149+
[PROJECT_ID_LABEL]: projectName,
149150
},
150151
} as any,
151152
} as KubeObjectInterface;
152153
await apply(namespace, cluster);
153154
}
154155
}
155156

156-
history.push(createRouteURL('projectDetails', { name: toKubernetesName(name) }));
157+
history.push(createRouteURL('projectDetails', { name: projectName }));
157158
} catch (e: any) {
158159
setError(e);
159160
} finally {
@@ -184,11 +185,36 @@ function ProjectFromExistingNamespace({ onBack }: { onBack: () => void }) {
184185
</Trans>
185186
</Typography>
186187
<TextField
187-
label={t('Name')}
188-
variant="outlined"
189-
size="small"
190-
value={name}
191-
onChange={e => setName(e.target.value)}
188+
label={t('translation|Project Name')}
189+
value={projectName}
190+
onChange={event => {
191+
const inputValue = event.target.value.toLowerCase();
192+
setProjectName(inputValue);
193+
}}
194+
onBlur={event => {
195+
// Convert to Kubernetes name when user finishes typing (loses focus)
196+
const converted = toKubernetesName(event.target.value);
197+
setProjectName(converted);
198+
}}
199+
onKeyDown={event => {
200+
// Convert spaces to dashes immediately when space is pressed
201+
if (event.key === ' ') {
202+
event.preventDefault();
203+
const target = event.target as HTMLInputElement;
204+
const start = target.selectionStart || 0;
205+
const end = target.selectionEnd || 0;
206+
const currentValue = projectName;
207+
const newValue = currentValue.substring(0, start) + '-' + currentValue.substring(end);
208+
setProjectName(newValue);
209+
// Set cursor position after the inserted dash
210+
setTimeout(() => {
211+
target.setSelectionRange(start + 1, start + 1);
212+
}, 0);
213+
}
214+
}}
215+
helperText={t('translation|Enter a name for your new project.')}
216+
autoComplete="off"
217+
fullWidth
192218
/>
193219
<Autocomplete
194220
fullWidth

frontend/src/components/project/projectUtils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ export const defaultApiResources = (() => {
204204
export const toKubernetesName = (name: string): string => {
205205
const converted = name
206206
.toLowerCase()
207-
.replace(/[^a-z0-9-]/g, '-') // Replace non-alphanumeric chars with dashes
207+
.replace(/\s+/g, '-') // Replace spaces with dashes
208+
.replace(/[^a-z0-9-]/g, '-') // Replace other non-alphanumeric chars with dashes
208209
.replace(/-+/g, '-') // Replace multiple dashes with single dash
209210
.replace(/^-+|-+$/g, '') // Remove leading/trailing dashes
210211
.substring(0, 63); // Ensure max 63 characters for DNS-1123 compliance

frontend/src/i18n/locales/de/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@
477477
"Preemption Policy": "Preemtions-Policy",
478478
"Create new project": "",
479479
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "",
480+
"Project Name": "",
481+
"Enter a name for your new project.": "",
480482
"Clusters": "",
481483
"Select one or more clusters for this project": "",
482484
"No available clusters": "",
@@ -496,7 +498,6 @@
496498
"Create new Project from YAML": "",
497499
"Project name": "",
498500
"Give your project a descriptive name": "",
499-
"Project Name": "",
500501
"Enter a name": "",
501502
"Select cluster for this project": "",
502503
"Upload files(s)": "",

frontend/src/i18n/locales/en/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@
477477
"Preemption Policy": "Preemption Policy",
478478
"Create new project": "Create new project",
479479
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "To create a new project pick which clusters you want to include and then select existing or create a new namespace",
480+
"Project Name": "Project Name",
481+
"Enter a name for your new project.": "Enter a name for your new project.",
480482
"Clusters": "Clusters",
481483
"Select one or more clusters for this project": "Select one or more clusters for this project",
482484
"No available clusters": "No available clusters",
@@ -496,7 +498,6 @@
496498
"Create new Project from YAML": "Create new Project from YAML",
497499
"Project name": "Project name",
498500
"Give your project a descriptive name": "Give your project a descriptive name",
499-
"Project Name": "Project Name",
500501
"Enter a name": "Enter a name",
501502
"Select cluster for this project": "Select cluster for this project",
502503
"Upload files(s)": "Upload files(s)",

frontend/src/i18n/locales/es/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@
479479
"Preemption Policy": "Política de \"Preemption\"",
480480
"Create new project": "",
481481
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "",
482+
"Project Name": "",
483+
"Enter a name for your new project.": "",
482484
"Clusters": "",
483485
"Select one or more clusters for this project": "",
484486
"No available clusters": "",
@@ -498,7 +500,6 @@
498500
"Create new Project from YAML": "",
499501
"Project name": "",
500502
"Give your project a descriptive name": "",
501-
"Project Name": "",
502503
"Enter a name": "",
503504
"Select cluster for this project": "",
504505
"Upload files(s)": "",

frontend/src/i18n/locales/fr/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@
479479
"Preemption Policy": "Politique de préemption",
480480
"Create new project": "",
481481
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "",
482+
"Project Name": "",
483+
"Enter a name for your new project.": "",
482484
"Clusters": "",
483485
"Select one or more clusters for this project": "",
484486
"No available clusters": "",
@@ -498,7 +500,6 @@
498500
"Create new Project from YAML": "",
499501
"Project name": "",
500502
"Give your project a descriptive name": "",
501-
"Project Name": "",
502503
"Enter a name": "",
503504
"Select cluster for this project": "",
504505
"Upload files(s)": "",

frontend/src/i18n/locales/hi/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@
477477
"Preemption Policy": "",
478478
"Create new project": "",
479479
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "",
480+
"Project Name": "",
481+
"Enter a name for your new project.": "",
480482
"Clusters": "",
481483
"Select one or more clusters for this project": "",
482484
"No available clusters": "",
@@ -496,7 +498,6 @@
496498
"Create new Project from YAML": "",
497499
"Project name": "",
498500
"Give your project a descriptive name": "",
499-
"Project Name": "",
500501
"Enter a name": "",
501502
"Select cluster for this project": "",
502503
"Upload files(s)": "",

frontend/src/i18n/locales/it/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@
479479
"Preemption Policy": "Politica di Preemption",
480480
"Create new project": "",
481481
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "",
482+
"Project Name": "",
483+
"Enter a name for your new project.": "",
482484
"Clusters": "",
483485
"Select one or more clusters for this project": "",
484486
"No available clusters": "",
@@ -498,7 +500,6 @@
498500
"Create new Project from YAML": "",
499501
"Project name": "",
500502
"Give your project a descriptive name": "",
501-
"Project Name": "",
502503
"Enter a name": "",
503504
"Select cluster for this project": "",
504505
"Upload files(s)": "",

frontend/src/i18n/locales/ja/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,8 @@
475475
"Preemption Policy": "プリエンプションポリシー",
476476
"Create new project": "",
477477
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "",
478+
"Project Name": "",
479+
"Enter a name for your new project.": "",
478480
"Clusters": "",
479481
"Select one or more clusters for this project": "",
480482
"No available clusters": "",
@@ -494,7 +496,6 @@
494496
"Create new Project from YAML": "",
495497
"Project name": "",
496498
"Give your project a descriptive name": "",
497-
"Project Name": "",
498499
"Enter a name": "",
499500
"Select cluster for this project": "",
500501
"Upload files(s)": "",

frontend/src/i18n/locales/ko/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,8 @@
475475
"Preemption Policy": "선점 정책",
476476
"Create new project": "",
477477
"To create a new project pick which clusters you want to include and then select existing or create a new namespace": "",
478+
"Project Name": "",
479+
"Enter a name for your new project.": "",
478480
"Clusters": "",
479481
"Select one or more clusters for this project": "",
480482
"No available clusters": "",
@@ -494,7 +496,6 @@
494496
"Create new Project from YAML": "",
495497
"Project name": "",
496498
"Give your project a descriptive name": "",
497-
"Project Name": "",
498499
"Enter a name": "",
499500
"Select cluster for this project": "",
500501
"Upload files(s)": "",

0 commit comments

Comments
 (0)