Implement copy form in formly (#9218)
* Implement copy form in formly * Add meta property handling to dynamic form * Remove copy projects controller, merge into projects * Fix copying of container attachments * Fix project copy path * Fix remainder of copy specpull/9224/head
parent
293b8935a2
commit
2adce94853
@ -1,85 +0,0 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2021 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. |
||||
#++ |
||||
|
||||
class CopyProjectsController < ApplicationController |
||||
before_action :find_project |
||||
before_action :authorize |
||||
|
||||
def copy |
||||
request_params = params |
||||
.permit(:send_notifications, only: []) |
||||
.to_h |
||||
.merge(target_project_params: target_project_params) |
||||
call = Projects::EnqueueCopyService |
||||
.new(user: current_user, model: @project) |
||||
.call(request_params) |
||||
|
||||
if call.success? |
||||
job = call.result |
||||
copy_started_notice |
||||
redirect_to job_status_path job.job_id |
||||
else |
||||
@copy_project = call.result |
||||
@errors = call.errors |
||||
render action: copy_action |
||||
end |
||||
end |
||||
|
||||
def copy_project |
||||
@copy_project = Projects::CopyService |
||||
.new(user: current_user, source: @project) |
||||
.call(target_project_params: target_project_params, attributes_only: true) |
||||
.result |
||||
|
||||
render action: copy_action |
||||
end |
||||
|
||||
private |
||||
|
||||
def target_project_params |
||||
params[:project] ? permitted_params.project.to_h : {} |
||||
end |
||||
|
||||
def copy_action |
||||
from = (%w(admin settings).include?(params[:coming_from]) ? params[:coming_from] : 'settings') |
||||
|
||||
"copy_from_#{from}" |
||||
end |
||||
|
||||
def origin |
||||
params[:coming_from] == 'admin' ? projects_path : settings_generic_project_path(@project.id) |
||||
end |
||||
|
||||
def copy_started_notice |
||||
flash[:notice] = I18n.t('copy_project.started', |
||||
source_project_name: @project.name, |
||||
target_project_name: permitted_params.project[:name]) |
||||
end |
||||
end |
@ -1,50 +0,0 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2021 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. |
||||
|
||||
++#%> |
||||
|
||||
<%= error_messages_for 'copy_project' %> |
||||
|
||||
<%= toolbar title: t(:label_project_new) %> |
||||
|
||||
<%= labelled_tabular_form_for @copy_project, url: { action: 'copy', coming_from: 'admin' } do |f| %> |
||||
<%= hidden_field_tag :coming_from, 'admin' %> |
||||
|
||||
<%= render partial: 'projects/form', locals: { f: f, |
||||
project: @copy_project, |
||||
errors: @errors, |
||||
is_copy: true, |
||||
render_advanced: true, |
||||
render_types: false, |
||||
render_modules: false, |
||||
render_custom_fields: false |
||||
} %> |
||||
|
||||
<%= render partial: "copy_projects/copy_settings/copy_associations", locals: { project: @project } %> |
||||
|
||||
<%= submit_tag t(:button_copy), class: 'button -highlight' %> |
||||
<% end %> |
@ -1,50 +0,0 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2021 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. |
||||
|
||||
++#%> |
||||
|
||||
<%= error_messages_for_contract @copy_project, @errors %> |
||||
<%= toolbar title: t(:label_project_new) %> |
||||
|
||||
<%= labelled_tabular_form_for @copy_project, url: { action: 'copy', coming_from: 'settings' } do |f| %> |
||||
<%= hidden_field_tag :coming_from, 'settings' %> |
||||
|
||||
<%= render partial: 'projects/form', locals: { f: f, |
||||
project: @copy_project, |
||||
errors: @errors, |
||||
is_copy: true, |
||||
render_advanced: true, |
||||
render_types: false, |
||||
render_modules: false, |
||||
render_custom_fields: false, |
||||
no_error_messages: true |
||||
} %> |
||||
|
||||
<%= render partial: "copy_projects/copy_settings/copy_associations", locals: { project: @project } %> |
||||
|
||||
<%= submit_tag t(:button_copy), class: 'button -highlight' %> |
||||
<% end %> |
@ -1,35 +0,0 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2021 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. |
||||
|
||||
++#%> |
||||
<% if count.nil? || count > 0 %> |
||||
<label class="block"> |
||||
<%= check_box_tag 'only[]', name, checked, id: "only_#{name}" %> |
||||
<% count_label = count ? " (#{count})" : "" %> |
||||
<%= "#{label}#{count_label}" %> |
||||
</label> |
||||
<% end %> |
@ -1,76 +0,0 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2021 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. |
||||
|
||||
++#%> |
||||
|
||||
<fieldset class="form--fieldset"> |
||||
<legend class="form--fieldset-legend"><%= t(:button_copy) %></legend> |
||||
|
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "overview", checked: true, label: t(:label_overview), count: nil } %> |
||||
|
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "queries", checked: true, label: t(:label_query_plural), |
||||
count: project.queries.count } %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "boards", checked: true, label: t('boards.label_boards'), |
||||
count: ::Boards::Grid.where(project: project).count } %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "forums", checked: false, label: t(:label_forum_plural), |
||||
count: project.forums.count } %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "members", checked: true, label: t(:label_member_plural), |
||||
count: project.members.count } %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "versions", checked: true, label: t(:label_version_plural), |
||||
count: project.versions.count } %> |
||||
<% if project.wiki.present? %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "wiki", checked: true, label: t(:label_wiki_page_plural), |
||||
count: project.wiki.nil? ? 0 : project.wiki.pages.count } %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "wiki_page_attachments", checked: false, label: t(:label_wiki_page_attachments), |
||||
count: project.wiki.pages.joins(:attachments).count('attachments.id') } %> |
||||
<% end %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "work_packages", checked: true, label: t(:label_work_package_plural), |
||||
count: project.work_packages.count } %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "work_package_attachments", checked: true, label: t(:label_work_package_attachments), |
||||
count: project.work_packages.joins(:attachments).count('attachments.id') } %> |
||||
<%= render partial: "copy_projects/copy_settings/block_checkbox", |
||||
locals: { name: "categories", checked: true, |
||||
label: t(:label_work_package_category_plural), |
||||
count: project.categories.count } %> |
||||
<%= hidden_field_tag 'only[]', '' %> |
||||
|
||||
<br /> |
||||
<label class="block"> |
||||
<%= check_box_tag 'send_notifications', 1, params[:send_notifications] %> |
||||
<%= t(:label_project_copy_notifications) %> |
||||
</label> |
||||
</fieldset> |
@ -1,37 +0,0 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2021 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. |
||||
|
||||
++#%> |
||||
|
||||
<% issue_custom_fields.each do |custom_field| %> |
||||
<% if @project.all_work_package_custom_fields.include?(custom_field) %> |
||||
<%= render partial: "projects/form/attributes/hidden_field", |
||||
locals: { form: form, name: :'work_package_custom_field_ids', |
||||
options: {multiple: true}, |
||||
value: custom_field.id } %> |
||||
<% end %> |
||||
<% end %> |
@ -1,39 +0,0 @@ |
||||
<%#-- copyright |
||||
OpenProject is an open source project management software. |
||||
Copyright (C) 2012-2021 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. |
||||
|
||||
++#%> |
||||
|
||||
<% unless types.empty? %> |
||||
<% types.each do |type| %> |
||||
<% if project.types.include?(type) %> |
||||
<%= render partial: "projects/form/attributes/hidden_field", |
||||
locals: { form: form, name: :'type_ids', |
||||
options: {multiple: true}, |
||||
value: type.id } %> |
||||
<% end %> |
||||
<% end %> |
||||
<% end %> |
@ -0,0 +1,41 @@ |
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) 2012-2021 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.
|
||||
//++
|
||||
|
||||
import {APIv3FormResource} from "core-app/modules/apiv3/forms/apiv3-form-resource"; |
||||
import {APIV3Service} from "core-app/modules/apiv3/api-v3.service"; |
||||
import {SimpleResource} from "core-app/modules/apiv3/paths/path-resources"; |
||||
|
||||
export class APIv3ProjectCopyPaths extends SimpleResource { |
||||
constructor(protected apiRoot:APIV3Service, |
||||
public basePath:string) { |
||||
super(basePath, 'copy'); |
||||
} |
||||
|
||||
// /api/v3/projects/:project_id/copy/form
|
||||
public readonly form = new APIv3FormResource(this.apiRoot, this.path, 'form'); |
||||
} |
@ -0,0 +1,6 @@ |
||||
<op-dynamic-form |
||||
[formUrl]="formUrl" |
||||
[fieldsSettingsPipe]="dynamicFieldsSettingsPipe" |
||||
(submitted)="onSubmitted($event)" |
||||
> |
||||
</op-dynamic-form> |
@ -0,0 +1,104 @@ |
||||
import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; |
||||
import {StateService, UIRouterGlobals} from "@uirouter/core"; |
||||
import {UntilDestroyedMixin} from "core-app/helpers/angular/until-destroyed.mixin"; |
||||
import {PathHelperService} from "core-app/modules/common/path-helper/path-helper.service"; |
||||
import {HalSource} from "core-app/modules/hal/resources/hal-resource"; |
||||
import {IOPFormlyFieldSettings, IOPFormlyTemplateOptions} from "core-app/modules/common/dynamic-forms/typings"; |
||||
import {I18nService} from "core-app/modules/common/i18n/i18n.service"; |
||||
import {APIV3Service} from "core-app/modules/apiv3/api-v3.service"; |
||||
import {JobStatusModal} from "core-app/modules/job-status/job-status-modal/job-status.modal"; |
||||
import {OpModalService} from "core-app/modules/modal/modal.service"; |
||||
import {ProjectFormAttributeGroups} from "core-app/modules/projects/form-helpers/form-attribute-groups"; |
||||
|
||||
interface CopyFormFieldConfig { |
||||
firstLevelFields:IOPFormlyFieldSettings[]; |
||||
metaLevelFields:IOPFormlyFieldSettings[]; |
||||
advancedSettingsFields:IOPFormlyFieldSettings[]; |
||||
} |
||||
|
||||
@Component({ |
||||
selector: 'op-copy-project', |
||||
templateUrl: './copy-project.component.html' |
||||
}) |
||||
export class CopyProjectComponent extends UntilDestroyedMixin implements OnInit { |
||||
dynamicFieldsSettingsPipe = this.fieldSettingsPipe.bind(this); |
||||
|
||||
formUrl:string; |
||||
|
||||
hiddenFields:string[] = [ |
||||
'identifier', |
||||
'active' |
||||
]; |
||||
|
||||
text = { |
||||
advancedSettingsLabel: this.I18n.t("js.forms.advanced_settings"), |
||||
copySettingsLabel: this.I18n.t("js.project.copy.copy_options"), |
||||
} |
||||
|
||||
constructor( |
||||
private apiV3Service:APIV3Service, |
||||
private uIRouterGlobals:UIRouterGlobals, |
||||
private pathHelperService:PathHelperService, |
||||
private modalService:OpModalService, |
||||
private $state:StateService, |
||||
private I18n:I18nService, |
||||
) { |
||||
super(); |
||||
} |
||||
|
||||
ngOnInit():void { |
||||
this.formUrl = this.apiV3Service.projects.id(this.uIRouterGlobals.params.projectPath).copy.form.path; |
||||
} |
||||
|
||||
onSubmitted(response:HalSource) { |
||||
this.modalService.show(JobStatusModal, 'global', { jobId: response.jobId }); |
||||
} |
||||
|
||||
private isHiddenField(key:string|undefined):boolean { |
||||
return !!key && this.hiddenFields.includes(key); |
||||
} |
||||
|
||||
private fieldSettingsPipe(dynamicFieldsSettings:IOPFormlyFieldSettings[]):IOPFormlyFieldSettings[] { |
||||
const fieldsLayoutConfig = dynamicFieldsSettings |
||||
.reduce((result, field) => { |
||||
field = { |
||||
...field, |
||||
hide: this.isHiddenField(field.key), |
||||
} |
||||
|
||||
const to = field.templateOptions; |
||||
if (this.isMeta(to?.property)) { |
||||
result.metaLevelFields = [...result.metaLevelFields, field]; |
||||
} else if (to && this.isPrimaryAttribute(to)) { |
||||
result.firstLevelFields = [...result.firstLevelFields, field]; |
||||
} else { |
||||
result.advancedSettingsFields = [...result.advancedSettingsFields, field]; |
||||
} |
||||
|
||||
return result; |
||||
}, { |
||||
firstLevelFields: [], |
||||
metaLevelFields: [], |
||||
advancedSettingsFields: [] |
||||
} as CopyFormFieldConfig |
||||
); |
||||
|
||||
return [ |
||||
...fieldsLayoutConfig.firstLevelFields, |
||||
ProjectFormAttributeGroups.collapsibleFieldset(fieldsLayoutConfig.advancedSettingsFields, this.text.advancedSettingsLabel), |
||||
ProjectFormAttributeGroups.collapsibleFieldset(fieldsLayoutConfig.metaLevelFields, this.text.copySettingsLabel), |
||||
]; |
||||
} |
||||
|
||||
private isPrimaryAttribute(to:IOPFormlyTemplateOptions):boolean { |
||||
return (to.required && |
||||
!to.hasDefault && |
||||
to.payloadValue == null) || |
||||
to.property === 'name' || |
||||
to.property === 'parent'; |
||||
} |
||||
|
||||
private isMeta(property:string|undefined):boolean { |
||||
return !!property && (property.startsWith('copy') || property == 'sendNotifications'); |
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
import {IOPFormlyFieldSettings} from "core-app/modules/common/dynamic-forms/typings"; |
||||
import {FormlyFieldConfig} from "@ngx-formly/core"; |
||||
|
||||
export namespace ProjectFormAttributeGroups { |
||||
|
||||
/** |
||||
* Create a collapsible formly fieldset for the given fields |
||||
* @param {IOPFormlyFieldSettings[]} fields Fields to include in the fieldset |
||||
* @param {string} label Label of the fieldset |
||||
*/ |
||||
export function collapsibleFieldset( |
||||
fields:IOPFormlyFieldSettings[], |
||||
label:string, |
||||
):IOPFormlyFieldSettings { |
||||
return { |
||||
fieldGroup: fields, |
||||
fieldGroupClassName: "op-form--field-group", |
||||
templateOptions: { |
||||
label: label, |
||||
isFieldGroup: true, |
||||
collapsibleFieldGroups: true, |
||||
collapsibleFieldGroupsCollapsed: true, |
||||
}, |
||||
type: "formly-group" as "formly-group", |
||||
wrappers: ["op-dynamic-field-group-wrapper"], |
||||
expressionProperties: { |
||||
'templateOptions.collapsibleFieldGroupsCollapsed': (model:unknown, formState:unknown, field:FormlyFieldConfig) => { |
||||
// Uncollapse field groups when the form has errors and has been submitted
|
||||
if ( |
||||
field.type !== 'formly-group' || |
||||
!field.templateOptions?.collapsibleFieldGroups || |
||||
!field.templateOptions?.collapsibleFieldGroupsCollapsed |
||||
) { |
||||
return; |
||||
} else { |
||||
return !( |
||||
field.fieldGroup?.some(groupField => |
||||
groupField?.formControl?.errors && |
||||
!groupField.hide && |
||||
field.options?.parentForm?.submitted |
||||
)); |
||||
} |
||||
}, |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -1,173 +0,0 @@ |
||||
#-- copyright |
||||
# OpenProject is an open source project management software. |
||||
# Copyright (C) 2012-2021 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. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
|
||||
describe CopyProjectsController, type: :controller do |
||||
let(:current_user) { FactoryBot.create(:admin) } |
||||
let(:permission) { :copy_projects } |
||||
let(:project) { FactoryBot.create(:project, public: false) } |
||||
let(:copy_project_params) do |
||||
{ |
||||
description: 'Some pretty description', |
||||
public: false |
||||
} |
||||
end |
||||
|
||||
before do |
||||
allow(User).to receive(:current).and_return current_user |
||||
# Prevent actually setting User.current. |
||||
# Otherwise the set user might be used in the next spec. |
||||
allow(User).to receive(:current=) |
||||
end |
||||
|
||||
describe 'copy_from_settings uses correct project to copy from' do |
||||
before do |
||||
get 'copy_project', params: { id: project.id, coming_from: :settings } |
||||
end |
||||
|
||||
it { expect(assigns(:project)).to eq(project) } |
||||
|
||||
it { expect(assigns(:copy_project).id).to be_nil } |
||||
|
||||
it { expect(response).to render_template('copy_from_settings') } |
||||
end |
||||
|
||||
describe 'copy_from_settings without valid project' do |
||||
before { get 'copy_project', params: { id: 'invalid' } } |
||||
|
||||
it { expect(response.code).to eq('404') } |
||||
end |
||||
|
||||
describe 'copy_from_settings without name and identifier' do |
||||
before do |
||||
post 'copy', |
||||
params: { id: project.id, project: copy_project_params } |
||||
end |
||||
|
||||
it { expect(response).to render_template('copy_from_settings') } |
||||
it 'should display error validation messages' do |
||||
expect(assigns(:errors)).not_to be_empty |
||||
end |
||||
end |
||||
|
||||
describe 'copy_from_settings permissions' do |
||||
def fetch |
||||
get 'copy_project', params: { id: project.id, coming_from: :settings } |
||||
end |
||||
|
||||
it_should_behave_like 'a controller action which needs project permissions' |
||||
end |
||||
|
||||
shared_examples_for 'successful copy' do |
||||
it { |
||||
expect(flash[:notice]).to eq(I18n.t('copy_project.started', source_project_name: source_project.name, |
||||
target_project_name: target_project_name)) |
||||
} |
||||
end |
||||
|
||||
def copy_project(project) |
||||
post 'copy', |
||||
params: { |
||||
id: project.id, |
||||
project: copy_project_params.merge(identifier: 'copy', name: 'copy') |
||||
} |
||||
perform_enqueued_jobs |
||||
end |
||||
|
||||
describe 'copy creates a new project' do |
||||
before { copy_project(project) } |
||||
|
||||
def expect_redirect_to |
||||
true |
||||
end |
||||
|
||||
it { expect(Project.count).to eq(2) } |
||||
|
||||
it 'copied project enables modules of source project' do |
||||
expect(Project.order(:id).last.enabled_modules.map(&:name)) |
||||
.to match_array(project.enabled_modules.map(&:name) - %w[repository]) |
||||
end |
||||
|
||||
it_behaves_like 'successful copy' do |
||||
let(:source_project) { project } |
||||
let(:target_project_name) { 'copy' } |
||||
end |
||||
|
||||
it 'should redirect to job status' do |
||||
expect(response).to redirect_to /\/job_statuses\/[\w-]+/ |
||||
end |
||||
end |
||||
|
||||
describe 'copy permissions' do |
||||
def fetch |
||||
post 'copy', |
||||
params: { |
||||
id: project.id, |
||||
project: copy_project_params.merge(identifier: 'copy', name: 'copy') |
||||
} |
||||
end |
||||
|
||||
def expect_redirect_to |
||||
true |
||||
end |
||||
|
||||
let(:permission) { %i[copy_projects add_project] } |
||||
let(:project) { FactoryBot.create(:project, public: false) } |
||||
|
||||
it_should_behave_like 'a controller action which needs project permissions' |
||||
end |
||||
|
||||
describe 'copy sends eMail' do |
||||
let(:maildouble) { double('Mail::Message', deliver: true) } |
||||
|
||||
before do |
||||
allow(maildouble).to receive(:deliver_now).and_return nil |
||||
end |
||||
|
||||
context 'on success' do |
||||
it 'user receives success mail' do |
||||
expect(ProjectMailer).to receive(:copy_project_succeeded).and_return(maildouble) |
||||
|
||||
copy_project(project) |
||||
end |
||||
end |
||||
|
||||
context 'on error' do |
||||
before do |
||||
allow(ProjectMailer).to receive(:with_deliveries).and_raise(ActiveRecord::RecordNotFound) |
||||
end |
||||
|
||||
it 'user receives success mail' do |
||||
expect(ProjectMailer).to receive(:copy_project_failed).and_return(maildouble) |
||||
|
||||
copy_project(project) |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue