responding to comments / clean up

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman committed 2021-10-27 11:32:39 +03:00
1 parent a33165044e
commit a02538999a
6 files changed
+38 -53

No files matched your search

@@ -24,16 +24,14 @@ import glob from "glob";
import path from "path";
import os from "os";
import { promisify } from "util";
import { action, makeObservable, observable } from "mobx";
import { action, makeObservable, observable, ObservableMap } from "mobx";
import logger from "../../../common/logger";
import { DockTabStore } from "./dock-tab.store";
import { dockStore, DockTabCreateSpecific, TabKind } from "./dock.store";
export interface TemplatesGroup {
label: string;
templates: {
[filepath: string]: string; // filepath is relative to templates folder
};
templates: ObservableMap<string/*filepath*/, string>;
}
export class CreateResourceStore extends DockTabStore<string> {
@@ -42,16 +40,16 @@ export class CreateResourceStore extends DockTabStore<string> {
makeObservable(this);
}
readonly templateGroups: Record<string, TemplatesGroup> = observable({
readonly templateGroups: Record<string, TemplatesGroup> = {
[this.appTemplatesFolder]: {
label: "Lens Templates",
templates: {},
templates: observable.map(),
},
[this.userTemplatesFolder]: {
label: "Custom templates",
templates: {},
templates: observable.map(),
},
});
};
get appTemplatesFolder(): string {
// production: declare files to copy in "package.json" -> "build.extraResources"
@@ -80,9 +78,7 @@ export class CreateResourceStore extends DockTabStore<string> {
await fs.ensureDir(sourceFolder);
const files = await promisify(glob)("**/*.@(yaml|yml|json)", { cwd: sourceFolder });
templatesGroup.templates = Object.fromEntries(
files.map(filePath => [filePath, "" /* empty: content not loaded yet */])
);
templatesGroup.templates.replace(files.map(filePath => [filePath, "" /*content*/]));
} catch (error) {
logger.error(`[CREATE-RESOURCE]: scanning template folders error: ${error}`);
}
@@ -98,9 +94,11 @@ export class CreateResourceStore extends DockTabStore<string> {
return ""; // unknown group, exit
}
const template = templatesGroup.templates[filePath];
const template = templatesGroup.templates.get(filePath);
if (template) return template; // return cache, preloaded already
if (template) {
return template; // return cache, preloaded already
}
try {
const templatePath = path.resolve(sourceFolder, filePath);
@@ -110,7 +108,7 @@ export class CreateResourceStore extends DockTabStore<string> {
const textContent = await fs.readFile(templatePath, { encoding: "utf-8" });
templatesGroup.templates[filePath] = textContent; // save cache
templatesGroup.templates.set(filePath, textContent); // save cache
return textContent;
} catch (error) {
@@ -41,7 +41,6 @@ type SelectOptionTemplate = SelectOption<SelectOptionTemplateValue>;
interface SelectOptionTemplateValue {
sourceFolder: string;
filePath: string; // relative to `sourceFolder`
content?: string; // available after loading (template selection)
}
@observer
@@ -115,11 +114,10 @@ export class CreateResource extends React.Component<Props> {
return Object.entries(createResourceStore.templateGroups).map(([sourceFolder, group]) => {
return {
label: group.label,
options: Object.entries(group.templates).map(([filePath, content]) => {
options: Array.from(group.templates.keys()).map(filePath => {
return {
label: filePath,
value: { filePath, sourceFolder },
content,
};
}),
};
@@ -127,8 +125,8 @@ export class CreateResource extends React.Component<Props> {
}
onSelectTemplate = async ({ value }: SelectOptionTemplate) => {
const { filePath, sourceFolder, content } = value;
const templateContent = content ?? await createResourceStore.loadTemplate({ filePath, sourceFolder });
const { filePath, sourceFolder } = value;
const templateContent = await createResourceStore.loadTemplate({ filePath, sourceFolder });
createResourceStore.setData(this.tabId, templateContent); // update draft
};
+4 -4
View File
@@ -89,8 +89,8 @@ export interface DockStorageState {
}
export interface DockTabChangeEvent {
tabId?: TabId;
tab?: DockTab;
tab: DockTab;
tabId: TabId;
prevTab?: DockTab;
}
@@ -212,11 +212,11 @@ export class DockStore implements DockStorageState {
});
}
onTabChange(callback?: (evt: DockTabChangeEvent) => void, options: DockTabChangeEventOptions = {}) {
onTabChange(callback: (evt: DockTabChangeEvent) => void, options: DockTabChangeEventOptions = {}) {
const { tabKind, dockIsVisible = true, ...reactionOpts } = options;
return reaction(() => this.selectedTab, ((tab, prevTab) => {
if (!tab) return; // skip
if (!tab) return; // skip when dock is empty
if (tabKind && tabKind !== tab.kind) return; // handle specific tab.kind only
if (dockIsVisible && !this.isOpen) return;
@@ -26,7 +26,7 @@ import { observer } from "mobx-react";
import { editor, Uri } from "monaco-editor";
import { MonacoTheme, registerCustomThemes } from "./monaco-themes";
import { MonacoValidator, monacoValidators } from "./monaco-validators";
import { cssNames, disposer, toJS } from "../../utils";
import { cssNames, disposer, noop, toJS } from "../../utils";
import { UserStore } from "../../../common/user-store";
import { ThemeStore } from "../../theme.store";
import debounce from "lodash/debounce";
@@ -71,6 +71,10 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
public staticId = `editor-id#${Math.round(1e7 * Math.random())}`;
public dispose = disposer();
// TODO: investigate why replacing console.* to common/logger.* calls leads for stucking UI / infinite loop..
// e.g. happens on tab change/create, maybe some other cases too.
logger = { info: noop, error: noop } as Console;
@observable.ref containerElem: HTMLElement;
@observable.ref editor: editor.IStandaloneCodeEditor;
@observable dimensions: { width?: number, height?: number } = {};
@@ -121,10 +125,8 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
return () => resizeObserver.unobserve(containerElem);
}
// TODO: investigate why replacing console.* to common logger.* calls in a file leads for stucking UI / infinite loop.
// e.g. happens on tab change/create, maybe some other cases
onModelChange = (model: editor.ITextModel, oldModel?: editor.ITextModel) => {
console.info("[MONACO]: model change", { model, oldModel });
this.logger.info("[MONACO]: model change", { model, oldModel });
this.saveViewState(oldModel);
this.editor.setModel(model);
@@ -157,9 +159,9 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
componentDidMount() {
try {
this.createEditor();
console.info(`[MONACO]: editor did mount`);
this.logger.info(`[MONACO]: editor did mount`);
} catch (error) {
console.error(`[MONACO]: mounting failed: ${error}`, this);
this.logger.error(`[MONACO]: mounting failed: ${error}`, this);
}
}
@@ -185,7 +187,7 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
...this.options,
});
console.info(`[MONACO]: editor created for language=${language}, theme=${theme}`);
this.logger.info(`[MONACO]: editor created for language=${language}, theme=${theme}`);
this.validateLazy(); // validate initial value
this.restoreViewState(); // restore previous state if any
@@ -231,7 +233,6 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
@action
setDimensions(width: number, height: number) {
console.info(`[MONACO]: refreshing dimensions to width=${width} and height=${height}`);
this.dimensions.width = width;
this.dimensions.height = height;
this.editor?.layout({ width, height });
@@ -31,7 +31,7 @@ export interface MonacoThemeData extends editor.IStandaloneThemeData {
}
// Registered names could be then used in "themes/*.json" in "{monacoTheme: [name]}"
export const customThemes: Partial<Record<MonacoTheme, MonacoThemeData>> = {
export const customThemes: Partial<Record<MonacoCustomTheme, MonacoThemeData>> = {
"clouds-midnight": cloudsMidnight as MonacoThemeData,
};
+9 -21
View File
@@ -23,15 +23,14 @@ import { computed, makeObservable, observable, reaction } from "mobx";
import { autoBind, Singleton } from "./utils";
import { UserStore } from "../common/user-store";
import logger from "../main/logger";
import lensDarkTheme from "./themes/lens-dark.json";
import lensLightTheme from "./themes/lens-light.json";
import lensDarkThemeJson from "./themes/lens-dark.json";
import lensLightThemeJson from "./themes/lens-light.json";
import type { SelectOption } from "./components/select";
import type { MonacoEditorProps } from "./components/monaco-editor";
export type ThemeId = string;
export interface Theme {
id?: ThemeId;
name: string;
type: "dark" | "light";
colors: Record<string, string>;
@@ -45,34 +44,23 @@ export class ThemeStore extends Singleton {
protected styles: HTMLStyleElement;
// bundled themes from `themes/${themeId}.json`
private allThemes = observable.map<string, Theme>({
"lens-dark": lensDarkTheme as Theme,
"lens-light": lensLightTheme as Theme,
private themes = observable.map<ThemeId, Theme>({
"lens-dark": lensDarkThemeJson as Theme,
"lens-light": lensLightThemeJson as Theme,
});
@computed get themes() {
return Array.from(this.allThemes.entries()).map(([themeId, themeOriginal]) => {
const theme: Required<Theme> = {
id: themeId, // take id from map's key
...themeOriginal,
};
return theme;
});
}
@computed get activeThemeId(): string {
return UserStore.getInstance().colorTheme;
}
@computed get activeTheme(): Theme {
return this.allThemes.get(this.activeThemeId) ?? this.allThemes.get(ThemeStore.defaultTheme);
return this.themes.get(this.activeThemeId) ?? this.themes.get(ThemeStore.defaultTheme);
}
@computed get themeOptions(): SelectOption<string>[] {
return this.themes.map(theme => ({
return Array.from(this.themes).map(([themeId, theme]) => ({
label: theme.name,
value: theme.id,
value: themeId,
}));
}
@@ -96,7 +84,7 @@ export class ThemeStore extends Singleton {
}
getThemeById(themeId: ThemeId): Theme {
return this.allThemes.get(themeId);
return this.themes.get(themeId);
}
protected applyTheme(theme: Theme) {