diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 6478533f0c..c4b6629b0d 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -79,7 +79,6 @@
#= require visual/ajax_spinner
#= require visual/button
#= require visual/colorbox
-#= require visual/details
#= require visual/iframe
#= require visual/input_enforcement
#= require visual/mobile_nav
diff --git a/app/assets/javascripts/models/library/libraries.js.coffee b/app/assets/javascripts/models/library/libraries.js.coffee
index 206b1e04a1..07b30e1c8d 100644
--- a/app/assets/javascripts/models/library/libraries.js.coffee
+++ b/app/assets/javascripts/models/library/libraries.js.coffee
@@ -20,21 +20,20 @@ You should have received a copy of the GNU Affero General Public License
along with Fairmondo. If not, see .
###
-# This function copies the first two comments to the comment preview for a given commentable (library)
-#
-document.Fairmondo.copyCommentsToPreview = (commentable_selector) ->
- commentable = $(commentable_selector)
- first_two_comments = $(commentable_selector + ".Comments-section .Comment-single:lt(2)").clone()
- preview_element = $(commentable_selector + '.Library-comments')
- preview_element.html(first_two_comments)
-
$(document).always ->
- $('.js-library-settings').hide()
- $('.js-library-show-settings').click (e) =>
- $(e.target).parent().parent().find('.js-library-settings').show()
- $(e.target).hide()
+ # Hide edit section per default (not doing this per CSS because our
+ # current test suite doesn't support JavaScript
+ $('.library-edit-settings').hide()
+
+ # Show edit section when button is clicked
+ $('.js-library-edit-trigger').click (e) ->
+ $(e.target).siblings('.library-edit-settings').slideToggle('fast')
+ false
+
+ # Scroll to and focus on new library form in library index view
$('#library-form-link a').click ->
- $('html, body').animate
- scrollTop: $('#library-form').offset().top, 'slow'
- $('#new_library_name').focus()
+ $('html, body').animate(
+ { scrollTop: $('#library-form').offset().top }, ->
+ $('#new_library_name').focus()
+ )
diff --git a/app/assets/javascripts/vendor/jquery.socialshareprivacy.js b/app/assets/javascripts/vendor/jquery.socialshareprivacy.js
index 0b32f77554..b97dabfa47 100644
--- a/app/assets/javascripts/vendor/jquery.socialshareprivacy.js
+++ b/app/assets/javascripts/vendor/jquery.socialshareprivacy.js
@@ -151,7 +151,7 @@
if (facebook_on) {
var fb_enc_uri = encodeURIComponent(uri + options.services.facebook.referrer_track);
var fb_code = '';
- var fb_dummy_btn = '';
+ var fb_dummy_btn = '';
context.append('
' + fb_dummy_btn + '
');
@@ -184,7 +184,7 @@
var twitter_enc_uri = encodeURIComponent(uri + options.services.twitter.referrer_track);
var twitter_count_url = encodeURIComponent(uri);
var twitter_code = '';
- var twitter_dummy_btn = '';
+ var twitter_dummy_btn = '';
context.append('');
@@ -212,7 +212,7 @@
// we use the Google+ "asynchronous" code, standard code is flaky if inserted into dom after load
var gplus_code = '';
- var gplus_dummy_btn = '';
+ var gplus_dummy_btn = '';
context.append('' + gplus_dummy_btn + '
');
@@ -240,7 +240,7 @@
// we use the Google+ "asynchronous" code, standard code is flaky if inserted into dom after load
var pinterest_code = '';
- var pinterest_dummy_btn = '';
+ var pinterest_dummy_btn = '';
var pinterest_script = document.createElement('script');
pinterest_script.type = 'text/javascript';
pinterest_script.src='https://assets.pinterest.com/js/pinit.js';
diff --git a/app/assets/javascripts/visual/details.coffee b/app/assets/javascripts/visual/details.coffee
deleted file mode 100644
index 0dbaf21cd3..0000000000
--- a/app/assets/javascripts/visual/details.coffee
+++ /dev/null
@@ -1,6 +0,0 @@
-$(document).always ->
- $(".Library").click (e) ->
- if $(e.target).is('a, i')
- e.stopImmediatePropagation
- else
- window.location=$(this).find("a.library-link").attr("href")
diff --git a/app/assets/stylesheets/controller/articles.scss b/app/assets/stylesheets/controller/articles.scss
index 9374d977e0..bdff90ff0f 100644
--- a/app/assets/stylesheets/controller/articles.scss
+++ b/app/assets/stylesheets/controller/articles.scss
@@ -284,7 +284,7 @@ ul.category-selected-list {
}
}
-// Fragezeichen-Button
+// Questionmark button
#libraries_popup > span.sprite_helper {
position: absolute;
top: 0.5em;
@@ -314,7 +314,7 @@ ul.category-selected-list {
margin-right: 0.6em;
}
-// Formular
+// Form
#libraries_popup > .formtastic.library {
margin-top: 0.25em;
@@ -323,7 +323,7 @@ ul.category-selected-list {
float: left;
}
- // Plus-Button
+ // Plus button
.actions {
float: left;
margin: 0;
@@ -331,7 +331,7 @@ ul.category-selected-list {
}
-// Auge
+// Eye
#eye_checkbox {
color: $blue;
cursor: pointer;
@@ -340,7 +340,7 @@ ul.category-selected-list {
}
-// Textfeld
+// Input field
#library_name_input {
float: left;
margin: 0 0.2em;
@@ -358,7 +358,7 @@ ul.category-selected-list {
// article borrow / swap links
-// Link zu Sammlungen
+// Link to libraries
#libraries_popup > #libraries_links {
padding: 0.75em 0 0 0;
margin: 0;
diff --git a/app/assets/stylesheets/controller/categories.scss b/app/assets/stylesheets/controller/categories.scss
new file mode 100644
index 0000000000..95d5c31094
--- /dev/null
+++ b/app/assets/stylesheets/controller/categories.scss
@@ -0,0 +1,11 @@
+@import "mixins/all";
+
+.libraries {
+ clear: both;
+ margin: 1em 0;
+ overflow: hidden;
+
+ h2 {
+ font-weight: 600;
+ }
+}
diff --git a/app/assets/stylesheets/controller/libraries.scss b/app/assets/stylesheets/controller/libraries.scss
index 4865c30851..a3264c240b 100644
--- a/app/assets/stylesheets/controller/libraries.scss
+++ b/app/assets/stylesheets/controller/libraries.scss
@@ -1,8 +1,26 @@
@import "mixins/all";
+h1 {
+ font-size: 1.5em;
+ font-weight: 600;
+ margin: 0.5em 0;
+}
+
+h2 {
+ font-size: 1em;
+ font-weight: 600;
+}
+
+h3 {
+ font-size: 1em;
+}
+
+
+/******************************** Index view **********************************/
+
#library-form {
@include whitebox;
- margin-bottom: 1em;
+ margin: 1em 0;
clear: both;
}
@@ -11,8 +29,115 @@
text-align: right;
}
+
.libraries {
clear: both;
border-top: 0.1em solid $lighter-gray;
padding-top: 1em;
}
+
+.pagination {
+ clear: both;
+}
+
+
+/******************************** Show view ***********************************/
+
+.library-header {
+ overflow: hidden;
+}
+
+.library-header-owner {
+ float: left;
+ overflow: hidden;
+ margin: 0.5em 0;
+ color: $black;
+
+ a {
+ text-transform: uppercase;
+ }
+
+ img {
+ display: block;
+ float: left;
+ width: 20px;
+ height: 20px;
+ margin-right: 0.5em;
+ margin-bottom: -4px;
+ }
+}
+
+.library-header-owner > .wrapper {
+ float: left;
+}
+
+
+.library-header-owner-by,
+.library-header-owner-name {
+
+}
+
+.library-header-title {
+ clear: left;
+ float: left;
+
+ small {
+ font-size: 0.8em;
+ }
+}
+
+.library-header-title-visibility {
+ color: $secondary-color;
+}
+
+.library-actions {
+ float: right;
+ margin: 0.4em 0 0 1em;
+ overflow: hidden;
+}
+
+.library-body {
+ clear: both;
+ margin-top: 1em;
+}
+
+.library-edit,
+.library-admin {
+ margin: 0.5em 0;
+ padding: 1em;
+ background-color: $lighter-gray;
+}
+
+.library-admin {
+ clear: both;
+ margin-top: 1em;
+}
+
+// Set to display:none once testing JavaScript works
+.library-edit-settings {
+ display: block;
+}
+
+.morelibraries {
+ margin-top: 2em;
+}
+
+
+/******************************* Breakpoints *********************************/
+
+// tablet
+@include at-breakpoint($bp-tablet) {
+ .library-header-owner {
+ img {
+ margin-right: 1em;
+ margin-bottom: 5px;
+ width: 60px;
+ height: 60px;
+ }
+ }
+
+ .library-header-owner-by,
+ .library-header-owner-name {
+ display: block;
+ }
+}
diff --git a/app/assets/stylesheets/controller/welcome.scss b/app/assets/stylesheets/controller/welcome.scss
index 54dff76b92..448902b25c 100644
--- a/app/assets/stylesheets/controller/welcome.scss
+++ b/app/assets/stylesheets/controller/welcome.scss
@@ -431,9 +431,7 @@
-/*
- * Responsive stuff
- */
+/******************************** Breakpoints *********************************/
// mobile-horizontal
@@ -572,7 +570,6 @@
}
}
-
// Remove one article from a teaser for layout reasons
.teaser--reducible .teaser-queue {
&:first-child {
diff --git a/app/assets/stylesheets/layout/_fonts.scss b/app/assets/stylesheets/layout/_fonts.scss
index 8f92f6feac..b379c28af8 100644
--- a/app/assets/stylesheets/layout/_fonts.scss
+++ b/app/assets/stylesheets/layout/_fonts.scss
@@ -59,7 +59,7 @@
* Italics
*/
-/*
+
@font-face {
font-family: 'Open Sans';
font-weight: 400;
@@ -70,7 +70,7 @@
font-url('opensans/OpenSans-Italic-webfont.ttf') format('truetype'),
font-url('opensans/OpenSans-Italic-webfont.svg#open_sansitalic') format('svg');
}
-*/
+
@font-face {
font-family: 'Open Sans';
diff --git a/app/assets/stylesheets/mixins/_variables.scss b/app/assets/stylesheets/mixins/_variables.scss
index ee092d50fe..b5764fcf92 100644
--- a/app/assets/stylesheets/mixins/_variables.scss
+++ b/app/assets/stylesheets/mixins/_variables.scss
@@ -15,6 +15,7 @@ $xsmall-font-size: 0.7em;
// colors
$blue: #428ebd;
+$secondary-color: #DA5230;
$green: #718b46;
$turquoise-green: #3ac25d;
$gray: #909090;
diff --git a/app/assets/stylesheets/modules/_comments.scss b/app/assets/stylesheets/modules/_comments.scss
index fe78c681e9..0e3228ac10 100644
--- a/app/assets/stylesheets/modules/_comments.scss
+++ b/app/assets/stylesheets/modules/_comments.scss
@@ -34,6 +34,15 @@
margin-right: 0.6em;
}
+.Comments-section {
+ margin: 2em 0 1em;
+}
+
+.Comments-section h2 {
+ font-weight: 600;
+ font-size: 1em;
+}
+
.Comments-section form li.input {
list-style: none;
overflow: visible !important;
@@ -46,9 +55,13 @@
}
.Comments-count {
- margin-right: 0.5em;
- > i.fa {
- font-size: 1.2rem;
+ float: left;
+
+ em {
+ margin-left: 0.3em;
+ color: $secondary-color;
+ font-size: 1em;
+ line-height: 2em;
}
}
diff --git a/app/assets/stylesheets/modules/_hearts.scss b/app/assets/stylesheets/modules/_hearts.scss
index 720e296085..2456682eab 100644
--- a/app/assets/stylesheets/modules/_hearts.scss
+++ b/app/assets/stylesheets/modules/_hearts.scss
@@ -1,15 +1,12 @@
-div[class$="-hearts"] {
- float: right;
-
- > i.fa-heart, i-fa-heart-o {
- font-size: 1.2rem;
- }
-
+.Hearts-button {
+ margin-right: 1.5em;
+ float: left;
+ color: $light-gray;
}
-.Hearts-button {
- position: relative;
- i.fa-heart, i.fa-heart-o {
- font-size: 1.2rem;
- }
+.Hearts-button em {
+ margin-left: 0.1em;
+ font-size: 1em;
+ line-height: 2em;
+ color: $secondary-color;
}
diff --git a/app/assets/stylesheets/modules/_library.scss b/app/assets/stylesheets/modules/_library.scss
index 14b4ef98ee..b05fe8e01f 100644
--- a/app/assets/stylesheets/modules/_library.scss
+++ b/app/assets/stylesheets/modules/_library.scss
@@ -8,132 +8,123 @@ details.Library
Styleguide Library
*/
+
.Library {
- display: block;
margin-bottom: 1em;
- padding: 1em;
- // @include whitebox;
- border-radius: 0.5em;
- border: 1px solid $lighter-gray;
- box-shadow: $even-lighter-gray 0px 0px 2px 1px;
- &:hover {
- background-color: $even-lighter-gray;
- }
}
-/* Libraries that have been clicked on and are 'spread out' */
-.Library.open {
- summary {
- border-radius: 0.5em 0.5em 0 0;
- &:hover {
- background-color: $even-lighter-gray;
- }
+.Library-wrapper {
+ position: relative;
+ padding: 1em;
+ overflow: hidden;
+
+ background-color: $even-lighter-gray;
+ transition: background-color 0.2s;
+
+ &:hover, &:active {
+ background-color: #dce8f0;
}
}
-/* div tag containing all the articles of the library */
-.Library > .Library-details {
- padding: em(10) em(20);
+.Library-wrapper > a {
+ z-index: 10;
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
}
-/* smoother ajax start transition */
-.Library .Grid--wider {
- transition: opacity 0.2s;
-}
-/* Comments in the summary */
-.Library > summary > .Library-comments {
- margin-top: 0.6rem;
+.Library h3 {
+ font-size: 1em;
+ font-weight: 700;
+ margin: 0.25em 0 0.75em;
}
-.Library.open > summary > .Library-comments {
- display: none;
+.Library p {
+ margin: 0;
+ color: $mid-dark-gray;
+ font-size: 0.8em;
}
-
-/* Div that contains the comments counter and the heart button */
-.Library-buttons {
- float: right;
-
- > div {
- display: inline-block;
- }
+.Library-thumbnails {
+ overflow: hidden;
+ // Min height for libraries without elements
+ min-height: 2em;
}
-/* div containing the user image */
-.Library-userimage {
- display: none;
+.Library-thumbnails li {
float: left;
- margin-right: 1em;
- padding: 0.5em;
- background-color: white;
- border-radius: 0.6em;
+ position: relative;
+ width: percentage(1 / 3);
+ height: 0;
+ // Calc padding-bottom so that is has an aspect ratio of 13/9 like the
+ // thumbnail images
+ padding-bottom: percentage((1 / 3) / (13 / 9));
+ overflow: hidden;
+
img {
- height: 6.3em;
- width: 6.3em;
- }
- @include at-breakpoint($bp-tablet) {
- display: block;
+ box-sizing: border-box;
+ position: absolute;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 1px solid $light-gray;
+ border-left: none;
}
}
-/* The biggest part of the library header containing title, user and preview thumbnails */
-.Library-info {
- overflow: hidden;
+.Library-thumbnails li:first-child img {
+ border-left: 1px solid $light-gray;
}
-.Library-info > .Library-info-text {
- margin-bottom: 0.5em;
+.Library-footer {
+ margin-top: 0.5em;
}
-.Library-info > .Library-info-text > .Library-info-text-title {
- font-size: 1.5em;
+.Library-footer-articles {
+ float: left;
}
-.Library-info > .Library-info-text > .Library-info-text-user {
- font-weight: 600;
+.Library-footer-heartsandcomments {
+ float: right;
}
-.Library-info > .Library-info-thumbnails {
- height: 5.1em;
- overflow: hidden;
-
- img {
- height: 4.5em;
- padding: 0.3em;
- display: inline-block;
- margin-right: 0.2em;
- border-radius: 0.5em;
- background-color: white;
- }
+.Library-footer-auditing {
+ clear: both;
}
-/* Library-comments */
-.Library > .Library-comments {
- margin-top: 0.5em;
-}
-/* User-specific section, only exists if the library belongs to the user */
-.Library-details-user {
- clear: both;
- margin: em(10) em(20);
-}
+/******************************** Breakpoints *********************************/
-.Library-details-user > .Library-details-user-warning {
- color: $red;
+@include till-breakpoint($bp-mobile-horizontal) {
+ // Show only 3 thumbnails here
+ .Library-thumbnails li:nth-child(n+4)
+ {
+ display: none;
+ }
}
-.Library-details-user > .Library-details-user-actions {
- float: right;
- margin-bottom: 1em;
+@include at-breakpoint($bp-mobile-horizontal) {
+ // Show 4 images in a row
+ .Library-thumbnails li {
+ width: percentage(1 / 4);
+ padding-bottom: percentage((1 / 4) / (13 / 9));
+ }
}
-.Library-details-user > .Library-details-user-visibility {
- font-weight: 600;
-}
+@include at-breakpoint($bp-tablet) {
+ .Library {
+ @include span(6 of 12);
+ }
-/* Contains the article grid */
-.Library-elements {
- clear: both;
- margin-top: 10px;
+ .Library:nth-of-type(odd) {
+ clear: both;
+ }
+
+ .Library:nth-of-type(even) {
+ @include omega;
+ }
}
diff --git a/app/assets/stylesheets/vendor/socialshareprivacy.scss b/app/assets/stylesheets/vendor/socialshareprivacy.scss
index ca6be27de4..aefbb2642a 100644
--- a/app/assets/stylesheets/vendor/socialshareprivacy.scss
+++ b/app/assets/stylesheets/vendor/socialshareprivacy.scss
@@ -2,9 +2,11 @@
.socialshareprivacy {
- clear: both;
- float: right;
- margin: 10px 0 !important;
+ margin: 15px 0;
+}
+
+.socialshareprivacy i.fa {
+ color: $blue;
}
.social_share_privacy_area {
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
index 12d3de7718..a01dd6c5d9 100644
--- a/app/controllers/categories_controller.rb
+++ b/app/controllers/categories_controller.rb
@@ -22,6 +22,18 @@ def select_category
def show
authorize @category
+
+ @example_libraries = Library.for_category(@category.self_and_descendants)
+
+ # exclude user's own libraries if he is logged in
+ if user_signed_in?
+ @example_libraries = @example_libraries.where('libraries.user_id != ?',
+ current_user.id)
+ end
+
+ # random() should work with PostgreSQL and SQLite
+ @example_libraries = @example_libraries.reorder('random()').limit(2)
+
respond_with @category do |format|
format.html { articles }
format.js { articles }
@@ -30,7 +42,8 @@ def show
end
def collection
- @categories = Category.other_category_last.sorted.roots.includes(children: { children: { children: :children } })
+ @categories = Category.other_category_last.sorted.roots
+ .includes(children: { children: { children: :children } })
end
private
diff --git a/app/controllers/libraries_controller.rb b/app/controllers/libraries_controller.rb
index 321c9407b6..720b2ad9b5 100644
--- a/app/controllers/libraries_controller.rb
+++ b/app/controllers/libraries_controller.rb
@@ -52,6 +52,18 @@ def index
def show
authorize @library
+
+ @library_elements = @library.library_elements.active
+ .preload(article_reduced: [:title_image, :seller])
+ .page(params[:library_page])
+ .per(24)
+
+ # random() should work with PostgreSQL and SQLite
+ @user_libraries = @library.user.libraries.not_empty.published
+ .where('id != ?', @library.id)
+ .reorder('random()')
+ .limit(2)
+
respond_with @library do |format|
format.js
end
@@ -69,9 +81,9 @@ def create
def update
authorize @library
if @library.update(params.for(@library).refine)
- redirect_to user_libraries_path(current_user, anchor: "library#{@library.id}")
+ redirect_to library_path(@library)
else
- redirect_to user_libraries_path(current_user), alert: @library.errors.values.first.first
+ redirect_to library_path(@library), alert: @library.errors.values.first.first
end
end
diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb
index 1272aa168a..4658a651e5 100644
--- a/app/controllers/welcome_controller.rb
+++ b/app/controllers/welcome_controller.rb
@@ -32,7 +32,8 @@ def index
@donation_articles = query_object.set(:donation_articles).find(2)
# Libraries
- @trending_libraries = Library.trending_welcome_page.includes(user: [:image], comments: { user: [:image] })
+ @trending_libraries = Library.trending_welcome_page
+ .includes(user: [:image], comments: { user: [:image] })
# Personalized section
if user_signed_in?
diff --git a/app/helpers/libraries_helper.rb b/app/helpers/libraries_helper.rb
new file mode 100644
index 0000000000..8071a0c521
--- /dev/null
+++ b/app/helpers/libraries_helper.rb
@@ -0,0 +1,63 @@
+#
+#
+# == License:
+# Fairmondo - Fairmondo is an open-source online marketplace.
+# Copyright (C) 2013 Fairmondo eG
+#
+# This file is part of Fairmondo.
+#
+# Fairmondo is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# Fairmondo 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Fairmondo. If not, see .
+#
+#
+
+module LibrariesHelper
+ # Show range of paginated articles
+ # Also works for library elements
+ def article_range_str(paginated_articles)
+ case
+ when paginated_articles.total_count == 0
+ t('common.text.no_articles')
+ when paginated_articles.total_count == paginated_articles.size
+ "#{paginated_articles.total_count} "\
+ "#{t('common.text.articles')}".html_safe
+ when article_range_start_number < article_range_end_number(paginated_articles)
+ "#{t('common.text.article')} #{article_range_start_number}–"\
+ "#{article_range_end_number(paginated_articles)}"\
+ " #{t('common.text.glue_without_spaces.of')} "\
+ "#{paginated_articles.total_count}".html_safe
+ when article_range_start_number == article_range_end_number(paginated_article s)
+ "#{t('common.text.article')} #{article_range_start_number}"\
+ " #{t('common.text.glue_without_spaces.of')} "\
+ "#{paginated_articles.total_count}".html_safe
+ end
+ end
+
+ private
+
+ def article_range_page
+ params[:library_page] ? params[:library_page].to_i : 1
+ end
+
+ def article_range_offset(page)
+ (page - 1) * 24
+ end
+
+ def article_range_start_number
+ article_range_offset(article_range_page) + 1
+ end
+
+ def article_range_end_number(paginated_articles)
+ article_range_offset(article_range_page) + paginated_articles.size
+ end
+end
diff --git a/app/models/images/user_image.rb b/app/models/images/user_image.rb
index ed23c6d900..a9e6f5ab24 100644
--- a/app/models/images/user_image.rb
+++ b/app/models/images/user_image.rb
@@ -4,13 +4,17 @@ class UserImage < Image
:image,
styles: {
original: { geometry: '300>x300>', animated: false },
- profile: { geometry: '300x300>', animated: false }
+ profile: { geometry: '300x300>', format: :jpg, animated: false },
+ thumb: { geometry: '60x60#', format: :jpg, animated: false }
+ },
+ convert_options: {
+ profile: '-quality 75 -strip -background white -gravity center -extent 300x300',
+ thumb: '-quality 75 -strip -background white'
},
- convert_options: { profile: '-quality 75 -strip -background white -gravity center -extent 300x300' },
default_url: '/assets/missing.png',
url: '/system/images/:id_partition/:style/:filename',
path: 'public/system/images/:id_partition/:style/:filename',
- only_process: [:profile]
+ only_process: [:profile, :thumb]
)
belongs_to :user, foreign_key: 'imageable_id'
diff --git a/app/models/library.rb b/app/models/library.rb
index de50ee5d99..238c43a7a5 100644
--- a/app/models/library.rb
+++ b/app/models/library.rb
@@ -48,6 +48,7 @@ class Library < ActiveRecord::Base
has_many :hearts, as: :heartable
+ # Scopes
scope :not_empty, -> { where('libraries.library_elements_count > 0') }
scope :min_elem, -> (num) { where('libraries.library_elements_count >= ?', num) }
scope :published, -> { where(public: true) }
@@ -56,7 +57,15 @@ class Library < ActiveRecord::Base
scope :most_recent, -> { reorder(created_at: :desc) }
scope :trending, -> { most_popular.not_empty.published }
scope :audited, -> { where(audited: true) }
- scope :trending_welcome_page, -> { trending.audited.limit(3) }
+ scope :trending_welcome_page, -> { trending.audited.limit(2) }
+
+ # libraries with most of the articles belonging to one of the given categories
+ scope :for_category, (lambda do |categories|
+ joins(articles: :categories)
+ .where(categories: { id: categories }, public: true)
+ .group('libraries.id')
+ .having('count(*) > libraries.library_elements_count / 2')
+ end)
default_scope { order(updated_at: :desc) }
diff --git a/app/views/categories/show.html.slim b/app/views/categories/show.html.slim
index fec819784d..c38d33ca71 100644
--- a/app/views/categories/show.html.slim
+++ b/app/views/categories/show.html.slim
@@ -1,8 +1,20 @@
/ insert elements that should only appear when there is nothing specific here
- begin
- = render "categories/show/#{resource.slug}", search_cache: @search_cache if resource.slug
+ = render "categories/show/#{resource.slug}",
+ search_cache: @search_cache if resource.slug
+ - render_libraries = true
- rescue ActionView::MissingTemplate, ArgumentError
+ - render_libraries = true
/ Elements that always get displayed
-= render '/articles/shared/search_results', articles: @articles, search_cache: @search_cache
+= render '/articles/shared/search_results', articles: @articles,
+ search_cache: @search_cache
+
+/ Render matching library for category if there is any
+- if render_libraries && !@example_libraries.empty?
+ section.libraries
+ h2= t('libraries.of_category', category: @category.name)
+
+ = render partial: 'libraries/library', collection: @example_libraries,
+ locals: { piwik_campaign: 'libraries', piwik_keyword: 'category_page' }
diff --git a/app/views/comments/_commentable_comments.html.slim b/app/views/comments/_commentable_comments.html.slim
index 867c2c761f..dce2410506 100644
--- a/app/views/comments/_commentable_comments.html.slim
+++ b/app/views/comments/_commentable_comments.html.slim
@@ -1,5 +1,7 @@
- comments = commentable.comments unless local_assigns.has_key? :comments
-.Comments-section
+
+section.Comments-section#comments
+ h2= t('comments.comments')
- if policy(Comment.new commentable: commentable).create?
.comment-info-text= comments_additional_notice_for commentable
= render "comments/new", comment: Comment.new, commentable: commentable
@@ -12,12 +14,12 @@
t('comments.more'),
param_name: :comments_page,
params: { :"#{commentable.class.to_s.parameterize}_id" => commentable.id, controller: "comments" },
- class: "next_link",
+ class: 'next_link',
remote: true
- if commentable.comments_count > Comment.default_per_page
= link_to t('comments.all'),
comments_path(commentable),
- class: "all_link",
+ class: 'all_link',
remote: true
.Comments-report= t('comments.report_info')
- else
diff --git a/app/views/comments/_commentable_counter.html.slim b/app/views/comments/_commentable_counter.html.slim
index c5ff52a324..62e96d44bf 100644
--- a/app/views/comments/_commentable_counter.html.slim
+++ b/app/views/comments/_commentable_counter.html.slim
@@ -1,4 +1,4 @@
.Comments-count
- i.fa.fa-comments
- |
- = commentable.comments_count
+ = link_to '#comments', title: t("comments.jump_to") do
+ = fa_icon('comments 2x')
+ em= commentable.comments_count
diff --git a/app/views/comments/create.js.erb b/app/views/comments/create.js.erb
index 2e6abe0263..054cb44518 100644
--- a/app/views/comments/create.js.erb
+++ b/app/views/comments/create.js.erb
@@ -1,13 +1,9 @@
-commentable_selector = '<%= "##{@commentable.class.to_s.underscore}#{@commentable.id}" %> ';
+$('.Comments-section form').replaceWith($("<%= j render(partial: "new", locals: { comment: @new_comment, commentable: @commentable} ) %>"));
-$(commentable_selector + '.Comments-section form').replaceWith($("<%= j render(partial: "new", locals: { comment: @new_comment, commentable: @commentable} ) %>"));
+$('.Comments-section .Comments').prepend($("<%= j render(partial: "comments/comment", locals: {comment: @comment}) %>"));
-$(commentable_selector + '.Comments-section .Comments').prepend($("<%= j render(partial: "comments/comment", locals: {comment: @comment}) %>"));
+$('#comment_text').val('');
-$(commentable_selector + '#comment_text').val("");
+$('.Comments-empty').html('');
-$(commentable_selector + '.Comments-empty').html("");
-
-$(commentable_selector + '.Comments-count').replaceWith('<%= j comments_counter(@commentable) %>');
-
-document.Fairmondo.copyCommentsToPreview(commentable_selector)
+$('.Comments-count').replaceWith('<%= j comments_counter(@commentable) %>');
diff --git a/app/views/comments/destroy.js.erb b/app/views/comments/destroy.js.erb
index 3bdd0f3aa7..bebc6f3c25 100644
--- a/app/views/comments/destroy.js.erb
+++ b/app/views/comments/destroy.js.erb
@@ -1,6 +1,3 @@
-commentable_selector = '<%= "##{@commentable.class.to_s.underscore}#{@commentable.id}" %> ';
-
$('.commentable_<%= @commentable.id %>_comment_<%= @comment.id %>').remove();
-$(commentable_selector + '.Comments-count').replaceWith('<%= j comments_counter(@commentable) %>');
-document.Fairmondo.copyCommentsToPreview(commentable_selector)
+$('.Comments-count').replaceWith('<%= j comments_counter(@commentable) %>');
diff --git a/app/views/hearts/_heart_button.html.slim b/app/views/hearts/_heart_button.html.slim
index 2f420e7f49..261673bf0f 100644
--- a/app/views/hearts/_heart_button.html.slim
+++ b/app/views/hearts/_heart_button.html.slim
@@ -1,10 +1,8 @@
.Hearts-button
- if disabled
- span
- i.fa.fa-heart disabled='true'
+ = fa_icon('heart 2x')
- else
= link_to path, method: method, remote: true do
- i.fa*{ class: filled ? 'fa-heart' : 'fa-heart-o', disabled: disabled }
- |
- span.Hearts-count
+ = fa_icon(filled ? 'heart 2x' : 'heart-o 2x')
+ em
= heartable_resource.hearts_count
diff --git a/app/views/hearts/_update.js.erb b/app/views/hearts/_update.js.erb
index f5cd1e7f7d..1115b1f88f 100644
--- a/app/views/hearts/_update.js.erb
+++ b/app/views/hearts/_update.js.erb
@@ -1 +1 @@
-$('<%= "#library#{heartable.id}" %> .Hearts-button').replaceWith('<%= j heart_button(heartable) %>');
+$('.Hearts-button').replaceWith('<%= j heart_button(heartable) %>');
diff --git a/app/views/libraries/_library.html.slim b/app/views/libraries/_library.html.slim
index c72936188e..804ddfc62d 100644
--- a/app/views/libraries/_library.html.slim
+++ b/app/views/libraries/_library.html.slim
@@ -1,23 +1,79 @@
-/ Partial for showing a library
-- single_view = false unless local_assigns.has_key? :single_view
-- header_comments = true unless local_assigns.has_key? :header_comments
-- if single_view
- div id="library#{library.id.to_s}"
- = render "library_header", library: library, comments: false
-
- / Show social media buttons if it is a public library
- - if library.public?
- .socialshareprivacy data={ uri: library_url(library), title: library.name }
-
- = render "library_buttons", library: library
- = render "library_body", library: library, remote_paginate: false, element_count: 24
-- else
- - if library.has_elements? || (library.user == current_user)
- .Library id="library#{library.id}"
- = render "libraries/library_header", library: library, comments: header_comments
- /.Library-details
- / Show social media buttons if it is a public library
- - if library.public?
- .socialshareprivacy data={ uri: library_url(library), title: library.name }
-
- = render "libraries/library_buttons", library: library
+/ Partial for showing the summary of a library
+
+/ Locals
+- piwik_campaign = nil unless local_assigns.has_key?(:piwik_campaign)
+- piwik_keyword = nil unless local_assigns.has_key?(:piwik_keyword)
+- show_owner = true unless local_assigns.has_key?(:show_owner)
+- show_visibility = false unless local_assigns.has_key?(:show_visibility)
+
+- is_own_library = library.user == current_user
+
+- if library.has_elements? || is_own_library
+
+ section.Library id="library#{library.id.to_s}"
+
+ .Library-wrapper
+
+ - link_target = library_path(library,
+ pk_campaign: piwik_campaign, pk_kwd: piwik_keyword)
+
+ / Extra link to library so the whole area is clickable
+ = link_to '', link_target
+
+ / Header
+ h3= link_to library.name, link_target
+
+ / Main part
+ ul.Library-thumbnails
+ - library_elements = library.library_elements.active\
+ .preload(article_reduced: :title_image).first(4)
+
+ / Display items even if there are no images to maintain the same height
+ / for all displayed libraries
+ - library_elements.each do |library_element|
+ li
+ - if library_element.article_reduced
+ = image_tag library_element.article_reduced.title_image_url(:thumb),
+ title: library_element.article_reduced_title
+
+ / Footer
+ footer.Library-footer
+ - if !show_owner && is_own_library
+ p.Library-footer-visibility
+ = library.public? ? t('library.visibility.public')\
+ : t('library.visibility.private')
+
+ - if show_owner
+ p.Library-footer-from
+ / name of owner, special message if own library
+ - if is_own_library
+ => t('library.by_you')
+ - else
+ = t('common.text.glue.from')
+ => library.user_nickname
+
+ p.Library-footer-articles
+ - if library.library_elements_count != 0
+ => library.library_elements_count
+ = t('common.text.articles')
+ - else
+ = t('common.text.no_articles')
+
+ p.Library-footer-heartsandcomments
+ span
+ => fa_icon('heart')
+ = library.hearts_count
+ |
+ span
+ => fa_icon('comments')
+ = library.comments_count
+
+ / Audit button for admins
+ - if policy(library).admin_audit?
+ .Library-auditing
+ = link_to (library.audited\
+ ? t('library.auditing.welcome_page_enabled')\
+ : t('library.auditing.welcome_page_disabled')),
+ admin_audit_library_path(library),
+ class: "Button #{library.audited ? 'Button--green' : 'Button--red'}",
+ method: :patch, remote: true
diff --git a/app/views/libraries/_library_body.html.slim b/app/views/libraries/_library_body.html.slim
deleted file mode 100644
index a80481f99b..0000000000
--- a/app/views/libraries/_library_body.html.slim
+++ /dev/null
@@ -1,14 +0,0 @@
-- element_count = 6 unless local_assigns.has_key? :element_count
-.Library-elements
- .js-library-ajax
- - library_elements = library.library_elements.active.preload(article_reduced: :title_image).page(params[:library_page]).per(element_count)
- - if library_elements.to_a.any?
- .Grid--wider
- - library_elements.each do |library_element|
- .Grid-item
- = render "libraries/library_element", library_element: library_element
- = paginate library_elements, param_name: :library_page, remote: remote_paginate, params: { controller: "libraries", action: "show", id: library.id, _: nil }
- - else
- p= t('library.no_products')
-
- = render "comments/commentable_comments", commentable: library
diff --git a/app/views/libraries/_library_buttons.html.slim b/app/views/libraries/_library_buttons.html.slim
deleted file mode 100644
index 9b91e4b242..0000000000
--- a/app/views/libraries/_library_buttons.html.slim
+++ /dev/null
@@ -1,22 +0,0 @@
-- if policy(library).update?
- .Library-details-user
- - if library.on_welcome_page?
- p.Library-details-user-warning= t('library.auditing.user_warning')
- .Library-details-user-actions
- a.Button.js-library-show-settings
- = t('common.actions.edit')
- - if policy(library).destroy?
- = link_to t('common.actions.destroy') , user_library_path(library.user.id, library.id.to_s) , class: "Button Button--red", confirm: t('library.delete_confirm', name: library.name), method: :delete
- .Library-details-user-visibility
- - if library.public?
- = t 'library.visibility.public'
- - else
- = t 'library.visibility.private'
- .library-settings.js-library-settings
- = semantic_form_for(library, url: user_library_path(library.user.id, library.id.to_s),
- namespace: "library#{library.id.to_s}") do |f|
- = f.inputs do
- = f.input :name, required: false
- = f.input :public, label: false
- = f.actions do
- = f.action :submit, label: :update, button_html: { class: "Button"}
diff --git a/app/views/libraries/_library_element.html.slim b/app/views/libraries/_library_element.html.slim
deleted file mode 100644
index e14e40efb8..0000000000
--- a/app/views/libraries/_library_element.html.slim
+++ /dev/null
@@ -1,4 +0,0 @@
-- if policy(library_element).show?
- = render layout: 'articles/shared/show_article', locals: { article: library_element.article_reduced, extra: policy(library_element).destroy? } do
- - if policy(library_element).destroy?
- = link_to t('common.actions.destroy'), user_library_element_path(current_user,library_element) , method: :delete, class: "Button Button--red"
diff --git a/app/views/libraries/_library_header.html.slim b/app/views/libraries/_library_header.html.slim
deleted file mode 100644
index 52030bf866..0000000000
--- a/app/views/libraries/_library_header.html.slim
+++ /dev/null
@@ -1,32 +0,0 @@
-- comments = true unless local_assigns.has_key? :comments
-
-.Library-buttons
- = comments_counter(library)
- = heart_button(library)
-.Library-userimage
- = image_tag(library.user.image_url(:profile), class: "User-profile-image")
-
-- cache [library,library.user,"library_header"] do
- .Library-info
- .Library-info-text
- span.Library-info-text-title
- = link_to library.name, library_path(library), class: "library-link"
- span.Library-info-text-user
- = t('common.text.glue.from')
- = link_to user_path(library.user) do
- = library.user_nickname
- .Library-info-thumbnails
- - library.library_elements.active.preload(article_reduced: :title_image).first(11).each do |library_element|
- - if library_element.article_reduced
- = image_tag(library_element.article_reduced.title_image_url(:thumb), :title => library_element.article_reduced_title)
-
-/ Show comments
-- if comments && library.has_comments?
- .Library-comments
- = render library.comments.limit(2)
-
-/ Show audit buttons for admins
-- if policy(library).admin_audit?
- .Library-auditing
- = link_to admin_audit_library_path(library), class: 'Button ' + (library.audited ? 'Button--green' : 'Button--red'), method: :patch, remote: true do
- = t(library.audited ? 'library.auditing.welcome_page_enabled' : 'library.auditing.welcome_page_disabled')
diff --git a/app/views/libraries/index.html.slim b/app/views/libraries/index.html.slim
index c430bb8433..c3d0d78e02 100644
--- a/app/views/libraries/index.html.slim
+++ b/app/views/libraries/index.html.slim
@@ -22,8 +22,14 @@
/ Title
h1.Title-next-to-tab
- => t('libraries.title')
- span.sprite_helper title="#{ t('libraries.tooltip') }"
+ - if user_focused?
+ - if @user == current_user
+ => "Meine Sammlungen"
+ - else
+ => "Sammlungen von #{@user.name}"
+ - else
+ => t('libraries.title')
+ span.sprite_helper title="#{ t('libraries.tooltip') }"
/ Tabs
- if !user_focused? || @user == current_user
@@ -44,7 +50,7 @@ h1.Title-next-to-tab
.libraries
/ Link to new library form
- - if @library && policy(@library).create? && @libraries.length > 5
+ - if @library && policy(@library).create? && @libraries.length > 0
p#library-form-link= link_to t('libraries.create_new'), '#library-form'
/ Sign-in message
@@ -61,7 +67,8 @@ h1.Title-next-to-tab
/ Libraries
- if user_signed_in? || @mode != 'myfavorite'
- if @libraries.any?
- = render partial: "libraries/library", collection: @libraries
+ = render partial: 'libraries/library', collection: @libraries,
+ locals: { show_owner: !user_focused? }
= paginate @libraries
- else
p= t('libraries.no_library')
diff --git a/app/views/libraries/show.html.slim b/app/views/libraries/show.html.slim
index 3cb14e7b2c..f662a5eabd 100644
--- a/app/views/libraries/show.html.slim
+++ b/app/views/libraries/show.html.slim
@@ -1,14 +1,78 @@
/ Render library
-= render resource, single_view: true
-
-/ Admin controls
-- if User.is_admin?(current_user) && resource.public?
- .Admin-controls
- h2= "Administration:"
- h3= "Sammlung featuren"
- = semantic_form_for resource, url: user_library_path(resource.user, resource), html: { id: "select_exhibition_for_library#{resource.id}" } do |f|
- = f.inputs do
- = f.input :exhibition_name, as: :select, collection: Library.exhibition_name.options
- = f.actions do
- = f.action :submit, button_html: { class: "Btn", id: "select_exhibition_submit_action" }
- / this generates the same form id twice on that page which is annoying
+
+/ Convenience variable
+- is_own_library = resource.user == current_user
+
+section.library
+ .library-wrapper
+ / edit form
+ = render partial: 'libraries/show/library_edit', object: resource,
+ as: :library
+
+ header.library-header
+
+ / user information
+ - unless is_own_library
+ .library-header-owner
+ = link_to user_path(resource.user) do
+ = image_tag resource.user.image_url(:thumb),
+ alt: t('users.user_image')
+
+ .wrapper
+ span.library-header-owner-by=> t('library.library_by')
+ = link_to resource.user_nickname, user_path(resource.user),
+ class: 'library-header-owner-name'
+
+ / library name and other information
+ h1.library-header-title
+ = "#{resource.name} ".html_safe
+ small
+ - if is_own_library
+ span.library-header-title-visibility
+ = resource.public? ? t('library.visibility.public')\
+ : t('library.visibility.private')
+ |
+ = article_range_str @library_elements
+
+ / actions section with hearts and comments
+ .library-actions
+ = heart_button(resource)
+ = comments_counter(resource)
+
+
+ / Library body section
+ .library-body.Library-elements
+ - if @library_elements.to_a.any?
+ .Grid--wider
+ = render partial: 'libraries/show/library_element',
+ collection: @library_elements
+
+ = paginate @library_elements, param_name: :library_page, remote: false,
+ params: { controller: 'libraries', action: 'show',
+ id: resource.id, _: nil }
+
+
+ / Show social media buttons if it is a public library
+ - if resource.public?
+ .socialshareprivacy data={ uri: library_url(resource), title: resource.name }
+
+
+ / Comments section
+ = render partial: 'comments/commentable_comments', object: resource,
+ as: :commentable
+
+
+ / More libraries of the same user
+ - unless is_own_library || @user_libraries.empty?
+ section.morelibraries
+ h2
+ = t('libraries.morelibraries_by')
+ =< link_to resource.user_nickname, user_path(resource.user)
+ = render partial: 'libraries/library', collection: @user_libraries,
+ locals: { show_owner: false, piwik_campaign: 'libraries',
+ piwik_keyword: 'library_page' }
+
+
+ / Admin section
+ = render partial: 'libraries/show/library_admin', object: resource,
+ as: :library
diff --git a/app/views/libraries/show.js.erb b/app/views/libraries/show.js.erb
deleted file mode 100644
index 65ecfb6e9e..0000000000
--- a/app/views/libraries/show.js.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-$("#library<%= resource.id %> .js-library-ajax").html('<%= escape_javascript render "library_body", library: resource, remote_paginate: true %>');
-$('html,body').animate({scrollTop: $("<%= "#library#{resource.id.to_s}" %>").offset().top},'slow');
diff --git a/app/views/libraries/show/_library_admin.html.slim b/app/views/libraries/show/_library_admin.html.slim
new file mode 100644
index 0000000000..79d6eae548
--- /dev/null
+++ b/app/views/libraries/show/_library_admin.html.slim
@@ -0,0 +1,19 @@
+/ Library admin section
+
+- if User.is_admin?(current_user) && library.public?
+ section.library-admin
+ h2= t('library.admin.section')
+
+ section.library-admin-feature
+ h3= t('library.admin.feature')
+
+ = semantic_form_for library,
+ url: user_library_path(library.user, library),
+ html: { id: "select_exhibition_for_library#{library.id}" } do |f|
+ = f.inputs do
+ = f.input :exhibition_name, as: :select,
+ collection: Library.exhibition_name.options
+ = f.actions do
+ = f.action :submit,
+ button_html: { class: 'Button', id: 'select_exhibition_submit_action' }
+ / this generates the same form id twice on that page which is annoying
diff --git a/app/views/libraries/show/_library_edit.html.slim b/app/views/libraries/show/_library_edit.html.slim
new file mode 100644
index 0000000000..a15dc8ed22
--- /dev/null
+++ b/app/views/libraries/show/_library_edit.html.slim
@@ -0,0 +1,34 @@
+/ library edit and delete form for show view
+
+- if policy(library).update?
+ section.library-edit
+
+ / button to show or hide entire section
+ a.js-library-edit-trigger[href='#']
+ = t('common.actions.edit')
+
+ / part that is initially hidden
+ .library-edit-settings
+ h2= t('library.edit_or_delete')
+
+ / user warning if library is on welcome page
+ - if library.on_welcome_page?
+ p.Library-details-user-warning= t('library.auditing.user_warning')
+
+ / edit form
+ = semantic_form_for library,
+ url: user_library_path(library.user.id, library.id.to_s),
+ namespace: "library#{library.id.to_s}" do |f|
+ = f.inputs do
+ = f.input :name, required: false
+ = f.input :public, label: false
+ = f.actions do
+ = f.action :submit, label: :update, button_html: { class: 'Button'}
+
+ / delete button
+ - if policy(library).destroy?
+ = link_to t('library.delete'),
+ user_library_path(library.user.id, library.id.to_s),
+ class: 'Button Button--red',
+ confirm: t('library.delete_confirm', name: library.name),
+ method: :delete
diff --git a/app/views/libraries/show/_library_element.html.slim b/app/views/libraries/show/_library_element.html.slim
new file mode 100644
index 0000000000..59a7c05b8e
--- /dev/null
+++ b/app/views/libraries/show/_library_element.html.slim
@@ -0,0 +1,11 @@
+/ Render one library element
+
+- if policy(library_element).show?
+ .Grid-item
+ = render layout: 'articles/shared/show_article',
+ locals: { article: library_element.article_reduced,
+ extra: policy(library_element).destroy? } do
+ - if policy(library_element).destroy?
+ = link_to t('common.actions.destroy'),
+ user_library_element_path(current_user, library_element),
+ method: :delete, class: 'Button Button--red'
diff --git a/app/views/welcome/index.html.slim b/app/views/welcome/index.html.slim
index 8a3a09dcc4..952dbb93e2 100644
--- a/app/views/welcome/index.html.slim
+++ b/app/views/welcome/index.html.slim
@@ -254,7 +254,8 @@
=> t( 'welcome.trending_libraries.heading' )
span.sprite_helper title="#{ t('libraries.tooltip') }"
- = render partial: "libraries/library", collection: @trending_libraries, locals: { header_comments: false }
+ = render partial: 'libraries/library', collection: @trending_libraries,
+ locals: { piwik_campaign: 'libraries', piwik_keyword: 'welcome_page' }
p.more
= link_to( t( 'welcome.trending_libraries.more' ), libraries_path )
diff --git a/config/application.rb b/config/application.rb
index 82ef5ddf0c..5c6fff4e36 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -111,7 +111,7 @@ class Application < Rails::Application
config.assets.initialize_on_precompile = true
# Version of your assets, change this if you want to expire all your assets
- config.assets.version = '1.2'
+ config.assets.version = '1.3'
# Enable fonts directory
config.assets.paths << Rails.root.join("app", "assets", "fonts")
diff --git a/config/locales/comment/de.yml b/config/locales/comment/de.yml
index b84a3f67f5..3025b4a320 100644
--- a/config/locales/comment/de.yml
+++ b/config/locales/comment/de.yml
@@ -6,6 +6,8 @@ de:
article_body: 'Du hast einen neuen Kommentar oder eine Rückfrage zu Deinem Artikel "%{title}" bekommen'
user_body: "Du hast einen neuen Kommentar oder eine Rückfrage zu Deinem Profil bekommen"
comments:
+ comments: "Kommentare"
+ jump_to: "Zu den Kommentaren"
no_comments: "Es sind noch keine Kommentare vorhanden."
login_href: "Melde dich an"
login_to_comment: "%{href}, um Kommentare schreiben zu können."
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 82680b97cf..053460caa5 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -78,6 +78,7 @@ de:
login: "Anmelden"
sign_up: "Registrieren"
edit_profile: "Profil bearbeiten"
+ my_profile: "Mein Profil"
search: "Suche"
report: "Melden"
take_part: "Mitmachen"
@@ -112,7 +113,8 @@ de:
relation: "Beziehung"
inserted: "Artikel wurden bereits eingestellt"
no_search_result_text: "Keine Suchergebnisse unter den Fairmondo-Artikeln"
- libraries: "Meine Sammlungen"
+ libraries: "Sammlungen"
+ my_libraries: "Meine Sammlungen"
about_terms: "Meine Firmendaten"
more: "mehr anzeigen"
less: "weniger anzeigen"
@@ -123,18 +125,22 @@ de:
fair: "Fair"
seller: "Händler*in"
product: "Produkt"
- libraries: "Sammlungen"
article: "Artikel"
+ articles: "Artikel"
+ no_articles: "Keine Artikel"
about_terms: "AGB / Widerrufserklärung / Impressum"
about_terms_short: 'Impressum, AGB …'
extended_search: "Erweiterte Suche"
glue:
+ of: " von "
from: " von "
and: " und "
by: " von "
per: " pro "
via: " per "
ago: " vor %{time}"
+ glue_without_spaces:
+ of: "von"
form:
select_from_list: Bitte wähle aus der Liste aus
diff --git a/config/locales/gems/formtastic/de.yml b/config/locales/gems/formtastic/de.yml
index d2075270d9..3c5a142ddb 100644
--- a/config/locales/gems/formtastic/de.yml
+++ b/config/locales/gems/formtastic/de.yml
@@ -198,6 +198,7 @@ de:
library:
name: Name
public: Öffentlich
+ exhibition_name: Name der Queue
business_transaction: &business_transaction
tos_accepted: Ich akzeptiere die AGB und die Widerrufserklärung
diff --git a/config/locales/library/de.yml b/config/locales/library/de.yml
index b01febb878..9da8fd6d77 100644
--- a/config/locales/library/de.yml
+++ b/config/locales/library/de.yml
@@ -4,7 +4,7 @@ de:
no_library: "Es gibt noch keine Sammlungen, die wir hier anzeigen können."
sign_in: "Melde Dich an"
to_show_favorites: >
- um Deine Sammlungs-Favoriten zu sehen. Wenn Du noch keinen Account hast,
+ um Deine Sammlungs-Favoriten zu sehen. Wenn Du noch kein Konto hast,
musst Du Dich vorher
sign_up: "registrieren"
create_new: "Neue Sammlung anlegen"
@@ -18,16 +18,20 @@ de:
updated: 'Neu'
favorites: 'Meine Favoriten'
own: 'Meine Sammlungen'
+ morelibraries_by: 'Weitere Sammlungen von'
+ of_category: 'Sammlungen mit Artikeln aus der Kategorie „%{category}“'
library:
- new: "Neue Sammlung"
+ new: 'Neue Sammlung'
+ edit_or_delete: 'Diese Sammlung bearbeiten oder löschen'
+ delete: 'Sammlung löschen'
+ library_by: 'Sammlung von'
+ by_you: 'von Dir'
default: "Standardsammlung"
- show: "Zur Sammlung"
- no_products: "Diese Sammlung enthält im Moment keine Artikel."
create: "Sammlung anlegen"
delete_confirm: "Soll die Sammlung '%{name}' wirklich gelöscht werden?"
visibility:
- public: "Öffentliche Sammlung"
- private: "Private Sammlung"
+ public: "öffentlich"
+ private: "privat"
control:
main_tooltip: >
Füge diesen Artikel einer Deiner Sammlungen hinzu. So behältst Du ihn
@@ -44,6 +48,9 @@ de:
und wieder freigeschaltet haben.
welcome_page_enabled: "Für Startseite freigeschaltet"
welcome_page_disabled: "Für Startseite gesperrt"
+ admin:
+ section: 'Admin-Bereich'
+ feature: 'Sammlung auszeichnen'
library_element:
notice:
success: >
diff --git a/config/locales/user/de.yml b/config/locales/user/de.yml
index 98918bafc0..9f24099f87 100644
--- a/config/locales/user/de.yml
+++ b/config/locales/user/de.yml
@@ -60,6 +60,7 @@ de:
seller_line_item_groups: 'Deine Verkäufe'
buyer_line_item_groups: 'Deine Einkäufe'
no_img: "Noch+kein+Bild"
+ user_image: "Nutzerbild"
headers:
you: "Du"
invitor: "Einladender"
diff --git a/test/controllers/registrations_controller_test.rb b/test/controllers/registrations_controller_test.rb
index da49fa62da..5dcd6b7031 100644
--- a/test/controllers/registrations_controller_test.rb
+++ b/test/controllers/registrations_controller_test.rb
@@ -80,7 +80,7 @@
user = FactoryGirl.create(:user)
sign_in user
Image.any_instance.expects(:save)
- put :update, user: { nickname: user.nickname, image_attributes: FactoryGirl.attributes_for(:user_image) }, address: { first_name: '' } # invalid params
+ put :update, user: { nickname: user.nickname, image_attributes: FactoryGirl.attributes_for(:user_image) }, address: { first_name: '' } # invalid params
end
end
end
diff --git a/test/features/comments_test.rb b/test/features/comments_test.rb
index 2e192e8835..84a0d37be9 100644
--- a/test/features/comments_test.rb
+++ b/test/features/comments_test.rb
@@ -157,24 +157,6 @@
page.wont_have_content('Kommentar löschen')
end
end
-
- scenario 'Guest is able to see the last two comments' +
- ' of a library on the overview' do
- library = FactoryGirl.create(:library, public: true)
- article = FactoryGirl.create(:article)
- article.libraries << library
- user = FactoryGirl.create(:user)
- FactoryGirl.create_pair(:comment,
- text: 'Test comment',
- commentable: library,
- user: user)
-
- visit libraries_path
-
- within("#library#{library.id} .Library-comments") do
- page.must_have_content('Test comment')
- end
- end
end
feature 'comments on articles' do
diff --git a/test/features/hearts_test.rb b/test/features/hearts_test.rb
index 3db5aeac5b..68125cf184 100644
--- a/test/features/hearts_test.rb
+++ b/test/features/hearts_test.rb
@@ -31,15 +31,15 @@
scenario 'User visits library path, finds no hearts, ' +
'then likes a library and finds his heart' do
library = FactoryGirl.create(:library_with_elements, public: true)
- visit libraries_path
+
+ visit library_path(library.id)
page.must_have_selector('.Hearts-button')
- page.must_have_selector('.Hearts-count')
- within('.Hearts-count') { page.must_have_content '0' }
+ within('.Hearts-button em') { page.must_have_content '0' }
# can't check JS (otherwise this would be click_link, wait...)
library.hearts.create(user_token: 'RandomUserToken')
- visit libraries_path
- within('.Hearts-count') { page.must_have_content '1' }
+ visit library_path(library.id)
+ within('.Hearts-button em') { page.must_have_content '1' }
end
end
@@ -50,17 +50,16 @@
library = FactoryGirl.create(:library_with_elements, public: true)
login_as user
- visit libraries_path
+ visit library_path(library.id)
page.must_have_selector('.Hearts-button')
- page.must_have_selector('.Hearts-count')
- within('.Hearts-count') { page.must_have_content '0' }
+ within('.Hearts-button em') { page.must_have_content '0' }
h = user.hearts.create(heartable: library) # can't check JS
- visit libraries_path
- within('.Hearts-count') { page.must_have_content '1' }
+ visit library_path(library.id)
+ within('.Hearts-button em') { page.must_have_content '1' }
h.destroy # can't check JS
- visit libraries_path
- within('.Hearts-count') { page.must_have_content '0' }
+ visit library_path(library.id)
+ within('.Hearts-button em') { page.must_have_content '0' }
end
end
diff --git a/test/features/libraries_test.rb b/test/features/libraries_test.rb
index 30dcea66ac..8bf870acf1 100644
--- a/test/features/libraries_test.rb
+++ b/test/features/libraries_test.rb
@@ -87,6 +87,65 @@
end
end
+feature 'Libraries on category pages' do
+ setup do
+ @user = FactoryGirl.create :user
+ @library = FactoryGirl.create(:library, :public, user: @user)
+
+ @category = FactoryGirl.create :category
+ @category_child = FactoryGirl.create(:category, parent: @category)
+ @category_grandchild = FactoryGirl.create(
+ :category, parent: @category_child)
+ end
+
+ scenario 'library is shown on category page unless owner is logged in' do
+ articles = []
+ 3.times do
+ articles.push FactoryGirl.create(
+ :article, seller: @user, categories: [@category])
+ end
+
+ articles.each do |article|
+ FactoryGirl.create(:library_element, library: @library, article: article)
+ end
+
+ visit category_path(@category)
+ page.must_have_content(@library.name)
+
+ login_as @user
+ visit category_path(@category)
+ page.wont_have_content(@library.name)
+ end
+
+ scenario 'library is shown on parent category page' do
+ articles = []
+ .push(FactoryGirl.create(
+ :article, seller: @user, categories: [@category]))
+ .push(FactoryGirl.create(
+ :article, seller: @user, categories: [@category_child]))
+ .push(FactoryGirl.create(
+ :article, seller: @user, categories: [@category_grandchild]))
+
+ articles.each do |article|
+ FactoryGirl.create(:library_element, library: @library, article: article)
+ end
+
+ visit category_path(@category)
+ page.must_have_content(@library.name)
+ end
+end
+
+feature 'Libraries on library pages' do
+ scenario 'more libraries of the same user are shown on a library page' do
+ user = FactoryGirl.create :user
+ library1 = FactoryGirl.create(:library_with_elements, :public, user: user)
+ library2 = FactoryGirl.create(:library_with_elements, :public, user: user)
+
+ visit library_path(library1)
+ page.must_have_content(library2.name)
+ end
+end
+
feature 'Library management' do
setup do
@user = FactoryGirl.create :user
@@ -109,7 +168,7 @@
page.must_have_content I18n.t 'activerecord.errors.models.library.attributes.name.blank'
end
- scenario 'user updates name of exsisting Library' do
+ scenario 'user updates name of existing Library' do
library = FactoryGirl.create :library, name: 'foobar', user: @user
visit user_libraries_path @user
click_link 'foobar'
@@ -117,7 +176,7 @@
fill_in "library#{library.id}_library_name", with: 'bazfuz'
click_button I18n.t 'formtastic.actions.update'
end
- page.must_have_selector 'a', text: 'bazfuz'
+ page.must_have_content 'bazfuz'
end
scenario 'user updates library with a blank name' do
@@ -129,17 +188,17 @@
click_button I18n.t 'formtastic.actions.update'
end
- page.must_have_selector 'a', text: 'foobar'
+ page.must_have_content 'foobar'
page.must_have_content I18n.t('activerecord.errors.models.library.attributes.name.blank')
end
scenario 'user deletes Library' do
- library = FactoryGirl.create :library, name: 'foobar', user: @user
+ FactoryGirl.create :library, name: 'foobar', user: @user
visit user_libraries_path @user
click_link 'foobar'
assert_difference 'Library.count', -1 do
- within "#library#{library.id}" do
- click_link I18n.t('common.actions.destroy')
+ within '.library-edit-settings' do
+ click_link I18n.t('library.delete')
end
end
page.wont_have_content 'foobar'
@@ -172,10 +231,7 @@
logout(:user)
login_as buyer
visit library_path library
-
- within("#library#{library.id}") do
- page.must_have_content I18n.t('library.no_products')
- end
+ page.must_have_content I18n.t('common.text.no_articles')
end
end
diff --git a/test/support/modules/quickerclip.rb b/test/support/modules/quickerclip.rb
index f3cb101439..45884710f7 100644
--- a/test/support/modules/quickerclip.rb
+++ b/test/support/modules/quickerclip.rb
@@ -41,7 +41,7 @@ def make
end
end
class Attachment
- def post_process image=nil
+ def post_process *attrs
end
end
# module Storage