Skip to content

Commit

Permalink
[#2109] Add search by tag functionality (#2116)
Browse files Browse the repository at this point in the history
Add search by tag functionality

It can be useful to search author/repos by git tags.

Let's add this functionality to make it easier to filter by tags.
  • Loading branch information
jonasongg committed Mar 19, 2024
1 parent bb977ea commit 147f473
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 20 deletions.
1 change: 1 addition & 0 deletions docs/ug/usingReports.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ The `Tool Bar` at the top of the Chart panel provides a set of configuration opt
* Multiple keywords/terms can be used, separated by spaces.
* Entries that contain _any_ (not necessarily _all_) of the search terms will be displayed.
* The keywords used to filter the author and repository are case-insensitive.
* Starting a search with `tag:` will filter author and repository by git tags. Similar search rules as above (like separating multiple tag names by space) apply.
* `Group by`: grouping criteria for the rows of results.
* `None`: results will not be grouped in any particular way.
* `Repo/Branch`: results will be grouped by repositories and its' associating branches.
Expand Down
119 changes: 115 additions & 4 deletions frontend/cypress/tests/chartView/chartView_toolBar_searchBox.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ describe('search bar', () => {
.type('abcdef')
.type('{enter}');

// Enter does not work. Related issue: https://github.com/cypress-io/cypress/issues/3405
// Let's manually submit form
cy.get('#summary-wrapper form.summary-picker')
.submit();

Expand All @@ -23,8 +21,6 @@ describe('search bar', () => {
.type('Yong Hao TENG')
.type('{enter}');

// Enter does not work. Related issue: https://github.com/cypress-io/cypress/issues/3405
// Let's manually submit form
cy.get('#summary-wrapper form.summary-picker')
.submit();

Expand All @@ -33,4 +29,119 @@ describe('search bar', () => {
expect(children).to.equal(1);
});
});

it('searching by non-existent tag shows no results', () => {
cy.get('#app #tab-resize .tab-close').click();
cy.get('#summary-wrapper input[type=text]')
.type('tag: asdfghjkl')
.type('{enter}');

cy.get('#summary-wrapper form.summary-picker')
.submit();

cy.get('#summary-wrapper #summary-charts')
.should('be.empty');
});

it("searching tag that only exists in one author's commits shows one result", () => {
cy.get('#app #tab-resize .tab-close').click();
cy.get('#summary-wrapper input[type=text]')
.type('tag: v1.8')
.type('{enter}');

cy.get('#summary-wrapper form.summary-picker')
.submit();

cy.get('.summary-chart__title--name')
.should('have.length', 1)
.and('contain', 'Eugene (eugenepeh)');

cy.get('.icon-button.fa-list-ul')
.should('exist')
.first()
.click();

cy.get('.zoom__title--tags > .tag span')
.should('contain', 'v1.8');
});

it("searching tag that only exists in two authors' commits shows two results", () => {
cy.get('#app #tab-resize .tab-close').click();
cy.get('#summary-wrapper input[type=text]')
.type('tag: v1.10')
.type('{enter}');

cy.get('#summary-wrapper form.summary-picker')
.submit();

cy.get('.summary-chart__title--name')
.should('have.length', 2)
.and('contain', 'Eugene (eugenepeh)')
.and('contain', 'James (jamessspanggg)');

cy.get('.icon-button.fa-list-ul')
.should('exist')
.each(($ele) => {
cy.wrap($ele).click();
cy.get('.zoom__title--tags > .tag span')
.should('contain', 'v1.10');
});
});

it("search field doesn't start with 'tag:' prefix but still contains it shows no results", () => {
cy.get('#app #tab-resize .tab-close').click();
cy.get('#summary-wrapper input[type=text]')
.type('v1.10 tag: v1.10')
.type('{enter}');

cy.get('#summary-wrapper form.summary-picker')
.submit();

cy.get('#summary-wrapper #summary-charts')
.should('be.empty');
});

it("search field doesn't contain 'tag:' at all shows no results", () => {
cy.get('#app #tab-resize .tab-close').click();
cy.get('#summary-wrapper input[type=text]')
.type('v1.10')
.type('{enter}');

cy.get('#summary-wrapper form.summary-picker')
.submit();

cy.get('#summary-wrapper #summary-charts')
.should('be.empty');
});

it('searching for multiple tags shows results containing all the tags searched', () => {
cy.get('#app #tab-resize .tab-close').click();
cy.get('#summary-wrapper input[type=text]')
.type('tag: bb v1.10')
.type('{enter}');

cy.get('#summary-wrapper form.summary-picker')
.submit();

cy.get('.summary-chart__title--name')
.should('have.length', 2)
.and('contain', 'Eugene (eugenepeh)')
.and('contain', 'James (jamessspanggg)');

cy.get('.icon-button.fa-list-ul')
.should('exist')
.first()
.click();

cy.get('.zoom__title--tags > .tag span')
.should('contain', 'bb');

cy.get('.icon-button.fa-list-ul')
.should('exist')
.eq(1)
.click();

cy.get('.zoom__title--tags > .tag span')
.should('contain', 'v1.10');
});
});
65 changes: 49 additions & 16 deletions frontend/src/views/c-summary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ import {
CommitResult,
} from '../types/types';
import { ErrorMessage } from '../types/zod/summary-type';
import { AuthorFileTypeContributions, FileTypeAndContribution } from '../types/zod/commits-type';
import {
AuthorDailyContributions,
AuthorFileTypeContributions,
FileTypeAndContribution,
} from '../types/zod/commits-type';
import { ZoomInfo } from '../types/vuex.d';
import {
FilterGroupSelection, FilterTimeFrame, SortGroupSelection, SortWithinGroupSelection,
Expand Down Expand Up @@ -472,6 +476,13 @@ export default defineComponent({
.some((param) => user.searchPath.includes(param));
},
isMatchSearchedTag(filterSearch: string, tag: string) {
return !filterSearch || filterSearch.toLowerCase()
.split(' ')
.filter(Boolean)
.some((param) => tag.includes(param));
},
toggleBreakdown() {
// Reset the file type filter
if (this.checkedFileTypes.length !== this.fileTypes.length) {
Expand All @@ -493,29 +504,51 @@ export default defineComponent({
getFilteredRepos() {
// array of array, sorted by repo
const full: Array<Array<User>> = [];
const tagSearchPrefix = 'tag:';
// create deep clone of this.repos to not modify the original content of this.repos
// when merging groups
const groups = this.hasMergedGroups() ? JSON.parse(JSON.stringify(this.repos)) as Array<Repo> : this.repos;
groups.forEach((repo) => {
const res: Array<User> = [];
const res: Array<User> = [];
// filtering
repo.users?.forEach((user) => {
if (this.isMatchSearchedUser(this.filterSearch, user)) {
this.getUserCommits(user, this.filterSinceDate, this.filterUntilDate);
if (this.filterTimeFrame === 'week') {
this.splitCommitsWeek(user, this.filterSinceDate, this.filterUntilDate);
if (this.filterSearch.startsWith(tagSearchPrefix)) {
const searchedTags = this.filterSearch.split(tagSearchPrefix)[1];
groups.forEach((repo) => {
const commits = repo.commits;
if (!commits) return;
Object.entries(commits.authorDailyContributionsMap).forEach(([author, contributions]) => {
contributions = contributions as Array<AuthorDailyContributions>;
const tags = contributions.flatMap((c) => c.commitResults).flatMap((r) => r.tags);
if (tags.some((tag) => tag && this.isMatchSearchedTag(searchedTags, tag))) {
const user = repo.users?.find((u) => u.name === author);
if (user) {
this.updateCheckedFileTypeContribution(user);
res.push(user);
}
}
this.updateCheckedFileTypeContribution(user);
res.push(user);
}
});
});
} else {
groups.forEach((repo) => {
// filtering
repo.users?.forEach((user) => {
if (this.isMatchSearchedUser(this.filterSearch, user)) {
this.getUserCommits(user, this.filterSinceDate, this.filterUntilDate);
if (this.filterTimeFrame === 'week') {
this.splitCommitsWeek(user, this.filterSinceDate, this.filterUntilDate);
}
this.updateCheckedFileTypeContribution(user);
res.push(user);
}
});
});
}
if (res.length) {
full.push(res);
}
});
if (res.length) {
full.push(res);
}
this.filtered = full;
this.getOptionWithOrder();
Expand Down

0 comments on commit 147f473

Please sign in to comment.