From ac4ba4fe61014a4228ad2d2650a8e0e8a202cd59 Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Tue, 11 Nov 2025 16:49:44 +0000 Subject: [PATCH 1/2] Add Catalyst as dependency --- package-lock.json | 8 +++++++- package.json | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2a3c0ab4ef34..12ffbc5efd6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "hasInstallScript": true, "dependencies": { + "@github/catalyst": "^1.7.0", "@xeokit/xeokit-gltf-to-xkt": "^1.3.1" }, "devDependencies": { @@ -19,6 +20,12 @@ "npm": "^10.1.0" } }, + "node_modules/@github/catalyst": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@github/catalyst/-/catalyst-1.7.0.tgz", + "integrity": "sha512-qOAxrDdRZz9+v4y2WoAfh11rpRY/x4FRofPNmJyZFzAjubtzE3sCa/tAycWWufmQGoYiwwzL/qJBBgyg7avxPw==", + "license": "MIT" + }, "node_modules/@redocly/ajv": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.0.tgz", @@ -424,7 +431,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", diff --git a/package.json b/package.json index 0fa91d81f6e7..2dc96a8d722e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@redocly/openapi-cli": "^1.0.0-beta.80" }, "dependencies": { + "@github/catalyst": "^1.7.0", "@xeokit/xeokit-gltf-to-xkt": "^1.3.1" } } From 9b19582e35d9159e84d7bb3fe925977f3c2a9982 Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Tue, 11 Nov 2025 17:52:28 +0000 Subject: [PATCH 2/2] [WIP] Icon + File Upload support --- app/assets/images/templates/example.svg | 151 ++++++++++++++++++ app/assets/images/templates/pmflexone.svg | 4 + .../settings/general/show_component.html.erb | 19 +++ app/contracts/projects/base_contract.rb | 9 ++ app/forms/projects/settings/icon_form.rb | 38 +++++ app/forms/projects/template_select_form.rb | 2 +- app/models/concerns/has_icon.rb | 37 +++++ app/models/custom_icon.rb | 31 ++++ app/models/icon.rb | 4 + app/models/octicon_icon.rb | 31 ++++ app/models/permitted_params.rb | 1 + app/models/project.rb | 2 + config/locales/en.yml | 3 + db/migrate/20251111183800_create_icons.rb | 46 ++++++ frontend/src/custom-elements/index.ts | 1 + .../src/custom-elements/primer-file-field.ts | 40 +++++ .../src/global_styles/openproject/_forms.sass | 34 ++++ frontend/src/main.ts | 3 + .../forms/dsl/file_field_input.rb | 67 ++++++++ .../open_project/forms/dsl/input_methods.rb | 4 + .../open_project/forms/file_field.html.erb | 7 + lib/primer/open_project/forms/file_field.rb | 56 +++++++ 22 files changed, 589 insertions(+), 1 deletion(-) create mode 100644 app/assets/images/templates/example.svg create mode 100644 app/assets/images/templates/pmflexone.svg create mode 100644 app/forms/projects/settings/icon_form.rb create mode 100644 app/models/concerns/has_icon.rb create mode 100644 app/models/custom_icon.rb create mode 100644 app/models/icon.rb create mode 100644 app/models/octicon_icon.rb create mode 100644 db/migrate/20251111183800_create_icons.rb create mode 100644 frontend/src/custom-elements/index.ts create mode 100644 frontend/src/custom-elements/primer-file-field.ts create mode 100644 lib/primer/open_project/forms/dsl/file_field_input.rb create mode 100644 lib/primer/open_project/forms/file_field.html.erb create mode 100644 lib/primer/open_project/forms/file_field.rb diff --git a/app/assets/images/templates/example.svg b/app/assets/images/templates/example.svg new file mode 100644 index 000000000000..617121d8c130 --- /dev/null +++ b/app/assets/images/templates/example.svg @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/templates/pmflexone.svg b/app/assets/images/templates/pmflexone.svg new file mode 100644 index 000000000000..288d54127b24 --- /dev/null +++ b/app/assets/images/templates/pmflexone.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/components/projects/settings/general/show_component.html.erb b/app/components/projects/settings/general/show_component.html.erb index ce1c10009958..d38e3854fb98 100644 --- a/app/components/projects/settings/general/show_component.html.erb +++ b/app/components/projects/settings/general/show_component.html.erb @@ -84,5 +84,24 @@ See COPYRIGHT and LICENSE files for more details. ) end end + + container.with_row(mb: 3) do + settings_primer_form_with(model: project, url: project_settings_general_path(project)) do |f| + concat( + render(Primer::Beta::Subhead.new) do |component| + component.with_heading(tag: :h3, size: :medium) { I18n.t("projects.settings.header_icon") } + end + ) + + concat( + render( + Primer::Forms::FormList.new( + Projects::Settings::IconForm.new(f), + Projects::Settings::Submit.new(f, label: I18n.t("projects.settings.button_update_icon")) + ) + ) + ) + end + end end %> diff --git a/app/contracts/projects/base_contract.rb b/app/contracts/projects/base_contract.rb index f36431cf7738..505beeeb602e 100644 --- a/app/contracts/projects/base_contract.rb +++ b/app/contracts/projects/base_contract.rb @@ -52,6 +52,9 @@ class BaseContract < ::ModelContract attribute :templated do validate_templated_set_by_admin end + attribute :icon do + validate_templated_present + end validate :validate_user_allowed_to_manage @@ -115,6 +118,12 @@ def validate_status_code_included errors.add :status, :inclusion if model.status_code && Project.status_codes.keys.exclude?(model.status_code.to_s) end + def validate_templated_present + if model.templated.nil? + errors.add(:templated, :blank) + end + end + def validate_templated_set_by_admin if model.templated_changed? && !user.admin? errors.add :templated, :error_unauthorized diff --git a/app/forms/projects/settings/icon_form.rb b/app/forms/projects/settings/icon_form.rb new file mode 100644 index 000000000000..3515d7e5ed9f --- /dev/null +++ b/app/forms/projects/settings/icon_form.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 Projects + module Settings + class IconForm < ApplicationForm + form do |f| + f.file_field name: :icon, label: attribute_name(:icon), accept: "foo", size: "15" + end + end + end +end diff --git a/app/forms/projects/template_select_form.rb b/app/forms/projects/template_select_form.rb index dd02d6d96649..3eba34d88f02 100644 --- a/app/forms/projects/template_select_form.rb +++ b/app/forms/projects/template_select_form.rb @@ -66,7 +66,7 @@ class TemplateSelectForm < ApplicationForm value: template.id, label: template.name, caption: format_caption(template.description), - icon: agile_image, # TODO: support customizable icons (OP #69068) + icon: template.icon, checked: template.id == template_id ) end diff --git a/app/models/concerns/has_icon.rb b/app/models/concerns/has_icon.rb new file mode 100644 index 000000000000..b1f0671f2396 --- /dev/null +++ b/app/models/concerns/has_icon.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# --copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 HasIcon + extend ActiveSupport::Concern + + included do + has_one :icon, as: :iconifiable, dependent: :destroy + end +end diff --git a/app/models/custom_icon.rb b/app/models/custom_icon.rb new file mode 100644 index 000000000000..ad9c4815eb1b --- /dev/null +++ b/app/models/custom_icon.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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. +#++ +class CustomIcon < Icon +end diff --git a/app/models/icon.rb b/app/models/icon.rb new file mode 100644 index 000000000000..d9710370aab4 --- /dev/null +++ b/app/models/icon.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class Icon < ApplicationRecord +end diff --git a/app/models/octicon_icon.rb b/app/models/octicon_icon.rb new file mode 100644 index 000000000000..959be74541f8 --- /dev/null +++ b/app/models/octicon_icon.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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. +#++ +class OcticonIcon < Icon +end diff --git a/app/models/permitted_params.rb b/app/models/permitted_params.rb index fd7f517eab8c..20f11a740899 100644 --- a/app/models/permitted_params.rb +++ b/app/models/permitted_params.rb @@ -292,6 +292,7 @@ def project :templated, :status_code, :status_explanation, + :icon, work_package_custom_field_ids: [], type_ids: [], enabled_module_names: []) diff --git a/app/models/project.rb b/app/models/project.rb index c68893d6a250..26a99843dd7a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -43,6 +43,8 @@ class Project < ApplicationRecord include ::Scopes::Scoped + include HasIcon + # Maximum length for project identifiers IDENTIFIER_MAX_LENGTH = 100 diff --git a/config/locales/en.yml b/config/locales/en.yml index 4a9cfdd5ba19..6345fdd8575f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -506,9 +506,11 @@ en: header_details: Basic details header_status: Project status header_relations: Project relations + header_icon: Template icon button_update_details: Update details button_update_status_description: Update status description button_update_parent_project: Update parent project + button_update_icon: Update icon public_warning: > This project is public. Anyone who has access to this instance will be able to view and interact with this project depending on their role and associated permissions. @@ -1995,6 +1997,7 @@ en: group: "Group" groups: "Groups" hexcode: "Hex code" + icon: "Icon" id: "ID" is_default: "Default value" is_for_all: "For all projects" diff --git a/db/migrate/20251111183800_create_icons.rb b/db/migrate/20251111183800_create_icons.rb new file mode 100644 index 000000000000..68e8ad56c4e0 --- /dev/null +++ b/db/migrate/20251111183800_create_icons.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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. +#++ +class CreateIcons < ActiveRecord::Migration[8.0] + def change + create_table :icons do |t| + t.string :type, null: false + + t.string :octicon_name + t.string :custom_file + + t.references :iconifiable, polymorphic: true, null: false + t.timestamps + end + + add_check_constraint :icons, + "(octicon_name IS NOT NULL) <> (custom_file IS NOT NULL)", + name: "only_one_icon_source" + end +end diff --git a/frontend/src/custom-elements/index.ts b/frontend/src/custom-elements/index.ts new file mode 100644 index 000000000000..94d296775131 --- /dev/null +++ b/frontend/src/custom-elements/index.ts @@ -0,0 +1 @@ +import './primer-file-field'; diff --git a/frontend/src/custom-elements/primer-file-field.ts b/frontend/src/custom-elements/primer-file-field.ts new file mode 100644 index 000000000000..822c969e0476 --- /dev/null +++ b/frontend/src/custom-elements/primer-file-field.ts @@ -0,0 +1,40 @@ +import { controller, target } from '@github/catalyst'; + +@controller +class PrimerFileFieldElement extends HTMLElement { + @target inputElement:HTMLInputElement; + + #abortController:AbortController | null; + + @target button:HTMLElement; + @target label:HTMLElement; + + connectedCallback() { + this.#abortController?.abort(); + const {signal} = (this.#abortController = new AbortController()); + + this.inputElement.addEventListener('change', () => { + const files = this.inputElement.files!; + if (files.length === 0) { + this.label.textContent = 'no file selected'; + } else { + this.label.textContent = files[0].name; + } + }, { signal }); + } + + disconnectedCallback() { + this.#abortController?.abort(); + } +} + +// if (!window.customElements.get('primer-file-field')) { +// window.PrimerFileFieldElement = PrimerFileFieldElement +// window.customElements.define('primer-file-field', PrimerFileFieldElement) +// } + +declare global { + interface Window { + PrimerFileFieldElement:typeof PrimerFileFieldElement + } +} diff --git a/frontend/src/global_styles/openproject/_forms.sass b/frontend/src/global_styles/openproject/_forms.sass index 2ad2073b2b27..5dcb5dc8cd09 100644 --- a/frontend/src/global_styles/openproject/_forms.sass +++ b/frontend/src/global_styles/openproject/_forms.sass @@ -222,3 +222,37 @@ input[type="number"] .FormControl-advanced-checkbox-icon, .FormControl-advanced-radio-icon fill: var(--fgColor-accent) + +.FormControl-file-wrap + position: relative + display: inline-flex + align-items: center + gap: 0.5rem + border: 1px solid #ccc + border-radius: 4px + padding: 0.4rem 0.5rem 0.4rem 0.5rem + width: 280px + box-sizing: border-box + +.FormControl-file + position: absolute + inset: 0 + opacity: 0 + cursor: pointer + +.file-label + flex: 1 + font-size: 0.875rem + color: #666 + white-space: nowrap + overflow: hidden + text-overflow: ellipsis + +.file-button + padding: 0.35rem 0.75rem + border-radius: 4px + border: 1px solid #ccc + background: #f5f5f5 + font-size: 0.85rem + cursor: pointer + white-space: nowrap diff --git a/frontend/src/main.ts b/frontend/src/main.ts index d723df2c3b1a..c76b29680e89 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -11,6 +11,9 @@ import { getMetaElement } from 'core-app/core/setup/globals/global-helpers'; import 'core-app/core/setup/init-vendors'; import 'core-app/core/setup/init-globals'; + +import './custom-elements'; + import './stimulus/setup'; import './turbo/setup'; import { platformBrowser } from '@angular/platform-browser'; diff --git a/lib/primer/open_project/forms/dsl/file_field_input.rb b/lib/primer/open_project/forms/dsl/file_field_input.rb new file mode 100644 index 000000000000..5d362b429416 --- /dev/null +++ b/lib/primer/open_project/forms/dsl/file_field_input.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 Primer + module OpenProject + module Forms + module Dsl + # :nodoc: + class FileFieldInput < Primer::Forms::Dsl::Input + attr_reader :name, :label + + def initialize(name:, label:, **system_arguments) + @name = name + @label = label + + super(**system_arguments) + + add_input_data(:target, "primer-file-field-element2.inputElement #{system_arguments.dig(:data, :target) || ''}") + end + + def to_component + FileField.new(input: self) + end + + # :nocov: + def type + :file_field + end + # :nocov: + + # :nocov: + def focusable? + true + end + # :nocov: + end + end + end + end +end diff --git a/lib/primer/open_project/forms/dsl/input_methods.rb b/lib/primer/open_project/forms/dsl/input_methods.rb index 7c217c9e2c70..21134f320c11 100644 --- a/lib/primer/open_project/forms/dsl/input_methods.rb +++ b/lib/primer/open_project/forms/dsl/input_methods.rb @@ -73,6 +73,10 @@ def work_package_autocompleter(**, &) add_input WorkPackageAutocompleterInput.new(builder:, form:, **decorate_options(**), &) end + def file_field(**) + add_input FileFieldInput.new(builder:, form:, **decorate_options(**)) + end + def decorate_options(include_help_text: true, help_text_options: {}, **options) if include_help_text && supports_help_texts?(form.model) attribute_name = help_text_options[:attribute_name] || options[:name] diff --git a/lib/primer/open_project/forms/file_field.html.erb b/lib/primer/open_project/forms/file_field.html.erb new file mode 100644 index 000000000000..ff771e378594 --- /dev/null +++ b/lib/primer/open_project/forms/file_field.html.erb @@ -0,0 +1,7 @@ +<%= render(FormControl.new(input: @input, tag: :"primer-file-field-element2")) do %> + <%= content_tag(:div, **@field_wrap_arguments) do %> + <%= builder.file_field(@input.name, **@input.input_arguments) %> + Choose a file… + Browse + <% end %> +<% end %> diff --git a/lib/primer/open_project/forms/file_field.rb b/lib/primer/open_project/forms/file_field.rb new file mode 100644 index 000000000000..e79e3405de1b --- /dev/null +++ b/lib/primer/open_project/forms/file_field.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 Primer + module OpenProject + module Forms + # :nodoc: + class FileField < Primer::Forms::BaseComponent + delegate :builder, :form, to: :@input + + def initialize(input:) + super() + + @input = input + @input.add_input_classes("FormControl-file") + + wrap_classes = [ + "FormControl-file-wrap" + ] + + @field_wrap_arguments = { + class: class_names(wrap_classes), + hidden: @input.hidden? + } + end + end + end + end +end