Skip to content

Commit

Permalink
feat(ui): new design for timeline filter (#3021)
Browse files Browse the repository at this point in the history
  • Loading branch information
sguiheux authored and fsamin committed Jul 10, 2018
1 parent da1c08a commit 49f48bc
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 157 deletions.
76 changes: 17 additions & 59 deletions engine/api/timeline.go
Expand Up @@ -25,47 +25,39 @@ func (api *API) getTimelineHandler() Handler {
return sdk.WrapError(errT, "getTimelineHandler> Unable to load timeline filter")
}

allPerm := make(map[string][]string)

jobs := make(chan timelineFilterJob, 50)
results := make(chan timelineFilterJob, 50)

for w := 1; w <= 3; w++ {
go haveToFilter(jobs, results, timelineFilter)
// Add all workflows to mute in a map
muteFilter := make(map[string]bool, len(timelineFilter.Projects))
for _, pf := range timelineFilter.Projects {
for _, wn := range pf.WorkflowNames {
muteFilter[pf.Key+"/"+wn] = true
}
}

permToRequest := make(map[string][]string, len(u.Permissions.WorkflowsPerm))
for k := range u.Permissions.WorkflowsPerm {
if _, ok := muteFilter[k]; ok {
continue
}

keySplitted := strings.Split(k, "/")
pKey := keySplitted[0]
wName := keySplitted[1]
j := timelineFilterJob{
Key: pKey,
WorkflowName: wName,
}
jobs <- j
}
close(jobs)

for a := 0; a < len(u.Permissions.WorkflowsPerm); a++ {
item := <-results
if !item.Add {
continue
}
workflows, ok := allPerm[item.Key]
pFilter, ok := permToRequest[pKey]
if !ok {
workflows = make([]string, 0, 1)
pFilter = make([]string, 0, 1)
}
workflows = append(workflows, item.WorkflowName)
allPerm[item.Key] = workflows
pFilter = append(pFilter, wName)
permToRequest[pKey] = pFilter
}

request := sdk.EventFilter{
CurrentItem: currentItem,
Filter: sdk.TimelineFilter{
Projects: make([]sdk.ProjectFilter, 0, len(allPerm)),
Projects: make([]sdk.ProjectFilter, 0, len(permToRequest)),
},
}
for k, v := range allPerm {
for k, v := range permToRequest {
pFilter := sdk.ProjectFilter{
Key: k,
WorkflowNames: v,
Expand All @@ -80,37 +72,3 @@ func (api *API) getTimelineHandler() Handler {
return WriteJSON(w, events, http.StatusOK)
}
}

type timelineFilterJob struct {
Key string
WorkflowName string
Add bool
}

func haveToFilter(jobs <-chan timelineFilterJob, results chan<- timelineFilterJob, filter sdk.TimelineFilter) {
for j := range jobs {
projectFound := false
insert := false
projLoop:
for _, pf := range filter.Projects {
if pf.Key == j.Key {
projectFound = true
for _, wName := range pf.WorkflowNames {
if wName == j.WorkflowName {
break projLoop
}
}
insert = true
break
}
}
if !projectFound {
insert = true
}
if insert {
j.Add = true
}

results <- j
}
}
2 changes: 1 addition & 1 deletion ui/src/app/app.service.ts
Expand Up @@ -76,7 +76,7 @@ export class AppService {
if (event.type_event === EventType.RUN_WORKFLOW_PREFIX) {
let mustAdd = true;
// Check if we have to mute it
if (this.filter) {
if (this.filter && this.filter.projects) {
let workflowList = this.filter.projects.find(p => p.key === event.project_key);
if (workflowList) {
let w = workflowList.workflow_names.find(wname => wname === event.workflow_name);
Expand Down
2 changes: 2 additions & 0 deletions ui/src/app/model/environment.model.ts
Expand Up @@ -10,4 +10,6 @@ export class Environment {
permission: number;
last_modified: number;
usage: Usage;

mute: boolean;
}
4 changes: 4 additions & 0 deletions ui/src/app/model/project.model.ts
Expand Up @@ -32,6 +32,7 @@ export class Project {
// true if someone has updated the project ( used for warnings )
externalChange: boolean;
loading: boolean;
mute: boolean;
}

export class LoadOpts {
Expand All @@ -45,4 +46,7 @@ export class IdName {
id: number;
name: string;
description?: string;

// ui params
mute: boolean;
}
18 changes: 9 additions & 9 deletions ui/src/app/service/project/project.store.spec.ts
@@ -1,19 +1,19 @@
/* tslint:disable:no-unused-variable */

import {async, TestBed} from '@angular/core/testing';
import {APP_BASE_HREF} from '@angular/common';
import {AppModule} from '../../app.module';
import {async, TestBed} from '@angular/core/testing';
import {RouterModule} from '@angular/router';
import {ProjectStore} from './project.store';
import {LoadOpts, Project} from '../../model/project.model';
import {Variable} from '../../model/variable.model';
import {Group, GroupPermission} from '../../model/group.model';
import {Environment} from '../../model/environment.model';
import {Observable} from 'rxjs/Observable';
import {first} from 'rxjs/operators';
import {AppModule} from '../../app.module';
import {Application} from '../../model/application.model';
import {Environment} from '../../model/environment.model';
import {Group, GroupPermission} from '../../model/group.model';
import {LoadOpts, Project} from '../../model/project.model';
import {RepositoriesManager} from '../../model/repositories.model';
import {first} from 'rxjs/operators';
import {Observable} from 'rxjs/Observable';
import {Variable} from '../../model/variable.model';
import {ProjectService} from './project.service';
import {ProjectStore} from './project.store';

describe('CDS: project Store', () => {

Expand Down
4 changes: 3 additions & 1 deletion ui/src/app/service/project/project.store.ts
Expand Up @@ -271,8 +271,10 @@ export class ProjectStore {
createProject(project: Project): Observable<Project> {
return this._projectService.addProject(project).pipe(map(res => {
let projects = this._projectNav.getValue();
if (!projects) {
projects = List();
}
this._projectNav.next(projects.push(project));

return res;
}));
}
Expand Down
Expand Up @@ -2,7 +2,6 @@ import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import { ApplicationStore } from 'app/service/services.module';
import {cloneDeep} from 'lodash';
import { finalize, first } from 'rxjs/operators';
import {Application} from '../../../../model/application.model';
import {Environment} from '../../../../model/environment.model';
import {IdName, Project} from '../../../../model/project.model';
import {WorkflowNode} from '../../../../model/workflow.model';
Expand Down Expand Up @@ -31,7 +30,7 @@ export class WorkflowNodeFormComponent implements OnInit {
this.environments = cloneDeep(this.project.environments) || [];
this.environments.unshift(voidEnv);

let voidApp = new Application();
let voidApp = new IdName();
voidApp.id = 0;
voidApp.name = ' ';
this.applications = cloneDeep(this.project.application_names) || [];
Expand Down
Expand Up @@ -117,13 +117,13 @@ export class WorkflowNodeAddWizardComponent implements OnInit {
}

if (Array.isArray(this.project.application_names)) {
let voidApp = new Application();
let voidApp = new IdName();
voidApp.id = 0;
voidApp.name = ' ';
this.applicationsName = [voidApp, ...this.project.application_names];
}
if (Array.isArray(this.project.environments)) {
let voidEnv = new Environment();
let voidEnv = new IdName();
voidEnv.id = 0;
voidEnv.name = ' ';
this.environmentsName = [voidEnv, ...this.project.environments];
Expand Down
Expand Up @@ -2,7 +2,7 @@ import {Component, Input} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {cloneDeep} from 'lodash';
import {finalize, first} from 'rxjs/operators';
import {LoadOpts, Project} from '../../../../model/project.model';
import {IdName, LoadOpts, Project} from '../../../../model/project.model';
import {ProjectFilter, TimelineFilter} from '../../../../model/timeline.model';
import {ProjectStore} from '../../../../service/project/project.store';
import {TimelineStore} from '../../../../service/timeline/timeline.store';
Expand All @@ -19,13 +19,15 @@ export class HomeTimelineFilterComponent {

_filter: TimelineFilter;
filterToEdit: TimelineFilter;

@Input('filter')
set filter(data: TimelineFilter) {
if (data) {
this._filter = data;
this.filterToEdit = cloneDeep(data);
}
}

get filter() {
return this.filterToEdit;
}
Expand Down Expand Up @@ -63,8 +65,7 @@ export class HomeTimelineFilterComponent {
let projFilter = new ProjectFilter();
projFilter.key = this.selectedProjectKey;
this.filter.projects.push(projFilter);

this.loadProjectWorkflow(projFilter);
this.loadProjectWorkflow(projFilter, true);

this.selectedProjectKey = '';
}
Expand All @@ -73,33 +74,8 @@ export class HomeTimelineFilterComponent {
this.filter.projects = this.filter.projects.filter(p => p.key !== pf.key);
}

removeWorkflow(pf: ProjectFilter, wname: string): void {
pf.workflow_names = pf.workflow_names.filter(w => w !== wname);
}

addWorkflow(projFilter: ProjectFilter): void {
if (!this.selectedWorkflow || this.selectedWorkflow === '') {
return;
}

if (projFilter.workflow_names) {
let exist = projFilter.workflow_names.find(w => w === this.selectedWorkflow);
if (exist) {
return;
}
} else {
projFilter.workflow_names = new Array<string>();
}
projFilter.workflow_names.push(this.selectedWorkflow);
this.selectedWorkflow = '';
}

openProject(projFilter: ProjectFilter): void {
projFilter.display = !projFilter.display;
this.loadProjectWorkflow(projFilter);
}

loadProjectWorkflow(projFilter: ProjectFilter) {
// load workflow when opening dropdown
loadProjectWorkflow(projFilter: ProjectFilter, mute: boolean) {
if (projFilter.project) {
return
}
Expand All @@ -109,13 +85,49 @@ export class HomeTimelineFilterComponent {
opts.push(new LoadOpts('withWorkflowNames', 'workflow_names'));
this._projectStore.resync(projFilter.key, opts).pipe(first(), finalize(() => projFilter.loading = false)).subscribe(proj => {
projFilter.project = proj;
if (projFilter.project && projFilter.project.workflow_names) {
projFilter.project.workflow_names.forEach(wn => {
if (mute) {
wn.mute = true;
} else {
let index = projFilter.workflow_names.findIndex(wwnn => wwnn === wn.name);
if (index >= 0) {
wn.mute = true;
} else {
wn.mute = false;
}
}
});
if (mute) {
projFilter.workflow_names = projFilter.project.workflow_names.map(idname => idname.name);
}
}

});
}

updateWorkflowInFilter(w: IdName, projFilter: ProjectFilter): void {
if (!projFilter.workflow_names) {
projFilter.workflow_names = new Array<string>();
}
w.mute = !w.mute;
if (!w.mute) {
let index = projFilter.workflow_names.findIndex(wn => wn === w.name);
if (index >= 0) {
projFilter.workflow_names.splice(index, 1);
}
} else {
let index = projFilter.workflow_names.findIndex(wn => wn === w.name);
if (index === -1) {
projFilter.workflow_names.push(w.name);
}
}
}

saveFilter(): void {
this.loading = true;
this._timelineStore.saveFilter(this.filter).pipe(finalize(() => this.loading = false)).subscribe(() => {
this._toast.success('', this._translate.instant('timeline_filter_updated'));
this._toast.success('', this._translate.instant('timeline_filter_updated'));
});
}

Expand Down

0 comments on commit 49f48bc

Please sign in to comment.