mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Moving dock info panel to the top (#1007)
* Moving EditorPanel to the top Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Preventing save with empty yaml Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Make tooltips in @withTooltip narrower Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Not showing api errors in icon Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Success notification for create resource operation Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Button outlined style Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Making second button to stay outlined Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Fine-tuning dock info panel colors Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Removing border-radius from ace-editor Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
parent
9ecfeb316c
commit
af71834676
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
.theme-light & {
|
.theme-light & {
|
||||||
border: 1px solid gainsboro;
|
border: 1px solid gainsboro;
|
||||||
border-radius: $radius;
|
|
||||||
|
|
||||||
.ace_scrollbar {
|
.ace_scrollbar {
|
||||||
@include custom-scrollbar(dark);
|
@include custom-scrollbar(dark);
|
||||||
@ -19,7 +18,6 @@
|
|||||||
width: inherit;
|
width: inherit;
|
||||||
height: inherit;
|
height: inherit;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
border-radius: $radius;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --Theme customization
|
// --Theme customization
|
||||||
|
|||||||
@ -41,6 +41,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.outlined {
|
||||||
|
color: inherit;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&.active,
|
||||||
|
&:focus {
|
||||||
|
color: inherit;
|
||||||
|
box-shadow: 0 0 0 1px inset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.big {
|
&.big {
|
||||||
font-size: 2.2 * $unit;
|
font-size: 2.2 * $unit;
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export interface ButtonProps extends ButtonHTMLAttributes<any>, TooltipDecorator
|
|||||||
primary?: boolean;
|
primary?: boolean;
|
||||||
accent?: boolean;
|
accent?: boolean;
|
||||||
plain?: boolean;
|
plain?: boolean;
|
||||||
|
outlined?: boolean;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
big?: boolean;
|
big?: boolean;
|
||||||
@ -23,12 +24,12 @@ export class Button extends React.PureComponent<ButtonProps, {}> {
|
|||||||
private button: HTMLButtonElement;
|
private button: HTMLButtonElement;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, waiting, label, primary, accent, plain, hidden, active, big, round, tooltip, children, ...props } = this.props;
|
const { className, waiting, label, primary, accent, plain, hidden, active, big, round, outlined, tooltip, children, ...props } = this.props;
|
||||||
const btnProps = props as Partial<ButtonProps>;
|
const btnProps = props as Partial<ButtonProps>;
|
||||||
if (hidden) return null;
|
if (hidden) return null;
|
||||||
|
|
||||||
btnProps.className = cssNames('Button', className, {
|
btnProps.className = cssNames('Button', className, {
|
||||||
waiting, primary, accent, plain, active, big, round,
|
waiting, primary, accent, plain, active, big, round, outlined
|
||||||
});
|
});
|
||||||
|
|
||||||
const btnContent: ReactNode = (
|
const btnContent: ReactNode = (
|
||||||
|
|||||||
@ -39,6 +39,7 @@ export class CreateResource extends React.Component<Props> {
|
|||||||
|
|
||||||
create = async () => {
|
create = async () => {
|
||||||
if (this.error) return;
|
if (this.error) return;
|
||||||
|
if (!this.data.trim()) return; // do not save when field is empty
|
||||||
const resources = jsYaml.safeLoadAll(this.data)
|
const resources = jsYaml.safeLoadAll(this.data)
|
||||||
.filter(v => !!v) // skip empty documents if "---" pasted at the beginning or end
|
.filter(v => !!v) // skip empty documents if "---" pasted at the beginning or end
|
||||||
const createdResources: string[] = [];
|
const createdResources: string[] = [];
|
||||||
@ -54,12 +55,14 @@ export class CreateResource extends React.Component<Props> {
|
|||||||
errors.forEach(Notifications.error);
|
errors.forEach(Notifications.error);
|
||||||
if (!createdResources.length) throw errors[0];
|
if (!createdResources.length) throw errors[0];
|
||||||
}
|
}
|
||||||
return (
|
const successMessage = (
|
||||||
<p>
|
<p>
|
||||||
<Plural value={createdResources.length} one="Resource" other="Resources"/>{" "}
|
<Plural value={createdResources.length} one="Resource" other="Resources"/>{" "}
|
||||||
<Trans><b>{createdResources.join(", ")}</b> successfully created</Trans>
|
<Trans><b>{createdResources.join(", ")}</b> successfully created</Trans>
|
||||||
</p>
|
</p>
|
||||||
)
|
)
|
||||||
|
Notifications.ok(successMessage)
|
||||||
|
return successMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -67,11 +70,6 @@ export class CreateResource extends React.Component<Props> {
|
|||||||
const { className } = this.props;
|
const { className } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={cssNames("CreateResource flex column", className)}>
|
<div className={cssNames("CreateResource flex column", className)}>
|
||||||
<EditorPanel
|
|
||||||
tabId={tabId}
|
|
||||||
value={data}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
tabId={tabId}
|
tabId={tabId}
|
||||||
error={error}
|
error={error}
|
||||||
@ -79,6 +77,11 @@ export class CreateResource extends React.Component<Props> {
|
|||||||
submitLabel={_i18n._(t`Create`)}
|
submitLabel={_i18n._(t`Create`)}
|
||||||
showNotifications={false}
|
showNotifications={false}
|
||||||
/>
|
/>
|
||||||
|
<EditorPanel
|
||||||
|
tabId={tabId}
|
||||||
|
value={data}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,11 +90,6 @@ export class EditResource extends React.Component<Props> {
|
|||||||
const { kind, getNs, getName } = resource;
|
const { kind, getNs, getName } = resource;
|
||||||
return (
|
return (
|
||||||
<div className={cssNames("EditResource flex column", this.props.className)}>
|
<div className={cssNames("EditResource flex column", this.props.className)}>
|
||||||
<EditorPanel
|
|
||||||
tabId={tabId}
|
|
||||||
value={draft}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
tabId={tabId}
|
tabId={tabId}
|
||||||
error={error}
|
error={error}
|
||||||
@ -109,6 +104,11 @@ export class EditResource extends React.Component<Props> {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<EditorPanel
|
||||||
|
tabId={tabId}
|
||||||
|
value={draft}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
@include hidden-scrollbar;
|
@include hidden-scrollbar;
|
||||||
|
|
||||||
background: $dockInfoBackground;
|
background: $dockInfoBackground;
|
||||||
border-top: 1px solid $dockInfoBorderColor;
|
border-bottom: 1px solid $dockInfoBorderColor;
|
||||||
padding: $padding $padding * 2;
|
padding: $padding $padding * 2;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
@ -12,37 +12,12 @@
|
|||||||
|
|
||||||
> .controls {
|
> .controls {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
flex: 1 1;
|
||||||
&:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:empty) + .info {
|
&:not(:empty) + .info {
|
||||||
border: 1px solid $borderColor;
|
|
||||||
border-top: 0;
|
|
||||||
border-bottom: 0;
|
|
||||||
min-height: 25px;
|
min-height: 25px;
|
||||||
padding-left: $padding;
|
padding-left: $padding;
|
||||||
padding-right: $padding;
|
padding-right: $padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .info {
|
|
||||||
@include hidden-scrollbar;
|
|
||||||
|
|
||||||
min-width: 40px; // min-space for icon
|
|
||||||
flex: 1 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
padding-right: $padding;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Icon {
|
|
||||||
margin: 0;
|
|
||||||
margin-right: $padding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -38,35 +38,29 @@ export class InfoPanel extends Component<Props> {
|
|||||||
showNotifications: true,
|
showNotifications: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable.ref result: ReactNode;
|
|
||||||
@observable error = "";
|
@observable error = "";
|
||||||
@observable waiting = false;
|
@observable waiting = false;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
disposeOnUnmount(this, [
|
disposeOnUnmount(this, [
|
||||||
reaction(() => this.props.tabId, () => {
|
reaction(() => this.props.tabId, () => {
|
||||||
this.result = ""
|
|
||||||
this.error = ""
|
|
||||||
this.waiting = false
|
this.waiting = false
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get errorInfo() {
|
@computed get errorInfo() {
|
||||||
return this.error || this.props.error;
|
return this.props.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
submit = async () => {
|
submit = async () => {
|
||||||
const { showNotifications } = this.props;
|
const { showNotifications } = this.props;
|
||||||
this.result = "";
|
|
||||||
this.error = "";
|
|
||||||
this.waiting = true;
|
this.waiting = true;
|
||||||
try {
|
try {
|
||||||
this.result = await this.props.submit()
|
const result = await this.props.submit();
|
||||||
if (showNotifications) Notifications.ok(this.result);
|
if (showNotifications) Notifications.ok(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.error = error.toString();
|
if (showNotifications) Notifications.error(error.toString());
|
||||||
if (showNotifications) Notifications.error(this.error);
|
|
||||||
} finally {
|
} finally {
|
||||||
this.waiting = false
|
this.waiting = false
|
||||||
}
|
}
|
||||||
@ -81,27 +75,15 @@ export class InfoPanel extends Component<Props> {
|
|||||||
dockStore.closeTab(this.props.tabId);
|
dockStore.closeTab(this.props.tabId);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInfo() {
|
renderErrorIcon() {
|
||||||
if (!this.props.showInlineInfo) {
|
if (!this.props.showInlineInfo || !this.errorInfo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { result, errorInfo } = this;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="error">
|
||||||
{result && (
|
<Icon material="error_outline" tooltip={this.errorInfo}/>
|
||||||
<div className="success flex align-center">
|
</div>
|
||||||
<Icon material="done" />
|
);
|
||||||
<span>{result}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{errorInfo && (
|
|
||||||
<div className="error flex align-center">
|
|
||||||
<Icon material="error_outline" />
|
|
||||||
<span>{errorInfo}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -114,11 +96,13 @@ export class InfoPanel extends Component<Props> {
|
|||||||
{controls}
|
{controls}
|
||||||
</div>
|
</div>
|
||||||
<div className="info flex gaps align-center">
|
<div className="info flex gaps align-center">
|
||||||
{waiting ? <><Spinner /> {submittingMessage}</> : this.renderInfo()}
|
{waiting ? <><Spinner /> {submittingMessage}</> : this.renderErrorIcon()}
|
||||||
</div>
|
</div>
|
||||||
<Button plain label={<Trans>Cancel</Trans>} onClick={close} />
|
<Button plain label={<Trans>Cancel</Trans>} onClick={close} />
|
||||||
<Button
|
<Button
|
||||||
primary active
|
active
|
||||||
|
outlined={showSubmitClose}
|
||||||
|
primary={!showSubmitClose}// one button always should be primary (blue)
|
||||||
label={submitLabel}
|
label={submitLabel}
|
||||||
onClick={submit}
|
onClick={submit}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
|||||||
@ -174,11 +174,6 @@ export class InstallChart extends Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="InstallChart flex column">
|
<div className="InstallChart flex column">
|
||||||
<EditorPanel
|
|
||||||
tabId={tabId}
|
|
||||||
value={values}
|
|
||||||
onChange={this.onValuesChange}
|
|
||||||
/>
|
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
tabId={tabId}
|
tabId={tabId}
|
||||||
controls={panelControls}
|
controls={panelControls}
|
||||||
@ -188,6 +183,11 @@ export class InstallChart extends Component<Props> {
|
|||||||
submittingMessage={_i18n._(t`Installing...`)}
|
submittingMessage={_i18n._(t`Installing...`)}
|
||||||
showSubmitClose={false}
|
showSubmitClose={false}
|
||||||
/>
|
/>
|
||||||
|
<EditorPanel
|
||||||
|
tabId={tabId}
|
||||||
|
value={values}
|
||||||
|
onChange={this.onValuesChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,18 +106,13 @@ export class UpgradeChart extends React.Component<Props> {
|
|||||||
themeName="outlined"
|
themeName="outlined"
|
||||||
value={version}
|
value={version}
|
||||||
options={versions}
|
options={versions}
|
||||||
formatOptionLabel={this.formatVersionLabel}
|
formatOptionLabel={this.formatVersionLabel}
|
||||||
onChange={({ value }: SelectOption) => this.version = value}
|
onChange={({ value }: SelectOption) => this.version = value}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<div className={cssNames("UpgradeChart flex column", className)}>
|
<div className={cssNames("UpgradeChart flex column", className)}>
|
||||||
<EditorPanel
|
|
||||||
tabId={tabId}
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
tabId={tabId}
|
tabId={tabId}
|
||||||
error={error}
|
error={error}
|
||||||
@ -126,6 +121,11 @@ export class UpgradeChart extends React.Component<Props> {
|
|||||||
submittingMessage={_i18n._(t`Updating..`)}
|
submittingMessage={_i18n._(t`Updating..`)}
|
||||||
controls={controlsAndInfo}
|
controls={controlsAndInfo}
|
||||||
/>
|
/>
|
||||||
|
<EditorPanel
|
||||||
|
tabId={tabId}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export function withTooltip<T extends React.ComponentType<any>>(Target: T): T {
|
|||||||
const tooltipProps: TooltipProps = {
|
const tooltipProps: TooltipProps = {
|
||||||
targetId: tooltipId,
|
targetId: tooltipId,
|
||||||
tooltipOnParentHover: tooltipOverrideDisabled,
|
tooltipOnParentHover: tooltipOverrideDisabled,
|
||||||
|
formatters: { narrow: true },
|
||||||
...(isReactNode(tooltip) ? { children: tooltip } : tooltip),
|
...(isReactNode(tooltip) ? { children: tooltip } : tooltip),
|
||||||
};
|
};
|
||||||
targetProps.id = tooltipId;
|
targetProps.id = tooltipId;
|
||||||
|
|||||||
@ -58,8 +58,8 @@
|
|||||||
"colorVague": "#36393e",
|
"colorVague": "#36393e",
|
||||||
"colorTerminated": "#4c5053",
|
"colorTerminated": "#4c5053",
|
||||||
"dockHeadBackground": "#2e3136",
|
"dockHeadBackground": "#2e3136",
|
||||||
"dockInfoBackground": "#111111",
|
"dockInfoBackground": "#1e2125",
|
||||||
"dockInfoBorderColor": "#4c5053",
|
"dockInfoBorderColor": "#303136",
|
||||||
"terminalBackground": "#000000",
|
"terminalBackground": "#000000",
|
||||||
"terminalForeground": "#ffffff",
|
"terminalForeground": "#ffffff",
|
||||||
"terminalCursor": "#ffffff",
|
"terminalCursor": "#ffffff",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user