<div style="display: flex; flex-direction: column; width: 100%;"> <turbo-frame id="lui-log-list-mocked-log-list-preview" class="lui-log_list"> <div class="lui-log_list__group" data-date="04-06-2025"> <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_de4df71c7b74"> <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"> 04-06-2025 </span> </div> </div> </span> </button> <div aria-controls="accordion_6e9b82a81ab3" class="lui-accordion__buttons"> </div> </div> <div id="accordion_19bf8467fc62" 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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Transition </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> double_arrow </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">Item </div> <div class="lui-log__word">transitioned </div> <div class="lui-log__word">from </div> <b>Handling - Terminated</b> <div class="lui-log__word">to </div> <b>End Terminated Handling - Terminated</b> <div class="lui-log__word">.</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"> 04/06/2025 16:18 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #495057; background-color: #ECEFF2;"> <i class="fa-regular fa-envelope lui-label__icon"></i> <span class="lui-label__text" data-lui--label="content">Submission XPTO</span> </span> </a></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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Email </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> mail </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <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">daniel.albino@theloop.pt</div> </div> <div class="lui-log__content__header__description"> By alexandre.rocha@theloop.pt </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 04/06/2025 16:18 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #495057; background-color: #ECEFF2;"> <i class="fa-regular fa-credit-card lui-label__icon"></i> <span class="lui-label__text" data-lui--label="content">Submission XPTO</span> </span> </a></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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> SMS </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> message </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">SMS </div> <div class="lui-log__word">sent </div> <div class="lui-log__word">to </div> <div class="lui-log__word">+351 </div> <div class="lui-log__word">912 </div> <div class="lui-log__word">345 </div> <div class="lui-log__word">678.</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"> 04/06/2025 16:17 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #495057; background-color: #ECEFF2;"> <i class="fa-regular fa-message-sms lui-label__icon"></i> <span class="lui-label__text" data-lui--label="content">Submission XPTO</span> </span> </a></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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Outgoing Payment </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <mask id="mask0_1093_6120" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="40" height="40"> <rect width="40" height="40" fill="#D9D9D9"/> </mask> <g mask="url(#mask0_1093_6120)"> <path d="M20 21.3149C21.3889 21.3149 22.5694 21.8011 23.5417 22.7733C24.5139 23.7455 25 24.9261 25 26.3149C25 27.7038 24.5139 28.8844 23.5417 29.8566C22.5694 30.8288 21.3889 31.3149 20 31.3149C18.6111 31.3149 17.4306 30.8288 16.4583 29.8566C15.4861 28.8844 15 27.7038 15 26.3149C15 24.9261 15.4861 23.7455 16.4583 22.7733C17.4306 21.8011 18.6111 21.3149 20 21.3149ZM31.6667 16.3149C32.5833 16.3149 33.3681 16.6413 34.0208 17.2941C34.6736 17.9469 35 18.7316 35 19.6483L35 32.9816C35 33.8983 34.6736 34.683 34.0208 35.3358C33.3681 35.9886 32.5833 36.3149 31.6667 36.3149L8.33333 36.3149C7.41667 36.3149 6.63194 35.9886 5.97917 35.3358C5.32639 34.683 5 33.8983 5 32.9816L5 19.6483C5 18.7316 5.32639 17.9469 5.97917 17.2941C6.63195 16.6413 7.41667 16.3149 8.33334 16.3149L31.6667 16.3149ZM28.3333 19.6483L11.6667 19.6483C11.6667 20.5649 11.3403 21.3497 10.6875 22.0024C10.0347 22.6552 9.25 22.9816 8.33334 22.9816L8.33333 29.6483C9.25 29.6483 10.0347 29.9747 10.6875 30.6274C11.3403 31.2802 11.6667 32.0649 11.6667 32.9816L28.3333 32.9816C28.3333 32.0649 28.6597 31.2802 29.3125 30.6274C29.9653 29.9747 30.75 29.6483 31.6667 29.6483L31.6667 22.9816C30.75 22.9816 29.9653 22.6552 29.3125 22.0024C28.6597 21.3497 28.3333 20.5649 28.3333 19.6483ZM21.6667 9.31494L23.1667 10.8149C23.4722 11.1205 23.8611 11.2733 24.3333 11.2733C24.8056 11.2733 25.1944 11.1205 25.5 10.8149C25.8056 10.5094 25.9583 10.1205 25.9583 9.64827C25.9583 9.17605 25.8056 8.78716 25.5 8.48161L21.1667 4.14827C21 3.9816 20.8194 3.86355 20.625 3.79411C20.4306 3.72467 20.2222 3.68994 20 3.68994C19.7778 3.68994 19.5694 3.72467 19.375 3.79411C19.1806 3.86355 19 3.9816 18.8333 4.14827L14.5 8.48161C14.1944 8.78716 14.0417 9.17605 14.0417 9.64827C14.0417 10.1205 14.1944 10.5094 14.5 10.8149C14.8056 11.1205 15.1944 11.2733 15.6667 11.2733C16.1389 11.2733 16.5278 11.1205 16.8333 10.8149L18.3333 9.31494L18.3333 12.9816C18.3333 13.4538 18.4931 13.8497 18.8125 14.1691C19.1319 14.4886 19.5278 14.6483 20 14.6483C20.4722 14.6483 20.8681 14.4886 21.1875 14.1691C21.5069 13.8497 21.6667 13.4538 21.6667 12.9816L21.6667 9.31494Z" fill="currentColor"/> </g> </svg> </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">Outgoing </div> <div class="lui-log__word">payment </div> <div class="lui-log__word">of </div> <div class="lui-log__word">150.00 </div> <div class="lui-log__word">EUR </div> <div class="lui-log__word">processed.</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"> 04/06/2025 16:16 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #495057; background-color: #ECEFF2;"> <i class="fa-regular fa-credit-card lui-label__icon"></i> <span class="lui-label__text" data-lui--label="content">Submission XPTO</span> </span> </a></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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Incoming Payment </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> payment_arrow_down </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">Incoming </div> <div class="lui-log__word">payment </div> <div class="lui-log__word">of </div> <div class="lui-log__word">200.00 </div> <div class="lui-log__word">EUR </div> <div class="lui-log__word">received.</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"> 04/06/2025 16:15 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #495057; background-color: #ECEFF2;"> <i class="fa-regular fa-credit-card lui-label__icon"></i> <span class="lui-label__text" data-lui--label="content">Submission XPTO</span> </span> </a></div> </div> </div> </div> </div> </div> </div> </div> <div class="lui-log_list__group" data-date="03-06-2025"> <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_7109bdd83b7d"> <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"> 03-06-2025 </span> </div> </div> </span> </button> <div aria-controls="accordion_f860e48e6666" class="lui-accordion__buttons"> </div> </div> <div id="accordion_a670077114b5" 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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Shipping </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> local_shipping </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">Shipment </div> <div class="lui-log__word">created. </div> <div class="lui-log__word">Tracking: </div> <div class="lui-log__word">DPD </div> <div class="lui-log__word">1234567890.</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"> 03/06/2025 12:44 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #495057; background-color: #ECEFF2;"> <i class="fa-regular fa-truck lui-label__icon"></i> <span class="lui-label__text" data-lui--label="content">Validation Block</span> </span> </a></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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Invoice </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> receipt_long </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">Invoice </div> <div class="lui-log__word">INV-2025-001 </div> <div class="lui-log__word">issued.</div> </div> <div class="lui-log__content__header__description"> By maria.silva@theloop.pt </div> <div class="lui-log__buttons"></div> </div> </div> <div class="lui-log__source_content"> 03/06/2025 12:42 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #495057; background-color: #ECEFF2;"> <i class="fa-regular fa-file-invoice lui-label__icon"></i> <span class="lui-label__text" data-lui--label="content">Validation Block</span> </span> </a></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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Item Value </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> money_range </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <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">agreed </div> <div class="lui-log__word">to </div> <div class="lui-log__word">cancelled.</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"> 03/06/2025 12:40 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #212529; background-color: #ECEFF2;"> <svg height="12" width="12" viewBox="0 0 12 12"> <path d="M7.92298 12H1.15375V8.30769C1.15375 7.26974 1.58452 6.33026 2.2758 5.65949C1.91068 5.53641 1.50862 5.32923 1.16606 4.98872C0.647086 4.4718 0.384521 3.77641 0.384521 2.92308C0.384521 0.777436 2.13221 0 3.3076 0H5.61529C7.2276 0 8.53837 1.31077 8.53837 2.92308V4.66872C9.84914 4.8841 11.6153 5.81128 11.6153 8.30769C11.6153 9.38872 11.285 10.2667 10.6327 10.9169C9.56196 11.9836 8.01324 12 7.92298 12ZM2.38452 10.7692H7.92298C8.17529 10.7692 10.3845 10.6872 10.3845 8.30769C10.3845 5.92821 8.17734 5.84821 7.92093 5.84615H4.84606C3.48811 5.84615 2.38452 6.94974 2.38452 8.30769V10.7692ZM3.3076 1.23077C3.3076 1.23077 2.83785 1.23897 2.39888 1.47077C1.8717 1.74769 1.61529 2.22154 1.61529 2.92308C1.61529 3.62462 1.8717 4.10256 2.39683 4.37949C2.8358 4.60923 3.3035 4.61538 3.30965 4.61538H7.3076V2.92308C7.3076 1.98974 6.54862 1.23077 5.61529 1.23077H3.3076Z" fill="url(#paint0_svg_49a8c2628a44)"/> <defs> <linearGradient id="paint0_svg_49a8c2628a44" x1="6.00093" y1="12" x2="6.00093" y2="0" gradientUnits="userSpaceOnUse"> <stop stop-color="#FFAA38"/> <stop offset="1" stop-color="#FFCB33"/> </linearGradient> </defs> </svg> <span class="lui-label__text" data-lui--label="content">Validation Block</span> </span> </a></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"> <div class="lui-log__content__icon"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Item </div> </div> <i class="lui-m_icon material-symbols-outlined" style="--lui-micon-size: 20px;"> package_2 </i> </div> <div class="lui-log__content__header"> <div class="lui-log__content__header__title" data-log-target="content"> <div class="lui-log__word">Item </div> <div class="lui-log__word">created.</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"> 03/06/2025 12:38 <a href="https://www.google.pt" class="lui-log__source_content__link" target="_blank" data-turbo="false"> <span class="lui-label" style="color: #212529; background-color: #ECEFF2;"> <svg height="12" width="12" viewBox="0 0 12 12"> <path d="M7.92298 12H1.15375V8.30769C1.15375 7.26974 1.58452 6.33026 2.2758 5.65949C1.91068 5.53641 1.50862 5.32923 1.16606 4.98872C0.647086 4.4718 0.384521 3.77641 0.384521 2.92308C0.384521 0.777436 2.13221 0 3.3076 0H5.61529C7.2276 0 8.53837 1.31077 8.53837 2.92308V4.66872C9.84914 4.8841 11.6153 5.81128 11.6153 8.30769C11.6153 9.38872 11.285 10.2667 10.6327 10.9169C9.56196 11.9836 8.01324 12 7.92298 12ZM2.38452 10.7692H7.92298C8.17529 10.7692 10.3845 10.6872 10.3845 8.30769C10.3845 5.92821 8.17734 5.84821 7.92093 5.84615H4.84606C3.48811 5.84615 2.38452 6.94974 2.38452 8.30769V10.7692ZM3.3076 1.23077C3.3076 1.23077 2.83785 1.23897 2.39888 1.47077C1.8717 1.74769 1.61529 2.22154 1.61529 2.92308C1.61529 3.62462 1.8717 4.10256 2.39683 4.37949C2.8358 4.60923 3.3035 4.61538 3.30965 4.61538H7.3076V2.92308C7.3076 1.98974 6.54862 1.23077 5.61529 1.23077H3.3076Z" fill="url(#paint0_svg_a802c1eb876e)"/> <defs> <linearGradient id="paint0_svg_a802c1eb876e" x1="6.00093" y1="12" x2="6.00093" y2="0" gradientUnits="userSpaceOnUse"> <stop stop-color="#FFAA38"/> <stop offset="1" stop-color="#FFCB33"/> </linearGradient> </defs> </svg> <span class="lui-label__text" data-lui--label="content">Validation Block</span> </span> </a></div> </div> </div> </div> </div> </div> </div> </div> </turbo-frame></div>LogList
Groups and renders logs by date with optional pagination/lazy loading support. It is the standard logs renderer in item tabs and logs modals.
Related components
| Used components | Components where it is used |
|---|---|
Log |
Individual entry rendering |
LogList::Group |
Date grouping wrapper |
Pagy |
Pagination integration when provided |
Usage rules
- ✅ Prefer
LooposUi::LogList.from_any_source(...)for backend payloads. - ✅ Pass
idand keepconfig.max_itemsaligned with endpoint pagination. - ✅
from_any_sourceexpects positionalsource(from_any_source(source, id:, ...)), notsource:. - ✅ If
config.has_paginationis enabled, passpage:. - ✅ Prefer
pagy:; otherwise passpagination: { page:, items:, count: }. - ✅ Pass
path:for stable pagination links (otherwise current path is used and a warning is logged). - ✅ If passing
items:, ensure the collection is non-empty (items.firstis used for factory detection). - ❌ Do not use deprecated
LogsComponent; useLogListinstead.
<div style="display: flex; flex-direction: column; width: 100%;"> <%= render LooposUi::LogList.from_any_source( log_list, id: "mocked-log-list-preview", page: page, config: { max_items: 15 } ) %></div>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 rendering behavior (used mostly by from_any_source) |
|
pagy |
nil |
Pagy object for pagination. Prefer over pagination. |
|
pagination |
nil |
Fallback pagination hash used to build Pagy (page, items, count) |
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 |
Pagination Hash (pagination:)
When you don't pass pagy:, you can pass:
pagination: { page: 1, # Integer, default 1 items: 15, # Integer, default Config::MAX_ITEMS count: 42 # Integer, required}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( 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( script_proxy, id: "script-logs", config: { max_items: 15 }, page: params[:page] || 1)from_any_source signature:
LooposUi::LogList.from_any_source(source, id:, config: {}, **options)Important pagination rule:
- If
config.has_paginationistrue, you must passpage:in**options. - If
page:is missing while pagination is enabled, it raises:"page must be present in the options if you want to use pagination"
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 grouped item logs from Core item presenter hashes. Source example: grouped logs payload returned by item logs endpoints/presenters.
- Script: Handles
LoopOs::Script(source) objects
Current production usage
LogList.from_any_source is the primary entrypoint used in item logs tabs and
financial logs modal/list flows. Prefer this over manually instantiating logs
unless you already have LooposUi::Log instances.
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 links use the current request path (can render more than just logs). - 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