.respondent-container[ data-controller="respondent-list" data-respondent-list-status-url-value=respondent_list_task_status_project_respondent_category_path(@project, @respondent_category) ] .card.mt-2.mb-2.d-none data-respondent-list-target="bulkActions" .card-body.d-flex.align-items-center.justify-content-between.py-2 div span.fw-bold.me-2 Selected: span.badge.bg-primary.me-2 data-respondent-list-target="count" 0 button.btn.btn-link.btn-sm.text-decoration-none.p-0 type="button" data-action="click->respondent-list#resetSelection" | (Clear) .d-flex.align-items-center.gap-2 button.btn.btn-outline-primary.btn-sm type="button" data-action="click->respondent-list#moveRespondentsDialog" i.feather-14.me-1 data-feather="arrow-right-circle" | Move button.btn.btn-outline-primary.btn-sm type="button" data-action="click->respondent-list#downloadTranscripts" i.feather-14.me-1 data-feather="download" | Download Transcripts button.btn.btn-outline-primary.btn-sm type="button" data-action="click->respondent-list#downloadTranscriptsExcel" i.feather-14.me-1 data-feather="file-spreadsheet" | Download Transcripts (Excel) button.btn.btn-outline-primary.btn-sm type="button" data-action="click->respondent-list#downloadSummaries" i.feather-14.me-1 data-feather="download" | Download Summaries button.btn.btn-outline-primary.btn-sm.position-relative[ type="button" data-action="click->respondent-list#generateBookmarks" data-respondent-list-target="bookmarksBtn" disabled=@bookmarks_generating ] span.d-flex.align-items-center class="#{'d-none' if @bookmarks_generating}" data-respondent-list-target="bookmarksIdle" i.feather-14.me-1 data-feather="bookmark" | Generate Sections span.d-flex.align-items-center class="#{'d-none' unless @bookmarks_generating}" data-respondent-list-target="bookmarksLoading" span.spinner-border.spinner-border-sm.me-2 role="status" aria-hidden="true" | Generating... button.btn.btn-outline-primary.btn-sm.position-relative[ type="button" data-action="click->respondent-list#summarizeTranscripts" data-respondent-list-target="summariesBtn" disabled=@transcripts_summarizing ] span.d-flex.align-items-center class="#{'d-none' if @transcripts_summarizing}" data-respondent-list-target="summariesIdle" i.feather-14.me-1 data-feather="file-text" | Summarize Transcripts span.d-flex.align-items-center class="#{'d-none' unless @transcripts_summarizing}" data-respondent-list-target="summariesLoading" span.spinner-border.spinner-border-sm.me-2 role="status" aria-hidden="true" | Summarizing... table.table.table-striped.table-borderless.mt-3.monospaced-table.fs-12 data-respondent-list-target="table" thead tr th.text-center style="width: 50px; vertical-align: middle;" .form-check.d-flex.justify-content-center.align-items-center input.form-check-input.cb-lg type="checkbox" data-respondent-list-target="selectAll" data-action="change->respondent-list#toggleAll" th style="max-width: 25vw; width: 25vw; vertical-align: middle;" = t(:name) th.text-center style="max-width: 11vw; vertical-align: middle;" = t(:type) th.text-center style="vertical-align: middle;" .d-flex.align-items-center.justify-content-center = t(:tags) .dropdown button.btn.btn-sm.btn-outline-secondary.dropdown-toggle type="button" data-bs-toggle="dropdown" aria-expanded="false" data-respondent-list-target="tagFilterButton" i.bi.bi-funnel .dropdown-menu.p-3 style="min-width: 250px;" data-respondent-list-target="tagFilterDropdown" onclick="event.stopPropagation();" .mb-2 input.form-control.form-control-sm type="text" placeholder="Search tags..." data-respondent-list-target="tagSearch" data-action="input->respondent-list#filterTagOptions" .tag-filter-options style="max-height: 300px; overflow-y: auto;" data-respondent-list-target="tagOptions" - if all_tags.count.positive? - all_tags.each do |tag| .form-check input.form-check-input type="checkbox" value="#{tag["name"]}" id="tag_#{tag["id"]}" data-respondent-list-target="tagCheckbox" data-action="change->respondent-list#applyTagFilter" label.form-check-label for="tag_#{tag["id"]}" = tag["name"] - else small.text-muted No tags found hr.my-2 .d-flex.justify-content-between.align-items-center button.btn.btn-sm.btn-link.text-decoration-none.p-0 type="button" data-action="click->respondent-list#clearTagFilter" | Clear all span.badge.bg-primary data-respondent-list-target="selectedTagCount" | 0 selected th.text-center style="vertical-align: middle;" = t(:media) th.text-center style="vertical-align: middle;" = t(:model) th.text-center style="vertical-align: middle;" = t(:bookmark_sections) th.text-center style="vertical-align: middle;" = t(:all_tags) th.text-center style="vertical-align: middle;" = t(:insights_status) th style="vertical-align: middle;" tbody - @respondents.includes(:whisper_transcript, :interview_insights).each do | respondent | - status = transcript_status(respondent) tr td.align-middle.text-center .form-check.d-flex.justify-content-center.align-items-center input.form-check-input.cb-lg type="checkbox" value="#{respondent.id}" data-respondent-list-target="checkbox" data-action="change->respondent-list#toggleOne" td.align-middle.text-wrap style="max-width: 25vw; width: 25vw" = link_to respondent.name, project_respondent_category_respondent_path(@project, @respondent_category, respondent) td.align-middle.text-center style="max-width: 11vw;" - if status == 'transcribing' - if respondent.model_with_no_progression? .state-pill-running span Running .dot.pulse-dot - else .progress-container id="progress_container_#{respondent.id}" .progress-bar .stripes id="stripes_#{respondent.id}" style="width: #{respondent.initial_transcribing_progress}%;" - elsif status == "video_conversion" | Processing Video - elsif status == 'none' | None - elsif status == 'manual' | Manual - elsif status == 'ai' | AI - else = link_to generate_internal_transcript_project_respondent_category_respondent_path(@project, @respondent_category, respondent), class: 'btn btn-secondary btn-sm ms-2 fs-10', style: "font-weight: 700; fontpadding: 5px; padding-top: 0px; padding-bottom: 0px;", data: { turbo_method: :post, turbo_confirm: "This will launch a transcription machine and transcribe the file: #{respondent.audio_file_file_name}. Are you sure you want to continue?" } do | QUEUE TRANSCRIPT td.align-middle.text-center data-search="#{respondent.tags.map(&:name).join('|')}" data-order="#{respondent.tags.size}" - if respondent.tags.any? / 1. Display first tag span.badge.bg-secondary.me-1.text-black.fs-10 = respondent.tags.first.name / 2. Display counter + tooltip for the rest - if respondent.tags.size > 1 - remaining_tags = respondent.tags[1..].map(&:name).join(', ') span.badge.bg-light.text-dark.border.fs-10 style="cursor: help;" data-bs-toggle="tooltip" data-bs-placement="top" title="#{remaining_tags}" | +#{respondent.tags.size - 1} td.align-middle.text-center = media_type_badge(respondent) td.align-middle.text-center span.badge.text-dark.bg-light.px-2.py-1.rounded = respondent.model_display_name td.align-middle.text-center = sprintf '%02d', respondent.transcript_sections.size = link_to "Manage", project_respondent_category_respondent_path(@project, @respondent_category, respondent, :edit => true), class: "btn btn-secondary btn-sm ms-2 fs-10", style: "font-weight: 600; fontpadding: 5px; padding-top: 0px; padding-bottom: 0px;" td.align-middle.text-end.text-center = sprintf '%02d', respondent.tags.size = link_to t(:tag), tag_project_respondent_category_respondent_path(@project, @respondent_category, respondent), class: "btn #{respondent.tags.size == 0 ? "btn-primary" : "btn-secondary"} btn-sm ms-2 fs-10 modal-trigger", style: "padding: 5px; padding-top: 0px; padding-bottom: 0px;", data: { turbo_frame: "modal_frame" } td.align-middle.text-center - if respondent.audio_file_file_name.nil? && respondent.transcript_file_name.nil? span.badge.text-bg-success.text-white .fs-10.semi-bold | MISSING TRANSCRIPT - elsif respondent.transcript_file_name.nil? && respondent.whisper_transcript.nil? span.badge.text-bg-success.text-white .fs-10.semi-bold | MISSING TRANSCRIPT - elsif respondent.interview_insights.empty? span.badge.text-bg-primary.text-white .fs-10.semi-bold | MISSING INSIGHTS - else span.badge.text-bg-secondary.text-primary .fs-10.semi-bold | INSIGHTS READY td.align-middle.text-center class="#{!current_user.organization.feature_enabled?(:respondent_cloning) ? 'py-3': 'py-0'}" - unless status == 'transcribing' = button_to [@project, @respondent_category, respondent], method: :delete, form: { data: { turbo_method: :delete, turbo_confirm: 'This will forever delete the respondent. This is irreversible. Are you sure?' } }, class: "btn btn-link text-primary" do i.feather-14 data-feather="trash-2" - if current_user.organization.feature_enabled?(:respondent_cloning) = button_to clone_project_respondent_category_respondent_path(@project, @respondent_category, respondent), method: :post, form: { data: { turbo_method: :post, turbo_confirm: 'Are you sure you want to create a copy of this respondent?' } }, class: "btn btn-link text-primary" do i.feather-14 data-feather="copy" .toast-container.position-fixed.top-0.end-0.p-3 style="z-index: 1080" #downloadToast.toast[ role="alert" aria-live="assertive" aria-atomic="true" data-respondent-list-target="toast" ] .toast-header.text-white[data-respondent-list-target="toastHeader"] strong.me-auto Notification button.btn-close.btn-close-white type="button" data-bs-dismiss="toast" aria-label="Close" .toast-body#toastMessage[data-respondent-list-target="toastMessage"] | Initializing... / Move Respondents Modal .modal.fade id="moveRespondentsModal" tabindex="-1" aria-labelledby="moveRespondentsLabel" aria-hidden="true" data-respondent-list-target="moveModal" .modal-dialog .modal-content .modal-header h5.modal-title Move Selected Respondents button.btn-close type="button" data-bs-dismiss="modal" aria-label="Close" .modal-body p.text-mutedSelect Select the destination Project and Sub-Project. .mb-3 label.form-label.fw-bold for="targetProject" Target Project select.form-control data-respondent-list-target="projectSelect" id="targetProject" option value="" placeholder="true" Select a Project... .mb-3 label.form-label.fw-bold for="targetCategory" Target Sub-Project select.form-control data-respondent-list-target="categorySelect" id="targetCategory" disabled=true option value="" placeholder="true" First select a project... small.text-muted | Note - This action will remove the selected respondents from the section & theme reports of the original project/sub-project. It will also remove any tags from respondents if the selected project is not the current project. .modal-footer button.btn.btn-secondary type="button" data-bs-dismiss="modal" Cancel button.btn.btn-primary type="button" data-action="click->respondent-list#moveRespondents" | Confirm Move