govuk_content_models 8.2.0 → 8.3.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.
- 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
|