diff --git a/app/assets/stylesheets/content/_action_menu_main.sass b/app/assets/stylesheets/content/_action_menu_main.sass index 6466467e54..cf62587a57 100644 --- a/app/assets/stylesheets/content/_action_menu_main.sass +++ b/app/assets/stylesheets/content/_action_menu_main.sass @@ -30,7 +30,7 @@ ul list-style-type: none margin: 0 - width: 230px + width: 240px border: 1px solid #dddddd box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.15) padding: 3px 0 diff --git a/app/assets/stylesheets/content/_modal.sass b/app/assets/stylesheets/content/_modal.sass index cc90544253..152f1ae48f 100644 --- a/app/assets/stylesheets/content/_modal.sass +++ b/app/assets/stylesheets/content/_modal.sass @@ -150,12 +150,14 @@ ul.export-options margin: 0 0 30px 0 text-align: center display: inline-block - min-width: 32% + width: 32% a cursor: pointer text-decoration: none color: $body-font-color font-weight: normal + overflow-wrap: break-word + word-wrap: break-word &:hover, &:active text-decoration: none color: $body-font-color diff --git a/app/cells/views/settings/text_setting/show.erb b/app/cells/views/settings/text_setting/show.erb index b02a0bf2fc..3c66649464 100644 --- a/app/cells/views/settings/text_setting/show.erb +++ b/app/cells/views/settings/text_setting/show.erb @@ -31,8 +31,9 @@ label: false, id: "settings-#{name}-#{lang}", class: 'wiki-edit', + with_text_formatting: true, rows: 5, - container_class: '-wide' + container_class: '-xxwide' ) %> diff --git a/app/helpers/text_formatting_helper.rb b/app/helpers/text_formatting_helper.rb index 5bccdbf77c..c7b027d3a5 100644 --- a/app/helpers/text_formatting_helper.rb +++ b/app/helpers/text_formatting_helper.rb @@ -47,7 +47,7 @@ def preview_context(object, project = nil) #TODO remove def current_formatting_helper helper_class = OpenProject::TextFormatting::Formats.rich_helper - helper_class.new(self) + helper_class.new end def project_preview_context(object, project) diff --git a/app/models/news.rb b/app/models/news.rb index 98e279544d..8b1ed2e11b 100644 --- a/app/models/news.rb +++ b/app/models/news.rb @@ -34,7 +34,7 @@ class News < ActiveRecord::Base order('created_on') }, as: :commented, dependent: :delete_all - validates_presence_of :title, :description + validates_presence_of :title validates_length_of :title, maximum: 60 validates_length_of :summary, maximum: 255 @@ -62,6 +62,10 @@ def visible?(user = User.current) !user.nil? && user.allowed_to?(:view_news, project) end + def description=(val) + super val.presence || '' + end + # returns latest news for projects visible by user def self.latest(user: User.current, count: 5) latest_for(user, count: count) diff --git a/app/models/work_package/pdf_export/work_package_list_to_pdf.rb b/app/models/work_package/pdf_export/work_package_list_to_pdf.rb index 546cc56a33..9e26d57d1f 100644 --- a/app/models/work_package/pdf_export/work_package_list_to_pdf.rb +++ b/app/models/work_package/pdf_export/work_package_list_to_pdf.rb @@ -151,9 +151,11 @@ def data_rows if options[:show_attachments] && work_package.attachments.exists? attachments = make_attachments_cells(work_package.attachments) - result << [ - { content: pdf.make_table([attachments]), colspan: description_colspan } - ] + if attachments.any? + result << [ + { content: pdf.make_table([attachments]), colspan: description_colspan } + ] + end end if query.grouped? && (group = query.group_by_column.value(work_package)) != previous_group diff --git a/app/views/messages/_form.html.erb b/app/views/messages/_form.html.erb index d144f6f238..a62fbd26a2 100644 --- a/app/views/messages/_form.html.erb +++ b/app/views/messages/_form.html.erb @@ -54,7 +54,6 @@ See docs/COPYRIGHT.rdoc for more details.
<%= f.text_area :content, - required: true, label: t(:description_message_content), class: 'wiki-edit', container_class: '-xxwide', diff --git a/app/views/news/_form.html.erb b/app/views/news/_form.html.erb index bb008d20de..b4a83e9667 100644 --- a/app/views/news/_form.html.erb +++ b/app/views/news/_form.html.erb @@ -39,7 +39,6 @@ See docs/COPYRIGHT.rdoc for more details.
<%= f.text_area :description, - required: true, class: 'wiki-edit wiki-toolbar', container_class: '-wide', with_text_formatting: true %> diff --git a/app/views/projects/form/attributes/_description.html.erb b/app/views/projects/form/attributes/_description.html.erb index 871f359a38..4a5b27df72 100644 --- a/app/views/projects/form/attributes/_description.html.erb +++ b/app/views/projects/form/attributes/_description.html.erb @@ -33,5 +33,5 @@ See docs/COPYRIGHT.rdoc for more details. with_text_formatting: true, rows: 5, class: 'wiki-edit', - container_class: '-wide' %> + container_class: '-xxwide' %>
diff --git a/app/views/settings/_general.html.erb b/app/views/settings/_general.html.erb index 2bc94b4ab1..5bc2cf79b5 100644 --- a/app/views/settings/_general.html.erb +++ b/app/views/settings/_general.html.erb @@ -68,7 +68,7 @@ See docs/COPYRIGHT.rdoc for more details. class: 'wiki-edit', id: 'settings_welcome_text', with_text_formatting: true, - container_class: '-wide' %> + container_class: '-xxwide' %>
<%= setting_check_box :welcome_on_homescreen %>
diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb index cc412061dc..67223f1dbb 100644 --- a/config/initializers/secure_headers.rb +++ b/config/initializers/secure_headers.rb @@ -25,9 +25,11 @@ # Allow requests to CLI in dev mode connect_src = default_src + # Add proxy configuration for Angular CLI to csp if FrontendAssetHelper.assets_proxied? - connect_src += %w[ws://localhost:* http://localhost:*] - assets_src += %w[ws://localhost:* http://localhost:*] + proxied = ['ws://localhost:*', 'http://localhost:*', FrontendAssetHelper.cli_proxy] + connect_src += proxied + assets_src += proxied end config.csp = { diff --git a/docs/development/running-tests.md b/docs/development/running-tests.md index 207fc6c1e2..6ddd0b56bf 100644 --- a/docs/development/running-tests.md +++ b/docs/development/running-tests.md @@ -242,6 +242,9 @@ on a machine with 8 parallel instances. If you want to access the development server of OpenProject from a VM, you need to work around the CSP `localhost` restrictions. + +### Old way, fixed compilation + One way is to disable the Angular CLI that serves some of the assets when developing. To do that, run ```bash @@ -255,6 +258,22 @@ OPENPROJECT_CLI_PROXY='' ./bin/rails s -b 0.0.0.0 -p 3000 Now assuming networking is set up in your VM, you can access your app server on `:3000` from it. +### New way, with ng serve + +**The better way** when you want to develop against Edge is to set up your server to allow the CSP to the remote host. +Assuming your openproject is served at `:3000` and your ng serve middleware is running at `:4200`, +you can access both from inside a VM with nat/bridged networking as follows: + +```bash +# Start ng serve middleware binding to all interfaces +ng serve --host 0.0.0.0 + +# Start your openproject server with the CLI proxy configuration set +OPENPROJECT_CLI_PROXY=':4200' ./bin/rails s -b 0.0.0.0 -p 3000 + +# Now access your server from http://:3000 with code reloading +``` + ## Legacy LDAP tests OpenProject supports using LDAP for user authentications. To test LDAP diff --git a/frontend/src/app/components/wp-fast-table/state/wp-table-columns.service.ts b/frontend/src/app/components/wp-fast-table/state/wp-table-columns.service.ts index f011e407e1..55d2b02713 100644 --- a/frontend/src/app/components/wp-fast-table/state/wp-table-columns.service.ts +++ b/frontend/src/app/components/wp-fast-table/state/wp-table-columns.service.ts @@ -61,10 +61,17 @@ export class WorkPackageTableColumnsService extends WorkPackageTableBaseService< } public applyToQuery(query:QueryResource) { - query.columns = cloneHalResourceCollection(this.getColumns()); + const toApply = this.getColumns(); + + const oldColumns = query.columns.map(el => el.id); + const newColumns = toApply.map(el => el.id); + query.columns = cloneHalResourceCollection(toApply); + + // We can avoid reloading even with relation columns if we only removed columns + const onlyRemoved = _.difference(newColumns, oldColumns).length === 0; // Reload the table visibly if adding relation columns. - return this.hasRelationColumns(); + return !onlyRemoved && this.hasRelationColumns(); } /** diff --git a/frontend/src/app/components/wp-query-select/wp-query-select.template.html b/frontend/src/app/components/wp-query-select/wp-query-select.template.html index fa8b5a3c90..0e97f44ede 100644 --- a/frontend/src/app/components/wp-query-select/wp-query-select.template.html +++ b/frontend/src/app/components/wp-query-select/wp-query-select.template.html @@ -13,9 +13,9 @@
+

-

diff --git a/frontend/src/app/components/wp-single-view-tabs/watchers-tab/watchers-tab.component.ts b/frontend/src/app/components/wp-single-view-tabs/watchers-tab/watchers-tab.component.ts index 403fce7d57..efb28f291a 100644 --- a/frontend/src/app/components/wp-single-view-tabs/watchers-tab/watchers-tab.component.ts +++ b/frontend/src/app/components/wp-single-view-tabs/watchers-tab/watchers-tab.component.ts @@ -165,7 +165,7 @@ export class WorkPackageWatchersTabComponent implements OnInit, OnDestroy { const img = document.createElement('img'); img.src = item.watcher.avatar; img.alt = item.watcher.name; - img.classList.add('avatar-mini'); + img.classList.add('avatar-mini', 'avatar--fallback'); link.appendChild(img); } diff --git a/lib/open_project/form_tag_helper.rb b/lib/open_project/form_tag_helper.rb index e9a84fc362..3921eec5c5 100644 --- a/lib/open_project/form_tag_helper.rb +++ b/lib/open_project/form_tag_helper.rb @@ -88,7 +88,7 @@ def styled_text_area_tag(name, content = nil, options = {}) def text_formatting_wrapper(target_id, options) return ''.html_safe unless target_id.present? - helper = ::OpenProject::TextFormatting::Formats.rich_helper.new(self) + helper = ::OpenProject::TextFormatting::Formats.rich_helper.new helper.wikitoolbar_for target_id, options end diff --git a/lib/open_project/text_formatting/formats/markdown/helper.rb b/lib/open_project/text_formatting/formats/markdown/helper.rb index ea1760c4ca..4d2cef1bdd 100644 --- a/lib/open_project/text_formatting/formats/markdown/helper.rb +++ b/lib/open_project/text_formatting/formats/markdown/helper.rb @@ -31,19 +31,16 @@ module OpenProject::TextFormatting::Formats module Markdown class Helper - attr_reader :view_context - def initialize(view_context) - @view_context = view_context - end + def initialize; end def text_formatting_js_includes - view_context.javascript_include_tag 'vendor/ckeditor/ckeditor.js' + helpers.javascript_include_tag 'vendor/ckeditor/ckeditor.js' end def wikitoolbar_for(field_id, **context) # Hide the original textarea - view_context.content_for(:additional_js_dom_ready) do + helpers.content_for(:additional_js_dom_ready) do js = <<-JAVASCRIPT var field = document.getElementById('#{field_id}'); field.style.display = 'none'; @@ -55,12 +52,18 @@ def wikitoolbar_for(field_id, **context) # Pass an optional resource to the CKEditor instance resource = context.fetch(:resource, {}) - view_context.content_tag 'op-ckeditor-form', + helpers.content_tag 'op-ckeditor-form', '', 'textarea-selector': "##{field_id}", 'preview-context': context[:preview_context], 'data-resource': resource.to_json end + + protected + + def helpers + ApplicationController.helpers + end end end end diff --git a/lib/open_project/text_formatting/formats/markdown/textile_converter.rb b/lib/open_project/text_formatting/formats/markdown/textile_converter.rb index a0ef351d4d..6f91a06c82 100644 --- a/lib/open_project/text_formatting/formats/markdown/textile_converter.rb +++ b/lib/open_project/text_formatting/formats/markdown/textile_converter.rb @@ -221,7 +221,8 @@ def models_to_convert ::Journal => [:notes], ::Journal::MessageJournal => [:content], ::Journal::WikiContentJournal => [:text], - ::Journal::WorkPackageJournal => [:description] + ::Journal::WorkPackageJournal => [:description], + ::AttributeHelpText => [:help_text] } end diff --git a/lib/tabular_form_builder.rb b/lib/tabular_form_builder.rb index ba33e42f17..c8ed087a62 100644 --- a/lib/tabular_form_builder.rb +++ b/lib/tabular_form_builder.rb @@ -211,7 +211,7 @@ def field_container_css_class(selector, options) def text_formatting_wrapper(target_id, options) return ''.html_safe unless target_id.present? - helper = ::OpenProject::TextFormatting::Formats.rich_helper.new(@template) + helper = ::OpenProject::TextFormatting::Formats.rich_helper.new helper.wikitoolbar_for target_id, options end diff --git a/vendored-plugins/openproject-backlogs/features/scrum_master.feature b/vendored-plugins/openproject-backlogs/features/scrum_master.feature index de358f6a22..fce2e23ecd 100644 --- a/vendored-plugins/openproject-backlogs/features/scrum_master.feature +++ b/vendored-plugins/openproject-backlogs/features/scrum_master.feature @@ -259,22 +259,6 @@ Feature: Scrum Master And Story A should be in the 2nd position of the sprint named Sprint 001 And Story B should be the higher item of Story A - Scenario: view the sprint notes - Given I have set the content for wiki page Sprint Template to Sprint Template - And I have made Sprint Template the template page for sprint notes - And I am on the taskboard for "Sprint 001" - When I view the sprint notes - Then the request should complete successfully - Then the wiki page Sprint 001 should contain Sprint Template - - Scenario: edit the sprint notes - Given I have set the content for wiki page Sprint Template to Sprint Template - And I have made Sprint Template the template page for sprint notes - And I am on the taskboard for "Sprint 001" - When I edit the sprint notes - Then the request should complete successfully - Then the wiki page Sprint 001 should contain Sprint Template - Scenario: View tasks that have subtasks Given I am on the taskboard for "Sprint 005" Then I should see "Task 10" within "#tasks" diff --git a/vendored-plugins/openproject-reporting/spec/features/menu_spec.rb b/vendored-plugins/openproject-reporting/spec/features/menu_spec.rb index 113ed1f256..10efef6bee 100644 --- a/vendored-plugins/openproject-reporting/spec/features/menu_spec.rb +++ b/vendored-plugins/openproject-reporting/spec/features/menu_spec.rb @@ -69,8 +69,7 @@ it 'leads to cost reports' do click_on 'Cost reports' - expect(page).to have_selector('.breadcrumb > li', text: 'Ponyo') - expect(page).to have_selector('.breadcrumb > li', text: 'Cost reports') + expect(page).to have_selector('.button--dropdown-text', text: 'Ponyo') end end @@ -100,8 +99,6 @@ click_on 'Cost reports', visible: false end - expect(page).to have_selector('.breadcrumb > li', text: 'Cost reports') - # to make sure we're not seeing the project cost reports: expect(page).not_to have_text('Ponyo') end