Compare commits
13 Commits
dev
...
feature/in
Author | SHA1 | Date |
---|---|---|
Benjamin Bädorf | f2fe7285d6 | 4 years ago |
Benjamin Bädorf | 7cbfdc6afe | 4 years ago |
Benjamin Bädorf | cbc8e97fdc | 4 years ago |
Benjamin Bädorf | 52cbb1f878 | 4 years ago |
Benjamin Bädorf | 691f55b6b2 | 4 years ago |
Benjamin Bädorf | 9baacafbc6 | 4 years ago |
Benjamin Bädorf | ee9cc75818 | 4 years ago |
Benjamin Bädorf | 4e848c9f9e | 4 years ago |
Benjamin Bädorf | 802447e9ba | 4 years ago |
Benjamin Bädorf | 3155074233 | 4 years ago |
Wieland Lindenthal | 9a6b77eb69 | 4 years ago |
Wieland Lindenthal | 7cf751d7ab | 4 years ago |
Wieland Lindenthal | 52093838e4 | 4 years ago |
@ -0,0 +1,69 @@ |
||||
class PlaceholderUserFilterCell < RailsCell |
||||
include UsersHelper |
||||
include ActionView::Helpers::FormOptionsHelper |
||||
|
||||
options :groups, :roles, :clear_url, :project |
||||
|
||||
class << self |
||||
def filter(params) |
||||
q = base_query.new |
||||
|
||||
filter_project q, params[:project_id] |
||||
filter_name q, params[:name] |
||||
filter_group q, params[:group_id] |
||||
filter_role q, params[:role_id] |
||||
|
||||
q.results |
||||
end |
||||
|
||||
def filtered?(params) |
||||
%i(name group_id role_id).any? { |name| params[name].present? } |
||||
end |
||||
|
||||
def filter_name(query, name) |
||||
if name.present? |
||||
query.where(:any_name_attribute, '~', name) |
||||
end |
||||
end |
||||
|
||||
def filter_group(query, group_id) |
||||
if group_id.present? |
||||
query.where(:group, '=', group_id) |
||||
end |
||||
end |
||||
|
||||
def filter_role(query, role_id) |
||||
if role_id.present? |
||||
query.where(:role_id, '=', role_id) |
||||
end |
||||
end |
||||
|
||||
def filter_project(query, project_id) |
||||
if project_id.present? |
||||
query.where(:project_id, '=', project_id) |
||||
end |
||||
end |
||||
|
||||
def base_query |
||||
Queries::PlaceholderUsers::PlaceholderUserQuery |
||||
end |
||||
end |
||||
|
||||
# INSTANCE METHODS: |
||||
|
||||
def filter_path |
||||
placeholder_users_path |
||||
end |
||||
|
||||
def initially_visible? |
||||
true |
||||
end |
||||
|
||||
def has_close_icon? |
||||
false |
||||
end |
||||
|
||||
def params |
||||
model |
||||
end |
||||
end |
@ -0,0 +1,11 @@ |
||||
module PlaceholderUsers |
||||
class PlaceholderUserFilterCell < ::PlaceholderUserFilterCell |
||||
def filter_role(query, role_id) |
||||
super.uniq |
||||
end |
||||
|
||||
def clear_url |
||||
placeholder_users_path |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,28 @@ |
||||
module PlaceholderUsers |
||||
class RowCell < ::RowCell |
||||
include AvatarHelper |
||||
include UsersHelper |
||||
|
||||
def placeholder_user |
||||
model |
||||
end |
||||
|
||||
def lastname |
||||
link_to h(placeholder_user.name), edit_placeholder_user_path(placeholder_user) |
||||
end |
||||
|
||||
def button_links |
||||
[delete_link].compact |
||||
end |
||||
|
||||
def delete_link |
||||
return nil unless Users::DeleteService.deletion_allowed? placeholder_user, User.current |
||||
|
||||
link_to '', |
||||
placeholder_user_path(placeholder_user), |
||||
data: { confirm: 'Are you sure?' }, |
||||
class: 'icon icon-delete', |
||||
method: :delete |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,28 @@ |
||||
module PlaceholderUsers |
||||
class TableCell < ::TableCell |
||||
options :current_user # adds this option to those of the base class |
||||
columns :lastname, :created_at |
||||
|
||||
def initial_sort |
||||
[:id, :asc] |
||||
end |
||||
|
||||
def headers |
||||
columns.map do |name| |
||||
[name.to_s, header_options(name)] |
||||
end |
||||
end |
||||
|
||||
def header_options(name) |
||||
options = { caption: name == :lastname ? User.human_attribute_name(:name) : User.human_attribute_name(name) } |
||||
|
||||
options[:default_order] = 'desc' if desc_by_default.include? name |
||||
|
||||
options |
||||
end |
||||
|
||||
def desc_by_default |
||||
[:created_at] |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,85 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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 docs/COPYRIGHT.rdoc for more details. |
||||
|
||||
++#%> |
||||
|
||||
<%= form_tag(filter_path, method: :get) do %> |
||||
<% collapsed_class = initially_visible? ? '' : 'collapsed' %> |
||||
<fieldset class="simple-filters--container <%= collapsed_class %>"> |
||||
<legend><%= t(:label_filter_plural) %></legend> |
||||
<% if has_close_icon? %> |
||||
<a title="<%= t('js.close_form_title') %>" |
||||
class="toggle-member-filter-link simple-filters--close icon-context icon-close"> |
||||
</a> |
||||
<% end %> |
||||
<ul class="simple-filters--filters"> |
||||
<% if groups.present? %> |
||||
<li class="simple-filters--filter"> |
||||
<label class='simple-filters--filter-name' for='group_id'><%= Group.model_name.human %>:</label> |
||||
<%= collection_select :group, |
||||
:id, |
||||
groups, |
||||
:id, |
||||
:name, |
||||
{ include_blank: true, |
||||
selected: params[:group_id].to_i }, |
||||
{ name: "group_id", |
||||
class: 'simple-filters--filter-value' } %> |
||||
</li> |
||||
<% end %> |
||||
<% if roles.present? %> |
||||
<li class="simple-filters--filter"> |
||||
<label class='simple-filters--filter-name' for='role_id'><%= Role.model_name.human %>:</label> |
||||
<%= |
||||
collection_select( |
||||
:role, |
||||
:id, |
||||
roles, |
||||
:id, |
||||
:name, |
||||
{ |
||||
include_blank: true, |
||||
selected: params[:role_id].to_i |
||||
}, |
||||
{ |
||||
name: "role_id", |
||||
class: 'simple-filters--filter-value' |
||||
}) |
||||
%> |
||||
</li> |
||||
<% end %> |
||||
<li class="simple-filters--filter"> |
||||
<label class='simple-filters--filter-name' for='name'><%= User.human_attribute_name :name %>:</label> |
||||
<%= text_field_tag 'name', params[:name], class: 'simple-filters--filter-value' %> |
||||
</li> |
||||
<li class="simple-filters--controls"> |
||||
<%= submit_tag t(:button_apply), class: 'button -highlight -small', name: nil %> |
||||
<%= link_to t(:button_clear), clear_url, class: 'button -small -with-icon icon-undo' %> |
||||
</li> |
||||
</ul> |
||||
</fieldset> |
||||
<% end %> |
@ -0,0 +1,92 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2020 the OpenProject GmbH |
||||
# |
||||
# 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. |
||||
#++ |
||||
|
||||
class PlaceholderUsers::MembershipsController < ApplicationController |
||||
layout 'admin' |
||||
|
||||
before_action :require_admin |
||||
before_action :find_placeholder_user |
||||
|
||||
def update |
||||
update_or_create(request.patch?, :notice_successful_update) |
||||
end |
||||
|
||||
def create |
||||
update_or_create(request.post?, :notice_successful_create) |
||||
end |
||||
|
||||
def destroy |
||||
@membership = @placeholder_user.memberships.find(params[:id]) |
||||
tab = redirected_to_tab(@membership) |
||||
|
||||
if @membership.deletable? && request.delete? |
||||
@membership.destroy |
||||
@membership = nil |
||||
|
||||
flash[:notice] = I18n.t(:notice_successful_delete) |
||||
end |
||||
|
||||
redirect_to controller: '/placeholder_users', action: 'edit', id: @user, tab: tab |
||||
end |
||||
|
||||
private |
||||
|
||||
def update_or_create(save_record, message) |
||||
@membership = params[:id].present? ? Member.find(params[:id]) : Member.new(principal: @placeholder_user, project: nil) |
||||
|
||||
result = ::Members::EditMembershipService |
||||
.new(@membership, save: save_record, current_user: current_user) |
||||
.call(attributes: permitted_params.membership) |
||||
|
||||
if result.success? |
||||
flash[:notice] = I18n.t(message) |
||||
else |
||||
flash[:error] = result.errors.full_messages.join("\n") |
||||
end |
||||
|
||||
redirect_to controller: '/placeholder_users', |
||||
action: 'edit', |
||||
id: @placeholder_user, |
||||
tab: redirected_to_tab(@membership) |
||||
end |
||||
|
||||
def find_placeholder_user |
||||
@placeholder_user = PlaceholderUser.find(params[:placeholder_user_id]) |
||||
rescue ActiveRecord::RecordNotFound |
||||
render_404 |
||||
end |
||||
|
||||
def redirected_to_tab(membership) |
||||
if membership.project |
||||
'memberships' |
||||
else |
||||
'global_roles' |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,160 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2020 the OpenProject GmbH |
||||
# |
||||
# 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. |
||||
#++ |
||||
|
||||
class PlaceholderUsersController < ApplicationController |
||||
layout 'admin' |
||||
|
||||
helper_method :gon |
||||
|
||||
before_action :require_admin, except: [:show, :deletion_info, :destroy] |
||||
before_action :find_placeholder_user, only: [:show, |
||||
:edit, |
||||
:update, |
||||
:destroy, |
||||
:resend_invitation] |
||||
before_action :check_if_deletion_allowed, only: [:destroy] |
||||
|
||||
def index |
||||
@groups = Group.all.sort |
||||
@placeholder_users = PlaceholderUsers::PlaceholderUserFilterCell.filter params |
||||
|
||||
respond_to do |format| |
||||
format.html do |
||||
render layout: !request.xhr? |
||||
end |
||||
end |
||||
end |
||||
|
||||
def show |
||||
# show projects based on current user visibility |
||||
@memberships = @user.memberships |
||||
.visible(current_user) |
||||
|
||||
events = Activities::Fetcher.new(User.current, author: @user).events(nil, nil, limit: 10) |
||||
@events_by_day = events.group_by { |e| e.event_datetime.to_date } |
||||
|
||||
if !User.current.admin? && |
||||
(!(@user.active? || |
||||
@user.registered?) || |
||||
(@user != User.current && @memberships.empty? && events.empty?)) |
||||
render_404 |
||||
else |
||||
respond_to do |format| |
||||
format.html { render layout: 'no_menu' } |
||||
end |
||||
end |
||||
end |
||||
|
||||
def new |
||||
@placeholder_user = PlaceholderUser.new |
||||
end |
||||
|
||||
def create |
||||
@placeholder_user = PlaceholderUser.new |
||||
@placeholder_user.attributes = permitted_params.placeholder_user |
||||
|
||||
if @placeholder_user.save |
||||
respond_to do |format| |
||||
format.html do |
||||
flash[:notice] = I18n.t(:notice_successful_create) |
||||
redirect_to(params[:continue] ? new_placeholder_user_path : edit_placeholder_user_path(@placeholder_user)) |
||||
end |
||||
end |
||||
else |
||||
respond_to do |format| |
||||
format.html do |
||||
render action: :new |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
def edit |
||||
@membership ||= Member.new |
||||
end |
||||
|
||||
def update |
||||
@placeholder_user.attributes = permitted_params.placeholder_user |
||||
|
||||
if @placeholder_user.save |
||||
respond_to do |format| |
||||
format.html do |
||||
flash[:notice] = I18n.t(:notice_successful_update) |
||||
redirect_back(fallback_location: edit_placeholder_user_path(@placeholder_user)) |
||||
end |
||||
end |
||||
else |
||||
@membership ||= Member.new |
||||
|
||||
respond_to do |format| |
||||
format.html do |
||||
render action: :edit |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
def destroy |
||||
Users::DeleteService.new(@placeholder_user, User.current).call |
||||
|
||||
flash[:notice] = I18n.t('account.deleted') |
||||
|
||||
respond_to do |format| |
||||
format.html do |
||||
redirect_to placeholder_users_path |
||||
end |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def find_placeholder_user |
||||
@placeholder_user = PlaceholderUser.find(params[:id]) |
||||
rescue ActiveRecord::RecordNotFound |
||||
render_404 |
||||
end |
||||
|
||||
def check_if_deletion_allowed |
||||
render_404 unless Users::DeleteService.deletion_allowed? @placeholder_user, User.current |
||||
end |
||||
|
||||
protected |
||||
|
||||
def default_breadcrumb |
||||
if action_name == 'index' |
||||
t('label_placeholder_user_plural') |
||||
else |
||||
ActionController::Base.helpers.link_to(t('label_placeholder_user_plural'), placeholder_users_path) |
||||
end |
||||
end |
||||
|
||||
def show_local_breadcrumb |
||||
current_user.admin? |
||||
end |
||||
end |
@ -0,0 +1,46 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2020 the OpenProject GmbH |
||||
# |
||||
# 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. |
||||
#++ |
||||
|
||||
class PlaceholderUser < Principal |
||||
validates_presence_of(:lastname) |
||||
validates_uniqueness_of(:lastname) |
||||
|
||||
acts_as_customizable |
||||
|
||||
has_and_belongs_to_many :groups, |
||||
join_table: "#{table_name_prefix}group_users#{table_name_suffix}", |
||||
foreign_key: 'user_id', |
||||
after_add: ->(user, group) { group.user_added(user) }, |
||||
after_remove: ->(user, group) { group.user_removed(user) } |
||||
|
||||
def to_s |
||||
lastname |
||||
end |
||||
end |
@ -0,0 +1,39 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2020 the OpenProject GmbH |
||||
# |
||||
# 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::PlaceholderUsers |
||||
Queries::Register.filter Queries::PlaceholderUsers::PlaceholderUserQuery, Queries::Users::Filters::NameFilter |
||||
Queries::Register.filter Queries::PlaceholderUsers::PlaceholderUserQuery, Queries::Users::Filters::AnyNameAttributeFilter |
||||
Queries::Register.filter Queries::PlaceholderUsers::PlaceholderUserQuery, Queries::Users::Filters::GroupFilter |
||||
|
||||
Queries::Register.order Queries::PlaceholderUsers::PlaceholderUserQuery, Queries::Users::Orders::DefaultOrder |
||||
Queries::Register.order Queries::PlaceholderUsers::PlaceholderUserQuery, Queries::Users::Orders::NameOrder |
||||
Queries::Register.order Queries::PlaceholderUsers::PlaceholderUserQuery, Queries::Users::Orders::GroupOrder |
||||
end |
@ -0,0 +1,37 @@ |
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2020 the OpenProject GmbH |
||||
# |
||||
# 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. |
||||
#++ |
||||
|
||||
class Queries::PlaceholderUsers::PlaceholderUserQuery < Queries::BaseQuery |
||||
def self.model |
||||
PlaceholderUser |
||||
end |
||||
|
||||
def default_scope |
||||
PlaceholderUser.not_builtin_but_with_placeholder_users |
||||
end |
||||
end |
@ -0,0 +1,45 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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. |
||||
|
||||
++#%> |
||||
|
||||
<%= error_messages_for 'placeholder_user' %> |
||||
|
||||
|
||||
<!--[form:user]--> |
||||
<section class="form--section"> |
||||
<div class="form--field -required"><%= f.text_field :lastname, label: t('label_name'), required: true, container_class: '-middle' %></div> |
||||
|
||||
<h3 class="form--section-title"><%= t(:label_custom_field_plural) %></h3> |
||||
<%= render partial: 'customizable/field', |
||||
collection: @placeholder_user.custom_field_values, |
||||
as: :value, |
||||
locals: { form: f } %> |
||||
|
||||
<%= call_hook(:view_placeholder_users_form, placeholder_user: @placeholder_user, form: f) %> |
||||
</section> |
||||
<!--[eoform:user]--> |
@ -0,0 +1,40 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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. |
||||
|
||||
++#%> |
||||
|
||||
<%= labelled_tabular_form_for @user, |
||||
url: { controller: '/placeholder_users', |
||||
action: "update", |
||||
tab: nil }, |
||||
html: { method: :put, |
||||
autocomplete: 'off' }, |
||||
as: :placeholder_user do |f| %> |
||||
<%= render partial: 'form', locals: { f: f } %> |
||||
|
||||
<%= styled_button_tag t(:button_save), class: '-highlight -with-icon icon-checkmark' %> |
||||
<% end %> |
@ -0,0 +1,49 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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. |
||||
|
||||
++#%> |
||||
<% groups = @placeholder_user.groups.pluck(:id, :lastname) %> |
||||
|
||||
<%= labelled_tabular_form_for(:placeholder_user, url: { action: 'update' }, html: { method: :put }) do %> |
||||
<section class="form--section"> |
||||
<% if groups.empty? %> |
||||
<%= no_results_box action_url: groups_path, |
||||
display_action: true, |
||||
custom_title: t('placeholder_users.groups.no_results_title_text'), |
||||
custom_action_text: t(:label_manage_groups) |
||||
%> |
||||
<% else %> |
||||
<p><%= t('placeholder_users.groups.member_in_these_groups') %></p> |
||||
<% end %> |
||||
|
||||
<% groups.each do |id, name| %> |
||||
<ul> |
||||
<li><%= link_to name, edit_group_path(id) %></li> |
||||
</ul> |
||||
<% end %> |
||||
</section> |
||||
<% end %> |
@ -0,0 +1,148 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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. |
||||
|
||||
++#%> |
||||
<% roles = Role.givable %> |
||||
<% projects = Project.active.order(Arel.sql('lft')) %> |
||||
|
||||
<div class="grid-block"> |
||||
<div class="grid-content"> |
||||
<% if @placeholder_user.memberships.any? %> |
||||
<div class="generic-table--container"> |
||||
<div class="generic-table--results-container"> |
||||
<table class="generic-table memberships"> |
||||
<colgroup> |
||||
<col highlight-col> |
||||
<col highlight-col> |
||||
<%= call_hook(:view_placeholder_users_memberships_table_colgroup, placeholder_user: @placeholder_user )%> |
||||
<col> |
||||
</colgroup> |
||||
<thead> |
||||
<tr> |
||||
<th> |
||||
<div class="generic-table--sort-header-outer"> |
||||
<div class="generic-table--sort-header"> |
||||
<span> |
||||
<%= Project.model_name.human %> |
||||
</span> |
||||
</div> |
||||
</div> |
||||
</th> |
||||
<th> |
||||
<div class="generic-table--sort-header-outer"> |
||||
<div class="generic-table--sort-header"> |
||||
<span> |
||||
<%= t(:label_role_plural) %> |
||||
</span> |
||||
</div> |
||||
</div> |
||||
</th> |
||||
<%= call_hook(:view_users_memberships_table_header, placeholder_user: @placeholder_user )%> |
||||
<th><div class="generic-table--empty-header"></div></th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% @placeholder_user.memberships.where.not(project: nil).each do |membership| %> |
||||
<% next if membership.new_record? %> |
||||
<tr id="member-<%= membership.id %>" class="member"> |
||||
<td class="project"> |
||||
<%= link_to_project membership.project %> |
||||
</td> |
||||
<td class="roles"> |
||||
<span id="member-<%= membership.id %>-roles" |
||||
class="member-<%= membership.id %>--edit-toggle-item"> |
||||
<%=h membership.roles.sort.collect(&:to_s).join(', ') %> |
||||
</span> |
||||
<%= labelled_tabular_form_for(:membership, |
||||
url: placeholder_user_membership_path(placeholder_user_id: @placeholder_user, id: membership), |
||||
html: { id: "member-#{membership.id}-roles-form", |
||||
class: "member-#{membership.id}--edit-toggle-item", |
||||
style: 'display:none;'}, |
||||
method: :patch) do |f| %> |
||||
<div> |
||||
<% roles.each do |role| %> |
||||
<label class="form--label-with-check-box"> |
||||
<%= f.collection_check_box :role_ids, |
||||
role.id, |
||||
membership.roles.include?(role), |
||||
role.name, |
||||
disabled: membership.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?}, |
||||
no_label: true, |
||||
id: nil |
||||
%> |
||||
<%= role %> |
||||
</label> |
||||
<% end %> |
||||
</div> |
||||
<p><%= submit_tag t(:button_change), class: 'user-memberships--edit-submit-button button -highlight -small' %> |
||||
<%= link_to_function t(:button_cancel), |
||||
"jQuery('.member-#{membership.id}--edit-toggle-item').toggle();", |
||||
class: 'button -small' %></p> |
||||
<% end %> |
||||
</td> |
||||
<%= call_hook(:view_placheholder_users_memberships_table_row, placeholder_user: @placeholder_user, membership: membership, roles: roles, projects: projects )%> |
||||
<td class="buttons"> |
||||
<%= link_to_function icon_wrapper('icon icon-edit', t(:button_edit)), |
||||
"jQuery('.member-#{membership.id}--edit-toggle-item').toggle();", |
||||
class: "member-#{membership.id}--edit-toggle-item user-memberships--edit-button", |
||||
title: t(:button_edit) %> |
||||
<%= link_to(icon_wrapper('icon icon-remove', t(:button_remove)), |
||||
placeholder_user_membership_path(placeholder_user_id: @placeholder_user, id: membership), |
||||
method: :delete, |
||||
title: t(:button_remove)) if membership.deletable? %> |
||||
</td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
|
||||
</div> |
||||
</div> |
||||
<% else %> |
||||
<%= no_results_box %> |
||||
<% end %> |
||||
</div> |
||||
<div class="grid-content"> |
||||
<% if projects.any? %> |
||||
<%= labelled_tabular_form_for(:membership, |
||||
url: placeholder_user_memberships_path(placeholder_user_id: @placeholder_user), |
||||
html: {id: "new_project_membership"}) do %> |
||||
<fieldset class="form--fieldset"> |
||||
<legend class="form--fieldset-legend"><%=t(:label_project_new)%></legend> |
||||
<%= styled_select_tag 'membership[project_id]', options_for_membership_project_select(@placeholder_user, projects) %> |
||||
<div class="form--field -vertical"> |
||||
<%= styled_label_tag nil, "#{t(:label_role_plural)}:" %> |
||||
<div class="form--field-container -vertical"> |
||||
<%= labeled_check_box_tags 'membership[role_ids][]', roles %> |
||||
</div> |
||||
</div> |
||||
<div><%= styled_button_tag t(:button_add), class: '-highlight -with-icon icon-checkmark' %></div> |
||||
</fieldset> |
||||
<% end %> |
||||
<% end %> |
||||
</div> |
||||
</div> |
@ -0,0 +1,36 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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. |
||||
|
||||
++#%> |
||||
|
||||
|
||||
<% html_title(t(:label_administration), "#{t(:label_edit)} #{PlaceholderUser.model_name.human} #{h(@placeholder_user.name)}") -%> |
||||
|
||||
<% local_assigns[:additional_breadcrumb] = @placeholder_user.name %> |
||||
<%= render partial: 'users/toolbar', locals: { new_user: false, :@user => @placeholder_user } %> |
||||
|
||||
<%= render_extensible_tabs :placeholder_user, placeholder_user: @placeholder_user %> |
@ -0,0 +1,46 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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. |
||||
|
||||
++#%> |
||||
<% html_title t(:label_administration), t(:label_placeholder_user_plural) -%> |
||||
|
||||
<%= toolbar title: t(:label_placeholder_user_plural), title_class: 'no-padding-bottom' do %> |
||||
<li class="toolbar-item"> |
||||
<%= link_to new_placeholder_user_path, |
||||
{ class: 'button -alt-highlight', |
||||
aria: { label: t(:label_placeholder_user_new) }, |
||||
title: t(:label_placeholder_user_new) } do %> |
||||
<%= op_icon('button--icon icon-add') %> |
||||
<span class="button--text"><%= t('activerecord.models.placeholder_user') %></span> |
||||
<% end %> |
||||
</li> |
||||
<%= call_hook(:user_admin_action_menu) %> |
||||
<% end %> |
||||
|
||||
<%= cell PlaceholderUsers::PlaceholderUserFilterCell, params, groups: @groups %> |
||||
|
||||
<%= cell PlaceholderUsers::TableCell, @placeholder_users, project: @project, current_user: current_user %> |
@ -0,0 +1,43 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2020 the OpenProject GmbH |
||||
|
||||
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. |
||||
|
||||
++#%> |
||||
|
||||
<% html_title t(:label_administration), t("label_placeholder_user_new") %> |
||||
<% local_assigns[:additional_breadcrumb] = t(:label_placeholder_user_new) %> |
||||
<%= render partial: 'users/toolbar', locals: { new_user: true, :@user => @placeholder_user } %> |
||||
<%= labelled_tabular_form_for @placeholder_user, |
||||
url: { action: "create" }, |
||||
html: { class: nil, autocomplete: 'off' }, |
||||
as: :placeholder_user do |f| %> |
||||
<%= render partial: 'form', locals: { f: f, placeholder_user: @placeholder_user } %> |
||||
|
||||
<p> |
||||
<%= styled_button_tag t(:button_create), class: '-highlight -with-icon icon-checkmark' %> |
||||
<%= styled_button_tag t(:button_create_and_continue), name: 'continue', class: '-highlight -with-icon icon-checkmark' %> |
||||
</p> |
||||
<% end %> |
@ -0,0 +1,22 @@ |
||||
<!-- This is an example structure --> |
||||
<div class="op-option-list"> |
||||
<label |
||||
*ngFor="let option of options" |
||||
class="op-option-list--item" |
||||
[ngClass]="option.value === selected ? 'op-option-list--item_selected' : ''" |
||||
> |
||||
<input |
||||
type="radio" |
||||
[attr.name]="name" |
||||
[value]="option.value" |
||||
[(ngModel)]="selectedInternal" |
||||
/> |
||||
<div> |
||||
<p class="op-option-list--title">{{ option.title }}</p> |
||||
<p |
||||
*ngIf="option.description" |
||||
class="op-option-list--description" |
||||
>{{ option.description }}</p> |
||||
</div> |
||||
</label> |
||||
</div> |
@ -0,0 +1,17 @@ |
||||
.op-option-list |
||||
display: flex |
||||
flex-direction: column |
||||
font-size: 1rem |
||||
|
||||
&--item |
||||
padding: 1rem 0.75rem |
||||
display: flex |
||||
border: 1px solid #cbd5e0 |
||||
background: #f7fafc |
||||
|
||||
&:not(:last-child) |
||||
margin-bottom: 0.5rem |
||||
|
||||
&_selected |
||||
border: 1px solid #90cdf4 |
||||
background: #ebf8ff |
@ -0,0 +1,48 @@ |
||||
import { |
||||
Component, |
||||
Input, |
||||
Output, |
||||
EventEmitter, |
||||
} from "@angular/core"; |
||||
import { ControlValueAccessor } from "@angular/forms"; |
||||
|
||||
export interface IOpOptionListOption<T> { |
||||
value:T; |
||||
title:string; |
||||
description?:string; |
||||
} |
||||
|
||||
export type IOpOptionListValue<T> = T|null; |
||||
|
||||
@Component({ |
||||
// Style is imported globally
|
||||
templateUrl: './option-list.component.html', |
||||
selector: 'op-option-list', |
||||
}) |
||||
export class OpOptionListComponent<T> implements ControlValueAccessor { |
||||
@Input() options:IOpOptionListOption<T>[] = []; |
||||
@Input() name:string = `op-option-list-${+(new Date())}`; |
||||
@Output() selectedChange = new EventEmitter<T>(); |
||||
|
||||
private _selected:IOpOptionListValue<T> = null; |
||||
get selected() { |
||||
return this._selected; |
||||
} |
||||
set selected(data:IOpOptionListValue<T>) { |
||||
this.onChange(data); |
||||
} |
||||
onChange = (_:IOpOptionListValue<T>) => {}; |
||||
onTouched = (_:IOpOptionListValue<T>) => {}; |
||||
|
||||
writeValue(value:IOpOptionListValue<T>) { |
||||
this._selected = value; |
||||
} |
||||
|
||||
registerOnChange(fn:any) { |
||||
this.onChange = fn; |
||||
} |
||||
|
||||
registerOnTouched(fn:any) { |
||||
this.onTouched = fn; |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
import {Component, ElementRef, OnInit} from '@angular/core'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-group', |
||||
templateUrl: './group.component.html', |
||||
styleUrls: ['./group.component.sass'], |
||||
}) |
||||
export class InviteGroupComponent implements OnInit { |
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
ngOnInit() { |
||||
} |
||||
} |
@ -0,0 +1,34 @@ |
||||
import {NgModule} from "@angular/core"; |
||||
import {ReactiveFormsModule} from "@angular/forms"; |
||||
import {InviteUserModalComponent} from "./invite-user.component"; |
||||
import {InviteProjectSelectionComponent} from "./project-selection.component"; |
||||
import {InviteUserComponent} from "./user.component"; |
||||
import {InviteGroupComponent} from "./group.component"; |
||||
import {InvitePlaceholderComponent} from "./placeholder.component"; |
||||
import {InviteRoleComponent} from "./role.component"; |
||||
import {InviteMessageComponent} from "./message.component"; |
||||
import {InviteSuccessComponent} from "./success.component"; |
||||
import {InviteSummaryComponent} from "./summary.component"; |
||||
import {NgSelectModule} from "@ng-select/ng-select"; |
||||
import {OpenprojectCommonModule} from "core-app/modules/common/openproject-common.module"; |
||||
|
||||
@NgModule({ |
||||
imports: [ |
||||
OpenprojectCommonModule, |
||||
NgSelectModule, |
||||
ReactiveFormsModule, |
||||
], |
||||
exports: [], |
||||
declarations: [ |
||||
InviteUserModalComponent, |
||||
InviteProjectSelectionComponent, |
||||
InviteUserComponent, |
||||
InviteGroupComponent, |
||||
InvitePlaceholderComponent, |
||||
InviteRoleComponent, |
||||
InviteMessageComponent, |
||||
InviteSuccessComponent, |
||||
InviteSummaryComponent, |
||||
] |
||||
}) |
||||
export class OpenprojectInviteUserModalModule { } |
@ -0,0 +1,17 @@ |
||||
<div class="op-modal--portal"> |
||||
<op-ium-project-selection |
||||
*ngIf="step === 'project-selection'" |
||||
class="op-modal--modal-container" |
||||
[project]="project" |
||||
[type]="type" |
||||
(save)="onProjectSelectionSave" |
||||
(close)="close" |
||||
></op-ium-project-selection> |
||||
<op-ium-user |
||||
*ngIf="step === 'user' && type === 'user'" |
||||
class="op-modal--modal-container" |
||||
[user]="principal" |
||||
(save)="onUserSave" |
||||
(back)="back" |
||||
></op-ium-user> |
||||
</div> |
@ -0,0 +1,60 @@ |
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inject, OnInit} from '@angular/core'; |
||||
import {OpModalLocalsMap} from 'core-components/op-modals/op-modal.types'; |
||||
import {OpModalComponent} from 'core-components/op-modals/op-modal.component'; |
||||
import {OpModalLocalsToken} from "core-components/op-modals/op-modal.service"; |
||||
import * as URI from 'urijs'; |
||||
import {HttpClient} from '@angular/common/http'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
import {Observable} from 'rxjs'; |
||||
|
||||
@Component({ |
||||
templateUrl: './invite-user.component.html', |
||||
styleUrls: ['./invite-user.component.sass'], |
||||
changeDetection: ChangeDetectionStrategy.OnPush, |
||||
}) |
||||
export class InviteUserModalComponent extends OpModalComponent implements OnInit { |
||||
private steps = [ |
||||
'project-selection', |
||||
'username', |
||||
'role', |
||||
'message', |
||||
'summary', |
||||
'success', |
||||
]; |
||||
private stepIndex = 0; |
||||
|
||||
/* Close on escape? */ |
||||
public closeOnEscape = true; |
||||
|
||||
/* Close on outside click */ |
||||
public closeOnOutsideClick = true; |
||||
|
||||
public type:string|null = null; |
||||
public project = null; |
||||
public principal = null; |
||||
public role = null; |
||||
public message = ''; |
||||
|
||||
public get step() { |
||||
return this.steps[this.stepIndex]; |
||||
} |
||||
|
||||
constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap, |
||||
readonly cdRef:ChangeDetectorRef, |
||||
readonly elementRef:ElementRef, |
||||
readonly httpClient:HttpClient) { |
||||
super(locals, cdRef, elementRef); |
||||
} |
||||
|
||||
ngOnInit() { |
||||
super.ngOnInit(); |
||||
} |
||||
|
||||
onProjectSelectionSave() { |
||||
console.log('select project'); |
||||
} |
||||
|
||||
back() { |
||||
this.stepIndex = Math.max(this.stepIndex - 1, 0); |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
import {Component, ElementRef, OnInit} from '@angular/core'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-message', |
||||
templateUrl: './message.component.html', |
||||
styleUrls: ['./message.component.sass'], |
||||
}) |
||||
export class InviteMessageComponent implements OnInit { |
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
ngOnInit() { |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
import {Component, ElementRef, OnInit} from '@angular/core'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-placeholder', |
||||
templateUrl: './placeholder.component.html', |
||||
styleUrls: ['./placeholder.component.sass'], |
||||
}) |
||||
export class InvitePlaceholderComponent implements OnInit { |
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
ngOnInit() { |
||||
} |
||||
} |
@ -0,0 +1,33 @@ |
||||
<form |
||||
[formGroup]="projectAndTypeForm" |
||||
ngSubmit="onSubmit" |
||||
> |
||||
<div class="op-modal--modal-container"> |
||||
<div class="op-modal--modal-header"> |
||||
<button |
||||
class="op-modal--modal-close-button" |
||||
type="button" |
||||
(click)="close" |
||||
[attr.aria-label]="text.closePopup" |
||||
> |
||||
<span class="icon-close"></span> |
||||
</button> |
||||
<h3 class="icon-context icon-attention" [textContent]="text.title"></h3> |
||||
</div> |
||||
|
||||
<div class="op-modal--modal-body"> |
||||
<op-option-list |
||||
[options]="typeOptions" |
||||
formControlName="type" |
||||
></op-option-list> |
||||
</div> |
||||
|
||||
<div class="op-modal--modal-footer"> |
||||
<button |
||||
type="button" |
||||
(click)="back" |
||||
>Back</button> |
||||
<button>Next</button> |
||||
</div> |
||||
</div> |
||||
</form> |
@ -0,0 +1,75 @@ |
||||
import { |
||||
Component, |
||||
Input, |
||||
EventEmitter, |
||||
Output, |
||||
ElementRef, |
||||
} from '@angular/core'; |
||||
import {
|
||||
FormControl, |
||||
FormGroup, |
||||
Validators, |
||||
} from '@angular/forms'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-project-selection', |
||||
templateUrl: './project-selection.component.html', |
||||
styleUrls: ['./project-selection.component.sass'], |
||||
}) |
||||
export class InviteProjectSelectionComponent { |
||||
public text = { |
||||
title: this.I18n.t('js.invite_user_modal.title'), |
||||
closePopup: this.I18n.t('js.close_popup_title'), |
||||
exportPreparing: this.I18n.t('js.label_export_preparing') |
||||
}; |
||||
|
||||
public typeOptions = [ |
||||
{ |
||||
value: 'user', |
||||
title: 'User', |
||||
description: 'Permissions based on the assigned role in the selected project' |
||||
}, |
||||
{ |
||||
value: 'group', |
||||
title: 'Group', |
||||
description: 'Permissions based on the assigned role in the selected project' |
||||
}, |
||||
{ |
||||
value: 'placeholder', |
||||
title: 'Placeholder', |
||||
description: 'Has no access to the proejct and no emails are sent out' |
||||
}, |
||||
]; |
||||
|
||||
@Input('type') type:string; |
||||
@Input('project') project:null; |
||||
|
||||
projectAndTypeForm = new FormGroup({ |
||||
type: new FormControl('', [ Validators.required ]), |
||||
project: new FormControl(null, [ Validators.required ]), |
||||
}); |
||||
|
||||
@Output('close') closeModal = new EventEmitter<void>(); |
||||
@Output() save = new EventEmitter<{project:any, type:string}>(); |
||||
|
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
close() { |
||||
this.closeModal.emit(); |
||||
} |
||||
|
||||
onSubmit($e:Event) { |
||||
console.log(this.projectAndTypeForm); |
||||
debugger; |
||||
|
||||
this.save.emit({ |
||||
project: this.projectAndTypeForm.get('project'), |
||||
type: this.projectAndTypeForm.get('type'), |
||||
}); |
||||
} |
||||
|
||||
back() { |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
import {Component, ElementRef, OnInit} from '@angular/core'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-role', |
||||
templateUrl: './role.component.html', |
||||
styleUrls: ['./role.component.sass'], |
||||
}) |
||||
export class InviteRoleComponent implements OnInit { |
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
ngOnInit() { |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
import {Component, ElementRef, OnInit} from '@angular/core'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-success', |
||||
templateUrl: './success.component.html', |
||||
styleUrls: ['./success.component.sass'], |
||||
}) |
||||
export class InviteSuccessComponent implements OnInit { |
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
ngOnInit() { |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
import {Component, ElementRef, OnInit} from '@angular/core'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-summary', |
||||
templateUrl: './summary.component.html', |
||||
styleUrls: ['./summary.component.sass'], |
||||
}) |
||||
export class InviteSummaryComponent implements OnInit { |
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
ngOnInit() { |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
import {Component, ElementRef, OnInit} from '@angular/core'; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
|
||||
@Component({ |
||||
selector: 'op-ium-user', |
||||
templateUrl: './user.component.html', |
||||
styleUrls: ['./user.component.sass'], |
||||
}) |
||||
export class InviteUserComponent implements OnInit { |
||||
constructor(readonly I18n:I18nService, |
||||
readonly elementRef:ElementRef) {} |
||||
|
||||
ngOnInit() { |
||||
} |
||||
} |
@ -0,0 +1,144 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2020 the OpenProject GmbH |
||||
# |
||||
# 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 API |
||||
module V3 |
||||
module PlaceholderUsers |
||||
class PlaceholderUserRepresenter < ::API::V3::Principals::PrincipalRepresenter |
||||
include AvatarHelper |
||||
|
||||
cached_representer dependencies: ->(*) { avatar_cache_dependencies } |
||||
|
||||
def self.create(user, current_user:) |
||||
new(user, current_user: current_user) |
||||
end |
||||
|
||||
def initialize(user, current_user:) |
||||
super(user, current_user: current_user) |
||||
end |
||||
|
||||
self_link |
||||
|
||||
link :updateImmediately, |
||||
cache_if: -> { current_user_is_admin } do |
||||
{ |
||||
href: api_v3_paths.user(represented.id), |
||||
title: "Update #{represented.login}", |
||||
method: :patch |
||||
} |
||||
end |
||||
|
||||
link :delete, |
||||
cache_if: -> { current_user_can_delete_represented? } do |
||||
{ |
||||
href: api_v3_paths.user(represented.id), |
||||
title: "Delete #{represented.login}", |
||||
method: :delete |
||||
} |
||||
end |
||||
|
||||
property :name, |
||||
exec_context: :decorator, |
||||
getter: ->(*) { represented.lastname }, |
||||
setter: ->(fragment:, represented:, **) { represented.lastname = fragment }, |
||||
render_nil: false, |
||||
cache_if: -> { current_user_is_admin_or_self } |
||||
|
||||
property :avatar, |
||||
exec_context: :decorator, |
||||
getter: ->(*) { avatar_url(represented) }, |
||||
render_nil: true |
||||
|
||||
property :identity_url, |
||||
exec_context: :decorator, |
||||
as: 'identityUrl', |
||||
getter: ->(*) { represented.identity_url }, |
||||
setter: ->(fragment:, represented:, **) { represented.identity_url = fragment }, |
||||
render_nil: true, |
||||
cache_if: -> { current_user_is_admin_or_self } |
||||
|
||||
## |
||||
# Used while parsing JSON to initialize `auth_source_id` through the given link. |
||||
def initialize_embedded_links!(data) |
||||
auth_source_id = parse_auth_source_id data, "auth_source" |
||||
|
||||
if auth_source_id |
||||
auth_source = AuthSource.find_by_unique auth_source_id |
||||
id = auth_source ? auth_source.id : 0 |
||||
|
||||
# set id to 0 (as opposed to nil) to produce an auth source not found |
||||
# error further down the line in the user's base contract |
||||
represented.auth_source_id = id |
||||
end |
||||
end |
||||
|
||||
## |
||||
# Overrides Roar::JSON::HAL::Resources#from_hash |
||||
def from_hash(hash, *) |
||||
if hash["_links"] |
||||
initialize_embedded_links! hash |
||||
end |
||||
|
||||
super |
||||
end |
||||
|
||||
def parse_auth_source_id(data, link_name) |
||||
value = data.dig("_links", link_name, "href") |
||||
|
||||
if value |
||||
::API::Utilities::ResourceLinkParser.parse_id( |
||||
value, |
||||
property: :auth_source, |
||||
expected_version: "3", |
||||
expected_namespace: "auth_sources" |
||||
) |
||||
end |
||||
end |
||||
|
||||
def _type |
||||
'PlaceholderUser' |
||||
end |
||||
|
||||
def current_user_can_delete_represented? |
||||
current_user && ::Users::DeleteService.deletion_allowed?(represented, current_user) |
||||
end |
||||
|
||||
private |
||||
|
||||
## |
||||
# Dependencies required to cache users with avatars |
||||
# Extended by plugin |
||||
def avatar_cache_dependencies |
||||
[] |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue