.container.my-5 .d-flex.justify-content-between.align-items-center.mb-4 h1.fw-bold Manage features - if current_user.developer? .btn-group button.btn.btn-success.shadow-sm[data-bs-toggle="modal" data-bs-target="#addFeatureModal"] i.bi.bi-plus-circle.me-2 | Add New Feature button.btn.btn-danger.shadow-sm.ms-2[data-bs-toggle="modal" data-bs-target="#removeFeatureModal"] i.bi.bi-trash.me-2 | Remove Feature p.text-muted.mb-5 Click on a card to manage features for an organization. #featuresApp[data-controller="features"] .input-group.mb-4 span.input-group-text.bg-light.border-0 i.bi.bi-search input.form-control.border-0.bg-light[type="text" placeholder="Search organizations..." autocomplete="off" v-model="searchQuery"] div.d-flex.justify-content-center.align-items-center.py-5(v-if="!filteredOrganizations.length && !isLoading") .spinner-border.text-primary[role="status"] span.visually-hidden Loading... div.row.row-cols-1.row-cols-md-2.row-cols-lg-3.g-4(v-if="filteredOrganizations.length") div.col(v-for="org in filteredOrganizations" :key="org.id") div.card.h-100.shadow-sm.custom-card(@click="showModal(org)") div.card-body div.d-flex.justify-content-between.align-items-center.mb-3 h5.card-title.fw-bold.text-truncate | {{ org.name }} i.bi.bi-building.text-primary.display-6 p.card-subtitle.text-muted.mb-2 Enabled Features: ul.list-unstyled(v-if="org.enabled_features.length") li(v-for="feature in org.enabled_features" :key="feature.name") i.bi.bi-check-lg.text-success.me-2 | {{ feature.name }} div.text-muted(v-else) | No features enabled. div.card-footer.bg-white.border-0 button.btn.btn-sm.btn-outline-primary.w-100 i.bi.bi-toggle-on.me-2 | Manage Features #featureModal.modal.fade[tabindex="-1" aria-labelledby="featureModalLabel" aria-hidden="true"] .modal-dialog.modal-dialog-centered .modal-content div.modal-header h5#featureModalLabel.modal-title | Manage Features for {{ selectedOrganization ? selectedOrganization.name : '' }} button.btn-close[type="button" data-bs-dismiss="modal" aria-label="Close"] .modal-body div.d-flex.justify-content-center.my-3(v-if="isLoading") div.spinner-border.text-primary(role="status") span.visually-hidden Loading... div(v-else-if="features.length") p.mb-3.text-muted Found {{ features.length }} feature(s) ul.list-group.list-group-flush li.list-group-item.d-flex.justify-content-between.align-items-center(v-for="feature in features" :key="feature.name") div.fw-bold | {{ feature.name }} div.form-check.form-switch input.form-check-input(type="checkbox" role="switch" :id="`toggle-${feature.name}`" :checked="feature.enabled" @change="toggleFeature(feature.name, $event.target.checked)") label.form-check-label(:for="`toggle-${feature.name}`") div.text-center.text-muted.py-3(v-else) | No features available .modal-footer button.btn.btn-secondary(type="button" data-bs-dismiss="modal") Close #addFeatureModal.modal.fade[tabindex="-1" aria-labelledby="addFeatureModalLabel" aria-hidden="true"] .modal-dialog.modal-dialog-centered .modal-content .modal-header h5#addFeatureModalLabel.modal-title Add a New Feature button.btn-close[type="button" data-bs-dismiss="modal" aria-label="Close"] .modal-body form#addFeatureForm .mb-3 label.form-label[for="newFeatureName"] Feature Name input.form-control#newFeatureName[type="text" placeholder="e.g., model_selection" v-model="newFeatureName" autocomplete="off"] .modal-footer button.btn.btn-secondary[type="button" data-bs-dismiss="modal"] Cancel button.btn.btn-primary#addFeatureBtn[type="submit" @click.prevent="addFeature"] Add Feature #removeFeatureModal.modal.fade[tabindex="-1" aria-labelledby="removeFeatureModalLabel" aria-hidden="true"] .modal-dialog.modal-dialog-centered .modal-content .modal-header h5#removeFeatureModalLabel.modal-title Remove a Feature button.btn-close[type="button" data-bs-dismiss="modal" aria-label="Close"] .modal-body p.text-muted.mb-3 Select a feature to permanently remove it and its settings. This action cannot be undone. div.mb-3(v-if="features.length") label.form-label[for="featureToRemove"] Feature to Remove select.form-select.border-0.bg-light#featureToRemove(v-model="featureToRemoveName") option(value="" disabled) Select a feature... option(v-for="feature in features" :key="feature.name" :value="feature.name") | {{ feature.name }} div.text-center.text-muted.py-3(v-else) | No features to remove. .modal-footer button.btn.btn-secondary[type="button" data-bs-dismiss="modal"] Cancel button.btn.btn-danger(type="button" :disabled="!featureToRemoveName" @click.prevent="removeFeature") | Remove Feature .toast-container.position-fixed.top-0.end-0.p-3 .toast id="tagSuccessToast" role="alert" aria-live="assertive" aria-atomic="true" .toast-header i.feather-18.text-success data-feather="check-circle" strong.ms-2.me-auto Success! button.btn-close.btn-sm data-bs-dismiss="toast" aria-label="Close" .toast-body | {{ successMessage }} .toast-container.position-fixed.top-0.end-0.p-3 .toast id="tagErrorToast" role="alert" aria-live="assertive" aria-atomic="true" .toast-header i.feather-18.text-danger data-feather="x-octagon" strong.ms-2.me-auto Error! button.btn-close.btn-sm data-bs-dismiss="toast" aria-label="Close" .toast-body | {{ errorMessage }}