fix pasting in search bar after page load showing no results
This commit is contained in:
@@ -2,6 +2,7 @@ import { IFilterResult } from './IFilterResult';
|
|||||||
import { ISignal } from '@/infrastructure/Events/Signal';
|
import { ISignal } from '@/infrastructure/Events/Signal';
|
||||||
|
|
||||||
export interface IUserFilter {
|
export interface IUserFilter {
|
||||||
|
readonly currentFilter: IFilterResult | undefined;
|
||||||
readonly filtered: ISignal<IFilterResult>;
|
readonly filtered: ISignal<IFilterResult>;
|
||||||
readonly filterRemoved: ISignal<void>;
|
readonly filterRemoved: ISignal<void>;
|
||||||
setFilter(filter: string): void;
|
setFilter(filter: string): void;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Signal } from '@/infrastructure/Events/Signal';
|
|||||||
export class UserFilter implements IUserFilter {
|
export class UserFilter implements IUserFilter {
|
||||||
public readonly filtered = new Signal<IFilterResult>();
|
public readonly filtered = new Signal<IFilterResult>();
|
||||||
public readonly filterRemoved = new Signal<void>();
|
public readonly filterRemoved = new Signal<void>();
|
||||||
|
public currentFilter: IFilterResult | undefined;
|
||||||
|
|
||||||
constructor(private application: IApplication) {
|
constructor(private application: IApplication) {
|
||||||
|
|
||||||
@@ -28,11 +29,12 @@ export class UserFilter implements IUserFilter {
|
|||||||
filteredCategories,
|
filteredCategories,
|
||||||
filter,
|
filter,
|
||||||
);
|
);
|
||||||
|
this.currentFilter = matches;
|
||||||
this.filtered.notify(matches);
|
this.filtered.notify(matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeFilter(): void {
|
public removeFilter(): void {
|
||||||
|
this.currentFilter = undefined;
|
||||||
this.filterRemoved.notify();
|
this.filterRemoved.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
state.filter.filtered.on(this.handleFiltered);
|
state.filter.filtered.on(this.handleFiltered);
|
||||||
// Update initial state
|
// Update initial state
|
||||||
await this.initializeNodesAsync(this.categoryId);
|
await this.initializeNodesAsync(this.categoryId);
|
||||||
|
await this.initializeFilter(state.filter.currentFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async toggleNodeSelectionAsync(event: INodeSelectedEvent) {
|
public async toggleNodeSelectionAsync(event: INodeSelectedEvent) {
|
||||||
@@ -84,6 +85,14 @@
|
|||||||
(category: ICategory) => node.id === getCategoryNodeId(category));
|
(category: ICategory) => node.id === getCategoryNodeId(category));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initializeFilter(currentFilter: IFilterResult | undefined) {
|
||||||
|
if (!currentFilter) {
|
||||||
|
this.handleFilterRemoved();
|
||||||
|
} else {
|
||||||
|
this.handleFiltered(currentFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private handleSelectionChanged(selectedScripts: ReadonlyArray<SelectedScript>): void {
|
private handleSelectionChanged(selectedScripts: ReadonlyArray<SelectedScript>): void {
|
||||||
this.selectedNodeIds = selectedScripts
|
this.selectedNodeIds = selectedScripts
|
||||||
.map((node) => node.id);
|
.map((node) => node.id);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
Node,
|
Node,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class SelectableTree extends Vue {
|
export default class SelectableTree extends Vue { // Keep it stateless to make it easier to switch out
|
||||||
@Prop() public filterPredicate?: FilterPredicate;
|
@Prop() public filterPredicate?: FilterPredicate;
|
||||||
@Prop() public filterText?: string;
|
@Prop() public filterText?: string;
|
||||||
@Prop() public selectedNodeIds?: ReadonlyArray<string>;
|
@Prop() public selectedNodeIds?: ReadonlyArray<string>;
|
||||||
|
|||||||
@@ -72,7 +72,6 @@
|
|||||||
public isSearching = false;
|
public isSearching = false;
|
||||||
public searchHasMatches = false;
|
public searchHasMatches = false;
|
||||||
|
|
||||||
|
|
||||||
public async mounted() {
|
public async mounted() {
|
||||||
const state = await this.getCurrentStateAsync();
|
const state = await this.getCurrentStateAsync();
|
||||||
this.repositoryUrl = state.app.repositoryUrl;
|
this.repositoryUrl = state.app.repositoryUrl;
|
||||||
|
|||||||
@@ -7,129 +7,156 @@ import 'mocha';
|
|||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
|
|
||||||
describe('UserFilter', () => {
|
describe('UserFilter', () => {
|
||||||
it('signals when removing filter', () => {
|
describe('removeFilter', () => {
|
||||||
// arrange
|
it('signals when removing filter', () => {
|
||||||
let isCalled = false;
|
|
||||||
const sut = new UserFilter(new ApplicationStub());
|
|
||||||
sut.filterRemoved.on(() => isCalled = true);
|
|
||||||
// act
|
|
||||||
sut.removeFilter();
|
|
||||||
// assert
|
|
||||||
expect(isCalled).to.be.equal(true);
|
|
||||||
});
|
|
||||||
it('signals when no matches', () => {
|
|
||||||
// arrange
|
|
||||||
let actual: IFilterResult;
|
|
||||||
const nonMatchingFilter = 'non matching filter';
|
|
||||||
const sut = new UserFilter(new ApplicationStub());
|
|
||||||
sut.filtered.on((filterResult) => actual = filterResult);
|
|
||||||
// act
|
|
||||||
sut.setFilter(nonMatchingFilter);
|
|
||||||
// assert
|
|
||||||
expect(actual.hasAnyMatches()).be.equal(false);
|
|
||||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
|
||||||
expect(actual.scriptMatches).to.have.lengthOf(0);
|
|
||||||
expect(actual.query).to.equal(nonMatchingFilter);
|
|
||||||
});
|
|
||||||
describe('signals when script matches', () => {
|
|
||||||
it('code matches', () => {
|
|
||||||
// arrange
|
// arrange
|
||||||
const code = 'HELLO world';
|
let isCalled = false;
|
||||||
const filter = 'Hello WoRLD';
|
const sut = new UserFilter(new ApplicationStub());
|
||||||
let actual: IFilterResult;
|
sut.filterRemoved.on(() => isCalled = true);
|
||||||
const script = new ScriptStub('id').withCode(code);
|
|
||||||
const category = new CategoryStub(33).withScript(script);
|
|
||||||
const sut = new UserFilter(new ApplicationStub()
|
|
||||||
.withAction(category));
|
|
||||||
sut.filtered.on((filterResult) => actual = filterResult);
|
|
||||||
// act
|
// act
|
||||||
sut.setFilter(filter);
|
sut.removeFilter();
|
||||||
// assert
|
// assert
|
||||||
expect(actual.hasAnyMatches()).be.equal(true);
|
expect(isCalled).to.be.equal(true);
|
||||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
|
||||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
|
||||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
|
||||||
expect(actual.query).to.equal(filter);
|
|
||||||
});
|
});
|
||||||
it('revertCode matches', () => {
|
it('currentFilter is undefined', () => {
|
||||||
// arrange
|
// arrange
|
||||||
const revertCode = 'HELLO world';
|
const sut = new UserFilter(new ApplicationStub());
|
||||||
const filter = 'Hello WoRLD';
|
|
||||||
let actual: IFilterResult;
|
|
||||||
const script = new ScriptStub('id').withRevertCode(revertCode);
|
|
||||||
const category = new CategoryStub(33).withScript(script);
|
|
||||||
const sut = new UserFilter(new ApplicationStub()
|
|
||||||
.withAction(category));
|
|
||||||
sut.filtered.on((filterResult) => actual = filterResult);
|
|
||||||
// act
|
// act
|
||||||
sut.setFilter(filter);
|
sut.removeFilter();
|
||||||
// assert
|
// assert
|
||||||
expect(actual.hasAnyMatches()).be.equal(true);
|
expect(sut.currentFilter).to.be.equal(undefined);
|
||||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
|
||||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
|
||||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
|
||||||
expect(actual.query).to.equal(filter);
|
|
||||||
});
|
|
||||||
it('name matches', () => {
|
|
||||||
// arrange
|
|
||||||
const name = 'HELLO world';
|
|
||||||
const filter = 'Hello WoRLD';
|
|
||||||
let actual: IFilterResult;
|
|
||||||
const script = new ScriptStub('id').withName(name);
|
|
||||||
const category = new CategoryStub(33).withScript(script);
|
|
||||||
const sut = new UserFilter(new ApplicationStub()
|
|
||||||
.withAction(category));
|
|
||||||
sut.filtered.on((filterResult) => actual = filterResult);
|
|
||||||
// act
|
|
||||||
sut.setFilter(filter);
|
|
||||||
// assert
|
|
||||||
expect(actual.hasAnyMatches()).be.equal(true);
|
|
||||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
|
||||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
|
||||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
|
||||||
expect(actual.query).to.equal(filter);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('signals when category matches', () => {
|
describe('setFilter', () => {
|
||||||
// arrange
|
it('signals when no matches', () => {
|
||||||
const categoryName = 'HELLO world';
|
// arrange
|
||||||
const filter = 'Hello WoRLD';
|
let actual: IFilterResult;
|
||||||
let actual: IFilterResult;
|
const nonMatchingFilter = 'non matching filter';
|
||||||
const category = new CategoryStub(55).withName(categoryName);
|
const sut = new UserFilter(new ApplicationStub());
|
||||||
const sut = new UserFilter(new ApplicationStub()
|
sut.filtered.on((filterResult) => actual = filterResult);
|
||||||
.withAction(category));
|
// act
|
||||||
sut.filtered.on((filterResult) => actual = filterResult);
|
sut.setFilter(nonMatchingFilter);
|
||||||
// act
|
// assert
|
||||||
sut.setFilter(filter);
|
expect(actual.hasAnyMatches()).be.equal(false);
|
||||||
// assert
|
expect(actual.query).to.equal(nonMatchingFilter);
|
||||||
expect(actual.hasAnyMatches()).be.equal(true);
|
});
|
||||||
expect(actual.categoryMatches).to.have.lengthOf(1);
|
it('sets currentFilter as expected when no matches', () => {
|
||||||
expect(actual.categoryMatches[0]).to.deep.equal(category);
|
// arrange
|
||||||
expect(actual.scriptMatches).to.have.lengthOf(0);
|
const nonMatchingFilter = 'non matching filter';
|
||||||
expect(actual.query).to.equal(filter);
|
const sut = new UserFilter(new ApplicationStub());
|
||||||
});
|
// act
|
||||||
it('signals when category and script matches', () => {
|
sut.setFilter(nonMatchingFilter);
|
||||||
// arrange
|
// assert
|
||||||
const matchingText = 'HELLO world';
|
const actual = sut.currentFilter;
|
||||||
const filter = 'Hello WoRLD';
|
expect(actual.hasAnyMatches()).be.equal(false);
|
||||||
let actual: IFilterResult;
|
expect(actual.query).to.equal(nonMatchingFilter);
|
||||||
const script = new ScriptStub('script')
|
});
|
||||||
.withName(matchingText);
|
describe('signals when script matches', () => {
|
||||||
const category = new CategoryStub(55)
|
it('code matches', () => {
|
||||||
.withName(matchingText)
|
// arrange
|
||||||
.withScript(script);
|
const code = 'HELLO world';
|
||||||
const app = new ApplicationStub()
|
const filter = 'Hello WoRLD';
|
||||||
.withAction(category);
|
let actual: IFilterResult;
|
||||||
const sut = new UserFilter(app);
|
const script = new ScriptStub('id').withCode(code);
|
||||||
sut.filtered.on((filterResult) => actual = filterResult);
|
const category = new CategoryStub(33).withScript(script);
|
||||||
// act
|
const sut = new UserFilter(new ApplicationStub()
|
||||||
sut.setFilter(filter);
|
.withAction(category));
|
||||||
// assert
|
sut.filtered.on((filterResult) => actual = filterResult);
|
||||||
expect(actual.hasAnyMatches()).be.equal(true);
|
// act
|
||||||
expect(actual.categoryMatches).to.have.lengthOf(1);
|
sut.setFilter(filter);
|
||||||
expect(actual.categoryMatches[0]).to.deep.equal(category);
|
// assert
|
||||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
expect(actual.hasAnyMatches()).be.equal(true);
|
||||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
expect(actual.categoryMatches).to.have.lengthOf(0);
|
||||||
expect(actual.query).to.equal(filter);
|
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||||
|
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||||
|
expect(actual.query).to.equal(filter);
|
||||||
|
expect(sut.currentFilter).to.deep.equal(actual);
|
||||||
|
});
|
||||||
|
it('revertCode matches', () => {
|
||||||
|
// arrange
|
||||||
|
const revertCode = 'HELLO world';
|
||||||
|
const filter = 'Hello WoRLD';
|
||||||
|
let actual: IFilterResult;
|
||||||
|
const script = new ScriptStub('id').withRevertCode(revertCode);
|
||||||
|
const category = new CategoryStub(33).withScript(script);
|
||||||
|
const sut = new UserFilter(new ApplicationStub()
|
||||||
|
.withAction(category));
|
||||||
|
sut.filtered.on((filterResult) => actual = filterResult);
|
||||||
|
// act
|
||||||
|
sut.setFilter(filter);
|
||||||
|
// assert
|
||||||
|
expect(actual.hasAnyMatches()).be.equal(true);
|
||||||
|
expect(actual.categoryMatches).to.have.lengthOf(0);
|
||||||
|
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||||
|
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||||
|
expect(actual.query).to.equal(filter);
|
||||||
|
expect(sut.currentFilter).to.deep.equal(actual);
|
||||||
|
});
|
||||||
|
it('name matches', () => {
|
||||||
|
// arrange
|
||||||
|
const name = 'HELLO world';
|
||||||
|
const filter = 'Hello WoRLD';
|
||||||
|
let actual: IFilterResult;
|
||||||
|
const script = new ScriptStub('id').withName(name);
|
||||||
|
const category = new CategoryStub(33).withScript(script);
|
||||||
|
const sut = new UserFilter(new ApplicationStub()
|
||||||
|
.withAction(category));
|
||||||
|
sut.filtered.on((filterResult) => actual = filterResult);
|
||||||
|
// act
|
||||||
|
sut.setFilter(filter);
|
||||||
|
// assert
|
||||||
|
expect(actual.hasAnyMatches()).be.equal(true);
|
||||||
|
expect(actual.categoryMatches).to.have.lengthOf(0);
|
||||||
|
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||||
|
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||||
|
expect(actual.query).to.equal(filter);
|
||||||
|
expect(sut.currentFilter).to.deep.equal(actual);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('signals when category matches', () => {
|
||||||
|
// arrange
|
||||||
|
const categoryName = 'HELLO world';
|
||||||
|
const filter = 'Hello WoRLD';
|
||||||
|
let actual: IFilterResult;
|
||||||
|
const category = new CategoryStub(55).withName(categoryName);
|
||||||
|
const sut = new UserFilter(new ApplicationStub()
|
||||||
|
.withAction(category));
|
||||||
|
sut.filtered.on((filterResult) => actual = filterResult);
|
||||||
|
// act
|
||||||
|
sut.setFilter(filter);
|
||||||
|
// assert
|
||||||
|
expect(actual.hasAnyMatches()).be.equal(true);
|
||||||
|
expect(actual.categoryMatches).to.have.lengthOf(1);
|
||||||
|
expect(actual.categoryMatches[0]).to.deep.equal(category);
|
||||||
|
expect(actual.scriptMatches).to.have.lengthOf(0);
|
||||||
|
expect(actual.query).to.equal(filter);
|
||||||
|
expect(sut.currentFilter).to.deep.equal(actual);
|
||||||
|
});
|
||||||
|
it('signals when category and script matches', () => {
|
||||||
|
// arrange
|
||||||
|
const matchingText = 'HELLO world';
|
||||||
|
const filter = 'Hello WoRLD';
|
||||||
|
let actual: IFilterResult;
|
||||||
|
const script = new ScriptStub('script')
|
||||||
|
.withName(matchingText);
|
||||||
|
const category = new CategoryStub(55)
|
||||||
|
.withName(matchingText)
|
||||||
|
.withScript(script);
|
||||||
|
const app = new ApplicationStub()
|
||||||
|
.withAction(category);
|
||||||
|
const sut = new UserFilter(app);
|
||||||
|
sut.filtered.on((filterResult) => actual = filterResult);
|
||||||
|
// act
|
||||||
|
sut.setFilter(filter);
|
||||||
|
// assert
|
||||||
|
expect(actual.hasAnyMatches()).be.equal(true);
|
||||||
|
expect(actual.categoryMatches).to.have.lengthOf(1);
|
||||||
|
expect(actual.categoryMatches[0]).to.deep.equal(category);
|
||||||
|
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||||
|
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||||
|
expect(actual.query).to.equal(filter);
|
||||||
|
expect(sut.currentFilter).to.deep.equal(actual);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user