Class: Diagrams::TimelineDiagram
- Defined in:
- lib/diagrams/timeline_diagram.rb
Overview
Represents a timeline diagram illustrating a chronology of events.
Constant Summary collapse
- DEFAULT_SECTION_TITLE =
'Default Section'
Instance Attribute Summary collapse
-
#sections ⇒ Object
readonly
Returns the value of attribute sections.
-
#title ⇒ Object
readonly
Returns the value of attribute title.
Attributes inherited from Base
Class Method Summary collapse
Instance Method Summary collapse
-
#add_period(period_label:, events:) ⇒ Elements::TimelinePeriod
Adds a time period with one or more events to the current (last) section.
-
#add_section(section_title) ⇒ Elements::TimelineSection
Adds a new section to the timeline.
- #identifiable_elements ⇒ Object
-
#initialize(title: nil, sections: [], version: 1) ⇒ TimelineDiagram
constructor
Initializes a new TimelineDiagram.
-
#set_title(new_title) ⇒ String
Sets the title of the timeline.
-
#to_h_content ⇒ Object
— Base Class Implementation —.
Methods inherited from Base
#diff, from_hash, from_json, #to_h, #to_json
Constructor Details
#initialize(title: nil, sections: [], version: 1) ⇒ TimelineDiagram
Initializes a new TimelineDiagram.
15 16 17 18 19 20 21 22 |
# File 'lib/diagrams/timeline_diagram.rb', line 15 def initialize(title: nil, sections: [], version: 1) super(version:) @title = title&.strip @sections = Array(sections) # Ensure there's always at least a default section if none provided initially ensure_default_section if @sections.empty? update_checksum! end |
Instance Attribute Details
#sections ⇒ Object (readonly)
Returns the value of attribute sections.
8 9 10 |
# File 'lib/diagrams/timeline_diagram.rb', line 8 def sections @sections end |
#title ⇒ Object (readonly)
Returns the value of attribute title.
8 9 10 |
# File 'lib/diagrams/timeline_diagram.rb', line 8 def title @title end |
Class Method Details
.from_h(data_hash, version:, checksum:) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/diagrams/timeline_diagram.rb', line 113 def self.from_h(data_hash, version:, checksum:) title = data_hash[:title] || data_hash['title'] sections_data = data_hash[:sections] || data_hash['sections'] || [] sections = sections_data.map do |section_h| section_data = section_h.transform_keys(&:to_sym) periods_data = section_data[:periods] || [] periods = periods_data.map do |period_h| period_data = period_h.transform_keys(&:to_sym) events_data = period_data[:events] || [] events = events_data.map do |event_h| event_data = event_h.transform_keys(&:to_sym) Elements::TimelineEvent.new(event_data) end Elements::TimelinePeriod.new(period_data.merge(events:)) end Elements::TimelineSection.new(section_data.merge(periods:)) end diagram = new(title:, sections:, version:) # Optional: Verify checksum if checksum && diagram.checksum != checksum warn "Checksum mismatch for loaded TimelineDiagram (version: #{version}). Expected #{checksum}, got #{diagram.checksum}." end diagram end |
Instance Method Details
#add_period(period_label:, events:) ⇒ Elements::TimelinePeriod
Adds a time period with one or more events to the current (last) section.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/diagrams/timeline_diagram.rb', line 63 def add_period(period_label:, events:) clean_label = period_label.strip raise ArgumentError, 'Period label cannot be empty' if clean_label.empty? event_list = Array(events).map(&:strip).reject(&:empty?) raise ArgumentError, 'Events cannot be empty' if event_list.empty? timeline_events = event_list.map { |desc| Elements::TimelineEvent.new(description: desc) } new_period = Elements::TimelinePeriod.new(label: clean_label, events: timeline_events) current_section = @sections.last raise StandardError, 'Cannot add period: No section available.' unless current_section # Add period to the current section's periods array # Dry::Struct arrays are immutable, so we need to create a new section object updated_periods = current_section.periods + [new_period] # Create a completely new section instance with the updated periods array updated_section = Elements::TimelineSection.new(title: current_section.title, periods: updated_periods) # Find the index of the current section and update it in place # Rebuild the sections array, replacing the modified section current_section_title = current_section.title # Rebuild the sections array by mapping, replacing the target section @sections = @sections.map do |section| section.title == current_section_title ? updated_section : section end update_checksum! new_period end |
#add_section(section_title) ⇒ Elements::TimelineSection
Adds a new section to the timeline. Subsequent periods/events will be added to this section.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/diagrams/timeline_diagram.rb', line 40 def add_section(section_title) clean_title = section_title.strip raise ArgumentError, "Section title '#{clean_title}' cannot be empty" if clean_title.empty? raise ArgumentError, "Section with title '#{clean_title}' already exists" if find_section(clean_title) # Remove default section if it's empty and we're adding a real one if @sections.size == 1 && @sections.first.title == DEFAULT_SECTION_TITLE && @sections.first.periods.empty? @sections.clear end new_section = Elements::TimelineSection.new(title: clean_title) @sections << new_section update_checksum! new_section end |
#identifiable_elements ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/diagrams/timeline_diagram.rb', line 104 def identifiable_elements # Sections and Periods are the main identifiable structures. Events are nested. # Use section title and period label as identifiers. { sections: @sections, periods: @sections.flat_map(&:periods) # Flatten periods from all sections } end |
#set_title(new_title) ⇒ String
Sets the title of the timeline.
28 29 30 31 32 |
# File 'lib/diagrams/timeline_diagram.rb', line 28 def set_title(new_title) @title = new_title.strip update_checksum! @title end |
#to_h_content ⇒ Object
— Base Class Implementation —
96 97 98 99 100 101 102 |
# File 'lib/diagrams/timeline_diagram.rb', line 96 def to_h_content content = { sections: @sections.map(&:to_h) } content[:title] = @title if @title content end |