wikidata_position_history 1.9.0 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/query_service.rb +8 -0
- data/lib/sparql/bio_query.rb +3 -9
- data/lib/sparql/item_query.rb +30 -1
- data/lib/sparql/mandates_query.rb +8 -33
- data/lib/sparql/position_query.rb +17 -47
- data/lib/wikidata_position_history.rb +1 -0
- data/lib/wikidata_position_history/output_row.rb +144 -0
- data/lib/wikidata_position_history/report.rb +38 -74
- data/lib/wikidata_position_history/template.rb +20 -14
- data/lib/wikidata_position_history/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d45377b5ba871d76f191e7dafe516f308c4f1b17f166b19d0658ee15fff98745
|
4
|
+
data.tar.gz: ede75c366b3cf99a417ab402f5151880a477b3aa1fc10ff0d4261fb7b7fc0d44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 141397d38a5a771e8b2cb159bcd8db327d50f157ba93539b09bb08ff23a64a60e6aa4bdac2bf1a45bdd65dc2f8d343e1a4737a89fc939eafe7ed25e7473562ff
|
7
|
+
data.tar.gz: 0a3cb133222f05d0ff46dd7810a62a72f3b19ca1f7431bf265752867b916b8ef176f04e11b65a50d2b6ed8d04ba20dc3ecf6fe73cd5fb24caf98737f401b685b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
# [1.10.0] 2020-09-13
|
4
|
+
|
5
|
+
## Enhancements
|
6
|
+
|
7
|
+
* If some other position has a "replaces" (P1365) or "replaced by"
|
8
|
+
(P1366) pointing to _this_ position, but this position doesn't have
|
9
|
+
the reciprocal inverse claims back to that one, include them as a
|
10
|
+
successor/predecessor, but warn that it’s only an indirect connection.
|
11
|
+
|
12
|
+
* The warnings in the above case now use an on-wiki template for their
|
13
|
+
text. This means they can be translated into other languages, and also
|
14
|
+
means that backlinks to these templates, via WhatLinksHere, can act as
|
15
|
+
a TODO list. The other warnings will be migrated to this approach Real
|
16
|
+
Soon Now™.
|
17
|
+
|
3
18
|
# [1.9.0] 2020-09-11
|
4
19
|
|
5
20
|
## Enhancements
|
data/lib/query_service.rb
CHANGED
@@ -37,6 +37,10 @@ module QueryService
|
|
37
37
|
@url = url
|
38
38
|
end
|
39
39
|
|
40
|
+
def eql?(other)
|
41
|
+
id == other.id
|
42
|
+
end
|
43
|
+
|
40
44
|
def id
|
41
45
|
url.split('/').last unless url.to_s.empty?
|
42
46
|
end
|
@@ -45,6 +49,10 @@ module QueryService
|
|
45
49
|
"{{Q|#{id}}}" if id
|
46
50
|
end
|
47
51
|
|
52
|
+
def qlink_i
|
53
|
+
"''{{Q|#{id}}}''" if id
|
54
|
+
end
|
55
|
+
|
48
56
|
private
|
49
57
|
|
50
58
|
attr_reader :url
|
data/lib/sparql/bio_query.rb
CHANGED
@@ -24,13 +24,9 @@ module WikidataPositionHistory
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Represents a single row returned from the Position query
|
27
|
-
class BioRow
|
28
|
-
def initialize(row)
|
29
|
-
@row = row
|
30
|
-
end
|
31
|
-
|
27
|
+
class BioRow < SPARQL::QueryRow
|
32
28
|
def person
|
33
|
-
|
29
|
+
item_from(:item)
|
34
30
|
end
|
35
31
|
|
36
32
|
def image_title
|
@@ -47,10 +43,8 @@ module WikidataPositionHistory
|
|
47
43
|
|
48
44
|
private
|
49
45
|
|
50
|
-
attr_reader :row
|
51
|
-
|
52
46
|
def image_url
|
53
|
-
|
47
|
+
raw(:image)
|
54
48
|
end
|
55
49
|
end
|
56
50
|
end
|
data/lib/sparql/item_query.rb
CHANGED
@@ -4,7 +4,7 @@ require 'erb'
|
|
4
4
|
|
5
5
|
module WikidataPositionHistory
|
6
6
|
module SPARQL
|
7
|
-
#
|
7
|
+
# Abstract class to turn raw SPARQL into result objects
|
8
8
|
class ItemQuery
|
9
9
|
def initialize(itemid)
|
10
10
|
@itemid = itemid
|
@@ -34,5 +34,34 @@ module WikidataPositionHistory
|
|
34
34
|
@json ||= QueryService::Query.new(sparql).results
|
35
35
|
end
|
36
36
|
end
|
37
|
+
|
38
|
+
# Abstract class to represents a single row returned from a query
|
39
|
+
class QueryRow
|
40
|
+
def initialize(row)
|
41
|
+
@row = row
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
attr_reader :row
|
47
|
+
|
48
|
+
def item_from(key)
|
49
|
+
value = raw(key)
|
50
|
+
return if value.to_s.empty?
|
51
|
+
|
52
|
+
QueryService::WikidataItem.new(value)
|
53
|
+
end
|
54
|
+
|
55
|
+
def date_from(key, precision_key)
|
56
|
+
trunc = raw(key).to_s[0..9]
|
57
|
+
return if trunc.empty?
|
58
|
+
|
59
|
+
QueryService::WikidataDate.new(trunc, raw(precision_key))
|
60
|
+
end
|
61
|
+
|
62
|
+
def raw(key)
|
63
|
+
row.dig(key, :value)
|
64
|
+
end
|
65
|
+
end
|
37
66
|
end
|
38
67
|
end
|
@@ -28,17 +28,13 @@ module WikidataPositionHistory
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# Represents a single row returned from the Mandates query
|
31
|
-
class MandateRow
|
32
|
-
def initialize(row)
|
33
|
-
@row = row
|
34
|
-
end
|
35
|
-
|
31
|
+
class MandateRow < SPARQL::QueryRow
|
36
32
|
def ordinal
|
37
|
-
|
33
|
+
raw(:ordinal)
|
38
34
|
end
|
39
35
|
|
40
36
|
def officeholder
|
41
|
-
|
37
|
+
item_from(:item)
|
42
38
|
end
|
43
39
|
|
44
40
|
# TODO: rename or remove. 'item' is meaningless/ambiguous
|
@@ -46,14 +42,17 @@ module WikidataPositionHistory
|
|
46
42
|
officeholder.qlink
|
47
43
|
end
|
48
44
|
|
45
|
+
# TODO: switch to item_from
|
49
46
|
def prev
|
50
47
|
QueryService::WikidataItem.new(row.dig(:prev, :value)).qlink
|
51
48
|
end
|
52
49
|
|
50
|
+
# TODO: switch to item_from
|
53
51
|
def next
|
54
52
|
QueryService::WikidataItem.new(row.dig(:next, :value)).qlink
|
55
53
|
end
|
56
54
|
|
55
|
+
# TODO: switch to item_from
|
57
56
|
def nature
|
58
57
|
QueryService::WikidataItem.new(row.dig(:nature, :value)).id
|
59
58
|
end
|
@@ -63,35 +62,11 @@ module WikidataPositionHistory
|
|
63
62
|
end
|
64
63
|
|
65
64
|
def start_date
|
66
|
-
|
67
|
-
|
68
|
-
QueryService::WikidataDate.new(start_date_raw, start_date_precision)
|
65
|
+
date_from(:start_date, :start_precision)
|
69
66
|
end
|
70
67
|
|
71
68
|
def end_date
|
72
|
-
|
73
|
-
|
74
|
-
QueryService::WikidataDate.new(end_date_raw, end_date_precision)
|
75
|
-
end
|
76
|
-
|
77
|
-
def start_date_raw
|
78
|
-
row.dig(:start_date, :value).to_s[0..9]
|
79
|
-
end
|
80
|
-
|
81
|
-
def end_date_raw
|
82
|
-
row.dig(:end_date, :value).to_s[0..9]
|
83
|
-
end
|
84
|
-
|
85
|
-
def start_date_precision
|
86
|
-
row.dig(:start_precision, :value)
|
69
|
+
date_from(:end_date, :end_precision)
|
87
70
|
end
|
88
|
-
|
89
|
-
def end_date_precision
|
90
|
-
row.dig(:end_precision, :value)
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
attr_reader :row
|
96
71
|
end
|
97
72
|
end
|
@@ -9,7 +9,7 @@ module WikidataPositionHistory
|
|
9
9
|
# position-metadata
|
10
10
|
|
11
11
|
SELECT DISTINCT ?item ?inception ?inception_precision ?abolition ?abolition_precision
|
12
|
-
?replaces ?replacedBy
|
12
|
+
?replaces ?replacedBy ?derivedReplaces ?derivedReplacedBy
|
13
13
|
?isPosition ?isLegislator
|
14
14
|
WHERE {
|
15
15
|
VALUES ?item { wd:%s }
|
@@ -23,6 +23,8 @@ module WikidataPositionHistory
|
|
23
23
|
] }
|
24
24
|
OPTIONAL { ?item wdt:P1365 ?replaces }
|
25
25
|
OPTIONAL { ?item wdt:P1366 ?replacedBy }
|
26
|
+
OPTIONAL { ?derivedReplaces wdt:P1366 ?item }
|
27
|
+
OPTIONAL { ?derivedReplacedBy wdt:P1365 ?item }
|
26
28
|
}
|
27
29
|
SPARQL
|
28
30
|
end
|
@@ -34,73 +36,41 @@ module WikidataPositionHistory
|
|
34
36
|
end
|
35
37
|
|
36
38
|
# Represents a single row returned from the Position query
|
37
|
-
class PositionRow
|
38
|
-
def initialize(row)
|
39
|
-
@row = row
|
40
|
-
end
|
41
|
-
|
39
|
+
class PositionRow < SPARQL::QueryRow
|
42
40
|
def item
|
43
|
-
|
41
|
+
item_from(:item)
|
44
42
|
end
|
45
43
|
|
46
44
|
def inception_date
|
47
|
-
|
48
|
-
|
49
|
-
QueryService::WikidataDate.new(inception_date_raw, inception_date_precision)
|
45
|
+
date_from(:inception, :inception_precision)
|
50
46
|
end
|
51
47
|
|
52
48
|
def abolition_date
|
53
|
-
|
54
|
-
|
55
|
-
QueryService::WikidataDate.new(abolition_date_raw, abolition_date_precision)
|
49
|
+
date_from(:abolition, :abolition_precision)
|
56
50
|
end
|
57
51
|
|
58
52
|
def replaces
|
59
|
-
|
60
|
-
|
61
|
-
QueryService::WikidataItem.new(replaces_raw)
|
53
|
+
item_from(:replaces)
|
62
54
|
end
|
63
55
|
|
64
56
|
def replaced_by
|
65
|
-
|
66
|
-
|
67
|
-
QueryService::WikidataItem.new(replaced_by_raw)
|
68
|
-
end
|
69
|
-
|
70
|
-
def position?
|
71
|
-
row.dig(:isPosition, :value) == 'true'
|
72
|
-
end
|
73
|
-
|
74
|
-
def legislator?
|
75
|
-
row.dig(:isLegislator, :value) == 'true'
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
attr_reader :row
|
81
|
-
|
82
|
-
def replaces_raw
|
83
|
-
row.dig(:replaces, :value)
|
84
|
-
end
|
85
|
-
|
86
|
-
def replaced_by_raw
|
87
|
-
row.dig(:replacedBy, :value)
|
57
|
+
item_from(:replacedBy)
|
88
58
|
end
|
89
59
|
|
90
|
-
def
|
91
|
-
|
60
|
+
def derived_replaces
|
61
|
+
item_from(:derivedReplaces)
|
92
62
|
end
|
93
63
|
|
94
|
-
def
|
95
|
-
|
64
|
+
def derived_replaced_by
|
65
|
+
item_from(:derivedReplacedBy)
|
96
66
|
end
|
97
67
|
|
98
|
-
def
|
99
|
-
|
68
|
+
def position?
|
69
|
+
raw(:isPosition) == 'true'
|
100
70
|
end
|
101
71
|
|
102
|
-
def
|
103
|
-
|
72
|
+
def legislator?
|
73
|
+
raw(:isLegislator) == 'true'
|
104
74
|
end
|
105
75
|
end
|
106
76
|
end
|
@@ -7,6 +7,7 @@ require 'sparql/bio_query'
|
|
7
7
|
require 'sparql/mandates_query'
|
8
8
|
require 'wikidata_position_history/checks'
|
9
9
|
require 'wikidata_position_history/template'
|
10
|
+
require 'wikidata_position_history/output_row'
|
10
11
|
require 'wikidata_position_history/report'
|
11
12
|
require 'wikidata_position_history/version'
|
12
13
|
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WikidataPositionHistory
|
4
|
+
# simplified version of a WikidataPositionHistory::Check
|
5
|
+
Warning = Struct.new(:headline, :explanation)
|
6
|
+
|
7
|
+
class OutputRow
|
8
|
+
# Date for a single mandate row, to be passed to the report template
|
9
|
+
class Mandate
|
10
|
+
CHECKS = [Check::MissingFields, Check::Overlap,
|
11
|
+
Check::WrongPredecessor, Check::MissingPredecessor,
|
12
|
+
Check::WrongSuccessor, Check::MissingSuccessor].freeze
|
13
|
+
|
14
|
+
def initialize(later, current, earlier)
|
15
|
+
@later = later
|
16
|
+
@current = current
|
17
|
+
@earlier = earlier
|
18
|
+
end
|
19
|
+
|
20
|
+
def ordinal_string
|
21
|
+
ordinal = current.ordinal or return ''
|
22
|
+
"#{ordinal}."
|
23
|
+
end
|
24
|
+
|
25
|
+
def person
|
26
|
+
current.item
|
27
|
+
end
|
28
|
+
|
29
|
+
def dates
|
30
|
+
dates = [current.start_date, current.end_date]
|
31
|
+
return '' if dates.compact.empty?
|
32
|
+
|
33
|
+
dates.join(' – ')
|
34
|
+
end
|
35
|
+
|
36
|
+
def acting?
|
37
|
+
current.acting?
|
38
|
+
end
|
39
|
+
|
40
|
+
def warnings
|
41
|
+
CHECKS.map { |klass| klass.new(later, current, earlier) }.select(&:problem?)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :later, :current, :earlier
|
47
|
+
end
|
48
|
+
|
49
|
+
# Base class for the Inception/Abolition date rows
|
50
|
+
class PositionDate
|
51
|
+
def initialize(metadata)
|
52
|
+
@metadata = metadata
|
53
|
+
end
|
54
|
+
|
55
|
+
def date
|
56
|
+
return if dates.empty?
|
57
|
+
|
58
|
+
dates.join(' / ')
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
attr_reader :metadata
|
64
|
+
|
65
|
+
def qlink
|
66
|
+
metadata.position.qlink
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Data for the Inception date of the position
|
71
|
+
class Inception < PositionDate
|
72
|
+
def warnings
|
73
|
+
count = dates.count
|
74
|
+
return [] if count == 1
|
75
|
+
|
76
|
+
return [Warning.new('Missing field', "#{qlink} is missing {{P|571}}")] if count.zero?
|
77
|
+
|
78
|
+
[Warning.new('Multiple values', "#{qlink} has more than one {{P|571}}")]
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def dates
|
84
|
+
metadata.inception_dates
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Data for the Abolition date of the position
|
89
|
+
class Abolition < PositionDate
|
90
|
+
def warnings
|
91
|
+
return [] unless dates.count > 1
|
92
|
+
|
93
|
+
[Warning.new('Multiple values', "#{qlink} has more than one {{P|576}}")]
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def dates
|
99
|
+
metadata.abolition_dates
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Data for related position: e.g. Successor/Predecessor
|
104
|
+
class RelatedPosition
|
105
|
+
def initialize(metadata)
|
106
|
+
@metadata = metadata
|
107
|
+
end
|
108
|
+
|
109
|
+
def position
|
110
|
+
return if implied_list.empty?
|
111
|
+
|
112
|
+
(implied_list.direct.map(&:qlink) + implied_list.indirect_only.map(&:qlink_i)).join(', ')
|
113
|
+
end
|
114
|
+
|
115
|
+
def warnings
|
116
|
+
implied_list.indirect_only.map do |from|
|
117
|
+
Warning.new('Indirect only', "{{PositionHolderHistory/#{indirect_warning_template}|from=#{from.id}|to=#{metadata.position.id}}}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
attr_reader :metadata
|
124
|
+
|
125
|
+
def indirect_warning_template
|
126
|
+
format('warning_indirect_%s', self.class.name.split('::').last.downcase)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Data for the position that comes after this one
|
131
|
+
class Successor < RelatedPosition
|
132
|
+
def implied_list
|
133
|
+
metadata.replaced_by_combined
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Data for the position that came before this one
|
138
|
+
class Predecessor < RelatedPosition
|
139
|
+
def implied_list
|
140
|
+
metadata.replaces_combined
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -1,97 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module WikidataPositionHistory
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(later, current, earlier)
|
11
|
-
@later = later
|
12
|
-
@current = current
|
13
|
-
@earlier = earlier
|
4
|
+
# A list made up of both direct and indirect claims, where we
|
5
|
+
# can tell which came from which, when required
|
6
|
+
class ImpliedList
|
7
|
+
def initialize(direct, indirect)
|
8
|
+
@direct = direct
|
9
|
+
@indirect = indirect
|
14
10
|
end
|
15
11
|
|
16
|
-
def
|
17
|
-
|
18
|
-
"#{ordinal}."
|
12
|
+
def empty?
|
13
|
+
all.empty?
|
19
14
|
end
|
20
15
|
|
21
|
-
def
|
22
|
-
|
16
|
+
def all
|
17
|
+
direct | indirect
|
23
18
|
end
|
24
19
|
|
25
|
-
def
|
26
|
-
|
27
|
-
return '' if dates.compact.empty?
|
28
|
-
|
29
|
-
dates.join(' – ')
|
20
|
+
def both
|
21
|
+
direct & indirect
|
30
22
|
end
|
31
23
|
|
32
|
-
def
|
33
|
-
|
24
|
+
def direct_only
|
25
|
+
direct - indirect
|
34
26
|
end
|
35
27
|
|
36
|
-
def
|
37
|
-
|
28
|
+
def indirect_only
|
29
|
+
indirect - direct
|
38
30
|
end
|
39
31
|
|
40
|
-
|
41
|
-
|
42
|
-
attr_reader :later, :current, :earlier
|
32
|
+
attr_reader :direct, :indirect
|
43
33
|
end
|
44
34
|
|
45
35
|
# Data about the position itself, to be passed to the report template
|
46
36
|
class Metadata
|
47
|
-
# simplified version of a WikidataPositionHistory::Check
|
48
|
-
Warning = Struct.new(:headline, :explanation)
|
49
|
-
|
50
37
|
def initialize(rows)
|
51
38
|
@rows = rows
|
52
39
|
end
|
53
40
|
|
54
|
-
def
|
41
|
+
def position
|
55
42
|
rows.map(&:item).first
|
56
43
|
end
|
57
44
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
replaces_list.map(&:qlink).join(', ')
|
45
|
+
def predecessor
|
46
|
+
@predecessor ||= OutputRow::Predecessor.new(self)
|
62
47
|
end
|
63
48
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
replaced_by_list.map(&:qlink).join(', ')
|
49
|
+
def successor
|
50
|
+
@successor ||= OutputRow::Successor.new(self)
|
68
51
|
end
|
69
52
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
inception_dates.join(' / ')
|
53
|
+
def inception
|
54
|
+
@inception ||= OutputRow::Inception.new(self)
|
74
55
|
end
|
75
56
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
return if count == 1
|
80
|
-
return Warning.new('Missing field', "#{item_qlink} is missing {{P|571}}") if count.zero?
|
81
|
-
|
82
|
-
Warning.new('Multiple values', "#{item_qlink} has more than one {{P|571}}")
|
83
|
-
end
|
84
|
-
|
85
|
-
def abolition_date
|
86
|
-
return if abolition_dates.empty?
|
87
|
-
|
88
|
-
abolition_dates.join(' / ')
|
89
|
-
end
|
90
|
-
|
91
|
-
def abolition_warning
|
92
|
-
return unless abolition_dates.count > 1
|
93
|
-
|
94
|
-
Warning.new('Multiple values', "#{item_qlink} has more than one {{P|576}}")
|
57
|
+
def abolition
|
58
|
+
@abolition ||= OutputRow::Abolition.new(self)
|
95
59
|
end
|
96
60
|
|
97
61
|
def position?
|
@@ -104,16 +68,12 @@ module WikidataPositionHistory
|
|
104
68
|
rows.map(&:legislator?).first
|
105
69
|
end
|
106
70
|
|
107
|
-
|
108
|
-
|
109
|
-
attr_reader :rows
|
110
|
-
|
111
|
-
def replaces_list
|
112
|
-
rows.map(&:replaces).compact.uniq(&:id).sort_by(&:id)
|
71
|
+
def replaces_combined
|
72
|
+
@replaces_combined ||= ImpliedList.new(uniq_by_id(:replaces), uniq_by_id(:derived_replaces))
|
113
73
|
end
|
114
74
|
|
115
|
-
def
|
116
|
-
|
75
|
+
def replaced_by_combined
|
76
|
+
@replaced_by_combined ||= ImpliedList.new(uniq_by_id(:replaced_by), uniq_by_id(:derived_replaced_by))
|
117
77
|
end
|
118
78
|
|
119
79
|
def inception_dates
|
@@ -124,8 +84,12 @@ module WikidataPositionHistory
|
|
124
84
|
rows.map(&:abolition_date).compact.uniq(&:to_s).sort
|
125
85
|
end
|
126
86
|
|
127
|
-
|
128
|
-
|
87
|
+
private
|
88
|
+
|
89
|
+
attr_reader :rows
|
90
|
+
|
91
|
+
def uniq_by_id(method)
|
92
|
+
rows.map(&method).compact.uniq(&:id).sort_by(&:id)
|
129
93
|
end
|
130
94
|
end
|
131
95
|
|
@@ -150,7 +114,7 @@ module WikidataPositionHistory
|
|
150
114
|
end
|
151
115
|
|
152
116
|
def position_dates
|
153
|
-
dates = [metadata.
|
117
|
+
dates = [metadata.inception.date, metadata.abolition.date]
|
154
118
|
return '' if dates.compact.empty?
|
155
119
|
|
156
120
|
format('(%s)', dates.join(' – '))
|
@@ -205,7 +169,7 @@ module WikidataPositionHistory
|
|
205
169
|
def table_rows
|
206
170
|
padded_mandates.each_cons(3).map do |later, current, earlier|
|
207
171
|
{
|
208
|
-
mandate:
|
172
|
+
mandate: OutputRow::Mandate.new(later, current, earlier),
|
209
173
|
bio: biodata_for(current.officeholder),
|
210
174
|
}
|
211
175
|
end
|
@@ -22,22 +22,25 @@ module WikidataPositionHistory
|
|
22
22
|
def template_text
|
23
23
|
<<~ERB
|
24
24
|
{| class="wikitable" style="text-align: center; border: none;"
|
25
|
-
<% if metadata.
|
25
|
+
<% if metadata.abolition.date -%>
|
26
26
|
|-
|
27
27
|
| colspan="2" style="border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Position abolished''':
|
28
|
-
| style="border: none; background: #fff; text-align: left;" | <%= metadata.
|
28
|
+
| style="border: none; background: #fff; text-align: left;" | <%= metadata.abolition.date %>
|
29
29
|
| style="border: none; background: #fff; text-align: left;" | \
|
30
|
-
<%
|
30
|
+
<% metadata.abolition.warnings.each do |warning| -%>
|
31
31
|
<span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]] <span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span> <ref><%= warning.explanation %></ref></span>\
|
32
32
|
<% end %>
|
33
33
|
<% end -%>
|
34
|
-
<% if metadata.
|
34
|
+
<% if metadata.successor.position -%>
|
35
35
|
|-
|
36
36
|
| colspan="2" style="border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Replaced by''':
|
37
|
-
| style=" border: none; background: #fff; text-align: left;" | <%= metadata.
|
38
|
-
| style=" border: none; background: #fff; text-align: left;" |
|
37
|
+
| style=" border: none; background: #fff; text-align: left;" | <%= metadata.successor.position %>
|
38
|
+
| style=" border: none; background: #fff; text-align: left;" | \
|
39
|
+
<% metadata.successor.warnings.each do |warning| -%>
|
40
|
+
<span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]] <span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span> <ref><%= warning.explanation %></ref></span>\
|
41
|
+
<% end %>
|
39
42
|
<% end -%>
|
40
|
-
<% if metadata.
|
43
|
+
<% if metadata.successor.position || metadata.abolition.date -%>
|
41
44
|
|-
|
42
45
|
| colspan="3" style="padding:0.5em; border: none; background: #fff"> |
|
43
46
|
| colspan="1" style="padding:0.5em; border: none; background: #fff"> |
|
@@ -52,25 +55,28 @@ module WikidataPositionHistory
|
|
52
55
|
<span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]] <span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span> <ref><%= warning.explanation %></ref></span>\
|
53
56
|
<% end %>
|
54
57
|
<% end -%>
|
55
|
-
<% if metadata.
|
58
|
+
<% if metadata.successor.position || metadata.abolition.date -%>
|
56
59
|
|-
|
57
60
|
| colspan="3" style="padding:0.5em; border: none; background: #fff"> |
|
58
61
|
| colspan="1" style="padding:0.5em; border: none; background: #fff"> |
|
59
62
|
<% end -%>
|
60
|
-
<% if metadata.
|
63
|
+
<% if metadata.inception.date -%>
|
61
64
|
|-
|
62
65
|
| colspan="2" style="border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Position created''':
|
63
|
-
| style="border: none; background: #fff; text-align: left;" | <%= metadata.
|
66
|
+
| style="border: none; background: #fff; text-align: left;" | <%= metadata.inception.date %>
|
64
67
|
| style="padding:0.5em 2em 0.5em 1em; border: none; background: #fff; text-align: left;" | \
|
65
|
-
<%
|
68
|
+
<% metadata.inception.warnings.each do |warning| -%>
|
66
69
|
<span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]] <span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span> <ref><%= warning.explanation %></ref></span>\
|
67
70
|
<% end %>
|
68
71
|
<% end -%>
|
69
|
-
<% if metadata.
|
72
|
+
<% if metadata.predecessor.position -%>
|
70
73
|
|-
|
71
74
|
| colspan="2" style=" border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Replaces''':
|
72
|
-
| style="border: none; background: #fff; text-align: left;" | <%= metadata.
|
73
|
-
| style="padding:0.5em 2em 0.5em 1em; border: none; background: #fff; text-align: left;" |
|
75
|
+
| style="border: none; background: #fff; text-align: left;" | <%= metadata.predecessor.position %>
|
76
|
+
| style="padding:0.5em 2em 0.5em 1em; border: none; background: #fff; text-align: left;" | \
|
77
|
+
<% metadata.predecessor.warnings.each do |warning| -%>
|
78
|
+
<span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]] <span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span> <ref><%= warning.explanation %></ref></span>\
|
79
|
+
<% end %>
|
74
80
|
<% end -%>
|
75
81
|
|}
|
76
82
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wikidata_position_history
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Bowden
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-09-
|
12
|
+
date: 2020-09-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mediawiki-replaceable-content
|
@@ -210,6 +210,7 @@ files:
|
|
210
210
|
- lib/sparql/position_query.rb
|
211
211
|
- lib/wikidata_position_history.rb
|
212
212
|
- lib/wikidata_position_history/checks.rb
|
213
|
+
- lib/wikidata_position_history/output_row.rb
|
213
214
|
- lib/wikidata_position_history/report.rb
|
214
215
|
- lib/wikidata_position_history/template.rb
|
215
216
|
- lib/wikidata_position_history/version.rb
|