spina-admin-journal 0.6.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -48
  3. data/app/assets/config/spina_admin_journal_manifest.js +1 -2
  4. data/app/assets/javascripts/spina/admin/journal/application.js +0 -0
  5. data/app/components/spina/admin/journal/affiliations_list_component.rb +32 -0
  6. data/app/components/spina/admin/journal/application_component.rb +11 -0
  7. data/app/components/spina/admin/journal/articles_list_component.rb +54 -0
  8. data/app/components/spina/admin/journal/authors_list_component.rb +37 -0
  9. data/app/components/spina/admin/journal/authorships_list_component.rb +45 -0
  10. data/app/components/spina/admin/journal/empty_list_component.html.haml +1 -0
  11. data/app/components/spina/admin/journal/empty_list_component.rb +14 -0
  12. data/app/components/spina/admin/journal/form_group_component.html.haml +4 -0
  13. data/app/components/spina/admin/journal/form_group_component.rb +17 -0
  14. data/app/components/spina/admin/journal/institutions_list_component.rb +32 -0
  15. data/app/components/spina/admin/journal/issues_list_component.rb +47 -0
  16. data/app/components/spina/admin/journal/licences_list_component.rb +32 -0
  17. data/app/components/spina/admin/journal/list_component.html.haml +11 -0
  18. data/app/components/spina/admin/journal/list_component.rb +22 -0
  19. data/app/components/spina/admin/journal/list_item_component.html.haml +17 -0
  20. data/app/components/spina/admin/journal/list_item_component.rb +23 -0
  21. data/app/components/spina/admin/journal/volumes_list_component.rb +34 -0
  22. data/app/controllers/spina/admin/journal/application_controller.rb +1 -1
  23. data/app/controllers/spina/admin/journal/articles_controller.rb +18 -24
  24. data/app/controllers/spina/admin/journal/authors_controller.rb +18 -26
  25. data/app/controllers/spina/admin/journal/institutions_controller.rb +13 -5
  26. data/app/controllers/spina/admin/journal/issues_controller.rb +20 -27
  27. data/app/controllers/spina/admin/journal/journals_controller.rb +4 -1
  28. data/app/controllers/spina/admin/journal/licences_controller.rb +8 -4
  29. data/app/controllers/spina/admin/journal/volumes_controller.rb +16 -21
  30. data/app/models/spina/admin/journal/author.rb +1 -0
  31. data/app/models/spina/admin/journal/authorship.rb +9 -0
  32. data/app/views/spina/admin/hooks/journal/_primary_navigation.html.haml +35 -26
  33. data/app/views/spina/admin/journal/articles/_form.html.haml +23 -23
  34. data/app/views/spina/admin/journal/articles/_form_authors.html.haml +3 -15
  35. data/app/views/spina/admin/journal/articles/_form_details.html.haml +37 -56
  36. data/app/views/spina/admin/journal/articles/index.html.haml +7 -17
  37. data/app/views/spina/admin/journal/articles/view_authors.html.haml +2 -0
  38. data/app/views/spina/admin/journal/authors/_form.html.haml +24 -24
  39. data/app/views/spina/admin/journal/authors/_form_affiliation.html.haml +12 -20
  40. data/app/views/spina/admin/journal/authors/_form_articles.html.haml +3 -18
  41. data/app/views/spina/admin/journal/authors/_form_details.html.haml +27 -5
  42. data/app/views/spina/admin/journal/authors/index.html.haml +7 -15
  43. data/app/views/spina/admin/journal/authors/view_articles.html.haml +2 -0
  44. data/app/views/spina/admin/journal/institutions/_form.html.haml +24 -24
  45. data/app/views/spina/admin/journal/institutions/_form_details.html.haml +3 -8
  46. data/app/views/spina/admin/journal/institutions/_form_view_affiliations.html.haml +3 -10
  47. data/app/views/spina/admin/journal/institutions/index.html.haml +7 -15
  48. data/app/views/spina/admin/journal/institutions/view_affiliations.html.haml +2 -0
  49. data/app/views/spina/admin/journal/issues/_form.html.haml +23 -23
  50. data/app/views/spina/admin/journal/issues/_form_articles.html.haml +3 -14
  51. data/app/views/spina/admin/journal/issues/_form_details.html.haml +14 -28
  52. data/app/views/spina/admin/journal/issues/index.html.haml +7 -16
  53. data/app/views/spina/admin/journal/issues/view_articles.html.haml +3 -0
  54. data/app/views/spina/admin/journal/journals/_form.html.haml +22 -30
  55. data/app/views/spina/admin/journal/licences/_form.html.haml +24 -37
  56. data/app/views/spina/admin/journal/licences/index.html.haml +7 -16
  57. data/app/views/spina/admin/journal/volumes/_form.html.haml +25 -12
  58. data/app/views/spina/admin/journal/volumes/_form_details.html.haml +5 -10
  59. data/app/views/spina/admin/journal/volumes/_form_issues.html.haml +2 -13
  60. data/app/views/spina/admin/journal/volumes/index.html.haml +7 -16
  61. data/app/views/spina/admin/journal/volumes/view_issues.html.haml +2 -0
  62. data/app/views/spina/admin/parts/admin/journal/page_ranges/_form.html.haml +3 -4
  63. data/config/locales/en.yml +70 -8
  64. data/config/routes.rb +26 -6
  65. data/db/migrate/20220130171603_add_orcid_to_spina_admin_journal_author.rb +7 -0
  66. data/lib/spina/admin/journal/engine.rb +12 -0
  67. data/lib/spina/admin/journal/version.rb +1 -1
  68. data/lib/spina/admin/journal.rb +1 -0
  69. metadata +53 -63
  70. data/app/assets/javascripts/spina/admin/journal/application.es6 +0 -72
  71. data/app/views/layouts/spina/admin/journal/articles.html.haml +0 -10
  72. data/app/views/layouts/spina/admin/journal/authors.html.haml +0 -10
  73. data/app/views/layouts/spina/admin/journal/institutions.html.haml +0 -10
  74. data/app/views/layouts/spina/admin/journal/issues.html.haml +0 -10
  75. data/app/views/layouts/spina/admin/journal/journals.html.haml +0 -10
  76. data/app/views/layouts/spina/admin/journal/licences.html.haml +0 -10
  77. data/app/views/layouts/spina/admin/journal/volumes.html.haml +0 -10
  78. data/app/views/spina/admin/journal/affiliations/_affiliation.html.haml +0 -8
  79. data/app/views/spina/admin/journal/application/_empty_list.html.haml +0 -3
  80. data/app/views/spina/admin/journal/articles/_article.html.haml +0 -10
  81. data/app/views/spina/admin/journal/authors/_author.html.haml +0 -8
  82. data/app/views/spina/admin/journal/authorships/_authorship.html.haml +0 -9
  83. data/app/views/spina/admin/journal/institutions/_institution.html.haml +0 -9
  84. data/app/views/spina/admin/journal/issues/_issue.html.haml +0 -9
  85. data/app/views/spina/admin/journal/journals/index.html.haml +0 -27
  86. data/app/views/spina/admin/journal/licences/_licence.html.haml +0 -11
  87. data/app/views/spina/admin/journal/volumes/_volume.html.haml +0 -7
  88. data/vendor/assets/javascripts/spina/admin/journal/html5sortable.js +0 -1295
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: afadf6fe1f99997005bc61d4c3d31b6a1fd02ea35e400539a6e3f3806010910a
4
- data.tar.gz: 7a4375228d01fa343613e8978860ff64c4ba8b1d3232d439efc71e150cab6d93
3
+ metadata.gz: 6a0055e328c3ad9ed3d723edb02c58062caf6621d4dd0a286021930957f42dd1
4
+ data.tar.gz: 303734e1e4dc5d2c90b45e24d2399872ada559e50ed60571316d35a48fbbd363
5
5
  SHA512:
6
- metadata.gz: 63d5deaf2bc734aafefcbd7ddb814f1593ab18ea6a3653beeadfede9ddb386579107f87147a78d036d9e95e5f1fd868f088a03352de57652b9a30afcc3a2fa58
7
- data.tar.gz: ad6606f902897fc5ffa29d00241c89c1c4cb68a666313e53bc21227e357dd06e760a9d7e011c7f6e1870b6f872327f4052ceacc77c63fbd5745d8ba10bda1800
6
+ metadata.gz: 8efcbe772ec874d7c1c5359b2ae00b62a9fba78af47a270371d3120f2845e11df8c808c3d7d3928ac97682dabb8d6cd5f365dbac94e4989c5da49f825e0c0a86
7
+ data.tar.gz: 0b2012a0505383c60e5fbd92c1c4718f76258032a7d428c0a6292f75dc9d87710fe43cf54ee1cb68fcf0164a8c1592df511174a2102cfb429ff1251ce6d1334d
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Spina::Admin::Journal
2
2
 
3
+ *Journal* is a plugin for [Spina](https://www.spinacms.com/) that provides a fully-fledged journal management package, intended to provide a more streamlined, easy-to-use, modern alternative to [OJS](https://pkp.sfu.ca/ojs/).
4
+
5
+ Spina is a content management system built in [Ruby on Rails](http://rubyonrails.org/). *Journal* augments Spina by providing an admin interface for managing an academic journal.
6
+
3
7
  ![Rails tests](https://github.com/louis-vs/spina-admin-journal/workflows/Verify/badge.svg?branch=master&event=push)
4
8
  [![codecov](https://codecov.io/gh/louis-vs/spina-admin-journal/branch/master/graph/badge.svg?token=9TZ9QGGLAH)](https://codecov.io/gh/louis-vs/spina-admin-journal)
5
9
  [![CodeFactor](https://www.codefactor.io/repository/github/louis-vs/spina-admin-journal/badge)](https://www.codefactor.io/repository/github/louis-vs/spina-admin-journal)
@@ -7,69 +11,48 @@
7
11
  [![Code quality: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/louis-vs/spina-admin-journal.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/louis-vs/spina-admin-journal/context:javascript)
8
12
  [![Inline docs](http://inch-ci.org/github/louis-vs/spina-admin-journal.svg?branch=master)](http://inch-ci.org/github/louis-vs/spina-admin-journal)
9
13
 
10
- *Journal* is a plugin for [Spina](https://www.spinacms.com/), a content management system built in [Ruby on Rails](http://rubyonrails.org/). *Journal* augments Spina by providing an admin interface for managing an academic journal.
11
-
12
- ## Usage
13
-
14
- The plugin adds two menus to Spina's primary navigation:
15
-
16
- * **Journal settings** provides access to global properties of the journal. It is divided into 3 submenus:
17
- * **Journal** allows you to change the name of the journal.
18
- * **Institutions** allows you to add institutions, to which authors can be affiliated.
19
- * **Authors** allows you to add authors, who can then be added to articles.
20
- * The **journal content** menu will be named after the journal as specified in Journal Settings. It provides a means of editing the content of the journal and is divided into three submenus:
21
- * **Volumes** allows you to add and remove volumes of the journal, and edit their respective issues.
22
- * **Issues** allows you to add, edit and remove issues of particular volumes of the journal, and edit their respective articles.
23
- * **Articles** allows you to add, edit and remove articles belonging to particular issues.
14
+ ## Features
24
15
 
25
- The plugin does not provide any public-facing frontend. However, an example implementation can be found at **[TBC]**.
16
+ The journal plugin covers many of the needs of a professional online journal publication, including:
26
17
 
27
- **NB this plugin is currently a work in progress**: please wait until an official release to use this plugin in production.
18
+ - Simple, responsive, intuitive interface that builds upon Spina's own.
19
+ - Seamlessly integrate published content with other information about the journal.
20
+ - Manage volumes, issues, articles and authors in a highly structured and organised manner.
21
+ - Keep track of individual authors with multiple affiliations, e.g. if they change name or institution, connecting with [ORCID](https://orcid.org/).
28
22
 
29
- ## Installation
30
-
31
- ### From scratch
32
-
33
- Make sure you have a working installation of Ruby on Rails 6.1. You can find a setup guide [here](https://guides.rubyonrails.org/getting_started.html).
34
-
35
- Then run:
36
-
37
- ```bash
38
- $ rails new your-app --database=postgresql
39
- $ cd your-app
40
- $ bin/rails db:create
41
- $ bin/rails active_storage:install
42
- ```
23
+ Currently, a submissions management system is not included, but this is planned for a future release. This will allow you to manage the submissions process for the journal in a streamlined manner in parallel to publication.
43
24
 
44
- Add this line to your new application's Gemfile:
25
+ ## Usage
45
26
 
46
- ```ruby
47
- gem 'spina', '~> 2.0'
48
- ```
27
+ The plugin adds two menus to Spina's primary navigation:
49
28
 
50
- And then execute:
29
+ - **Journal settings** provides access to global properties of the journal. It is divided into 3 submenus:
30
+ - **Journal** allows you to change metadata such as the name of the journal, as well as content that will appear on the journal homepage.
31
+ - **Institutions** allows you to add institutions, to which authors can be affiliated.
32
+ - **Authors** allows you to add authors and their affiliations, which can then be added to articles.
33
+ - **Licences** allows you to add licences and association information, which can be associated with individual articles, representing the licence under which the content is released.
34
+ - The **journal content** menu will be named after the journal as specified in Journal Settings. It provides a means of editing the content of the journal and is divided into three submenus:
35
+ - **Volumes** allows you to add and remove volumes of the journal, and edit their respective issues.
36
+ - **Issues** allows you to add, edit and remove issues of particular volumes of the journal, and edit their respective articles.
37
+ - **Articles** allows you to add, edit and remove articles belonging to particular issues.
51
38
 
52
- ```bash
53
- $ bundle install
54
- ```
39
+ **NB:** This release of the plugin does not provide any public-facing frontend or Spina theme. An example implementation can be found within the [Conferences Primer Theme](https://github.com/louis-vs/spina-conferences-primer_theme-fork). Note that this theme also contains frontends for two other Spina plugins, [Spina Conferences Blog](https://github.com/louis-vs/spina-admin-conferences-blog) and [Spina Admin Conferences](https://github.com/louis-vs/spina-admin-conferences-fork/). You can use the theme in your project as is, or copy whichever parts of the code you need.
55
40
 
56
- Run the Spina install generator:
41
+ A dedicated journal theme, coupled with an automatic installer, is being planned. A system to manage submissions is also on the roadmap.
57
42
 
58
- ```bash
59
- $ bin/rails g spina:install
60
- ```
43
+ ## Installation
61
44
 
62
- And follow the prompts. Once this is complete, follow the instructions below.
45
+ Make sure you have a working installation of Ruby on Rails 7. You can find a setup guide [here](https://guides.rubyonrails.org/getting_started.html).
63
46
 
64
- ### For existing Spina installations
47
+ You then need to install Spina, following the guide [on the Spina website](https://spinacms.com/docs).
65
48
 
66
- Add this line to your application's Gemfile:
49
+ To install the plugin, add this line to your application's Gemfile:
67
50
 
68
51
  ```ruby
69
- gem 'spina-admin-journal', '~> 0.1'
52
+ gem 'spina-admin-journal', '~> 1.0'
70
53
  ```
71
54
 
72
- And then execute:
55
+ Then execute:
73
56
 
74
57
  ```bash
75
58
  $ bundle install
@@ -78,7 +61,7 @@ $ bundle install
78
61
  You'll then need to install and run the migrations for the journal:
79
62
 
80
63
  ```bash
81
- $ bin/rails spina_admin_journal_engine:install:migrations
64
+ $ bin/rails spina_admin_journal:install:migrations
82
65
  $ bin/rails db:migrate
83
66
  ```
84
67
 
@@ -94,6 +77,11 @@ You can manually populate the database from within the app, or alternatively you
94
77
 
95
78
  Bug reports and feature requests are welcome in the [Issues](https://github.com/louis-vs/spina-admin-journal/issues) section. Translations are also very welcome!
96
79
 
80
+ ### Planned features
81
+
82
+ - [ ] Submissions management
83
+ - [ ] Translations
84
+
97
85
  ## License
98
86
 
99
87
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,3 +1,2 @@
1
- //= link spina/admin/journal/application.js
2
1
  //= link spina/admin/journal/application.css
3
- //= link spina_manifest.js
2
+ //= link spina/admin/journal/application.js
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A list of licences. Not sortable.
7
+ class AffiliationsListComponent < ListComponent
8
+ def initialize(affiliations:)
9
+ @affiliations = affiliations
10
+ end
11
+
12
+ def before_render
13
+ @list_items = generate_list_items(@affiliations)
14
+ end
15
+
16
+ def call
17
+ render ListComponent.new(list_items: @list_items, sortable: false)
18
+ end
19
+
20
+ private
21
+
22
+ def generate_list_items(affiliations)
23
+ affiliations.map do |affiliation|
24
+ { id: affiliation.id,
25
+ label: affiliation.reversed_name,
26
+ path: helpers.spina.edit_admin_journal_author_path(affiliation.author) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # Base class for components.
7
+ class ApplicationComponent < Spina::ApplicationComponent
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A list of articles. Articles should only be sortable if presented within the contex of an
7
+ # issue.
8
+ class ArticlesListComponent < ListComponent
9
+ attr_reader :sortable
10
+
11
+ def initialize(articles:, sortable: false)
12
+ @articles = articles
13
+ @sortable = sortable
14
+ end
15
+
16
+ def before_render
17
+ @list_items = generate_list_items(@articles)
18
+ end
19
+
20
+ def call
21
+ render ListComponent.new(list_items: @list_items,
22
+ sortable: sortable?,
23
+ sort_path: generate_sort_path)
24
+ end
25
+
26
+ def sortable?
27
+ sortable
28
+ end
29
+
30
+ private
31
+
32
+ def generate_list_items(articles)
33
+ articles.map do |article|
34
+ { id: article.id,
35
+ label: generate_label(article),
36
+ path: helpers.spina.edit_admin_journal_article_path(article.id) }
37
+ end
38
+ end
39
+
40
+ def generate_label(article) # rubocop:disable Metrics/AbcSize
41
+ t('spina.admin.journal.articles.article_number', volume_number: article.issue.volume.number, # rubocop:disable Style/StringConcatenation
42
+ issue_number: article.issue.number,
43
+ article_number: article.number
44
+ ) + ' | ' + t('spina.admin.journal.articles.title_author', title: article.title, # rubocop:disable Layout/MultilineMethodCallBraceLayout Layout/SpaceInsideParens
45
+ author: article.authorships.sorted_within_article.map { |authorship| authorship.affiliation.surname }.join(', ')) # rubocop:disable Layout/LineLength
46
+ end
47
+
48
+ def generate_sort_path
49
+ @articles.any? ? helpers.spina.sort_admin_journal_issues_path(@articles.first.issue.id) : ''
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A list of authors. Not sortable.
7
+ class AuthorsListComponent < ListComponent
8
+ def initialize(authors:)
9
+ @authors = authors
10
+ end
11
+
12
+ def before_render
13
+ @list_items = generate_list_items(@authors)
14
+ end
15
+
16
+ def call
17
+ render ListComponent.new(list_items: @list_items, sortable: false)
18
+ end
19
+
20
+ private
21
+
22
+ def generate_list_items(authors)
23
+ authors.map do |author|
24
+ { id: author.id,
25
+ label: generate_label(author),
26
+ path: helpers.spina.edit_admin_journal_author_path(author) }
27
+ end
28
+ end
29
+
30
+ def generate_label(author)
31
+ t 'spina.admin.journal.authors.name_institution', name: author.primary_affiliation.name,
32
+ institution: author.primary_affiliation.institution.name
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A list of authorships. Sortable when displayed in their corresponding article.
7
+ class AuthorshipsListComponent < ListComponent
8
+ attr_reader :sortable
9
+
10
+ def initialize(authorships:, sortable: false)
11
+ @authorships = authorships
12
+ @sortable = sortable
13
+ end
14
+
15
+ def before_render
16
+ @list_items = generate_list_items(@authorships)
17
+ end
18
+
19
+ def call
20
+ render ListComponent.new(list_items: @list_items,
21
+ sortable: sortable?,
22
+ sort_path: generate_sort_path)
23
+ end
24
+
25
+ def sortable?
26
+ sortable
27
+ end
28
+
29
+ private
30
+
31
+ def generate_list_items(authorships)
32
+ authorships.map do |authorship|
33
+ { id: authorship.id,
34
+ label: authorship.affiliation.reversed_name,
35
+ path: helpers.spina.edit_admin_journal_author_path(authorship.affiliation.author) }
36
+ end
37
+ end
38
+
39
+ def generate_sort_path
40
+ @authorships.any? ? helpers.spina.sort_admin_journal_authors_path(@authorships.first.article.id) : ''
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # Displays a message indicating that a {ListComponent} has no items.
7
+ class EmptyListComponent < ApplicationComponent
8
+ def initialize(message: t('spina.admin.journal.empty_list'))
9
+ @message = message
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ .mt-6
2
+ %label.block.text-sm.leading-5.font-medium.text-gray-700= label
3
+ .text-gray-400.text-sm= description
4
+ .mt-1= content
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # Correctly styles label, description and content of form fields.
7
+ class FormGroupComponent < ApplicationComponent
8
+ attr_reader :label, :description
9
+
10
+ def initialize(label:, description: '')
11
+ @label = label
12
+ @description = description
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A list of institutions. Not sortable.
7
+ class InstitutionsListComponent < ListComponent
8
+ def initialize(institutions:)
9
+ @institutions = institutions
10
+ end
11
+
12
+ def before_render
13
+ @list_items = generate_list_items(@institutions)
14
+ end
15
+
16
+ def call
17
+ render ListComponent.new(list_items: @list_items, sortable: false)
18
+ end
19
+
20
+ private
21
+
22
+ def generate_list_items(institutions)
23
+ institutions.map do |institution|
24
+ { id: institution.id,
25
+ label: institution.name,
26
+ path: helpers.spina.edit_admin_journal_institution_path(institution.id) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A list of issues. Issues should only be sortable if presented within the contex of a
7
+ # volume.
8
+ class IssuesListComponent < ListComponent
9
+ attr_reader :sortable
10
+
11
+ def initialize(issues:, sortable: false)
12
+ @issues = issues
13
+ @sortable = sortable
14
+ end
15
+
16
+ def before_render
17
+ @list_items = generate_list_items(@issues)
18
+ end
19
+
20
+ def call
21
+ render ListComponent.new(list_items: @list_items,
22
+ sortable: sortable?,
23
+ sort_path: generate_sort_path)
24
+ end
25
+
26
+ def sortable?
27
+ sortable
28
+ end
29
+
30
+ private
31
+
32
+ def generate_list_items(issues)
33
+ issues.map do |issue|
34
+ { id: issue.id,
35
+ label: t('spina.admin.journal.issues.volume_issue', volume_number: issue.volume.number,
36
+ issue_number: issue.number),
37
+ path: helpers.spina.edit_admin_journal_issue_path(issue.id) }
38
+ end
39
+ end
40
+
41
+ def generate_sort_path
42
+ @issues.any? ? helpers.spina.sort_admin_journal_issues_path(@issues.first.volume.id) : ''
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A list of licences. Not sortable.
7
+ class LicencesListComponent < ListComponent
8
+ def initialize(licences:)
9
+ @licences = licences
10
+ end
11
+
12
+ def before_render
13
+ @list_items = generate_list_items(@licences)
14
+ end
15
+
16
+ def call
17
+ render ListComponent.new(list_items: @list_items, sortable: false)
18
+ end
19
+
20
+ private
21
+
22
+ def generate_list_items(licences)
23
+ licences.map do |licence|
24
+ { id: licence.id,
25
+ label: licence.name,
26
+ path: helpers.spina.edit_admin_journal_licence_path(licence) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ .my-6.md:m-8
2
+ - if sortable?
3
+ .mb-4.text-gray-600.text-sm= t 'spina.admin.journal.sort_info'
4
+ .bg-white.md:rounded-lg.border-l-0.border-r-0.border.md:border-r.md:border-l.border-gray-200.border-b-0.shadow-sm{ data: { controller: 'sortable' } }
5
+ = form_with(url: @sort_path, data: { sortable_target: 'form' }) { |f| }
6
+ %ul{ data: { sortable_target: 'list' } }
7
+ - if @list_items.any?
8
+ - @list_items.each do |item|
9
+ = render Spina::Admin::Journal::ListItemComponent.new(id: item[:id], label: item[:label], path: item[:path], sortable: sortable?)
10
+ - else
11
+ = render Spina::Admin::Journal::EmptyListComponent.new
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A generic implementation of a list, resembling Spina's page list.
7
+ class ListComponent < ApplicationComponent
8
+ attr_reader :sortable
9
+
10
+ def initialize(list_items:, sortable: false, sort_path: '')
11
+ @sortable = sortable
12
+ @list_items = list_items
13
+ @sort_path = sort_path
14
+ end
15
+
16
+ def sortable?
17
+ sortable
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ %li{data: { id: @id }}
2
+ .flex.items-center.border-gray-200.border-b.bg-opacity-50.w-full
3
+ - if sortable?
4
+ .p-4.text-gray-300.hover:text-gray-600.cursor-move{ data: { 'sortable-handle': true } }
5
+ = helpers.heroicon('menu-alt-4', style: :solid, class: 'w-4 h-4 -mr-4')
6
+
7
+ .flex-auto
8
+ .block.text-spina.font-medium.text-sm.p-4{class: 'hover:text-spina-dark' }
9
+ = link_to @path do
10
+ = @label
11
+
12
+ .flex-1
13
+
14
+ = link_to @path, class: 'btn btn-link mr-4' do
15
+ .flex.flex-nowrap.items-center.px-8.py-1
16
+ = helpers.heroicon 'pencil-alt', style: :outline, class: 'w-4 h-4'
17
+ .ml-2= t 'spina.admin.journal.edit'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A generic list item that is only intended to be called by {ListItemComponent}.
7
+ class ListItemComponent < ApplicationComponent
8
+ attr_reader :sortable
9
+
10
+ def initialize(id:, label:, path:, sortable: false)
11
+ @label = label
12
+ @id = id
13
+ @path = path
14
+ @sortable = sortable
15
+ end
16
+
17
+ def sortable?
18
+ sortable
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spina
4
+ module Admin
5
+ module Journal
6
+ # A sortable list of volumes.
7
+ class VolumesListComponent < ListComponent
8
+ def initialize(volumes:)
9
+ @volumes = volumes
10
+ end
11
+
12
+ def before_render
13
+ @list_items = generate_list_items(@volumes)
14
+ end
15
+
16
+ def call
17
+ render ListComponent.new(list_items: @list_items,
18
+ sortable: true,
19
+ sort_path: helpers.spina.sort_admin_journal_volumes_path(Journal.instance.id))
20
+ end
21
+
22
+ private
23
+
24
+ def generate_list_items(volumes)
25
+ volumes.map do |volume|
26
+ { id: volume.id,
27
+ label: t('spina.admin.journal.volumes.volume_number', number: volume.number),
28
+ path: helpers.spina.edit_admin_journal_volume_path(volume.id) }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -9,7 +9,7 @@ module Spina
9
9
 
10
10
  add_flash_types :success
11
11
 
12
- layout :admin_layout, only: %i[new edit]
12
+ layout :admin_layout
13
13
 
14
14
  before_action :set_locale
15
15