govuk_content_models 8.2.0 → 8.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +18 -0
- data/app/models/edition.rb +1 -0
- data/app/models/specialist_document_edition.rb +14 -213
- data/lib/govuk_content_models/version.rb +1 -1
- data/test/models/edition_test.rb +28 -0
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 8.3.0
|
2
|
+
|
3
|
+
Add `editors_note` field to the edition model
|
4
|
+
|
5
|
+
## 8.2.0
|
6
|
+
* Added support for publishing editions in the future
|
7
|
+
* Removed #capitalized_state_name, in favor of #status_text which shows a publish_at time for editions scheduled for publishing
|
8
|
+
|
9
|
+
## 8.1.0
|
10
|
+
|
11
|
+
This adds a new tag type for an artefact called "organisations".
|
12
|
+
|
13
|
+
## 8.0.0
|
14
|
+
* Remove `lined_up` state and `start_work` transition
|
15
|
+
* `draft` is the new default state
|
16
|
+
* Editions can now be transitioned from Out for fact check and Ready to Amends needed
|
17
|
+
* Fact check received can transition back to Out for fact check
|
18
|
+
|
1
19
|
## 7.2.1
|
2
20
|
|
3
21
|
Added Finder artefact kind
|
data/app/models/edition.rb
CHANGED
@@ -1,30 +1,15 @@
|
|
1
|
-
require "workflow"
|
2
1
|
require "fact_check_address"
|
3
2
|
|
4
3
|
class SpecialistDocumentEdition
|
5
4
|
include Mongoid::Document
|
6
5
|
include Mongoid::Timestamps
|
7
|
-
include Workflow
|
8
6
|
|
9
7
|
field :document_id, type: String
|
10
8
|
field :version_number, type: Integer, default: 1
|
11
|
-
field :sibling_in_progress, type: Integer, default: nil
|
12
|
-
field :business_proposition, type: Boolean, default: false
|
13
9
|
|
14
10
|
field :title, type: String
|
15
11
|
field :created_at, type: DateTime, default: lambda { Time.zone.now }
|
16
|
-
field :overview, type: String
|
17
|
-
field :alternative_title, type: String
|
18
12
|
field :slug, type: String
|
19
|
-
field :section, type: String
|
20
|
-
field :department, type: String
|
21
|
-
field :rejected_count, type: Integer, default: 0
|
22
|
-
field :tags, type: String
|
23
|
-
|
24
|
-
field :assignee, type: String
|
25
|
-
field :creator, type: String
|
26
|
-
field :publisher, type: String
|
27
|
-
field :archiver, type: String
|
28
13
|
|
29
14
|
field :summary, type: String
|
30
15
|
field :body, type: String
|
@@ -35,30 +20,27 @@ class SpecialistDocumentEdition
|
|
35
20
|
field :market_sector, type: String
|
36
21
|
field :outcome_type, type: String
|
37
22
|
|
38
|
-
|
23
|
+
field :state, type: String
|
24
|
+
|
25
|
+
state_machine initial: :draft do
|
26
|
+
event :publish do
|
27
|
+
transition draft: :published
|
28
|
+
end
|
29
|
+
|
30
|
+
event :archive do
|
31
|
+
transition all => :archived, :unless => :archived?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
GOVSPEAK_FIELDS = [:body]
|
39
36
|
|
40
37
|
def whole_body
|
41
38
|
self.body
|
42
39
|
end
|
43
40
|
|
44
|
-
belongs_to :assigned_to, class_name: "User"
|
45
|
-
|
46
41
|
scope :draft, where(state: "draft")
|
47
|
-
scope :amends_needed, where(state: "amends_needed")
|
48
|
-
scope :in_review, where(state: "in_review")
|
49
|
-
scope :fact_check, where(state: "fact_check")
|
50
|
-
scope :fact_check_received, where(state: "fact_check_received")
|
51
|
-
scope :ready, where(state: "ready")
|
52
42
|
scope :published, where(state: "published")
|
53
43
|
scope :archived, where(state: "archived")
|
54
|
-
scope :in_progress, where(:state.nin => ["archived", "published"])
|
55
|
-
scope :assigned_to, lambda { |user|
|
56
|
-
if user
|
57
|
-
where(assigned_to_id: user.id)
|
58
|
-
else
|
59
|
-
where(:assigned_to_id.exists => false)
|
60
|
-
end
|
61
|
-
}
|
62
44
|
|
63
45
|
validates :title, presence: true
|
64
46
|
validates :summary, presence: true
|
@@ -71,21 +53,11 @@ class SpecialistDocumentEdition
|
|
71
53
|
validates :document_id, presence: true
|
72
54
|
validates_with SafeHtml
|
73
55
|
|
74
|
-
index "assigned_to_id"
|
75
56
|
index "document_id"
|
76
57
|
index "state"
|
77
58
|
|
78
|
-
class << self; attr_accessor :fields_to_clone end
|
79
|
-
@fields_to_clone = []
|
80
|
-
|
81
|
-
alias_method :admin_list_title, :title
|
82
|
-
|
83
59
|
def series
|
84
|
-
SpecialistDocumentEdition.where(document_id: document_id)
|
85
|
-
end
|
86
|
-
|
87
|
-
def history
|
88
|
-
series.order([:version_number, :desc])
|
60
|
+
::SpecialistDocumentEdition.where(document_id: document_id)
|
89
61
|
end
|
90
62
|
|
91
63
|
def siblings
|
@@ -103,175 +75,4 @@ class SpecialistDocumentEdition
|
|
103
75
|
def latest_edition?
|
104
76
|
subsequent_siblings.empty?
|
105
77
|
end
|
106
|
-
|
107
|
-
def published_edition
|
108
|
-
series.where(state: "published").order(version_number: "desc").first
|
109
|
-
end
|
110
|
-
|
111
|
-
def previous_published_edition
|
112
|
-
series.where(state: "published").order(version_number: "desc").second
|
113
|
-
end
|
114
|
-
|
115
|
-
def in_progress_sibling
|
116
|
-
subsequent_siblings.in_progress.order(version_number: "desc").first
|
117
|
-
end
|
118
|
-
|
119
|
-
def can_create_new_edition?
|
120
|
-
subsequent_siblings.in_progress.empty?
|
121
|
-
end
|
122
|
-
|
123
|
-
def meta_data
|
124
|
-
PublicationMetadata.new self
|
125
|
-
end
|
126
|
-
|
127
|
-
def fact_check_email_address
|
128
|
-
FactCheckAddress.new.for_edition(self)
|
129
|
-
end
|
130
|
-
|
131
|
-
def get_next_version_number
|
132
|
-
latest_version = series.order(version_number: "desc").first.version_number
|
133
|
-
latest_version + 1
|
134
|
-
end
|
135
|
-
|
136
|
-
def indexable_content
|
137
|
-
respond_to?(:parts) ? indexable_content_with_parts : indexable_content_without_parts
|
138
|
-
end
|
139
|
-
|
140
|
-
def indexable_content_without_parts
|
141
|
-
if respond_to?(:body)
|
142
|
-
"#{alternative_title} #{Govspeak::Document.new(body).to_text}".strip
|
143
|
-
else
|
144
|
-
alternative_title
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def indexable_content_with_parts
|
149
|
-
content = indexable_content_without_parts
|
150
|
-
return content unless published_edition
|
151
|
-
parts.inject([content]) { |acc, part|
|
152
|
-
acc.concat([part.title, Govspeak::Document.new(part.body).to_text])
|
153
|
-
}.compact.join(" ").strip
|
154
|
-
end
|
155
|
-
|
156
|
-
# If the new clone is of the same type, we can copy all its fields over; if
|
157
|
-
# we are changing the type of the edition, any fields other than the base
|
158
|
-
# fields will likely be meaningless.
|
159
|
-
def fields_to_copy(edition_class)
|
160
|
-
edition_class == self.class ? self.class.fields_to_clone : []
|
161
|
-
end
|
162
|
-
|
163
|
-
def build_clone(edition_class=nil)
|
164
|
-
unless state == "published"
|
165
|
-
raise "Cloning of non published edition not allowed"
|
166
|
-
end
|
167
|
-
unless can_create_new_edition?
|
168
|
-
raise "Cloning of a published edition when an in-progress edition exists
|
169
|
-
is not allowed"
|
170
|
-
end
|
171
|
-
|
172
|
-
edition_class = self.class unless edition_class
|
173
|
-
new_edition = edition_class.new(title: self.title,
|
174
|
-
version_number: get_next_version_number)
|
175
|
-
|
176
|
-
real_fields_to_merge = fields_to_copy(edition_class) +
|
177
|
-
[:panopticon_id, :overview, :alternative_title,
|
178
|
-
:slug, :section, :department]
|
179
|
-
|
180
|
-
real_fields_to_merge.each do |attr|
|
181
|
-
new_edition[attr] = read_attribute(attr)
|
182
|
-
end
|
183
|
-
|
184
|
-
if edition_class == AnswerEdition and %w(GuideEdition ProgrammeEdition TransactionEdition).include?(self.class.name)
|
185
|
-
new_edition.body = whole_body
|
186
|
-
end
|
187
|
-
|
188
|
-
if edition_class == TransactionEdition and %w(AnswerEdition GuideEdition ProgrammeEdition).include?(self.class.name)
|
189
|
-
new_edition.more_information = whole_body
|
190
|
-
end
|
191
|
-
|
192
|
-
if edition_class == GuideEdition and self.is_a?(AnswerEdition)
|
193
|
-
new_edition.parts.build(title: "Part One", body: whole_body,
|
194
|
-
slug: "part-one")
|
195
|
-
end
|
196
|
-
|
197
|
-
new_edition
|
198
|
-
end
|
199
|
-
|
200
|
-
def self.find_or_create_from_panopticon_data(panopticon_id,
|
201
|
-
importing_user, api_credentials)
|
202
|
-
existing_publication = Edition.where(panopticon_id: panopticon_id)
|
203
|
-
.order_by([:version_number, :desc]).first
|
204
|
-
return existing_publication if existing_publication
|
205
|
-
|
206
|
-
raise "Artefact not found" unless metadata = Artefact.find(panopticon_id)
|
207
|
-
|
208
|
-
importing_user.create_edition(metadata.kind.to_sym,
|
209
|
-
panopticon_id: metadata.id,
|
210
|
-
slug: metadata.slug,
|
211
|
-
title: metadata.name,
|
212
|
-
section: metadata.section,
|
213
|
-
department: metadata.department,
|
214
|
-
business_proposition: metadata.business_proposition)
|
215
|
-
end
|
216
|
-
|
217
|
-
def self.find_and_identify(slug, edition)
|
218
|
-
scope = where(slug: slug)
|
219
|
-
|
220
|
-
if edition.present? and edition == "latest"
|
221
|
-
scope.order_by(:version_number).last
|
222
|
-
elsif edition.present?
|
223
|
-
scope.where(version_number: edition).first
|
224
|
-
else
|
225
|
-
scope.where(state: "published").order_by(:created_at).last
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def panopticon_uri
|
230
|
-
Plek.current.find("panopticon") + "/artefacts/" + (panopticon_id || slug).to_s
|
231
|
-
end
|
232
|
-
|
233
|
-
def format
|
234
|
-
self.class.to_s.gsub("Edition", "")
|
235
|
-
end
|
236
|
-
|
237
|
-
def format_name
|
238
|
-
format
|
239
|
-
end
|
240
|
-
|
241
|
-
def has_video?
|
242
|
-
false
|
243
|
-
end
|
244
|
-
|
245
|
-
def safe_to_preview?
|
246
|
-
true
|
247
|
-
end
|
248
|
-
|
249
|
-
def has_sibling_in_progress?
|
250
|
-
! sibling_in_progress.nil?
|
251
|
-
end
|
252
|
-
|
253
|
-
# Stop broadcasting a delete message unless there are no siblings.
|
254
|
-
def broadcast_action(callback_action)
|
255
|
-
unless callback_action == "destroyed" and self.siblings.any?
|
256
|
-
super(callback_action)
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def was_published
|
261
|
-
previous_siblings.all.each(&:archive)
|
262
|
-
notify_siblings_of_published_edition
|
263
|
-
end
|
264
|
-
|
265
|
-
def update_from_artefact(artefact)
|
266
|
-
self.title = artefact.name unless published?
|
267
|
-
self.slug = artefact.slug
|
268
|
-
self.section = artefact.section
|
269
|
-
self.department = artefact.department
|
270
|
-
self.business_proposition = artefact.business_proposition
|
271
|
-
self.save!
|
272
|
-
end
|
273
|
-
|
274
|
-
def artefact
|
275
|
-
Artefact.find(panopticon_id)
|
276
|
-
end
|
277
78
|
end
|
data/test/models/edition_test.rb
CHANGED
@@ -992,4 +992,32 @@ class EditionTest < ActiveSupport::TestCase
|
|
992
992
|
end
|
993
993
|
end
|
994
994
|
end
|
995
|
+
|
996
|
+
context "Editors note" do
|
997
|
+
def set_note(edition, note)
|
998
|
+
edition.editors_note = note
|
999
|
+
edition.save
|
1000
|
+
edition.reload
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
setup do
|
1004
|
+
@edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "ready")
|
1005
|
+
set_note(@edition, "This is an important note.")
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
should "be able to add an editors note to an edition" do
|
1009
|
+
assert_equal "This is an important note.", @edition.editors_note
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
should "be able to update an existing editors note" do
|
1013
|
+
set_note(@edition, "New note.")
|
1014
|
+
assert_equal "New note.", @edition.editors_note
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
should "should not exist when creating new editions" do
|
1018
|
+
Edition.subclasses.each do |klass|
|
1019
|
+
refute klass.fields_to_clone.include?(:editors_note), "Editors note is cloned in a #{klass}"
|
1020
|
+
end
|
1021
|
+
end
|
1022
|
+
end
|
995
1023
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_content_models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.
|
4
|
+
version: 8.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-03-
|
12
|
+
date: 2014-03-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bson_ext
|
@@ -458,7 +458,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
458
458
|
version: '0'
|
459
459
|
segments:
|
460
460
|
- 0
|
461
|
-
hash:
|
461
|
+
hash: 273183051789129622
|
462
462
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
463
463
|
none: false
|
464
464
|
requirements:
|
@@ -467,7 +467,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
467
467
|
version: '0'
|
468
468
|
segments:
|
469
469
|
- 0
|
470
|
-
hash:
|
470
|
+
hash: 273183051789129622
|
471
471
|
requirements: []
|
472
472
|
rubyforge_project:
|
473
473
|
rubygems_version: 1.8.23
|