commit
386f550e04
@ -0,0 +1,193 @@ |
||||
/* ***** BEGIN LICENSE BLOCK ***** |
||||
* This file is part of DotClear. |
||||
* Copyright (c) 2005 Nicolas Martin & Olivier Meunier and contributors. All |
||||
* rights reserved. |
||||
* |
||||
* DotClear 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. |
||||
* |
||||
* DotClear 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 DotClear; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
* |
||||
* ***** END LICENSE BLOCK ***** |
||||
*/ |
||||
|
||||
/* Modified by JP LANG for textile formatting */ |
||||
|
||||
// strong
|
||||
jsToolBar.prototype.elements.strong = { |
||||
type: 'button', |
||||
title: 'Strong', |
||||
fn: { |
||||
wiki: function() { this.singleTag('**') } |
||||
} |
||||
}; |
||||
|
||||
// em
|
||||
jsToolBar.prototype.elements.em = { |
||||
type: 'button', |
||||
title: 'Italic', |
||||
fn: { |
||||
wiki: function() { this.singleTag("_") } |
||||
} |
||||
}; |
||||
|
||||
// del
|
||||
jsToolBar.prototype.elements.del = { |
||||
type: 'button', |
||||
title: 'Deleted', |
||||
fn: { |
||||
wiki: function() { this.singleTag('~~') } |
||||
} |
||||
}; |
||||
|
||||
// code
|
||||
jsToolBar.prototype.elements.code = { |
||||
type: 'button', |
||||
title: 'Code', |
||||
fn: { |
||||
wiki: function() { this.singleTag('`') } |
||||
} |
||||
}; |
||||
|
||||
// spacer
|
||||
jsToolBar.prototype.elements.space1 = {type: 'space'}; |
||||
|
||||
// headings
|
||||
jsToolBar.prototype.elements.h1 = { |
||||
type: 'button', |
||||
title: 'Heading 1', |
||||
fn: { |
||||
wiki: function() { |
||||
this.encloseLineSelection('# ', '',function(str) { |
||||
str = str.replace(/^#+/, ''); |
||||
return str; |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
jsToolBar.prototype.elements.h2 = { |
||||
type: 'button', |
||||
title: 'Heading 2', |
||||
fn: { |
||||
wiki: function() { |
||||
this.encloseLineSelection('## ', '',function(str) { |
||||
str = str.replace(/^#+/, ''); |
||||
return str; |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
jsToolBar.prototype.elements.h3 = { |
||||
type: 'button', |
||||
title: 'Heading 3', |
||||
fn: { |
||||
wiki: function() { |
||||
this.encloseLineSelection('### ', '',function(str) { |
||||
str = str.replace(/^#+/, ''); |
||||
return str; |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// spacer
|
||||
jsToolBar.prototype.elements.space2 = {type: 'space'}; |
||||
|
||||
// ul
|
||||
jsToolBar.prototype.elements.ul = { |
||||
type: 'button', |
||||
title: 'Unordered list', |
||||
fn: { |
||||
wiki: function() { |
||||
this.encloseLineSelection('','',function(str) { |
||||
str = str.replace(/\r/g,''); |
||||
return str.replace(/(\n|^)[#-]?\s*/g,"$1- "); |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// ol
|
||||
jsToolBar.prototype.elements.ol = { |
||||
type: 'button', |
||||
title: 'Ordered list', |
||||
fn: { |
||||
wiki: function() { |
||||
this.encloseLineSelection('','',function(str) { |
||||
str = str.replace(/\r/g,''); |
||||
return str.replace(/(\n|^)[*-]?\s*/g,"$11. "); |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// spacer
|
||||
jsToolBar.prototype.elements.space3 = {type: 'space'}; |
||||
|
||||
// bq
|
||||
jsToolBar.prototype.elements.bq = { |
||||
type: 'button', |
||||
title: 'Quote', |
||||
fn: { |
||||
wiki: function() { |
||||
this.encloseLineSelection('','',function(str) { |
||||
str = str.replace(/\r/g,''); |
||||
return str.replace(/(\n|^) *([^\n]*)/g,"$1> $2"); |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// unbq
|
||||
jsToolBar.prototype.elements.unbq = { |
||||
type: 'button', |
||||
title: 'Unquote', |
||||
fn: { |
||||
wiki: function() { |
||||
this.encloseLineSelection('','',function(str) { |
||||
str = str.replace(/\r/g,''); |
||||
return str.replace(/(\n|^) *[>]? *([^\n]*)/g,"$1$2"); |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// pre
|
||||
jsToolBar.prototype.elements.code = { |
||||
type: 'button', |
||||
title: 'Code fence', |
||||
fn: { |
||||
wiki: function() { this.encloseLineSelection('```\n', '\n```') } |
||||
} |
||||
}; |
||||
|
||||
// spacer
|
||||
jsToolBar.prototype.elements.space4 = {type: 'space'}; |
||||
|
||||
// wiki page
|
||||
jsToolBar.prototype.elements.link = { |
||||
type: 'button', |
||||
title: 'Link', |
||||
fn: { |
||||
wiki: function() { this.encloseSelection("[", "]()") } |
||||
} |
||||
}; |
||||
// image
|
||||
jsToolBar.prototype.elements.img = { |
||||
type: 'button', |
||||
title: 'Image', |
||||
fn: { |
||||
wiki: function() { this.encloseSelection("![](", ")") } |
||||
} |
||||
}; |
||||
|
||||
|
@ -0,0 +1,62 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Queries |
||||
module Relations |
||||
module Filters |
||||
module VisibilityChecking |
||||
def visibility_checked? |
||||
true |
||||
end |
||||
|
||||
def where |
||||
integer_values = values.map(&:to_i) |
||||
|
||||
visible_sql = WorkPackage.visible(User.current).select(:id).to_sql |
||||
|
||||
operator_string = case operator |
||||
when "=" |
||||
"IN" |
||||
when "!" |
||||
"NOT IN" |
||||
end |
||||
|
||||
visibility_checked_sql(operator_string, values, visible_sql) |
||||
end |
||||
|
||||
private |
||||
|
||||
def visibility_checked_sql(_operator, _values, _visible_sql) |
||||
raise NotImplementedError |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,86 @@ |
||||
// -- 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 {Component, DebugElement} from "@angular/core"; |
||||
|
||||
require('core-app/angular4-test-setup'); |
||||
|
||||
import {async, fakeAsync, TestBed, tick} from '@angular/core/testing'; |
||||
import {AccessibleByKeyboardComponent} from 'core-components/a11y/accessible-by-keyboard.component'; |
||||
import {ComponentFixture} from '@angular/core/testing/src/component_fixture'; |
||||
import {AccessibleClickDirective} from "core-components/a11y/accessible-click.directive"; |
||||
import {By} from "@angular/platform-browser"; |
||||
|
||||
@Component({ |
||||
template: `<div (accessibleClick)="onClick()">Click me</div>` |
||||
}) |
||||
class TestAccessibleClickDirective { |
||||
public onClick() { |
||||
} |
||||
} |
||||
|
||||
describe('accessibleByKeyboard component', () => { |
||||
|
||||
beforeEach(async(() => { |
||||
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
TestBed.configureTestingModule({ |
||||
declarations: [ |
||||
AccessibleClickDirective, |
||||
TestAccessibleClickDirective |
||||
] |
||||
}).compileComponents(); |
||||
})); |
||||
|
||||
describe('triggering the click handler', () => { |
||||
let app:TestAccessibleClickDirective; |
||||
let fixture:ComponentFixture<TestAccessibleClickDirective>; |
||||
let element:DebugElement; |
||||
|
||||
it('should render an inner link with specified classes', fakeAsync(() => { |
||||
fixture = TestBed.createComponent(TestAccessibleClickDirective); |
||||
app = fixture.debugElement.componentInstance; |
||||
element = fixture.debugElement.query(By.css('div')); |
||||
|
||||
const spy = sinon.spy(app, 'onClick'); |
||||
fixture.detectChanges(); |
||||
|
||||
// Trigger click
|
||||
element.triggerEventHandler('click', {type: 'click'}); |
||||
element.triggerEventHandler('keyup', {type: 'keyup', which: 13}); |
||||
element.triggerEventHandler('keyup', {type: 'keyup', which: 32}); |
||||
|
||||
tick(); |
||||
fixture.detectChanges(); |
||||
expect(spy).to.have.been.calledThrice; |
||||
})); |
||||
}); |
||||
}); |
||||
|
||||
|
||||
|
@ -1,10 +0,0 @@ |
||||
<a data-ng-click='isDisabled || execute({ "$event": $event })' |
||||
role="link" |
||||
class='{{ linkClass }}' |
||||
ng-disabled="isDisabled" |
||||
title='{{ linkTitle }}' |
||||
aria-label="{{ linkAriaLabel }}" |
||||
data-click-on-keypress="[13, 32]" |
||||
href> |
||||
<span ng-transclude class='{{ spanClass }}'></span> |
||||
</a> |
@ -0,0 +1,16 @@ |
||||
|
||||
// Based on wrapper by @banjankri
|
||||
// https://github.com/angular/angular/issues/16695#issuecomment-336456199
|
||||
import {downgradeComponent} from "@angular/upgrade/static"; |
||||
|
||||
export function downgradeAttributeDirective(componentClass:new(...args:any[]) => any) { |
||||
const wrapper = function($compile:any, $injector:any, $parse:any) { |
||||
const factory = downgradeComponent({ component: componentClass }); |
||||
const component = factory($compile, $injector, $parse); |
||||
component.restrict = "AE"; |
||||
return component; |
||||
}; |
||||
wrapper.$inject = ["$compile", "$injector", "$parse"]; |
||||
return wrapper; |
||||
} |
||||
|
@ -1,36 +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 {filtersModule} from './../../../angular-modules'; |
||||
|
||||
function htmlEscape() { |
||||
return function(string:string) { |
||||
return _.escape(string); |
||||
}; |
||||
} |
||||
|
||||
filtersModule.filter('htmlEscape', htmlEscape); |
@ -0,0 +1,110 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2018 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-2017 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 docs/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
import {opServicesModule} from 'core-app/angular-modules'; |
||||
import {downgradeInjectable} from '@angular/upgrade/static'; |
||||
import {Injectable} from '@angular/core'; |
||||
|
||||
@Injectable() |
||||
export class FocusHelperService { |
||||
private minimumOffsetForNewSwitchInMs = 100; |
||||
private lastFocusSwitch = -this.minimumOffsetForNewSwitchInMs; |
||||
private lastPriority = -1; |
||||
|
||||
private static FOCUSABLE_SELECTORS = ['a, button, :input, [tabindex], select']; |
||||
|
||||
public throttleAndCheckIfAllowedFocusChangeBasedOnTimeout() { |
||||
var allowFocusSwitch = (Date.now() - this.lastFocusSwitch) >= this.minimumOffsetForNewSwitchInMs; |
||||
|
||||
// Always update so that a chain of focus-change-requests gets considered as one
|
||||
this.lastFocusSwitch = Date.now(); |
||||
|
||||
return allowFocusSwitch; |
||||
} |
||||
|
||||
public checkIfAllowedFocusChange(priority?:any) { |
||||
var checkTimeout = this.throttleAndCheckIfAllowedFocusChangeBasedOnTimeout(); |
||||
|
||||
if (checkTimeout) { |
||||
// new timeout window -> reset priority
|
||||
this.lastPriority = -1; |
||||
} else { |
||||
// within timeout window
|
||||
if (priority > this.lastPriority) { |
||||
this.lastPriority = priority; |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return checkTimeout; |
||||
} |
||||
|
||||
public getFocusableElement(element:JQuery) { |
||||
var focusser = element.find('input.ui-select-focusser'); |
||||
|
||||
if (focusser.length > 0) { |
||||
return focusser[0]; |
||||
} |
||||
|
||||
var focusable = element; |
||||
|
||||
if (!element.is(FocusHelperService.FOCUSABLE_SELECTORS)) { |
||||
focusable = element.find(FocusHelperService.FOCUSABLE_SELECTORS); |
||||
} |
||||
|
||||
return focusable[0]; |
||||
} |
||||
|
||||
public focus(element:JQuery) { |
||||
var focusable = angular.element(this.getFocusableElement(element)), |
||||
$focusable = angular.element(focusable), |
||||
isDisabled = $focusable.is('[disabled]'); |
||||
|
||||
if (isDisabled && !$focusable.attr('ng-disabled')) { |
||||
$focusable.prop('disabled', false); |
||||
} |
||||
|
||||
focusable.focus(); |
||||
|
||||
if (isDisabled && !$focusable.attr('ng-disabled')) { |
||||
$focusable.prop('disabled', true); |
||||
} |
||||
} |
||||
|
||||
public focusElement(element:JQuery, priority?:any) { |
||||
if (!this.checkIfAllowedFocusChange(priority)) { |
||||
return; |
||||
} |
||||
|
||||
setTimeout(() => { |
||||
this.focus(element); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
opServicesModule.service('FocusHelper', downgradeInjectable(FocusHelperService)); |
@ -1,105 +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 {States} from '../../states.service'; |
||||
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||
import {WorkPackageTableFocusService} from 'core-components/wp-fast-table/state/wp-table-focus.service'; |
||||
import {StateService} from '@uirouter/core'; |
||||
|
||||
export class WorkPackageDestroyModalController { |
||||
public text:any; |
||||
public workPackages:WorkPackageResource[]; |
||||
public workPackageLabel:string; |
||||
|
||||
constructor(private $scope:any, |
||||
private $state:StateService, |
||||
private states:States, |
||||
private WorkPackageService:any, |
||||
private wpTableFocus:WorkPackageTableFocusService, |
||||
private I18n:op.I18n, |
||||
private wpDestroyModal:any) { |
||||
|
||||
this.workPackages = $scope.workPackages; |
||||
this.workPackageLabel = I18n.t('js.units.workPackage', { count: this.workPackages.length }); |
||||
|
||||
this.text = { |
||||
close: I18n.t('js.close_popup_title'), |
||||
cancel: I18n.t('js.button_cancel'), |
||||
confirm: I18n.t('js.button_confirm'), |
||||
warning: I18n.t('js.label_warning'), |
||||
|
||||
title: I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel }), |
||||
text: I18n.t('js.modals.destroy_work_package.text', { label: this.workPackageLabel, count: this.workPackages.length }), |
||||
|
||||
childCount: (wp:WorkPackageResource) => { |
||||
const count = this.children(wp).length; |
||||
return this.I18n.t('js.units.child_work_packages', {count: count}); |
||||
}, |
||||
hasChildren: (wp:WorkPackageResource) => |
||||
I18n.t('js.modals.destroy_work_package.has_children', {childUnits: this.text.childCount(wp) }), |
||||
deletesChildren: I18n.t('js.modals.destroy_work_package.deletes_children') |
||||
}; |
||||
} |
||||
|
||||
public $onInit() { |
||||
// Created for interface compliance
|
||||
} |
||||
|
||||
public close() { |
||||
try { |
||||
this.wpDestroyModal.deactivate(); |
||||
} catch(e) { |
||||
console.error("Failed to close deletion modal: " + e); |
||||
} |
||||
} |
||||
|
||||
public confirmDeletion() { |
||||
this.wpDestroyModal.deactivate(); |
||||
this.WorkPackageService.performBulkDelete(this.workPackages.map(el => el.id), true) |
||||
.then(() => { |
||||
this.close(); |
||||
this.wpTableFocus.clear(); |
||||
this.$state.go('work-packages.list'); |
||||
}); |
||||
} |
||||
|
||||
public childLabel (workPackage:WorkPackageResource) { |
||||
} |
||||
|
||||
public children(workPackage:WorkPackageResource) { |
||||
if (workPackage.hasOwnProperty('children')) { |
||||
return workPackage.children; |
||||
} else { |
||||
return []; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
wpControllersModule.controller('WorkPackageDestroyModalController', WorkPackageDestroyModalController); |
@ -1,76 +0,0 @@ |
||||
<div class="op-modal--portal" id="wp_destroy_modal"> |
||||
<div class="op-modal--modal-container"> |
||||
<div class="op-modal--modal-header"> |
||||
<a> |
||||
<i class="icon-close" |
||||
ng-click="$ctrl.close()" |
||||
title="{{ ::$ctrl.text.close }}"> |
||||
</i> |
||||
</a> |
||||
</div> |
||||
|
||||
<form name="modalWpDestroyForm" class="form danger-zone"> |
||||
<section class="form--section -inner-scrolling"> |
||||
<h3 class="form--section-title" ng-bind="::$ctrl.text.title"></h3> |
||||
|
||||
<div ng-if="$ctrl.workPackages.length === 1" |
||||
class="modal-inner-scrolling-container" |
||||
ng-init="workPackage = $ctrl.workPackages[0]; children = $ctrl.children(workPackage)"> |
||||
<p> |
||||
<span ng-bind="$ctrl.text.text"></span> |
||||
<br/> |
||||
<strong> |
||||
{{ workPackage.type.name }} |
||||
#{{ workPackage.id }} |
||||
{{ workPackage.subject }} |
||||
</strong> |
||||
</p> |
||||
<div ng-if="children.length > 0"> |
||||
<p class="danger-zone--warning"> |
||||
<span class="icon icon-error"></span> |
||||
<strong ng-bind="$ctrl.text.warning"></strong>: |
||||
<span ng-bind="$ctrl.text.hasChildren(workPackage)"></span> |
||||
</p> |
||||
<ul> |
||||
<li ng-repeat="child in children track by $index"> |
||||
#<span ng-bind="child.id"></span> |
||||
<span ng-bind="child.subject"></span> |
||||
</li> |
||||
</ul> |
||||
<p> |
||||
<span ng-bind="$ctrl.text.deletesChildren"></span> |
||||
</p> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="modal-inner-scrolling-container" ng-if="$ctrl.workPackages.length > 1"> |
||||
<p class="danger-zone--warning"> |
||||
<span class="icon icon-error"></span> |
||||
<strong ng-bind="$ctrl.text.text"></strong> |
||||
</p> |
||||
<ul> |
||||
<li ng-repeat="wp in $ctrl.workPackages track by $index"> |
||||
#<span ng-bind="wp.id"></span> |
||||
<span ng-bind="wp.subject"></span> |
||||
<strong ng-if="$ctrl.children(wp).length > 0"> |
||||
(+ {{ $ctrl.text.childCount(wp) }}) |
||||
</strong> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</section> |
||||
|
||||
<div class="form--space -left-spacing"> |
||||
<button class="button -danger" |
||||
ng-bind="::$ctrl.text.confirm" |
||||
ng-click="$ctrl.confirmDeletion()"> |
||||
</button> |
||||
<button class="button" |
||||
ng-bind="::$ctrl.text.cancel" |
||||
ng-click="$ctrl.close()"> |
||||
</button> |
||||
</div> |
||||
</form> |
||||
|
||||
</div> |
||||
</div> |
@ -1,39 +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 wpDestroyService(btfModal:any) { |
||||
return btfModal({ |
||||
controller: 'WorkPackageDestroyModalController', |
||||
controllerAs: '$ctrl', |
||||
templateUrl: '/components/modals/wp-destroy-modal/wp-destroy-modal.html' |
||||
}); |
||||
} |
||||
|
||||
wpControllersModule.factory('wpDestroyModal', wpDestroyService); |
@ -0,0 +1,78 @@ |
||||
<div class="op-modal--portal "> |
||||
<div id="wp_destroy_modal" |
||||
class="op-modal--modal-container wp-table--configuration-modal loading-indicator--location" |
||||
data-indicator-name="modal" |
||||
tabindex="0"> |
||||
<div class="op-modal--modal-header"> |
||||
<a class="op-modal--modal-close-button"> |
||||
<i |
||||
class="icon-close" |
||||
(click)="closeMe($event)" |
||||
[attr.title]="text.close"> |
||||
</i> |
||||
</a> |
||||
</div> |
||||
|
||||
<form name="modalWpDestroyForm" class="form danger-zone"> |
||||
<section class="form--section -inner-scrolling"> |
||||
<h3 class="form--section-title" [textContent]="text.title"></h3> |
||||
|
||||
<div *ngIf="singleWorkPackage" |
||||
class="modal-inner-scrolling-container"> |
||||
<p> |
||||
<span [textContent]="text.text"></span> |
||||
<br/> |
||||
<strong> |
||||
{{ singleWorkPackage.type.name }} |
||||
#{{ singleWorkPackage.id }} |
||||
{{ singleWorkPackage.subject }} |
||||
</strong> |
||||
</p> |
||||
<div *ngIf="singleWorkPackageChildren && singleWorkPackageChildren.length > 0"> |
||||
<p class="danger-zone--warning"> |
||||
<span class="icon icon-error"></span> |
||||
<strong [textContent]="text.warning"></strong>: |
||||
<span [textContent]="text.hasChildren(singleWorkPackage)"></span> |
||||
</p> |
||||
<ul> |
||||
<li *ngFor="let child of singleWorkPackageChildren"> |
||||
#<span [textContent]="child.id"></span> |
||||
<span [textContent]="child.subject"></span> |
||||
</li> |
||||
</ul> |
||||
<p> |
||||
<span [textContent]="text.deletesChildren"></span> |
||||
</p> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="modal-inner-scrolling-container" *ngIf="workPackages.length > 1"> |
||||
<p class="danger-zone--warning"> |
||||
<span class="icon icon-error"></span> |
||||
<strong [textContent]="text.text"></strong> |
||||
</p> |
||||
<ul> |
||||
<li *ngFor="let wp of workPackages"> |
||||
#<span [textContent]="wp.id"></span> |
||||
<span [textContent]="wp.subject"></span> |
||||
<strong *ngIf="children(wp).length > 0"> |
||||
(+ {{ text.childCount(wp) }}) |
||||
</strong> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</section> |
||||
|
||||
<div class="form--space -left-spacing"> |
||||
<button class="button -danger" |
||||
[textContent]="text.confirm" |
||||
(click)="confirmDeletion($event)"> |
||||
</button> |
||||
<button class="button" |
||||
[textContent]="text.cancel" |
||||
(click)="closeMe($event)"> |
||||
</button> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
</div> |
@ -0,0 +1,118 @@ |
||||
//-- 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 {WorkPackagesListService} from '../../wp-list/wp-list.service'; |
||||
import {States} from '../../states.service'; |
||||
import {WorkPackageNotificationService} from '../../wp-edit/wp-notification.service'; |
||||
import {NotificationsService} from "core-components/common/notifications/notifications.service"; |
||||
import {OpModalComponent} from "core-components/op-modals/op-modal.component"; |
||||
import {Component, ElementRef, Inject, OnInit} from "@angular/core"; |
||||
import {$stateToken, I18nToken, OpModalLocalsToken, WorkPackageServiceToken} from "core-app/angular4-transition-utils"; |
||||
import {OpModalLocalsMap} from "core-components/op-modals/op-modal.types"; |
||||
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||
import {WorkPackageTableFocusService} from 'core-components/wp-fast-table/state/wp-table-focus.service'; |
||||
import {StateService} from '@uirouter/core'; |
||||
|
||||
@Component({ |
||||
template: require('!!raw-loader!./wp-destroy.modal.html') |
||||
}) |
||||
export class WpDestroyModal extends OpModalComponent implements OnInit { |
||||
// When deleting multiple
|
||||
public workPackages:WorkPackageResource[]; |
||||
public workPackageLabel:string; |
||||
|
||||
// Single work package
|
||||
public singleWorkPackage:WorkPackageResource; |
||||
public singleWorkPackageChildren:WorkPackageResource[]; |
||||
|
||||
public text:{ [key:string]:any } = { |
||||
label_visibility_settings: this.I18n.t('js.label_visibility_settings'), |
||||
button_save: this.I18n.t('js.modals.button_save'), |
||||
confirm: this.I18n.t('js.button_confirm'), |
||||
warning: this.I18n.t('js.label_warning'), |
||||
cancel: this.I18n.t('js.button_cancel'), |
||||
close: this.I18n.t('js.close_popup_title'), |
||||
}; |
||||
|
||||
constructor(readonly elementRef:ElementRef, |
||||
@Inject(WorkPackageServiceToken) readonly WorkPackageService:any, |
||||
@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap, |
||||
@Inject(I18nToken) readonly I18n:op.I18n, |
||||
@Inject($stateToken) readonly $state:StateService, |
||||
readonly states:States, |
||||
readonly wpTableFocus:WorkPackageTableFocusService, |
||||
readonly wpListService:WorkPackagesListService, |
||||
readonly wpNotificationsService:WorkPackageNotificationService, |
||||
readonly notificationsService:NotificationsService) { |
||||
super(locals, elementRef); |
||||
} |
||||
|
||||
ngOnInit() { |
||||
super.ngOnInit(); |
||||
|
||||
this.workPackages = this.locals.workPackages; |
||||
this.workPackageLabel = this.I18n.t('js.units.workPackage', { count: this.workPackages.length }); |
||||
|
||||
// Ugly way to provide the same view bindings as the ng-init in the previous template.
|
||||
if (this.workPackages.length === 1) { |
||||
this.singleWorkPackage = this.workPackages[0]; |
||||
this.singleWorkPackageChildren = this.singleWorkPackage.children; |
||||
} |
||||
|
||||
this.text.title = this.I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel }), |
||||
this.text.text = this.I18n.t('js.modals.destroy_work_package.text', { label: this.workPackageLabel, count: this.workPackages.length }), |
||||
|
||||
this.text.childCount = (wp:WorkPackageResource) => { |
||||
const count = this.children(wp).length; |
||||
return this.I18n.t('js.units.child_work_packages', {count: count}); |
||||
}; |
||||
|
||||
this.text.hasChildren = (wp:WorkPackageResource) => |
||||
this.I18n.t('js.modals.destroy_work_package.has_children', {childUnits: this.text.childCount(wp) }), |
||||
|
||||
this.text.deletesChildren = this.I18n.t('js.modals.destroy_work_package.deletes_children'); |
||||
} |
||||
|
||||
|
||||
public confirmDeletion($event:JQueryEventObject) { |
||||
this.WorkPackageService.performBulkDelete(this.workPackages.map(el => el.id), true) |
||||
.then(() => { |
||||
this.closeMe($event); |
||||
this.wpTableFocus.clear(); |
||||
this.$state.go('work-packages.list'); |
||||
}); |
||||
} |
||||
|
||||
public children(workPackage:WorkPackageResource) { |
||||
if (workPackage.hasOwnProperty('children')) { |
||||
return workPackage.children; |
||||
} else { |
||||
return []; |
||||
} |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue