pact_broker 2.6.0 → 2.7.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/db/migrations/42_delete_orphan_webhook_data.rb +0 -2
- data/db/migrations/43_add_provider_version_to_verification.rb +12 -0
- data/db/migrations/44_populate_verifications_provider_version_id.rb +25 -0
- data/db/migrations/45_set_verification_provider_number_nullable.rb +7 -0
- data/db/migrations/46_recreate_latest_verifications.rb +18 -0
- data/db/migrations/47_create_all_verifications.rb +19 -0
- data/lib/pact_broker/api.rb +4 -0
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +114 -0
- data/lib/pact_broker/api/decorators/verification_decorator.rb +1 -1
- data/lib/pact_broker/api/pact_broker_urls.rb +2 -2
- data/lib/pact_broker/api/resources/index.rb +3 -5
- data/lib/pact_broker/api/resources/matrix.rb +48 -0
- data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +42 -0
- data/lib/pact_broker/domain/relationship.rb +26 -6
- data/lib/pact_broker/domain/verification.rb +5 -1
- data/lib/pact_broker/matrix/repository.rb +51 -0
- data/lib/pact_broker/matrix/service.rb +50 -0
- data/lib/pact_broker/pacticipants/service.rb +21 -5
- data/lib/pact_broker/pacts/all_pact_publications.rb +11 -0
- data/lib/pact_broker/pacts/pact_publication.rb +4 -0
- data/lib/pact_broker/pacts/repository.rb +1 -1
- data/lib/pact_broker/repositories.rb +5 -0
- data/lib/pact_broker/services.rb +5 -0
- data/lib/pact_broker/tags/service.rb +0 -1
- data/lib/pact_broker/ui/app.rb +5 -0
- data/lib/pact_broker/ui/controllers/matrix.rb +27 -0
- data/lib/pact_broker/ui/controllers/relationships.rb +2 -2
- data/lib/pact_broker/ui/view_models/matrix_line.rb +79 -0
- data/lib/pact_broker/ui/view_models/relationship.rb +22 -4
- data/lib/pact_broker/ui/views/matrix/show.haml +42 -0
- data/lib/pact_broker/ui/views/relationships/show-prod-tags.haml +83 -0
- data/lib/pact_broker/ui/views/relationships/show.haml +1 -1
- data/lib/pact_broker/verifications/repository.rb +8 -1
- data/lib/pact_broker/verifications/service.rb +2 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/service.rb +7 -0
- data/lib/pact_broker/webhooks/status.rb +1 -1
- data/lib/rack/pact_broker/convert_file_extension_to_accept_header.rb +1 -1
- data/script/seed.rb +5 -0
- data/spec/features/get_matrix_for_consumer_and_provider_spec.rb +25 -0
- data/spec/features/get_matrix_spec.rb +31 -0
- data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +133 -0
- data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +2 -8
- data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +3 -2
- data/spec/lib/pact_broker/api/resources/matrix_spec.rb +38 -0
- data/spec/lib/pact_broker/domain/relationship_spec.rb +1 -1
- data/spec/lib/pact_broker/matrix/repository_spec.rb +153 -0
- data/spec/lib/pact_broker/matrix/service_spec.rb +46 -0
- data/spec/lib/pact_broker/pacticipants/service_spec.rb +78 -4
- data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +35 -0
- data/spec/lib/pact_broker/pacts/repository_spec.rb +16 -14
- data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +5 -6
- data/spec/lib/pact_broker/verifications/repository_spec.rb +7 -7
- data/spec/lib/pact_broker/verifications/service_spec.rb +6 -0
- data/spec/lib/pact_broker/versions/service_spec.rb +37 -0
- data/spec/lib/pact_broker/webhooks/status_spec.rb +6 -0
- data/spec/migrations/44_add_provider_version_to_verification_spec.rb +60 -0
- data/spec/service_consumers/provider_states_for_pact_broker_client.rb +12 -0
- data/spec/support/shared_examples_for_responses.rb +4 -0
- data/spec/support/test_data_builder.rb +26 -3
- metadata +34 -4
@@ -8,6 +8,7 @@ module PactBroker
|
|
8
8
|
|
9
9
|
set_primary_key :id
|
10
10
|
associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", key: :pact_version_id, primary_key: :id)
|
11
|
+
associate(:many_to_one, :provider_version, class: "PactBroker::Domain::Version", key: :provider_version_id, primary_key: :id)
|
11
12
|
|
12
13
|
def before_create
|
13
14
|
super
|
@@ -78,10 +79,13 @@ module PactBroker
|
|
78
79
|
.limit(1).select(:provider_id))
|
79
80
|
end
|
80
81
|
|
82
|
+
def provider_version_number
|
83
|
+
provider_version.number
|
84
|
+
end
|
85
|
+
|
81
86
|
def latest_pact_publication
|
82
87
|
pact_version.latest_pact_publication
|
83
88
|
end
|
84
|
-
|
85
89
|
end
|
86
90
|
|
87
91
|
Verification.plugin :timestamps
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pact_broker/repositories/helpers'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Matrix
|
5
|
+
class Repository
|
6
|
+
include PactBroker::Repositories::Helpers
|
7
|
+
include PactBroker::Repositories
|
8
|
+
|
9
|
+
def find pacticipant_1_name, pacticipant_2_name
|
10
|
+
find_for_version_ids([], [pacticipant_1_name, pacticipant_2_name])
|
11
|
+
.sort{|l1, l2| l2[:consumer_version_order] <=> l1[:consumer_version_order]}
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# candidate_versions Hash of pacticipant name => version
|
16
|
+
# Ihe value is nil, it means all versions for that pacticipant are to be included
|
17
|
+
# Returns a list of matrix lines indicating the compatible versions
|
18
|
+
#
|
19
|
+
def find_compatible_pacticipant_versions criteria
|
20
|
+
version_ids = criteria.reject{ |key, value| !value }.collect do | key, value |
|
21
|
+
version_repository.find_by_pacticipant_name_and_number(key, value).id
|
22
|
+
end
|
23
|
+
|
24
|
+
pacticipant_names = criteria.reject{|key, value| value }.keys
|
25
|
+
|
26
|
+
find_for_version_ids(version_ids, pacticipant_names)
|
27
|
+
.group_by{|line| [line[:consumer_version_number], line[:provider_version_number]]}
|
28
|
+
.values
|
29
|
+
.collect(&:last)
|
30
|
+
.select{ |line | line[:success] }
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_for_version_ids version_ids, pacticipant_names = []
|
34
|
+
PactBroker::Pacts::LatestPactPublicationsByConsumerVersion
|
35
|
+
.select_append(:consumer_version_number, :provider_name, :consumer_name, :provider_version_id, :provider_version_number, :success)
|
36
|
+
.select_append(Sequel[:latest_pact_publications_by_consumer_versions][:created_at].as(:pact_created_at))
|
37
|
+
.select_append(Sequel[:all_verifications][:number])
|
38
|
+
.select_append(Sequel[:all_verifications][:id].as(:verification_id))
|
39
|
+
.select_append(Sequel[:execution_date].as(:verification_executed_at))
|
40
|
+
.left_outer_join(:all_verifications, pact_version_id: :pact_version_id)
|
41
|
+
.where(provider_version_id: version_ids)
|
42
|
+
.or(provider_version_id: nil)
|
43
|
+
.or(provider_name: pacticipant_names)
|
44
|
+
.where(consumer_version_id: version_ids)
|
45
|
+
.or(consumer_name: pacticipant_names)
|
46
|
+
.order(:execution_date, :verification_id)
|
47
|
+
.collect(&:values)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'pact_broker/repositories'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Matrix
|
5
|
+
module Service
|
6
|
+
VERSION_SELECTOR_PATTERN = %r{(^[^/]+)/version/[^/]+$}.freeze
|
7
|
+
|
8
|
+
extend self
|
9
|
+
extend PactBroker::Repositories
|
10
|
+
extend PactBroker::Services
|
11
|
+
|
12
|
+
def find params
|
13
|
+
matrix_repository.find params[:consumer_name], params[:provider_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_compatible_pacticipant_versions criteria
|
17
|
+
matrix_repository.find_compatible_pacticipant_versions criteria
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_selectors selectors
|
21
|
+
error_messages = []
|
22
|
+
selectors.each do | version_selector |
|
23
|
+
if !(version_selector =~ VERSION_SELECTOR_PATTERN)
|
24
|
+
error_messages << "Invalid version selector '#{version_selector}'. Format must be <pacticipant_name>/version/<version>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
selectors.each do | version_selector |
|
29
|
+
if match = version_selector.match(VERSION_SELECTOR_PATTERN)
|
30
|
+
pacticipant_name = match[1]
|
31
|
+
unless pacticipant_service.find_pacticipant_by_name(pacticipant_name)
|
32
|
+
error_messages << "Pacticipant '#{pacticipant_name}' not found"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if error_messages.empty?
|
38
|
+
selected_versions = version_service.find_versions_by_selector(selectors)
|
39
|
+
if selected_versions.any?(&:nil?)
|
40
|
+
selected_versions.each_with_index do | selected_version, i |
|
41
|
+
error_messages << "No pact or verification found for #{selectors[i]}" if selected_version.nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
error_messages
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -62,11 +62,27 @@ module PactBroker
|
|
62
62
|
def self.find_relationships
|
63
63
|
pact_repository.find_latest_pacts
|
64
64
|
.collect do | pact|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
65
|
+
latest_relationship = build_latest_pact_relationship(pact)
|
66
|
+
prod_relationship = build_relationship_for_tagged_pact(pact, 'prod')
|
67
|
+
production_relationship = build_relationship_for_tagged_pact(pact, 'production')
|
68
|
+
[latest_relationship, prod_relationship, production_relationship].compact
|
69
|
+
end.flatten
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.build_latest_pact_relationship pact
|
73
|
+
latest_verification = verification_service.find_latest_verification_for(pact.consumer, pact.provider)
|
74
|
+
webhooks = webhook_service.find_by_consumer_and_provider pact.consumer, pact.provider
|
75
|
+
triggered_webhooks = webhook_service.find_latest_triggered_webhooks pact.consumer, pact.provider
|
76
|
+
tag_names = pact.consumer_version_tag_names.select{ |name| name == 'prod' || name == 'production' }
|
77
|
+
PactBroker::Domain::Relationship.create pact.consumer, pact.provider, pact, true, latest_verification, webhooks, triggered_webhooks, tag_names
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.build_relationship_for_tagged_pact latest_pact, tag
|
81
|
+
pact = pact_service.find_latest_pact consumer_name: latest_pact.consumer_name, provider_name: latest_pact.provider_name, tag: tag
|
82
|
+
return nil unless pact
|
83
|
+
return nil if pact.id == latest_pact.id
|
84
|
+
verification = verification_repository.find_latest_verification_for pact.consumer_name, pact.provider_name, tag
|
85
|
+
PactBroker::Domain::Relationship.create pact.consumer, pact.provider, pact, false, verification, [], [], [tag]
|
70
86
|
end
|
71
87
|
|
72
88
|
def self.update params
|
@@ -28,6 +28,17 @@ module PactBroker
|
|
28
28
|
where(name_like(:provider_name, provider_name))
|
29
29
|
end
|
30
30
|
|
31
|
+
# must be exactly correct names
|
32
|
+
def pacticipants pacticipant_1, pacticipant_2
|
33
|
+
where(
|
34
|
+
consumer_name: pacticipant_1,
|
35
|
+
provider_name: pacticipant_2
|
36
|
+
).or(
|
37
|
+
consumer_name: pacticipant_2,
|
38
|
+
provider_name: pacticipant_1
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
31
42
|
def tag tag_name
|
32
43
|
filter = name_like(Sequel.qualify(:tags, :name), tag_name)
|
33
44
|
join(:tags, {version_id: :consumer_version_id}).where(filter)
|
@@ -86,7 +86,7 @@ module PactBroker
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def find_latest_pacts
|
89
|
-
LatestPactPublications.order(:consumer_name, :provider_name).collect(&:
|
89
|
+
LatestPactPublications.order(:consumer_name, :provider_name).collect(&:to_domain)
|
90
90
|
end
|
91
91
|
|
92
92
|
def find_latest_pact(consumer_name, provider_name, tag = nil)
|
data/lib/pact_broker/services.rb
CHANGED
data/lib/pact_broker/ui/app.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'pact_broker/ui/controllers/relationships'
|
2
2
|
require 'pact_broker/ui/controllers/groups'
|
3
|
+
require 'pact_broker/ui/controllers/matrix'
|
3
4
|
require 'pact_broker/doc/controllers/app'
|
4
5
|
|
5
6
|
module PactBroker
|
@@ -21,6 +22,10 @@ module PactBroker
|
|
21
22
|
run PactBroker::Doc::Controllers::App
|
22
23
|
end
|
23
24
|
|
25
|
+
map "/matrix" do
|
26
|
+
run PactBroker::UI::Controllers::Matrix
|
27
|
+
end
|
28
|
+
|
24
29
|
map "/" do
|
25
30
|
run PactBroker::UI::Controllers::Relationships
|
26
31
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'pact_broker/ui/controllers/base_controller'
|
2
|
+
require 'pact_broker/ui/view_models/matrix_line'
|
3
|
+
require 'haml'
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module UI
|
7
|
+
module Controllers
|
8
|
+
class Matrix < Base
|
9
|
+
|
10
|
+
include PactBroker::Services
|
11
|
+
|
12
|
+
get "/provider/:provider_name/consumer/:consumer_name" do
|
13
|
+
lines = matrix_service.find consumer_name: params[:consumer_name], provider_name: params[:provider_name]
|
14
|
+
lines = lines.collect{|line| PactBroker::UI::ViewDomain::MatrixLine.new(line)}
|
15
|
+
locals = {
|
16
|
+
lines: lines,
|
17
|
+
title: "The Matrix",
|
18
|
+
consumer_name: params[:consumer_name],
|
19
|
+
provider_name: params[:provider_name]
|
20
|
+
}
|
21
|
+
haml :'matrix/show', {locals: locals, layout: :'layouts/main'}
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -11,8 +11,8 @@ module PactBroker
|
|
11
11
|
|
12
12
|
get "/" do
|
13
13
|
view_model = ViewDomain::Relationships.new(pacticipant_service.find_relationships)
|
14
|
-
|
15
|
-
haml
|
14
|
+
page = params[:showProdPacts] == 'true' ? :'relationships/show-prod-tags' : :'relationships/show'
|
15
|
+
haml page, {locals: {relationships: view_model, title: "Pacts"}, layout: :'layouts/main'}
|
16
16
|
end
|
17
17
|
|
18
18
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'pact_broker/api/pact_broker_urls'
|
2
|
+
require 'pact_broker/ui/helpers/url_helper'
|
3
|
+
require 'pact_broker/date_helper'
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module UI
|
7
|
+
module ViewDomain
|
8
|
+
class MatrixLine
|
9
|
+
|
10
|
+
include PactBroker::Api::PactBrokerUrls
|
11
|
+
|
12
|
+
def initialize line
|
13
|
+
@line = line
|
14
|
+
end
|
15
|
+
|
16
|
+
def provider_name
|
17
|
+
@line[:provider_name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def consumer_name
|
21
|
+
@line[:consumer_name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def pact_version_sha
|
25
|
+
@line[:pact_version_sha]
|
26
|
+
end
|
27
|
+
|
28
|
+
# verification number
|
29
|
+
def number
|
30
|
+
@line[:number]
|
31
|
+
end
|
32
|
+
|
33
|
+
def consumer_version_number
|
34
|
+
@line[:consumer_version_number]
|
35
|
+
end
|
36
|
+
|
37
|
+
def consumer_version_number_url
|
38
|
+
pact_url_from_params('', @line)
|
39
|
+
end
|
40
|
+
|
41
|
+
def consumer_version_order
|
42
|
+
@line[:consumer_version_order]
|
43
|
+
end
|
44
|
+
|
45
|
+
def provider_version_number
|
46
|
+
@line[:provider_version]
|
47
|
+
end
|
48
|
+
|
49
|
+
def provider_version_number_url
|
50
|
+
hal_browser_url(verification_url(self))
|
51
|
+
end
|
52
|
+
|
53
|
+
def provider_version_order
|
54
|
+
if @line[:execution_date]
|
55
|
+
@line[:execution_date].to_time.to_i
|
56
|
+
else
|
57
|
+
0
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def verification_status
|
62
|
+
case @line[:success]
|
63
|
+
when true then "Verified"
|
64
|
+
when false then "Failed"
|
65
|
+
else ''
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def verification_status_class
|
70
|
+
case @line[:success]
|
71
|
+
when true then 'success'
|
72
|
+
when false then 'danger'
|
73
|
+
else ''
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -21,6 +21,18 @@ module PactBroker
|
|
21
21
|
@relationship.provider_name
|
22
22
|
end
|
23
23
|
|
24
|
+
def consumer_version_number
|
25
|
+
@relationship.consumer_version_number
|
26
|
+
end
|
27
|
+
|
28
|
+
def provider_version_number
|
29
|
+
@relationship.provider_version_number
|
30
|
+
end
|
31
|
+
|
32
|
+
def tag_names
|
33
|
+
@relationship.tag_names.any? ? " (#{@relationship.tag_names.join(', ')}) ": ""
|
34
|
+
end
|
35
|
+
|
24
36
|
def consumer_group_url
|
25
37
|
Helpers::URLHelper.group_url consumer_name
|
26
38
|
end
|
@@ -29,7 +41,7 @@ module PactBroker
|
|
29
41
|
Helpers::URLHelper.group_url provider_name
|
30
42
|
end
|
31
43
|
|
32
|
-
def
|
44
|
+
def pact_url
|
33
45
|
"#{pactigration_base_url('', @relationship)}/latest"
|
34
46
|
end
|
35
47
|
|
@@ -38,6 +50,7 @@ module PactBroker
|
|
38
50
|
end
|
39
51
|
|
40
52
|
def webhook_label
|
53
|
+
return "" unless show_webhook_status?
|
41
54
|
case @relationship.webhook_status
|
42
55
|
when :none then "Create"
|
43
56
|
when :success, :failure then webhook_last_execution_date
|
@@ -47,6 +60,7 @@ module PactBroker
|
|
47
60
|
end
|
48
61
|
|
49
62
|
def webhook_status
|
63
|
+
return "" unless show_webhook_status?
|
50
64
|
case @relationship.webhook_status
|
51
65
|
when :success then "success"
|
52
66
|
when :failure then "danger"
|
@@ -55,6 +69,10 @@ module PactBroker
|
|
55
69
|
end
|
56
70
|
end
|
57
71
|
|
72
|
+
def show_webhook_status?
|
73
|
+
@relationship.latest?
|
74
|
+
end
|
75
|
+
|
58
76
|
def webhook_last_execution_date
|
59
77
|
PactBroker::DateHelper.distance_of_time_in_words(@relationship.last_webhook_execution_date, DateTime.now) + " ago"
|
60
78
|
end
|
@@ -99,11 +117,11 @@ module PactBroker
|
|
99
117
|
def verification_tooltip
|
100
118
|
case @relationship.verification_status
|
101
119
|
when :success
|
102
|
-
"Successfully verified by #{provider_name} (v#{@relationship.
|
120
|
+
"Successfully verified by #{provider_name} (v#{@relationship.latest_verification_provider_version_number})"
|
103
121
|
when :stale
|
104
|
-
"Pact has changed since last successful verification by #{provider_name} (v#{@relationship.
|
122
|
+
"Pact has changed since last successful verification by #{provider_name} (v#{@relationship.latest_verification_provider_version_number})"
|
105
123
|
when :failed
|
106
|
-
"Verification by #{provider_name} (v#{@relationship.
|
124
|
+
"Verification by #{provider_name} (v#{@relationship.latest_verification_provider_version_number}) failed"
|
107
125
|
else
|
108
126
|
nil
|
109
127
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
%body
|
2
|
+
%link{rel: 'stylesheet', href: '/css/bootstrap.min.css'}
|
3
|
+
%link{rel: 'stylesheet', href: '/stylesheets/relationships.css'}
|
4
|
+
%script{type: 'text/javascript', src:'/javascripts/jquery-2.1.1.min.js'}
|
5
|
+
%script{type: 'text/javascript', src:'/javascripts/jquery.tablesorter.min.js'}
|
6
|
+
%script{type: 'text/javascript', src:'/js/bootstrap.min.js'}
|
7
|
+
|
8
|
+
.container
|
9
|
+
%h1.page-header
|
10
|
+
= title
|
11
|
+
%table.table.table-bordered.table-striped{id: 'matrix'}
|
12
|
+
%thead
|
13
|
+
%th.consumer
|
14
|
+
= "#{consumer_name} version"
|
15
|
+
%span.glyphicon.glyphicon-sort.sort
|
16
|
+
%th.provider
|
17
|
+
= "#{provider_name} version"
|
18
|
+
%span.glyphicon.glyphicon-sort.sort
|
19
|
+
%th.verification-result
|
20
|
+
Verification
|
21
|
+
%span.glyphicon.glyphicon-sort.sort
|
22
|
+
%tbody
|
23
|
+
- lines.each do | line |
|
24
|
+
%tr
|
25
|
+
%td.consumer-version{'data-sort-value' => line.consumer_version_order}
|
26
|
+
%a{href: line.consumer_version_number_url}
|
27
|
+
= line.consumer_version_number
|
28
|
+
%td.provider{'data-sort-value' => line.provider_version_order}
|
29
|
+
%a{href: line.provider_version_number_url}
|
30
|
+
= line.provider_version_number
|
31
|
+
%td.verification-result{class: line.verification_status_class}
|
32
|
+
= line.verification_status
|
33
|
+
|
34
|
+
:javascript
|
35
|
+
$(function(){
|
36
|
+
$("#matrix").tablesorter({
|
37
|
+
textExtraction : function(node, table, cellIndex){
|
38
|
+
n = $(node);
|
39
|
+
return n.attr('data-sort-value') || n.text();
|
40
|
+
}
|
41
|
+
});
|
42
|
+
});
|