Merge branch 'dev-angular' into feature/client-side-routing

Signed-off-by: Alex Coles <alex@alexbcoles.com>

Conflicts:
	app/views/work_packages/index.html.erb
pull/1315/head
Alex Coles 11 years ago
commit 1a6fe9db47
  1. 52
      app/assets/javascripts/angular/controllers/dialogs/sorting.js
  2. 9
      app/assets/javascripts/angular/controllers/work-packages-controller.js
  3. 6
      app/assets/javascripts/angular/directives/work_packages/options-dropdown-directive.js
  4. 8
      app/assets/javascripts/angular/models/query.js
  5. 8
      app/assets/javascripts/angular/models/sortation.js
  6. 2
      app/assets/javascripts/angular/openproject-app.js
  7. 8
      app/assets/javascripts/angular/services/query-service.js
  8. 80
      app/assets/stylesheets/content/_action_menu_main.md
  9. 103
      app/assets/stylesheets/content/_action_menu_main.sass
  10. 12
      app/assets/stylesheets/content/_headings.md
  11. 12
      app/assets/stylesheets/content/_headings.sass
  12. 16
      app/assets/stylesheets/content/_modal.md
  13. 77
      app/assets/stylesheets/content/_modal.sass
  14. 21
      app/assets/stylesheets/fonts/_openproject_icon_font.sass
  15. 34
      app/assets/stylesheets/global/_mixins.sass
  16. 9
      app/assets/stylesheets/global/_variables.sass
  17. 1
      public/templates/work_packages.html
  18. 13
      public/templates/work_packages/column_context_menu.html
  19. 2
      public/templates/work_packages/modals/columns.html
  20. 2
      public/templates/work_packages/modals/export.html
  21. 2
      public/templates/work_packages/modals/save.html
  22. 2
      public/templates/work_packages/modals/settings.html
  23. 2
      public/templates/work_packages/modals/share.html
  24. 20
      public/templates/work_packages/modals/sorting.html
  25. 3
      public/templates/work_packages/work_package_context_menu.html

@ -36,7 +36,57 @@ angular.module('openproject.workPackages.controllers')
});
}])
.controller('SortingModalController', ['sortingModal', function(sortingModal) {
.controller('SortingModalController', ['sortingModal',
'$scope',
'QueryService',
function(sortingModal, $scope, QueryService) {
this.name = 'Sorting';
this.closeMe = sortingModal.deactivate;
$scope.sortByOptions = {};
$scope.initSortation = function(){
var currentSortation = QueryService.getSortation();
$scope.sortElements = currentSortation.sortElements.map(function(element){
return [$scope.availableColumnsData.filter(function(column) { return column.id == element.field; })[0],
$scope.availableDirectionsData.filter(function(direction) { return direction.id == element.direction; })[0]]
});
while($scope.sortElements.length < 3) {
$scope.sortElements.push([]);
}
}
$scope.getAvailableColumnsData = function(term, result) {
result($scope.availableColumnsData);
}
$scope.getDirectionsData = function(term, result) {
result([{ id: 'asc', label: 'Ascending'}, { id: 'desc', label: 'Descending'}]);
}
$scope.updateSortation = function(){
var sortElements = $scope.sortElements
.filter(function(element){
return element.length == 2;
})
.map(function(element){
return { field: element[0].id, direction: element[1].id }
})
QueryService.updateSortElements(sortElements);
sortingModal.deactivate();
}
QueryService.loadAvailableColumns()
.then(function(available_columns){
$scope.availableColumns = available_columns
$scope.availableColumnsData = available_columns.map(function(column){
return { id: column.name, label: column.title, other: column.title };
});
$scope.initSortation();
});
$scope.availableDirectionsData = [{ id: 'desc', label: 'Descending'}, { id: 'asc', label: 'Ascending'}];
}]);

@ -237,4 +237,13 @@ angular.module('openproject.workPackages.controllers')
}
});
// Note: Again, this was in the work packages table directive but in an isolated scope so it wasn't picking up the changes to sortation.
// Think it would probably be a good idea to have the table directive just share the scope but that requires a refactor.
$scope.$watch('query.sortation.sortElements', function(oldValue, newValue) {
if (JSON.stringify(newValue) != JSON.stringify(oldValue)) {
$scope.updateResults();
$scope.updateBackUrl();
}
}, true);
}]);

@ -52,7 +52,6 @@ angular.module('openproject.workPackages.directives')
scope.showExportModal = exportModal.activate;
scope.showSettingsModal = settingsModal.activate;
scope.showShareModal = shareModal.activate;
scope.showSortingModal = sortingModal.activate;
scope.showSaveModal = function(saveAs){
scope.$emit('hideAllDropdowns');
@ -71,6 +70,11 @@ angular.module('openproject.workPackages.directives')
columnsModal.activate();
};
scope.showSortingModal = function(){
scope.$emit('hideAllDropdowns');
sortingModal.activate();
};
scope.toggleDisplaySums = function(){
scope.$emit('hideAllDropdowns');
scope.query.displaySums = !scope.query.displaySums;

@ -92,10 +92,18 @@ angular.module('openproject.models')
return UrlParamsHelper.buildQueryString(this.toParams());
},
getSortation: function(){
return this.sortation;
},
setSortation: function(sortation){
this.sortation = sortation;
},
updateSortElements: function(sortElements){
this.sortation.setSortElements(sortElements);
},
setName: function(name) {
this.name = name;
},

@ -83,6 +83,14 @@ angular.module('openproject.models')
this.sortElements.unshift(sortElement);
};
Sortation.prototype.setSortElements = function(sortElements) {
var elements = this.sortElements;
elements.length = 0;
angular.forEach(sortElements, function(element){
elements.push(element);
});
};
Sortation.prototype.getTargetSortationOfHeader = function(headerName) {
var targetSortation = angular.copy(this);
var targetSortDirection = this.getCurrentSortDirectionOfHeader(headerName) === 'asc' ? 'desc' : 'asc';

@ -130,7 +130,7 @@ openprojectApp
config.url = window.appBasePath + config.url;
return config || $q.when(config);
}
}
};
});
}])
.run(['$http', function($http){

@ -157,6 +157,14 @@ angular.module('openproject.services')
this.showColumns(selectedColumnNames);
},
updateSortElements: function(sortation) {
return query.updateSortElements(sortation);
},
getSortation: function() {
return query.getSortation();
},
getAvailableFilters: function(projectIdentifier){
// TODO once this is becoming more single-page-app-like keep the available filters of the query model in sync when the project identifier is changed on the scope but the page isn't reloaded
var identifier = 'global';

@ -2,50 +2,42 @@
```
<div class="action-menu">
<ul class="menu">
<li>
<a href="#"><i class="icon-edit icon-actionmenu"></i>menu item for modal...</a>
</li>
<li>
<a href="#"><i class="icon-yes icon-actionmenu"></i>menu item</a>
</li>
<li>
<a href="#"><i class="icon-copy icon-actionmenu"></i>menu item</a>
</li>
<li class="submenu-item">
<a href="#"><i class="icon-priority icon-actionmenu"></i>menu item with sub</a><i class="icon-pulldown-arrow4 icon-submenu"></i>
</li>
<li>
<a href="#"><i class="icon-delete icon-actionmenu"></i>menu item</a>
</li>
<li class="hasnoicon">
<a href="#">menu item no icon</a>
</li>
<li class="dropdown-divider"></li>
<li>
<a href="#"><i class="icon-time icon-actionmenu"></i>menu item</a>
</li>
</ul>
<ul class="menu">
<li>
<a href="#"><i class="icon-edit icon-action-menu"></i>menu item for modal...</a>
</li>
<li>
<a href="#"><i class="icon-yes icon-action-menu"></i>menu item</a>
</li>
<li>
<a href="#"><i class="icon-copy icon-action-menu"></i>menu item</a>
</li>
<li>
<a href="#"><i class="icon-priority icon-action-menu"></i>menu item with sub</a>
<i class="icon-pulldown-arrow4 icon-sub-menu"></i>
<ul class="sub-menu">
<li>
<a href="#"><i class="icon-edit icon-action-menu"></i>menu item</a>
</li>
<li>
<a href="#"><i class="icon-yes icon-action-menu"></i>menu item</a>
</li>
<li>
<a href="#"><i class="icon-copy icon-action-menu"></i>menu item</a>
</li>
</ul>
</li>
<li>
<a href="#"><i class="icon-delete icon-action-menu"></i>menu item</a>
</li>
<li class="has-no-icon">
<a href="#">menu item no icon</a>
</li>
<li class="dropdown-divider"></li>
<li>
<a href="#"><i class="icon-time icon-action-menu"></i>menu item</a>
</li>
</ul>
</div>
<div id="submenu" class="action-menu">
<ul class="menu">
<li>
<a href="#"><i class="icon-edit icon-actionmenu"></i>menu item for modal...</a>
</li>
<li>
<a href="#"><i class="icon-yes icon-actionmenu"></i>menu item</a>
</li>
<li>
<a href="#"><i class="icon-copy icon-actionmenu"></i>menu item</a>
</li>
</ul>
</div>
```

@ -26,105 +26,44 @@
* See doc/COPYRIGHT.rdoc for more details. ++
*/
@mixin action_menu_defaults($margin-top: 7px)
float: right
margin-top: $margin-top
> li
float: left
position: relative
list-style: none
@mixin contextual($margin-top: 8px)
float: right
white-space: nowrap
line-height: 1.4em
margin-top: $margin-top
padding-left: 10px
ul.action_menu_main
@include action_menu_defaults
ul.action_menu_specific,
.nosidebar ul.action_menu_specific
@include action_menu_defaults(-34px)
p.subtitle + ul.action_menu_specific
@include action_menu_defaults(-57px)
ul.action_menu_more
position: absolute
top: 23px
right: 0px
z-index: 100
white-space: nowrap
padding: 10px
padding-top: 5px
background: white
border: 1px solid #B7B7B7
box-shadow: 1px 1px 2px #aaa
> li
padding-top: 5px
#lower-title-bar ul.action_menu_specific
@include action_menu_defaults
padding-top: 10px
#lower-title-bar ul.action_menu_more
bottom: 0
right: 0
margin-bottom: 25px
top: auto
> li.drop-down
position: relative
.message-reply-menu
@include contextual(-39px)
.action-menu
float: left
width: 200px
border: 1px solid #dddddd
box-shadow: 1px 1px 4px #cccccc
-webkit-box-shadow: 1px 1px 4px #cccccc
padding: 3px 0
background: $action_menu_bg_color
ul
list-style-type: none
padding: 0
margin: 0
width: 200px
border: 1px solid #dddddd
box-shadow: 1px 1px 4px #cccccc
padding: 3px 0
background: #ffffff
li
padding: 4px 10px
padding: 4px 13px 4px 10px
&:hover
background: #f0f0f0
&.hasnoicon
&.has-no-icon
padding: 4px 10px 4px 35px
&.dropdown-divider
border-top: 1px solid #eeeeee
margin: 3px 0
padding: 0
font-size: 1px
&:hover ul
display: block
margin: -28px 0 0 190px
a
color: $main_menu_font_color
font-weight: normal
white-space: nowrap
&:hover
text-decoration: none
ul
display: none
position: absolute
i
.icon-actionmenu
padding: 0 10px 0 0
font-size: 15px
line-height: 5px
vertical-align: -40%
.icon-submenu
padding: 0 0 0 0
float: right
font-size: 15px
line-height: 5px
vertical-align: -40%
.icon-action-menu
@include icon-action-menu-rules
.icon-sub-menu
@include icon-sub-menu-rules
#submenu
margin: 81px 0 0 0

@ -1 +1,13 @@
# Headings
```
<h1>Headline H1</h1>
<span class="sample-text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.<br /><br /></span>
<h2>Headline H2</h2>
<span class="sample-text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.<br /><br /></span>
<h3>Headline H3</h3>
<span class="sample-text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.<br /><br /></span>
<h4>Headline H4</h4>
<span class="sample-text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.<br /><br /></span>
```

@ -29,3 +29,15 @@
#content
h2
padding-right: 340px
h1
@include default-headline-h1
h2
@include default-headline-h2
h3
@include default-headline-h3
h4
@include default-headline-h4

@ -1 +1,17 @@
# Modal
```
<div id="content-behind-modal">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Crasdapibus. Vivamus elementum semper</div>
<div id="modal-dark-overlay">
</div>
<div class="modal-container">
<div class="modal-header"><i class="icon-close"></i></div>
<div class="modal-content">
<h3>Modal Headline</h3>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper
</div>
</div>
```

@ -32,26 +32,6 @@ $ng-modal-image-width: $ng-modal-image-height
.ng-modal-inner
top: 0
.ng-modal-close
+position(absolute, $ng-modal-padding / 2 $ng-modal-padding / 2 0 0)
+size(1.5em)
cursor: pointer
background: $ng-modal-background
&:after,
&:before
+position(absolute, 3px 3px 0 50%)
+transform(rotate(45deg))
+size(0.15em 1.5em)
background: $ng-modal-close-color
content: ''
display: block
margin: -3px 0 0 -1px
&:hover:after,
&:hover:before
background: darken($ng-modal-close-color, 10)
&:before
+transform(rotate(-45deg))
.ng-modal-inner
+transition(opacity 0.25s ease)
border-radius: $base-border-radius
@ -74,29 +54,38 @@ $ng-modal-image-width: $ng-modal-image-height
width: 50%
margin-top: 10em
h1
color: $base-font-color
margin-bottom: .6em
text-align: left
text-transform: capitalize
p
font-size: $base-font-size
max-width: 100% !important
.modal-header
padding: 0
i
float: right
padding: 10px
#content-behind-modal
position: absolute
z-index: 1
padding: 10px
#modal-dark-overlay
position: absolute
z-index: 2
background: #000000
opacity: 0.3
width: 97%
height: 94%
.modal-container
position: relative
z-index: 3
margin: 20px auto
width: 60%
background: #ffffff
padding: 0
.modal-header
padding: 0
text-align: left
&.intro
color: $blue
line-height: 1.6em
&.body
color: $base-font-color
line-height: 1.45em
//+media($medium-screen)
+columns(2 8em)
i
float: right
padding: 10px
.modal-content
padding: 20px 20px 20px 20px
a.cta
color: white
display: inline-block
margin-right: .5em
margin-top: 1em
&:last-child
padding: 0 2em

@ -80,6 +80,19 @@
@mixin icon-table-rules
padding: 0 0 0 0
@mixin icon-action-menu-rules
padding: 0 10px 0 0
font-size: 15px
line-height: 5px
vertical-align: -40%
@mixin icon-sub-menu-rules
padding: 0 0 0 0
float: right
font-size: 15px
line-height: 5px
vertical-align: -40%
[data-icon]:before
@include icon-common
@ -120,6 +133,14 @@
@include icon-common
content: attr(data-icon-table)
@include icon-table-rules
[data-icon-action-menu]:before
content: attr(data-icon-action-menu)
@include icon-action-menu-rules
[data-icon-sub-menu]:before
content: attr(data-icon-sub-menu)
@include icon-sub-menu-rules
[class^="icon-"]:before,
[class*=" icon-"]:before

@ -37,6 +37,40 @@ $button_gray_font_color: #222222
@each $vendor in $vendors
#{$vendor}transition: all 200ms ease-in-out 0s
@mixin default-headline-h1
color: $headline_h1_font-color
font-size: $headline_h1_font_size
font-family: $font_family_normal
font-weight: normal
padding: 0 0 8px 0
margin: 0
@mixin default-headline-h2
color: $headline_h2_font-color
font-size: $headline_h2_font_size
font-family: $font_family_normal
font-weight: normal
text-transform: uppercase
padding: 0 0 8px 0
margin: 0
@mixin default-headline-h3
color: $headline_h3_font-color
font-size: $headline_h3_font_size
font-family: $font_family_normal
font-weight: normal
border-bottom: 1px solid #dddddd
padding: 0 0 8px 0
margin: 0 0 20px 0
@mixin default-headline-h4
color: $headline_h4_font-color
font-size: $headline_h4_font_size
font-family: $font_family_normal
font-weight: normal
padding: 0 0 5px 0
margin: 0 0 20px 0
@mixin default-font-normal($color, $font-size: 13px)
color: $color
font-size: $font-size

@ -30,6 +30,15 @@ $global_font_color: #555555 !default
$global_font_size: 13px !default
$global_line_height: 1.5 !default
$headline_h1_font_size: 28px !default
$headline_h1_font-color: #555555 !default
$headline_h2_font_size: 22px !default
$headline_h2_font-color: #06799F !default
$headline_h3_font_size: 19px !default
$headline_h3_font-color: #555555 !default
$headline_h4_font_size: 17px !default
$headline_h4_font-color: #555555 !default
$header_height: 55px !default
$header_bg_color: #3493B3 !default
$header_border_bottom_color: #3493B3 !default

@ -42,7 +42,6 @@
<li><a href ng-click="showSaveModal(true)">Save as</a></li>
<li><a href ng-click="showExportModal()">Export</a></li>
<li ng-show="!query.isNew()"><a href ng-click="showShareModal()">Share</a></li>
<li><a href ng-click="showSettingsModal()">Page settings</a></li>
</ul>
</div>

@ -1,26 +1,33 @@
<div id="column-context-menu" class="action-menu" ng-show="opened">
<ul class="menu">
<li ng-click="groupBy(column.name)">
<a href="#"><span ng-bind="I18n.t('js.work_packages.query.group_by')"/> {{column.title}}</a>
<li ng-click="groupBy(column.name)" class="has-no-icon">
<a href="#"><span ng-bind="I18n.t('js.work_packages.query.group_by')"/> <span ng-bind="column.title"/></a>
</li>
<li ng-click="sortAscending(column.name)">
<a href="#"><span ng-bind="I18n.t('js.label_sort_by')"/> <span ng-bind="column.title"/> <span ng-bind="I18n.t('js.label_ascending')"/></a>
<a href="#">
<i class="icon-action-menu icon-pulldown-arrow3"></i>
<span ng-bind="I18n.t('js.label_sort_by')"/> <span ng-bind="column.title"/> <span ng-bind="I18n.t('js.label_ascending')"/>
</a>
</li>
<li ng-click="sortDescending(column.name)">
<i class="icon-action-menu icon-pulldown-arrow1"></i>
<a href="#"><span ng-bind="I18n.t('js.label_sort_by')"/> <span ng-bind="column.title"/> <span ng-bind="I18n.t('js.label_descending')"/></a>
</li>
<li ng-click="moveLeft(column.name)">
<i class="icon-action-menu icon-paragraph-left"></i>
<a href="#"><span ng-bind="I18n.t('js.label_move_column_left')"/></a>
</li>
<li ng-click="moveRight(column.name)">
<i class="icon-action-menu icon-paragraph-right"></i>
<a href="#"><span ng-bind="I18n.t('js.label_move_column_right')"/></a>
</li>
<li ng-click="hideColumn(column.name)">
<i class="icon-action-menu icon-delete2"></i>
<a href="#"><span ng-bind="I18n.t('js.label_hide_column')"/></a>
</li>

@ -1,6 +1,6 @@
<div class="ng-modal-window">
<div class="ng-modal-inner">
<a href class="ng-modal-close" ng-click="modal.closeMe()">&nbsp;</a>
<div class="modal-header"><i class="icon-close" ng-click="modal.closeMe()"></i></div>
<h1>Columns</h1>

@ -1,6 +1,6 @@
<div class="ng-modal-window">
<div class="ng-modal-inner">
<a href class="ng-modal-close" ng-click="modal.closeMe()">&nbsp;</a>
<div class="modal-header"><i class="icon-close" ng-click="modal.closeMe()"></i></div>
<h1>{{modal.name}}</h1>
<div class="grid-items-lines">

@ -1,6 +1,6 @@
<div class="ng-modal-window">
<div class="ng-modal-inner">
<a href class="ng-modal-close" ng-click="modal.closeMe()">&nbsp;</a>
<div class="modal-header"><i class="icon-close" ng-click="modal.closeMe()"></i></div>
<h1>Save</h1>

@ -1,6 +1,6 @@
<div class="ng-modal-window">
<div class="ng-modal-inner">
<a href class="ng-modal-close" ng-click="modal.closeMe()">&nbsp;</a>
<div class="modal-header"><i class="icon-close" ng-click="modal.closeMe()"></i></div>
<h1>Settings</h1>

@ -1,6 +1,6 @@
<div class="ng-modal-window">
<div class="ng-modal-inner">
<a href class="ng-modal-close" ng-click="modal.closeMe()">&nbsp;</a>
<div class="modal-header"><i class="icon-close" ng-click="modal.closeMe()"></i></div>
<h1>Share</h1>

@ -1,8 +1,24 @@
<div class="ng-modal-window">
<div class="ng-modal-inner">
<a href class="ng-modal-close" ng-click="modal.closeMe()">&nbsp;</a>
<div class="ng-modal-inner modal-content">
<div class="modal-header"><i class="icon-close" ng-click="modal.closeMe()"></i></div>
<h1>Sorting</h1>
<div ng-repeat="element in sortElements">
<input type="hidden"
ui-select2-sortable="sortByOptions"
simple-query="getAvailableColumnsData"
ng-model="element[0]"></input>
<input type="hidden"
ui-select2-sortable="sortDirectionOptions"
simple-query="getDirectionsData"
ng-model="element[1]"></input>
</div>
<div>
<button ng-click="updateSortation()">Apply</button>
<button ng-click="modal.closeMe()">Cancel</button>
</div>
</div>
</div>

@ -12,7 +12,8 @@
<li class="folder priority">
<a href="#" class="context_item">TODO Priority</a>
<ul>
<i class="icon-pulldown-arrow4 icon-submenu"></i>
<ul class="sub-menu">
<li><a href="#" class=" disabled">Immediate</a></li>
<li><a href="#" class=" disabled">Urgent</a></li>
<li><a href="#" class=" disabled">High</a></li>

Loading…
Cancel
Save