Remove modals from dropdown

pull/6245/head
Oliver Günther 7 years ago
parent 3d8eff243f
commit d0acc070d6
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 30
      frontend/app/angular4-modules.ts
  2. 115
      frontend/app/components/modals/columns-modal/columns-modal.controller.ts
  3. 89
      frontend/app/components/modals/columns-modal/columns-modal.service.html
  4. 40
      frontend/app/components/modals/columns-modal/columns-modal.service.ts
  5. 54
      frontend/app/components/modals/grouping-modal/grouping-modal.controller.ts
  6. 47
      frontend/app/components/modals/grouping-modal/grouping-modal.service.html
  7. 40
      frontend/app/components/modals/grouping-modal/grouping-modal.service.ts
  8. 107
      frontend/app/components/modals/sorting-modal/sorting-modal.controller.ts
  9. 56
      frontend/app/components/modals/sorting-modal/sorting-modal.service.html
  10. 40
      frontend/app/components/modals/sorting-modal/sorting-modal.service.ts
  11. 75
      frontend/app/components/modals/timelines-modal/timelines-modal.controller.ts
  12. 45
      frontend/app/components/modals/timelines-modal/timelines-modal.service.html
  13. 40
      frontend/app/components/modals/timelines-modal/timelines-modal.service.ts
  14. 20
      frontend/app/components/op-context-menu/handlers/op-settings-dropdown-menu.directive.ts
  15. 61
      frontend/app/components/op-modals/modals/columns-modal.component.html
  16. 120
      frontend/app/components/op-modals/modals/columns-modal.component.ts
  17. 1
      frontend/app/components/wp-table/configuration-modal/tabs/timelines-tab.component.html

@ -26,7 +26,7 @@
// See doc/COPYRIGHT.rdoc for more details.
// ++
import {InjectionToken, NgModule} from '@angular/core';
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {UpgradeModule} from '@angular/upgrade/static';
import {FormsModule} from '@angular/forms';
@ -49,9 +49,7 @@ import {WorkPackageTableRelationColumnsService} from 'core-components/wp-fast-ta
import {WorkPackageTableSelection} from 'core-components/wp-fast-table/state/wp-table-selection.service';
import {WorkPackageTableSortByService} from 'core-components/wp-fast-table/state/wp-table-sort-by.service';
import {WorkPackageTableTimelineService} from 'core-components/wp-fast-table/state/wp-table-timeline.service';
import {
WorkPackageInlineCreateComponent,
} from 'core-components/wp-inline-create/wp-inline-create.component';
import {WorkPackageInlineCreateComponent,} from 'core-components/wp-inline-create/wp-inline-create.component';
import {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';
import {WorkPackageRelationsService} from 'core-components/wp-relations/wp-relations.service';
import {WpResizerDirectiveUpgraded} from 'core-components/wp-resizer/wp-resizer.directive';
@ -71,16 +69,20 @@ import {
$rootScopeToken,
$stateToken,
$timeoutToken,
columnsModalToken, exportModalToken,
FocusHelperToken, groupingModalToken,
halRequestToken, HalResourceToken,
columnsModalToken,
exportModalToken,
FocusHelperToken,
halRequestToken,
HalResourceToken,
HookServiceToken,
I18nToken,
NotificationsServiceToken,
PathHelperToken, QueryFilterInstanceResourceToken, QueryResourceToken, saveModalToken,
settingsModalToken, shareModalToken,
sortingModalToken,
timelinesModalToken,
PathHelperToken,
QueryFilterInstanceResourceToken,
QueryResourceToken,
saveModalToken,
settingsModalToken,
shareModalToken,
TimezoneServiceToken,
upgradeService,
upgradeServiceWithToken,
@ -189,7 +191,6 @@ import {WpRelationsAutocompleteComponent} from 'core-components/wp-relations/wp-
import {WpRelationAddChildComponent} from 'core-components/wp-relations/wp-relation-add-child/wp-relation-add-child';
import {WpRelationParentComponent} from 'core-components/wp-relations/wp-relations-parent/wp-relations-parent.component';
import {OpModalService} from 'core-components/op-modals/op-modal.service';
import {ColumnsModalComponent} from 'core-components/op-modals/modals/columns-modal.component';
import {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal';
import {WpTableConfigurationColumnsTab} from 'core-components/wp-table/configuration-modal/tabs/columns-tab.component';
import {WpTableConfigurationDisplaySettingsTab} from 'core-components/wp-table/configuration-modal/tabs/display-settings-tab.component';
@ -228,13 +229,10 @@ import {WpTableConfigurationTimelinesTab} from 'core-components/wp-table/configu
upgradeServiceWithToken('TimezoneService', TimezoneServiceToken),
upgradeServiceWithToken('v3Path', v3PathToken),
upgradeServiceWithToken('wpDestroyModal', wpDestroyModalToken),
upgradeServiceWithToken('sortingModal', sortingModalToken),
upgradeServiceWithToken('groupingModal', groupingModalToken),
upgradeServiceWithToken('shareModal', shareModalToken),
upgradeServiceWithToken('saveModal', saveModalToken),
upgradeServiceWithToken('settingsModal', settingsModalToken),
upgradeServiceWithToken('exportModal', exportModalToken),
upgradeServiceWithToken('timelinesModal', timelinesModalToken),
upgradeService('wpRelations', WorkPackageRelationsService),
WorkPackageCacheService,
WorkPackageEditingService,
@ -403,7 +401,6 @@ import {WpTableConfigurationTimelinesTab} from 'core-components/wp-table/configu
// Embedded table
WorkPackageEmbeddedTableComponent,
// Modals
ColumnsModalComponent,
WpTableConfigurationModalComponent,
WpTableConfigurationColumnsTab,
WpTableConfigurationDisplaySettingsTab,
@ -457,7 +454,6 @@ import {WpTableConfigurationTimelinesTab} from 'core-components/wp-table/configu
WorkPackageRelationsHierarchyComponent,
// Modals
ColumnsModalComponent,
WpTableConfigurationModalComponent,
WpTableConfigurationColumnsTab,
WpTableConfigurationDisplaySettingsTab,

@ -1,115 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
import {WorkPackageTableColumnsService} from '../../wp-fast-table/state/wp-table-columns.service';
import {QueryColumn} from '../../wp-query/query-column';
function ColumnsModalController(this:any,
$scope:any,
$timeout:ng.ITimeoutService,
I18n:op.I18n,
columnsModal:any,
wpTableColumns:WorkPackageTableColumnsService,
ConfigurationService:any) {
var vm = this;
vm.name = 'Columns';
vm.closeMe = columnsModal.deactivate;
vm.selectedColumns = [];
vm.availableColumns = [];
vm.unusedColumns = [];
vm.text = {
closePopup: I18n.t('js.close_popup_title'),
columnsLabel: I18n.t('js.label_columns'),
selectedColumns: I18n.t('js.description_selected_columns'),
multiSelectLabel: I18n.t('js.work_packages.label_column_multiselect'),
applyButton: I18n.t('js.modals.button_apply'),
cancelButton: I18n.t('js.modals.button_cancel'),
upsaleRelationColumns: I18n.t('js.modals.upsale_relation_columns'),
upsaleRelationColumnsLink: I18n.t('js.modals.upsale_relation_columns_link')
};
vm.availableColumns = wpTableColumns.all;
vm.unusedColumns = wpTableColumns.unused;
vm.selectedColumns = angular.copy(wpTableColumns.getColumns());
vm.impaired = ConfigurationService.accessibilityModeEnabled();
vm.selectedColumnMap = {};
vm.eeShowBanners = angular.element('body').hasClass('ee-banners-visible');
if (vm.impaired) {
vm.selectedColumns.forEach((column:QueryColumn) => {
vm.selectedColumnMap[column.id] = true;
});
}
vm.updateSelectedColumns = () => {
wpTableColumns.setColumns(vm.selectedColumns);
columnsModal.deactivate();
};
/**
* When a column is removed from the selection it becomes unused and hence available for
* selection again. When a column is added to the selection it becomes used and is
* therefore unavailable for selection.
*
* This function updates the unused columns according to the currently selected columns.
*
* @param selectedColumns Columns currently selected through the multi select box.
*/
vm.updateUnusedColumns = (selectedColumns:QueryColumn[]) => {
vm.unusedColumns = _.differenceBy(vm.availableColumns, selectedColumns, '$href');
};
vm.setSelectedColumn = (column:QueryColumn) => {
if (vm.selectedColumnMap[column.id]) {
vm.selectedColumns.push(column);
}
else {
_.remove(vm.selectedColumns, (c: any) => c.id === column.id);
}
};
//hack to prevent dragging of close icons
$timeout(() => {
angular.element('.columns-modal-content .ui-select-match-close').on('dragstart', event => {
event.preventDefault();
});
});
$scope.$on('uiSelectSort:change', (event:any, args:any) => {
vm.selectedColumns = args.array;
});
}
wpControllersModule.controller('ColumnsModalController', ColumnsModalController);

@ -1,89 +0,0 @@
<div class="ng-modal-window columns-modal loading-indicator--location"
data-indicator-name="modal">
<div class="ng-modal-inner" tabindex="0">
<div class="modal-header">
<a>
<i
class="icon-close"
ng-click="$ctrl.closeMe()"
title="{{ ::$ctrl.text.closePopup }}">
</i>
</a>
</div>
<h3>{{ ::$ctrl.text.columnsLabel }}</h3>
<div class="columns-modal-content select2-modal-content"
ng-if="!$ctrl.impaired">
<label
for="selected_columns"
class="hidden-for-sighted">
{{ ::$ctrl.text.selectedColumns }}
</label>
<ui-select
sortable="true"
ng-model="$ctrl.selectedColumns"
theme="select2"
id="selected_columns"
focus
multiple
aria-labelledby="column_multiselect_description"
title="{{ ::$ctrl.text.columnsLabel }}">
<ui-select-match>{{ $item.name }}</ui-select-match>
<ui-select-choices
repeat="column in $ctrl.unusedColumns | filter: { name: $select.search } | orderBy:'name'"
refresh="$ctrl.updateUnusedColumns($select.selected)"
refresh-delay="0">
<div ng-bind-html="column.name | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
<span class="tooltip--right -multiline" tabindex="0" title
data-tooltip="{{ ::$ctrl.text.multiSelectLabel }}"
aria-labelledby="column_multiselect_description">
<op-icon icon-classes="icon icon-help1"></op-icon>
</span>
<div class="hidden-for-sighted" id="column_multiselect_description">
{{ ::$ctrl.text.multiSelectLabel }}
</div>
</div>
<div
class="columns-modal-content select2-modal-content"
ng-if="$ctrl.impaired">
<label
for="selected_columns"
class="hidden-for-sighted">
{{ ::$ctrl.text.selectedColumns }}
</label>
<div ng-repeat="column in $ctrl.availableColumns | orderBy:'name'">
<label class="form--label-with-check-box" for="column-{{column.id}}">
<div class="form--check-box-container">
<input id="column-{{column.id}}"
type="checkbox"
title="{{ column.name }}"
ng-model="$ctrl.selectedColumnMap[column.id]"
ng-change="$ctrl.setSelectedColumn(column)"
focus="$first" />
</div>
{{column.name}}
</label>
</div>
</div>
<div ng-if="$ctrl.eeShowBanners" class="ee-relation-columns-upsale">
{{$ctrl.text.upsaleRelationColumns}}
<a href="https://www.openproject.org/enterprise-edition/?op_edtion=community-edition&op_referrer=wp-list-columns#relations" target='blank' ng-bind="$ctrl.text.upsaleRelationColumnsLink"></a>
</div>
<div>
<button class="button -highlight" ng-click="$ctrl.updateSelectedColumns()">
{{ ::$ctrl.text.applyButton }}
</button>
<button class="button" ng-click="$ctrl.closeMe()">
{{ ::$ctrl.text.cancelButton }}
</button>
</div>
</div>
</div>

@ -1,40 +0,0 @@
// -- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
// ++
import {wpControllersModule} from '../../../angular-modules';
function columnsModalService(btfModal:any) {
return btfModal({
controller: 'ColumnsModalController',
controllerAs: '$ctrl',
afterFocusOn: '#work-packages-settings-button',
templateUrl: '/components/modals/columns-modal/columns-modal.service.html'
});
}
wpControllersModule.factory('columnsModal', columnsModalService);

@ -1,54 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
import {WorkPackageTableGroupByService} from '../../wp-fast-table/state/wp-table-group-by.service';
function GroupingModalController(this:any,
$scope:any,
groupingModal:any,
wpTableGroupBy:WorkPackageTableGroupByService,
I18n:op.I18n) {
this.name = 'GroupBy';
this.closeMe = groupingModal.deactivate;
let emptyOption = {title: I18n.t('js.inplace.clear_value_label')};
$scope.vm = {};
wpTableGroupBy.onReady().then(() => {
$scope.vm.available = wpTableGroupBy.available;
$scope.vm.current = wpTableGroupBy.current;
});
$scope.updateGroupBy = () => {
wpTableGroupBy.set($scope.vm.current);
groupingModal.deactivate();
};
}
wpControllersModule.controller('GroupingModalController', GroupingModalController);

@ -1,47 +0,0 @@
<div class="ng-modal-window">
<div class="ng-modal-inner" tabindex="0">
<div class="modal-header">
<a>
<i
class="icon-close"
ng-click="$ctrl.closeMe()"
title="{{ ::I18n.t('js.close_popup_title') }}">
</i>
</a>
</div>
<h3>{{ ::I18n.t('js.label_group_by') }}</h3>
<form>
<div class="form--field -full-width">
<label
for="selected_columns_new"
class="form--label hidden-for-sighted">
{{ ::I18n.t('js.label_group_by') }}
</label>
<div class="form--field-container">
<div class="form--select-container">
<select
ng-model="vm.current"
focus="true"
title="{{ fieldController.editTitle }}"
id="selected_columns_new"
class="form--select"
ng-options="groupBy.name for groupBy in vm.available | orderBy: 'name' track by groupBy.$href">
<option value="">{{::I18n.t('js.placeholders.default')}}</option>
</select>
</div>
</div>
</div>
<div>
<button class="button -highlight" ng-click="updateGroupBy()">
{{ ::I18n.t('js.modals.button_apply') }}
</button>
<button class="button" ng-click="$ctrl.closeMe()">
{{ ::I18n.t('js.modals.button_cancel') }}
</button>
</div>
</form>
</div>
</div>

@ -1,40 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
function groupingModalService(btfModal:any) {
return btfModal({
controller: 'GroupingModalController',
controllerAs: '$ctrl',
afterFocusOn: '#work-packages-settings-button',
templateUrl: '/components/modals/grouping-modal/grouping-modal.service.html'
});
}
wpControllersModule.factory('groupingModal', groupingModalService);

@ -1,107 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
import {WorkPackageTableSortByService} from '../../wp-fast-table/state/wp-table-sort-by.service';
import {
QUERY_SORT_BY_ASC,
QUERY_SORT_BY_DESC,
QuerySortByResource
} from '../../api/api-v3/hal-resources/query-sort-by-resource.service';
import {QueryColumn} from '../../wp-query/query-column';
class SortModalObject {
constructor(public column: QueryColumn|null,
public direction: string) {
}
}
function SortingModalController(this:any,
sortingModal:any,
$scope:any,
wpTableSortBy:WorkPackageTableSortByService,
I18n:op.I18n) {
this.name = 'Sorting';
this.closeMe = sortingModal.deactivate;
$scope.currentSortation = [];
$scope.availableColumns = [];
$scope.allColumns = [];
$scope.sortationObjects = [];
wpTableSortBy.onReady().then(() => {
$scope.currentSortation = wpTableSortBy.currentSortBys;
let availableSortation = wpTableSortBy.available;
let allColumns:QueryColumn[] = _.map(availableSortation, sort => sort.column);
$scope.allColumns = _.uniqBy(allColumns, '$href');
_.each($scope.currentSortation, sort => {
$scope.sortationObjects.push(new SortModalObject(sort.column,
sort.direction.$href));
});
fillUpSortElements();
});
function fillUpSortElements() {
while ($scope.sortationObjects.length < 3) {
$scope.sortationObjects.push(new SortModalObject(null, QUERY_SORT_BY_ASC));
}
}
$scope.$watchCollection('sortationObjects', () => $scope.updatedSelection());
$scope.updatedSelection = () => {
let usedColumns = _.map($scope.sortationObjects, (object:SortModalObject) => object.column);
$scope.availableColumns = _.differenceBy($scope.allColumns, usedColumns, '$href');
};
$scope.availableColumnsAndCurrent = (column:SortModalObject) => {
return _.uniqBy(_.concat($scope.availableColumns, _.compact([column])), '$href');
};
$scope.updateSortation = () => {
let sortElements = ($scope.sortationObjects as SortModalObject[])
.filter(object => object.column)
.map(object => _.find(wpTableSortBy.available, availableSort =>
availableSort.column.$href === object.column!.$href &&
availableSort.direction.$href === object.direction
));
wpTableSortBy.set(_.compact(sortElements));
sortingModal.deactivate();
};
$scope.availableDirections = [
{$href: QUERY_SORT_BY_ASC, name: I18n.t('js.label_ascending')},
{$href: QUERY_SORT_BY_DESC, name: I18n.t('js.label_descending')}
];
}
wpControllersModule.controller('SortingModalController', SortingModalController);

@ -1,56 +0,0 @@
<div class="ng-modal-window">
<div class="ng-modal-inner modal-content" tabindex="0">
<div class="modal-header">
<a><op-icon icon-classes="icon-close" ng-click="$ctrl.closeMe()" title="{{ ::I18n.t('js.close_popup_title') }}"></op-icon></a></div>
<h3>{{ ::I18n.t('js.label_sorting') }}</h3>
<form name="modalSortingForm">
<div id="modal-sorting"
class="modal-content-container loading-indicator--location"
data-indicator-name="sorting-modal">
<div class="form--row modal-sorting-row-{{$index}}" ng-repeat="sort in sortationObjects">
<div class="form--field -full-width">
<label
for="modal-sorting-attribute-{{$index}}"
class="form--label hidden-for-sighted">
{{ I18n.t('js.filter.sorting.criteria.' + { 1: 'one', 2: 'two', 3: 'three'}[$index + 1]) }}
</label>
<div class="form--field-container">
<div class="form--select-container">
<select
id="modal-sorting-attribute-{{$index}}"
ng-model="sort.column"
ng-change="updatedSelection()"
focus="!$index"
class="form--select"
ng-options="column.name for column in availableColumnsAndCurrent(sort.column) | orderBy:'name' track by column.$href">
<option value="">{{::I18n.t('js.placeholders.default')}}</option>
</select>
</div>
</div>
</div>
<div class="form--field -full-width">
<div class="form--field-container">
<label class="option-label" ng-repeat="availableDirection in availableDirections">
<input type="radio"
ng-model="sort.direction"
ng-value="availableDirection.$href"
name="modal-sorting-attribute-{{sort.column.name}}--sort-direction">
{{availableDirection.name}}
</label>
</div>
</div>
</div>
</div>
<button class="button -highlight"
ng-disabled="modalSortingForm.$invalid"
ng-click="updateSortation()">
{{ ::I18n.t('js.modals.button_apply') }}
</button>
<button class="button" ng-click="$ctrl.closeMe()">
{{ ::I18n.t('js.modals.button_cancel') }}
</button>
</form>
</div>
</div>

@ -1,40 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
function sortingModalService(btfModal:any) {
return btfModal({
controller: 'SortingModalController',
controllerAs: '$ctrl',
afterFocusOn: '#work-packages-settings-button',
templateUrl: '/components/modals/sorting-modal/sorting-modal.service.html'
});
}
wpControllersModule.factory('sortingModal', sortingModalService);

@ -1,75 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
import {WorkPackageTableTimelineService} from '../../wp-fast-table/state/wp-table-timeline.service';
import {WorkPackageTableColumnsService} from '../../wp-fast-table/state/wp-table-columns.service';
function TimelinesModalController(this:any,
timelinesModal:any,
$scope:any,
wpTableTimeline:WorkPackageTableTimelineService,
wpTableColumns:WorkPackageTableColumnsService,
I18n:op.I18n) {
this.name = 'Timelines';
this.closeMe = timelinesModal.deactivate;
$scope.text = {
apply: I18n.t('js.modals.button_apply'),
cancel: I18n.t('js.modals.button_cancel'),
close: I18n.t('js.close_popup_title'),
title: I18n.t('js.timelines.gantt_chart'),
labels: {
description: I18n.t('js.timelines.labels.description'),
bar: I18n.t('js.timelines.labels.bar'),
none: I18n.t('js.timelines.filter.noneSelection'),
left: I18n.t('js.timelines.labels.left'),
right: I18n.t('js.timelines.labels.right'),
farRight: I18n.t('js.timelines.labels.farRight')
}
};
// Current label models
const labels = wpTableTimeline.labels;
$scope.labels = _.clone(labels);
// Available labels
const availableColumns = wpTableColumns
.allPropertyColumns
.sort((a, b) => a.name.localeCompare(b.name));
$scope.availableAttributes = [{ id: '', name: $scope.text.labels.none }].concat(availableColumns);
// Save
$scope.updateLabels = () => {
wpTableTimeline.updateLabels($scope.labels);
timelinesModal.deactivate();
};
}
wpControllersModule.controller('TimelinesModalController', TimelinesModalController);

@ -1,45 +0,0 @@
<div class="ng-modal-window">
<div class="ng-modal-inner modal-content">
<div class="modal-header">
<a><op-icon icon-classes="icon-close" ng-click="$ctrl.closeMe()" title="{{ ::text.close }}"></op-icon></a></div>
<h3>{{ ::text.title }}</h3>
<form name="modalTimelinesForm">
<div id="modal-timelines"
class="modal-content-container">
<p ng-bind="::text.labels.description"></p>
<section class="form--section">
<div class="form--row" ng-repeat="(key, value) in labels">
<div class="form--field">
<label
for="modal-timelines-label-{{key}}"
class="form--label">
{{ text.labels[key] }}
</label>
<div class="form--field-container">
<div class="form--select-container">
<select
id="modal-timelines-label-{{key}}"
ng-model="labels[key]"
focus="$first"
class="form--select"
ng-options="c.id as c.name for c in availableAttributes">
</select>
</div>
</div>
</div>
</div>
</section>
</div>
<button class="button -highlight"
ng-bind="::text.apply"
ng-click="updateLabels()">
</button>
<button class="button"
ng-bind="::text.cancel"
ng-click="$ctrl.closeMe()">
</button>
</form>
</div>
</div>

@ -1,40 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
function timelinesModalService(btfModal:any) {
return btfModal({
controller: 'TimelinesModalController',
controllerAs: '$ctrl',
afterFocusOn: '#work-packages-settings-button',
templateUrl: '/components/modals/timelines-modal/timelines-modal.service.html'
});
}
wpControllersModule.factory('timelinesModal', timelinesModalService);

@ -64,23 +64,13 @@ export class OpSettingsMenuDirective extends OpContextMenuTrigger implements OnD
constructor(readonly elementRef:ElementRef,
readonly opContextMenu:OPContextMenuService,
readonly wpTableColumns:WorkPackageTableColumnsService,
readonly wpTableSortBy:WorkPackageTableSortByService,
readonly wpTableGroupBy:WorkPackageTableGroupByService,
readonly wpTableHierarchies:WorkPackageTableHierarchiesService,
readonly wpTableTimeline:WorkPackageTableTimelineService,
readonly wpTableSum:WorkPackageTableSumService,
readonly wpListService:WorkPackagesListService,
readonly authorisationService:AuthorisationService,
readonly states:States,
@Inject(columnsModalToken) readonly columnsModal:any,
@Inject(sortingModalToken) readonly sortingModal:any,
@Inject(groupingModalToken) readonly groupingModal:any,
@Inject(shareModalToken) readonly shareModal:any,
@Inject(saveModalToken) readonly saveModal:any,
@Inject(settingsModalToken) readonly settingsModal:any,
@Inject(exportModalToken) readonly exportModal:any,
@Inject(timelinesModalToken) readonly timelinesModal:any,
@Inject(I18nToken) readonly I18n:op.I18n) {
super(elementRef, opContextMenu);
@ -260,16 +250,6 @@ export class OpSettingsMenuDirective extends OpContextMenuTrigger implements OnD
linkText: this.query.results.customFields && this.query.results.customFields.name,
icon: 'icon-custom-fields',
onClick: () => false
},
{
// Timelines modal
disabled: !this.wpTableTimeline.isVisible,
linkText: this.I18n.t('js.timelines.gantt_chart') + ' ...',
icon: 'icon-view-timeline',
onClick: () => {
this.timelinesModal.activate();
return true;
}
}
];
}

@ -1,61 +0,0 @@
<div class="ng-modal-window columns-modal loading-indicator--location"
data-indicator-name="modal">
<div class="ng-modal-inner" tabindex="0">
<div class="modal-header">
<a>
<i
class="icon-close"
(click)="closeMe()"
[attr.title]="text.closePopup">
</i>
</a>
</div>
<h3 [textContent]="text.columnsLabel"></h3>
<div class="columns-modal-content select2-modal-content"
*ngIf="!impaired">
</div>
<div
class="columns-modal-content select2-modal-content"
*ngIf="impaired">
<label
for="selected_columns"
[textContent]="text.selectedColumns"
class="hidden-for-sighted">
</label>
<div *ngFor="let column of availableColumns; let first = first;">
<label class="form--label-with-check-box" for="column-{{column.id}}">
<div class="form--check-box-container">
<input id="column-{{column.id}}"
type="checkbox"
title="{{ column.name }}"
[(ngModel)]="selectedColumnMap[column.id]"
(ngModelChange)="setSelectedColumn(column)"
focus="first" />
</div>
{{column.name}}
</label>
</div>
</div>
<div *ngIf="eeShowBanners" class="ee-relation-columns-upsale">
{{text.upsaleRelationColumns}}
<a href="https://www.openproject.org/enterprise-edition/?op_edtion=community-edition&op_referrer=wp-list-columns#relations"
target='blank'
[textContent]="text.upsaleRelationColumnsLink"></a>
</div>
<div>
<button class="button -highlight"
[textContent]="text.applyButton"
(click)="updateSelectedColumns()">
</button>
<button class="button"
[textContent]="text.cancelButton"
(click)="closeMe()">
</button>
</div>
</div>
</div>

@ -1,120 +0,0 @@
import {Component, ElementRef, Inject, OnInit} from '@angular/core';
import {I18nToken, OpModalLocalsToken} from 'core-app/angular4-transition-utils';
import {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types';
import {QueryColumn} from 'core-components/wp-query/query-column';
import {ConfigurationService} from 'core-components/common/config/configuration.service';
import {WorkPackageTableColumnsService} from 'core-components/wp-fast-table/state/wp-table-columns.service';
import {OpModalComponent} from 'core-components/op-modals/op-modal.component';
@Component({
template: require('!!raw-loader!./columns-modal.component.html')
})
export class ColumnsModalComponent extends OpModalComponent {
/* Close on escape? */
public closeOnEscape = false;
/* Close on outside click */
public closeOnOutsideClick = false;
public $element:JQuery;
public text = {
closePopup: this.I18n.t('js.close_popup_title'),
columnsLabel: this.I18n.t('js.label_columns'),
selectedColumns: this.I18n.t('js.description_selected_columns'),
multiSelectLabel: this.I18n.t('js.work_packages.label_column_multiselect'),
applyButton: this.I18n.t('js.modals.button_apply'),
cancelButton: this.I18n.t('js.modals.button_cancel'),
upsaleRelationColumns: this.I18n.t('js.modals.upsale_relation_columns'),
upsaleRelationColumnsLink: this.I18n.t('js.modals.upsale_relation_columns_link')
};
public availableColumns = this.wpTableColumns.all;
public unusedColumns = this.wpTableColumns.unused;
public selectedColumns = angular.copy(this.wpTableColumns.getColumns());
public impaired = this.ConfigurationService.accessibilityModeEnabled();
public selectedColumnMap:{ [id:string]: boolean } = {};
public eeShowBanners:boolean;
// //hack to prevent dragging of close icons
// $timeout(() => {
// angular.element('.columns-modal-content .ui-select-match-close').on('dragstart', event => {
// event.preventDefault();
// });
// });
//
// $scope.$on('uiSelectSort:change', (event:any, args:any) => {
// vm.selectedColumns = args.array;
// });
constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,
@Inject(I18nToken) readonly I18n:op.I18n,
readonly wpTableColumns:WorkPackageTableColumnsService,
readonly ConfigurationService:ConfigurationService,
readonly elementRef:ElementRef) {
super(locals, elementRef);
}
ngOnInit() {
this.$element = jQuery(this.elementRef.nativeElement);
this.impaired = true; // TODO
this.eeShowBanners = angular.element('body').hasClass('ee-banners-visible');
if (this.impaired) {
this.selectedColumns.forEach((column:QueryColumn) => {
this.selectedColumnMap[column.id] = true;
});
}
}
public updateSelectedColumns() {
this.wpTableColumns.setColumns(this.selectedColumns);
this.service.close();
}
/**
* When a column is removed from the selection it becomes unused and hence available for
* selection again. When a column is added to the selection it becomes used and is
* therefore unavailable for selection.
*
* This function updates the unused columns according to the currently selected columns.
*
* @param selectedColumns Columns currently selected through the multi select box.
*/
public updateUnusedColumns(selectedColumns:QueryColumn[]) {
this.unusedColumns = _.differenceBy(this.availableColumns, selectedColumns, '$href');
}
public setSelectedColumn(column:QueryColumn) {
if (this.selectedColumnMap[column.id]) {
this.selectedColumns.push(column);
}
else {
_.remove(this.selectedColumns, (c:QueryColumn) => c.id === column.id);
}
}
/**
* Called when the user attempts to close the modal window.
* The service will close this modal if this method returns true
* @returns {boolean}
*/
public onClose():boolean {
this.afterFocusOn.focus();
return true;
}
public onOpen(modalElement:JQuery) {
}
protected get afterFocusOn():JQuery {
return this.$element;
}
}

@ -20,6 +20,7 @@
<legend class="form--fieldset-legend"
[textContent]="text.labels.title">
</legend>
<p [textContent]="text.labels.description"></p>
<div class="form--row" *ngFor="let key of availableLabels">
<div class="form--field">
<label

Loading…
Cancel
Save