Skip to content

Commit

Permalink
[FEATURE] Clickable Steps (#282)
Browse files Browse the repository at this point in the history
* [FEATURE] Clickable Steps

* "version": "1.0.9"
  • Loading branch information
tomer-epstein authored May 20, 2020
1 parent 321cb7c commit df3cc6a
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 17 deletions.
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yeoman-ui",
"version": "1.0.8",
"version": "1.0.9",
"displayName": "Application Wizard",
"publisher": "SAPOS",
"author": {
Expand Down
8 changes: 6 additions & 2 deletions backend/src/replayUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class ReplayUtils {
private answersCache: Map<string, Environment.Adapter.Answers>;
private replayStack: Array<Environment.Adapter.Answers>;
private replayQueue: Array<Environment.Adapter.Answers>;
private numOfSteps: number;
private prompts: Array<IPrompt>;
public isReplaying: boolean;

Expand All @@ -26,10 +27,12 @@ export class ReplayUtils {
this.replayStack = [];
this.prompts = [];
this.answersCache.clear();
this.numOfSteps = 0;
}

start(questions: Environment.Adapter.Questions<any>, answers: Environment.Adapter.Answers): void {
start(questions: Environment.Adapter.Questions<any>, answers: Environment.Adapter.Answers, numOfSteps: number): void {
this._rememberAnswers(questions, answers);
this.numOfSteps = numOfSteps;
this.replayQueue = JSON.parse(JSON.stringify(this.replayStack));
this.isReplaying = true;
}
Expand All @@ -41,6 +44,7 @@ export class ReplayUtils {
this.replayQueue = [];
const answers: Environment.Adapter.Answers = this.replayStack.pop();
ReplayUtils.setDefaults(questions, answers);
this.replayStack.splice(this.replayStack.length - this.numOfSteps + 1);
return prompts;
}

Expand Down Expand Up @@ -74,7 +78,7 @@ export class ReplayUtils {

getReplayState(): ReplayState{
if (this.isReplaying) {
if (this.replayQueue.length > 1) {
if (this.replayQueue.length > this.numOfSteps) {
return ReplayState.Replaying;
} else {
return ReplayState.EndingReplay;
Expand Down
4 changes: 2 additions & 2 deletions backend/src/yeomanui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ export class YeomanUI {
return answers;
}

private back(partialAnswers: Environment.Adapter.Answers): void {
this.replayUtils.start(this.currentQuestions, partialAnswers);
private back(partialAnswers: Environment.Adapter.Answers, numOfSteps: number): void {
this.replayUtils.start(this.currentQuestions, partialAnswers, numOfSteps);
this.runGenerator(this.generatorName);
}

Expand Down
2 changes: 1 addition & 1 deletion backend/tests/yeomanui.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ describe('yeomanui unit test', () => {
// tslint:disable-next-line: no-unused-expression
expect(yeomanUiInstance["replayUtils"]["isReplaying"]).to.be.false;

yeomanUiInstance["back"](undefined);
yeomanUiInstance["back"](undefined,1);
// tslint:disable-next-line: no-unused-expression
expect(yeomanUiInstance["replayUtils"]["isReplaying"]).to.be.true;

Expand Down
15 changes: 10 additions & 5 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

<v-row class="main-row ma-0 pa-0">
<v-col class="left-col ma-0 pa-0" cols="3">
<Navigation v-if="prompts.length" :promptIndex="promptIndex" :prompts="prompts" />
<Navigation v-if="prompts.length" :promptIndex="promptIndex" :prompts="prompts" @onGotoStep="gotoStep" />
</v-col>
<v-col cols="9" class="right-col">
<v-row class="prompts-col">
Expand Down Expand Up @@ -115,7 +115,8 @@ function initialState() {
messages: {},
showBusyIndicator: false,
promptsInfoToDisplay: [],
isReplaying: false
isReplaying: false,
numOfSteps: 1
};
}
Expand Down Expand Up @@ -173,11 +174,15 @@ export default {
&& !this.isDone);
},
back() {
this.gotoStep(1); // go 1 step back
},
gotoStep(numOfSteps) { // go numOfSteps step back
try {
this.isReplaying = true;
this.numOfSteps = numOfSteps;
const answers = this.currentPrompt.answers;
if (this.promptIndex > 1) {
this.rpc.invoke("back", [answers]);
if (this.promptIndex - numOfSteps > 0) {
this.rpc.invoke("back", [answers, numOfSteps]);
} else {
this.reload();
}
Expand Down Expand Up @@ -282,7 +287,7 @@ export default {
async showPrompt(questions, name) {
this.prepQuestions(questions);
if (this.isReplaying) {
this.promptIndex--;
this.promptIndex -= this.numOfSteps;
this.isReplaying = false;
}
const prompt = this.createPrompt(questions, name);
Expand Down
24 changes: 21 additions & 3 deletions frontend/src/components/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
:key="`${index}-step`"
:step="index"
:complete="currentStep > index"
>{{ prompts[index - 1] ? prompts[index - 1].name : "" }}</v-stepper-step>
@click="gotoStep(currentStep - index)"
:class="getStepClass(currentStep, index)"
>
{{ prompts[index - 1] ? prompts[index - 1].name : "" }}
</v-stepper-step>
<v-stepper-content :step="index" :key="`${index}-content`"></v-stepper-content>
</template>
</v-stepper>
</div>
</template>


<script>
export default {
name: "Navigation",
Expand All @@ -25,7 +28,16 @@ export default {
steps: 1
};
},
methods: {
getStepClass(currentStep, index) {
return {'step-linkable' : currentStep > index};
},
gotoStep(numOfSteps) { // numOfSteps is number of steps to go back
if (numOfSteps > 0) {
this.$emit("onGotoStep", numOfSteps);
}
}
},
watch: {
promptIndex(val) {
this.$nextTick(() => {
Expand Down Expand Up @@ -105,5 +117,11 @@ div.v-application div.v-stepper.v-stepper--vertical .v-stepper__content:not(:las
background-position: left;
background-color:var(--vscode-editorCodeLens-foreground, #999999);
}
.step-linkable {
cursor: pointer;
}
.step-linkable:hover {
background-color: var(--vscode-list-hoverBackground,#2a2d2e);
}
</style>
46 changes: 43 additions & 3 deletions frontend/tests/App.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,9 @@ describe('App.vue', () => {

wrapper.vm.back();

expect(wrapper.vm.promptIndex).toBe(2);
expect(wrapper.vm.prompts.length).toBe(3);
expect(wrapper.vm.isReplaying).toBe(true);
expect(invokeSpy).toHaveBeenCalledWith("back", [undefined]);
expect(wrapper.vm.numOfSteps).toBe(1);
expect(invokeSpy).toHaveBeenCalledWith("back", [undefined,1]);
});

test('set props', async () => {
Expand All @@ -287,6 +286,47 @@ describe('App.vue', () => {
});
});

describe('gotoStep - method', () => {
test('promptIndex is 1, goto 1 step back -> (Select Generator)', () => {
wrapper = initComponent(App, {}, true);
wrapper.vm.rpc = {
invoke: jest.fn(),
registerMethod: jest.fn()
}
const invokeSpy = jest.spyOn(wrapper.vm.rpc, 'invoke');

wrapper.vm.resolve = undefined;
wrapper.vm.promptIndex = 1;
wrapper.vm.prompts = [{}, {}];

wrapper.vm.gotoStep(1);

expect(wrapper.vm.promptIndex).toBe(0);
expect(wrapper.vm.prompts.length).toBe(0);
expect(wrapper.vm.isReplaying).toBe(false);
expect(invokeSpy).toHaveBeenCalledWith("getState");
});

test('promptIndex is 3, goto 2 step back', async () => {
wrapper = initComponent(App, {}, true);
wrapper.vm.rpc = {
invoke: jest.fn(),
registerMethod: jest.fn()
}
const invokeSpy = jest.spyOn(wrapper.vm.rpc, 'invoke');

wrapper.vm.resolve = undefined;
wrapper.vm.promptIndex = 3;
wrapper.vm.prompts = [{}, {}, {}, {}];

wrapper.vm.gotoStep(2);

expect(wrapper.vm.isReplaying).toBe(true);
expect(wrapper.vm.numOfSteps).toBe(2);
expect(invokeSpy).toHaveBeenCalledWith("back", [undefined,2]);
});
});

describe('setPromptList - method', () => {
it('prompts is empty array', () => {
wrapper = initComponent(App)
Expand Down
55 changes: 55 additions & 0 deletions frontend/tests/components/Navigation.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { initComponent, destroy } from '../Utils'
import Navigation from '../../src/components/Navigation.vue'
import Vue from 'vue'
//There are issues of importing vuetify components https://github.com/vuejs/vue-cli/issues/1584
// import { VBtn } from 'vuetify/lib'

Expand Down Expand Up @@ -34,4 +35,58 @@ describe('Navigation.vue', () => {
expect(wrapper.vm.currentStep).toEqual(6)
});
})

describe('gotoStep', () => {
test('numOfSteps > 0', async () => {
wrapper = initComponent(Navigation,{promptIndex: 1,prompts: 1}, true)
expect(wrapper.vm.steps).toEqual(1)
expect(wrapper.vm.currentStep).toEqual(1)
wrapper.vm.$options.watch.prompts.call(wrapper.vm, [1,2,3])
expect(wrapper.vm.steps).toEqual(3)
wrapper.vm.$options.watch.promptIndex.call(wrapper.vm, 2)

await Vue.nextTick()
expect(wrapper.vm.currentStep).toEqual(3);

let numOfSteps = wrapper.vm.currentStep - 1;
wrapper.vm.gotoStep(numOfSteps);

expect(wrapper.emitted().onGotoStep).toBeTruthy();
})

test('numOfSteps = 0', async () => {
wrapper = initComponent(Navigation,{promptIndex: 1,prompts: 1}, true)
expect(wrapper.vm.steps).toEqual(1)
expect(wrapper.vm.currentStep).toEqual(1)
wrapper.vm.$options.watch.prompts.call(wrapper.vm, [1,2,3])
expect(wrapper.vm.steps).toEqual(3)
wrapper.vm.$options.watch.promptIndex.call(wrapper.vm, 2)

await Vue.nextTick()
expect(wrapper.vm.currentStep).toEqual(3);

let numOfSteps = wrapper.vm.currentStep - 3;
wrapper.vm.gotoStep(numOfSteps);

expect(wrapper.emitted().onGotoStep).toBeFalsy();
})
})

test('getStepClass method', async () => {
wrapper = initComponent(Navigation,{promptIndex: 1,prompts: 1}, true)
expect(wrapper.vm.steps).toEqual(1)
expect(wrapper.vm.currentStep).toEqual(1)
wrapper.vm.$options.watch.prompts.call(wrapper.vm, [1,2,3])
expect(wrapper.vm.steps).toEqual(3)
wrapper.vm.$options.watch.promptIndex.call(wrapper.vm, 2)

await Vue.nextTick()
expect(wrapper.vm.currentStep).toEqual(3);

let claz = wrapper.vm.getStepClass(wrapper.vm.currentStep, 1);
expect(claz).toEqual({'step-linkable' : true});

claz = wrapper.vm.getStepClass(wrapper.vm.currentStep, 3);
expect(claz).toEqual({'step-linkable' : false});
})
})

0 comments on commit df3cc6a

Please sign in to comment.