mirror of
https://github.com/logos-storage/logos-storage-installer.git
synced 2026-01-05 06:53:06 +00:00
195 lines
4.9 KiB
JavaScript
195 lines
4.9 KiB
JavaScript
export class PathSelector {
|
|
constructor(uiService, menuLoop, fsService) {
|
|
this.ui = uiService;
|
|
this.loop = menuLoop;
|
|
this.fs = fsService;
|
|
|
|
this.pathMustExist = true;
|
|
this.loop.initialize(this.showPathSelector);
|
|
}
|
|
|
|
show = async (startingPath, pathMustExist) => {
|
|
this.startingPath = startingPath;
|
|
this.pathMustExist = pathMustExist;
|
|
this.roots = this.fs.getAvailableRoots();
|
|
this.currentPath = this.splitPath(startingPath);
|
|
if (!this.hasValidRoot(this.currentPath)) {
|
|
this.currentPath = [this.roots[0]];
|
|
}
|
|
|
|
await this.loop.showLoop();
|
|
|
|
return this.resultingPath;
|
|
};
|
|
|
|
showPathSelector = async () => {
|
|
this.showCurrent();
|
|
await this.ui.askMultipleChoice("Select an option:", [
|
|
{
|
|
label: "Enter path",
|
|
action: this.enterPath,
|
|
},
|
|
{
|
|
label: "Go up one",
|
|
action: this.upOne,
|
|
},
|
|
{
|
|
label: "Go down one",
|
|
action: this.downOne,
|
|
},
|
|
{
|
|
label: "Create new folder here",
|
|
action: this.createSubDir,
|
|
},
|
|
{
|
|
label: "Select this path",
|
|
action: this.selectThisPath,
|
|
},
|
|
{
|
|
label: "Cancel",
|
|
action: this.cancel,
|
|
},
|
|
]);
|
|
};
|
|
|
|
splitPath = (str) => {
|
|
var result = this.dropEmptyParts(str.replaceAll("\\", "/").split("/"));
|
|
if (str.startsWith("/") && this.roots.includes("/")) {
|
|
result = ["/", ...result];
|
|
}
|
|
return result;
|
|
};
|
|
|
|
dropEmptyParts = (parts) => {
|
|
return parts.filter((part) => part.length > 0);
|
|
};
|
|
|
|
combine = (parts) => {
|
|
const toJoin = this.dropEmptyParts(parts);
|
|
if (toJoin.length == 1) return toJoin[0];
|
|
var result = this.fs.pathJoin(toJoin);
|
|
if (result.startsWith("//")) {
|
|
result = result.substring(1);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
combineWith = (parts, extra) => {
|
|
const toJoin = this.dropEmptyParts(parts);
|
|
if (toJoin.length == 1) return this.fs.pathJoin([toJoin[0], extra]);
|
|
return this.fs.pathJoin([...toJoin, extra]);
|
|
};
|
|
|
|
showCurrent = () => {
|
|
const len = this.currentPath.length;
|
|
this.ui.showInfoMessage(
|
|
`Current path: [${len}]\n` + this.combine(this.currentPath),
|
|
);
|
|
|
|
if (len < 2) {
|
|
this.ui.showInfoMessage(
|
|
"Warning - Known issue:\n" +
|
|
"Path selection does not work in root paths on some platforms.\n" +
|
|
'Use "Enter path" or "Create new folder" to navigate and create folders\n' +
|
|
"if this is the case for you.",
|
|
);
|
|
}
|
|
};
|
|
|
|
hasValidRoot = (checkPath) => {
|
|
if (checkPath.length < 1) return false;
|
|
var result = false;
|
|
this.roots.forEach(function (root) {
|
|
if (root.toLowerCase() == checkPath[0].toLowerCase()) {
|
|
result = true;
|
|
}
|
|
});
|
|
return result;
|
|
};
|
|
|
|
updateCurrentIfValidFull = (newFullPath) => {
|
|
if (this.pathMustExist && !this.fs.isDir(newFullPath)) {
|
|
this.ui.showErrorMessage("The path does not exist.");
|
|
return;
|
|
}
|
|
this.updateCurrentIfValidParts(this.splitPath(newFullPath));
|
|
};
|
|
|
|
updateCurrentIfValidParts = (newParts) => {
|
|
if (!this.hasValidRoot(newParts)) {
|
|
this.ui.showErrorMessage("The path has no valid root.");
|
|
return;
|
|
}
|
|
this.currentPath = newParts;
|
|
};
|
|
|
|
enterPath = async () => {
|
|
const newPath = await this.ui.askPrompt("Enter Path:");
|
|
this.updateCurrentIfValidFull(newPath);
|
|
};
|
|
|
|
upOne = () => {
|
|
const newParts = this.currentPath.slice(0, this.currentPath.length - 1);
|
|
this.updateCurrentIfValidParts(newParts);
|
|
};
|
|
|
|
isSubDir = (entry) => {
|
|
const newPath = this.combineWith(this.currentPath, entry);
|
|
return this.fs.isDir(newPath);
|
|
};
|
|
|
|
getSubDirOptions = () => {
|
|
const fullPath = this.combine(this.currentPath);
|
|
try {
|
|
const entries = this.fs.readDir(fullPath);
|
|
return entries.filter((entry) => this.isSubDir(entry));
|
|
} catch {
|
|
return [];
|
|
}
|
|
};
|
|
|
|
downOne = async () => {
|
|
const options = this.getSubDirOptions();
|
|
if (options.length == 0) {
|
|
this.ui.showInfoMessage("There are no subdirectories here.");
|
|
return;
|
|
}
|
|
|
|
var selected = "";
|
|
var uiOptions = [];
|
|
options.forEach(function (option) {
|
|
uiOptions.push({
|
|
label: option,
|
|
action: () => {
|
|
selected = option;
|
|
},
|
|
});
|
|
});
|
|
|
|
await this.ui.askMultipleChoice("Select an subdir", uiOptions);
|
|
|
|
if (selected.length < 1) return;
|
|
this.updateCurrentIfValidParts([...this.currentPath, selected]);
|
|
};
|
|
|
|
createSubDir = async () => {
|
|
const name = await this.ui.askPrompt("Enter name:");
|
|
if (name.length < 1) return;
|
|
const newPath = [...this.currentPath, name];
|
|
if (this.pathMustExist) {
|
|
this.fs.makeDir(this.combine(newPath));
|
|
}
|
|
this.updateCurrentIfValidParts(newPath);
|
|
};
|
|
|
|
selectThisPath = async () => {
|
|
this.resultingPath = this.combine(this.currentPath);
|
|
this.loop.stopLoop();
|
|
};
|
|
|
|
cancel = async () => {
|
|
this.resultingPath = this.startingPath;
|
|
this.loop.stopLoop();
|
|
};
|
|
}
|