drag & drop renewed, imageCropper revisited, imageOrder persisted, css quirks
This commit is contained in:
193
crawler/filechooser.ts
Normal file
193
crawler/filechooser.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
// import { prompt, Question} from 'inquirer';
|
||||
import inquirer from 'inquirer';
|
||||
import chalk from 'chalk';
|
||||
|
||||
|
||||
const COMPLETED = 'SELECTION_COMPLETED';
|
||||
const CANCELLED = 'SELECTION_CANCELLED';
|
||||
const CHECKMARK = '\u2713';
|
||||
|
||||
class FilesSystemService {
|
||||
directories(directoryPath, directoryFilter ?: (joinedPath) => true) {
|
||||
return fs.readdirSync(directoryPath).filter((name) => {
|
||||
const joinedPath = path.join(directoryPath, name);
|
||||
return this.isDirectory(joinedPath) && directoryFilter(joinedPath);
|
||||
});
|
||||
}
|
||||
|
||||
files(directoryPath, fileFilter = (joinedPath) => true) {
|
||||
return fs.readdirSync(directoryPath).filter((name) => {
|
||||
const joinedPath = path.join(directoryPath, name);
|
||||
return this.isFile(joinedPath) && fileFilter(joinedPath);
|
||||
});
|
||||
}
|
||||
|
||||
isDirectory(directoryPath) {
|
||||
return fs.statSync(directoryPath).isDirectory();
|
||||
}
|
||||
|
||||
isFile(filePath) {
|
||||
return fs.statSync(filePath).isFile();
|
||||
}
|
||||
}
|
||||
|
||||
class FilesSelectionService extends Set {
|
||||
lastFileSelected = null;
|
||||
constructor(selectedFiles) {
|
||||
super(selectedFiles);
|
||||
}
|
||||
|
||||
get selectedFiles() {
|
||||
return Array.from(this);
|
||||
}
|
||||
|
||||
isSelected(file) {
|
||||
return this.has(file);
|
||||
}
|
||||
|
||||
selectFile(file) {
|
||||
this.add(file);
|
||||
this.lastFileSelected = file;
|
||||
}
|
||||
|
||||
removeFile(file) {
|
||||
this.delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
class LocationService {
|
||||
constructor(public currentPath) {
|
||||
this.currentPath = currentPath;
|
||||
}
|
||||
}
|
||||
|
||||
class OptionsService {
|
||||
constructor(public options) {
|
||||
this.options = { ...this.defaultOptions, ...options };
|
||||
}
|
||||
|
||||
get defaultOptions() {
|
||||
return {
|
||||
directoryFilter: () => true,
|
||||
fileFilter: () => true,
|
||||
root: process.cwd(),
|
||||
startingPath: process.cwd(),
|
||||
multi: true,
|
||||
pageSize: 10,
|
||||
selectedFiles: [],
|
||||
clearConsole: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const selectFiles = function (options = {}) {
|
||||
const optionsService = new OptionsService(options);
|
||||
const locationService = new LocationService(
|
||||
optionsService.options.startingPath
|
||||
);
|
||||
const fileSystemService = new FilesSystemService();
|
||||
const filesSelectionService = new FilesSelectionService(
|
||||
optionsService.options.selectedFiles
|
||||
);
|
||||
|
||||
return new Promise((resolve):FCResult|void => {
|
||||
(async function promptUserToSelectFiles() {
|
||||
const directories = fileSystemService.directories(
|
||||
locationService.currentPath,
|
||||
optionsService.options.directoryFilter
|
||||
);
|
||||
|
||||
if (locationService.currentPath !== optionsService.options.root) {
|
||||
directories.unshift('..');
|
||||
}
|
||||
|
||||
const files = fileSystemService.files(
|
||||
locationService.currentPath,
|
||||
optionsService.options.fileFilter
|
||||
);
|
||||
|
||||
const choices = [
|
||||
...directories.map((directoryName) => {
|
||||
const value = path.join(locationService.currentPath, directoryName);
|
||||
const name = chalk.yellow(directoryName);
|
||||
return { value, name };
|
||||
}),
|
||||
...files.map((fileName) => {
|
||||
const value = path.join(locationService.currentPath, fileName);
|
||||
const name = `${fileName} ${
|
||||
filesSelectionService.isSelected(value)
|
||||
? chalk.green(CHECKMARK)
|
||||
: ''
|
||||
}`;
|
||||
return { value, name };
|
||||
}),
|
||||
];
|
||||
|
||||
if (filesSelectionService.selectedFiles.length) {
|
||||
choices.push({
|
||||
name: chalk.green('-- File Selection Complete --'),
|
||||
value: COMPLETED,
|
||||
});
|
||||
}
|
||||
|
||||
choices.push({
|
||||
name: chalk.red('-- Cancel File Selection --'),
|
||||
value: CANCELLED,
|
||||
});
|
||||
|
||||
if (optionsService.options.clearConsole) {
|
||||
console.clear();
|
||||
}
|
||||
|
||||
const { selection } = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
message: `Select file(s) in ${locationService.currentPath}`,
|
||||
name: 'selection',
|
||||
pageSize: optionsService.options.pageSize,
|
||||
choices,
|
||||
default: () => filesSelectionService.lastFileSelected,
|
||||
},
|
||||
]);
|
||||
|
||||
if (optionsService.options.clearConsole) {
|
||||
console.clear();
|
||||
}
|
||||
|
||||
if (selection === COMPLETED || selection === CANCELLED) {
|
||||
return resolve({
|
||||
selectedFiles: filesSelectionService.selectedFiles,
|
||||
status: selection,
|
||||
});
|
||||
} else if (!optionsService.options.multi) {
|
||||
return resolve({
|
||||
selectedFiles: [selection],
|
||||
status: COMPLETED,
|
||||
});
|
||||
}
|
||||
|
||||
if (fileSystemService.isDirectory(selection)) {
|
||||
locationService.currentPath = selection;
|
||||
} else {
|
||||
if (filesSelectionService.isSelected(selection)) {
|
||||
filesSelectionService.removeFile(selection);
|
||||
} else {
|
||||
filesSelectionService.selectFile(selection);
|
||||
}
|
||||
}
|
||||
|
||||
promptUserToSelectFiles();
|
||||
})();
|
||||
});
|
||||
};
|
||||
export type FCResult = {
|
||||
selectedFiles:Array<string>
|
||||
status:'SELECTION_COMPLETED'|'SELECTION_CANCELLED'
|
||||
}
|
||||
// const exports = {
|
||||
// COMPLETED,
|
||||
// CANCELLED,
|
||||
// selectFiles,
|
||||
// };
|
||||
Reference in New Issue
Block a user