[29130] Documents: Remove angularjs collapsible section and fix group_by

AngularJS wasn't activated for the documents collapsible-section.
Instead, refactor it into a augmented component with a rails helper to render it.

https://community.openproject.com/wp/29130
pull/6887/head
Oliver Günther 6 years ago
parent 0015ac900e
commit 7d262955ed
No known key found for this signature in database
GPG Key ID: A3A8BDAD7C0C552C
  1. 46
      app/helpers/augmenting_helper.rb
  2. 6
      app/views/augmented/_collapsible_section.html.erb
  3. 66
      frontend/src/app/modules/common/collapsible-section/collapsible-section.component.ts
  4. 15
      frontend/src/app/modules/common/collapsible-section/collapsible-section.html
  5. 3
      frontend/src/app/modules/common/openproject-common.module.ts
  6. 24
      modules/documents/app/controllers/documents_controller.rb
  7. 25
      modules/documents/app/views/documents/index.html.erb
  8. 3
      modules/documents/config/locales/en.yml
  9. 7
      modules/documents/spec/controllers/documents_controller_spec.rb

@ -0,0 +1,46 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# 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-2017 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.
#++
module AugmentingHelper
##
# Create a collapsible section and yield to render the block
#
# @param title [String] Section title
#
# @param initiallyExpanded [Boolean] Whether the section is initially expanded
#
# @param block [Block] A block that renders the section's body.
def augmented_collapsible_section(title:, initiallyExpanded: true, &block)
render(
partial: '/augmented/collapsible_section',
locals: { title: title, initiallyExpanded: !!initiallyExpanded, block: block }
)
end
end

@ -0,0 +1,6 @@
<collapsible-section-augment initially-expanded="<%= initiallyExpanded %>"
section-title="<%= title %>">
</collapsible-section-augment>
<div class="collapsible-section-augment--body" hidden>
<%= capture(&block) %>
</div>

@ -0,0 +1,66 @@
// -- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// 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 doc/COPYRIGHT.rdoc for more details.
// ++
import {Component, ElementRef, OnInit, ViewChild} from "@angular/core";
import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper";
export const collapsibleSectionAugmentSelector = 'collapsible-section-augment';
@Component({
selector: collapsibleSectionAugmentSelector,
templateUrl: './collapsible-section.html'
})
export class CollapsibleSectionComponent implements OnInit {
public expanded:boolean = false;
public sectionTitle:string;
@ViewChild('sectionBody') public sectionBody:ElementRef;
constructor(public elementRef:ElementRef) {
}
ngOnInit():void {
const element:HTMLElement = this.elementRef.nativeElement;
this.sectionTitle = element.getAttribute('section-title')!;
if (element.getAttribute('initially-expanded') === 'true') {
this.expanded = true;
}
const target:HTMLElement = element.nextElementSibling as HTMLElement;
this.sectionBody.nativeElement.appendChild(target);
target.removeAttribute('hidden');
}
public toggle() {
this.expanded = !this.expanded;
}
}
DynamicBootstrapper.register({ selector: collapsibleSectionAugmentSelector, cls: CollapsibleSectionComponent });

@ -0,0 +1,15 @@
<section class="collapsible-section"
[ngClass]="{ '-expanded': expanded }">
<accessible-by-keyboard (execute)="toggle()"
[linkAriaLabel]="sectionTitle"
linkClass="collapsible-section--toggle-link"
spanClass="collapsible-section--legend">
<span [textContent]="sectionTitle"></span>
</accessible-by-keyboard>
<div class="collapsible-section--body toggle-slide-animation"
#sectionBody
[hidden]="!expanded">
<!-- Wrapped by component -->
</div>
</section>

@ -68,6 +68,7 @@ import {TimezoneService} from 'core-components/datetime/timezone.service';
import {UIRouterModule} from "@uirouter/angular";
import {PortalModule} from "@angular/cdk/portal";
import {CommonModule} from "@angular/common";
import {CollapsibleSectionComponent} from "core-app/modules/common/collapsible-section/collapsible-section.component";
export function bootstrapModule(injector:Injector) {
return () => {
@ -162,6 +163,7 @@ export function bootstrapModule(injector:Injector) {
// Add functionality to rails rendered templates
CopyToClipboardDirective,
CollapsibleSectionComponent,
CopyToClipboardDirective,
ColorsAutocompleter,
@ -186,6 +188,7 @@ export function bootstrapModule(injector:Injector) {
OPContextMenuComponent,
ZenModeButtonComponent,
CollapsibleSectionComponent,
],
providers: [
{ provide: APP_INITIALIZER, useFactory: bootstrapModule, deps: [Injector], multi: true },

@ -39,18 +39,20 @@ class DocumentsController < ApplicationController
before_action :authorize
def index
@sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
@group_by = %w(category date title author).include?(params[:group_by]) ? params[:group_by] : 'category'
documents = @project.documents
case @sort_by
when 'date'
@grouped = documents.group_by {|d| d.updated_on.to_date }
when 'title'
@grouped = documents.group_by {|d| d.title.first.upcase}
when 'author'
@grouped = documents.with_attachments.group_by {|d| d.attachments.last.author}
else
@grouped = documents.includes(:category).group_by(&:category)
end
@grouped =
case @group_by
when 'date'
documents.group_by {|d| d.updated_on.to_date }
when 'title'
documents.group_by {|d| d.title.first.upcase}
when 'author'
documents.with_attachments.group_by {|d| d.attachments.last.author}
else
documents.includes(:category).group_by(&:category)
end
render layout: false if request.xhr?
end

@ -51,36 +51,35 @@ See doc/COPYRIGHT.rdoc for more details.
<% end %>
<% @grouped.keys.sort.each do |group| %>
<collapsible-section initially-expanded="true"
section-title="<%= group %>">
<%= augmented_collapsible_section title: group do %>
<div class="document-category--inner-section">
<div class="form--field document-category-elements">
<%= render :partial => 'documents/document', :collection => @grouped[group] %>
</div>
</div>
</collapsible-section>
<% end %>
<% end %>
<% content_for :sidebar do %>
<%= form_tag({}, :method => :get, class: 'sidebar--document-sort') do %>
<fieldset class="form--fieldset">
<legend class="form--fieldset-legend"><%= l(:label_sort_by, '') %></legend>
<legend class="form--fieldset-legend"><%= l(:label_group_by, '') %></legend>
<p>
<%= radio_button_tag 'sort_by', 'category', (@sort_by == 'category'), class: 'submit-this-form' %>
<label for="sort_by_category">
<%= radio_button_tag 'group_by', 'category', (@group_by == 'category'), class: 'submit-this-form' %>
<label for="group_by_category">
<%= Document.human_attribute_name(:category) %>
</label><br />
<%= radio_button_tag 'sort_by', 'date', (@sort_by == 'date'), class: 'submit-this-form' %>
<label for="sort_by_date">
<%= radio_button_tag 'group_by', 'date', (@group_by == 'date'), class: 'submit-this-form' %>
<label for="group_by_date">
<%= l(:label_date) %>
</label><br />
<%= radio_button_tag 'sort_by', 'title', (@sort_by == 'title'), class: 'submit-this-form' %>
<label for="sort_by_title">
<%= radio_button_tag 'group_by', 'title', (@group_by == 'title'), class: 'submit-this-form' %>
<label for="group_by_title">
<%= Document.human_attribute_name(:title) %>
</label><br />
<%= radio_button_tag 'sort_by', 'author', (@sort_by == 'author'), class: 'submit-this-form' %>
<label for="sort_by_author">
<%= Document.human_attribute_name(:author) %>
<%= radio_button_tag 'group_by', 'author', (@group_by == 'author'), class: 'submit-this-form' %>
<label for="group_by_author">
<%= t 'documents.attachment_author' %>
</label>
</p>
</fieldset>

@ -44,6 +44,9 @@ en:
specification: Specification
other: Other
documents:
label_attachment_author: "Attachment author"
label_document_added: "Document added"
label_document_new: "New document"
label_document_plural: "Documents"

@ -86,10 +86,9 @@ describe DocumentsController do
end
it "should render documents with long descriptions properly" do
expect(response.body).to have_css('.wiki p')
expect(response.body).to have_css('.wiki p', text: (document.description.split("\n").first + '...'))
expect(response.body).to have_css('.wiki p', text: /EndOfLineHere.../)
expect(response.body).to have_selector('.wiki p', visible: :all)
expect(response.body).to have_selector('.wiki p', visible: :all, text: (document.description.split("\n").first + '...'))
expect(response.body).to have_selector('.wiki p', visible: :all, text: /EndOfLineHere.../)
end
end

Loading…
Cancel
Save