Skip to content

Commit dc603c1

Browse files
committed
Make new Mechanism/OpMode name dialog ask for a PascalCase style class name.
Show class names in the tree, instead of the module (file) names.
1 parent cefe0fa commit dc603c1

File tree

3 files changed

+124
-71
lines changed

3 files changed

+124
-71
lines changed

src/App.tsx

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
Flex,
88
Input,
99
message,
10-
Modal,
1110
Popconfirm,
1211
Space,
1312
Splitter,
@@ -44,8 +43,8 @@ import {pythonGenerator} from 'blockly/python';
4443

4544
import BlocklyComponent from './Blockly';
4645

47-
import { NewProjectNameModalProps, NewProjectNameModal } from './modal/NewProjectNameModal';
48-
import { NewModuleNameModalProps, NewModuleNameModal } from './modal/NewModuleNameModal';
46+
import * as NewProjectNameModal from './modal/NewProjectNameModal';
47+
import * as NewModuleNameModal from './modal/NewModuleNameModal';
4948

5049
import * as CustomBlocks from './blocks/setup_custom_blocks';
5150
import { initialize as initializeGeneratedBlocks } from './blocks/utils/generated/initialize';
@@ -95,10 +94,13 @@ const App: React.FC = () => {
9594
const [newProjectNameModalPurpose, setNewProjectNameModalPurpose] = useState('');
9695
const [newProjectNameModalInitialValue, setNewProjectNameModalInitialValue] = useState('');
9796
const [newProjectNameModalTitle, setNewProjectNameModalTitle] = useState('');
97+
const [newProjectNameModalMessage, setNewProjectNameModalMessage] = useState('');
9898
const [newProjectNameModalIsOpen, setNewProjectNameModalIsOpen] = useState(false);
9999
const [newModuleNameModalPurpose, setNewModuleNameModalPurpose] = useState('');
100100
const [newModuleNameModalInitialValue, setNewModuleNameModalInitialValue] = useState('');
101101
const [newModuleNameModalTitle, setNewModuleNameModalTitle] = useState('');
102+
const [newModuleNameModalExample, setNewModuleNameModalExample] = useState('');
103+
const [newModuleNameModalLabel, setNewModuleNameModalLabel] = useState('');
102104
const [newModuleNameModalIsOpen, setNewModuleNameModalIsOpen] = useState(false);
103105
const [toolboxSettingsModalIsOpen, setToolboxSettingsModalIsOpen] = useState(false);
104106
const [popconfirmTitle, setPopconfirmTitle] = useState('');
@@ -192,7 +194,8 @@ const App: React.FC = () => {
192194
if (array.length === 0) {
193195
setNewProjectNameModalPurpose(PURPOSE_NEW_PROJECT);
194196
setNewProjectNameModalInitialValue('');
195-
setNewProjectNameModalTitle('Welcome to WPILib Blocks!');
197+
setNewProjectNameModalTitle(NewProjectNameModal.TITLE_WELCOME);
198+
setNewProjectNameModalMessage(NewProjectNameModal.MESSAGE_WELCOME);
196199
setNewProjectNameModalIsOpen(true);
197200
}
198201
};
@@ -242,7 +245,7 @@ const App: React.FC = () => {
242245
}
243246
const child: TreeDataNode = {
244247
key: mechanism.modulePath,
245-
title: mechanism.moduleName,
248+
title: mechanism.className,
246249
icon: <MechanismOutlined />,
247250
};
248251
children.push(child);
@@ -256,7 +259,7 @@ const App: React.FC = () => {
256259
}
257260
const child: TreeDataNode = {
258261
key: opMode.modulePath,
259-
title: opMode.moduleName,
262+
title: opMode.className,
260263
icon: <OpModeOutlined />,
261264
};
262265
children.push(child);
@@ -432,7 +435,8 @@ const App: React.FC = () => {
432435
checkIfBlocksWereModified(() => {
433436
setNewProjectNameModalPurpose(PURPOSE_NEW_PROJECT);
434437
setNewProjectNameModalInitialValue('');
435-
setNewProjectNameModalTitle('New Project');
438+
setNewProjectNameModalTitle(NewProjectNameModal.TITLE_NEW_PROJECT);
439+
setNewProjectNameModalMessage('');
436440
setNewProjectNameModalIsOpen(true);
437441
});
438442
};
@@ -457,8 +461,7 @@ const App: React.FC = () => {
457461
const newProjectName = commonStorage.classNameToModuleName(newProjectClassName);
458462
const newProjectPath = commonStorage.makeProjectPath(newProjectName);
459463
if (newProjectNameModalPurpose === PURPOSE_NEW_PROJECT) {
460-
const projectContent = commonStorage.newProjectContent(
461-
newProjectClassName, newProjectName, newProjectPath);
464+
const projectContent = commonStorage.newProjectContent(newProjectName);
462465
try {
463466
await storage.createModule(
464467
commonStorage.MODULE_TYPE_PROJECT, newProjectPath, projectContent);
@@ -503,7 +506,9 @@ const App: React.FC = () => {
503506
checkIfBlocksWereModified(() => {
504507
setNewModuleNameModalPurpose(PURPOSE_NEW_MECHANISM);
505508
setNewModuleNameModalInitialValue('');
506-
setNewModuleNameModalTitle('New Mechanism');
509+
setNewModuleNameModalTitle(NewModuleNameModal.TITLE_NEW_MECHANISM);
510+
setNewModuleNameModalExample(NewModuleNameModal.EXAMPLE_MECHANISM);
511+
setNewModuleNameModalLabel(NewModuleNameModal.LABEL_MECHANISM);
507512
setNewModuleNameModalIsOpen(true);
508513
});
509514
};
@@ -512,7 +517,9 @@ const App: React.FC = () => {
512517
checkIfBlocksWereModified(() => {
513518
setNewModuleNameModalPurpose(PURPOSE_NEW_OPMODE);
514519
setNewModuleNameModalInitialValue('');
515-
setNewModuleNameModalTitle('New OpMode');
520+
setNewModuleNameModalTitle(NewModuleNameModal.TITLE_NEW_OPMODE);
521+
setNewModuleNameModalExample(NewModuleNameModal.EXAMPLE_OPMODE);
522+
setNewModuleNameModalLabel(NewModuleNameModal.LABEL_OPMODE);
516523
setNewModuleNameModalIsOpen(true);
517524
});
518525
};
@@ -524,24 +531,25 @@ const App: React.FC = () => {
524531
};
525532

526533
// Provide a callback so the NewModuleNameModal will know what the existing
527-
// module names are in the current project.
528-
const getModuleNames = (projectName: string): string[] => {
529-
const moduleNames: string[] = [];
534+
// module class names are in the current project.
535+
const getModuleClassNames = (projectName: string): string[] => {
536+
const moduleClassNames: string[] = [];
530537
for (const project of modules) {
531538
if (project.projectName === projectName) {
532539
project.mechanisms.forEach((mechanism) => {
533-
moduleNames.push(mechanism.moduleName);
540+
moduleClassNames.push(mechanism.className);
534541
});
535542
project.opModes.forEach((opMode) => {
536-
moduleNames.push(opMode.moduleName);
543+
moduleClassNames.push(opMode.className);
537544
});
538545
break;
539546
}
540547
}
541-
return moduleNames;
548+
return moduleClassNames;
542549
};
543550

544-
const handleNewModuleNameOk = async (newModuleName: string) => {
551+
const handleNewModuleNameOk = async (newModuleClassName: string) => {
552+
const newModuleName = commonStorage.classNameToModuleName(newModuleClassName);
545553
const newModulePath = commonStorage.makeModulePath(currentModule.projectName, newModuleName);
546554
if (newModuleNameModalPurpose === PURPOSE_NEW_MECHANISM) {
547555
const mechanismContent = commonStorage.newMechanismContent(
@@ -630,20 +638,25 @@ const App: React.FC = () => {
630638
if (currentModule.moduleType == commonStorage.MODULE_TYPE_PROJECT) {
631639
// This is a Project.
632640
setNewProjectNameModalPurpose(PURPOSE_RENAME_PROJECT);
633-
setNewProjectNameModalInitialValue(currentModule.projectName);
634-
setNewProjectNameModalTitle('Rename Project');
641+
setNewProjectNameModalInitialValue(commonStorage.moduleNameToClassName(currentModule.projectName));
642+
setNewProjectNameModalTitle(NewProjectNameModal.TITLE_RENAME_PROJECT);
643+
setNewProjectNameModalMessage('');
635644
setNewProjectNameModalIsOpen(true);
636645
} else if (currentModule.moduleType == commonStorage.MODULE_TYPE_MECHANISM) {
637646
// This is a Mechanism.
638647
setNewModuleNameModalPurpose(PURPOSE_RENAME_MODULE);
639-
setNewModuleNameModalInitialValue(currentModule.moduleName);
640-
setNewModuleNameModalTitle('Rename Mechanism');
648+
setNewModuleNameModalInitialValue(currentModule.className);
649+
setNewModuleNameModalTitle(NewModuleNameModal.TITLE_RENAME_MECHANISM);
650+
setNewModuleNameModalExample(NewModuleNameModal.EXAMPLE_MECHANISM);
651+
setNewModuleNameModalLabel(NewModuleNameModal.LABEL_MECHANISM);
641652
setNewModuleNameModalIsOpen(true);
642653
} else if (currentModule.moduleType == commonStorage.MODULE_TYPE_OPMODE) {
643654
// This is an OpMode.
644655
setNewModuleNameModalPurpose(PURPOSE_RENAME_MODULE);
645-
setNewModuleNameModalInitialValue(currentModule.moduleName);
646-
setNewModuleNameModalTitle('Rename OpMode');
656+
setNewModuleNameModalInitialValue(currentModule.className);
657+
setNewModuleNameModalTitle(NewModuleNameModal.TITLE_RENAME_OPMODE);
658+
setNewModuleNameModalExample(NewModuleNameModal.EXAMPLE_OPMODE);
659+
setNewModuleNameModalLabel(NewModuleNameModal.LABEL_OPMODE);
647660
setNewModuleNameModalIsOpen(true);
648661
}
649662
});
@@ -657,20 +670,25 @@ const App: React.FC = () => {
657670
if (currentModule.moduleType == commonStorage.MODULE_TYPE_PROJECT) {
658671
// This is a Project.
659672
setNewProjectNameModalPurpose(PURPOSE_COPY_PROJECT);
660-
setNewProjectNameModalInitialValue(currentModule.projectName + '_copy');
661-
setNewProjectNameModalTitle('Copy Project');
673+
setNewProjectNameModalInitialValue(commonStorage.moduleNameToClassName(currentModule.projectName) + 'Copy');
674+
setNewProjectNameModalTitle(NewProjectNameModal.TITLE_COPY_PROJECT);
675+
setNewProjectNameModalMessage('');
662676
setNewProjectNameModalIsOpen(true);
663677
} else if (currentModule.moduleType == commonStorage.MODULE_TYPE_MECHANISM) {
664678
// This is a Mechanism.
665679
setNewModuleNameModalPurpose(PURPOSE_COPY_MODULE);
666-
setNewModuleNameModalInitialValue(currentModule.moduleName + '_copy');
667-
setNewModuleNameModalTitle('Copy Mechanism');
680+
setNewModuleNameModalInitialValue(currentModule.className + 'Copy');
681+
setNewModuleNameModalTitle(NewModuleNameModal.TITLE_COPY_MECHANISM);
682+
setNewModuleNameModalExample(NewModuleNameModal.EXAMPLE_MECHANISM);
683+
setNewModuleNameModalLabel(NewModuleNameModal.LABEL_MECHANISM);
668684
setNewModuleNameModalIsOpen(true);
669685
} else if (currentModule.moduleType == commonStorage.MODULE_TYPE_OPMODE) {
670686
// This is an OpMode.
671687
setNewModuleNameModalPurpose(PURPOSE_COPY_MODULE);
672-
setNewModuleNameModalInitialValue(currentModule.moduleName + '_copy');
673-
setNewModuleNameModalTitle('Copy OpMode');
688+
setNewModuleNameModalInitialValue(currentModule.className + 'Copy');
689+
setNewModuleNameModalTitle(NewModuleNameModal.TITLE_COPY_OPMODE);
690+
setNewModuleNameModalExample(NewModuleNameModal.EXAMPLE_OPMODE);
691+
setNewModuleNameModalLabel(NewModuleNameModal.LABEL_OPMODE);
674692
setNewModuleNameModalIsOpen(true);
675693
}
676694
});
@@ -1084,8 +1102,9 @@ const App: React.FC = () => {
10841102
</Splitter>
10851103
</Flex>
10861104

1087-
<NewProjectNameModal
1105+
<NewProjectNameModal.NewProjectNameModal
10881106
title={newProjectNameModalTitle}
1107+
message={newProjectNameModalMessage}
10891108
isOpen={newProjectNameModalIsOpen}
10901109
initialValue={newProjectNameModalInitialValue}
10911110
getProjectClassNames={getProjectClassNames}
@@ -1095,12 +1114,14 @@ const App: React.FC = () => {
10951114
}}
10961115
onCancel={() => setNewProjectNameModalIsOpen(false)}
10971116
/>
1098-
<NewModuleNameModal
1117+
<NewModuleNameModal.NewModuleNameModal
10991118
title={newModuleNameModalTitle}
1119+
example={newModuleNameModalExample}
1120+
label={newModuleNameModalLabel}
11001121
isOpen={newModuleNameModalIsOpen}
11011122
initialValue={newModuleNameModalInitialValue}
11021123
getCurrentProjectName={getCurrentProjectName}
1103-
getModuleNames={getModuleNames}
1124+
getModuleClassNames={getModuleClassNames}
11041125
onOk={(newName) => {
11051126
setNewModuleNameModalIsOpen(false);
11061127
handleNewModuleNameOk(newName);

src/modal/NewModuleNameModal.tsx

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,51 +34,72 @@ import type { InputRef } from 'antd';
3434
import * as commonStorage from '../storage/common_storage';
3535

3636

37-
export type NewModuleNameModalProps = {
37+
export const TITLE_NEW_MECHANISM = 'New Mechanism';
38+
export const TITLE_RENAME_MECHANISM = 'Rename Mechanism';
39+
export const TITLE_COPY_MECHANISM = 'Copy Mechanism';
40+
export const TITLE_NEW_OPMODE = 'New OpMode';
41+
export const TITLE_RENAME_OPMODE = 'Rename OpMode';
42+
export const TITLE_COPY_OPMODE = 'Copy OpMode';
43+
44+
const DESCRIPTION = 'No spaces are allowed in the name. Each word in the name should start with a capital letter.';
45+
46+
export const EXAMPLE_MECHANISM = 'For example, GamePieceShooter';
47+
export const EXAMPLE_OPMODE = 'For example, AutoParkAndShoot';
48+
export const LABEL_MECHANISM = 'Mechanism Name:';
49+
export const LABEL_OPMODE = 'OpMode Name:';
50+
51+
type NewModuleNameModalProps = {
3852
title: string;
53+
example: string;
54+
label: string;
3955
isOpen: boolean;
4056
initialValue: string;
4157
getCurrentProjectName: () => string;
42-
getModuleNames: (projectName: string) => string[];
58+
getModuleClassNames: (projectName: string) => string[];
4359
onOk: (newName: string) => void;
4460
onCancel: () => void;
4561
}
4662

47-
export const NewModuleNameModal: React.FC<NewModuleNameModalProps> = ({ title, isOpen, initialValue, getCurrentProjectName, getModuleNames, onOk, onCancel }) => {
63+
export const NewModuleNameModal: React.FC<NewModuleNameModalProps> = ({ title, example, label, isOpen, initialValue, getCurrentProjectName, getModuleClassNames, onOk, onCancel }) => {
4864
const inputRef = useRef<InputRef>(null);
4965
const [value, setValue] = useState('');
50-
const [projectName, setProjectName] = useState('');
51-
const [moduleNames, setModuleNames] = useState<string[]>([]);
66+
const [projectClassName, setProjectClassName] = useState('');
67+
const [moduleClassNames, setModuleClassNames] = useState<string[]>([]);
5268
const [alertErrorMessage, setAlertErrorMessage] = useState('');
5369
const [alertErrorVisible, setAlertErrorVisible] = useState(false);
5470

5571
const afterOpenChange = (open: boolean) => {
5672
if (open) {
5773
setValue(initialValue);
5874
const currentProjectName = getCurrentProjectName();
59-
setProjectName(currentProjectName);
60-
setModuleNames(getModuleNames(currentProjectName));
75+
setProjectClassName(commonStorage.moduleNameToClassName(currentProjectName));
76+
setModuleClassNames(getModuleClassNames(currentProjectName));
6177
if (inputRef.current) {
6278
inputRef.current.focus();
6379
}
6480
} else {
6581
setValue('');
82+
setAlertErrorVisible(false);
6683
}
6784
};
6885

86+
const onChange = (e) => {
87+
setValue(commonStorage.onChangeClassName(e.target.value));
88+
};
89+
6990
const handleOk = () => {
70-
if (!commonStorage.isValidPythonModuleName(value)) {
71-
setAlertErrorMessage(value + ' is not a valid blocks module name');
91+
if (!commonStorage.isValidClassName(value)) {
92+
setAlertErrorMessage(value + ' is not a valid name. Please enter a different name.');
7293
setAlertErrorVisible(true);
7394
return;
7495
}
75-
if (projectName === value) {
76-
setAlertErrorMessage('The project is already named ' + value);
96+
if (projectClassName === value) {
97+
setAlertErrorMessage('The project is already named ' + value + '. Please enter a different name.');
7798
setAlertErrorVisible(true);
7899
return;
79100
}
80-
if (moduleNames.includes(value)) {
81-
setAlertErrorMessage('Another module is already named ' + value);
101+
if (moduleClassNames.includes(value)) {
102+
setAlertErrorMessage('Another Mechanism or OpMode is already named ' + value + '. Please enter a different name.');
82103
setAlertErrorVisible(true);
83104
return;
84105
}
@@ -97,13 +118,17 @@ export const NewModuleNameModal: React.FC<NewModuleNameModalProps> = ({ title, i
97118
]}
98119
>
99120
<Flex vertical gap="small">
100-
<Typography.Paragraph> Name </Typography.Paragraph>
101-
<Input
102-
ref={inputRef}
103-
value={value}
104-
onPressEnter={handleOk}
105-
onChange={(e) => setValue(e.target.value.toLowerCase())}
106-
/>
121+
<Typography.Paragraph>{DESCRIPTION}</Typography.Paragraph>
122+
<Typography.Paragraph>{example}</Typography.Paragraph>
123+
<Flex vertical gap="0">
124+
<Typography.Paragraph>{label}</Typography.Paragraph>
125+
<Input
126+
ref={inputRef}
127+
value={value}
128+
onPressEnter={handleOk}
129+
onChange={onChange}
130+
/>
131+
</Flex>
107132
{alertErrorVisible && (
108133
<Alert
109134
type="error"

0 commit comments

Comments
 (0)