Skip to content

Commit 951693e

Browse files
committed
Store modules with double extension: .robot.json, .mechanism.json, .opmode.json.
Add getModuleType(modulePath) to names.ts.
1 parent e4a55c1 commit 951693e

File tree

3 files changed

+91
-17
lines changed

3 files changed

+91
-17
lines changed

src/storage/client_side_storage.ts

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import * as commonStorage from './common_storage';
2323
import * as storageModuleContent from './module_content';
24+
import * as storageNames from './names';
2425

2526
// Functions for saving blocks modules to client side storage.
2627

@@ -57,7 +58,62 @@ export async function openClientSideStorage(): Promise<commonStorage.Storage> {
5758
};
5859
openRequest.onsuccess = () => {
5960
const db = openRequest.result;
60-
resolve(ClientSideStorage.create(db));
61+
fixOldModules(db).then(() => {
62+
resolve(ClientSideStorage.create(db));
63+
})
64+
};
65+
});
66+
}
67+
68+
// The following function allows Alan and Liz to load older projects.
69+
// TODO(lizlooney): Remove this function.
70+
async function fixOldModules(db: IDBDatabase): Promise<void> {
71+
return new Promise((resolve, reject) => {
72+
const transaction = db.transaction([MODULES_STORE_NAME], 'readwrite');
73+
transaction.oncomplete = () => {
74+
resolve();
75+
};
76+
transaction.onabort = () => {
77+
console.log('IndexedDB transaction aborted.');
78+
reject(new Error('IndexedDB transaction aborted.'));
79+
};
80+
const modulesObjectStore = transaction.objectStore(MODULES_STORE_NAME);
81+
const openCursorRequest = modulesObjectStore.openCursor();
82+
openCursorRequest.onerror = () => {
83+
console.log('IndexedDB openCursor request failed. openCursorRequest.error is...');
84+
console.log(openCursorRequest.error);
85+
reject(new Error('IndexedDB openCursor request failed.'));
86+
};
87+
openCursorRequest.onsuccess = () => {
88+
const cursor = openCursorRequest.result;
89+
if (cursor) {
90+
const value = cursor.value;
91+
const regexForOldModulePath = new RegExp('^([A-Z][A-Za-z0-9]*)/([A-Z][A-Za-z0-9]*).json$');
92+
const result = regexForOldModulePath.exec(value.path);
93+
if (result) {
94+
const oldModulePath = value.path;
95+
const projectName = result[1];
96+
const className = result[2];
97+
const moduleType = storageModuleContent.parseModuleContentText(value.content).getModuleType();
98+
value.path = storageNames.makeModulePath(projectName, className, moduleType);
99+
const putRequest = modulesObjectStore.put(value);
100+
putRequest.onerror = () => {
101+
console.log('IndexedDB put request failed. putRequest.error is...');
102+
console.log(putRequest.error);
103+
throw new Error('IndexedDB put request failed.');
104+
};
105+
const deleteRequest = modulesObjectStore.delete(oldModulePath);
106+
deleteRequest.onerror = () => {
107+
console.log('IndexedDB delete request failed. deleteRequest.error is...');
108+
console.log(deleteRequest.error);
109+
throw new Error('IndexedDB delete request failed.');
110+
};
111+
}
112+
cursor.continue();
113+
} else {
114+
// The cursor is done. We have finished reading all the modules.
115+
resolve();
116+
}
61117
};
62118
});
63119
}
@@ -257,8 +313,6 @@ class ClientSideStorage implements commonStorage.Storage {
257313
console.log(deleteRequest.error);
258314
throw new Error('IndexedDB delete request failed.');
259315
};
260-
deleteRequest.onsuccess = () => {
261-
};
262316
});
263317
}
264318
}

src/storage/names.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,18 @@ export const CLASS_NAME_TELEOP = 'Teleop';
2828
export const JSON_FILE_EXTENSION = '.json';
2929
export const UPLOAD_DOWNLOAD_FILE_EXTENSION = '.blocks';
3030

31-
const REGEX_PROJECT_OR_CLASS_NAME_PART = '[A-Z][A-Za-z0-9]*';
32-
const REGEX_CLASS_NAME = '^' + REGEX_PROJECT_OR_CLASS_NAME_PART + '$';
33-
const REGEX_MODULE_PATH = '^(' + REGEX_PROJECT_OR_CLASS_NAME_PART + ')/(' +
34-
REGEX_PROJECT_OR_CLASS_NAME_PART + ')' + escapeRegExp(JSON_FILE_EXTENSION) + '$';
31+
const REGEX_PROJECT_NAME_PART = '[A-Z][A-Za-z0-9]*';
32+
const REGEX_CLASS_NAME_PART = '[A-Z][A-Za-z0-9]*';
33+
const REGEX_MODULE_TYPE = '\.(robot|mechanism|opmode)';
34+
const REGEX_MODULE_PATH = '^(' + REGEX_PROJECT_NAME_PART + ')/(' + REGEX_CLASS_NAME_PART + ')' +
35+
REGEX_MODULE_TYPE + escapeRegExp(JSON_FILE_EXTENSION) + '$';
3536

3637
/**
3738
* Returns true if the given name is a valid class name.
3839
*/
3940
export function isValidClassName(name: string): boolean {
4041
if (name) {
41-
return new RegExp(REGEX_CLASS_NAME).test(name);
42+
return new RegExp('^' + REGEX_CLASS_NAME_PART + '$').test(name);
4243
}
4344
return false;
4445
}
@@ -82,8 +83,8 @@ export function snakeCaseToPascalCase(snakeCaseName: string): string {
8283
* Returns the module path regex pattern for modules in the given project.
8384
*/
8485
export function makeModulePathRegexPattern(projectName: string): string {
85-
return '^' + escapeRegExp(projectName) + '/' + REGEX_PROJECT_OR_CLASS_NAME_PART +
86-
escapeRegExp(JSON_FILE_EXTENSION) + '$';
86+
return '^' + escapeRegExp(projectName) + '/' + REGEX_CLASS_NAME_PART +
87+
REGEX_MODULE_TYPE + escapeRegExp(JSON_FILE_EXTENSION) + '$';
8788
}
8889

8990
function escapeRegExp(text: string): string {
@@ -94,8 +95,8 @@ function escapeRegExp(text: string): string {
9495
* Returns the module path for the given project name and class name.
9596
*/
9697
export function makeModulePath(
97-
projectName: string, className: string, _moduleType: storageModule.ModuleType): string {
98-
return projectName + '/' + className + JSON_FILE_EXTENSION;
98+
projectName: string, className: string, moduleType: storageModule.ModuleType): string {
99+
return projectName + '/' + className + '.' + moduleType + JSON_FILE_EXTENSION;
99100
}
100101

101102
/**
@@ -129,6 +130,25 @@ export function getClassName(modulePath: string): string {
129130
return result[2];
130131
}
131132

133+
/**
134+
* Returns the module type for given module path.
135+
*/
136+
export function getModuleType(modulePath: string): storageModule.ModuleType {
137+
const regex = new RegExp(REGEX_MODULE_PATH);
138+
const result = regex.exec(modulePath)
139+
if (!result) {
140+
throw new Error('Unable to extract the module type from "' + modulePath + '"');
141+
}
142+
143+
const str = result[2];
144+
const moduleType = storageModule.ModuleType[str as keyof typeof storageModule.ModuleType];
145+
if (!Object.values(storageModule.ModuleType).includes(moduleType)) {
146+
throw new Error('Unable to extract the module type from "' + modulePath + '"');
147+
}
148+
149+
return moduleType;
150+
}
151+
132152
/**
133153
* Makes a unique name given a list of existing names
134154
*/

src/storage/project.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ export type Project = {
3838
export async function listProjects(storage: commonStorage.Storage): Promise<Project[]> {
3939
const pathToModuleContent = await storage.listModules();
4040

41-
const projects: {[key: string]: Project} = {}; // key is project name, value is Project
41+
const projects: {[projectName: string]: Project} = {};
4242
// The mechanisms and opModes variables hold any Mechanisms and OpModes that
43-
// are read before the Project to which they belong is read.
44-
const mechanisms: {[key: string]: storageModule.Mechanism[]} = {}; // key is project name, value is list of Mechanisms
45-
const opModes: {[key: string]: storageModule.OpMode[]} = {}; // key is project name, value is list of OpModes
43+
// are read before the Robot of the Project to which they belong is read.
44+
const mechanisms: {[projectName: string]: storageModule.Mechanism[]} = {};
45+
const opModes: {[projectName: string]: storageModule.OpMode[]} = {};
4646

4747
for (const modulePath in pathToModuleContent) {
4848
const moduleContent = pathToModuleContent[modulePath];
49-
const moduleType = moduleContent.getModuleType();
49+
const moduleType = storageNames.getModuleType(modulePath);
5050
const dateModifiedMillis = await storage.fetchModuleDateModifiedMillis(modulePath);
5151
const module: storageModule.Module = {
5252
modulePath: modulePath,

0 commit comments

Comments
 (0)