spina-admin-journal 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +99 -0
- data/Rakefile +36 -0
- data/app/assets/config/spina_admin_journal_manifest.js +3 -0
- data/app/assets/javascripts/spina/admin/journal/application.es6 +72 -0
- data/app/assets/stylesheets/spina/admin/journal/application.css +27 -0
- data/app/controllers/spina/admin/journal/application_controller.rb +26 -0
- data/app/controllers/spina/admin/journal/articles_controller.rb +125 -0
- data/app/controllers/spina/admin/journal/authors_controller.rb +83 -0
- data/app/controllers/spina/admin/journal/institutions_controller.rb +71 -0
- data/app/controllers/spina/admin/journal/issues_controller.rb +129 -0
- data/app/controllers/spina/admin/journal/journals_controller.rb +73 -0
- data/app/controllers/spina/admin/journal/volumes_controller.rb +79 -0
- data/app/models/spina/admin/journal.rb +11 -0
- data/app/models/spina/admin/journal/affiliation.rb +62 -0
- data/app/models/spina/admin/journal/article.rb +55 -0
- data/app/models/spina/admin/journal/author.rb +47 -0
- data/app/models/spina/admin/journal/authorship.rb +19 -0
- data/app/models/spina/admin/journal/institution.rb +32 -0
- data/app/models/spina/admin/journal/issue.rb +49 -0
- data/app/models/spina/admin/journal/journal.rb +50 -0
- data/app/models/spina/admin/journal/volume.rb +37 -0
- data/app/validators/spina/admin/journal/uri_validator.rb +24 -0
- data/app/views/layouts/spina/admin/journal/articles.html.haml +10 -0
- data/app/views/layouts/spina/admin/journal/authors.html.haml +10 -0
- data/app/views/layouts/spina/admin/journal/institutions.html.haml +10 -0
- data/app/views/layouts/spina/admin/journal/issues.html.haml +10 -0
- data/app/views/layouts/spina/admin/journal/journals.html.haml +10 -0
- data/app/views/layouts/spina/admin/journal/volumes.html.haml +10 -0
- data/app/views/spina/admin/hooks/journal/_head.html.haml +2 -0
- data/app/views/spina/admin/hooks/journal/_primary_navigation.html.haml +27 -0
- data/app/views/spina/admin/hooks/journal/_website_secondary_navigation.html.haml +0 -0
- data/app/views/spina/admin/journal/affiliations/_affiliation.html.haml +8 -0
- data/app/views/spina/admin/journal/application/_empty_list.html.haml +3 -0
- data/app/views/spina/admin/journal/articles/_article.html.haml +10 -0
- data/app/views/spina/admin/journal/articles/_form.html.haml +29 -0
- data/app/views/spina/admin/journal/articles/_form_authors.html.haml +10 -0
- data/app/views/spina/admin/journal/articles/_form_details.html.haml +52 -0
- data/app/views/spina/admin/journal/articles/edit.html.haml +1 -0
- data/app/views/spina/admin/journal/articles/index.html.haml +19 -0
- data/app/views/spina/admin/journal/articles/new.html.haml +1 -0
- data/app/views/spina/admin/journal/authors/_author.html.haml +8 -0
- data/app/views/spina/admin/journal/authors/_form.html.haml +29 -0
- data/app/views/spina/admin/journal/authors/_form_affiliation.html.haml +20 -0
- data/app/views/spina/admin/journal/authors/_form_articles.html.haml +18 -0
- data/app/views/spina/admin/journal/authors/_form_details.html.haml +6 -0
- data/app/views/spina/admin/journal/authors/edit.html.haml +1 -0
- data/app/views/spina/admin/journal/authors/index.html.haml +17 -0
- data/app/views/spina/admin/journal/authors/new.html.haml +1 -0
- data/app/views/spina/admin/journal/institutions/_form.html.haml +29 -0
- data/app/views/spina/admin/journal/institutions/_form_details.html.haml +9 -0
- data/app/views/spina/admin/journal/institutions/_form_view_affiliations.html.haml +10 -0
- data/app/views/spina/admin/journal/institutions/_institution.html.haml +9 -0
- data/app/views/spina/admin/journal/institutions/edit.html.haml +1 -0
- data/app/views/spina/admin/journal/institutions/index.html.haml +16 -0
- data/app/views/spina/admin/journal/institutions/new.html.haml +1 -0
- data/app/views/spina/admin/journal/issues/_form.html.haml +29 -0
- data/app/views/spina/admin/journal/issues/_form_articles.html.haml +14 -0
- data/app/views/spina/admin/journal/issues/_form_details.html.haml +32 -0
- data/app/views/spina/admin/journal/issues/_issue.html.haml +9 -0
- data/app/views/spina/admin/journal/issues/edit.html.haml +1 -0
- data/app/views/spina/admin/journal/issues/index.html.haml +18 -0
- data/app/views/spina/admin/journal/issues/new.html.haml +1 -0
- data/app/views/spina/admin/journal/journals/_form.html.haml +35 -0
- data/app/views/spina/admin/journal/journals/edit.html.haml +1 -0
- data/app/views/spina/admin/journal/journals/index.html.haml +27 -0
- data/app/views/spina/admin/journal/journals/new.html.haml +1 -0
- data/app/views/spina/admin/journal/volumes/_form.html.haml +15 -0
- data/app/views/spina/admin/journal/volumes/_form_details.html.haml +10 -0
- data/app/views/spina/admin/journal/volumes/_form_issues.html.haml +13 -0
- data/app/views/spina/admin/journal/volumes/_volume.html.haml +7 -0
- data/app/views/spina/admin/journal/volumes/edit.html.haml +1 -0
- data/app/views/spina/admin/journal/volumes/index.html.haml +17 -0
- data/app/views/spina/admin/journal/volumes/new.html.haml +1 -0
- data/config/locales/en.yml +184 -0
- data/config/routes.rb +21 -0
- data/db/migrate/20201216152147_create_spina_admin_journal_journals.rb +13 -0
- data/db/migrate/20201216153822_create_spina_admin_journal_volumes.rb +13 -0
- data/db/migrate/20201216155113_create_spina_admin_journal_issues.rb +15 -0
- data/db/migrate/20201216161122_create_spina_admin_journal_articles.rb +16 -0
- data/db/migrate/20201216205633_create_spina_admin_journal_institutions.rb +11 -0
- data/db/migrate/20201216211224_create_spina_admin_journal_authors.rb +7 -0
- data/db/migrate/20201216221146_create_spina_admin_journal_affiliations.rb +15 -0
- data/db/migrate/20201216230816_create_spina_admin_journal_authorships.rb +14 -0
- data/db/migrate/20201231165231_create_spina_admin_journal_parts.rb +12 -0
- data/db/migrate/20210424123450_add_json_attributes_to_spina_admin_journal_journals.rb +7 -0
- data/db/migrate/20210424123521_add_json_attributes_to_spina_admin_journal_issues.rb +7 -0
- data/db/migrate/20210424123555_add_json_attributes_to_spina_admin_journal_articles.rb +7 -0
- data/lib/spina/admin/journal.rb +18 -0
- data/lib/spina/admin/journal/engine.rb +17 -0
- data/lib/spina/admin/journal/version.rb +9 -0
- data/lib/tasks/spina/admin/journal_tasks.rake +5 -0
- data/vendor/assets/javascripts/spina/admin/journal/html5sortable.js +1295 -0
- metadata +388 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 75a11c42a861742be9bee3d10d3a84f745f2d489b8a1ad61bf8e699f4f7fdc04
|
4
|
+
data.tar.gz: 343abc141c3af6b35492ec12a4c99325b116a3f63c5058fe7c61359cdfcd0da2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8209f366bfdd31dee8b559a9ca0c3966f3383687560b87a20cda19fbb198eb8faa5929d07e1b97b773464ab950fb5d2c298b4e168a22afacec726c7bb7fee2a4
|
7
|
+
data.tar.gz: 7182be875c118c6c59322b6e5a3fd51d81d5d51700be8db549ae48438df05bbb2fd9c290219cdbcae3d28b5530e172e5891ceb1636954c7aa36410406f96573b
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2021 Louis Van Steene
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Spina::Admin::Journal
|
2
|
+
|
3
|
+
![Rails tests](https://github.com/louis-vs/spina-admin-journal/workflows/Verify/badge.svg?branch=master&event=push)
|
4
|
+
[![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
|
+
[![CodeFactor](https://www.codefactor.io/repository/github/louis-vs/spina-admin-journal/badge)](https://www.codefactor.io/repository/github/louis-vs/spina-admin-journal)
|
6
|
+
[![LGTM alerts](https://img.shields.io/lgtm/alerts/g/louis-vs/spina-admin-journal.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/louis-vs/spina-admin-journal/alerts/)
|
7
|
+
[![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
|
+
[![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
|
+
|
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.
|
24
|
+
|
25
|
+
The plugin does not provide any public-facing frontend. However, an example implementation can be found at **[TBC]**.
|
26
|
+
|
27
|
+
**NB this plugin is currently a work in progress**: please wait until an official release to use this plugin in production.
|
28
|
+
|
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
|
+
```
|
43
|
+
|
44
|
+
Add this line to your new application's Gemfile:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
gem 'spina', '~> 2.0'
|
48
|
+
```
|
49
|
+
|
50
|
+
And then execute:
|
51
|
+
|
52
|
+
```bash
|
53
|
+
$ bundle install
|
54
|
+
```
|
55
|
+
|
56
|
+
Run the Spina install generator:
|
57
|
+
|
58
|
+
```bash
|
59
|
+
$ bin/rails g spina:install
|
60
|
+
```
|
61
|
+
|
62
|
+
And follow the prompts. Once this is complete, follow the instructions below.
|
63
|
+
|
64
|
+
### For existing Spina installations
|
65
|
+
|
66
|
+
Add this line to your application's Gemfile:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
gem 'spina-admin-journal', '~> 0.1'
|
70
|
+
```
|
71
|
+
|
72
|
+
And then execute:
|
73
|
+
|
74
|
+
```bash
|
75
|
+
$ bundle install
|
76
|
+
```
|
77
|
+
|
78
|
+
You'll then need to install and run the migrations for the journal:
|
79
|
+
|
80
|
+
```bash
|
81
|
+
$ bin/rails spina_admin_journal_engine:install:migrations
|
82
|
+
$ bin/rails db:migrate
|
83
|
+
```
|
84
|
+
|
85
|
+
You can then start a local server to test that everything's working.
|
86
|
+
|
87
|
+
```bash
|
88
|
+
$ bin/rails s
|
89
|
+
```
|
90
|
+
|
91
|
+
You can manually populate the database from within the app, or alternatively you can use seed data for testing. A sample `seeds.rb` file can be found [here](../master/test/dummy/db/seeds.rb).
|
92
|
+
|
93
|
+
## Contributing
|
94
|
+
|
95
|
+
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
|
+
|
97
|
+
## License
|
98
|
+
|
99
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'yard'
|
10
|
+
|
11
|
+
YARD::Rake::YardocTask.new(:yardoc) do |t|
|
12
|
+
t.files = ['lib/**/*.rb', 'app/**/*.rb']
|
13
|
+
end
|
14
|
+
|
15
|
+
APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
|
16
|
+
load 'rails/tasks/engine.rake'
|
17
|
+
|
18
|
+
load 'rails/tasks/statistics.rake'
|
19
|
+
|
20
|
+
require 'bundler/gem_tasks'
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
|
24
|
+
Rake::TestTask.new(:test) do |t|
|
25
|
+
t.libs << 'test'
|
26
|
+
t.pattern = 'test/**/*_test.rb'
|
27
|
+
t.verbose = false
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'rubocop/rake_task'
|
31
|
+
|
32
|
+
RuboCop::RakeTask.new do |t|
|
33
|
+
t.options << '--parallel' if ENV['CI']
|
34
|
+
end
|
35
|
+
|
36
|
+
task default: :test
|
@@ -0,0 +1,72 @@
|
|
1
|
+
//= require spina/admin/journal/html5sortable
|
2
|
+
/* global sortable */
|
3
|
+
|
4
|
+
$(document).on('turbolinks:load', () => {
|
5
|
+
// html5sortable configuration
|
6
|
+
sortable('.html5sortable', {
|
7
|
+
items: 'tr',
|
8
|
+
itemSerializer: (serializedItem) => {
|
9
|
+
return {
|
10
|
+
position: serializedItem.index + 1,
|
11
|
+
id: serializedItem.node.getAttribute('data-id')
|
12
|
+
};
|
13
|
+
},
|
14
|
+
containerSerializer: (serializedContainer) => {
|
15
|
+
return {
|
16
|
+
name: serializedContainer.node.getAttribute('data-sorted-collection')
|
17
|
+
};
|
18
|
+
}
|
19
|
+
});
|
20
|
+
|
21
|
+
// add sorting event listener if there is a sortable container on the page
|
22
|
+
if(typeof sortable('.html5sortable')[0] !== 'undefined') {
|
23
|
+
sortable('.html5sortable')[0].addEventListener('sortupdate', e => {
|
24
|
+
let container = e.detail.destination.container;
|
25
|
+
let serialized = sortable('.html5sortable', 'serialize')[0];
|
26
|
+
let data = serialized.items.reduce((map, obj) => {
|
27
|
+
map[`${serialized.container.name}[list[${obj.id}]]`] = obj.position;
|
28
|
+
return map;
|
29
|
+
}, {});
|
30
|
+
|
31
|
+
let displayError = (...args) => {
|
32
|
+
let message = 'An unknown error occured.'; // not translateable (but should never happen)
|
33
|
+
if(typeof args[0] === 'string') {
|
34
|
+
message = args[0];
|
35
|
+
}
|
36
|
+
// display error message
|
37
|
+
$('.sort-message').html('');
|
38
|
+
$('.sort-message').removeClass('animate-fadein success');
|
39
|
+
$('.sort-message').width(); // trigger reflow
|
40
|
+
$('.sort-message').html(message).addClass('error animate-fadein');
|
41
|
+
// TODO: return element to its origin
|
42
|
+
// this needs to be done manually, but may not really be necessary since the displayed
|
43
|
+
// numbers won't change
|
44
|
+
};
|
45
|
+
|
46
|
+
// send sort request
|
47
|
+
$.ajax({
|
48
|
+
url: $('.html5sortable').eq(0).data('sort-url'),
|
49
|
+
type: 'PATCH',
|
50
|
+
dataType: 'json',
|
51
|
+
data: data,
|
52
|
+
success: (data) => {
|
53
|
+
if(data.success) {
|
54
|
+
// display success message
|
55
|
+
$('.sort-message').html(''); // clear message
|
56
|
+
$('.sort-message').removeClass('animate-fadein error');
|
57
|
+
$('.sort-message').width(); // trigger reflow (for animation to work)
|
58
|
+
$('.sort-message').html(data.message).addClass('success animate-fadein');
|
59
|
+
// update displayed position number
|
60
|
+
// NB this is done entirely clientside, so there is the potential for desync
|
61
|
+
for(let i = 0; i < container.children.length; i++) {
|
62
|
+
container.children[i].getElementsByClassName('position-display')[0].innerHTML = (i+1).toString();
|
63
|
+
}
|
64
|
+
} else {
|
65
|
+
displayError(data.message);
|
66
|
+
}
|
67
|
+
},
|
68
|
+
error: displayError
|
69
|
+
});
|
70
|
+
});
|
71
|
+
}
|
72
|
+
});
|
@@ -0,0 +1,27 @@
|
|
1
|
+
/* Completely overkill animated message for successful sorting */
|
2
|
+
.sort-message {
|
3
|
+
padding-top: 10px;
|
4
|
+
}
|
5
|
+
|
6
|
+
.sort-message.success {
|
7
|
+
color: green;
|
8
|
+
}
|
9
|
+
|
10
|
+
.sort-message.error {
|
11
|
+
color: red;
|
12
|
+
}
|
13
|
+
|
14
|
+
.animate-fadein {
|
15
|
+
animation-name: fadein;
|
16
|
+
animation-duration: 500ms;
|
17
|
+
animation-timing-function: ease-out;
|
18
|
+
}
|
19
|
+
|
20
|
+
@keyframes fadein {
|
21
|
+
from {
|
22
|
+
opacity: 0.1;
|
23
|
+
}
|
24
|
+
to {
|
25
|
+
opacity: 1;
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spina
|
4
|
+
module Admin
|
5
|
+
module Journal
|
6
|
+
# Custom controller for journal plugin. Sets the layout and adds a flash type.
|
7
|
+
class ApplicationController < AdminController
|
8
|
+
add_flash_types :success
|
9
|
+
|
10
|
+
layout :admin_layout, only: %i[new edit]
|
11
|
+
|
12
|
+
before_action :set_locale
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def admin_layout
|
17
|
+
'spina/admin/admin'
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_locale
|
21
|
+
@locale = params[:locale] || I18n.default_locale
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spina
|
4
|
+
module Admin
|
5
|
+
module Journal
|
6
|
+
# Controller for {Article} records.
|
7
|
+
class ArticlesController < ApplicationController
|
8
|
+
PARTS_PARAMS = [
|
9
|
+
:name, :title, :type, :content, :filename, :signed_blob_id, :alt, :attachment_id, :image_id,
|
10
|
+
{ images_attributes: %i[filename signed_blob_id image_id alt],
|
11
|
+
content_attributes: [
|
12
|
+
:name, :title,
|
13
|
+
{ parts_attributes: [
|
14
|
+
:name, :title, :type, :content, :filename, :signed_blob_id, :alt, :attachment_id, :image_id,
|
15
|
+
{ images_attributes: %i[filename signed_blob_id image_id alt] }
|
16
|
+
] }
|
17
|
+
] }
|
18
|
+
].freeze
|
19
|
+
CONTENT_PARAMS = Spina.config.locales.inject({}) do |params, locale|
|
20
|
+
params.merge("#{locale}_content_attributes": [*PARTS_PARAMS])
|
21
|
+
end
|
22
|
+
PARAMS = [:issue_id, :title, :url, :doi, { affiliation_ids: [], **CONTENT_PARAMS }].freeze
|
23
|
+
PARTS = %w[abstract attachment].freeze
|
24
|
+
|
25
|
+
before_action :set_breadcrumb
|
26
|
+
before_action :set_tabs, except: %i[index destroy sort]
|
27
|
+
before_action :set_article, only: %i[edit update destroy]
|
28
|
+
before_action :set_parts_attributes, only: %i[new edit]
|
29
|
+
before_action :build_parts, only: %i[edit]
|
30
|
+
|
31
|
+
def index
|
32
|
+
@articles = Article.sorted_desc
|
33
|
+
end
|
34
|
+
|
35
|
+
def new
|
36
|
+
@article = Article.new
|
37
|
+
build_parts
|
38
|
+
add_breadcrumb t('.new')
|
39
|
+
end
|
40
|
+
|
41
|
+
def edit; end
|
42
|
+
|
43
|
+
def create
|
44
|
+
@article = Article.new(article_params)
|
45
|
+
sister_articles = Article.where(issue: @article.issue_id)
|
46
|
+
@article.number = sister_articles.any? ? sister_articles.sorted_desc.first.number + 1 : 1
|
47
|
+
|
48
|
+
if @article.save
|
49
|
+
redirect_to admin_journal_articles_path, success: t('.saved')
|
50
|
+
else
|
51
|
+
render :new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def update
|
56
|
+
if @article.update(article_params)
|
57
|
+
redirect_to admin_journal_articles_path, success: t('.saved')
|
58
|
+
else
|
59
|
+
render :edit
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def destroy
|
64
|
+
@article.destroy
|
65
|
+
respond_to do |format|
|
66
|
+
format.html do
|
67
|
+
redirect_to admin_journal_articles_path, success: t('.deleted')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def sort
|
73
|
+
ActiveRecord::Base.transaction do
|
74
|
+
sort_params.each do |id, new_pos|
|
75
|
+
Article.find(id.to_i).update_attribute(:number, new_pos.to_i) # rubocop:disable Rails/SkipsModelValidations
|
76
|
+
end
|
77
|
+
validate_sort_order
|
78
|
+
end
|
79
|
+
render json: { success: true, message: t('.sort_success') }
|
80
|
+
rescue ActiveRecord::RecordInvalid
|
81
|
+
render json: { success: false, message: t('.sort_error') }
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def article_params
|
87
|
+
params.require(:admin_journal_article).permit(PARAMS)
|
88
|
+
end
|
89
|
+
|
90
|
+
def sort_params
|
91
|
+
params.require(:admin_journal_articles).require(:list).permit!
|
92
|
+
end
|
93
|
+
|
94
|
+
def validate_sort_order
|
95
|
+
Article.where(issue_id: params[:issue_id]).each do |article|
|
96
|
+
raise ActiveRecord::RecordInvalid if article.invalid?
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def set_breadcrumb
|
101
|
+
add_breadcrumb Article.model_name.human(count: :many), admin_journal_articles_path
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_tabs
|
105
|
+
@tabs = %w[details authors]
|
106
|
+
end
|
107
|
+
|
108
|
+
def set_article
|
109
|
+
@article = Article.find(params[:id])
|
110
|
+
add_breadcrumb @article.title
|
111
|
+
end
|
112
|
+
|
113
|
+
def set_parts_attributes
|
114
|
+
@parts_attributes = current_theme.parts.select { |part| PARTS.include? part[:name] }
|
115
|
+
end
|
116
|
+
|
117
|
+
def build_parts
|
118
|
+
return unless @parts_attributes.is_a? Array
|
119
|
+
|
120
|
+
@parts = @parts_attributes.collect { |part_attributes| @article.part(part_attributes) }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spina
|
4
|
+
module Admin
|
5
|
+
module Journal
|
6
|
+
# Controller for {Author} records and their corresponding {Affiliation}s.
|
7
|
+
class AuthorsController < ApplicationController
|
8
|
+
before_action :set_breadcrumb
|
9
|
+
before_action :set_tabs, except: %i[index destroy]
|
10
|
+
before_action :set_author, only: %i[edit update destroy]
|
11
|
+
|
12
|
+
def index
|
13
|
+
@authors = Author.all
|
14
|
+
end
|
15
|
+
|
16
|
+
def new
|
17
|
+
@author = Author.new
|
18
|
+
@author.affiliations << Affiliation.new(status: :primary)
|
19
|
+
end
|
20
|
+
|
21
|
+
def edit; end
|
22
|
+
|
23
|
+
def create
|
24
|
+
@author = Author.new(modified_params)
|
25
|
+
if @author.save
|
26
|
+
redirect_to admin_journal_authors_path, success: t('.saved')
|
27
|
+
else
|
28
|
+
render :new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def update
|
33
|
+
if @author.update(modified_params)
|
34
|
+
redirect_to admin_journal_authors_path, success: t('.saved')
|
35
|
+
else
|
36
|
+
render :edit
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
@author.destroy
|
42
|
+
respond_to do |format|
|
43
|
+
format.html do
|
44
|
+
redirect_to admin_journal_authors_path, success: t('.deleted')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def author_params
|
52
|
+
params.require(:admin_journal_author).permit(:primary_affiliation_index,
|
53
|
+
affiliations_attributes: %i[id institution_id first_name
|
54
|
+
surname])
|
55
|
+
end
|
56
|
+
|
57
|
+
def modified_params
|
58
|
+
primary_affiliation_index = params[:admin_journal_author][:primary_affiliation_index]
|
59
|
+
new_params = author_params.except :primary_affiliation_index
|
60
|
+
unless new_params[:affiliations_attributes].nil? || primary_affiliation_index.nil?
|
61
|
+
new_params[:affiliations_attributes].each_key do |index|
|
62
|
+
new_params[:affiliations_attributes][index][:status] = index == primary_affiliation_index ? 'primary' : 'other' # rubocop:disable Layout/LineLength
|
63
|
+
end
|
64
|
+
end
|
65
|
+
new_params
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_breadcrumb
|
69
|
+
add_breadcrumb Author.model_name.human(count: :many), admin_journal_authors_path
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_tabs
|
73
|
+
@tabs = %w[details articles]
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_author
|
77
|
+
@author = Author.find(params[:id])
|
78
|
+
add_breadcrumb @author.primary_affiliation.name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|