Skip to content
This repository has been archived by the owner on Feb 28, 2023. It is now read-only.

Commit

Permalink
Feature/modul 582 arbo multinode select (#612)
Browse files Browse the repository at this point in the history
* Checkboxes and recursive node select

* Refactoring and completion of logic

* Fixed recursivity between elements

* Moved tree sub-components, updated broken unit tests

* Unit tests for tree-icon

* Made interminated state for checkboxes and revised tree prop name

* Intégration du partially-checked

* Refactored multiple tree nodes code

* Added a few states for multiple-node selection

* Merged integration branch, adjusted autoselect multinode's behavior

* Fine-tuned code, started unit testing

* Updated unit tests

* Changes prior to yet another small refactor

* Finished correcting checkboxes behavior

* Prior to new tree being added to sandbox

* Prior to selectedParentNodes prop

* Button auto-select feature completed

* Added more tests and checkbox states

* Updated tests and added descriptions to trees

* Light refactor

* MODUL-582 Added new behaviors (parent-checkbox auto-select) and new tests

* MODUL-582 Removed the ability to show selection button when checkboxes are hidden

* MODUL-582 Added conditional icon class name rendering to prevent all snapshots to be updated

* MODUL-582 Updated behaviors and tests

* MODUL-582 Fixed multinode tree's behavior

* MODUL-582 Simplified indeterminated checkbox state

* MODUL-582 Removed consective blank lines from Checkbox.spec

* MODUL-582 Updated sandbox to improve terminology comprehension

* MODUL-582 Prior to checkbox display condition refactor

* MODUL-582 Prior to dev merge

* MODUL-582 Merged develop, updated tree unit tests, refactored, added comments

* MODUL-582 Slight var names improvement

* MODUL-582 Simplified tree-node code

* MODUL-582 TreeNode light refactor

* MODUL-582 Removed treeNode and TreeIcon module export

* MODUL-582 Fixed tree plugin
  • Loading branch information
DDurandDTI authored and chuckmah committed Dec 20, 2018
1 parent 963610a commit e6073ba
Show file tree
Hide file tree
Showing 40 changed files with 1,430 additions and 464 deletions.
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 23 additions & 1 deletion src/components/checkbox/__snapshots__/checkbox.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,28 @@ exports[`MCheckbox should render correctly when disabled 1`] = `
</div>
`;
exports[`MCheckbox should render correctly when disabled and checked 1`] = `
<div class="m-checkbox m--is-checkbox-left m--is-checked m--is-disabled">
<input type="checkbox" id="mCheckbox-uuid" disabled="disabled" checked="checked" class="m-checkbox__hidden">
<label for="mCheckbox-uuid" aria-hidden="true" class="m-checkbox__wrap"><span aria-hidden="true" class="m-checkbox__input"><span class="m-checkbox__input__icon"></span></span>
</label>
<div class="m-validation-message m-checkbox__message">
<m-accordion-transition transition="true"></m-accordion-transition>
</div>
</div>
`;
exports[`MCheckbox should render correctly when indeterminated (with correct classes) 1`] = `
<div class="m-checkbox m--is-checkbox-left m--is-indeterminate">
<input type="checkbox" id="mCheckbox-uuid" class="m-checkbox__hidden">
<label for="mCheckbox-uuid" aria-hidden="true" class="m-checkbox__wrap"><span aria-hidden="true" class="m-checkbox__input"><span class="m-checkbox__input__icon"></span></span>
</label>
<div class="m-validation-message m-checkbox__message">
<m-accordion-transition transition="true"></m-accordion-transition>
</div>
</div>
`;
exports[`MCheckbox should render correctly when position prop is right 1`] = `
<div class="m-checkbox m--is-checkbox-right">
<input type="checkbox" id="mCheckbox-uuid" class="m-checkbox__hidden">
Expand All @@ -46,7 +68,7 @@ exports[`MCheckbox should render correctly when position prop is right 1`] = `
exports[`MCheckbox should render correctly when readonly 1`] = `
<div class="m-checkbox m--is-checkbox-left m--is-readonly">
<input type="hidden" id="mCheckbox-uuid">
<label aria-hidden="true" class="m-checkbox__wrap"><span aria-hidden="true" class="m-checkbox__input"><span class="m-checkbox__input__icon"></span></span>
<label for="mCheckbox-uuid" aria-hidden="true" class="m-checkbox__wrap"><span aria-hidden="true" class="m-checkbox__input"><span class="m-checkbox__input__icon"></span></span>
</label>
<div class="m-validation-message m-checkbox__message">
<m-accordion-transition transition="true"></m-accordion-transition>
Expand Down
14 changes: 8 additions & 6 deletions src/components/checkbox/checkbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@
'm--is-checkbox-right': !hasCheckboxLeft,
'm--is-checked': propValue,
'm--is-disabled': isDisabled,
'm--is-indeterminate': propIndeterminate,
'm--is-readonly': readonly,
'm--is-focus': isFocus,
'm--has-error': hasError,
'm--is-valid': isValid }">
<input v-if="!readonly"
<input class="m-checkbox__hidden"
v-if="!readonly"
ref="checkbox"
type="checkbox"
:id="id"
class="m-checkbox__hidden"
:indeterminate.prop="propIndeterminate"
:disabled="isDisabled"
v-model="propValue"
@click="onClick"
@focus="setFocus(true)"
@blur="setFocus(false)" />
@blur="setFocus(false)">
<input v-if="readonly"
type="hidden"
:id="id"
:value="propValue" />
<label class="m-checkbox__wrap"
:for="forId"
:for="id"
:aria-hidden="!hasLabelSlot">
<span class="m-checkbox__input"
aria-hidden="true">
Expand All @@ -33,8 +35,8 @@
<slot></slot>
</span>
</label>
<m-validation-message ref="validation"
class="m-checkbox__message"
<m-validation-message class="m-checkbox__message"
ref="validation"
:disabled="isDisabled"
:error="hasError"
:error-message="errorMessage"
Expand Down
16 changes: 10 additions & 6 deletions src/components/checkbox/checkbox.sandbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ <h3>
<p>
<m-checkbox error-message="Enim ipsum qui consectetur ea in non.">Choix de réponse 1</m-checkbox><br>
<m-checkbox>Choix de réponse 2</m-checkbox><br>
<m-checkbox error-message="Enim ipsum qui consectetur ea in non.">Choix de réponse 3</m-checkbox>
<m-checkbox error-message="Enim ipsum qui consectetur ea in non.">Choix de réponse 3</m-checkbox><br>
<m-checkbox :disabled="true">Choix invalide</m-checkbox><br>
<m-checkbox :indeterminate="true">État <a target="_blank"
href="https://developer.mozilla.org/fr/docs/Web/CSS/:indeterminate">indéterminé</a></m-checkbox>
</p>

<!-- Sandbox template -->
Expand All @@ -22,16 +25,17 @@ <h3>Le crochet reste visible lorsque la case est désactivée</h3>
<p class="m-u--margin-bottom">

<!-- if relevant, add link to PR
</br>From <a href="/ulaval/modul-components/pull/000" target="blank" label="PR description</a>
</br>From <a href="/ulaval/modul-components/pull/000" target="blank" label="PR description</a>
</p>-->
</p>-->
<m-checkbox v-model="disabledCheckboxValue"
:disabled="disabledCheckbox"></m-checkbox>
<m-button @click="disabledCheckbox = !disabledCheckbox">Désactiver/Activer le checkbox</m-button>
</p>

<m-checkbox :readonly="isReadOnly"
v-model="checkboxReadOnlyValue">Readonly</m-checkbox><em>(Valeur checkbox: {{checkboxReadOnlyValue}})</em><br />
<m-button @click="isReadOnly = !isReadOnly">Activer/Désactiver ReadOnly</m-button>
<m-checkbox :readonly="isReadOnly"
v-model="checkboxReadOnlyValue">Readonly</m-checkbox><em>(Valeur checkbox: {{checkboxReadOnlyValue}})</em><br />
<m-button @click="isReadOnly = !isReadOnly">Activer/Désactiver ReadOnly</m-button>

</p>
</div>
78 changes: 77 additions & 1 deletion src/components/checkbox/checkbox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,66 @@ $m-checkbox--width: 16px;
line-height: 1;

&:not(.m--is-disabled) {
&:not(.m--has-error):not(.m--is-valid):not(.m--is-readonly) {
.m-checkbox {
&__wrap {
cursor: pointer;
}

&__input {
border-color: $m-color--text;
color: $m-color--interactive;

&::before {
content: '';
position: absolute;
width: 10px;
height: 10px;
background-color: $m-color--ul-blue;
transform: scale(0);
transition: transform $m-transition-duration ease;
}

&__icon {
position: relative;
top: -1px; // Magic number
left: 1px; // Magic number
width: 10px;
height: 5px;
transform: rotate(-32deg);

&::before,
&::after {
transition: background $m-transition-duration ease;
position: absolute;
bottom: 0;
left: 0;
content: '';
width: 0;
background: $m-color--interactive;
border-radius: 2px;
}

&::before {
bottom: 0;
transition: width $m-transition-duration--xs ease;
transition-delay: 0;
transform: rotate(-20deg);
width: 0;
height: 2px;
}

&::after {
top: 0;
transition: height $m-transition-duration--xs ease;
transition-delay: $m-transition-duration--xs;
width: 2px;
height: 0;
}
}
}
}

&:not(.m--has-error):not(.m--is-valid):not(.m--is-disabled-and-checked):not(.m--is-readonly) {
.m-checkbox__wrap:hover,
&.m--is-focus {
.m-checkbox {
Expand Down Expand Up @@ -67,6 +126,23 @@ $m-checkbox--width: 16px;
}
}

&.m--is-indeterminate {
.m-checkbox__input {
&::before {
transform: scale(1);
}
}
}

&.m--is-disabled-and-checked {
.m-checkbox__input__icon {
&::after,
&::before {
background: $m-color--disabled;
}
}
}

&.m--is-disabled {
.m-checkbox {
&__wrap {
Expand Down
34 changes: 34 additions & 0 deletions src/components/checkbox/checkbox.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ describe('MCheckbox', () => {
return expect(renderComponent(chkbox.vm)).resolves.toMatchSnapshot();
});

it('should render correctly when disabled and checked', () => {
const chkbox: Wrapper<MCheckbox> = mount(MCheckbox, {
localVue: localVue,
propsData: {
disabled: true,
value: true
}
});

return expect(renderComponent(chkbox.vm)).resolves.toMatchSnapshot();
});

it('should render correctly when readonly', () => {
const chkbox: Wrapper<MCheckbox> = mount(MCheckbox, {
localVue: localVue,
Expand Down Expand Up @@ -87,6 +99,28 @@ describe('MCheckbox', () => {
expect(chkbox.emitted('click')).toBeTruthy();
});

it('should render correctly when indeterminated (with correct classes)', () => {
const chkbox: Wrapper<MCheckbox> = mount(MCheckbox, {
localVue: localVue,
propsData: {
'indeterminate': true
}
});

return expect(renderComponent(chkbox.vm)).resolves.toMatchSnapshot();
});

it('should should have the indeterminated prop when indeterminated', () => {
const chkbox: Wrapper<MCheckbox> = mount(MCheckbox, {
localVue: localVue,
propsData: {
'indeterminate': true
}
});

return expect(chkbox.find('input').element.indeterminate).toBeTruthy(); // TODO: Add prop to linter?
});

it('should flow down InputState mixin props to m-validation-message', () => {
const valMsgProps: any = {
disabled: false,
Expand Down
11 changes: 11 additions & 0 deletions src/components/checkbox/checkbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export class MCheckbox extends ModulVue {
@Prop()
public value: boolean;

@Prop({ default: false })
public indeterminate: boolean;

@Prop({
default: MCheckboxPosition.Left,
validator: value =>
Expand Down Expand Up @@ -62,6 +65,14 @@ export class MCheckbox extends ModulVue {
this.isFocus = value;
}

public get propIndeterminate(): boolean {
return this.indeterminate && !this.propValue;
}

public set propIndeterminate(newValue: boolean) {
this.indeterminate = newValue;
}

private get hasCheckboxLeft(): boolean {
return this.position === MCheckboxPosition.Left;
}
Expand Down
2 changes: 0 additions & 2 deletions src/components/component-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,4 @@ export const TOAST: string = 'm-toast';
export const TOUCH_NAME: string = 'm-touch';
export const TOOLTIP_NAME: string = 'm-tooltip';
export const TREE_NAME: string = 'm-tree';
export const TREE_ICON_NAME: string = 'm-tree-icon';
export const TREE_NODE_NAME: string = 'm-tree-node';
export const VALIDATION_MESSAGE_NAME: string = 'm-validation-message';
4 changes: 0 additions & 4 deletions src/components/components-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ import TextfieldPlugin from './textfield/textfield';
import TimepickerPlugin from './timepicker/timepicker';
import ToastPlugin from './toast/toast';
import TooltipPlugin from './tooltip/tooltip';
import TreeIconPlugin from './tree-icon/tree-icon';
import TreeNodePlugin from './tree-node/tree-node';
import TreePlugin from './tree/tree';
import ValidationMessagePlugin from './validation-message/validation-message';

Expand Down Expand Up @@ -181,8 +179,6 @@ const ComponentsPlugin: PluginObject<any> = {
Vue.use(ValidationMessagePlugin);
Vue.use(InplaceEditPlugin);
Vue.use(TreePlugin);
Vue.use(TreeIconPlugin);
Vue.use(TreeNodePlugin);
}
};

Expand Down
7 changes: 6 additions & 1 deletion src/components/icon-file/icon-file.html
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
<m-icon class="m-icon-file" :name="spriteId" :svgTitle="svgTitle" :size="size" @click="onClick" @keydown="onKeydown"></m-icon>
<m-icon class="m-icon-file"
:name="spriteId"
:svgTitle="svgTitle"
:size="size"
@click="onClick"
@keydown="onKeydown"></m-icon>
11 changes: 9 additions & 2 deletions src/components/icon/icon.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
<svg class="m-icon" @click="onClick" @keydown="onKeydown" :aria-hidden="!hasSvgTitle" :width="size" :height="size">
<svg class="m-icon"
@click="onClick"
@keydown="onKeydown"
:aria-hidden="!hasSvgTitle"
:width="size"
:height="size">
<title v-if="hasSvgTitle">{{svgTitle}}</title>
<use :xlink:href="spriteId" aria-hidden="true"></use>
<use :xlink:href="spriteId"
aria-hidden="true"
:class="showNameAsClassInHtml"></use>
</svg>
7 changes: 7 additions & 0 deletions src/components/icon/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export class MIcon extends Vue {
@Prop({ default: '1em' })
public size: string;

@Prop({ default: false })
public showNameAsClass: boolean;

@Emit('click')
onClick(event: Event): void { }

Expand All @@ -33,6 +36,10 @@ export class MIcon extends Vue {
Vue.prototype.$log.warn('"' + this.name + '" is not a valid svg id. Make sure that the sprite has been loaded via the $svg instance service.');
}
}

private get showNameAsClassInHtml(): string {
return this.showNameAsClass ? name : '';
}
}

const IconPlugin: PluginObject<any> = {
Expand Down
2 changes: 0 additions & 2 deletions src/components/tree-icon/tree-icon.html

This file was deleted.

5 changes: 0 additions & 5 deletions src/components/tree-icon/tree-icon.scss

This file was deleted.

Loading

0 comments on commit e6073ba

Please sign in to comment.