mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Allow to install packed extensions from URL or local file (#1456)
* Option to install an extension from filesystem/url #1227 -- part 1 (UI) Signed-off-by: Roman <ixrock@gmail.com> * DropFileInput: common component to handle droped files (replaced also in add-cluster-page) Signed-off-by: Roman <ixrock@gmail.com> * fix: install via url-string on input.submit Signed-off-by: Roman <ixrock@gmail.com> * ui tweaks & minor fixes Signed-off-by: Roman <ixrock@gmail.com> * more ui/ux tweaks & fixes Signed-off-by: Roman <ixrock@gmail.com> * layout fixes Signed-off-by: Roman <ixrock@gmail.com> * component renaming: `copy-to-click` => `copy-to-clipboard` => `clipboard` Signed-off-by: Roman <ixrock@gmail.com> * reworks -- part 1 Signed-off-by: Roman <ixrock@gmail.com> * fix downloading file, added common/utils/downloadFile Signed-off-by: Roman <ixrock@gmail.com> * confirm before install, unpack tar first steps Signed-off-by: Roman <ixrock@gmail.com> * installation flow, extracting .tgz Signed-off-by: Roman <ixrock@gmail.com> * clean up, fix lint issues Signed-off-by: Roman <ixrock@gmail.com> * update .azure-pipelines.yml Signed-off-by: Roman <ixrock@gmail.com> * fixes & refactoring Signed-off-by: Roman <ixrock@gmail.com> * fix lint harder :/ Signed-off-by: Roman <ixrock@gmail.com> * fix validation Signed-off-by: Roman <ixrock@gmail.com> * fix validation harder Signed-off-by: Roman <ixrock@gmail.com> * responding to comments, fixed package validation Signed-off-by: Roman <ixrock@gmail.com> * common/utils/tar.ts: reject with Error-type Signed-off-by: Roman <ixrock@gmail.com> * fix: unit-tests Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
1 parent
2da598b66e
commit
77ae31550a
36 files changed
+799
-193
No files matched your search
@@ -1,12 +1,4 @@
|
||||
.AddCluster {
|
||||
.droppable {
|
||||
box-shadow: 0 0 0 5px inset $primary;
|
||||
|
||||
> * {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.hint {
|
||||
margin-top: -$padding;
|
||||
color: $textColorSecondary;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { KubeConfig } from "@kubernetes/client-node";
|
||||
import { _i18n } from "../../i18n";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { Select, SelectOption } from "../select";
|
||||
import { Input } from "../input";
|
||||
import { DropFileInput, Input } from "../input";
|
||||
import { AceEditor } from "../ace-editor";
|
||||
import { Button } from "../button";
|
||||
import { Icon } from "../icon";
|
||||
@@ -44,7 +44,6 @@ export class AddCluster extends React.Component {
|
||||
@observable proxyServer = "";
|
||||
@observable isWaiting = false;
|
||||
@observable showSettings = false;
|
||||
@observable dropAreaActive = false;
|
||||
|
||||
componentDidMount() {
|
||||
clusterStore.setActive(null);
|
||||
@@ -121,6 +120,11 @@ export class AddCluster extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
onDropKubeConfig = (files: File[]) => {
|
||||
this.sourceTab = KubeConfigSourceTab.FILE;
|
||||
this.setKubeConfig(files[0].path);
|
||||
};
|
||||
|
||||
@action
|
||||
addClusters = () => {
|
||||
let newClusters: ClusterModel[] = [];
|
||||
@@ -139,7 +143,7 @@ export class AddCluster extends React.Component {
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.error = String(err.message);
|
||||
if (err instanceof ExecValidationNotFoundError ) {
|
||||
if (err instanceof ExecValidationNotFoundError) {
|
||||
Notifications.error(<Trans>Error while adding cluster(s): {this.error}</Trans>);
|
||||
return false;
|
||||
} else {
|
||||
@@ -230,7 +234,7 @@ export class AddCluster extends React.Component {
|
||||
<Tab
|
||||
value={KubeConfigSourceTab.FILE}
|
||||
label={<Trans>Select kubeconfig file</Trans>}
|
||||
active={this.sourceTab == KubeConfigSourceTab.FILE} />
|
||||
active={this.sourceTab == KubeConfigSourceTab.FILE}/>
|
||||
<Tab
|
||||
value={KubeConfigSourceTab.TEXT}
|
||||
label={<Trans>Paste as text</Trans>}
|
||||
@@ -344,71 +348,55 @@ export class AddCluster extends React.Component {
|
||||
return (
|
||||
<div className={cssNames("kube-context flex gaps align-center", context)}>
|
||||
<span>{context}</span>
|
||||
{isNew && <Icon small material="fiber_new" />}
|
||||
{isSelected && <Icon small material="check" className="box right" />}
|
||||
{isNew && <Icon small material="fiber_new"/>}
|
||||
{isSelected && <Icon small material="check" className="box right"/>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const addDisabled = this.selectedContexts.length === 0;
|
||||
|
||||
return (
|
||||
<WizardLayout
|
||||
className="AddCluster"
|
||||
infoPanel={this.renderInfo()}
|
||||
contentClass={{ droppable: this.dropAreaActive }}
|
||||
contentProps={{
|
||||
onDragEnter: event => this.dropAreaActive = true,
|
||||
onDragLeave: event => this.dropAreaActive = false,
|
||||
onDragOver: event => {
|
||||
event.preventDefault(); // enable onDrop()-callback
|
||||
event.dataTransfer.dropEffect = "move";
|
||||
},
|
||||
onDrop: event => {
|
||||
this.sourceTab = KubeConfigSourceTab.FILE;
|
||||
this.dropAreaActive = false;
|
||||
this.setKubeConfig(event.dataTransfer.files[0].path);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<h2><Trans>Add Cluster</Trans></h2>
|
||||
{this.renderKubeConfigSource()}
|
||||
{this.renderContextSelector()}
|
||||
<div className="cluster-settings">
|
||||
<a href="#" onClick={() => this.showSettings = !this.showSettings}>
|
||||
<Trans>Proxy settings</Trans>
|
||||
</a>
|
||||
</div>
|
||||
{this.showSettings && (
|
||||
<div className="proxy-settings">
|
||||
<p>HTTP Proxy server. Used for communicating with Kubernetes API.</p>
|
||||
<Input
|
||||
autoFocus
|
||||
value={this.proxyServer}
|
||||
onChange={value => this.proxyServer = value}
|
||||
theme="round-black"
|
||||
/>
|
||||
<small className="hint">
|
||||
{'A HTTP proxy server URL (format: http://<address>:<port>).'}
|
||||
</small>
|
||||
<DropFileInput onDropFiles={this.onDropKubeConfig}>
|
||||
<WizardLayout className="AddCluster" infoPanel={this.renderInfo()}>
|
||||
<h2><Trans>Add Cluster</Trans></h2>
|
||||
{this.renderKubeConfigSource()}
|
||||
{this.renderContextSelector()}
|
||||
<div className="cluster-settings">
|
||||
<a href="#" onClick={() => this.showSettings = !this.showSettings}>
|
||||
<Trans>Proxy settings</Trans>
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
{this.error && (
|
||||
<div className="error">{this.error}</div>
|
||||
)}
|
||||
<div className="actions-panel">
|
||||
<Button
|
||||
primary
|
||||
disabled={addDisabled}
|
||||
label={<Trans>Add cluster(s)</Trans>}
|
||||
onClick={this.addClusters}
|
||||
waiting={this.isWaiting}
|
||||
tooltip={addDisabled ? _i18n._("Select at least one cluster to add.") : undefined}
|
||||
tooltipOverrideDisabled
|
||||
/>
|
||||
</div>
|
||||
</WizardLayout>
|
||||
{this.showSettings && (
|
||||
<div className="proxy-settings">
|
||||
<p>HTTP Proxy server. Used for communicating with Kubernetes API.</p>
|
||||
<Input
|
||||
autoFocus
|
||||
value={this.proxyServer}
|
||||
onChange={value => this.proxyServer = value}
|
||||
theme="round-black"
|
||||
/>
|
||||
<small className="hint">
|
||||
{'A HTTP proxy server URL (format: http://<address>:<port>).'}
|
||||
</small>
|
||||
</div>
|
||||
)}
|
||||
{this.error && (
|
||||
<div className="error">{this.error}</div>
|
||||
)}
|
||||
<div className="actions-panel">
|
||||
<Button
|
||||
primary
|
||||
disabled={addDisabled}
|
||||
label={<Trans>Add cluster(s)</Trans>}
|
||||
onClick={this.addClusters}
|
||||
waiting={this.isWaiting}
|
||||
tooltip={addDisabled ? _i18n._("Select at least one cluster to add.") : undefined}
|
||||
tooltipOverrideDisabled
|
||||
/>
|
||||
</div>
|
||||
</WizardLayout>
|
||||
</DropFileInput>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user