superthread 0.7.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 (84) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +4 -0
  3. data/LICENSE +21 -0
  4. data/README.md +492 -0
  5. data/exe/suth +19 -0
  6. data/lib/superthread/cli/accounts.rb +240 -0
  7. data/lib/superthread/cli/activity.rb +210 -0
  8. data/lib/superthread/cli/base.rb +355 -0
  9. data/lib/superthread/cli/boards.rb +131 -0
  10. data/lib/superthread/cli/cards.rb +530 -0
  11. data/lib/superthread/cli/checklists.rb +223 -0
  12. data/lib/superthread/cli/comments.rb +86 -0
  13. data/lib/superthread/cli/completion.rb +306 -0
  14. data/lib/superthread/cli/concerns/board_resolvable.rb +70 -0
  15. data/lib/superthread/cli/concerns/confirmable.rb +55 -0
  16. data/lib/superthread/cli/concerns/date_parsable.rb +196 -0
  17. data/lib/superthread/cli/concerns/list_resolvable.rb +53 -0
  18. data/lib/superthread/cli/concerns/space_resolvable.rb +52 -0
  19. data/lib/superthread/cli/concerns/sprint_resolvable.rb +55 -0
  20. data/lib/superthread/cli/concerns/tag_resolvable.rb +49 -0
  21. data/lib/superthread/cli/concerns/user_resolvable.rb +52 -0
  22. data/lib/superthread/cli/concerns/workspace_resolvable.rb +83 -0
  23. data/lib/superthread/cli/config.rb +129 -0
  24. data/lib/superthread/cli/formatter.rb +388 -0
  25. data/lib/superthread/cli/lists.rb +85 -0
  26. data/lib/superthread/cli/main.rb +121 -0
  27. data/lib/superthread/cli/members.rb +19 -0
  28. data/lib/superthread/cli/notes.rb +64 -0
  29. data/lib/superthread/cli/pages.rb +128 -0
  30. data/lib/superthread/cli/projects.rb +124 -0
  31. data/lib/superthread/cli/replies.rb +94 -0
  32. data/lib/superthread/cli/search.rb +34 -0
  33. data/lib/superthread/cli/setup.rb +253 -0
  34. data/lib/superthread/cli/spaces.rb +141 -0
  35. data/lib/superthread/cli/sprints.rb +32 -0
  36. data/lib/superthread/cli/tags.rb +86 -0
  37. data/lib/superthread/cli/ui/gum_prompt.rb +58 -0
  38. data/lib/superthread/cli/ui/plain_prompt.rb +73 -0
  39. data/lib/superthread/cli/ui.rb +263 -0
  40. data/lib/superthread/cli/workspaces.rb +105 -0
  41. data/lib/superthread/cli.rb +12 -0
  42. data/lib/superthread/client.rb +207 -0
  43. data/lib/superthread/configuration.rb +354 -0
  44. data/lib/superthread/connection.rb +57 -0
  45. data/lib/superthread/error.rb +164 -0
  46. data/lib/superthread/mention_formatter.rb +96 -0
  47. data/lib/superthread/model.rb +178 -0
  48. data/lib/superthread/models/board.rb +59 -0
  49. data/lib/superthread/models/card.rb +321 -0
  50. data/lib/superthread/models/checklist.rb +91 -0
  51. data/lib/superthread/models/checklist_item.rb +69 -0
  52. data/lib/superthread/models/comment.rb +71 -0
  53. data/lib/superthread/models/concerns/archivable.rb +32 -0
  54. data/lib/superthread/models/concerns/presentable.rb +113 -0
  55. data/lib/superthread/models/concerns/timestampable.rb +91 -0
  56. data/lib/superthread/models/list.rb +67 -0
  57. data/lib/superthread/models/member.rb +40 -0
  58. data/lib/superthread/models/note.rb +56 -0
  59. data/lib/superthread/models/page.rb +70 -0
  60. data/lib/superthread/models/project.rb +83 -0
  61. data/lib/superthread/models/space.rb +71 -0
  62. data/lib/superthread/models/sprint.rb +53 -0
  63. data/lib/superthread/models/tag.rb +52 -0
  64. data/lib/superthread/models/team.rb +68 -0
  65. data/lib/superthread/models/user.rb +76 -0
  66. data/lib/superthread/models.rb +12 -0
  67. data/lib/superthread/object.rb +285 -0
  68. data/lib/superthread/objects/collection.rb +179 -0
  69. data/lib/superthread/resources/base.rb +204 -0
  70. data/lib/superthread/resources/boards.rb +150 -0
  71. data/lib/superthread/resources/cards.rb +363 -0
  72. data/lib/superthread/resources/comments.rb +163 -0
  73. data/lib/superthread/resources/notes.rb +61 -0
  74. data/lib/superthread/resources/pages.rb +110 -0
  75. data/lib/superthread/resources/projects.rb +117 -0
  76. data/lib/superthread/resources/search.rb +46 -0
  77. data/lib/superthread/resources/spaces.rb +104 -0
  78. data/lib/superthread/resources/sprints.rb +37 -0
  79. data/lib/superthread/resources/tags.rb +52 -0
  80. data/lib/superthread/resources/users.rb +29 -0
  81. data/lib/superthread/version.rb +6 -0
  82. data/lib/superthread/version_checker.rb +174 -0
  83. data/lib/superthread.rb +30 -0
  84. metadata +259 -0
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superthread
4
+ module Models
5
+ # Represents a checklist item.
6
+ #
7
+ # Individual todo items within a checklist that can be marked as complete.
8
+ #
9
+ # @example
10
+ # item = checklist.items.first
11
+ # item.title # => "Write specs"
12
+ # item.checked? # => true
13
+ class ChecklistItem < Superthread::Model
14
+ include Concerns::Presentable
15
+ include Concerns::Timestampable
16
+
17
+ detail_fields :id, :title, :checked, :checklist_id
18
+ list_columns :id, :title, :checked
19
+
20
+ # @!attribute [rw] id
21
+ # @return [String] unique checklist item identifier
22
+ attribute :id, Shale::Type::String
23
+
24
+ # @!attribute [rw] title
25
+ # @return [String] display title of the item
26
+ attribute :title, Shale::Type::String
27
+
28
+ # @!attribute [rw] content
29
+ # @return [String] optional description or notes
30
+ attribute :content, Shale::Type::String
31
+
32
+ # @!attribute [rw] checklist_id
33
+ # @return [String] ID of the parent checklist
34
+ attribute :checklist_id, Shale::Type::String
35
+
36
+ # @!attribute [rw] user_id
37
+ # @return [String] ID of the user who created the item
38
+ attribute :user_id, Shale::Type::String
39
+
40
+ # @!attribute [rw] checked
41
+ # @return [Boolean] whether this item is checked/completed
42
+ attribute :checked, Shale::Type::Boolean
43
+
44
+ # @!attribute [rw] time_created
45
+ # @return [Integer] Unix timestamp when the item was created
46
+ attribute :time_created, Shale::Type::Integer
47
+
48
+ # @!attribute [rw] time_updated
49
+ # @return [Integer] Unix timestamp when the item was last updated
50
+ attribute :time_updated, Shale::Type::Integer
51
+
52
+ timestamps :time_created, :time_updated
53
+
54
+ # Check if the item is checked.
55
+ #
56
+ # @return [Boolean] True if checked
57
+ def checked?
58
+ !!checked
59
+ end
60
+
61
+ # Alias for checked?.
62
+ #
63
+ # @return [Boolean] True if complete
64
+ def complete?
65
+ checked?
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superthread
4
+ module Models
5
+ # Represents a Superthread comment.
6
+ #
7
+ # Comments are discussion items attached to cards. They support threaded
8
+ # replies through the parent_id and replies attributes.
9
+ #
10
+ # @example
11
+ # comment = client.comments.find(workspace_id, comment_id)
12
+ # comment.content # => "This looks great!"
13
+ # comment.user_id # => "u123"
14
+ # comment.replies # => [#<Superthread::Models::Comment ...>]
15
+ # comment.reply? # => false
16
+ class Comment < Superthread::Model
17
+ include Concerns::Presentable
18
+ include Concerns::Timestampable
19
+
20
+ presents_as(:content) { content.to_s.then { |c| (c.length > 50) ? "#{c[0..47]}..." : c } }
21
+
22
+ detail_fields :id, :content, :user_id, :time_created
23
+ list_columns :id, :content, :user_id
24
+
25
+ # @!attribute [rw] id
26
+ # @return [String] unique comment identifier
27
+ attribute :id, Shale::Type::String
28
+
29
+ # @!attribute [rw] type
30
+ # @return [String] comment type
31
+ attribute :type, Shale::Type::String
32
+
33
+ # @!attribute [rw] content
34
+ # @return [String] HTML content of the comment
35
+ attribute :content, Shale::Type::String
36
+
37
+ # @!attribute [rw] user_id
38
+ # @return [String] ID of the user who posted the comment
39
+ attribute :user_id, Shale::Type::String
40
+
41
+ # @!attribute [rw] card_id
42
+ # @return [String] ID of the card this comment is on
43
+ attribute :card_id, Shale::Type::String
44
+
45
+ # @!attribute [rw] parent_id
46
+ # @return [String, nil] ID of the parent comment if this is a reply
47
+ attribute :parent_id, Shale::Type::String
48
+
49
+ # @!attribute [rw] time_created
50
+ # @return [Integer] Unix timestamp when the comment was posted
51
+ attribute :time_created, Shale::Type::Integer
52
+
53
+ # @!attribute [rw] time_updated
54
+ # @return [Integer] Unix timestamp when the comment was last edited
55
+ attribute :time_updated, Shale::Type::Integer
56
+
57
+ # @!attribute [rw] replies
58
+ # @return [Array<Comment>] threaded replies to this comment
59
+ attribute :replies, Comment, collection: true
60
+
61
+ timestamps :time_created, :time_updated
62
+
63
+ # Check if this is a reply to another comment.
64
+ #
65
+ # @return [Boolean] True if this is a reply
66
+ def reply?
67
+ !!parent_id
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Superthread
6
+ module Models
7
+ # Shared behavior modules for Superthread models.
8
+ module Concerns
9
+ # Provides archived status checking for models with an `archived` attribute.
10
+ #
11
+ # @example
12
+ # class Board < Superthread::Model
13
+ # include Concerns::Archivable
14
+ #
15
+ # attribute :archived, Shale::Type::Value
16
+ # end
17
+ #
18
+ # board.archived? # => true/false
19
+ module Archivable
20
+ extend ActiveSupport::Concern
21
+
22
+ # Check if the resource is archived.
23
+ # The archived attribute can be a boolean or a hash with metadata.
24
+ #
25
+ # @return [Boolean] True if archived
26
+ def archived?
27
+ !!archived
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Superthread
6
+ module Models
7
+ module Concerns
8
+ # Provides string representation via a configurable attribute.
9
+ # Default uses :title, but can be customized.
10
+ #
11
+ # @example Default (uses title)
12
+ # class Board < Superthread::Model
13
+ # include Concerns::Presentable
14
+ #
15
+ # attribute :title, Shale::Type::String
16
+ # end
17
+ #
18
+ # board.to_s # => "My Board"
19
+ #
20
+ # @example Custom attribute
21
+ # class User < Superthread::Model
22
+ # include Concerns::Presentable
23
+ # presents_as :display_name
24
+ #
25
+ # attribute :display_name, Shale::Type::String
26
+ # end
27
+ #
28
+ # user.to_s # => "John Doe"
29
+ #
30
+ # @example With block for custom formatting
31
+ # class Checklist < Superthread::Model
32
+ # include Concerns::Presentable
33
+ # presents_as(:title) { "#{title} (#{completed_count}/#{total_count})" }
34
+ # end
35
+ #
36
+ # checklist.to_s # => "Requirements (2/3)"
37
+ module Presentable
38
+ extend ActiveSupport::Concern
39
+
40
+ included do
41
+ @presentation_attribute = :title
42
+ @presentation_block = nil
43
+ end
44
+
45
+ class_methods do
46
+ # Configure which attribute to use for string representation.
47
+ #
48
+ # When called with just an attribute, that attribute's value becomes
49
+ # the string representation. When called with a block, the block is
50
+ # evaluated in the instance context to produce the string.
51
+ #
52
+ # @param attribute [Symbol] attribute name to use for to_s output
53
+ # @yield optional block evaluated in instance context for custom formatting
54
+ # @yieldreturn [String] the formatted string representation
55
+ # @return [void]
56
+ def presents_as(attribute, &block)
57
+ @presentation_attribute = attribute
58
+ @presentation_block = block
59
+ end
60
+
61
+ # Returns the configured presentation attribute.
62
+ #
63
+ # @return [Symbol] attribute name used for string representation
64
+ def presentation_attribute
65
+ @presentation_attribute || :title
66
+ end
67
+
68
+ # Returns the configured presentation block, if any.
69
+ #
70
+ # @return [Proc, nil] custom formatting block or nil if using attribute directly
71
+ def presentation_block
72
+ @presentation_block
73
+ end
74
+
75
+ # Configure the default fields shown in CLI detail view.
76
+ #
77
+ # @param fields [Array<Symbol>] field names for detail output
78
+ # @return [Array<Symbol>] the configured detail fields
79
+ def detail_fields(*fields)
80
+ if fields.empty?
81
+ @detail_fields || []
82
+ else
83
+ @detail_fields = fields.flatten
84
+ end
85
+ end
86
+
87
+ # Configure the default columns shown in CLI list view.
88
+ #
89
+ # @param columns [Array<Symbol>] column names for list output
90
+ # @return [Array<Symbol>] the configured list columns
91
+ def list_columns(*columns)
92
+ if columns.empty?
93
+ @list_columns || []
94
+ else
95
+ @list_columns = columns.flatten
96
+ end
97
+ end
98
+ end
99
+
100
+ # Returns the string representation using the configured attribute or block.
101
+ #
102
+ # @return [String] formatted string for display
103
+ def to_s
104
+ if self.class.presentation_block
105
+ instance_eval(&self.class.presentation_block).to_s
106
+ else
107
+ send(self.class.presentation_attribute).to_s
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Superthread
6
+ module Models
7
+ module Concerns
8
+ # Provides a DSL for defining timestamp accessor methods.
9
+ #
10
+ # Converts Unix timestamps (integers) to Ruby Time objects automatically.
11
+ # Supports both auto-generated method names and explicit mappings.
12
+ #
13
+ # @example
14
+ # class Card < Superthread::Model
15
+ # include Concerns::Timestampable
16
+ #
17
+ # attribute :time_created, Shale::Type::Integer
18
+ # attribute :time_updated, Shale::Type::Integer
19
+ # attribute :start_date, Shale::Type::Integer
20
+ #
21
+ # timestamps :time_created, :time_updated
22
+ # timestamps start_date: :start_time, due_date: :due_time
23
+ # end
24
+ #
25
+ # card.created_at # => Time object
26
+ # card.start_time # => Time object
27
+ module Timestampable
28
+ extend ActiveSupport::Concern
29
+
30
+ class_methods do
31
+ # Define timestamp accessor methods.
32
+ #
33
+ # With symbols, creates standard accessor names:
34
+ # - time_created -> created_at
35
+ # - time_updated -> updated_at
36
+ # - start_date -> start_time
37
+ #
38
+ # With hash, creates custom accessor names (e.g., start_date: :start_time).
39
+ #
40
+ # @param fields [Array<Symbol>] attribute names to create accessors for
41
+ # @param mappings [Hash{Symbol => Symbol}] explicit attribute to method name mappings
42
+ # @return [void]
43
+ def timestamps(*fields, **mappings)
44
+ # Handle simple field names with auto-generated method names
45
+ fields.each do |field|
46
+ method_name = derive_method_name(field)
47
+ define_timestamp_method(field, method_name)
48
+ end
49
+
50
+ # Handle explicit field => method mappings
51
+ mappings.each do |field, method_name|
52
+ define_timestamp_method(field, method_name)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ # Derives a conventional method name from a timestamp field name.
59
+ #
60
+ # @param field [Symbol] the attribute name
61
+ # @return [Symbol] the derived method name
62
+ def derive_method_name(field)
63
+ name = field.to_s
64
+ if name.start_with?("time_")
65
+ # time_created -> created_at, time_updated -> updated_at
66
+ name.sub(/^time_/, "").concat("_at").to_sym
67
+ elsif name.end_with?("_date")
68
+ # start_date -> start_time, due_date -> due_time
69
+ name.sub(/_date$/, "_time").to_sym
70
+ else
71
+ # fallback: field_at
72
+ :"#{name}_at"
73
+ end
74
+ end
75
+
76
+ # Defines an instance method that converts a Unix timestamp to Time.
77
+ #
78
+ # @param field [Symbol] the source attribute name
79
+ # @param method_name [Symbol] the accessor method name to define
80
+ # @return [void]
81
+ def define_timestamp_method(field, method_name)
82
+ define_method(method_name) do
83
+ ts = send(field)
84
+ (ts && ts != 0) ? Time.at(ts) : nil
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superthread
4
+ module Models
5
+ # Represents a list (column) on a board.
6
+ #
7
+ # Lists are vertical columns on a Kanban board that contain cards.
8
+ # They have a position for ordering and an optional color for visual distinction.
9
+ #
10
+ # @example
11
+ # list = board.lists.first
12
+ # list.title # => "To Do"
13
+ # list.color # => "blue"
14
+ # list.position # => 0
15
+ # list.archived? # => false
16
+ class List < Superthread::Model
17
+ include Concerns::Archivable
18
+ include Concerns::Presentable
19
+ include Concerns::Timestampable
20
+
21
+ detail_fields :id, :title, :color, :position, :board_id
22
+ list_columns :id, :title, :color
23
+
24
+ # @!attribute [rw] id
25
+ # @return [String] unique list identifier
26
+ attribute :id, Shale::Type::String
27
+
28
+ # @!attribute [rw] type
29
+ # @return [String] list type
30
+ attribute :type, Shale::Type::String
31
+
32
+ # @!attribute [rw] board_id
33
+ # @return [String] ID of the board this list belongs to
34
+ attribute :board_id, Shale::Type::String
35
+
36
+ # @!attribute [rw] title
37
+ # @return [String] display title of the list
38
+ attribute :title, Shale::Type::String
39
+
40
+ # @!attribute [rw] color
41
+ # @return [String] color code for visual styling
42
+ attribute :color, Shale::Type::String
43
+
44
+ # @!attribute [rw] position
45
+ # @return [Integer] zero-based position for ordering lists on the board
46
+ attribute :position, Shale::Type::Integer
47
+
48
+ # @!attribute [rw] user_id
49
+ # @return [String] ID of the user who created the list
50
+ attribute :user_id, Shale::Type::String
51
+
52
+ # @!attribute [rw] time_created
53
+ # @return [Integer] Unix timestamp when the list was created
54
+ attribute :time_created, Shale::Type::Integer
55
+
56
+ # @!attribute [rw] time_updated
57
+ # @return [Integer] Unix timestamp when the list was last updated
58
+ attribute :time_updated, Shale::Type::Integer
59
+
60
+ # @!attribute [rw] archived
61
+ # @return [Hash{String => Object}, nil] archive metadata with user_id and time_archived
62
+ attribute :archived, Shale::Type::Value
63
+
64
+ timestamps :time_created, :time_updated
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superthread
4
+ module Models
5
+ # Represents a card member assignment.
6
+ #
7
+ # Members link users to cards with a specific role (e.g., assignee).
8
+ # They track when the assignment was made.
9
+ #
10
+ # @example
11
+ # member = card.members.first
12
+ # member.user_id # => "user-123"
13
+ # member.role # => "assignee"
14
+ # member.assigned_at # => 2024-01-15 10:30:00 -0800
15
+ class Member < Superthread::Model
16
+ include Concerns::Presentable
17
+ include Concerns::Timestampable
18
+
19
+ presents_as(:display_name) { display_name || user_id }
20
+
21
+ # @!attribute [rw] user_id
22
+ # @return [String] ID of the assigned user
23
+ attribute :user_id, Shale::Type::String
24
+
25
+ # @!attribute [rw] display_name
26
+ # @return [String, nil] display name of the assigned user (enriched client-side)
27
+ attribute :display_name, Shale::Type::String
28
+
29
+ # @!attribute [rw] role
30
+ # @return [String] assignment role (e.g., "assignee")
31
+ attribute :role, Shale::Type::String
32
+
33
+ # @!attribute [rw] assigned_date
34
+ # @return [Integer] Unix timestamp when the user was assigned
35
+ attribute :assigned_date, Shale::Type::Integer
36
+
37
+ timestamps assigned_date: :assigned_at
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superthread
4
+ module Models
5
+ # Represents a Superthread note.
6
+ #
7
+ # Notes are standalone documents within a workspace, used for
8
+ # meeting notes, documentation, or other text content.
9
+ #
10
+ # @example
11
+ # note = client.notes.find(workspace_id, note_id)
12
+ # note.title # => "Meeting Notes"
13
+ # note.content # => "<p>Discussed...</p>"
14
+ class Note < Superthread::Model
15
+ include Concerns::Presentable
16
+ include Concerns::Timestampable
17
+
18
+ detail_fields :id, :title, :time_created
19
+ list_columns :id, :title
20
+
21
+ # @!attribute [rw] id
22
+ # @return [String] unique note identifier
23
+ attribute :id, Shale::Type::String
24
+
25
+ # @!attribute [rw] type
26
+ # @return [String] note type
27
+ attribute :type, Shale::Type::String
28
+
29
+ # @!attribute [rw] team_id
30
+ # @return [String] ID of the team/workspace this note belongs to
31
+ attribute :team_id, Shale::Type::String
32
+
33
+ # @!attribute [rw] title
34
+ # @return [String] display title of the note
35
+ attribute :title, Shale::Type::String
36
+
37
+ # @!attribute [rw] content
38
+ # @return [String] HTML content of the note
39
+ attribute :content, Shale::Type::String
40
+
41
+ # @!attribute [rw] user_id
42
+ # @return [String] ID of the user who created the note
43
+ attribute :user_id, Shale::Type::String
44
+
45
+ # @!attribute [rw] time_created
46
+ # @return [Integer] Unix timestamp when the note was created
47
+ attribute :time_created, Shale::Type::Integer
48
+
49
+ # @!attribute [rw] time_updated
50
+ # @return [Integer] Unix timestamp when the note was last updated
51
+ attribute :time_updated, Shale::Type::Integer
52
+
53
+ timestamps :time_created, :time_updated
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superthread
4
+ module Models
5
+ # Represents a Superthread page (document).
6
+ #
7
+ # Pages are wiki-style documents that live within spaces. They support
8
+ # rich text content, icons, and can be archived.
9
+ #
10
+ # @example
11
+ # page = client.pages.find(workspace_id, page_id)
12
+ # page.title # => "Project Overview"
13
+ # page.content # => "<p>This project...</p>"
14
+ # page.archived? # => false
15
+ class Page < Superthread::Model
16
+ include Concerns::Archivable
17
+ include Concerns::Presentable
18
+ include Concerns::Timestampable
19
+
20
+ detail_fields :id, :title, :space_id, :time_created, :time_updated
21
+ list_columns :id, :title
22
+
23
+ # @!attribute [rw] id
24
+ # @return [String] unique page identifier
25
+ attribute :id, Shale::Type::String
26
+
27
+ # @!attribute [rw] type
28
+ # @return [String] page type
29
+ attribute :type, Shale::Type::String
30
+
31
+ # @!attribute [rw] team_id
32
+ # @return [String] ID of the team/workspace this page belongs to
33
+ attribute :team_id, Shale::Type::String
34
+
35
+ # @!attribute [rw] space_id
36
+ # @return [String] ID of the space this page belongs to
37
+ attribute :space_id, Shale::Type::String
38
+
39
+ # @!attribute [rw] title
40
+ # @return [String] display title of the page
41
+ attribute :title, Shale::Type::String
42
+
43
+ # @!attribute [rw] content
44
+ # @return [String] HTML content of the page
45
+ attribute :content, Shale::Type::String
46
+
47
+ # @!attribute [rw] icon
48
+ # @return [String] emoji or icon identifier for the page
49
+ attribute :icon, Shale::Type::String
50
+
51
+ # @!attribute [rw] user_id
52
+ # @return [String] ID of the user who created the page
53
+ attribute :user_id, Shale::Type::String
54
+
55
+ # @!attribute [rw] time_created
56
+ # @return [Integer] Unix timestamp when the page was created
57
+ attribute :time_created, Shale::Type::Integer
58
+
59
+ # @!attribute [rw] time_updated
60
+ # @return [Integer] Unix timestamp when the page was last updated
61
+ attribute :time_updated, Shale::Type::Integer
62
+
63
+ # @!attribute [rw] archived
64
+ # @return [Hash{String => Object}, nil] archive metadata with user_id and time_archived
65
+ attribute :archived, Shale::Type::Value
66
+
67
+ timestamps :time_created, :time_updated
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superthread
4
+ module Models
5
+ # Represents a Superthread project (epic/roadmap item).
6
+ #
7
+ # Projects are high-level work items that group related cards together.
8
+ # They have their own timeline with start and due dates.
9
+ #
10
+ # @example
11
+ # project = client.projects.find(workspace_id, project_id)
12
+ # project.title # => "Q4 Planning"
13
+ # project.status # => "active"
14
+ # project.archived? # => false
15
+ class Project < Superthread::Model
16
+ include Concerns::Archivable
17
+ include Concerns::Presentable
18
+ include Concerns::Timestampable
19
+
20
+ detail_fields :id, :title, :status, :start_date, :due_date
21
+ list_columns :id, :title, :status
22
+
23
+ # @!attribute [rw] id
24
+ # @return [String] unique project identifier
25
+ attribute :id, Shale::Type::String
26
+
27
+ # @!attribute [rw] type
28
+ # @return [String] project type
29
+ attribute :type, Shale::Type::String
30
+
31
+ # @!attribute [rw] team_id
32
+ # @return [String] ID of the team/workspace this project belongs to
33
+ attribute :team_id, Shale::Type::String
34
+
35
+ # @!attribute [rw] space_id
36
+ # @return [String] ID of the space this project belongs to
37
+ attribute :space_id, Shale::Type::String
38
+
39
+ # @!attribute [rw] title
40
+ # @return [String] display title of the project
41
+ attribute :title, Shale::Type::String
42
+
43
+ # @!attribute [rw] description
44
+ # @return [String] project description or summary
45
+ attribute :description, Shale::Type::String
46
+
47
+ # @!attribute [rw] status
48
+ # @return [String] project status (e.g., "active", "completed")
49
+ attribute :status, Shale::Type::String
50
+
51
+ # @!attribute [rw] icon
52
+ # @return [String] emoji or icon identifier for the project
53
+ attribute :icon, Shale::Type::String
54
+
55
+ # @!attribute [rw] user_id
56
+ # @return [String] ID of the user who created the project
57
+ attribute :user_id, Shale::Type::String
58
+
59
+ # @!attribute [rw] start_date
60
+ # @return [Integer] Unix timestamp when the project starts
61
+ attribute :start_date, Shale::Type::Integer
62
+
63
+ # @!attribute [rw] due_date
64
+ # @return [Integer] Unix timestamp when the project is due
65
+ attribute :due_date, Shale::Type::Integer
66
+
67
+ # @!attribute [rw] time_created
68
+ # @return [Integer] Unix timestamp when the project was created
69
+ attribute :time_created, Shale::Type::Integer
70
+
71
+ # @!attribute [rw] time_updated
72
+ # @return [Integer] Unix timestamp when the project was last updated
73
+ attribute :time_updated, Shale::Type::Integer
74
+
75
+ # @!attribute [rw] archived
76
+ # @return [Hash{String => Object}, nil] archive metadata with user_id and time_archived
77
+ attribute :archived, Shale::Type::Value
78
+
79
+ timestamps :time_created, :time_updated
80
+ timestamps start_date: :start_time, due_date: :due_time
81
+ end
82
+ end
83
+ end