Skip to content

Commit

Permalink
V1.5.0 (#3)
Browse files Browse the repository at this point in the history
- pushed ng2-archwizard version to 1.5.0
- added index.ts file to the root level of the project
- updated README file to illustrate how the module can be imported at the root level
- removed postcss-loader dependency
- added a WizardStep interface, that needs to be implemented by all wizard steps
- added a WizardCompletionStep component, which is a wizard step that can't be left and shows all steps (including optional steps) as completed upon entering
- add reset method to the wizard component
- added a function enter and exit to the WizardSteps
- moved the function canExitStep to WizardComponent
- added documentation to the code
- added tests for the WizardCompletionStepComponent
- added a test for the reset function
- replaced the wizard init code with a reset() call
- added missing tests for 100% branch converage
- updated style-loader to current version
- add a description of the wizard-completion-step to the README file
  • Loading branch information
madoar authored May 26, 2017
1 parent d858e1a commit c6a924b
Showing 20 changed files with 675 additions and 194 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ $ npm install --save ng2-archwizard

Afterwards you can import ng2-archwizard in your angular 2 project by adding the `WizardModule` to your Module declaration as followed:
```typescript
import {WizardModule} from "ng2-archwizard/dist";
import { WizardModule } from 'ng2-archwizard';

@NgModule({
imports: [
@@ -168,6 +168,27 @@ Possible `<wizard-step>` parameters:
| (stepEnter) | function(MovingDirection) | null |
| (stepExit) | function(MovingDirection) | null |

### \<wizard-completion-step\>
In addition to the "normal" step component `<wizard-step>` it's also possible to define an optional `<wizard-completion-step>`.
This wizard completion step is, if defined, always appended at the end of your wizard as its last step.
It is meant as a step, which signalises the user that he successfully completed the wizard.
When the wizard completion step has been entered by the user all wizard steps, including the optional steps, are marked as completed.
In addition the user gets prevented from leaving the wizard completion step to another step after it has been entered.

The given parameters for the wizard completion step are identical to the normal wizard step.
The only difference is, that it it isn't possible to pass a `(stepExit)` and `[canExit]` parameter to the wizard completion step,
because it can't be exited.

#### Parameter overview
Possible `<wizard-completion-step>` parameters:

| Parameter name | Possible Values | Default Value |
| ----------------------------- | ------------------------------------------------- | ------------- |
| [title] | string | null |
| [navigationSymbol] | string | '' |
| [navigationSymbolFontFamily] | string | null |
| (stepEnter) | function(MovingDirection) | null |

### \[optionalStep\]
If you need to define an optional step, that doesn't need to be done to continue to the next steps, you can define an optional step
by adding the `optionalStep` directive to the step you want to declare as optional.
5 changes: 5 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Created by marc on 14.05.17.
*/

export * from './dist';
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng2-archwizard",
"version": "1.4.1",
"version": "1.5.0",
"license": "MIT",
"description": "An angular 2 module containing a wizard component and its supporting components and directives",
"homepage": "https://github.com/madoar/ng2-archwizard",
@@ -84,15 +84,14 @@
"less-loader": "^4.0.3",
"node-sass": "^4.5.0",
"phantomjs-prebuilt": "^2.1.14",
"postcss-loader": "^1.3.0",
"protractor": "^5.1.1",
"raw-loader": "0.5.1",
"reflect-metadata": "^0.1.9",
"remap-istanbul": "^0.9.1",
"rimraf": "^2.6.1",
"rxjs": "^5.1.1",
"sass-loader": "^6.0.0",
"style-loader": "^0.17.0",
"style-loader": "^0.18.1",
"to-string-loader": "^1.1.5",
"ts-helpers": "^1.1.2",
"tslint": "^5.0.0",
@@ -105,6 +104,7 @@
"zone.js": "^0.8.5"
},
"files": [
"dist"
"dist",
"index.ts"
]
}
1 change: 1 addition & 0 deletions src/components/components/index.ts
Original file line number Diff line number Diff line change
@@ -5,3 +5,4 @@
export {WizardComponent} from './wizard.component';
export {WizardStepComponent} from './wizard-step.component';
export {WizardNavigationBarComponent} from './wizard-navigation-bar.component';
export {WizardCompletionStepComponent} from './wizard-completion-step.component';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:host {
height: auto;
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ng-content></ng-content>
136 changes: 136 additions & 0 deletions src/components/components/wizard-completion-step.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* Created by marc on 20.05.17.
*/
/* tslint:disable:no-unused-variable */
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {WizardStepComponent} from './wizard-step.component';
import {WizardCompletionStepComponent} from './wizard-completion-step.component';
import {ViewChild, Component} from '@angular/core';
import {WizardComponent} from './wizard.component';
import {MovingDirection} from '../util/MovingDirection';
import {WizardNavigationBarComponent} from './wizard-navigation-bar.component';
import {GoToStepDirective} from '../directives/go-to-step.directive';
import {By} from '@angular/platform-browser';
import {OptionalStepDirective} from '../directives/optional-step.directive';

@Component({
selector: 'test-wizard',
template: `
<wizard>
<wizard-step title='Steptitle 1' (stepEnter)="enterInto($event, 1)" (stepExit)="exitFrom($event, 1)">Step 1</wizard-step>
<wizard-step title='Steptitle 2' [canExit]="isValid"
optionalStep (stepEnter)="enterInto($event, 2)" (stepExit)="exitFrom($event, 2)">Step 2</wizard-step>
<wizard-completion-step title='Completion steptitle 3' (stepEnter)="enterInto($event, 3)">Step 3</wizard-completion-step>
</wizard>
`
})
class WizardTestComponent {
@ViewChild(WizardComponent)
public wizard: WizardComponent;

public isValid: any = true;

public eventLog: Array<string> = new Array<string>();

enterInto(direction: MovingDirection, destination: number): void {
this.eventLog.push(`enter ${MovingDirection[direction]} ${destination}`);
}

exitFrom(direction: MovingDirection, source: number): void {
this.eventLog.push(`exit ${MovingDirection[direction]} ${source}`);
}
}

describe('WizardCompletionStepComponent', () => {
let wizardTest: WizardTestComponent;
let wizardTestFixture: ComponentFixture<WizardTestComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [WizardComponent, WizardStepComponent, WizardCompletionStepComponent, WizardNavigationBarComponent,
WizardTestComponent, GoToStepDirective, OptionalStepDirective]
}).compileComponents();
}));

beforeEach(() => {
wizardTestFixture = TestBed.createComponent(WizardTestComponent);
wizardTest = wizardTestFixture.componentInstance;
wizardTestFixture.detectChanges();
});

it('should create', () => {
expect(wizardTest).toBeTruthy();
expect(wizardTestFixture.debugElement.queryAll(By.css('wizard-step')).length).toBe(2);
expect(wizardTestFixture.debugElement.queryAll(By.css('wizard-completion-step')).length).toBe(1);
});

it('should have correct step title', () => {
expect(wizardTest).toBeTruthy();
expect(wizardTest.wizard.getStepAtIndex(0).title).toBe('Steptitle 1');
expect(wizardTest.wizard.getStepAtIndex(1).title).toBe('Steptitle 2');
expect(wizardTest.wizard.getStepAtIndex(2).title).toBe('Completion steptitle 3');
});

it('should enter first step after initialisation', () => {
expect(wizardTest.eventLog).toEqual(['enter Forwards 1']);
});

it('should enter completion step after first step', () => {
expect(wizardTest.wizard.currentStepIndex).toBe(0);

wizardTest.wizard.goToNextStep();
wizardTestFixture.detectChanges();

expect(wizardTest.wizard.currentStepIndex).toBe(1);
expect(wizardTest.eventLog).toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 2']);

wizardTest.wizard.goToNextStep();
wizardTestFixture.detectChanges();

expect(wizardTest.wizard.currentStepIndex).toBe(2);
expect(wizardTest.eventLog).toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 2',
'exit Forwards 2', 'enter Forwards 3']);
});

it('should enter completion step after jumping over second optional step', () => {
wizardTest.wizard.goToStep(2);
wizardTestFixture.detectChanges();

expect(wizardTest.eventLog).toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 3']);
});

it('should be unable to leave the completion step', () => {
wizardTest.wizard.goToStep(2);
wizardTestFixture.detectChanges();

expect(wizardTest.wizard.canGoToStep(0)).toBe(false);
expect(wizardTest.wizard.canGoToStep(1)).toBe(false);
});


it('should not be able to leave the completion step in any direction', () => {
wizardTest.isValid = false;

wizardTest.wizard.goToStep(2);
wizardTestFixture.detectChanges();

expect(wizardTest.wizard.currentStepIndex).toBe(2);
expect(wizardTest.wizard.currentStep.canExit).toBe(false);
});

it('should not leave the completion step if it can\'t be exited', () => {
wizardTest.isValid = false;

wizardTest.wizard.goToStep(2);
wizardTestFixture.detectChanges();

expect(wizardTest.wizard.currentStepIndex).toBe(2);

wizardTest.wizard.goToPreviousStep();
wizardTestFixture.detectChanges();

expect(wizardTest.wizard.currentStepIndex).toBe(2);
expect(wizardTest.eventLog)
.toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 3', 'enter Stay 3']);
});
});
75 changes: 75 additions & 0 deletions src/components/components/wizard-completion-step.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Created by marc on 20.05.17.
*/

import {Component, EventEmitter, HostBinding, Input, Output} from '@angular/core';
import {MovingDirection} from '../util/MovingDirection';
import {WizardComponent} from './wizard.component';
import {WizardStep} from '../util/WizardStep';

@Component({
selector: 'wizard-completion-step',
templateUrl: 'wizard-completion-step.component.html',
styleUrls: ['wizard-completion-step.component.css']
})
export class WizardCompletionStepComponent implements WizardStep {
/**
* The visible title of this step in the navigation bar of this wizard
*/
@Input()
public title: string;

/**
* The symbol which is visible inside the circle belonging to this wizard step in the navigation bar.
*
* @type {string}
*/
@Input()
public navigationSymbol = '';

/**
* The font in which the navigation symbol should be shown.
* If no font is specified the system one should be taken.
*/
@Input()
public navigationSymbolFontFamily: string;

/**
* This EventEmitter is called when this step is entered.
* The bound method should do initializing work.
*
* @type {EventEmitter<MovingDirection>}
*/
@Output()
public stepEnter = new EventEmitter<MovingDirection>();

/**
* This EventEmitter is called when this step is exited.
*
* @type {EventEmitter<MovingDirection>}
*/
public stepExit = new EventEmitter<MovingDirection>();

@HostBinding('hidden')
public get hidden(): boolean {
return !this.selected;
}

public completed: false;
public selected = false;
public optional = false;

public canExit: ((direction: MovingDirection) => boolean) | boolean = false;

constructor(private wizard: WizardComponent) {
}

enter(direction: MovingDirection): void {
this.wizard.completed = true;
this.stepEnter.emit(direction);
}

exit(direction: MovingDirection): void {
// do nothing
}
}
14 changes: 7 additions & 7 deletions src/components/components/wizard-navigation-bar.component.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<ul class="steps-indicator steps-{{numberOfWizardSteps()}}">
<li *ngFor="let step of getWizardSteps()"
<ul class="steps-indicator steps-{{numberOfWizardSteps}}">
<li *ngFor="let step of wizardSteps"
[attr.step-symbol]="step.navigationSymbol"
[ngStyle]="{
'font-family': step.navigationSymbolFontFamily
}"
[ngClass]="{
default: !step.completed && !step.selected,
current: step.selected && !step.completed,
done: step.completed && !step.selected,
editing: step.selected && step.completed,
optional: step.optional && !step.completed && !step.selected
default: !step.optional && !step.completed && !step.selected && !wizard.completed,
current: (step.selected && !step.completed && !wizard.completed),
done: (step.completed && !step.selected) || wizard.completed,
editing: step.selected && step.completed && !wizard.completed,
optional: step.optional && !step.completed && !step.selected && !wizard.completed
}">
<div>
<a [goToStep]="step">{{step.title}}</a>
Loading

0 comments on commit c6a924b

Please # to comment.