From c425b99e28be0534d7ed14a1d969d19c6c061f31 Mon Sep 17 00:00:00 2001 From: CI Date: Sat, 19 Aug 2017 00:37:33 +0000 Subject: [PATCH 01/14] Update reference to OpenProject-Translations --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4e5429a5ef..60774e5e0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,7 +60,7 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: 37346939a2da071f53d55383c92c8d93be6628c0 + revision: d12a3d0ed38138d2cdbf4d8a547b02b170db36b4 branch: release/7.2 specs: openproject-translations (7.2.2) From ea19a9697d002ef43dcd963e6172ee2c02153fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 21 Aug 2017 11:27:17 +0200 Subject: [PATCH 02/14] Fix aria-label when textnode before html node (#5868) [ci skip] --- .../app/components/wp-edit-form/display-field-renderer.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/app/components/wp-edit-form/display-field-renderer.ts b/frontend/app/components/wp-edit-form/display-field-renderer.ts index deab9b333f..1d045ac60a 100644 --- a/frontend/app/components/wp-edit-form/display-field-renderer.ts +++ b/frontend/app/components/wp-edit-form/display-field-renderer.ts @@ -99,7 +99,12 @@ export class DisplayFieldRenderer { let labelContent = this.getLabelContent(field); if (field.isFormattable && !field.isEmpty()) { - titleContent = angular.element(labelContent).text(); + try { + titleContent = _.escape(angular.element(`
${labelContent}
`).text()); + } catch(e) { + console.error("Failed to parse formattable labelContent"); + titleContent = "Label for " + field.displayName; + } } else { titleContent = labelContent; From 8bec9d22ea3f274d7bc4c1bcb140f624ba9ea0f8 Mon Sep 17 00:00:00 2001 From: Wieland Lindenthal Date: Mon, 21 Aug 2017 14:38:11 +0200 Subject: [PATCH 03/14] SEO: Adding meta tags for title and description (#5864) * Add meta tags for title and description to Wiki * Remove unnecessary test for wether project is public * Fix: Use app title instead of app_name [ci skip] --- Gemfile | 2 ++ Gemfile.lock | 3 +++ app/helpers/application_helper.rb | 1 - app/views/layouts/base.html.erb | 6 +++--- app/views/wiki/show.html.erb | 5 +++++ 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 7f082c799b..028299c137 100644 --- a/Gemfile +++ b/Gemfile @@ -124,6 +124,8 @@ gem 'prawn-table', '~> 0.2.2' gem 'cells-rails', '~> 0.0.6' gem 'cells-erb', '~> 0.0.8' +gem 'meta-tags', '~> 2.4.1' + group :production do # we use dalli as standard memcache client # requires memcached 1.4+ diff --git a/Gemfile.lock b/Gemfile.lock index 60774e5e0e..d07a39f9c1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -344,6 +344,8 @@ GEM nokogiri (>= 1.5.9) mail (2.6.6) mime-types (>= 1.16, < 4) + meta-tags (2.4.1) + actionpack (>= 3.2.0, < 5.2) method_source (0.8.2) mime-types (2.99.3) mini_portile2 (2.2.0) @@ -655,6 +657,7 @@ DEPENDENCIES launchy (~> 2.4.3) letter_opener livingstyleguide (~> 2.0.1) + meta-tags (~> 2.4.1) multi_json (~> 1.12.1) mysql2 (~> 0.4.4) net-ldap (~> 0.16.0) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8362d15cd4..2c41e96e51 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -420,7 +420,6 @@ module ApplicationHelper if args.empty? title << h(@project.name) if @project title += @html_title if @html_title - title << h(Setting.app_title) else @html_title ||= [] @html_title += args diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index 72d13d7cda..7c8370f52a 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -30,10 +30,10 @@ See doc/COPYRIGHT.rdoc for more details. - <%= html_title %> - - + + <%= display_meta_tags site: Setting.app_title, title: html_title %> + diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb index fcec539a27..12d91b262a 100644 --- a/app/views/wiki/show.html.erb +++ b/app/views/wiki/show.html.erb @@ -33,6 +33,11 @@ See doc/COPYRIGHT.rdoc for more details. <% else %> <% title = h(@page.title) %> <% end %> + +<%# Set meta tags %> +<% title "#{t(:project_module_wiki)} | #{title}" %> +<% description strip_tags(format_text(@content, :text)) %> + <%= toolbar title: title, html: {class: '-with-dropdown'} do %> <% if @editable %> <% if User.current.allowed_to? :edit_wiki_pages, @project %> From 6af0ee6efa4daa491f6c8660b57973204fef19ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 22 Aug 2017 09:20:38 +0200 Subject: [PATCH 04/14] [26163] Skip activation of edit field on link click (#5869) Avoids a race condition that causes an internal error message on FF. https://community.openproject.com/wp/26163 [ci skip] --- .../wp-edit-field/wp-edit-field.directive.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/wp-edit/wp-edit-field/wp-edit-field.directive.ts b/frontend/app/components/wp-edit/wp-edit-field/wp-edit-field.directive.ts index cc3211d72d..88732f63f8 100644 --- a/frontend/app/components/wp-edit/wp-edit-field/wp-edit-field.directive.ts +++ b/frontend/app/components/wp-edit/wp-edit-field/wp-edit-field.directive.ts @@ -126,8 +126,19 @@ export class WorkPackageEditFieldController { } public handleUserActivate(evt:JQueryEventObject|null) { - // Get the position where the user clicked. - const positionOffset = evt ? ClickPositionMapper.getPosition(evt) : 0; + let positionOffset = 0; + + if (evt) { + // Skip activation if the user clicked on a link + const target = jQuery(evt.target); + + if (target.closest('a', this.displayContainer[0]).length > 0) { + return true; + } + + // Get the position where the user clicked. + positionOffset = ClickPositionMapper.getPosition(evt); + } this.activate() .then((handler) => { @@ -135,6 +146,8 @@ export class WorkPackageEditFieldController { const input = handler.element.find('input'); ClickPositionMapper.setPosition(input, positionOffset); }); + + return false; } public get displayContainer() { From 48a44978392f498bfd42ada8a3ea7d8d44475dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 22 Aug 2017 10:13:11 +0200 Subject: [PATCH 05/14] [26168] Fix removal of mousemove handler by timeline cell (#5870) https://community.openproject.com/wp/26168 [ci skip] --- .../cells/wp-timeline-cell-mouse-handler.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/frontend/app/components/wp-table/timeline/cells/wp-timeline-cell-mouse-handler.ts b/frontend/app/components/wp-table/timeline/cells/wp-timeline-cell-mouse-handler.ts index a467def57e..d4882b0af0 100644 --- a/frontend/app/components/wp-table/timeline/cells/wp-timeline-cell-mouse-handler.ts +++ b/frontend/app/components/wp-table/timeline/cells/wp-timeline-cell-mouse-handler.ts @@ -94,7 +94,7 @@ export function registerWorkPackageMouseHandler(this: void, // add/remove css class while drag'n'drop is active const classNameActiveDrag = 'active-drag'; bar.classList.add(classNameActiveDrag); - jBody.on('mouseup', () => bar.classList.remove(classNameActiveDrag)); + jBody.on('mouseup.timelinecell', () => bar.classList.remove(classNameActiveDrag)); workPackageTimeline.disableViewParamsCalculation = true; mouseDownStartDay = getCursorOffsetInDaysFromLeft(renderInfo, ev); @@ -108,9 +108,9 @@ export function registerWorkPackageMouseHandler(this: void, // Determine what attributes of the work package should be changed const direction = renderer.onMouseDown(ev, null, renderInfo, labels, bar); - jBody.on('mousemove', createMouseMoveFn(direction)); - jBody.on('keyup', keyPressFn); - jBody.on('mouseup', () => deactivate(false)); + jBody.on('mousemove.timelinecell', createMouseMoveFn(direction)); + jBody.on('keyup.timelinecell', keyPressFn); + jBody.on('mouseup.timelinecell', () => deactivate(false)); } function createMouseMoveFn(direction:'left' | 'right' | 'both' | 'create' | 'dragright') { @@ -186,7 +186,7 @@ export function registerWorkPackageMouseHandler(this: void, deactivate(false); }; - jBody.on('keyup', keyPressFn); + jBody.on('keyup.timelinecell', keyPressFn); }; } @@ -199,9 +199,7 @@ export function registerWorkPackageMouseHandler(this: void, cell.onmouseup = _.noop; bar.style.pointerEvents = 'auto'; - jBody.off('mouseup'); - jBody.off('mousemove'); - jBody.off('keyup'); + jBody.off('.timelinecell'); jQuery('.hascontextmenu').css('cursor', 'context-menu'); jQuery('.' + timelineElementCssClass).css('cursor', ''); jQuery('.' + classNameLeftHandle).css('cursor', 'w-resize'); From 37ac1b8d221cdb5874f6723550ce9900274a93e6 Mon Sep 17 00:00:00 2001 From: Markus Kahl Date: Fri, 11 Aug 2017 13:45:54 +0100 Subject: [PATCH 06/14] added after_login redirect URL configurations --- app/controllers/concerns/redirect_after_login.rb | 16 ++++++++++++++-- config/configuration.yml.example | 4 ++++ lib/open_project/configuration.rb | 3 +++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/controllers/concerns/redirect_after_login.rb b/app/controllers/concerns/redirect_after_login.rb index 63f940033d..242240e6bd 100644 --- a/app/controllers/concerns/redirect_after_login.rb +++ b/app/controllers/concerns/redirect_after_login.rb @@ -33,7 +33,7 @@ module Concerns::RedirectAfterLogin def redirect_after_login(user) if user.first_login user.update_attribute(:first_login, false) - redirect_to home_url(first_time_user: true) + first_login_redirect else default_redirect end @@ -42,6 +42,18 @@ module Concerns::RedirectAfterLogin # * * * def default_redirect - redirect_back_or_default controller: '/my', action: 'page' + if url = OpenProject::Configuration.after_login_default_redirect_url + redirect_to url + else + redirect_back_or_default controller: '/my', action: 'page' + end + end + + def first_login_redirect + if url = OpenProject::Configuration.after_first_login_redirect_url + redirect_to url + else + redirect_to home_url(first_time_user: true) + end end end diff --git a/config/configuration.yml.example b/config/configuration.yml.example index 9a3c2181bb..b83bbceb53 100644 --- a/config/configuration.yml.example +++ b/config/configuration.yml.example @@ -344,6 +344,10 @@ default: # Uncomment the following line to restrict APIv3 access to session. # apiv3_enable_basic_auth: false + # You can configure where users should be sent after the login + # after_login_default_redirect_url: '/my/page' + # after_first_login_redirect_url: '/projects/demo' + # specific configuration options for production environment # that overrides the default ones diff --git a/lib/open_project/configuration.rb b/lib/open_project/configuration.rb index da10325e47..e667356217 100644 --- a/lib/open_project/configuration.rb +++ b/lib/open_project/configuration.rb @@ -106,6 +106,9 @@ module OpenProject 'health_checks_jobs_queue_count_threshold' => 50, # Maximum number of minutes that jobs have not yet run after their designated 'run_at' time 'health_checks_jobs_never_ran_minutes_ago' => 5, + + 'after_login_default_redirect_url' => nil, + 'after_first_login_redirect_url' => nil } @config = nil From 3da8cf8470c770ef391d10cbbe0d22b63178184a Mon Sep 17 00:00:00 2001 From: Markus Kahl Date: Fri, 11 Aug 2017 14:36:38 +0100 Subject: [PATCH 07/14] support first time user modal everywhere --- app/views/homescreen/index.html.erb | 6 ------ app/views/layouts/base.html.erb | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/views/homescreen/index.html.erb b/app/views/homescreen/index.html.erb index 3c94cb5afe..db8fd0c9b7 100644 --- a/app/views/homescreen/index.html.erb +++ b/app/views/homescreen/index.html.erb @@ -34,12 +34,6 @@ See doc/COPYRIGHT.rdoc for more details. -<% if show_onboarding_modal? %> - - <%= render partial: '/onboarding/starting_video_modal' %> - -<% end %> - <%= render partial: 'announcements/show' %> <% if @homescreen[:blocks].any? %> diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index 7c8370f52a..786850099b 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -141,6 +141,11 @@ See doc/COPYRIGHT.rdoc for more details. <% end %> <%= render_flash_messages %> + <% if show_onboarding_modal? %> + + <%= render partial: '/onboarding/starting_video_modal' %> + + <% end %>

<%= l(:label_content) %>

From f57880b81e7265f643709a61c7aad67e0295b1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 22 Aug 2017 13:12:30 +0200 Subject: [PATCH 08/14] Remove let from js [ci skip] --- app/assets/javascripts/colors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/colors.js b/app/assets/javascripts/colors.js index d71b3777d2..ff57ef4531 100644 --- a/app/assets/javascripts/colors.js +++ b/app/assets/javascripts/colors.js @@ -44,7 +44,7 @@ } func = function () { - let previewColor = ''; + var previewColor = ''; if(input.val() && input.val().length > 0) { previewColor = input.val(); From cdd0f9031543848ef39066a9866a34e21e6d53cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 22 Aug 2017 13:19:06 +0200 Subject: [PATCH 09/14] Fix escaping empty html --- .../field-types/wp-display-formattable-field.module.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/app/components/wp-display/field-types/wp-display-formattable-field.module.ts b/frontend/app/components/wp-display/field-types/wp-display-formattable-field.module.ts index 86c0fd9f3c..1c50cb4172 100644 --- a/frontend/app/components/wp-display/field-types/wp-display-formattable-field.module.ts +++ b/frontend/app/components/wp-display/field-types/wp-display-formattable-field.module.ts @@ -66,6 +66,10 @@ export class FormattableDisplayField extends DisplayField { // Escape the given HTML string from the backend, which contains escaped Angular expressions. // Since formattable fields are only binded to but never evaluated, we can safely remove these expressions. protected unescape(html:string) { - return this.ExpressionService.unescape(html); + if (html) { + return this.ExpressionService.unescape(html); + } else { + return ''; + } } } From d1fd8dad18ed5e4e6a6169fb00fc5722db1fe05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 22 Aug 2017 14:53:10 +0200 Subject: [PATCH 10/14] Casted CF value filter returns <= where it should return >= (#5871) [ci skip] --- app/models/queries/operators/casted_greater_or_equal.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/queries/operators/casted_greater_or_equal.rb b/app/models/queries/operators/casted_greater_or_equal.rb index af577a6866..e2e439a2e1 100644 --- a/app/models/queries/operators/casted_greater_or_equal.rb +++ b/app/models/queries/operators/casted_greater_or_equal.rb @@ -34,7 +34,7 @@ module Queries::Operators def self.sql_for_field(values, db_table, db_field) "#{db_table}.#{db_field} != '' " + - "AND CAST(#{db_table}.#{db_field} AS decimal(60,4)) <= #{values.first.to_f}" + "AND CAST(#{db_table}.#{db_field} AS decimal(60,4)) >= #{values.first.to_f}" end end end From a5b53bd2743860e0e54827b6edbddc3811ec3fb4 Mon Sep 17 00:00:00 2001 From: CI Date: Wed, 23 Aug 2017 00:50:01 +0000 Subject: [PATCH 11/14] Update reference to OpenProject-Translations --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index d07a39f9c1..2abe62f794 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,7 +60,7 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: d12a3d0ed38138d2cdbf4d8a547b02b170db36b4 + revision: 21ec9f71d2979909b427b94fb73ababbfff99e55 branch: release/7.2 specs: openproject-translations (7.2.2) From c683ec725eab2952d77c949b247826b2df96c573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 23 Aug 2017 07:52:00 +0200 Subject: [PATCH 12/14] Bundling with next version on release branch --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2abe62f794..55e8adba3d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,10 +60,10 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: 21ec9f71d2979909b427b94fb73ababbfff99e55 + revision: 6c5ffada972fa05a43a361444da744511b4e7fad branch: release/7.2 specs: - openproject-translations (7.2.2) + openproject-translations (7.2.3) crowdin-api (~> 0.4.1) mixlib-shellout (~> 2.1.0) rails (~> 5.0.0) From 429f1d004694e1329c8031fcc67745a58039698d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 23 Aug 2017 07:52:00 +0200 Subject: [PATCH 13/14] Bump VERSION to 7.2.3 --- lib/open_project/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index 4da16d481d..0862202c98 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -34,7 +34,7 @@ module OpenProject module VERSION #:nodoc: MAJOR = 7 MINOR = 2 - PATCH = 2 + PATCH = 3 TINY = PATCH # Redmine compat # Used by semver to define the special version (if any). From e6db31c37d95243093b97a7e44de711d92410148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 23 Aug 2017 07:53:45 +0200 Subject: [PATCH 14/14] Run npm install on travis at all times (#5872) Otherwise, downstream repos will fail on a lot of spec runs due to foundation still being accessed. [ci skip] --- script/ci_setup.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/script/ci_setup.sh b/script/ci_setup.sh index 6bd5d2ac1c..7065aea2ed 100644 --- a/script/ci_setup.sh +++ b/script/ci_setup.sh @@ -55,13 +55,13 @@ if [ $1 != 'npm' ]; then run "bundle exec rake db:migrate" fi -if [ $1 != 'specs' ] && [ $1 != 'spec_legacy' ]; then - # We need npm 4.0 for a bugfix in cross-platform shrinkwrap - # https://github.com/npm/npm/issues/14042 - run "npm install npm@4.0" +# We need npm 4.0 for a bugfix in cross-platform shrinkwrap +# https://github.com/npm/npm/issues/14042 +run "npm install npm@4.0" - run "for i in {1..3}; do npm install && break || sleep 15; done" +run "for i in {1..3}; do npm install && break || sleep 15; done" +if [ $1 != 'specs' ] && [ $1 != 'spec_legacy' ]; then run "bundle exec rake assets:precompile" else # fake result of npm/asset run