<h1>Note: this example requires manual pagination, sorting and log building. It's not recommended, you should use the factory methods instead.</h1><br><turbo-frame id="lui-log-list-preview-log-list" class="lui-log_list"> <div class="lui-log_list__group" data-date="19-03-2026"> <div class="lui-accordion lui-accordion--open" data-controller="accordion" data-accordion-open-value="true"> <div class="lui-accordion__header"> <button class="cursor-pointer flex justify-start gap-1 flex-1 items-center" type="button" data-action="click->accordion#toggle" data-accordion-target="trigger" aria-controls="accordion_22a6bb01e858"> <div class="lui-accordion__icon mt-1"> <div class="lui-icon h-[8px] w-[8px]"> <i class="fa-regular fa-chevron-down lui-icon__icon" style="font-size: 8px; color: black;"></i> </div> </div> <span class="lui-accordion__title flex justify-start gap-1"> <div class="lui-header lui-header--medium"> <div class="lui-header__title_container"> <span class="lui-header__title_container__title"> 19-03-2026 </span> </div> </div> </span> </button> <div aria-controls="accordion_96883ed7057a" class="lui-accordion__buttons"> </div> </div> <div id="accordion_23b9ddede560" class="lui-accordion__content" data-accordion-target="content" > <div class="lui-accordion__content-inner"> <div class="pb-4"> <div class="lui-log" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">0: </div> <div class="lui-log__word">Item </div> <div class="lui-log__word">Value's </div> <div class="lui-log__word">Status </div> <div class="lui-log__word">updated </div> <div class="lui-log__word">from </div> <div class="lui-log__word">draft </div> <div class="lui-log__word">to </div> <div class="lui-log__word">waiting_agreement.</div> </div> <div class="lui-log__content__header__description"> By System </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 16:32 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">1: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">In </div> <div class="lui-log__word">eveniet </div> <div class="lui-log__word">enim </div> <div class="lui-log__word">qui.</div> </div> <div class="lui-log__content__header__description"> By Percy Heller </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 13:57 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">2: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Accusamus </div> <div class="lui-log__word">eaque </div> <div class="lui-log__word">laborum </div> <div class="lui-log__word">distinctio.</div> </div> <div class="lui-log__content__header__description"> By Rep. Denver O'Hara </div> <div class="lui-log__expand-content" data-log-target="expand"> <div class="lui-log__expand-inner"> <div class="lui-log__word">Item </div> <div class="lui-log__word">transitioned </div> <div class="lui-log__word">from </div> <div class="lui-log__word"><b>Draft</b> </div> <div class="lui-log__word">to </div> <div class="lui-log__word"><b>Submitted</b>.</div> </div> </div> <div class="lui-log__buttons"> <button class="lui-button lui-button--neutral--secondary lui-button--size-tiny w-fit w-fit relative" data-controller="lui--button" data-action="click->log#showMore:prevent log:toggleExpand->lui--button#rotateTrailingIcon" data-log-target="toggleExpand"> <span class="lui-button__text opacity-100 inline-flex" data-lui--button-target="text"> Show details </span> <div class="opacity-100 inline-flex" data-lui--button-target="trailingIcon"> <div class="flex items-center justify-center" style="width: 12px; height: 12px;"><i class="lui-button__icon lui-button__icon--tiny fa-regular fa-chevron-down"></i></div> </div> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 12px;"> progress_activity </i> </div> </button> </div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 13:50 </div> </div> </div> <div class="lui-log" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">3: </div> <div class="lui-log__word">File </div> <div class="lui-log__word">uploaded: </div> <div class="lui-log__word">fruit-notebook/provident.png</div> </div> <div class="lui-log__content__header__description"> By System </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 13:14 </div> </div> </div> <div class="lui-log" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">4: </div> <div class="lui-log__word">File </div> <div class="lui-log__word">uploaded: </div> <div class="lui-log__word">rung-scale/dicta.doc</div> </div> <div class="lui-log__content__header__description"> By Rubye O'Keefe </div> <div class="lui-log__expand-content" data-log-target="expand"> <div class="lui-log__expand-inner"> <div class="lui-log__word">Protocol </div> <div class="lui-log__word">Answers </div> <div class="lui-log__word">saved.</div> </div> </div> <div class="lui-log__buttons"> <button class="lui-button lui-button--neutral--secondary lui-button--size-tiny w-fit w-fit relative" data-controller="lui--button" data-action="click->log#showMore:prevent log:toggleExpand->lui--button#rotateTrailingIcon" data-log-target="toggleExpand"> <span class="lui-button__text opacity-100 inline-flex" data-lui--button-target="text"> Show details </span> <div class="opacity-100 inline-flex" data-lui--button-target="trailingIcon"> <div class="flex items-center justify-center" style="width: 12px; height: 12px;"><i class="lui-button__icon lui-button__icon--tiny fa-regular fa-chevron-down"></i></div> </div> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 12px;"> progress_activity </i> </div> </button> </div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 12:33 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">5: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Expedita </div> <div class="lui-log__word">quo </div> <div class="lui-log__word">vel </div> <div class="lui-log__word">et.</div> </div> <div class="lui-log__content__header__description"> By Jana MacGyver </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 11:23 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">6: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Voluptatem </div> <div class="lui-log__word">ducimus </div> <div class="lui-log__word">illum </div> <div class="lui-log__word">officia.</div> </div> <div class="lui-log__content__header__description"> By System </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 10:38 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">7: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Aut </div> <div class="lui-log__word">dolor </div> <div class="lui-log__word">asperiores </div> <div class="lui-log__word">consequuntur.</div> </div> <div class="lui-log__content__header__description"> By Doug Morar </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 09:34 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">8: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Iusto </div> <div class="lui-log__word">asperiores </div> <div class="lui-log__word">aut </div> <div class="lui-log__word">aliquid.</div> </div> <div class="lui-log__content__header__description"> By Sommer Hilll </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 09:18 </div> </div> </div> <div class="lui-log" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">9: </div> <div class="lui-log__word">Email </div> <div class="lui-log__word">sent </div> <div class="lui-log__word">to </div> <div class="lui-log__word">jerry_hoppe@littel.example</div> </div> <div class="lui-log__content__header__description"> By System </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 07:53 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">10: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Enim </div> <div class="lui-log__word">quisquam </div> <div class="lui-log__word">corporis </div> <div class="lui-log__word">maxime.</div> </div> <div class="lui-log__content__header__description"> By Jackelyn Rippin </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 06:18 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">11: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Beatae </div> <div class="lui-log__word">dicta </div> <div class="lui-log__word">eveniet </div> <div class="lui-log__word">atque.</div> </div> <div class="lui-log__content__header__description"> By Jutta Bradtke VM </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 05:45 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">12: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Provident </div> <div class="lui-log__word">nihil </div> <div class="lui-log__word">molestiae </div> <div class="lui-log__word">commodi.</div> </div> <div class="lui-log__content__header__description"> By Salvador Murray </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 04:16 </div> </div> </div> <div class="lui-log" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">13: </div> <div class="lui-log__word">Export </div> <div class="lui-log__word">completed </div> <div class="lui-log__word">with </div> <div class="lui-log__word">619 </div> <div class="lui-log__word">records</div> </div> <div class="lui-log__content__header__description"> By Phuong Graham III </div> <div class="lui-log__expand-content" data-log-target="expand"> <div class="lui-log__expand-inner"> <div class="lui-log__word">Email </div> <div class="lui-log__word">sent </div> <div class="lui-log__word">to </div> <div class="lui-log__word">ilda@bogisich.example</div> </div> </div> <div class="lui-log__buttons"> <button class="lui-button lui-button--neutral--secondary lui-button--size-tiny w-fit w-fit relative" data-controller="lui--button" data-action="click->log#showMore:prevent log:toggleExpand->lui--button#rotateTrailingIcon" data-log-target="toggleExpand"> <span class="lui-button__text opacity-100 inline-flex" data-lui--button-target="text"> Show details </span> <div class="opacity-100 inline-flex" data-lui--button-target="trailingIcon"> <div class="flex items-center justify-center" style="width: 12px; height: 12px;"><i class="lui-button__icon lui-button__icon--tiny fa-regular fa-chevron-down"></i></div> </div> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 12px;"> progress_activity </i> </div> </button> </div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 02:35 </div> </div> </div> <div class="lui-log lui-log--error" data-controller="log" data-log-expanded-copy-text-value="Show details" data-log-collapsed-copy-text-value="Hide details"> <div class="lui-log__main"> <div class="lui-log__content"> <!-- TODO: remove this once the log classes have been established --> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">log </div> <div class="lui-log__word">14: </div> <div class="lui-log__word">Error: </div> <div class="lui-log__word">Et </div> <div class="lui-log__word">eius </div> <div class="lui-log__word">ea </div> <div class="lui-log__word">repellendus.</div> </div> <div class="lui-log__content__header__description"> By Willy Considine </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 19/03/2026 02:30 </div> </div> </div> </div> </div> </div> </div> </div> <div class="lui-log_list__pagination"> <span class="lui-pagination" data-controller="lui--pagination"> <button class="lui-button lui-button--icon-only lui-button--neutral--secondary lui-button--size-small lui-button--disabled w-fit w-fit relative" data-controller="lui--button" disabled="disabled"> <div class="opacity-100 inline-flex" data-lui--button-target="leadingIcon"> <div class="flex items-center justify-center" style="width: 14px; height: 14px;"><i class="lui-button__icon lui-button__icon--small fa-regular fa-chevron-left" data-lui--button-target="leadingIcon"></i></div> </div> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 14px;"> progress_activity </i> </div> </button> <a class="lui-pagination__item lui-pagination__item--active" disabled="disabled">1</a> <a href="/lookbook/inspect/log_list/manual?page=2" class="lui-pagination__item" disabled="disabled">2</a> <a class="lui-button lui-button--icon-only lui-button--neutral--secondary lui-button--size-small w-fit w-fit relative" data-controller="lui--button" data-action="lui--button#startLoading" href="/lookbook/inspect/log_list/manual?page=2" disabled="disabled"> <div class="opacity-100 inline-flex" data-lui--button-target="leadingIcon"> <div class="flex items-center justify-center" style="width: 14px; height: 14px;"><i class="lui-button__icon lui-button__icon--small fa-regular fa-chevron-right" data-lui--button-target="leadingIcon"></i></div> </div> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 14px;"> progress_activity </i> </div> </a> </span> </div></turbo-frame>LogList
Description
Related components
| Used Components | Components where is Used |
|---|---|
| Label |
Usage rules
- ✅ Do
- ❌ Don't
<% def generate_random_log_data date = DateTime.now + rand(0..23).hours + rand(0..59).minutes error = [true, false].sample author = [Faker::Name.name, nil].sample app_kinds = ["submission", "validation", "handling", "neutral"] app_names = ["bil-submission-prod", "bil-validation-prod", "bil-handling-prod", "System"] app_instance = { "name" => app_names.sample, "kind" => app_kinds.sample } messages = [ "Item transitioned from <b>Draft</b> to <b>Submitted</b>.", "Protocol Answers saved.", "Email sent to #{Faker::Internet.email}", "Item Value's Status updated from draft to waiting_agreement.", "Validation completed successfully.", "File uploaded: #{Faker::File.file_name}", "User #{Faker::Name.name} logged in", "Export completed with #{rand(10..1000)} records", "Synchronization with external system completed", "Backup created successfully" ] extra_messages = [ "Item transitioned from <b>Draft</b> to <b>Submitted</b>.", "Protocol Answers saved.", "Email sent to #{Faker::Internet.email}", "Item Value's Status updated from draft to waiting_agreement.", "Validation completed successfully.", "File uploaded: #{Faker::File.file_name}", "User #{Faker::Name.name} logged in", "Export completed with #{rand(10..1000)} records", "Synchronization with external system completed", "Backup created successfully" ] { date: date, author: author, app_instance: app_instance, message: error ? "Error: #{Faker::Lorem.sentence}" : messages.sample, error: error, extra_message: rand(0..3) == 0 ? extra_messages.sample : nil } end logs = (25).times.map { generate_random_log_data }.sort_by { |log| log[:date] }.reverse logs = logs.map.with_index do |log_data, i| # Create individual Log components log = LooposUi::Log.new( error: log_data[:error], user: log_data[:author], date: log_data[:date] ) log.with_content("log #{i}: #{log_data[:message]}") # Add source based on app_instance app_instance = log_data[:app_instance] if app_instance[:kind] == "neutral" log.with_entity_token_source(text: app_instance[:name], color: :general) else log.with_source(entity: LooposUi::Entities::AppInstance.from_hash(app_instance)) end log.with_expand_content(log_data[:extra_message]) if log_data[:extra_message] log end per_page = 15 page = params.fetch("page", 1).to_i total_logs = logs.size logs = logs.sort_by(&:date).reverse logs = logs.slice((page - 1) * per_page, per_page)%><h1>Note: this example requires manual pagination, sorting and log building. It's not recommended, you should use the factory methods instead.</h1><br><%= render LooposUi::LogList.new( id: "preview-log-list", pagination: { page: page, items: per_page, count: total_logs }, logs: logs) %>No notes provided.
No params configured.
Description
LogList is a component for displaying chronological logs in a grouped, paginated format. It automatically groups logs by date and provides built-in pagination support. The component can work with various data sources through its factory system.
Arguments
| Property | Default | Required | Description |
|---|---|---|---|
id |
"lui-log-list-{id}" |
✓ | Unique identifier for the component |
logs |
[] |
Array of LooposUi::Log objects to display |
|
items |
nil |
Enumerable of items to convert to logs using a factory | |
factory |
nil |
Factory class to convert items to logs (must inherit from LooposUi::Log::Factories::Base) |
|
path |
nil |
URL path for pagination links | |
config |
Config.new.to_h |
Configuration object for component behavior. Applicable only for from_any_source method. |
|
pagy |
nil |
Pagy object for pagination. Prefer over pagination. |
|
pagination |
nil |
Pagination parameters hash |
Configuration Options
The config option accepts a LogList::Config object with the following attributes:
| Attribute | Type | Default | Description |
|---|---|---|---|
max_items |
Integer |
15 |
Maximum number of logs to display |
sort_direction |
Symbol |
:desc |
Sort direction (:asc or :desc) |
has_pagination |
Boolean |
true |
Whether to show pagination controls |
Usage
There are three ways to use the LogList component:
- using the factory
from_any_sourcemethod - passing
items:and an optionalfactory:arguments - passing in a
logs:list with pre-builtLogcomponents
These examples are ordered in order of preference, complexity, convenience and control.
You probably want to use the from_any_source factory method.
LooposUI comes with two built-in factories:
CoreItemLogListPresenterHashfor hash data from core item log presenters.ScriptforLoopOs::Scriptobjects.
You can read more in the Factory System section.
Using the factory from_any_source method
Automatically detects and uses the appropriate factory for a given data source.
This usage already takes care of pagination, but you must pass the page parameter.
Otherwise, the component will render without pagination.
You can also pass a config: hash to configure the component.
This usage does not require ordering or pagination, it will be done automatically.
# Automatically detects the right factoryrender LooposUi::LogList.from_any_source( source: my_data_source, id: "auto-detected-logs", config: { max_items: 20 }, page: params[:page] || 1)# With custom retry path for script logs using ScriptProxyscript_proxy = LoopOs::Scripts::ScriptProxy.new(@loop_os_script, context: { retry_path_proc: ->(script_log) { rerun_script_script_path(@loop_os_script, script_log_id: script_log.id) }})render LooposUi::LogList.from_any_source( source: script_proxy, id: "script-logs", config: { max_items: 15 }, page: params[:page] || 1)Note: The ScriptProxy approach provides a clean separation of concerns. The proxy encapsulates the retry functionality and is passed as context to individual log entries, allowing the factories to remain unaware of specific implementation details.
Passing items: and an optional factory: arguments
Use when you have a collection of items that need to be converted to logs.
The items are expected to be paginated and sorted.
Not passing in pagination parameters will disable pagination.
The LogList will attempt to detect an usable factory, but you can use your own with the factory: option.
# With automatic factory detectionrender LooposUi::LogList.new( id: "item-logs", items: Item.all, path: some_path_that_renders_this_list)# With custom factoryrender LooposUi::LogList.new( id: "custom-logs", items: MyCustomModel.all, factory: MyCustomFactory, path: some_path_that_renders_this_list)Passing in a logs: list with pre-built Log components
Use when you already have LooposUi::Log objects ready to display, or want to build them without
creating a factory.
This usage also expects the logs to be paginated and sorted.
Not passing in pagination parameters will disable pagination.
logs = [ LooposUi::Log.new(date: Time.current, user: "John Doe", error: false).with_content("Item created"), LooposUi::Log.new(date: 1.day.ago, user: "Jane Smith", error: true).with_content("Error occurred")]render LooposUi::LogList.new( id: "my-logs", logs: logs,)Factory System
The LogList component uses a factory system to convert different data sources into LooposUi::ListLog objects.
Similar to the LooposUi::Log component, the factory system is used to create the log lists.
It expects a source object, and returns a LooposUi::ListLog object.
Built-in Factories
LooposUi comes with two built-in factories, which already handle pagination and sorting.
- CoreItemLogListPresenterHash: Handles hash data from one core item log presenter.
Source: (Core)
Item.log_presenter.view_logsis an example of such data. - Script: Handles
LoopOs::Script(source) objects
Controller Usage
class ItemsController < ApplicationController def logs pagy, logs = pagy( SomeLog.where(item: @item).order(created_at: :desc), page: params[:page], items: 15 ) render LooposUi::LogList.new( id: "item-#{@item.id}-logs", logs: logs, pagy: pagy, path: item_logs_path(@item) ) endendPerformance Considerations
Warnings
The component will log warnings in the following scenarios:
- Missing Path: When
pathis not provided, pagination will use the current path. - Too Many Logs: When more than
config.max_itemslogs are passed, performance may be impacted. Ensure to paginate the data.
Error Handling
The component includes a NilLog constant that represents a failed log creation, displaying "Failed to show this log." when errors occur during initialization.
- If
createraises an exception, it returnsLooposUi::Log::NilLog - In development mode, exceptions are re-raised for debugging
- Errors are logged for production debugging