Skip to content

Commit

Permalink
Responsive Wizard header (#1802)
Browse files Browse the repository at this point in the history
* WizardHeaderWithDisplayNameAndName: refactor #1801

* codacy

* Changed to less generic style names and made prefix of a hidden path always be shown (#1801)

* Added FormContext.setFormState (#1805)

* Incorrect label resolution of an option-set inside an item-set #1788

* Incorrect label resolution of an option-set inside an item-set #1788

* Incorrect highlighting of required item/option-set occurrence #1789

* Correct styling of the Wizard's form icon (#1807)

* Codacy (#2885)

* Fixed missing minimize icon in the Wizard (#1807)

* Codacy (#1807)

* #1801

-letting path input to grow and take all available space if needed, but not more than required

* codacy

* WizardHeaderWithDisplayNameAndName: refactor #1801

* WizardHeaderWithDisplayNameAndName: refactor #1801

* Removed commented code (#1801)

* Removed left padding for WizardStepsPanel (#1801)

* WizardHeaderWithDisplayNameAndName: refactor #1801

Co-authored-by: Alan Semenov <ase@enonic.com>
Co-authored-by: Pavel Milkevich <pavel.milkevich@gmail.com>
Co-authored-by: Alan Semenov <alansemenov@users.noreply.github.com>
  • Loading branch information
4 people committed Feb 25, 2021
1 parent 5f383a2 commit 85a4e8a
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 123 deletions.
Original file line number Diff line number Diff line change
@@ -1,54 +1,47 @@
import {i18n} from '../../util/Messages';
import {AppHelper} from '../../util/AppHelper';
import {QueryField} from '../../query/QueryField';
import {TextInput} from '../../ui/text/TextInput';
import {TextInput, TextInputSize} from '../../ui/text/TextInput';
import {SpanEl} from '../../dom/SpanEl';
import {AutosizeTextInput} from '../../ui/text/AutosizeTextInput';
import {ValueChangedEvent} from '../../ValueChangedEvent';
import {StringHelper} from '../../util/StringHelper';
import {WindowDOM} from '../../dom/WindowDOM';
import {NamePrettyfier} from '../../NamePrettyfier';
import {DisplayNameGenerator} from './DisplayNameGenerator';
import {WizardHeader} from './WizardHeader';
import {Name} from '../../Name';
import {DivEl} from '../../dom/DivEl';
import {ElementHelper} from '../../dom/ElementHelper';
import {Element} from '../../dom/Element';
import {ResponsiveManager} from '../../ui/responsive/ResponsiveManager';

export class WizardHeaderWithDisplayNameAndNameBuilder {
export interface WizardHeaderWithDisplayNameAndNameOptions {

displayNameGenerator: DisplayNameGenerator;
displayNameGenerator?: DisplayNameGenerator;

displayNameLabel: string;

setDisplayNameGenerator(value: DisplayNameGenerator): WizardHeaderWithDisplayNameAndNameBuilder {
this.displayNameGenerator = value;
return this;
}

setDisplayNameLabel(value: string): WizardHeaderWithDisplayNameAndNameBuilder {
this.displayNameLabel = value;
return this;
}

build(): WizardHeaderWithDisplayNameAndName {
return new WizardHeaderWithDisplayNameAndName(this);
}
displayNameLabel?: string;

}

export class WizardHeaderWithDisplayNameAndName
extends WizardHeader {

private displayNameGenerator: DisplayNameGenerator;

private forbiddenChars: RegExp = /[\/\\]+/ig;

protected displayNameEl: TextInput;

private displayNameProgrammaticallySet: boolean;

protected options?: WizardHeaderWithDisplayNameAndNameOptions;

protected pathEl: SpanEl;

protected nameEl: TextInput;

protected topRow: DivEl;

protected bottomRow: DivEl;

private autoGenerateName: boolean = false;

private autoGenerationEnabled: boolean = true;
Expand All @@ -57,41 +50,49 @@ export class WizardHeaderWithDisplayNameAndName

private simplifiedNameGeneration: boolean = false;

constructor(builder: WizardHeaderWithDisplayNameAndNameBuilder) {
constructor(options?: WizardHeaderWithDisplayNameAndNameOptions) {
super();
this.addClass('wizard-header-with-display-name-and-name');
this.displayNameGenerator = builder.displayNameGenerator;
this.displayNameProgrammaticallySet = this.displayNameGenerator != null;

const debounceNotify = (query: string) => AppHelper.debounce((event: ValueChangedEvent) => {
this.notifyPropertyChanged(query, event.getOldValue(), event.getNewValue());
}, 100);
this.options = options;
this.initElements();
this.postInitElements();
this.initListeners();
}

this.displayNameEl = AutosizeTextInput.large();
this.displayNameEl.setPlaceholder(
'<' + (builder.displayNameLabel ? builder.displayNameLabel : i18n('field.displayName')) + '>').setName(
QueryField.DISPLAY_NAME);
this.displayNameEl.onValueChanged(debounceNotify(QueryField.DISPLAY_NAME));
this.appendChild(this.displayNameEl);
protected initElements() {
this.displayNameProgrammaticallySet = !!this.options?.displayNameGenerator;

this.topRow = new DivEl('wizard-header-top-row');
this.bottomRow = new DivEl('wizard-header-bottom-row');
this.displayNameEl = new TextInput('', TextInputSize.LARGE);

this.pathEl = new SpanEl('path');
this.pathEl.hide();
this.appendChild(this.pathEl);

this.nameEl = AutosizeTextInput.middle().setForbiddenCharsRe(this.forbiddenChars);
this.nameEl.setPlaceholder('<' + i18n('field.path') + '>').setName('name');
this.nameEl.onValueChanged(debounceNotify(`<${i18n('field.path')}>`));
this.nameEl = new WizardHeaderNameInput().setForbiddenCharsRe(this.forbiddenChars);
}

this.appendChild(this.nameEl);
protected postInitElements() {
const displayNamePlaceholder: string = !!this.options?.displayNameLabel ? this.options.displayNameLabel : i18n('field.displayName');
this.displayNameEl.setPlaceholder(`<${displayNamePlaceholder}>`).setName(QueryField.DISPLAY_NAME);
this.nameEl.setPlaceholder(`<${i18n('field.path')}>`).setName('name');
}

this.displayNameEl.onValueChanged((event: ValueChangedEvent) => {
protected initListeners() {
ResponsiveManager.onAvailableSizeChanged(this);

this.displayNameEl.removeClass('generated');
const debounceNotify = (query: string) => AppHelper.debounce((event: ValueChangedEvent) => {
this.notifyPropertyChanged(query, event.getOldValue(), event.getNewValue());
}, 100);

let currentDisplayName = event.getNewValue() || '';
this.displayNameEl.onValueChanged(debounceNotify(QueryField.DISPLAY_NAME));
this.nameEl.onValueChanged(debounceNotify(`<${i18n('field.path')}>`));
this.displayNameEl.onValueChanged((event: ValueChangedEvent) => {
this.displayNameEl.removeClass('generated');
const currentDisplayName: string = event.getNewValue() || '';

if (this.displayNameGenerator && this.displayNameGenerator.hasExpression()) {
let generatedDisplayName = this.displayNameGenerator.execute() || '';
if (this.options?.displayNameGenerator?.hasExpression()) {
const generatedDisplayName: string = this.options.displayNameGenerator.execute() || '';

this.displayNameProgrammaticallySet =
generatedDisplayName.toLowerCase() === currentDisplayName.toLowerCase() ||
Expand All @@ -106,17 +107,13 @@ export class WizardHeaderWithDisplayNameAndName
});

this.nameEl.onValueChanged((event: ValueChangedEvent) => {
let currentName = event.getNewValue() || '';
let displayName = this.getDisplayName() || '';
const currentName: string = event.getNewValue() || '';
const displayName: string = this.getDisplayName() || '';

this.autoGenerateName = this.checkAutoGenerateName(currentName, displayName);

this.updateNameGeneratedStatus();
});

this.onShown(() => this.updatePathAndNameWidth());
WindowDOM.get().onResized(() => this.updatePathAndNameWidth(), this);

}

resetBaseValues() {
Expand All @@ -142,9 +139,9 @@ export class WizardHeaderWithDisplayNameAndName
this.nameEl.setValue(this.generateName(displayName));
}

if (this.displayNameGenerator && this.displayNameGenerator.hasExpression()) {
if (this.options?.displayNameGenerator?.hasExpression()) {
if (!forceDisplayNameProgrammaticallySet) {
let generatedDisplayName = this.displayNameGenerator.execute();
const generatedDisplayName: string = this.options.displayNameGenerator.execute();
this.displayNameProgrammaticallySet = generatedDisplayName === displayName;
} else {
this.displayNameProgrammaticallySet = true;
Expand All @@ -169,12 +166,16 @@ export class WizardHeaderWithDisplayNameAndName
}

setPath(value: string) {
this.pathEl.getEl().setText(value);
if (value) {
this.pathEl.getEl().setText(value.replace(/\/$/, ''));
this.pathEl.setTitle(value);
this.pathEl.show();
} else {
this.pathEl.hide();
this.pathEl.getEl().setText('');
}

this.pathEl.toggleClass('empty', StringHelper.isEmpty(this.pathEl.getEl().getText()));
}

setSimplifiedNameGeneration(value: boolean) {
Expand Down Expand Up @@ -267,24 +268,6 @@ export class WizardHeaderWithDisplayNameAndName
}
}

private updatePathAndNameWidth() {
let pathEl = this.pathEl.getEl();
let nameEl = this.nameEl.getEl();
let headerWidth = this.getEl().getWidth();
let pathWidth = pathEl.getWidthWithMargin();
let nameWidth = nameEl.getWidthWithMargin();
let nameMinWidth = nameEl.getMinWidth();

if (pathWidth + nameWidth > headerWidth) {
if (nameWidth > nameMinWidth) {
nameEl.setWidthPx(Math.max(nameMinWidth, headerWidth - pathWidth));
}
if (pathWidth + nameMinWidth > headerWidth) {
pathEl.setWidthPx(headerWidth - nameMinWidth - pathEl.getMarginLeft() - pathEl.getMarginRight());
}
}
}

setName(value: string) {
this.nameEl.setValue(value);
}
Expand All @@ -308,4 +291,45 @@ export class WizardHeaderWithDisplayNameAndName
'is deprecated and will be removed in lib-admin-ui 4.0.0');
this.toggleDisplayNameInput(false);
}

doRender(): Q.Promise<boolean> {
return super.doRender().then((rendered: boolean) => {
this.addClass('wizard-header-with-display-name-and-name');

const separator: SpanEl = new SpanEl('separator');
separator.setHtml('/');

this.topRow.appendChild(this.displayNameEl);
this.bottomRow.appendChildren(this.pathEl, separator, this.nameEl);

this.appendChild(this.topRow);
this.appendChild(this.bottomRow);

return rendered;
});
}
}

class WizardHeaderNameInput extends AutosizeTextInput {

protected doUpdateSize() {
const inputEl: ElementHelper = this.getEl();
const cloneEl: ElementHelper = this.clone.getEl();
const parent: Element = this.getParentElement();

let spaceLeftForInput: number = parent.getEl().getWidthWithMargin();

parent.getChildren().filter((c: Element) => c.isVisible() && !c.hasClass('autosize-attendant')).forEach((child: Element) => {
if (child.hasClass('path') && !child.hasClass('empty')) {
spaceLeftForInput -= 20; // min size of a static path element
} else if (child !== this) {
spaceLeftForInput -= child.getEl().getWidthWithMargin();
}
});

const currentInputWidth: number = cloneEl.getWidthWithBorder();
const min: number = Math.min(spaceLeftForInput, currentInputWidth);

inputEl.getHTMLElement().style.flexBasis = `${min}px`;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,6 @@ export class WizardPanel<EQUITABLE extends Equitable>
this.scrollPosition = scroll;
this.splitPanel.savePanelSizesAndDistribute(40, 0, SplitPanelUnit.PIXEL);
this.splitPanel.hideSplitter();
this.minimizeEditButton.getEl().setLeftPx(this.stepsPanel.getEl().getWidth());

this.stepNavigator.onNavigationItemActivated(this.toggleMinimizeListener);
} else {
Expand Down Expand Up @@ -680,10 +679,6 @@ export class WizardPanel<EQUITABLE extends Equitable>
console.debug('WizardPanel.doRenderOnDataLoaded');
}

let updateMinimizeButtonPosition = () => {
this.minimizeEditButton.getEl().setLeftPx(this.stepsPanel.getEl().getWidth());
};

this.updateToolbarActions();

this.formPanel = new Panel('form-panel rendering');
Expand Down Expand Up @@ -714,10 +709,6 @@ export class WizardPanel<EQUITABLE extends Equitable>
this.lastFocusedElement.focus();
}

if (this.minimizeEditButton) {
updateMinimizeButtonPosition();
}

// check validity on rendered
this.notifyValidityChanged(this.isValid());
});
Expand All @@ -727,16 +718,17 @@ export class WizardPanel<EQUITABLE extends Equitable>
this.mainToolbar.addClass('rendering');
}

let headerAndNavigatorContainer = new DivEl('header-and-navigator-container');
const headerAndNavigatorContainer: DivEl = new DivEl('header-and-navigator-container');
const headerContainer: DivEl = new DivEl('header-container');

this.formIcon = this.createFormIcon().addClassEx('form-icon', StyleHelper.COMMON_PREFIX);
if (this.formIcon) {
headerAndNavigatorContainer.appendChild(this.formIcon);
headerContainer.appendChild(this.formIcon);
}

this.wizardHeader = this.createWizardHeader();
if (this.wizardHeader) {
headerAndNavigatorContainer.appendChild(this.wizardHeader);
headerContainer.appendChild(this.wizardHeader);
this.notifyWizardHeaderCreated();
this.validityManager.setHeader(this.wizardHeader);
}
Expand All @@ -745,6 +737,7 @@ export class WizardPanel<EQUITABLE extends Equitable>
this.stepNavigator = new WizardStepNavigator();
this.stepNavigatorAndToolbarContainer = new WizardStepNavigatorAndToolbar(this.stepNavigator, this.stepToolbar);

headerAndNavigatorContainer.appendChild(headerContainer);
headerAndNavigatorContainer.appendChild(this.stepNavigatorAndToolbarContainer);

this.stepsPanel = new WizardStepsPanel(this.stepNavigator, this.formPanel);
Expand All @@ -764,11 +757,11 @@ export class WizardPanel<EQUITABLE extends Equitable>
this.toggleMinimize(event.getIndex());
};
this.minimizeEditButton = new DivEl('minimize-edit');
ResponsiveManager.onAvailableSizeChanged(this.formPanel, updateMinimizeButtonPosition);
ResponsiveManager.onAvailableSizeChanged(this.formPanel);

this.minimizeEditButton.onClicked(this.toggleMinimize.bind(this, -1));

this.formPanel.prependChild(this.minimizeEditButton);
this.stepNavigatorAndToolbarContainer.appendChild(this.minimizeEditButton);

this.livePanel.onAdded(() => {
if (WizardPanel.debug) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import {DivEl} from '../../dom/DivEl';
import {WindowDOM} from '../../dom/WindowDOM';
import {ResponsiveManager} from '../responsive/ResponsiveManager';
import {TextInput, TextInputSize} from './TextInput';
import {ElementHelper} from '../../dom/ElementHelper';

export class AutosizeTextInput
extends TextInput {

private attendant: Element;
private clone: Element;
protected attendant: Element;
protected clone: Element;

constructor(className?: string, size: TextInputSize = TextInputSize.MIDDLE, originalValue?: string) {
super(className, size, originalValue);
Expand Down Expand Up @@ -54,28 +55,36 @@ export class AutosizeTextInput
return;
}

let inputEl = this.getEl();
let cloneEl = this.clone.getEl();
const inputEl: ElementHelper = this.getEl();
const cloneEl: ElementHelper = this.clone.getEl();

cloneEl.setFontSize(inputEl.getFontSize()).setPaddingLeft(inputEl.getPaddingLeft() + 'px').setPaddingRight(
inputEl.getPaddingRight() + 'px');

this.attendant.insertAfterEl(this);

let cloneHtml = this.getValue();
let cloneHtml: string = this.getValue();
if (StringHelper.isEmpty(cloneHtml)) {
cloneHtml = this.getPlaceholder();
}
cloneEl.setInnerHtml(cloneHtml);

this.doUpdateSize();

this.attendant.remove();
}

protected doUpdateSize() {
const inputEl: ElementHelper = this.getEl();
const cloneEl: ElementHelper = this.clone.getEl();

// Set input width to text length from the clone <div>
// or to maximum possible width corresponding to attendant width.
if (cloneEl.getWidthWithBorder() > this.attendant.getEl().getWidth()) {
inputEl.setWidth('100%');
} else {
inputEl.setWidthPx(cloneEl.getWidthWithBorder());
}

this.attendant.remove();
}

}
Loading

0 comments on commit 85a4e8a

Please sign in to comment.