commit
06a05c115c
@ -0,0 +1,51 @@ |
|||||||
|
# Widget Boxes |
||||||
|
|
||||||
|
``` |
||||||
|
<form> |
||||||
|
<section class="widget-boxes"> |
||||||
|
<div class="widget-box"> |
||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-home1"></span> |
||||||
|
<span class="widget-box--header-title">Widget Box</span> |
||||||
|
</h3> |
||||||
|
<p class="widget-box--additional-info">This widget box can be used to display content belonging to one subject.</p> |
||||||
|
<ul class="widget-box--arrow-links"> |
||||||
|
<li> |
||||||
|
<a>Go to Link 1</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a>Go to link 2</a> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="widget-box"> |
||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-home2"></span> |
||||||
|
<span class="widget-box--header-title">Widget Box 2</span> |
||||||
|
</h3> |
||||||
|
<ul class="widget-box--enumeration"> |
||||||
|
<li> |
||||||
|
Enum1 |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
Enum2 |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
Enum3 |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
Enum4 |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div class="widget-box--buttons"> |
||||||
|
<a class="button -highlight"> |
||||||
|
<i class="button--icon icon-add"></i> |
||||||
|
<span class="button--text">Add</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</section> |
||||||
|
</form> |
||||||
|
|
||||||
|
``` |
@ -0,0 +1,106 @@ |
|||||||
|
//-- 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. |
||||||
|
//++ |
||||||
|
|
||||||
|
@mixin widget-box--style |
||||||
|
background: $widget-box-block-bg-color |
||||||
|
border: 1px solid $widget-box-block-border-color |
||||||
|
margin: 10px |
||||||
|
|
||||||
|
$widget-box--enumeration-width: 20px |
||||||
|
|
||||||
|
.widget-boxes--screen-header |
||||||
|
margin-left: 10px |
||||||
|
|
||||||
|
.widget-boxes |
||||||
|
display: flex |
||||||
|
flex-flow: row wrap |
||||||
|
|
||||||
|
.icon-context:before |
||||||
|
padding-right: 5px |
||||||
|
|
||||||
|
.widget-box |
||||||
|
@include widget-box--style |
||||||
|
padding: 10px 10px 10px 20px |
||||||
|
flex: 1 |
||||||
|
flex-basis: 32% |
||||||
|
display: flex |
||||||
|
flex-direction: column |
||||||
|
min-height: 250px |
||||||
|
word-wrap: break-words |
||||||
|
overflow: hidden |
||||||
|
|
||||||
|
.widget-box--header |
||||||
|
font-weight: bold |
||||||
|
font-size: 1.25rem |
||||||
|
border: none |
||||||
|
|
||||||
|
.widget-box--header-title |
||||||
|
vertical-align: middle |
||||||
|
.icon:before, |
||||||
|
.icon-context:before |
||||||
|
vertical-align: middle |
||||||
|
|
||||||
|
|
||||||
|
.widget-box--additional-info |
||||||
|
margin: 0 |
||||||
|
font-size: 0.9rem |
||||||
|
font-style: italic |
||||||
|
|
||||||
|
.widget-box--enumeration |
||||||
|
margin-left: 1.5rem |
||||||
|
margin-top: 0.5rem |
||||||
|
flex-grow: 2 |
||||||
|
|
||||||
|
.widget-box--arrow-links |
||||||
|
list-style: none |
||||||
|
margin: 0.5rem 0 1rem 0 |
||||||
|
flex-grow: 2 |
||||||
|
|
||||||
|
li:before |
||||||
|
@include icon-common |
||||||
|
@extend .icon-context |
||||||
|
content: "\e03f" |
||||||
|
display: inline-block |
||||||
|
font-size: 0.6rem |
||||||
|
color: $content-icon-link-color |
||||||
|
width: $widget-box--enumeration-width |
||||||
|
|
||||||
|
.-widget-box--arrow-multiline |
||||||
|
&:before |
||||||
|
float: left |
||||||
|
|
||||||
|
&:after |
||||||
|
clear: both |
||||||
|
content: "" |
||||||
|
display: table |
||||||
|
|
||||||
|
> div |
||||||
|
float: left |
||||||
|
margin-bottom: 10px |
||||||
|
//necessary for correct alignment even with long texts |
||||||
|
width: calc(100% - #{$widget-box--enumeration-width}) |
@ -0,0 +1,110 @@ |
|||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
module UserInvitation |
||||||
|
EVENT_NAME = 'user_invited' |
||||||
|
|
||||||
|
module_function |
||||||
|
|
||||||
|
## |
||||||
|
# Creates an invited user with the given email address. |
||||||
|
# If no first and last is given it will default to 'OpenProject User' |
||||||
|
# for the first name and 'To-be' for the last name. |
||||||
|
# The default login is the email address. |
||||||
|
# |
||||||
|
# @param email E-Mail address the invitation is sent to. |
||||||
|
# @param login User's login (optional) |
||||||
|
# @param first_name The user's first name (optional) |
||||||
|
# @param last_name The user's last name (optional) |
||||||
|
# |
||||||
|
# @yield [user] Allows modifying the created user before saving it. |
||||||
|
# |
||||||
|
# @return The invited user. If the invitation failed, calling `#registered?` |
||||||
|
# on the returned user will yield `false`. Check for validation errors |
||||||
|
# in that case. |
||||||
|
def invite_new_user(email:, login: nil, first_name: nil, last_name: nil) |
||||||
|
user = User.new login: login || email, |
||||||
|
mail: email, |
||||||
|
firstname: first_name || email, |
||||||
|
lastname: last_name || '(invited)', |
||||||
|
status: Principal::STATUSES[:invited] |
||||||
|
|
||||||
|
yield user if block_given? |
||||||
|
|
||||||
|
invite_user! user |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Invites the given user. An email will be sent to their email address |
||||||
|
# containing the token necessary for the user to register. |
||||||
|
# |
||||||
|
# Validates and saves the given user. The invitation will fail if the user is invalid. |
||||||
|
# |
||||||
|
# @return The invited user or nil if the invitation failed. |
||||||
|
def invite_user!(user) |
||||||
|
user, token = user_invitation user |
||||||
|
|
||||||
|
if token |
||||||
|
OpenProject::Notifications.send(EVENT_NAME, token) |
||||||
|
|
||||||
|
user |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Creates an invited user with the given email address. |
||||||
|
# If no first and last is given it will default to 'OpenProject User' |
||||||
|
# for the first name and 'To-be' for the last name. |
||||||
|
# The default login is the email address. |
||||||
|
# |
||||||
|
# @return Returns the user and the invitation token required to register. |
||||||
|
def user_invitation(user) |
||||||
|
User.transaction do |
||||||
|
user.invite |
||||||
|
|
||||||
|
if user.valid? |
||||||
|
token = invitation_token user |
||||||
|
token.save! |
||||||
|
|
||||||
|
user.save! |
||||||
|
|
||||||
|
return [user, token] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
[user, nil] |
||||||
|
end |
||||||
|
|
||||||
|
def token_action |
||||||
|
'invite' |
||||||
|
end |
||||||
|
|
||||||
|
def invitation_token(user) |
||||||
|
Token.find_or_initialize_by user: user, action: token_action |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,109 @@ |
|||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'uri' |
||||||
|
|
||||||
|
class InvitationsController < ApplicationController |
||||||
|
|
||||||
|
skip_before_filter :check_if_login_required, only: [:claim] |
||||||
|
|
||||||
|
def index |
||||||
|
|
||||||
|
end |
||||||
|
|
||||||
|
def create |
||||||
|
email = params.require(:email) |
||||||
|
user = User.create mail: email, login: email, firstname: email, lastname: email |
||||||
|
token = invite_user user |
||||||
|
|
||||||
|
if user.errors.empty? |
||||||
|
first, last = email.split("@") |
||||||
|
user.firstname = first |
||||||
|
user.lastname = "@#{last}" |
||||||
|
user.invite |
||||||
|
|
||||||
|
user.save! |
||||||
|
token.save! |
||||||
|
|
||||||
|
puts |
||||||
|
puts "CREATED NEW TOKEN: #{token.value}" |
||||||
|
puts |
||||||
|
|
||||||
|
redirect_to action: :show, id: user.id |
||||||
|
else |
||||||
|
flash.now[:error] = user.errors.full_messages.first |
||||||
|
|
||||||
|
render 'index', locals: { email: email } |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def show |
||||||
|
user = User.find params.require(:id) |
||||||
|
token = Token.find_by action: token_action, user: user |
||||||
|
|
||||||
|
render 'show', locals: { token: token.value, email: user.mail } |
||||||
|
end |
||||||
|
|
||||||
|
def claim |
||||||
|
token = Token.find_by action: token_action, value: params.require(:id) |
||||||
|
|
||||||
|
if current_user.logged? |
||||||
|
flash[:warning] = 'You are already registered, mate.' |
||||||
|
|
||||||
|
redirect_to invitation_path id: token.user_id |
||||||
|
elsif token.expired? |
||||||
|
flash[:error] = 'The invitation has expired.' |
||||||
|
token.destroy |
||||||
|
|
||||||
|
redirect_to signin_path |
||||||
|
else |
||||||
|
session[:invitation_token] = token.value |
||||||
|
flash[:info] = 'Create a new account or register now, pl0x!' |
||||||
|
|
||||||
|
redirect_to signin_path |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
module Functions |
||||||
|
def token_action |
||||||
|
'invitation' |
||||||
|
end |
||||||
|
|
||||||
|
def invite_user(user) |
||||||
|
token = invitation_token user |
||||||
|
|
||||||
|
token |
||||||
|
end |
||||||
|
|
||||||
|
def invitation_token(user) |
||||||
|
Token.find_or_initialize_by user: user, action: token_action |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
include Functions |
||||||
|
end |
@ -0,0 +1,50 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
module HomescreenHelper |
||||||
|
## |
||||||
|
# Homescreen name |
||||||
|
def organization_name |
||||||
|
Setting.app_title || Setting.software_name |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Homescreen organization icon |
||||||
|
def organization_icon |
||||||
|
content_tag :span, '', class: 'icon-context icon-enterprise' |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Returns the user avatar or a default image |
||||||
|
def homescreen_user_avatar |
||||||
|
avatar = avatar(User.current) |
||||||
|
|
||||||
|
avatar.presence || content_tag(:span, '', class: 'icon-context icon-user1') |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,39 @@ |
|||||||
|
class DummyAuthSource < AuthSource |
||||||
|
def test_connection |
||||||
|
# the dummy connection is always available |
||||||
|
end |
||||||
|
|
||||||
|
def authenticate(login, password) |
||||||
|
existing_user(login, password) || on_the_fly_user(login) |
||||||
|
end |
||||||
|
|
||||||
|
def auth_method_name |
||||||
|
'LDAP' |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def existing_user(login, password) |
||||||
|
registered_login?(login) && password == 'dummy' |
||||||
|
end |
||||||
|
|
||||||
|
def on_the_fly_user(login) |
||||||
|
return nil unless onthefly_register? |
||||||
|
|
||||||
|
{ |
||||||
|
firstname: login.capitalize, |
||||||
|
lastname: 'Dummy', |
||||||
|
mail: 'login@DerpLAP.net', |
||||||
|
auth_source_id: id |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
def registered_login?(login) |
||||||
|
not users.where(login: login).empty? # empty? to use EXISTS query |
||||||
|
end |
||||||
|
|
||||||
|
# Does this auth source backend allow password changes? |
||||||
|
def self.allow_password_changes? |
||||||
|
false |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,149 @@ |
|||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'uri' |
||||||
|
require 'cgi' |
||||||
|
|
||||||
|
# This capsulates the validation of a requested redirect URL. |
||||||
|
# |
||||||
|
class RedirectPolicy |
||||||
|
attr_reader :validated_redirect_url, :request |
||||||
|
|
||||||
|
def initialize(requested_url, hostname:, default:, return_escaped: true) |
||||||
|
@current_host = hostname |
||||||
|
@return_escaped = return_escaped |
||||||
|
|
||||||
|
@requested_url = preprocess(requested_url) |
||||||
|
@default_url = default |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Performs all validations for the requested URL |
||||||
|
def valid? |
||||||
|
return false if @requested_url.nil? |
||||||
|
|
||||||
|
[ |
||||||
|
# back_url must not contain two consecutive dots |
||||||
|
:no_upper_levels, |
||||||
|
# Require the path to begin with a slash |
||||||
|
:path_has_slash, |
||||||
|
# do not redirect user to another host |
||||||
|
:same_host, |
||||||
|
# do not redirect user to the login or register page |
||||||
|
:path_not_blacklisted, |
||||||
|
# do not redirect to another subdirectory |
||||||
|
:matches_relative_root |
||||||
|
].all? { |check| send(check) } |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Return a valid redirect URI. |
||||||
|
# If the validation check on the current back URL apply |
||||||
|
def redirect_url |
||||||
|
if valid? |
||||||
|
postprocess(@requested_url) |
||||||
|
else |
||||||
|
@default_url |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
## |
||||||
|
# Preprocesses the requested redirect URL. |
||||||
|
# - Escapes it when necessary |
||||||
|
# - Tries to parse it |
||||||
|
# - Escapes the redirect URL when requested so. |
||||||
|
def preprocess(requested) |
||||||
|
url = URI.escape(CGI.unescape(requested.to_s)) |
||||||
|
URI.parse(url) |
||||||
|
rescue URI::InvalidURIError => e |
||||||
|
Rails.logger.warn("Encountered invalid redirect URL '#{requested}': #{e.message}") |
||||||
|
nil |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Postprocesses the validated URL |
||||||
|
def postprocess(redirect_url) |
||||||
|
# Remove basic auth credentials |
||||||
|
redirect_url.userinfo = '' |
||||||
|
|
||||||
|
if @return_escaped |
||||||
|
redirect_url.to_s |
||||||
|
else |
||||||
|
URI.unescape(redirect_url.to_s) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Avoid paths with references to parent paths |
||||||
|
def no_upper_levels |
||||||
|
!@requested_url.path.include? '../' |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Require URLs to contain a path slash. |
||||||
|
# This will always be the case for parsed URLs unless |
||||||
|
# +URI.parse('@foo.bar')+ or a non-root relative URL +URI.parse('foo')+ |
||||||
|
def path_has_slash |
||||||
|
@requested_url.path =~ %r{\A/([^/]|\z)} |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# do not redirect user to another host (even protocol relative urls have the host set) |
||||||
|
# whenever a host is set it must match the request's host |
||||||
|
def same_host |
||||||
|
@requested_url.host.nil? || @requested_url.host == @current_host |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Avoid redirect URLs to specific locations, such as login page |
||||||
|
def path_not_blacklisted |
||||||
|
!@requested_url.path.match( |
||||||
|
%r{/( |
||||||
|
# Ignore login since redirect to back url is result of successful login. |
||||||
|
login | |
||||||
|
# When signing out with a direct login provider enabled you will be left at the logout |
||||||
|
# page with a message indicating that you were logged out. Logging in from there would |
||||||
|
# normally cause you to be redirected to this page. As it is the logout page, however, |
||||||
|
# this would log you right out again after a successful login. |
||||||
|
logout | |
||||||
|
# Avoid sending users to the register form. The exact reasoning behind |
||||||
|
# this is unclear, but grown from tradition. |
||||||
|
account/register |
||||||
|
)}x # ignore whitespace |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Requires the redirect URL to reside inside the relative root, when given. |
||||||
|
def matches_relative_root |
||||||
|
relative_root = OpenProject::Configuration['rails_relative_url_root'] |
||||||
|
relative_root.blank? || @requested_url.path.starts_with?(relative_root) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,47 @@ |
|||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-settings"></span> |
||||||
|
<span class="widget-box--header-title"><%= l(:label_administration) %></span> |
||||||
|
</h3> |
||||||
|
|
||||||
|
<ul class="widget-box--arrow-links"> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_project_plural), admin_projects_path, |
||||||
|
title: l(:label_project_plural) %> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_user_plural), users_path, |
||||||
|
title: l(:label_user_plural) %> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_group_plural), groups_path, |
||||||
|
title: l(:label_group_plural) %> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_role_and_permissions), roles_path, |
||||||
|
title: l(:label_role_and_permissions) %> |
||||||
|
|
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_work_package_types), types_path, |
||||||
|
title: l(:label_work_package_types) %> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_work_package_status), statuses_path, |
||||||
|
title: l(:label_work_package_status) %> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_workflow_plural), workflows_path, |
||||||
|
title: l(:label_workflow_plural) %> |
||||||
|
|
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l('attributes.custom_values'), custom_fields_path, |
||||||
|
title: l('attributes.custom_values') %> |
||||||
|
|
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_settings), settings_path, |
||||||
|
title: l(:label_settings) %> |
||||||
|
</li> |
||||||
|
<%= call_hook(:homescreen_administration_links) %> |
||||||
|
</ul> |
@ -0,0 +1,55 @@ |
|||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-op-icon"></span> |
||||||
|
<span class="widget-box--header-title"><%= l('homescreen.blocks.community') %></span> |
||||||
|
</h3> |
||||||
|
|
||||||
|
<ul class="widget-box--arrow-links"> |
||||||
|
<li> |
||||||
|
<a href="https://www.openproject.org/open-source/release-notes/" |
||||||
|
title="<%= l(:label_release_notes) %>"> |
||||||
|
<%= l(:label_release_notes) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a href="https://community.openproject.org/projects/openproject/roadmap" |
||||||
|
title="<%= l(:label_development_roadmap) %>"> |
||||||
|
<%= l(:label_development_roadmap) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a href="https://community.openproject.org/projects/openproject/work_packages" |
||||||
|
title="<%= l(:label_report_bug) %>"> |
||||||
|
<%= l(:label_report_bug) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a href="https://www.openproject.com/enterprise-services/" |
||||||
|
title="<%= l(:label_professional_support) %>"> |
||||||
|
<%= l(:label_professional_support) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a href="https://www.openproject.org/blog/" |
||||||
|
title="<%= l(:label_blog) %>"> |
||||||
|
<%= l(:label_blog) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a href="https://www.openproject.org/open-source/openproject-plugins/" |
||||||
|
title="<%= l(:label_plugins) %>"> |
||||||
|
<%= l(:label_plugins) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a href="https://crowdin.com/projects/opf" |
||||||
|
title="<%= l(:label_add_edit_translations) %>"> |
||||||
|
<%= l(:label_add_edit_translations) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<a href="https://www.openproject.org/api/" |
||||||
|
title="<%= l(:label_api_documentation) %>"> |
||||||
|
<%= l(:label_api_documentation) %> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
</ul> |
@ -0,0 +1,17 @@ |
|||||||
|
<h3 class="widget-box--header"> |
||||||
|
<%= homescreen_user_avatar %> |
||||||
|
<span class="widget-box--header-title"><%= l(:label_my_account) %></span> |
||||||
|
</h3> |
||||||
|
|
||||||
|
<ul class="widget-box--arrow-links"> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_profile), my_account_path, title: l(:label_profile) %> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:label_my_page), my_page_path, |
||||||
|
title: l(:label_my_page) %> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<%= link_to l(:button_change_password), my_password_path, title: l(:button_change_password) %> |
||||||
|
</li> |
||||||
|
</ul> |
@ -0,0 +1,20 @@ |
|||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-news"></span> |
||||||
|
<span class="widget-box--header-title"><%= l(:label_news_latest) %></span> |
||||||
|
</h3> |
||||||
|
|
||||||
|
<% unless @news.empty? %> |
||||||
|
<ul class="widget-box--arrow-links"> |
||||||
|
<% @news.each do |news| %> |
||||||
|
<li class="-widget-box--arrow-multiline"> |
||||||
|
<div> |
||||||
|
<%= avatar(news.author, {class: 'avatar-mini'}) %> |
||||||
|
<%= link_to_project(news.project) + ': ' %> |
||||||
|
<%= link_to h(news.title), news_path(news) %> |
||||||
|
<br/> |
||||||
|
<p class="widget-box--additional-info"><%= authoring news.created_on, news.author %></p> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<% end %> |
||||||
|
</ul> |
||||||
|
<% end %> |
@ -0,0 +1,28 @@ |
|||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-unit"></span> |
||||||
|
<span class="widget-box--header-title"><%= l(:label_project_plural) %></span> |
||||||
|
</h3> |
||||||
|
|
||||||
|
<% unless @newest_projects.empty? %> |
||||||
|
<p class="widget-box--additional-info"><%= l('homescreen.additional.projects') %></p> |
||||||
|
<ul class="widget-box--arrow-links"> |
||||||
|
<% @newest_projects.each do |project| %> |
||||||
|
<li> |
||||||
|
<%= link_to project, project_path(project), :title => project.short_description %> |
||||||
|
<small>(<%= format_date(project.created_on) %>)</small> |
||||||
|
</li> |
||||||
|
<% end %> |
||||||
|
</ul> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<div class="widget-box--blocks--buttons"> |
||||||
|
<% if User.current.allowed_to?(:add_project, nil, global: true) %> |
||||||
|
<%= link_to new_project_path, class: 'button -alt-highlight' do %> |
||||||
|
<i class="button--icon icon-add"></i> |
||||||
|
<span class="button--text"><%= l(:label_project_new) %></span> |
||||||
|
<% end %> |
||||||
|
<% end %> |
||||||
|
<%= link_to l(:label_project_view_all), projects_path, |
||||||
|
class: 'button -highlight', |
||||||
|
title: l(:label_project_view_all) %> |
||||||
|
</div> |
@ -0,0 +1,26 @@ |
|||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-group"></span> |
||||||
|
<span class="widget-box--header-title"><%= l(:label_user_plural) %></span> |
||||||
|
</h3> |
||||||
|
|
||||||
|
<p class="widget-box--additional-info"><%= l('homescreen.additional.users') %></p> |
||||||
|
|
||||||
|
<% unless @newest_users.empty? %> |
||||||
|
<ul class="widget-box--arrow-links"> |
||||||
|
<% @newest_users.each do |user| %> |
||||||
|
<li> |
||||||
|
<%= link_to user, user_path(user), :title => user.name %> |
||||||
|
<small>(<%= format_date(user.created_on) %>)</small> |
||||||
|
</li> |
||||||
|
<% end %> |
||||||
|
</ul> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<div class="widget-box--buttons"> |
||||||
|
<% if User.current.admin? %> |
||||||
|
<%= link_to new_user_path, class: 'button -alt-highlight' do %> |
||||||
|
<i class="button--icon icon-add"></i> |
||||||
|
<span class="button--text"><%= l(:label_invite_user) %></span> |
||||||
|
<% end %> |
||||||
|
<% end %> |
||||||
|
</div> |
@ -0,0 +1,8 @@ |
|||||||
|
<h3 class="widget-box--header"> |
||||||
|
<span class="icon-context icon-projects"></span> |
||||||
|
<span class="widget-box--header-title"><%= Setting.welcome_title.presence || organization_name %></span> |
||||||
|
</h3> |
||||||
|
|
||||||
|
<div class="wiki"> |
||||||
|
<%= format_text(Setting.welcome_text, headings: false) %> |
||||||
|
</div> |
@ -0,0 +1,61 @@ |
|||||||
|
<%#-- 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. |
||||||
|
|
||||||
|
++#%> |
||||||
|
<% breadcrumb_paths(nil) %> |
||||||
|
<div class="widget-boxes--screen-header"> |
||||||
|
<h2> |
||||||
|
<span><%= organization_icon %></span> |
||||||
|
<%= organization_name %> |
||||||
|
</h2> |
||||||
|
</div> |
||||||
|
|
||||||
|
<% if @homescreen[:blocks].any? %> |
||||||
|
<section class="widget-boxes"> |
||||||
|
<% @homescreen[:blocks].each do |block| %> |
||||||
|
<% if block[:if].nil? || instance_eval(&block[:if]) %> |
||||||
|
<div class="widget-box"> |
||||||
|
<%= render partial: "homescreen/blocks/#{block[:partial]}", locals: (block[:locals] || {}) %> |
||||||
|
</div> |
||||||
|
<% end %> |
||||||
|
<% end %> |
||||||
|
</section> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<% if @homescreen[:links].any? %> |
||||||
|
<section class="homescreen--links"> |
||||||
|
<% @homescreen[:links].each do |link| %> |
||||||
|
<% title = I18n.t(link[:label], scope: 'homescreen.links') %> |
||||||
|
<a class="homescreen--links--item" href="<%= link[:url] %>" title="<%= title %>"> |
||||||
|
<span class="<%= link[:icon] %>"></span> |
||||||
|
<%= title %> |
||||||
|
</a> |
||||||
|
<% end %> |
||||||
|
</section> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<%= call_hook :homescreen_after_links %> |
@ -0,0 +1,4 @@ |
|||||||
|
// reload iframes parent (project members view) |
||||||
|
// to show updated list of members and a flash message |
||||||
|
window.parent.document.location.reload(); |
||||||
|
|
@ -0,0 +1,158 @@ |
|||||||
|
<%#-- 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. |
||||||
|
|
||||||
|
++#%> |
||||||
|
|
||||||
|
<% html_title 'Members' %> |
||||||
|
<%= toolbar title: 'Members' do %> |
||||||
|
<% if authorize_for(:members, :new) %> |
||||||
|
<a href="<%= new_project_member_path %>" id="add-member-button" title="Add Member" class="button -alt-highlight"> |
||||||
|
<i class="button--icon icon-add"></i> |
||||||
|
<span class="button--text"><%= I18n.t(:button_add_member) %></span> |
||||||
|
</a> |
||||||
|
<% end %> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<%= error_messages_for 'member' %> |
||||||
|
|
||||||
|
<div> |
||||||
|
<% if @members.any? %> |
||||||
|
<% authorized = authorize_for('members', 'update') %> |
||||||
|
<div class="generic-table--container"> |
||||||
|
<div class="generic-table--results-container"> |
||||||
|
<table interactive-table role="grid" class="generic-table"> |
||||||
|
<colgroup> |
||||||
|
<col highlight-col> |
||||||
|
<col highlight-col> |
||||||
|
<%= call_hook(:view_projects_settings_members_table_colgroup, :project => @project) %> |
||||||
|
<col> |
||||||
|
</colgroup> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th> |
||||||
|
<div class="generic-table--sort-header-outer"> |
||||||
|
<div class="generic-table--sort-header"> |
||||||
|
<span> |
||||||
|
<%= User.model_name.human %> / <%= Group.model_name.human %> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</th> |
||||||
|
<th> |
||||||
|
<div class="generic-table--sort-header-outer"> |
||||||
|
<div class="generic-table--sort-header"> |
||||||
|
<span> |
||||||
|
<%= l(:label_role_plural) %> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</th> |
||||||
|
<%= call_hook(:view_projects_settings_members_table_header, :project => @project) %> |
||||||
|
<th></th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<% @members.each do |member| %> |
||||||
|
<% next if member.new_record? %> |
||||||
|
<tr id="member-<%= member.id %>" class=" member"> |
||||||
|
<% |
||||||
|
member_type = member.principal.class.name.downcase |
||||||
|
classes = [ |
||||||
|
member_type, |
||||||
|
('icon icon-group' if member_type == 'group'), |
||||||
|
user_status_class(member.principal) |
||||||
|
].compact.join(' ') |
||||||
|
%> |
||||||
|
<td class="<%= classes %>" title="<%= user_status_i18n member.principal %>"> |
||||||
|
<%= link_to_user member.principal %> |
||||||
|
<% if member.user && member.user.invited? %> |
||||||
|
<i title="<%= t('text_user_invited') %>" class="icon icon-mail"></i> |
||||||
|
<% end %> |
||||||
|
</td> |
||||||
|
<td class="roles"> |
||||||
|
<span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> |
||||||
|
<% if authorized %> |
||||||
|
<%= form_for(member, :url => {:controller => '/members', |
||||||
|
:action => 'update', |
||||||
|
:id => member, |
||||||
|
:page => params[:page], |
||||||
|
:per_page => params[:per_page] }, |
||||||
|
:method => :put, |
||||||
|
:html => { :id => "member-#{member.id}-roles-form", |
||||||
|
:class => 'hol', |
||||||
|
:style => 'display:none' }) do |f| %> |
||||||
|
<p><% @roles.each do |role| %> |
||||||
|
<label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), |
||||||
|
:disabled => member.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?} %> <%=h role %></label> |
||||||
|
<% end %></p> |
||||||
|
<%= hidden_field_tag 'member[role_ids][]', '' %> |
||||||
|
<p><%= submit_tag l(:button_change), :class => 'button -highlight -small' %> |
||||||
|
<%= link_to_function l(:button_cancel), |
||||||
|
"$('member-#{member.id}-roles').show(); $('member-#{member.id}-roles-form').hide(); return false;", |
||||||
|
class: 'button -small' %></p> |
||||||
|
<% end %> |
||||||
|
<% end %> |
||||||
|
</td> |
||||||
|
<%= call_hook(:view_projects_settings_members_table_row, { :project => @project, :member => member}) %> |
||||||
|
<% if authorized %> |
||||||
|
<td class="buttons"> |
||||||
|
<% |
||||||
|
delete_class, delete_title = if member.disposable? |
||||||
|
['icon icon-delete', I18n.t(:title_remove_and_delete_user)] |
||||||
|
else |
||||||
|
['icon icon-close', I18n.t(:button_remove)] |
||||||
|
end |
||||||
|
%> |
||||||
|
<%= link_to_function '', "$('member-#{member.id}-roles').hide(); $('member-#{member.id}-roles-form').show(); return false;", :class => 'icon icon-edit', :title => l(:button_edit) %> |
||||||
|
<%= link_to('', {:controller => '/members', :action => 'destroy', :id => member, :page => params[:page]}, |
||||||
|
:method => :delete, |
||||||
|
data: { confirm: ((!User.current.admin? && member.include?(User.current)) ? l(:text_own_membership_delete_confirmation) : nil) }, |
||||||
|
:title => delete_title, :class => delete_class) if member.deletable? %> |
||||||
|
</td> |
||||||
|
<% end %> |
||||||
|
</tr> |
||||||
|
<% end %> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
<div class="generic-table--header-background"></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<%= pagination_links_full @members, @pagination_url_options || {} %> |
||||||
|
<% else %> |
||||||
|
<div class="generic-table--container"> |
||||||
|
<div class="generic-table--no-results-container"> |
||||||
|
<h2 class="generic-table--no-results-title"> |
||||||
|
<i class="icon-info"></i> |
||||||
|
<%= l(:label_nothing_display) %> |
||||||
|
</h2> |
||||||
|
<div class="generic-table--no-results-description"> |
||||||
|
<p class="nodata"><%= l(:label_no_data) %></p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<% end %> |
||||||
|
</div> |
@ -0,0 +1,43 @@ |
|||||||
|
<%#-- 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. |
||||||
|
|
||||||
|
++#%> |
||||||
|
<%= javascript_include_tag "members_form.js" %> |
||||||
|
|
||||||
|
<%= error_messages_for 'member' %> |
||||||
|
|
||||||
|
<div> |
||||||
|
<% if @principals_available.any? %> |
||||||
|
<%= render :partial => "members/member_form", |
||||||
|
:locals => { :project => @project, :roles => @roles } %> |
||||||
|
<% else %> |
||||||
|
<p> |
||||||
|
<%= I18n.t('text_no_roles_defined') %> |
||||||
|
</p> |
||||||
|
<%= link_to I18n.t('button_back'), :back, class: 'button' %> |
||||||
|
<% end %> |
||||||
|
</div> |
@ -1,147 +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. |
|
||||||
|
|
||||||
++#%> |
|
||||||
<%= javascript_include_tag "members_form.js" %> |
|
||||||
|
|
||||||
<%= error_messages_for 'member' %> |
|
||||||
<% roles = Role.find_all_givable |
|
||||||
# Check if there is at least one principal that can be added to the project |
|
||||||
principals_available = @project.possible_members("", 1) |
|
||||||
member_per_page = 20 |
|
||||||
|
|
||||||
@members = @project.member_principals.includes(:roles, :principal, :member_roles) |
|
||||||
.order(User::USER_FORMATS_STRUCTURE[Setting.user_format].map{|attr| attr.to_s}.join(", ")) |
|
||||||
.page(params[:page]) |
|
||||||
.references(:users) |
|
||||||
.per_page(per_page_param) |
|
||||||
%> |
|
||||||
<div> |
|
||||||
<% if roles.any? && principals_available.any? %> |
|
||||||
<%= render :partial => "members/member_form", |
|
||||||
:locals => { :project => @project, |
|
||||||
:members => @members, |
|
||||||
:roles => roles } %> |
|
||||||
|
|
||||||
<% end %> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<% if @members.any? %> |
|
||||||
<% authorized = authorize_for('members', 'update') %> |
|
||||||
<div class="generic-table--container"> |
|
||||||
<div class="generic-table--results-container"> |
|
||||||
<table interactive-table role="grid" class="generic-table"> |
|
||||||
<colgroup> |
|
||||||
<col highlight-col> |
|
||||||
<col highlight-col> |
|
||||||
<%= call_hook(:view_projects_settings_members_table_colgroup, :project => @project) %> |
|
||||||
<col> |
|
||||||
</colgroup> |
|
||||||
<thead> |
|
||||||
<tr> |
|
||||||
<th> |
|
||||||
<div class="generic-table--sort-header-outer"> |
|
||||||
<div class="generic-table--sort-header"> |
|
||||||
<span> |
|
||||||
<%= User.model_name.human %> / <%= Group.model_name.human %> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</th> |
|
||||||
<th> |
|
||||||
<div class="generic-table--sort-header-outer"> |
|
||||||
<div class="generic-table--sort-header"> |
|
||||||
<span> |
|
||||||
<%= l(:label_role_plural) %> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</th> |
|
||||||
<%= call_hook(:view_projects_settings_members_table_header, :project => @project) %> |
|
||||||
<th></th> |
|
||||||
</tr> |
|
||||||
</thead> |
|
||||||
<tbody> |
|
||||||
<% @members.each do |member| %> |
|
||||||
<% next if member.new_record? %> |
|
||||||
<tr id="member-<%= member.id %>" class=" member"> |
|
||||||
<td class="<%= member.principal.class.name.downcase %> <%= 'icon icon-group' if member.principal.class.name.downcase == 'group' %> <%= user_status_class member.principal%>" title="<%= user_status_i18n member.principal%>"><%= link_to_user member.principal %></td> |
|
||||||
<td class="roles"> |
|
||||||
<span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> |
|
||||||
<% if authorized %> |
|
||||||
<%= form_for(member, :url => {:controller => '/members', |
|
||||||
:action => 'update', |
|
||||||
:id => member, |
|
||||||
:page => params[:page]}, |
|
||||||
:method => :put, |
|
||||||
:remote => true, |
|
||||||
:html => { :id => "member-#{member.id}-roles-form", |
|
||||||
:class => 'hol', |
|
||||||
:style => 'display:none' }) do |f| %> |
|
||||||
<p><% roles.each do |role| %> |
|
||||||
<label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), |
|
||||||
:disabled => member.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?} %> <%=h role %></label> |
|
||||||
<% end %></p> |
|
||||||
<%= hidden_field_tag 'member[role_ids][]', '' %> |
|
||||||
<p><%= submit_tag l(:button_change), :class => 'button -highlight -small' %> |
|
||||||
<%= link_to_function l(:button_cancel), |
|
||||||
"$('member-#{member.id}-roles').show(); $('member-#{member.id}-roles-form').hide(); return false;", |
|
||||||
class: 'button -small' %></p> |
|
||||||
<% end %> |
|
||||||
<%= call_hook(:view_projects_settings_members_table_row, { :project => @project, :member => member}) %> |
|
||||||
<td class="buttons"> |
|
||||||
<%= link_to_function l(:button_edit), "$('member-#{member.id}-roles').hide(); $('member-#{member.id}-roles-form').show(); return false;", :class => 'icon icon-edit' %> |
|
||||||
<%= link_to(l(:button_delete), {:controller => '/members', :action => 'destroy', :id => member, :page => params[:page]}, |
|
||||||
:method => :delete, |
|
||||||
:remote => true, |
|
||||||
data: { confirm: ((!User.current.admin? && member.include?(User.current)) ? l(:text_own_membership_delete_confirmation) : nil) }, |
|
||||||
:title => l(:button_delete), :class => 'icon icon-delete') if member.deletable? %> |
|
||||||
</td> |
|
||||||
<% end %> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<% end %> |
|
||||||
</tbody> |
|
||||||
</table> |
|
||||||
<div class="generic-table--header-background"></div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<%= pagination_links_full @members, params: { tab: 'members' }.merge(@pagination_url_options || {}) %> |
|
||||||
<% else %> |
|
||||||
<div class="generic-table--container"> |
|
||||||
<div class="generic-table--no-results-container"> |
|
||||||
<h2 class="generic-table--no-results-title"> |
|
||||||
<i class="icon-info"></i> |
|
||||||
<%= l(:label_nothing_display) %> |
|
||||||
</h2> |
|
||||||
<div class="generic-table--no-results-description"> |
|
||||||
<p class="nodata"><%= l(:label_no_data) %></p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<% end %> |
|
||||||
</div> |
|
@ -0,0 +1,60 @@ |
|||||||
|
<%#-- 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. |
||||||
|
|
||||||
|
++#%> |
||||||
|
|
||||||
|
<%= error_messages_for 'user' %> |
||||||
|
|
||||||
|
<%= javascript_include_tag 'admin_users' %> |
||||||
|
|
||||||
|
<!--[form:user]--> |
||||||
|
<section class="form--section"> |
||||||
|
<div class="form--field"><%= f.text_field :mail, required: true, autofocus: true %></div> |
||||||
|
<div class="form--field"><%= f.text_field :firstname, required: true %></div> |
||||||
|
<div class="form--field"><%= f.text_field :lastname, required: true %></div> |
||||||
|
|
||||||
|
<%= render partial: 'customizable/field', |
||||||
|
collection: @user.custom_field_values, |
||||||
|
as: :value, |
||||||
|
locals: { form: f } %> |
||||||
|
|
||||||
|
<% unless @auth_sources.empty? || OpenProject::Configuration.disable_password_login? %> |
||||||
|
<div class="form--field"> |
||||||
|
<% sources = ([[l(:label_internal), ""]] + @auth_sources.collect { |a| [a.name, a.id] }) %> |
||||||
|
<%= f.select :auth_source_id, sources %> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form--field" id="new_user_login" style="display: none;"> |
||||||
|
<%= f.text_field :login, :required => true, :size => 25, :disabled => true %> |
||||||
|
</div> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<div class="form--field"><%= f.check_box :admin, :disabled => (@user == User.current) %></div> |
||||||
|
<%= call_hook(:view_users_form, :user => @user, :form => f) %> |
||||||
|
</section> |
||||||
|
|
||||||
|
<!--[eoform:user]--> |
@ -0,0 +1,73 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
class DeliverNotificationJob |
||||||
|
include OpenProject::BeforeDelayedJob |
||||||
|
|
||||||
|
def initialize(recipient_id, sender_id) |
||||||
|
@recipient_id = recipient_id |
||||||
|
@sender_id = sender_id |
||||||
|
end |
||||||
|
|
||||||
|
def perform |
||||||
|
# nothing to do if recipient was deleted in the meantime |
||||||
|
return unless recipient |
||||||
|
|
||||||
|
mail = User.execute_as(recipient) { build_mail } |
||||||
|
if mail |
||||||
|
mail.deliver |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
# To be implemented by subclasses. |
||||||
|
# Actual recipient and sender User objects are passed (always non-nil). |
||||||
|
# Returns a Mail::Message, or nil if no message should be sent. |
||||||
|
def render_mail(recipient:, sender:) |
||||||
|
raise 'SubclassResponsibility' |
||||||
|
end |
||||||
|
|
||||||
|
def build_mail |
||||||
|
render_mail(recipient: recipient, sender: sender) |
||||||
|
rescue StandardError => e |
||||||
|
Rails.logger.error "#{self.class.name}: Unexpected error rendering a mail: #{e}" |
||||||
|
# not raising, to avoid re-schedule of DelayedJob; don't expect render errors to fix themselves |
||||||
|
# by retrying |
||||||
|
nil |
||||||
|
end |
||||||
|
|
||||||
|
def recipient |
||||||
|
@recipient ||= User.find_by(id: @recipient_id) |
||||||
|
end |
||||||
|
|
||||||
|
def sender |
||||||
|
@sender ||= User.find_by(id: @sender_id) || DeletedUser.first |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,77 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'open_project/homescreen' |
||||||
|
|
||||||
|
OpenProject::Homescreen.manage :blocks do |blocks| |
||||||
|
blocks.push( |
||||||
|
{ partial: 'welcome', |
||||||
|
if: Proc.new { Setting.welcome_on_homescreen? && !Setting.welcome_text.empty? } }, |
||||||
|
{ partial: 'projects' }, |
||||||
|
{ partial: 'users', |
||||||
|
if: Proc.new { User.current.admin? } }, |
||||||
|
{ partial: 'my_account', |
||||||
|
if: Proc.new { User.current.logged? } }, |
||||||
|
{ partial: 'news', |
||||||
|
if: Proc.new { !@news.empty? } }, |
||||||
|
{ partial: 'community' }, |
||||||
|
{ partial: 'administration', |
||||||
|
if: Proc.new { User.current.admin? } } |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
OpenProject::Homescreen.manage :links do |links| |
||||||
|
links.push( |
||||||
|
{ |
||||||
|
label: :user_guides, |
||||||
|
icon: 'icon-context icon-rename', |
||||||
|
url: 'https://www.openproject.org/help/user-guides/' |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: :faq, |
||||||
|
icon: 'icon-context icon-faq', |
||||||
|
url: 'https://www.openproject.org/help/faq/' |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: :glossary, |
||||||
|
icon: 'icon-context icon-glossar', |
||||||
|
url: 'https://www.openproject.org/help/user-guides/glossary/' |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: :shortcuts, |
||||||
|
icon: 'icon-context icon-shortcuts', |
||||||
|
url: 'https://www.openproject.org/help/user-guides/keyboard-shortcuts-access-keys/' |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: :forums, |
||||||
|
icon: 'icon-context icon-bubble3', |
||||||
|
url: 'https://community.openproject.org/projects/openproject/boards' |
||||||
|
} |
||||||
|
) |
||||||
|
end |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue