fabric8-planner
Version:
A planner front-end for Fabric8.
579 lines • 26.2 kB
JavaScript
import { ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { cloneDeep } from 'lodash';
import { Broadcaster } from 'ngx-base';
import { combineLatest } from 'rxjs';
import { delay, filter, map } from 'rxjs/operators';
import { AuthenticationService } from 'ngx-login-client';
import { AreaQuery } from '../../models/area.model';
import { WorkItemQuery } from '../../models/work-item';
import { WorkItemTypeQuery } from '../../models/work-item-type';
import { FilterService } from '../../services/filter.service';
import { AND, EQUAL } from '../../services/query-keys';
import { GroupTypeQuery } from './../../models/group-types.model';
import { IterationQuery } from './../../models/iteration.model';
import { LabelQuery } from './../../models/label.model';
import { UserQuery } from './../../models/user';
// ngrx stuff
import { select, Store } from '@ngrx/store';
import * as CustomQueryActions from './../../actions/custom-query.actions';
import { SpaceQuery } from './../../models/space';
var ToolbarPanelComponent = /** @class */ (function () {
function ToolbarPanelComponent(router, route, broadcaster, filterService, auth, store, cdr, userQuery, labelQuery, groupTypeQuery, iterationQuery, areaQuery, workItemQuery, workItemTypeQuery, spaceQuery) {
this.router = router;
this.route = route;
this.broadcaster = broadcaster;
this.filterService = filterService;
this.auth = auth;
this.store = store;
this.cdr = cdr;
this.userQuery = userQuery;
this.labelQuery = labelQuery;
this.groupTypeQuery = groupTypeQuery;
this.iterationQuery = iterationQuery;
this.areaQuery = areaQuery;
this.workItemQuery = workItemQuery;
this.workItemTypeQuery = workItemTypeQuery;
this.spaceQuery = spaceQuery;
this.loggedInUser = {};
this.dropdownPlacement = 'right'; // value is right or left
this.onCreateNewWorkItemSelected = new EventEmitter();
this.loggedIn = false;
this.showTypesOptions = false;
this.filters = [];
this.spaceSubscription = null;
this.eventListeners = [];
this.existingAllowedQueryParams = {};
this.filterConfig = {
fields: [{
id: 'type',
title: 'Select',
placeholder: 'Select a filter type',
type: 'select'
}],
appliedFilters: [],
resultsCount: -1,
selectedCount: 0,
totalCount: 0,
tooltipPlacement: 'right'
};
this.toolbarConfig = {
actionConfig: {},
filterConfig: this.filterConfig
};
this.allowedFilterKeys = [];
this.allowedMultipleFilterKeys = [
'label'
];
this.textFilterKeys = [
'title'
];
this.showSaveFilterButton = true;
this.isFilterSaveOpen = false;
// the type of the list is changed (Hierarchy/Flat).
this.currentListType = 'Hierarchy';
this.queryParamSubscriber = null;
this.savedFIlterFieldQueries = {};
this.separator = {
id: 'separator',
value: null,
separator: true
};
this.loader = {
id: 'loader',
value: 'Loading...',
iconStyleClass: 'fa fa-spinner'
};
this.activeFilters = [];
this.activeFilterFromSidePanel = '';
this.currentQuery = '';
this.isShowTreeOn = false;
this.isShowCompletedOn = false;
this.isStateFilterSelected = false;
this.routeSource = this.route.queryParams
.pipe(filter(function (p) { return p.hasOwnProperty('q'); }));
}
ToolbarPanelComponent.prototype.ngOnInit = function () {
var _this = this;
console.log('[ToolbarPanelComponent] Running in context: ' + this.context);
this.loggedIn = this.auth.isLoggedIn();
this.initiateDataSources();
//on the board view - do not show state filter as the lanes are based on state
this.allowedFilterKeys = [
'assignee', 'creator', 'area', 'label',
'workitemtype', 'title'
];
if (this.context !== 'boardview') {
this.allowedFilterKeys.push('state');
}
this.routeSource.subscribe(function (queryParam) { return _this.queryExp = queryParam.q; });
var customQueriesData = this.store
.pipe(select('planner'), select('customQueries'), filter(function (customQueries) { return !!customQueries.length; }));
this.totalCount = this.workItemQuery.getWorkItems()
.pipe(map(function (items) {
if (_this.isShowTreeOn) {
return items.filter(function (item) { return item.bold === true; }).length;
}
else {
return items.length;
}
}));
this.eventListeners.push(customQueriesData.subscribe(function (queries) {
var selected = queries.find(function (q) { return q.selected; });
if (selected) {
// if any selected saved filter found
// then save filter button will not be shown
// to avoid duplication
_this.showSaveFilterButton = false;
}
else {
_this.showSaveFilterButton = true;
}
}));
};
ToolbarPanelComponent.prototype.ngAfterViewInit = function () {
var _this = this;
// listen for logout events.
this.eventListeners.push(this.broadcaster.on('logout')
.subscribe(function (message) {
_this.loggedIn = false;
}));
this.eventListeners.push(this.filterData
.pipe(delay(1000))
.subscribe(function (filters) { return _this.setFilterTypes(filters); }));
this.eventListeners.push(combineLatest(this.areaQuery.getAreas(), this.userQuery.getCollaborators(), this.workItemTypeData, this.stateData, this.labelData).subscribe(function () {
// Once all the attributes are resolved
// Listen for the URLs to set applied filters
_this.checkURL();
_this.checkFilterFromSidePanle();
}));
};
ToolbarPanelComponent.prototype.ngOnDestroy = function () {
// make sure we unsubscribe from all events.
if (this.queryParamSubscriber) {
this.queryParamSubscriber.unsubscribe();
}
this.eventListeners.map(function (e) { return e.unsubscribe(); });
// clean up.
this.filterConfig.appliedFilters = [];
this.filterService.clearFilters(this.allowedFilterKeys);
};
ToolbarPanelComponent.prototype.setFilterTypes = function (filters) {
var _this = this;
filters = filters.filter(function (f) { return _this.allowedFilterKeys.indexOf(f.attributes.key) > -1; });
/*
* The current version of the patternfly filter dropdown does not fully support the async
* update of the filterConfig.fields fields set. It does not refresh the widget on field
* array change. The current workaround is to add a 'dummy' entry 'Select Filter..' as
* the first entry in the fields array. When the user selects a new value from the
* filter list, the implementation works subsequently.
*/
var filterMap = this.getFilterMap();
this.toolbarConfig.filterConfig.fields = [
this.toolbarConfig.filterConfig.fields[0]
].concat(filters.map(function (filter) {
var type = filter.attributes.key;
return {
id: type,
title: filter.attributes.title,
placeholder: filter.attributes.description,
type: filterMap[type].type,
queries: [_this.loader]
};
}));
};
ToolbarPanelComponent.prototype.filterChange = function ($event) {
this.toolbarConfig.filterConfig.appliedFilters = [];
var oldQueryJson = this.filterService.queryToJson(this.currentQuery);
var field = $event.field.id;
var value = $event.hasOwnProperty('query') ?
$event.query.id : $event.value;
var newQuery = this.filterService.queryBuilder(field, EQUAL, value);
var finalQuery = this.filterService.queryJoiner(oldQueryJson, AND, newQuery);
var queryString = this.filterService.jsonToQuery(finalQuery);
var queryParams = cloneDeep(this.route.snapshot.queryParams);
queryParams['q'] = queryString;
this.router.navigate([], {
relativeTo: this.route,
queryParams: queryParams
});
};
ToolbarPanelComponent.prototype.selectFilterType = function (event) {
var _this = this;
var filterMap = this.getFilterMap();
if (Object.keys(filterMap).indexOf(event.field.id) > -1) {
var index_1 = this.filterConfig.fields.findIndex(function (i) { return i.id === event.field.id; });
if (filterMap[event.field.id].type !== 'text') {
this.eventListeners.push(filterMap[event.field.id].datasource.subscribe(function (resp) {
if (filterMap[event.field.id].datamap(resp).primaryQueries.length) {
_this.toolbarConfig.filterConfig.fields[index_1].queries = filterMap[event.field.id].datamap(resp).primaryQueries.concat([
_this.separator
], filterMap[event.field.id].datamap(resp).queries);
}
else {
_this.toolbarConfig.filterConfig.fields[index_1].queries = filterMap[event.field.id].datamap(resp).queries;
}
_this.savedFIlterFieldQueries[_this.filterConfig.fields[index_1].id] = {};
_this.savedFIlterFieldQueries[_this.filterConfig.fields[index_1].id]['fixed'] = filterMap[event.field.id].datamap(resp).primaryQueries;
_this.savedFIlterFieldQueries[_this.filterConfig.fields[index_1].id]['filterable'] = filterMap[event.field.id].datamap(resp).queries;
}));
}
else if (this.filterConfig.fields[index_1].type === 'typeahead') {
this.filterQueries({
value: '',
field: event.field
});
}
}
};
/**
* For type ahead event handle
* from tool bar component
* @param event
*/
ToolbarPanelComponent.prototype.filterQueries = function (event) {
var index = this.filterConfig.fields.findIndex(function (i) { return i.id === event.field.id; });
var inp = event.value.trim();
if (inp) {
this.filterConfig.fields[index].queries = this.savedFIlterFieldQueries[event.field.id]['fixed'].concat([
this.separator
], this.savedFIlterFieldQueries[event.field.id]['filterable'].filter(function (item) {
return item.value.toLowerCase().indexOf(inp.toLowerCase()) > -1;
}));
}
if (inp === '' && typeof (this.savedFIlterFieldQueries[event.field.id]) !== 'undefined') {
this.filterConfig.fields[index].queries = this.savedFIlterFieldQueries[event.field.id]['fixed'].concat([
this.separator
], this.savedFIlterFieldQueries[event.field.id]['filterable']);
}
};
ToolbarPanelComponent.prototype.initiateDataSources = function () {
this.workItemTypeData = this.workItemTypeQuery.getWorkItemTypes()
.pipe(filter(function (a) { return !!a.length; }));
this.stateData = this.store
.pipe(select('planner'), select('workItemStates'), filter(function (a) { return !!a.length; }));
this.labelData = this.labelQuery.getLables()
.pipe(filter(function (l) { return l !== null; }));
this.spaceData = this.spaceQuery.getCurrentSpace
.pipe(filter(function (space) { return space !== null; }));
this.filterData = this.store
.pipe(select('toolbar'), select('filters'), filter(function (filters) { return !!filters.length; }));
this.iterationData = this.iterationQuery.getIterations()
.pipe(filter(function (i) { return !!i.length; }));
this.groupTypeData = this.groupTypeQuery.getGroupTypes
.pipe(filter(function (i) { return !!i.length; }));
};
ToolbarPanelComponent.prototype.getFilterMap = function () {
return {
area: {
datasource: this.areaQuery.getAreas(),
datamap: function (areas) {
return {
queries: areas.map(function (area) { return { id: area.id, value: area.name }; }),
primaryQueries: []
};
},
getvalue: function (area) { return area.name; },
type: 'select'
},
assignee: {
datasource: this.userQuery.getCollaborators(),
datamap: function (users) {
var currentUsers = users.filter(function (u) { return u.currentUser; });
var authUser = currentUsers.length ? currentUsers[0] : null;
return {
queries: users.filter(function (u) { return !u.currentUser; }).map(function (user) { return { id: user.id, value: user.username, imageUrl: user.avatar }; }),
primaryQueries: authUser ?
[{ id: authUser.id, value: authUser.username + ' (me)', imageUrl: authUser.avatar }, { id: null, value: 'Unassigned' }] :
[{ id: null, value: 'Unassigned' }]
};
},
type: 'typeahead'
},
creator: {
datasource: this.userQuery.getCollaborators(),
datamap: function (users) {
var currentUsers = users.filter(function (u) { return u.currentUser; });
var authUser = currentUsers.length ? currentUsers[0] : null;
return {
queries: users.filter(function (u) { return !u.currentUser; }).map(function (user) { return { id: user.id, value: user.username, imageUrl: user.avatar }; }),
primaryQueries: authUser ?
[{ id: authUser.id, value: authUser.username + ' (me)', imageUrl: authUser.avatar }] :
[]
};
},
getvalue: function (user) { return user.attributes.username; },
type: 'typeahead'
},
workitemtype: {
datasource: this.workItemTypeData,
datamap: function (witypes) {
return {
queries: witypes.sort(function (a, b) { return (a.name > b.name ? 1 : 0); }).map(function (witype) { return ({ id: witype.id, value: witype.name, iconStyleClass: witype.icon }); }),
primaryQueries: []
};
},
getvalue: function (type) { return type.name; },
type: 'select'
},
state: {
datasource: this.stateData,
datamap: function (wistates) {
return {
queries: wistates.map(function (wistate) { return { id: wistate, value: wistate }; }),
primaryQueries: []
};
},
getvalue: function (type) { return type; },
type: 'select'
},
label: {
datasource: this.labelData,
datamap: function (labels) {
return {
queries: labels.sort(function (l1, l2) { return (l1.name.toLowerCase() > l2.name.toLowerCase() ? 1 : 0); })
.map(function (label) {
return {
id: label.id,
value: label.name
};
}),
primaryQueries: []
};
},
getvalue: function (label) { return label.name; },
type: 'typeahead'
},
title: {
type: 'text'
}
};
};
ToolbarPanelComponent.prototype.checkURL = function () {
var _this = this;
this.eventListeners.push(this.route.queryParams.subscribe(function (query) {
if (query.hasOwnProperty('q')) {
_this.currentQuery = query.q;
var fields = _this.filterService.queryToFlat(_this.currentQuery);
var stateFilter = fields.findIndex(function (f) { return f.field === 'state'; });
_this.isStateFilterSelected = false;
if (stateFilter > -1) {
_this.isStateFilterSelected = true;
}
_this.handleShowTreeCheckBox();
_this.formatFilterFIelds(fields);
}
else {
_this.activeFilters = [];
_this.currentQuery = '';
}
}));
};
ToolbarPanelComponent.prototype.checkFilterFromSidePanle = function () {
var _this = this;
this.eventListeners.push(combineLatest(this.groupTypeData, this.iterationData)
.pipe(map(function (_a) {
var gt = _a[0], it = _a[1];
var selectedIt = it.find(function (i) { return i.selected; });
var selectedGt = gt.find(function (i) { return i.selected; });
return [selectedIt, selectedGt];
}), filter(function (_a) {
var gt = _a[0], it = _a[1];
return !!gt || !!it;
}), map(function (_a) {
var gt = _a[0], it = _a[1];
if (!!gt) {
return gt.name;
}
if (!!it) {
return it.name;
}
}))
.subscribe(function (selected) {
_this.activeFilterFromSidePanel = selected;
_this.cdr.markForCheck();
}));
};
ToolbarPanelComponent.prototype.formatFilterFIelds = function (fields) {
var _this = this;
combineLatest(this.areaQuery.getAreas(), this.userQuery.getCollaborators(), this.workItemTypeData, this.stateData, this.labelData).subscribe(function (_a) {
var areas = _a[0], users = _a[1], wiTypes = _a[2], states = _a[3], labels = _a[4];
var filterMap = _this.getFilterMap();
fields = fields.filter(function (f) {
return _this.allowedFilterKeys.indexOf(f.field) > -1;
});
_this.activeFilters = fields.map(function (f) {
switch (f.field) {
case 'creator':
case 'assignee':
var user = users.find(function (u) { return u.id === f.value; });
f['displayValue'] = f.value == 'null' ? 'Unassigned' :
(user ? user.username : f.value);
break;
case 'area':
var area = areas.find(function (a) { return a.id === f.value; });
f['displayValue'] = area ? area.name : f.value;
break;
case 'workitemtype':
var witype = wiTypes.find(function (w) { return w.id === f.value; });
f['displayValue'] = witype ? witype.name : f.value;
break;
case 'state':
var state = states.find(function (s) { return s === f.value; });
f['displayValue'] = state ? state : f.value;
break;
case 'label':
var label = labels.find(function (l) { return l.id === f.value; });
f['displayValue'] = label ? label.name : f.value;
break;
case 'title':
f['displayValue'] = f.value;
break;
default:
f['displayValue'] = '';
break;
}
return f;
}).slice();
});
};
ToolbarPanelComponent.prototype.removeFilter = function (field) {
if (field === void 0) { field = null; }
var fields = this.filterService.queryToFlat(this.currentQuery);
fields.splice(field.index, 1);
var queryString = this.filterService.jsonToQuery(this.filterService.flatToQuery(fields));
var queryParams = cloneDeep(this.route.snapshot.queryParams);
queryParams['q'] = queryString;
this.router.navigate([], {
relativeTo: this.route,
queryParams: queryParams
});
};
ToolbarPanelComponent.prototype.removeAllFilters = function () {
var _this = this;
var fields = this.filterService.queryToFlat(this.currentQuery).filter(function (f) {
return _this.activeFilters.findIndex(function (af) { return af.field === f.field && af.value === f.value; }) === -1;
});
var queryString = this.filterService.jsonToQuery(this.filterService.flatToQuery(fields));
var queryParams = cloneDeep(this.route.snapshot.queryParams);
queryParams['q'] = queryString;
this.router.navigate([], {
relativeTo: this.route,
queryParams: queryParams
});
};
ToolbarPanelComponent.prototype.saveFilters = function (filterSaveInp) {
if (filterSaveInp.value !== '') {
//let exp = JSON.stringify(this.filterService.queryToJson(this.queryExp));
var exp = this.queryExp;
var e1 = this.filterService.queryToJson(exp);
var str = '' + JSON.stringify(e1);
var customQuery = {
'attributes': {
'fields': str,
'title': filterSaveInp.value
},
'type': 'queries'
};
this.store.dispatch(new CustomQueryActions.Add(customQuery));
this.closeFilterSave(filterSaveInp);
}
};
ToolbarPanelComponent.prototype.showTreeToggle = function (e) {
var queryParams = cloneDeep(this.route.snapshot.queryParams);
if (e.target.checked) {
queryParams['showTree'] = true;
}
else {
if (queryParams.hasOwnProperty('showTree')) {
delete queryParams['showTree'];
}
}
this.router.navigate([], {
relativeTo: this.route,
queryParams: queryParams
});
};
ToolbarPanelComponent.prototype.showCompletedToggle = function (e) {
var queryParams = cloneDeep(this.route.snapshot.queryParams);
if (e.target.checked) {
queryParams['showCompleted'] = true;
}
else {
if (queryParams.hasOwnProperty('showCompleted')) {
delete queryParams['showCompleted'];
}
}
this.router.navigate([], {
relativeTo: this.route,
queryParams: queryParams
});
};
ToolbarPanelComponent.prototype.handleShowTreeCheckBox = function () {
var currentParams = cloneDeep(this.route.snapshot.queryParams);
if (currentParams.hasOwnProperty('showTree')) {
if (currentParams['showTree'] === 'true') {
this.isShowTreeOn = true;
}
else if (currentParams['showTree'] === 'false') {
this.isShowTreeOn = false;
}
}
else {
this.isShowTreeOn = false;
}
if (currentParams.hasOwnProperty('showCompleted')) {
if (currentParams['showCompleted'] === 'true') {
this.isShowCompletedOn = true;
}
else if (currentParams['showCompleted'] === 'false') {
this.isShowCompletedOn = false;
}
}
else {
this.isShowCompletedOn = false;
}
};
ToolbarPanelComponent.prototype.closeFilterSave = function (filterSaveInp) {
this.isFilterSaveOpen = false;
filterSaveInp.value = '';
};
ToolbarPanelComponent.prototype.saveFilterDropdownChange = function (value) {
this.isFilterSaveOpen = value;
};
ToolbarPanelComponent.decorators = [
{ type: Component, args: [{
encapsulation: ViewEncapsulation.None,
selector: 'toolbar-panel',
template: require('./toolbar-panel.component.html'),
styles: [require('./toolbar-panel.component.css').toString()]
},] },
];
/** @nocollapse */
ToolbarPanelComponent.ctorParameters = function () { return [
{ type: Router, },
{ type: ActivatedRoute, },
{ type: Broadcaster, },
{ type: FilterService, },
{ type: AuthenticationService, },
{ type: Store, },
{ type: ChangeDetectorRef, },
{ type: UserQuery, },
{ type: LabelQuery, },
{ type: GroupTypeQuery, },
{ type: IterationQuery, },
{ type: AreaQuery, },
{ type: WorkItemQuery, },
{ type: WorkItemTypeQuery, },
{ type: SpaceQuery, },
]; };
ToolbarPanelComponent.propDecorators = {
'context': [{ type: Input },],
'loggedInUser': [{ type: Input },],
'dropdownPlacement': [{ type: Input },],
'onCreateNewWorkItemSelected': [{ type: Output },],
};
return ToolbarPanelComponent;
}());
export { ToolbarPanelComponent };
//# sourceMappingURL=toolbar-panel.component.js.map