mural-ruby 0.1.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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +28 -0
  3. data/.ruby-version +1 -0
  4. data/README.md +126 -0
  5. data/Rakefile +16 -0
  6. data/UNLICENSE +24 -0
  7. data/img/draw-widget.png +0 -0
  8. data/img/inking-widget.png +0 -0
  9. data/img/mind-map.png +0 -0
  10. data/img/smart-planner.png +0 -0
  11. data/lib/mural/asset.rb +26 -0
  12. data/lib/mural/client/authentication.rb +75 -0
  13. data/lib/mural/client/mural_content/files.rb +40 -0
  14. data/lib/mural/client/mural_content/sticky_notes.rb +30 -0
  15. data/lib/mural/client/mural_content/tags.rb +48 -0
  16. data/lib/mural/client/mural_content/widgets.rb +33 -0
  17. data/lib/mural/client/mural_content.rb +30 -0
  18. data/lib/mural/client/murals.rb +138 -0
  19. data/lib/mural/client/rooms.rb +92 -0
  20. data/lib/mural/client/search.rb +55 -0
  21. data/lib/mural/client/templates.rb +77 -0
  22. data/lib/mural/client/users/mural_users.rb +67 -0
  23. data/lib/mural/client/users/room_users.rb +62 -0
  24. data/lib/mural/client/users.rb +38 -0
  25. data/lib/mural/client/workspaces.rb +33 -0
  26. data/lib/mural/client.rb +119 -0
  27. data/lib/mural/codec.rb +44 -0
  28. data/lib/mural/create_mural_params.rb +33 -0
  29. data/lib/mural/create_room_params.rb +16 -0
  30. data/lib/mural/create_sticky_note_params.rb +37 -0
  31. data/lib/mural/create_tag_params.rb +45 -0
  32. data/lib/mural/current_user.rb +21 -0
  33. data/lib/mural/duplicate_mural_params.rb +14 -0
  34. data/lib/mural/mural_board.rb +96 -0
  35. data/lib/mural/mural_export.rb +16 -0
  36. data/lib/mural/mural_invitation.rb +16 -0
  37. data/lib/mural/mural_invitation_params.rb +14 -0
  38. data/lib/mural/mural_user.rb +30 -0
  39. data/lib/mural/removed_mural_user.rb +14 -0
  40. data/lib/mural/removed_room_user.rb +14 -0
  41. data/lib/mural/room.rb +63 -0
  42. data/lib/mural/room_folder.rb +21 -0
  43. data/lib/mural/room_invitation.rb +16 -0
  44. data/lib/mural/room_invitation_params.rb +13 -0
  45. data/lib/mural/room_user.rb +17 -0
  46. data/lib/mural/search_mural_result.rb +21 -0
  47. data/lib/mural/search_room_result.rb +16 -0
  48. data/lib/mural/search_template_result.rb +18 -0
  49. data/lib/mural/tag.rb +25 -0
  50. data/lib/mural/template.rb +24 -0
  51. data/lib/mural/update_mural_params.rb +23 -0
  52. data/lib/mural/update_room_params.rb +15 -0
  53. data/lib/mural/update_room_user_params.rb +16 -0
  54. data/lib/mural/update_sticky_note_params.rb +24 -0
  55. data/lib/mural/update_tag_params.rb +22 -0
  56. data/lib/mural/version.rb +5 -0
  57. data/lib/mural/widget/area.rb +53 -0
  58. data/lib/mural/widget/arrow.rb +139 -0
  59. data/lib/mural/widget/comment.rb +92 -0
  60. data/lib/mural/widget/create_file_params.rb +56 -0
  61. data/lib/mural/widget/file.rb +34 -0
  62. data/lib/mural/widget/icon.rb +34 -0
  63. data/lib/mural/widget/image.rb +77 -0
  64. data/lib/mural/widget/shape.rb +79 -0
  65. data/lib/mural/widget/sticky_note.rb +81 -0
  66. data/lib/mural/widget/table.rb +54 -0
  67. data/lib/mural/widget/table_cell.rb +50 -0
  68. data/lib/mural/widget/text.rb +58 -0
  69. data/lib/mural/widget/update_file_params.rb +50 -0
  70. data/lib/mural/widget.rb +158 -0
  71. data/lib/mural/workspace.rb +47 -0
  72. data/lib/mural/workspace_invitation.rb +16 -0
  73. data/lib/mural.rb +27 -0
  74. metadata +132 -0
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mural
4
+ class Widget
5
+ # UNDOCUMENTED
6
+ # This widget is not documented within Mural public API documentation.
7
+ class TableCell
8
+ include Mural::Codec
9
+
10
+ define_attributes(
11
+ **Mural::Widget.attrs,
12
+
13
+ title: 'title',
14
+ col_span: 'colSpan',
15
+ column_id: 'columnId',
16
+ row_id: 'rolId',
17
+ row_span: 'rowSpan',
18
+ style: 'style',
19
+ text_content: 'textContent'
20
+ )
21
+
22
+ def self.decode(json)
23
+ super.tap do |cell|
24
+ cell.style = Style.decode(cell.style)
25
+ cell.text_content = TextContent.decode(cell.text_content)
26
+ end
27
+ end
28
+
29
+ class Style
30
+ include Mural::Codec
31
+
32
+ define_attributes(background_color: 'backgroundColor')
33
+ end
34
+
35
+ class TextContent
36
+ include Mural::Codec
37
+
38
+ define_attributes(
39
+ font_family: 'fontFamily',
40
+ font_size: 'fontSize',
41
+ orientation: 'orientation',
42
+ padding: 'padding',
43
+ text: 'text',
44
+ text_align: 'textAlign',
45
+ vertical_align: 'verticalAlign'
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mural
4
+ class Widget
5
+ class Text
6
+ include Mural::Codec
7
+
8
+ define_attributes(
9
+ **Mural::Widget.attrs,
10
+
11
+ # Style properties of the widget.
12
+ style: 'style',
13
+
14
+ # The text in the widget.
15
+ text: 'text',
16
+
17
+ # The URL used in the widget.
18
+ hyperlink: 'hyperlink',
19
+
20
+ # Text displayed on the hyperlink button.
21
+ hyperlinkTitle: 'hyperlinkTitle',
22
+
23
+ # When true, the text wraps to fit the widget. When false, the widget
24
+ # grows to fit the text. True when widget is created as a textbox and
25
+ # false when widget is created as a title.
26
+ fixed_width: 'fixedWidth',
27
+
28
+ # The title of the widget in the outline.
29
+ title: 'title'
30
+ )
31
+
32
+ def self.decode(json)
33
+ super.tap do |text|
34
+ text.style = Style.decode(text.style)
35
+ end
36
+ end
37
+
38
+ class Style
39
+ include Mural::Codec
40
+
41
+ define_attributes(
42
+ # The background color of the widget in hex with alpha format.
43
+ background_color: 'backgroundColor',
44
+
45
+ # Font-family of the text.
46
+ font: 'font',
47
+
48
+ # Text size.
49
+ font_size: 'fontSize',
50
+
51
+ # The alignment of the text.
52
+ # ["left", "center", "right"]
53
+ text_align: 'textAlign'
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mural
4
+ class Widget
5
+ class UpdateFileParams
6
+ include Mural::Codec
7
+
8
+ # https://developers.mural.co/public/reference/updatefile
9
+ define_attributes(
10
+ # The height of the widget in px. This value will be overwritten if the
11
+ # file has a preview from which the final value will be extracted.
12
+ height: 'height',
13
+
14
+ # If true, the widget is hidden from non-facilitators. Applies only when
15
+ # the widget is in the outline.
16
+ hidden: 'hidden',
17
+
18
+ # The instructions for a section of the outline. This text can only be
19
+ # added and modified by a facilitator.
20
+ instruction: 'instruction',
21
+
22
+ # The ID of the area widget that contains the widget.
23
+ parent_id: 'parentId',
24
+
25
+ # The list order of the widget in the outline.
26
+ presentation_index: 'presentationIndex',
27
+
28
+ # The angle of widget rotation in degrees.
29
+ rotation: 'rotation',
30
+
31
+ # The title in the file widget and in the outline.
32
+ title: 'title',
33
+
34
+ # The width of the widget in px. This value will be overwritten if the
35
+ # file has a preview from which the final value will be extracted.
36
+ width: 'width',
37
+
38
+ # The horizontal position of the widget in px. This is the distance from
39
+ # the left of the parent widget, such as an area. If the widget has no
40
+ # parent widget, this is the distance from the left of the mural.
41
+ x: 'x',
42
+
43
+ # The vertical position of the widget in px. This is the distance from
44
+ # the top of the parent widget, such as an area. If the widget has no
45
+ # parent widget, this is the distance from the top of the mural.
46
+ y: 'y'
47
+ )
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mural
4
+ class Widget
5
+ include Mural::Codec
6
+
7
+ SPECIALIZED = {
8
+ 'area' => 'Mural::Widget::Area',
9
+ 'arrow' => 'Mural::Widget::Arrow',
10
+ 'comment' => 'Mural::Widget::Comment',
11
+ 'file' => 'Mural::Widget::File',
12
+ 'icon' => 'Mural::Widget::Icon',
13
+ 'image' => 'Mural::Widget::Image',
14
+ 'shape' => 'Mural::Widget::Shape',
15
+ 'sticky note' => 'Mural::Widget::StickyNote',
16
+ 'table cell' => 'Mural::Widget::TableCell',
17
+ 'table' => 'Mural::Widget::Table',
18
+ 'text' => 'Mural::Widget::Text'
19
+ }.freeze
20
+
21
+ define_attributes(
22
+ # The unique ID of the widget.
23
+ id: 'id',
24
+
25
+ # The height of the widget in px.
26
+ height: 'height',
27
+
28
+ # The width of the widget in px.
29
+ width: 'width',
30
+
31
+ # The horizontal position of the widget in px. This is the distance from
32
+ # the left of the parent widget, such as an area. If the widget has no
33
+ # parent widget, this is the distance from the left of the mural.
34
+ x: 'x',
35
+
36
+ # The vertical position of the widget in px. This is the distance from
37
+ # the top of the parent widget, such as an area. If the widget has no
38
+ # parent widget, this is the distance from the top of the mural.
39
+ y: 'y',
40
+
41
+ # Indicates whether the widget is invisible, defaults to `false`.
42
+ invisible: 'invisible',
43
+
44
+ # Timestamp in milliseconds.
45
+ content_edited_on: 'contentEditedOn',
46
+
47
+ # The collaborator who last edited content on the widget.
48
+ content_edited_by: 'contentEditedBy',
49
+
50
+ # Timestamp in milliseconds.
51
+ created_on: 'createdOn',
52
+
53
+ # The collaborator who created the widget.
54
+ created_by: 'createdBy',
55
+
56
+ # Timestamp in milliseconds.
57
+ updated_on: 'updatedOn',
58
+
59
+ # The collaborator who last updated the widget.
60
+ updated_by: 'updatedBy',
61
+
62
+ # The angle of widget rotation, in degrees.
63
+ rotation: 'rotation',
64
+
65
+ # The z-index stacking order of the widget.
66
+ stacking_order: 'stackingOrder',
67
+
68
+ # If true, the widget is hidden from non-facilitators. Applies only when
69
+ # the widget is in the outline.
70
+ hidden: 'hidden',
71
+
72
+ # If true, the name of the collaborator who updated the widget is not
73
+ # recorded (because Private Mode is enabled).
74
+ hide_editor: 'hideEditor',
75
+
76
+ # If true, the name of the collaborator who created the widget is not
77
+ # recorded (because Private Mode is enabled).
78
+ hide_owner: 'hideOwner',
79
+
80
+ # The instructions for a section of the outline. This text can only be
81
+ # added and modified by a facilitator.
82
+ instruction: 'instruction',
83
+
84
+ # If true, the widget is locked and cannot be updated by a
85
+ # non-facilitator. Any collaborator can unlock a locked widget.
86
+ locked: 'locked',
87
+
88
+ # If true, the widget is locked by a facilitator. Only a facilitator can
89
+ # unlock it.
90
+ locked_by_facilitator: 'lockedByFacilitator',
91
+
92
+ # The ID of the area widget that contains the widget.
93
+ parent_id: 'parentId',
94
+
95
+ # The list order of the widget in the outline.
96
+ presentation_index: 'presentationIndex',
97
+
98
+ # The type of the widget (`file`).
99
+ type: 'type'
100
+ )
101
+
102
+ def self.decode(json)
103
+ specialized = SPECIALIZED[json['type']]
104
+ widget = specialized ? Object.const_get(specialized).decode(json) : super
105
+
106
+ widget.tap do |f|
107
+ f.content_edited_by = ContentEditedBy.decode(f.content_edited_by)
108
+ f.created_by = CreatedBy.decode(f.created_by)
109
+ f.updated_by = UpdatedBy.decode(f.updated_by)
110
+ end
111
+ end
112
+
113
+ class ContentEditedBy
114
+ include Mural::Codec
115
+
116
+ define_attributes(
117
+ id: 'id',
118
+
119
+ # when edited by a member
120
+ first_name: 'firstName',
121
+ last_name: 'lastName',
122
+
123
+ # when edited by a visitor
124
+ alias: 'alias'
125
+ )
126
+ end
127
+
128
+ class CreatedBy
129
+ include Mural::Codec
130
+
131
+ define_attributes(
132
+ id: 'id',
133
+
134
+ # when edited by a member
135
+ first_name: 'firstName',
136
+ last_name: 'lastName',
137
+
138
+ # when edited by a visitor
139
+ alias: 'alias'
140
+ )
141
+ end
142
+
143
+ class UpdatedBy
144
+ include Mural::Codec
145
+
146
+ define_attributes(
147
+ id: 'id',
148
+
149
+ # when edited by a member
150
+ first_name: 'firstName',
151
+ last_name: 'lastName',
152
+
153
+ # when edited by a visitor
154
+ alias: 'alias'
155
+ )
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mural
4
+ class Workspace
5
+ include Mural::Codec
6
+
7
+ # https://developers.mural.co/public/reference/getworkspaces
8
+ # https://developers.mural.co/public/reference/getworkspace
9
+ define_attributes(
10
+ id: 'id',
11
+ name: 'name',
12
+ description: 'description',
13
+ sharing_settings: 'sharingSettings',
14
+ locked: 'locked',
15
+ suspended: 'suspended',
16
+ company_id: 'companyId',
17
+ created_on: 'createdOn',
18
+ trial_ends: 'trialEnds',
19
+ trial_extended: 'trialExtended',
20
+ # 👇 Only available when retrieving a single workspace
21
+ created_by: 'createdBy'
22
+ )
23
+
24
+ def self.decode(json)
25
+ super.tap do |w|
26
+ w.created_by = CreatedBy.decode(w.created_by)
27
+ w.sharing_settings = SharingSettings.decode(w.sharing_settings)
28
+ end
29
+ end
30
+
31
+ class SharingSettings
32
+ include Mural::Codec
33
+
34
+ define_attributes(link: 'link')
35
+ end
36
+
37
+ class CreatedBy
38
+ include Mural::Codec
39
+
40
+ define_attributes(
41
+ id: 'id',
42
+ first_name: 'firstName',
43
+ last_name: 'lastName'
44
+ )
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mural
4
+ class WorkspaceInvitation
5
+ include Mural::Codec
6
+
7
+ # https://developers.mural.co/public/reference/inviteuserstoworkspace
8
+ define_attributes(
9
+ email: 'email',
10
+ ref_code: 'refCode',
11
+ rejected: 'rejected',
12
+ reason: 'reason',
13
+ username: 'username'
14
+ )
15
+ end
16
+ end
data/lib/mural.rb ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'json'
5
+ require 'net/http'
6
+ require 'zeitwerk'
7
+
8
+ loader = Zeitwerk::Loader.for_gem
9
+ loader.setup
10
+
11
+ module Mural
12
+ class Error < StandardError
13
+ attr_reader :code, :details
14
+
15
+ def initialize(message, code:, details: nil)
16
+ @code = code
17
+ @details = details
18
+
19
+ super(message)
20
+ end
21
+
22
+ def inspect
23
+ "#<Mural::Error message=#{message.inspect} code=#{code.inspect} " \
24
+ "details=#{details.inspect}>"
25
+ end
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mural-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mickaël Pham
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2025-09-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: zeitwerk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.7'
27
+ description:
28
+ email:
29
+ - inbox@mickael.dev
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".github/workflows/ruby.yml"
35
+ - ".ruby-version"
36
+ - README.md
37
+ - Rakefile
38
+ - UNLICENSE
39
+ - img/draw-widget.png
40
+ - img/inking-widget.png
41
+ - img/mind-map.png
42
+ - img/smart-planner.png
43
+ - lib/mural.rb
44
+ - lib/mural/asset.rb
45
+ - lib/mural/client.rb
46
+ - lib/mural/client/authentication.rb
47
+ - lib/mural/client/mural_content.rb
48
+ - lib/mural/client/mural_content/files.rb
49
+ - lib/mural/client/mural_content/sticky_notes.rb
50
+ - lib/mural/client/mural_content/tags.rb
51
+ - lib/mural/client/mural_content/widgets.rb
52
+ - lib/mural/client/murals.rb
53
+ - lib/mural/client/rooms.rb
54
+ - lib/mural/client/search.rb
55
+ - lib/mural/client/templates.rb
56
+ - lib/mural/client/users.rb
57
+ - lib/mural/client/users/mural_users.rb
58
+ - lib/mural/client/users/room_users.rb
59
+ - lib/mural/client/workspaces.rb
60
+ - lib/mural/codec.rb
61
+ - lib/mural/create_mural_params.rb
62
+ - lib/mural/create_room_params.rb
63
+ - lib/mural/create_sticky_note_params.rb
64
+ - lib/mural/create_tag_params.rb
65
+ - lib/mural/current_user.rb
66
+ - lib/mural/duplicate_mural_params.rb
67
+ - lib/mural/mural_board.rb
68
+ - lib/mural/mural_export.rb
69
+ - lib/mural/mural_invitation.rb
70
+ - lib/mural/mural_invitation_params.rb
71
+ - lib/mural/mural_user.rb
72
+ - lib/mural/removed_mural_user.rb
73
+ - lib/mural/removed_room_user.rb
74
+ - lib/mural/room.rb
75
+ - lib/mural/room_folder.rb
76
+ - lib/mural/room_invitation.rb
77
+ - lib/mural/room_invitation_params.rb
78
+ - lib/mural/room_user.rb
79
+ - lib/mural/search_mural_result.rb
80
+ - lib/mural/search_room_result.rb
81
+ - lib/mural/search_template_result.rb
82
+ - lib/mural/tag.rb
83
+ - lib/mural/template.rb
84
+ - lib/mural/update_mural_params.rb
85
+ - lib/mural/update_room_params.rb
86
+ - lib/mural/update_room_user_params.rb
87
+ - lib/mural/update_sticky_note_params.rb
88
+ - lib/mural/update_tag_params.rb
89
+ - lib/mural/version.rb
90
+ - lib/mural/widget.rb
91
+ - lib/mural/widget/area.rb
92
+ - lib/mural/widget/arrow.rb
93
+ - lib/mural/widget/comment.rb
94
+ - lib/mural/widget/create_file_params.rb
95
+ - lib/mural/widget/file.rb
96
+ - lib/mural/widget/icon.rb
97
+ - lib/mural/widget/image.rb
98
+ - lib/mural/widget/shape.rb
99
+ - lib/mural/widget/sticky_note.rb
100
+ - lib/mural/widget/table.rb
101
+ - lib/mural/widget/table_cell.rb
102
+ - lib/mural/widget/text.rb
103
+ - lib/mural/widget/update_file_params.rb
104
+ - lib/mural/workspace.rb
105
+ - lib/mural/workspace_invitation.rb
106
+ homepage: https://github.com/mickaelpham/mural-ruby
107
+ licenses:
108
+ - Unlicense
109
+ metadata:
110
+ homepage_uri: https://github.com/mickaelpham/mural-ruby
111
+ source_code_uri: https://github.com/mickaelpham/mural-ruby
112
+ rubygems_mfa_required: 'true'
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: 3.2.0
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubygems_version: 3.4.19
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Ruby library for the Mural public API
132
+ test_files: []