YAML Templates in Create Resource dock tab (#2327)

Co-authored-by: Pavel Ashevskiy <pavel.ashevskiy@ifellow.ru>
This commit is contained in:
pashevskiiandPavel Ashevskiy authored and GitHub committed 2021-04-15 08:19:54 -04:00
1 parent 1ac5588fab
commit ec9c47752f
23 files changed
+673 -3

No files matched your search

@@ -1,2 +1,2 @@
.CreateResource {
}
}
@@ -1,13 +1,61 @@
import fs from "fs-extra";
import path from "path";
import os from "os";
import groupBy from "lodash/groupBy";
import filehound from "filehound";
import { watch } from "chokidar";
import { autobind } from "../../utils";
import { DockTabStore } from "./dock-tab.store";
import { dockStore, IDockTab, TabKind } from "./dock.store";
@autobind()
export class CreateResourceStore extends DockTabStore<string> {
constructor() {
super({
storageKey: "create_resource"
});
fs.ensureDirSync(this.userTemplatesFolder);
}
get lensTemplatesFolder():string {
return path.resolve(__static, "../templates/create-resource");
}
get userTemplatesFolder():string {
return path.join(os.homedir(), ".k8slens", "templates");
}
async getTemplates(templatesPath: string, defaultGroup: string) {
const templates = await filehound.create().path(templatesPath).ext(["yaml", "json"]).depth(1).find();
return templates ? this.groupTemplates(templates, templatesPath, defaultGroup) : {};
}
groupTemplates(templates: string[], templatesPath: string, defaultGroup: string) {
return groupBy(templates,(v:string) =>
path.relative(templatesPath,v).split(path.sep).length>1
? path.parse(path.relative(templatesPath,v)).dir
: defaultGroup);
}
async getMergedTemplates() {
const userTemplates = await this.getTemplates(this.userTemplatesFolder, "ungrouped");
const lensTemplates = await this.getTemplates(this.lensTemplatesFolder, "lens");
return {...userTemplates,...lensTemplates};
}
async watchUserTemplates(callback: ()=> void){
watch(this.userTemplatesFolder, {
depth: 1,
ignoreInitial: true,
awaitWriteFinish: {
stabilityThreshold: 500
}
}).on("all", () => {
callback();
});
}
}
@@ -1,6 +1,9 @@
import "./create-resource.scss";
import React from "react";
import path from "path";
import fs from "fs-extra";
import {Select, GroupSelectOption, SelectOption} from "../select";
import jsYaml from "js-yaml";
import { observable } from "mobx";
import { observer } from "mobx-react";
@@ -20,7 +23,25 @@ interface Props {
@observer
export class CreateResource extends React.Component<Props> {
@observable currentTemplates:Map<string,SelectOption> = new Map();
@observable error = "";
@observable templates:GroupSelectOption<SelectOption>[] = [];
componentDidMount() {
createResourceStore.getMergedTemplates().then(v => this.updateGroupSelectOptions(v));
createResourceStore.watchUserTemplates(() => createResourceStore.getMergedTemplates().then(v => this.updateGroupSelectOptions(v)));
}
updateGroupSelectOptions(templates :Record<string, string[]>) {
this.templates = Object.entries(templates)
.map(([name, grouping]) => this.convertToGroup(name, grouping));
}
convertToGroup(group:string, items:string[]):GroupSelectOption {
const options = items.map(v => ({label: path.parse(v).name, value: v}));
return {label: group, options};
}
get tabId() {
return this.props.tab.id;
@@ -30,11 +51,20 @@ export class CreateResource extends React.Component<Props> {
return createResourceStore.getData(this.tabId);
}
get currentTemplate() {
return this.currentTemplates.get(this.tabId) ?? null;
}
onChange = (value: string, error?: string) => {
createResourceStore.setData(this.tabId, value);
this.error = error;
};
onSelectTemplate = (item: SelectOption) => {
this.currentTemplates.set(this.tabId, item);
fs.readFile(item.value,"utf8").then(v => createResourceStore.setData(this.tabId,v));
};
create = async () => {
if (this.error) return;
if (!this.data.trim()) return; // do not save when field is empty
@@ -67,6 +97,24 @@ export class CreateResource extends React.Component<Props> {
return successMessage;
};
renderControls(){
return (
<div className="flex gaps align-center">
<Select
autoConvertOptions = {false}
className="TemplateSelect"
placeholder="Select Template ..."
options={this.templates}
menuPlacement="top"
themeName="outlined"
onChange={v => this.onSelectTemplate(v)}
value = {this.currentTemplate}
/>
</div>
);
}
render() {
const { tabId, data, error, create, onChange } = this;
const { className } = this.props;
@@ -76,6 +124,7 @@ export class CreateResource extends React.Component<Props> {
<InfoPanel
tabId={tabId}
error={error}
controls={this.renderControls()}
submit={create}
submitLabel="Create"
showNotifications={false}