Skip to content

Commit

Permalink
[Op#50737] Convert new storage page to primer design (#14053)
Browse files Browse the repository at this point in the history
  • Loading branch information
akabiru authored Nov 16, 2023
2 parents 4eb61e9 + 317a3fe commit c1803ef
Show file tree
Hide file tree
Showing 68 changed files with 2,223 additions and 455 deletions.
12 changes: 12 additions & 0 deletions app/components/op_turbo/frame_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,19 @@
module OpTurbo
class FrameComponent < ApplicationComponent
def turbo_frame_id
optional_custom_id || turbo_frame_id_from_model
end

private

def turbo_frame_id_from_model
ActionView::RecordIdentifier.dom_id(model, options[:context])
end

def optional_custom_id
return if options[:id].blank?

options.values_at(:context, :id).compact.join("_")
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class ClipboardCopyComponent < ApplicationComponent

options visually_hide_label: true,
readonly: true,
required: false
required: false,
input_group_options: {}

def text_field_options
{ name: options[:name],
Expand All @@ -44,13 +45,13 @@ def text_field_options
value: value_to_copy,
inset: true,
readonly:,
required: }
required: }.merge(input_group_options)
end

def clipboard_copy_options
{ value: value_to_copy,
aria: { label: clipboard_copy_aria_label },
classes: clipboard_copy_classes }
classes: clipboard_copy_classes }.merge(input_group_options)
end

private
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,53 @@

import { Controller } from '@hotwired/stimulus';

export default class StorageFormController extends Controller {
export default class OAuthClientFormController extends Controller {
static targets = [
'clientId',
'clientSecret',
'redirectUri',
'submitButton',
];

static values = {
clientIdMissing: String,
};

declare readonly hasClientIdTarget:boolean;
declare readonly hasClientSecretTarget:boolean;
declare readonly hasSubmitButtonTarget:boolean;
declare readonly clientIdTarget:HTMLInputElement;
declare readonly redirectUriTarget:HTMLInputElement;
declare readonly clientSecretTarget:HTMLInputElement;
declare readonly redirectUriTargets:HTMLInputElement[];
declare readonly submitButtonTarget:HTMLInputElement;

declare readonly clientIdMissingValue:string;

connect():void {
this.clientIdTarget.addEventListener('input', () => {
this.redirectUriTarget.value = this.redirectUri();
});
this.setRedirectUriValue();
this.toggleSubmitButtonDisabled();
}

public toggleSubmitButtonDisabled():void {
const targetsConfigured = this.hasClientIdTarget && this.hasClientSecretTarget && this.hasSubmitButtonTarget;

if (!targetsConfigured) {
return;
}

this.redirectUriTarget.value = this.redirectUri();
if (this.clientIdTarget.value === '' || this.clientSecretTarget.value === '') {
this.submitButtonTarget.disabled = true;
} else {
this.submitButtonTarget.disabled = false;
}
}

public setRedirectUriValue():void {
const newValue = this.redirectUri();
this.redirectUriTargets.forEach((target) => {
target.value = newValue;
target.setAttribute('value', newValue);
});
}

private redirectUri():string {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* -- copyright
* OpenProject is an open source project management software.
* Copyright (C) 2023 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 COPYRIGHT and LICENSE files for more details.
* ++
*/

import { Controller } from '@hotwired/stimulus';

export default class SelectProviderFormController extends Controller {
static targets = [
'providerForm',
'providerSelect',
];

declare readonly providerFormTarget:HTMLFormElement;
declare readonly providerSelectTarget:HTMLSelectElement;

connect():void {
// On first load if providerTypeValue is already selected, show the provider form
this.fetchProviderTypeForm(this.providerSelectTarget.value);
}

public showProviderForm(evt:Event):void {
this.fetchProviderTypeForm((evt.target as HTMLSelectElement).value);
}

fetchProviderTypeForm(providerTypeValue:string):void {
if (providerTypeValue === '') {
return;
}

this.providerFormTarget.requestSubmit();
}
}
6 changes: 6 additions & 0 deletions lib/open_project/static/links.rb
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ def static_links
storage_docs: {
setup: {
href: 'https://www.openproject.org/docs/system-admin-guide/integrations/nextcloud/'
},
nextcloud_oauth_application: {
href: 'https://apps.nextcloud.com/apps/integration_openproject'
},
one_drive_oauth_application: {
href: 'https://docs.microsoft.com/en-us/graph/auth-register-app-v2'
}
},
ical_docs: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<%=
grid_layout('op-storage-view--row', tag: :div, align_items: :center) do |grid|
grid.with_area(:item, tag: :div, mr: 3) do
concat(render(Primer::Beta::Text.new(font_weight: :bold, mr: 1, test_selector: 'storage-managed-project-folders-label')) { I18n.t('storages.file_storage_view.automatically_managed_folders') })
concat(automatically_managed_project_folders_status_label)
end

grid.with_area(:description, tag: :div, color: :subtle, test_selector: 'storage-automatically-managed-project-folders-description') do
render(Primer::Beta::Truncate.new) { I18n.t('storages.page_titles.managed_project_folders.subtitle_short') }
end

if editable_storage?
grid.with_area(:"icon-button", tag: :div, color: :muted) do
flex_layout(justify_content: :flex_end) do |icons_container|
icons_container.with_column do
render(
Primer::Beta::IconButton.new(
icon: :pencil,
tag: :a,
href: edit_button_path,
scheme: :invisible,
aria: { label: I18n.t('storages.label_edit_storage_automatically_managed_folders') },
test_selector: 'storage-edit-automatically-managed-project-folders-button',
data: { turbo_stream: true }
)
)
end
end
end
end
end
%>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2023 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 COPYRIGHT and LICENSE files for more details.
#++
#
module Storages::Admin
class AutomaticallyManagedProjectFoldersInfoComponent < ApplicationComponent
include OpPrimer::ComponentHelpers
include StorageViewInformation

alias_method :storage, :model

def edit_button_path
if storage.automatic_management_unspecified?
new_admin_settings_storage_automatically_managed_project_folders_path(storage)
else
edit_admin_settings_storage_automatically_managed_project_folders_path(storage)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<%=
render(Primer::Beta::Text.new(tag: :div, test_selector: 'storage-automatically-managed-project-folders-form')) do
primer_form_with(
model: storage,
url: admin_settings_storage_automatically_managed_project_folders_path(storage),
method: :patch,
model:,
url: form_url,
method: form_method,
data: {
controller: "storages--automatically-managed-project-folders-form",
'application-target': "dynamic",
Expand All @@ -12,11 +12,11 @@
) do |form|
flex_layout do |project_folders_form|
project_folders_form.with_row(mb: 3) do
render(Primer::Beta::Text.new(font_weight: :semibold)) { I18n.t(:'storages.label_managed_project_folders.automatically_managed_folders') }
render(Primer::Beta::Text.new(font_weight: :bold)) { I18n.t(:'storages.label_managed_project_folders.automatically_managed_folders') }
end

project_folders_form.with_row(mb: 3) do
render(Primer::Beta::Text.new(font_weight: :light)) { I18n.t("storages.page_titles.managed_project_folders.subtitle") }
render(Primer::Beta::Text.new) { I18n.t("storages.page_titles.managed_project_folders.subtitle") }
end

project_folders_form.with_row(mb: 3) do
Expand All @@ -28,7 +28,14 @@
end

project_folders_form.with_row do
render(Storages::Admin::SaveOrCancelForm.new(form, storage:, submit_label: I18n.t("storages.buttons.done_complete_setup")))
render(
Storages::Admin::SubmitOrCancelForm.new(
form,
storage:,
submit_button_options:,
cancel_button_options:
)
)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,39 @@ class AutomaticallyManagedProjectFoldersFormComponent < ApplicationComponent
include OpPrimer::ComponentHelpers
alias_method :storage, :model

def form_method
options[:form_method] || default_form_method
end

def form_url
options[:form_url] || default_form_url
end

def submit_button_options
{ label: I18n.t("storages.buttons.done_complete_setup") }.tap do |options_hash|
# For create action, break from Turbo Frame and follow full page redirect
options_hash[:data] = { turbo: false } if new_record?
end
end

def cancel_button_options
{ href: edit_admin_settings_storage_path(storage) }
end

private

def default_form_method
new_record? ? :post : :patch
end

def new_record?
storage.automatic_management_new_record?
end

def default_form_url
admin_settings_storage_automatically_managed_project_folders_path(storage)
end

def storage_provider_credentials_copy_instructions
"#{I18n.t('storages.instructions.copy_from')}: #{provider_credentials_instructions_link}".html_safe
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
<%=
render(Primer::Beta::Text.new(tag: :div, test_selector: 'storage-general-info-form')) do
primer_form_with(
model: storage,
url: admin_settings_storage_path(storage),
method: :patch
model:,
url: form_url,
method: form_method
) do |form|
flex_layout do |general_info_row|
general_info_row.with_row(mb: 3) do
render(Storages::Admin::StorageProviderForm.new(form, storage:))
render(
Storages::Admin::ProviderTypeSelectForm.new(
form,
storage:,
select_list_options: { caption: provider_type_select_caption, readonly: storage.new_record? }
)
)
end

general_info_row.with_row(mb: 3) do
render(Storages::Admin::ProviderNameInputForm.new(form))
end

if storage.provider_type_nextcloud?
general_info_row.with_row(mb: 3) do
render(Storages::Admin::ProviderHostInputForm.new(form))
end
end

if storage.provider_type_one_drive?
general_info_row.with_row(mb: 3) do
render(Storages::Admin::ProviderTenantIdInputForm.new(form))
end

general_info_row.with_row(mb: 3) do
render(Storages::Admin::ProviderDriveIdInputForm.new(form))
end
end

general_info_row.with_row do
render(Storages::Admin::SaveOrCancelForm.new(form, storage:))
render(
Storages::Admin::SubmitOrCancelForm.new(
form,
storage:,
submit_button_options:,
cancel_button_options:
)
)
end
end
end
Expand Down
Loading

0 comments on commit c1803ef

Please sign in to comment.