w3c_api 0.1.0 → 0.1.2

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.rubocop_todo.yml +40 -0
  4. data/LICENSE.md +1 -1
  5. data/README.adoc +1032 -439
  6. data/Rakefile +7 -3
  7. data/lib/w3c_api/cli.rb +20 -20
  8. data/lib/w3c_api/client.rb +57 -237
  9. data/lib/w3c_api/commands/affiliation.rb +33 -33
  10. data/lib/w3c_api/commands/ecosystem.rb +47 -47
  11. data/lib/w3c_api/commands/group.rb +68 -68
  12. data/lib/w3c_api/commands/output_formatter.rb +11 -11
  13. data/lib/w3c_api/commands/participation.rb +20 -22
  14. data/lib/w3c_api/commands/series.rb +26 -26
  15. data/lib/w3c_api/commands/specification.rb +77 -52
  16. data/lib/w3c_api/commands/translation.rb +18 -18
  17. data/lib/w3c_api/commands/user.rb +60 -60
  18. data/lib/w3c_api/hal.rb +294 -0
  19. data/lib/w3c_api/models/account.rb +46 -0
  20. data/lib/w3c_api/models/affiliation.rb +54 -65
  21. data/lib/w3c_api/models/affiliation_index.rb +11 -0
  22. data/lib/w3c_api/models/call_for_translation.rb +15 -39
  23. data/lib/w3c_api/models/chair_index.rb +11 -0
  24. data/lib/w3c_api/models/charter.rb +48 -89
  25. data/lib/w3c_api/models/charter_index.rb +11 -0
  26. data/lib/w3c_api/models/connected_account.rb +21 -30
  27. data/lib/w3c_api/models/ecosystem.rb +20 -42
  28. data/lib/w3c_api/models/{ecosystems.rb → ecosystem_index.rb} +4 -10
  29. data/lib/w3c_api/models/evangelist_index.rb +11 -0
  30. data/lib/w3c_api/models/extension.rb +5 -7
  31. data/lib/w3c_api/models/group.rb +63 -142
  32. data/lib/w3c_api/models/group_index.rb +12 -0
  33. data/lib/w3c_api/models/group_link_set.rb +24 -0
  34. data/lib/w3c_api/models/join_emails.rb +5 -7
  35. data/lib/w3c_api/models/participant_index.rb +11 -0
  36. data/lib/w3c_api/models/participation.rb +31 -90
  37. data/lib/w3c_api/models/participation_index.rb +11 -0
  38. data/lib/w3c_api/models/photo.rb +28 -0
  39. data/lib/w3c_api/models/serie.rb +21 -51
  40. data/lib/w3c_api/models/{series.rb → serie_index.rb} +22 -13
  41. data/lib/w3c_api/models/spec_version.rb +69 -83
  42. data/lib/w3c_api/models/spec_version_index.rb +14 -0
  43. data/lib/w3c_api/models/spec_version_ref.rb +11 -13
  44. data/lib/w3c_api/models/specification.rb +54 -66
  45. data/lib/w3c_api/models/specification_index.rb +12 -0
  46. data/lib/w3c_api/models/team_contact_index.rb +11 -0
  47. data/lib/w3c_api/models/testimonial.rb +19 -0
  48. data/lib/w3c_api/models/translation.rb +33 -72
  49. data/lib/w3c_api/models/{translations.rb → translation_index.rb} +5 -11
  50. data/lib/w3c_api/models/user.rb +95 -165
  51. data/lib/w3c_api/models/user_index.rb +11 -0
  52. data/lib/w3c_api/models.rb +36 -12
  53. data/lib/w3c_api/version.rb +1 -1
  54. data/lib/w3c_api.rb +3 -2
  55. metadata +38 -19
  56. data/lib/w3c_api/models/affiliations.rb +0 -33
  57. data/lib/w3c_api/models/base.rb +0 -39
  58. data/lib/w3c_api/models/call_for_translation_ref.rb +0 -15
  59. data/lib/w3c_api/models/charters.rb +0 -17
  60. data/lib/w3c_api/models/collection_base.rb +0 -79
  61. data/lib/w3c_api/models/delegate_enumerable.rb +0 -54
  62. data/lib/w3c_api/models/groups.rb +0 -38
  63. data/lib/w3c_api/models/link.rb +0 -17
  64. data/lib/w3c_api/models/participations.rb +0 -17
  65. data/lib/w3c_api/models/series_collection.rb +0 -17
  66. data/lib/w3c_api/models/spec_versions.rb +0 -17
  67. data/lib/w3c_api/models/specifications.rb +0 -17
  68. data/lib/w3c_api/models/users.rb +0 -44
@@ -1,79 +1,67 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
- require_relative 'link'
5
-
3
+ # https://api.w3.org/specifications/html5
6
4
  # {
7
- # "shortlink"=>"https://www.w3.org/TR/PNG/",
8
- # "description"=>"<p>This document describes PNG (Portable Network Graphics), an extensible file format for the lossless, portable, well-compressed storage of raster images. PNG provides a patent-free replacement for GIF and can also replace many common uses of TIFF. Indexed-color, grayscale, and truecolor images are supported, plus an optional alpha channel. Sample depths range from 1 to 16 bits.</p>\r\n<p>PNG is designed to work well in online viewing applications, such as the World Wide Web, so it is fully streamable with a progressive display option. PNG is robust, providing both full file integrity checking and simple detection of common transmission errors. Also, PNG can store gamma and chromaticity data for improved color matching on heterogeneous platforms.</p>\r\n<p>This specification defines an Internet Media Type image/png.</p>",
9
- # "title"=>"Portable Network Graphics (PNG) Specification (Second Edition)",
10
- # "shortname"=>"png-2",
11
- # "editor-draft"=>"https://w3c.github.io/png/",
12
- # "_links"=>{
13
- # "self"=>{
14
- # "href"=>"https://api.w3.org/specifications/png-2"
15
- # },
16
- # "version-history"=>{
17
- # "href"=>"https://api.w3.org/specifications/png-2/versions"
18
- # },
19
- # "first-version"=>{
20
- # "href"=>"https://api.w3.org/specifications/png-2/versions/20030520",
21
- # "title"=>"Proposed Recommendation"
22
- # },
23
- # "latest-version"=>{
24
- # "href"=>"https://api.w3.org/specifications/png-2/versions/20031110",
25
- # "title"=>"Recommendation"
26
- # },
27
- # "series"=>{
28
- # "href"=>"https://api.w3.org/specification-series/png"
5
+ # "shortlink": "https://www.w3.org/TR/html5/",
6
+ # "description": "<p>This specification defines the 5th major revision of the core language of the World Wide Web: the Hypertext Markup Language (HTML). In this version, new features are introduced to help Web application authors, new elements are introduced based on research into prevailing authoring practices, and special attention has been given to defining clear conformance criteria for user agents in an effort to improve interoperability.</p>",
7
+ # "title": "HTML5",
8
+ # "shortname": "html5",
9
+ # "series-version": "5",
10
+ # "_links": {
11
+ # "self": {
12
+ # "href": "https://api.w3.org/specifications/html5"
13
+ # },
14
+ # "version-history": {
15
+ # "href": "https://api.w3.org/specifications/html5/versions"
16
+ # },
17
+ # "first-version": {
18
+ # "href": "https://api.w3.org/specifications/html5/versions/20080122",
19
+ # "title": "Working Draft"
20
+ # },
21
+ # "latest-version": {
22
+ # "href": "https://api.w3.org/specifications/html5/versions/20180327",
23
+ # "title": "Retired"
24
+ # },
25
+ # "supersedes": {
26
+ # "href": "https://api.w3.org/specifications/html5/supersedes"
27
+ # },
28
+ # "series": {
29
+ # "href": "https://api.w3.org/specification-series/html"
30
+ # }
29
31
  # }
30
- # }
31
32
  # }
32
33
 
33
34
  module W3cApi
34
- module Models
35
- class SpecificationLinks < Lutaml::Model::Serializable
36
- attribute :self, Link
37
- attribute :version_history, Link
38
- attribute :first_version, Link
39
- attribute :latest_version, Link
40
- attribute :series, Link
41
- end
42
-
43
- class Specification < Base
44
- attribute :shortlink, :string
45
- attribute :description, :string
46
- attribute :title, :string
47
- attribute :href, :string
48
- attribute :shortname, :string
49
- attribute :editor_draft, :string
50
- attribute :series_version, :string
51
- attribute :_links, SpecificationLinks
52
-
53
- # Return versions of this specification
54
- def versions(client = nil)
55
- return nil unless client && shortname
56
-
57
- client.specification_versions(shortname)
58
- end
35
+ module Models
36
+ class Specification < Lutaml::Hal::Resource
37
+ attribute :shortlink, :string
38
+ attribute :description, :string
39
+ attribute :title, :string
40
+ attribute :href, :string
41
+ attribute :shortname, :string
42
+ attribute :editor_draft, :string
43
+ attribute :series_version, :string
59
44
 
60
- def self.from_response(response)
61
- transformed_response = transform_keys(response)
45
+ hal_link :self, key: 'self', realize_class: 'Specification'
46
+ hal_link :version_history, key: 'version-history', realize_class: 'SpecVersionIndex'
47
+ hal_link :first_version, key: 'first-version', realize_class: 'SpecVersion'
48
+ hal_link :latest_version, key: 'latest-version', realize_class: 'SpecVersion'
49
+ hal_link :supersedes, key: 'supersedes', realize_class: 'SpecificationIndex', collection: true
50
+ hal_link :series, key: 'series', realize_class: 'Serie'
62
51
 
63
- spec = new
64
- transformed_response.each do |key, value|
65
- case key
66
- when :_links
67
- links = value.each_with_object({}) do |(link_name, link_data), acc|
68
- acc[link_name] = Link.new(href: link_data[:href], title: link_data[:title])
69
- end
70
- spec._links = SpecificationLinks.new(links)
71
- else
72
- spec.send("#{key}=", value) if spec.respond_to?("#{key}=")
73
- end
74
- end
75
- spec
52
+ key_value do
53
+ %i[
54
+ shortlink
55
+ description
56
+ title
57
+ href
58
+ shortname
59
+ editor_draft
60
+ series_version
61
+ ].each do |key|
62
+ map key.to_s.tr('_', '-'), to: key
76
63
  end
77
64
  end
78
65
  end
66
+ end
79
67
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'specification'
4
+
5
+ module W3cApi
6
+ module Models
7
+ # SpecificationIndex class that models `/specifications`
8
+ class SpecificationIndex < Lutaml::Hal::Page
9
+ hal_link :specifications, key: 'specifications', realize_class: 'Specification', collection: true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'user'
4
+
5
+ module W3cApi
6
+ module Models
7
+ class TeamContactIndex < Lutaml::Hal::Page
8
+ hal_link :team_contacts, key: 'team-contacts', realize_class: 'User', collection: true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/hal'
4
+
5
+ # "testimonials": {
6
+ # "en": "Google's mission is to organize the world’s information and make it universally accessible and useful."
7
+ # },
8
+
9
+ module W3cApi
10
+ module Models
11
+ class Testimonial < Lutaml::Hal::Resource
12
+ attribute :en, :string
13
+
14
+ key_value do
15
+ map 'en', to: :en
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
- require_relative 'call_for_translation_ref'
5
- require_relative 'link'
3
+ require_relative 'call_for_translation'
6
4
  require_relative 'user'
7
5
 
8
6
  # {
@@ -85,78 +83,41 @@ require_relative 'user'
85
83
  # }
86
84
 
87
85
  module W3cApi
88
- module Models
89
- class TranslationLinks < Lutaml::Model::Serializable
90
- attribute :self, Link
91
- end
92
-
93
- class Translation < Base
94
- attribute :uri, :string
95
- attribute :title, :string
96
- attribute :href, :string
97
- attribute :language, :string
98
- attribute :published, :string # Date-time format
99
- attribute :updated, :string # Date-time format
100
- attribute :authorized, :boolean
101
- attribute :lto_name, :string
102
- attribute :call_for_translation, CallForTranslationRef
103
- attribute :comments, :string
104
- attribute :states, :string, collection: true
105
- attribute :translators, User, collection: true
106
- attribute :_links, TranslationLinks
107
-
108
- # Parse date strings to Date objects
109
- def published_date
110
- Date.parse(published) if published
111
- rescue Date::Error
112
- nil
113
- end
114
-
115
- def updated_date
116
- Date.parse(updated) if updated
117
- rescue Date::Error
118
- nil
119
- end
120
-
121
- # Get the call for translation as a CallForTranslation object
122
- def call_for_translation_object
123
- return nil unless call_for_translation
124
-
125
- Models::CallForTranslation.new(call_for_translation)
126
- end
127
-
128
- # Get the specification version associated with this translation
129
- def specification_version(client = nil)
130
- return nil unless call_for_translation&.spec_version
131
-
132
- call_for_translation.spec_version
133
- end
86
+ module Models
87
+ class Translation < Lutaml::Hal::Resource
88
+ attribute :uri, :string
89
+ attribute :title, :string
90
+ attribute :href, :string
91
+ attribute :language, :string
92
+ attribute :published, :date_time
93
+ attribute :updated, :date_time
94
+ attribute :authorized, :boolean
95
+ attribute :lto_name, :string
96
+ attribute :call_for_translation, CallForTranslation
97
+ attribute :comments, :string
98
+ attribute :states, :string, collection: true
99
+ attribute :translators, User, collection: true
134
100
 
135
- def self.from_response(response)
136
- transformed_response = transform_keys(response)
101
+ hal_link :self, key: 'self', realize_class: 'Translation'
137
102
 
138
- translation = new
139
- transformed_response.each do |key, value|
140
- case key
141
- when :_links
142
- links = value.each_with_object({}) do |(link_name, link_data), acc|
143
- acc[link_name] = Link.new(href: link_data[:href], title: link_data[:title])
144
- end
145
- translation._links = TranslationLinks.new(links)
146
- when :call_for_translation
147
- translation.call_for_translation = CallForTranslationRef.new(value)
148
- when :translators
149
- # Handle translators as User objects if present
150
- if value.is_a?(Array)
151
- users = value.map { |user_data| User.from_response(user_data) }
152
- translation.translators = users
153
- end
154
- else
155
- translation.send("#{key}=", value) if translation.respond_to?("#{key}=")
156
- end
157
- end
158
- translation
103
+ key_value do
104
+ %i[
105
+ uri
106
+ title
107
+ href
108
+ language
109
+ published
110
+ updated
111
+ authorized
112
+ lto_name
113
+ call_for_translation
114
+ comments
115
+ states
116
+ translators
117
+ ].each do |key|
118
+ map key.to_s.tr('_', '-'), to: key
159
119
  end
160
120
  end
161
121
  end
122
+ end
162
123
  end
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'lutaml/model'
4
3
  require_relative 'translation'
5
- require_relative 'delegate_enumerable'
6
- require_relative 'collection_base'
7
4
 
8
5
  # {
9
6
  # "page"=>1,
@@ -14,7 +11,7 @@ require_relative 'collection_base'
14
11
  # "translations"=>[
15
12
  # {
16
13
  # "href"=>"https://api.w3.org/translations/2",
17
- # "title"=>"Vidéo: introduction à laccessibilité web et aux standards du W3C",
14
+ # "title"=>"Vidéo : introduction à l'accessibilité web et aux standards du W3C",
18
15
  # "language"=>"fr"
19
16
  # },
20
17
  # {
@@ -29,12 +26,9 @@ require_relative 'collection_base'
29
26
  # },
30
27
 
31
28
  module W3cApi
32
- module Models
33
- class Translations < CollectionBase
34
- attribute :translations, Translation, collection: true
35
-
36
- delegate_enumerable :translations
37
- collection_instance_class Translation, :translations
38
- end
29
+ module Models
30
+ class TranslationIndex < Lutaml::Hal::Page
31
+ hal_link :translations, key: 'translations', realize_class: 'Translation', collection: true
39
32
  end
33
+ end
40
34
  end
@@ -1,178 +1,108 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
- require_relative 'connected_account'
5
- require_relative 'link'
6
-
3
+ # https://api.w3.org/users/f1of1ovb5rydm8s0go04oco0cgk0sow44w
7
4
  # {
8
- # "id"=>58291,
9
- # "name"=>"David Grogan",
10
- # "given"=>"David",
11
- # "family"=>"Grogan",
12
- # "work-title"=>"Software Engineer",
13
- # "connected-accounts"=>[
14
- # {
15
- # "created"=>"2019-07-18T21:28:31+00:00",
16
- # "updated"=>"2021-01-21T10:49:57+00:00",
17
- # "service"=>"github",
18
- # "identifier"=>"1801875",
19
- # "nickname"=>"davidsgrogan",
20
- # "profile-picture"=>"https://avatars.githubusercontent.com/u/1801875?v=4",
21
- # "href"=>"https://github.com/davidsgrogan",
22
- # "_links"=>{
23
- # "user"=>{
24
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8"
5
+ # "id": 128112,
6
+ # "name": "Jennifer Strickland",
7
+ # "given": "Jennifer",
8
+ # "family": "Strickland",
9
+ # "country-code": "US",
10
+ # "connected-accounts": [
11
+ # {
12
+ # "created": "2021-03-12T22:06:06+00:00",
13
+ # "service": "github",
14
+ # "identifier": "57469",
15
+ # "nickname": "jenstrickland",
16
+ # "profile-picture": "https://avatars.githubusercontent.com/u/57469?v=4",
17
+ # "href": "https://github.com/jenstrickland",
18
+ # "_links": {
19
+ # "user": {
20
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w"
21
+ # }
22
+ # }
23
+ # }
24
+ # ],
25
+ # "discr": "user",
26
+ # "_links": {
27
+ # "self": {
28
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w"
29
+ # },
30
+ # "affiliations": {
31
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w/affiliations"
32
+ # },
33
+ # "groups": {
34
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w/groups"
35
+ # },
36
+ # "specifications": {
37
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w/specifications"
38
+ # },
39
+ # "photos": [
40
+ # {
41
+ # "href": "https://www.w3.org/thumbnails/360/avatar-images/f1ovb5rydm8s0go04oco0cgk0sow44w.webp?x-version=3",
42
+ # "name": "large"
43
+ # },
44
+ # {
45
+ # "href": "https://www.w3.org/thumbnails/100/avatar-images/f1ovb5rydm8s0go04oco0cgk0sow44w.webp?x-version=3",
46
+ # "name": "thumbnail"
47
+ # },
48
+ # {
49
+ # "href": "https://www.w3.org/thumbnails/48/avatar-images/f1ovb5rydm8s0go04oco0cgk0sow44w.webp?x-version=3",
50
+ # "name": "tiny"
51
+ # }
52
+ # ],
53
+ # "participations": {
54
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w/participations"
55
+ # },
56
+ # "chair_of_groups": {
57
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w/chair-of-groups"
58
+ # },
59
+ # "team_contact_of_groups": {
60
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w/team-contact-of-groups"
25
61
  # }
26
- # }
27
- # }
28
- # ],
29
- # "discr"=>"user",
30
- # "_links"=>{
31
- # "self"=>{
32
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8"
33
- # },
34
- # "affiliations"=>{
35
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8/affiliations"
36
- # },
37
- # "groups"=>{
38
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8/groups"
39
- # },
40
- # "specifications"=>{
41
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8/specifications"
42
- # },
43
- # "participations"=>{
44
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8/participations"
45
- # },
46
- # "chair_of_groups"=>{
47
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8/chair-of-groups"
48
- # },
49
- # "team_contact_of_groups"=>{
50
- # "href"=>"https://api.w3.org/users/c2yerd5euz48gcw08s44oww8g4oo8w8/team-contact-of-groups"
51
62
  # }
52
- # }
53
63
  # }
54
64
 
55
- # {
56
- # "id": 40757,
57
- # "name": "Stéphane Deschamps",
58
- # "given": "Stéphane",
59
- # "family": "Deschamps",
60
- # "work_title": "Mr.",
61
- # "discr": "user",
62
- # "biography": "I love accessibility and standards. Don't we all.",
63
- # "country_code": "FR",
64
- # "city": "Arcueil Cedex",
65
- # "_links": {
66
- # "self": {
67
- # "href": "https://api.w3.org/users/56nw1z8a5uo0sscsgk4kso8g0004008"
68
- # },
69
- # "affiliations": {
70
- # "href": "https://api.w3.org/users/56nw1z8a5uo0sscsgk4kso8g0004008/affiliations"
71
- # },
72
- # "groups": {
73
- # "href": "https://api.w3.org/users/56nw1z8a5uo0sscsgk4kso8g0004008/groups"
74
- # },
75
- # "specifications": {
76
- # "href": "https://api.w3.org/users/56nw1z8a5uo0sscsgk4kso8g0004008/specifications"
77
- # },
78
- # "participations": {
79
- # "href": "https://api.w3.org/users/56nw1z8a5uo0sscsgk4kso8g0004008/participations"
80
- # },
81
- # "chair_of_groups": {
82
- # "href": "https://api.w3.org/users/56nw1z8a5uo0sscsgk4kso8g0004008/chair-of-groups"
83
- # },
84
- # "team_contact_of_groups": {
85
- # "href": "https://api.w3.org/users/56nw1z8a5uo0sscsgk4kso8g0004008/team-contact-of-groups"
86
- # }
87
- # }
88
- # }
65
+ require_relative 'account'
66
+ require_relative 'photo'
89
67
 
90
68
  module W3cApi
91
- module Models
92
- class UserPhoto < Lutaml::Model::Serializable
93
- attribute :href, :string
94
- attribute :name, :string
95
- end
96
-
97
- class UserLinks < Lutaml::Model::Serializable
98
- attribute :self, Link
99
- attribute :affiliations, Link
100
- attribute :groups, Link
101
- attribute :specifications, Link
102
- attribute :participations, Link
103
- attribute :chair_of_groups, Link
104
- attribute :team_contact_of_groups, Link
105
- end
106
-
107
- class User < Base
108
- attribute :id, :integer
109
- attribute :href, :string
110
- attribute :title, :string
111
- attribute :name, :string
112
- attribute :email, :string
113
- attribute :given, :string
114
- attribute :family, :string
115
- attribute :work_title, :string
116
- attribute :discr, :string
117
- attribute :biography, :string
118
- attribute :phone, :string
119
- attribute :country_code, :string
120
- attribute :country_division, :string
121
- attribute :city, :string
122
- attribute :connected_accounts, ConnectedAccount, collection: true
123
- attribute :_links, UserLinks
124
-
125
- # Return groups this user is a member of
126
- def groups(client = nil)
127
- return nil unless client && _links&.groups
128
-
129
- client.user_groups(id)
130
- end
131
-
132
- # Return specifications this user has contributed to
133
- def specifications(client = nil)
134
- return nil unless client && _links&.specifications
135
-
136
- client.user_specifications(id)
137
- end
138
-
139
- def self.from_response(response)
140
- transformed_response = transform_keys(response)
141
-
142
- user = new
143
- transformed_response.each do |key, value|
144
- case key
145
- when :connected_accounts
146
- user.connected_accounts = value.map do |account|
147
- ConnectedAccount.from_response(account)
148
- end
149
- when :_links
150
- links_data = {}
151
-
152
- # Handle all standard links
153
- value.each do |link_name, link_data|
154
- next if link_name == :photos
155
-
156
- # Handle photos array separately
157
-
158
- links_data[link_name] = Link.new(href: link_data[:href], title: link_data[:title])
159
- end
160
-
161
- # Handle photos if present
162
- if value[:photos]
163
- photos = value[:photos].map do |photo|
164
- UserPhoto.new(href: photo[:href], name: photo[:name])
165
- end
166
- links_data[:photos] = photos
167
- end
168
-
169
- user._links = UserLinks.new(links_data)
170
- else
171
- user.send("#{key}=", value) if user.respond_to?("#{key}=")
172
- end
173
- end
174
- user
69
+ module Models
70
+ # User model representing a W3C user/participant
71
+ class User < Lutaml::Hal::Resource
72
+ attribute :id, :string
73
+ attribute :name, :string
74
+ attribute :link, :string
75
+ attribute :given, :string
76
+ attribute :family, :string
77
+ attribute :discr, :string
78
+ attribute :country_code, :string
79
+ attribute :connected_accounts, Account, collection: true
80
+ attribute :photos, Photo, collection: true
81
+
82
+ hal_link :self, key: 'self', realize_class: 'User'
83
+ hal_link :affiliations, key: 'affiliations', realize_class: 'AffiliationIndex'
84
+ hal_link :groups, key: 'groups', realize_class: 'GroupIndex'
85
+ hal_link :specifications, key: 'specifications', realize_class: 'SpecificationIndex'
86
+ hal_link :participations, key: 'participations', realize_class: 'ParticipationIndex'
87
+ hal_link :chair_of_groups, key: 'chair-of-groups', realize_class: 'GroupIndex'
88
+ hal_link :team_contact_of_groups, key: 'team-contact-of-groups', realize_class: 'GroupIndex'
89
+ hal_link :photos, key: 'photos', realize_class: 'Photo', collection: true
90
+
91
+ key_value do
92
+ %i[
93
+ id
94
+ name
95
+ link
96
+ given
97
+ family
98
+ discr
99
+ country_code
100
+ connected_accounts
101
+ photos
102
+ ].each do |key|
103
+ map key.to_s.tr('_', '-'), to: key
175
104
  end
176
105
  end
177
106
  end
107
+ end
178
108
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'user'
4
+
5
+ module W3cApi
6
+ module Models
7
+ class UserIndex < Lutaml::Hal::Page
8
+ hal_link :users, key: 'users', realize_class: 'User', collection: true
9
+ end
10
+ end
11
+ end