Merge pull request #5258 from opf/spike/details-icon

Restyle details icon in table
pull/5262/head
Oliver Günther 8 years ago committed by GitHub
commit 8cf8f7c14e
  1. 2
      app/assets/stylesheets/content/_work_packages.sass
  2. 1
      app/assets/stylesheets/content/work_packages/_table_content.sass
  3. 24
      app/assets/stylesheets/content/work_packages/details/_fullscreen_toggle.sass
  4. 8
      app/assets/stylesheets/content/work_packages/fullscreen/_back_button.sass
  5. 16
      app/assets/stylesheets/content/work_packages/single_view/_single_view.sass
  6. 4
      app/assets/stylesheets/layout/_accessibility.sass
  7. 1
      config/locales/js-en.yml
  8. 17
      frontend/app/components/routing/wp-details/wp-details.controller.ts
  9. 13
      frontend/app/components/routing/wp-details/wp.list.details.html
  10. 27
      frontend/app/components/routing/wp-list/wp.list.html
  11. 4
      frontend/app/components/routing/wp-list/wp.list.new.html
  12. 4
      frontend/app/components/routing/wp-show/wp-show.controller.ts
  13. 21
      frontend/app/components/routing/wp-show/wp.show.html
  14. 47
      frontend/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.directive.ts
  15. 6
      frontend/app/components/wp-create/wp-create.controller.ts
  16. 2
      frontend/app/components/wp-fast-table/builders/details-link-builder.ts
  17. 2
      spec/features/work_packages/cancel_editing_spec.rb
  18. 4
      spec/features/work_packages/details/details_relations_spec.rb
  19. 4
      spec/features/work_packages/navigation_spec.rb
  20. 3
      spec/features/work_packages/select_work_package_row_spec.rb
  21. 6
      spec/features/work_packages/tabs/keep_tab_spec.rb
  22. 4
      spec/support/pages/abstract_work_package.rb
  23. 5
      spec/support/pages/split_work_package.rb
  24. 7
      spec/support/pages/work_packages_table.rb
  25. 4
      spec/support/work_packages/table_work_package_field.rb

@ -41,6 +41,8 @@
@import work_packages/single_view/attachments @import work_packages/single_view/attachments
@import work_packages/single_view/inplace_esque_fields @import work_packages/single_view/inplace_esque_fields
@import work_packages/_work_packages_show_view_overwrite @import work_packages/_work_packages_show_view_overwrite
@import work_packages/details/fullscreen_toggle
@import work_packages/fullscreen/back_button
// Tabs // Tabs
@import work_packages/tabs/_activities @import work_packages/tabs/_activities

@ -61,6 +61,7 @@
// Show details view button when hovering // Show details view button when hovering
.wp-table--details-link .wp-table--details-link
.issue:hover &, .issue:hover &,
.issue.-checked &,
&:focus &:focus
position: relative position: relative
left: 0 left: 0

@ -0,0 +1,24 @@
// Full screen toggle indicator on the
// left side of the details container
.wp--details--switch-fullscreen
width: 20px
height: 50px
position: absolute
left: -12px
top: calc(50% - 25px)
background: #eee
border: 1px solid $light-gray
color: $body-font-color
cursor: pointer
&:hover
background: #ddd
// Align icon
font-size: 10px
text-align: center
padding-top: 18px
span:before
padding: 0

@ -0,0 +1,8 @@
.wp-show--back-button
width: 100px
padding: 0 10px
a
margin: 0
margin-top: 18px
width: 75px

@ -120,7 +120,7 @@ i
height: $work-package-details--tab-height height: $work-package-details--tab-height
overflow: hidden overflow: hidden
position: relative position: relative
width: 97.5% width: 100%
font-weight: bold font-weight: bold
text-transform: uppercase text-transform: uppercase
@ -131,15 +131,27 @@ i
margin: 0 margin: 0
padding: 0 padding: 0
text-align: center text-align: center
width: 23.25% width: 22%
cursor: pointer cursor: pointer
a a
color: #333 color: #333
text-decoration: none text-decoration: none
&:hover &:hover
text-decoration: none text-decoration: none
li.tab-icon
width: 8%
.icon-context:before
padding-top: 10px
li.selected li.selected
color: #999 color: #999
border-bottom: 2px solid $content-link-color border-bottom: 2px solid $content-link-color
a a
color: $content-link-color color: $content-link-color
.work-packages--details-close-icon span
display: inline-block
padding-top: 2px
font-size: 0.9rem
&:before
@include varprop(color, $body-font-color)

@ -34,5 +34,9 @@
height: 1px height: 1px
overflow: hidden overflow: hidden
body.accessibility-mode
.hidden-for-accessibility
display: none !important
[hidden] [hidden]
display: none display: none

@ -57,6 +57,7 @@ en:
button_more: "More" button_more: "More"
button_move: "Move" button_move: "Move"
button_open_details: "Open details view" button_open_details: "Open details view"
button_close_details: "Close details view"
button_open_fullscreen: "Open fullscreen view" button_open_fullscreen: "Open fullscreen view"
button_quote: "Quote" button_quote: "Quote"
button_save: "Save" button_save: "Save"

@ -30,6 +30,7 @@ import {wpControllersModule} from '../../../angular-modules';
import {WorkPackageViewController} from '../wp-view-base/wp-view-base.controller'; import {WorkPackageViewController} from '../wp-view-base/wp-view-base.controller';
import {States} from '../../states.service'; import {States} from '../../states.service';
import {WorkPackageTableSelection} from '../../wp-fast-table/state/wp-table-selection.service'; import {WorkPackageTableSelection} from '../../wp-fast-table/state/wp-table-selection.service';
import {KeepTabService} from '../../wp-panels/keep-tab/keep-tab.service';
export class WorkPackageDetailsController extends WorkPackageViewController { export class WorkPackageDetailsController extends WorkPackageViewController {
@ -37,6 +38,7 @@ export class WorkPackageDetailsController extends WorkPackageViewController {
public $scope:ng.IScope, public $scope:ng.IScope,
public $rootScope:ng.IRootScopeService, public $rootScope:ng.IRootScopeService,
public states:States, public states:States,
public keepTab:KeepTabService,
public wpTableSelection:WorkPackageTableSelection, public wpTableSelection:WorkPackageTableSelection,
public $state:ng.ui.IStateService) { public $state:ng.ui.IStateService) {
super($injector, $scope, $state.params['workPackageId']); super($injector, $scope, $state.params['workPackageId']);
@ -61,9 +63,22 @@ export class WorkPackageDetailsController extends WorkPackageViewController {
}); });
} }
public close() {
this.$state.go('work-packages.list', this.$state.params);
}
public switchToFullscreen() {
this.$state.go(this.keepTab.currentShowState, this.$state.params);
}
public onWorkPackageSave() { public onWorkPackageSave() {
this.$rootScope.$emit('workPackagesRefreshInBackground'); this.$rootScope.$emit('workPackagesRefreshInBackground');
}; }
protected initializeTexts() {
super.initializeTexts();
this.text.closeDetailsView = this.I18n.t('js.button_close_details');
}
} }
wpControllersModule.controller('WorkPackageDetailsController', WorkPackageDetailsController); wpControllersModule.controller('WorkPackageDetailsController', WorkPackageDetailsController);

@ -1,3 +1,7 @@
<div class="work-packages-show-view-button wp--details--switch-fullscreen hidden-for-accessibility"
ng-click="$ctrl.switchToFullscreen()">
<span class="icon-context icon-double-arrow-left"></span>
</div>
<div class="work-packages--details loading-indicator--location" <div class="work-packages--details loading-indicator--location"
data-indicator-name="wpDetails"> data-indicator-name="wpDetails">
<div wp-edit-form="$ctrl.workPackage" <div wp-edit-form="$ctrl.workPackage"
@ -25,6 +29,13 @@
ui-sref-active="selected"> ui-sref-active="selected">
<a href="" ng-bind="::$ctrl.text.tabs.watchers"/> <a href="" ng-bind="::$ctrl.text.tabs.watchers"/>
</li> </li>
<li class="tab-icon">
<accessible-by-keyboard execute="$ctrl.close()"
link-aria-label="{{ ::$ctrl.text.closeDetailsView }}"
link-class="work-packages--details-close-icon"
span-class="icon-context icon-close">
</accessible-by-keyboard>
</li>
</ul> </ul>
</div> </div>
<div class="work-packages--details-content"> <div class="work-packages--details-content">
@ -45,4 +56,4 @@
></edit-actions-bar> ></edit-actions-bar>
</div> </div>
</div> </div>
</div> </div

@ -22,28 +22,13 @@
</wp-filter-button> </wp-filter-button>
</li> </li>
<li class="toolbar-item hidden-for-mobile"> <li class="toolbar-item hidden-for-mobile">
<ul id="work-packages-view-mode-selection" class="toolbar-button-group"> <wp-details-view-button>
<li> </wp-details-view-button>
<wp-list-view-button </li>
project-identifier="projectIdentifier"> <li class="toolbar-item hidden-for-mobile">
</wp-list-view-button> <wp-timeline-toggle-button>
</li> </wp-timeline-toggle-button>
<li>
<wp-details-view-button
next-wp-func="nextAvailableWorkPackage">
</wp-details-view-button>
</li>
<li>
<wp-view-button
next-wp-func="nextAvailableWorkPackage">
</wp-view-button>
</li>
</ul>
</li> </li>
<li class="toolbar-item">
<wp-timeline-toggle-button>
</wp-timeline-toggle-button>
</li>
<li class="toolbar-item hidden-for-mobile"> <li class="toolbar-item hidden-for-mobile">
<button id="work-packages-settings-button" <button id="work-packages-settings-button"
ng-disabled="wpEditModeState.active" ng-disabled="wpEditModeState.active"

@ -1,3 +1,7 @@
<div class="work-packages-show-view-button wp--details--switch-fullscreen hidden-for-accessibility"
ng-click="$ctrl.switchToFullscreen()">
<span class="icon-context icon-double-arrow-left"></span>
</div>
<div <div
class="work-packages--details" class="work-packages--details"
ng-if="$ctrl.newWorkPackage" ng-if="$ctrl.newWorkPackage"

@ -71,6 +71,10 @@ export class WorkPackageShowController extends WorkPackageViewController {
this.setWorkPackageScopeProperties(this.workPackage); this.setWorkPackageScopeProperties(this.workPackage);
} }
public goToList() {
this.$state.go('work-packages.list', this.$state.params);
}
public deleteSelectedWorkPackage() { public deleteSelectedWorkPackage() {
var promise = this.WorkPackageService.performBulkDelete([this.workPackage.id], true); var promise = this.WorkPackageService.performBulkDelete([this.workPackage.id], true);

@ -5,6 +5,13 @@
ng-if="$ctrl.workPackage"> ng-if="$ctrl.workPackage">
<div class="toolbar-container"> <div class="toolbar-container">
<div wp-toolbar id="toolbar"> <div wp-toolbar id="toolbar">
<div class="wp-show--back-button">
<accessible-by-keyboard execute="$ctrl.goToList()"
link-class="work-packages-list-view-button button -small"
link-aria-label="{{ ::$ctrl.sectionTitle }}"
span-class="button--icon icon-arrow-left1">
</accessible-by-keyboard>
</div>
<ul id="toolbar-items" class="toolbar-items"> <ul id="toolbar-items" class="toolbar-items">
<li class="toolbar-item"> <li class="toolbar-item">
<wp-create-button project-identifier="$ctrl.projectIdentifier" <wp-create-button project-identifier="$ctrl.projectIdentifier"
@ -24,20 +31,6 @@
<li class="toolbar-item" ng-if="$ctrl.displayWatchButton"> <li class="toolbar-item" ng-if="$ctrl.displayWatchButton">
<wp-watcher-button work-package="$ctrl.workPackage" disabled="$ctrl.wpEditModeState.active"></wp-watcher-button> <wp-watcher-button work-package="$ctrl.workPackage" disabled="$ctrl.wpEditModeState.active"></wp-watcher-button>
</li> </li>
<li class="toolbar-item hidden-for-mobile">
<ul id="work-packages-view-mode-selection" class="toolbar-button-group">
<li>
<wp-list-view-button edit-all="editAll"
project-identifier="$ctrl.projectIdentifier"></wp-list-view-button>
</li>
<li>
<wp-details-view-button project-identifier="$ctrl.projectIdentifier"></wp-details-view-button>
</li>
<li>
<wp-view-button work-package-id="$ctrl.workPackage.id"></wp-view-button>
</li>
</ul>
</li>
<li class="toolbar-item action_menu_main" id="action-show-more-dropdown-menu"> <li class="toolbar-item action_menu_main" id="action-show-more-dropdown-menu">
<button class="button dropdown-relative" <button class="button dropdown-relative"
ng-disabled="!actionsAvailable || $ctrl.wpEditModeState.active" ng-disabled="!actionsAvailable || $ctrl.wpEditModeState.active"

@ -27,17 +27,21 @@
// ++ // ++
import {wpButtonsModule} from '../../../angular-modules'; import {wpButtonsModule} from '../../../angular-modules';
import {WorkPackageNavigationButtonController, wpButtonDirective} from '../wp-buttons.module'; import {WorkPackageButtonController, wpButtonDirective} from '../wp-buttons.module';
import {KeepTabService} from '../../wp-panels/keep-tab/keep-tab.service'; import {KeepTabService} from '../../wp-panels/keep-tab/keep-tab.service';
import {States} from '../../states.service'; import {States} from '../../states.service';
export class WorkPackageDetailsViewButtonController extends WorkPackageNavigationButtonController {
public projectIdentifier:number;
export class WorkPackageDetailsViewButtonController extends WorkPackageButtonController {
public projectIdentifier:string;
public accessKey:number = 8; public accessKey:number = 8;
public activeState:string = 'work-packages.list.details'; public activeState:string = 'work-packages.list.details';
public listState: string = 'work-packages.list';
public buttonId:string = 'work-packages-details-view-button'; public buttonId:string = 'work-packages-details-view-button';
public iconClass:string = 'icon-view-split'; public iconClass:string = 'icon-info2';
public activateLabel:string;
public deactivateLabel:string;
constructor( constructor(
public $state:ng.ui.IStateService, public $state:ng.ui.IStateService,
@ -46,16 +50,43 @@ export class WorkPackageDetailsViewButtonController extends WorkPackageNavigatio
public loadingIndicator:any, public loadingIndicator:any,
public keepTab:KeepTabService) { public keepTab:KeepTabService) {
'ngInject'; 'ngInject';
super(I18n);
this.activateLabel = I18n.t('js.button_open_details');
this.deactivateLabel = I18n.t('js.button_close_details');
}
super($state, I18n); public get label():string {
if (this.isActive()) {
return this.deactivateLabel;
} else {
return this.activateLabel;
}
} }
public get labelKey():string { public isToggle():boolean {
return 'js.button_details_view'; return true;
}
public isActive():boolean {
return this.$state.includes(this.activeState);
} }
public performAction() { public performAction() {
this.openDetailsView(); if (this.isActive()) {
this.openListView();
} else {
this.openDetailsView();
}
}
public openListView() {
var params = {
projectPath: this.projectIdentifier
};
angular.extend(params, this.$state.params);
this.$state.go(this.listState, params);
} }
public openDetailsView() { public openDetailsView() {

@ -1,4 +1,3 @@
import {WorkPackageTableSelection} from '../wp-fast-table/state/wp-table-selection.service';
// -- copyright // -- copyright
// OpenProject is a project management system. // OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF) // Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
@ -37,6 +36,7 @@ import {WorkPackageCacheService} from "../work-packages/work-package-cache.servi
import IRootScopeService = angular.IRootScopeService; import IRootScopeService = angular.IRootScopeService;
import {WorkPackageEditModeStateService} from "../wp-edit/wp-edit-mode-state.service"; import {WorkPackageEditModeStateService} from "../wp-edit/wp-edit-mode-state.service";
import {WorkPackageNotificationService} from '../wp-edit/wp-notification.service'; import {WorkPackageNotificationService} from '../wp-edit/wp-notification.service';
import {WorkPackageTableSelection} from '../wp-fast-table/state/wp-table-selection.service';
import {States} from '../states.service'; import {States} from '../states.service';
export class WorkPackageCreateController { export class WorkPackageCreateController {
@ -100,6 +100,10 @@ export class WorkPackageCreateController {
.catch(error => this.wpNotificationsService.handleErrorResponse(error)); .catch(error => this.wpNotificationsService.handleErrorResponse(error));
} }
public switchToFullscreen() {
this.$state.go('work-packages.new', this.$state.params);
}
protected newWorkPackageFromParams(stateParams:any) { protected newWorkPackageFromParams(stateParams:any) {
const type = parseInt(stateParams.type); const type = parseInt(stateParams.type);

@ -33,7 +33,7 @@ export class DetailsLinkBuilder {
detailsLink.classList.add(detailsLinkClassName, 'hidden-for-sighted'); detailsLink.classList.add(detailsLinkClassName, 'hidden-for-sighted');
let icon = document.createElement('i'); let icon = document.createElement('i');
icon.classList.add('icon', 'icon-view-split'); icon.classList.add('icon', 'icon-info2');
detailsLink.appendChild(icon); detailsLink.appendChild(icon);
td.appendChild(detailsLink); td.appendChild(detailsLink);

@ -106,7 +106,7 @@ describe 'Cancel editing work package', js: true do
find('#wp-new-inline-edit--field-subject').set 'foobar' find('#wp-new-inline-edit--field-subject').set 'foobar'
# Expect editing works when moving to full screen # Expect editing works when moving to full screen
find('#work-packages-show-view-button').click find('.work-packages-show-view-button').click
expect(wp_page).not_to have_alert_dialog expect(wp_page).not_to have_alert_dialog
expect(page).to have_selector('.wp-edit-field.subject.-active') expect(page).to have_selector('.wp-edit-field.subject.-active')

@ -256,7 +256,7 @@ describe 'Work package relations tab', js: true, selenium: true do
add_relation('follows', relatable) add_relation('follows', relatable)
# Switch to full view # Switch to full view
find('#work-packages-show-view-button').click find('.work-packages-show-view-button').click
# Expect to have row # Expect to have row
created_row = find(".relation-row-#{relatable.id}", wait: 10) created_row = find(".relation-row-#{relatable.id}", wait: 10)
@ -268,7 +268,7 @@ describe 'Work package relations tab', js: true, selenium: true do
expect(page).to have_no_selector('.wp-relations--subject-field', text: relatable.subject) expect(page).to have_no_selector('.wp-relations--subject-field', text: relatable.subject)
# Back to split view # Back to split view
find('#work-packages-details-view-button').click page.evaluate_script('window.history.back()')
work_packages_page.expect_subject work_packages_page.expect_subject
expect(page).to have_no_selector('.relation-group--header', text: 'FOLLOWS') expect(page).to have_no_selector('.relation-group--header', text: 'FOLLOWS')

@ -86,13 +86,13 @@ RSpec.feature 'Work package navigation', js: true, selenium: true do
split_project_work_package.expect_current_path split_project_work_package.expect_current_path
# open work package full screen by button # open work package full screen by button
full_work_package = project_work_packages.open_full_screen_by_button(work_package) full_work_package = split_project_work_package.switch_to_fullscreen
full_work_package.expect_subject full_work_package.expect_subject
expect(current_path).to eq project_work_package_path(project, work_package, 'activity') expect(current_path).to eq project_work_package_path(project, work_package, 'activity')
# Back to table using the button # Back to table using the button
find('#work-packages-list-view-button').click find('.work-packages-list-view-button').click
global_work_packages.expect_work_package_listed(work_package) global_work_packages.expect_work_package_listed(work_package)
expect(current_path).to eq project_work_packages_path(project) expect(current_path).to eq project_work_packages_path(project)

@ -239,7 +239,8 @@ describe 'Select work package row', type: :feature, js:true, selenium: true do
split_wp = Pages::SplitWorkPackage.new(work_package_2) split_wp = Pages::SplitWorkPackage.new(work_package_2)
split_wp.expect_attributes Subject: work_package_2.subject split_wp.expect_attributes Subject: work_package_2.subject
find('#work-packages-list-view-button').click find('#work-packages-details-view-button').click
expect(page).to have_no_selector('.work-packages--details')
end end
end end
end end

@ -62,17 +62,17 @@ RSpec.feature 'Keep current details tab', js: true, selenium: true do
wp_split.expect_tab :relations wp_split.expect_tab :relations
# open work package full screen by button # open work package full screen by button
wp_full = wp_table.open_full_screen_by_button(wp2) wp_full = wp_split.switch_to_fullscreen
wp_full.expect_tab :relations wp_full.expect_tab :relations
wp_full.open_in_split_view page.evaluate_script('window.history.back()')
wp_split.expect_tab :relations wp_split.expect_tab :relations
# Assert that overview tab is mapped to activity in show # Assert that overview tab is mapped to activity in show
wp_split.visit_tab! :overview wp_split.visit_tab! :overview
wp_split.expect_tab :overview wp_split.expect_tab :overview
wp_split.open_in_full_view wp_split.switch_to_fullscreen
wp_full.expect_tab :activity wp_full.expect_tab :activity
wp_full.ensure_page_loaded wp_full.ensure_page_loaded
end end

@ -76,10 +76,6 @@ module Pages
find('#work-packages-details-view-button').click find('#work-packages-details-view-button').click
end end
def open_in_full_view
find('#work-packages-show-view-button').click
end
def ensure_page_loaded def ensure_page_loaded
expect(page).to have_selector('.work-package-details-activities-activity-contents .user', expect(page).to have_selector('.work-package-details-activities-activity-contents .user',
text: work_package.journals.last.user.name, text: work_package.journals.last.user.name,

@ -42,6 +42,11 @@ module Pages
super(attribute, container) super(attribute, container)
end end
def switch_to_fullscreen
find('.work-packages-show-view-button').click
FullWorkPackage.new(work_package, project)
end
def closed? def closed?
expect(page).not_to have_selector(@selector) expect(page).not_to have_selector(@selector)
end end

@ -106,13 +106,6 @@ module Pages
FullWorkPackage.new(work_package, project) FullWorkPackage.new(work_package, project)
end end
def open_full_screen_by_button(work_package)
row(work_package).click
click_button(I18n.t('js.label_activate') + ' ' + I18n.t('js.button_show_view'))
FullWorkPackage.new(work_package, project)
end
def open_full_screen_by_link(work_package) def open_full_screen_by_link(work_package)
row(work_package).click_link(work_package.id) row(work_package).click_link(work_package.id)
end end

@ -162,10 +162,10 @@ class TableWorkPackageField
if Capybara.current_driver == Capybara.javascript_driver if Capybara.current_driver == Capybara.javascript_driver
extend ::Angular::DSL unless singleton_class.included_modules.include?(::Angular::DSL) extend ::Angular::DSL unless singleton_class.included_modules.include?(::Angular::DSL)
expect(page).to have_selector('#work-packages-list-view-button.-active, expect(page).to have_selector(".wp-table--row,
.work-packages--details--title, .work-packages--details--title,
.work-package-details-activities-activity-contents, .work-package-details-activities-activity-contents,
#work-packages--edit-actions-save'.squish) #work-packages--edit-actions-save".squish)
end end
end end

Loading…
Cancel
Save