import { create_dataframe, create_selection, create_uploaded_file_radio, showLoader, clearPreviousContent, resetContainers, showSuccess, showElement, showError, hideElement, openModal, closeModal } from './methods.js'; $(document).ready(function () { // --- Fade-in Animation on Scroll --- const fadeElements = $('.fade-in'); function handleFadeAnimation() { fadeElements.each(function () { if ($(this).offset().top <= $(window).scrollTop() + $(window).height()) { $(this).addClass('visible'); } }); } $(window).on('scroll', handleFadeAnimation); handleFadeAnimation(); // --- Cached DOM Elements --- const $newOrLoad = $('#new_or_load'); const $viewPreTrainedButton = $('#viewPreTrainedButton'); const $datasetButtons = $('.btn-dataset'); const $timeseriesDatasets = $('#timeseries-datasets input[type="radio"]'); const $radioButtons = $('#radio_buttons'); const $uploadBtn = $('#upload_btn'); const $labelSelectionModal = $('#labelSelectionModal'); const $positiveDropdown = $('#positive-label'); const $negativeDropdown = $('#negative-label'); const $saveLabelChoicesBtn = $('#save-label-choices'); const $loader = $('#loader'); // --- Utility Functions --- function showOrHideViewModelsButton() { if (localStorage.getItem('datasetSelected') === 'true') { $newOrLoad.show(); } else { $newOrLoad.hide(); } } function updateDropdownOptions($dropdown, options, exclude, currentValue = null) { $dropdown.empty(); $dropdown.append(''); options.forEach(option => { if (option !== exclude) { $dropdown.append( `` ); } }); if (exclude === currentValue) { $dropdown.val(""); } } function validateSelection(positive, negative, showErrorMsg = false) { const $errorContainer = $("#selection-error"); if (!positive || !negative) { if (showErrorMsg) $errorContainer.text("You must select both a positive and a negative label!").removeClass("d-none"); return false; } if (positive === negative) { if (showErrorMsg) $errorContainer.text("Positive and Negative labels must be different!").removeClass("d-none"); return false; } $errorContainer.addClass("d-none").text(""); return true; } // --- AJAX Helpers --- function postData(url, data, onSuccess, onError, showLoaders = []) { showLoaders.forEach(sel => showElement($(sel))); $.ajax({ method: 'POST', url: url, headers: { 'X-CSRFToken': $("[name=csrfmiddlewaretoken]").val() }, data: data, success: function (resp) { showLoaders.forEach(sel => hideElement($(sel))); onSuccess(resp); }, error: function (err) { showLoaders.forEach(sel => hideElement($(sel))); if (onError) onError(err); else showError('An error occurred. Please try again.', 'error-message'); } }); } // --- Dataset Fetch and Render --- function fetchAndRenderDataset(df_name) { showLoader(true); postData( '', { action: "dataset", df_name: df_name }, function (values) { showLoader(false); clearPreviousContent(); if (!values) return; const datasetType = values["dataset_type"]; localStorage.setItem("selectedDatasetType", datasetType); if (datasetType === "tabular") renderTabularDataset(values); else if (datasetType === "timeseries") renderTimeseriesDataset(values); $newOrLoad.show(); } ); } function renderTabularDataset(ret) { const { data_to_display: df, fig, features, feature1, feature2, labels, curlabel } = ret; const selection1 = create_selection(features, "feature1", null, feature1); const selection2 = create_selection(features, "feature2", null, feature2); const selection3 = create_selection(labels, "label", null, curlabel); const tb = create_dataframe(df, "df_container"); $("#model_container, #df, #df_stats").fadeIn(200); $("#df_div").append(tb); if ($("#selection").is(":visible")) { $("#selection").empty().append(selection1, selection2, selection3); } else if ($("#selection").is(":hidden")) { $("#stats_div").prepend( $("
", { class: "d-flex mb-3", id: "selection" }) .append(selection1, selection2, selection3) ); } // Update or create stats_container if ($("#stats_container").length > 0) { $("#stats_container").html(fig); } else { $("#stats_div").append($("
", { id: 'stats_container', class: "plotly_fig" }).html(fig)); } } function renderTimeseriesDataset(ret) { const { fig, fig1 } = ret; $("#ts_stats, #ts_confidence").fadeIn(200); $("#ts_stats_div").append($("
", { id: 'ts_confidence_container', class: "plotly_fig" }).html(fig)); $("#ts_confidence_div").append($("
", { id: 'ts_stats_container', class: "plotly_fig" }).html(fig1)); } // --- Dataset Button Click Handler --- function handleDatasetClick(elementId) { const df_name = elementId === "upload" ? "upload" : elementId; $("#new_or_load_cached").hide(); resetContainers(); $("#upload_col").toggle(df_name === "upload"); $("#timeseries-datasets").toggle(df_name === "timeseries"); $(`#${elementId}`).toggleClass("active").siblings().removeClass("active"); $(`#${elementId}`).addClass("active"); const timeseries_dataset = df_name === "timeseries" ? $("input:radio[name=timeseries_dataset]:checked").val() : ""; if (timeseries_dataset || (df_name !== "timeseries")) { fetchAndRenderDataset(timeseries_dataset || df_name); localStorage.setItem('datasetSelected', 'true'); } else { $newOrLoad.hide(); localStorage.setItem('datasetSelected', 'false'); } } // --- Event Bindings --- $datasetButtons.on('click', function () { handleDatasetClick($(this).attr('id')); }); $('#timeseries-datasets').on('click', function () { handleDatasetClick('timeseries'); }); // --- Uploaded Dataset Radio Change --- $radioButtons.on('change', function () { const uploaded_dataset = $("input:radio[name=uploaded_file]:checked").val(); if (!uploaded_dataset) return; resetContainers(); showElement($("#loader_ds")); showElement($("#loader_stats")); postData( '', { action: "uploaded_datasets", df_name: uploaded_dataset }, function (values) { hideElement($("#loader_ds")); hideElement($("#loader_stats")); $newOrLoad.show(); clearPreviousContent(); if (!values) return; const dataset_type = values["dataset_type"]; localStorage.setItem("selectedDatasetType", dataset_type); if (dataset_type === "tabular") renderTabularDataset(values); else if (dataset_type === "timeseries") renderTimeseriesDataset(values); } ); }); // --- Pre-trained Models Button --- $viewPreTrainedButton.on('click', function () { window.location.href = '/charts.html'; }); // --- Show/Hide View Models Button on Load --- showOrHideViewModelsButton(); // --- File Upload Handler --- $uploadBtn.on('click', async function (event) { event.preventDefault(); const datasetType = $('input[name="dataset_type"]:checked').val(); const fileInput = $('#doc')[0].files[0]; const csrfToken = $('input[name="csrfmiddlewaretoken"]').val(); let valid = true, message = ""; if (!datasetType && !fileInput) { valid = false; message = 'Please select a dataset type and choose a file to upload.'; } else if (!datasetType) { valid = false; message = 'Please define the type of the uploaded dataset.'; } else if (!fileInput) { valid = false; message = 'Please choose a file to upload.'; } if (!valid) { showError(message, "error-message"); return; } const formData = new FormData(); formData.append('action', 'upload_dataset'); formData.append('dataset_type', datasetType); formData.append('excel_file', fileInput); formData.append('csrfmiddlewaretoken', csrfToken); hideElement($uploadBtn); showElement($('#cfbtn_loader')); try { const response = await fetch('', { method: 'POST', headers: { 'X-CSRFToken': csrfToken, 'X-Requested-With': 'XMLHttpRequest' }, body: formData }); if (response.ok) { const data = await response.json(); handleUploadResponse(data); hideElement($('#cfbtn_loader')); showElement($uploadBtn); hideElement($('#default-non-uploaded')); } else { throw new Error(await response.text() || 'Unknown server error'); } } catch (error) { showError(`An error occurred during upload: ${error.message}`, "error-message"); } finally { hideElement($('#cfbtn_loader')); } }); function handleUploadResponse(data) { const { df_name, uploaded_files, target_labels } = data; const counter = uploaded_files - 1; hideElement($("#default-non-uploaded")); $radioButtons.append(create_uploaded_file_radio(df_name, counter)); if (target_labels) populateLabelModal(target_labels); showSuccess('File uploaded successfully!', "success-message"); } function populateLabelModal(targetLabels) { updateDropdownOptions($positiveDropdown, targetLabels); updateDropdownOptions($negativeDropdown, targetLabels); showError(null); openModal($labelSelectionModal[0]); let selectedPositive = null, selectedNegative = null; $positiveDropdown.on('change', function () { selectedPositive = $(this).val(); updateDropdownOptions($negativeDropdown, targetLabels, selectedPositive); validateSelection(selectedPositive, selectedNegative); }); $negativeDropdown.on('change', function () { selectedNegative = $(this).val(); updateDropdownOptions($positiveDropdown, targetLabels, selectedNegative); validateSelection(selectedPositive, selectedNegative); }); } $saveLabelChoicesBtn.on('click', async function () { const selectedPositive = $positiveDropdown.val(); const selectedNegative = $negativeDropdown.val(); if (!validateSelection(selectedPositive, selectedNegative, true)) { showError("Labels cannot be assigned the same value.", "selection-error"); return; } const csrfToken = $('input[name="csrfmiddlewaretoken"]').val(); const formData = new FormData(); formData.append('action', 'select_class_labels_for_uploaded_timeseries'); formData.append('positive_label', selectedPositive); formData.append('negative_label', selectedNegative); formData.append('csrfmiddlewaretoken', csrfToken); showElement($loader); $saveLabelChoicesBtn.prop('disabled', true); try { const response = await fetch('', { method: 'POST', headers: { 'X-CSRFToken': csrfToken, 'X-Requested-With': 'XMLHttpRequest' }, body: formData }); if (response.ok) { closeModal($labelSelectionModal[0]); showSuccess('Labels saved successfully!', "success-message"); } else { throw new Error(await response.text() || 'Unknown server error'); } } catch (error) { showError(error.message || 'An error occurred while saving labels.', "selection-error"); } finally { hideElement($loader); $saveLabelChoicesBtn.prop('disabled', false); } }); // --- Selection Change for Tabular Stats --- $('#stats_div').on('change', function () { const feature1 = $('#feature1').val(); const feature2 = $('#feature2').val(); const label = $('#label').val(); $("#stats_container").remove(); showElement($('#loader_stats')); postData( '', { action: "stat", feature1, feature2, label }, function (ret) { hideElement($('#loader_stats')); $("#stats_div").append($('
', { id: 'stats_container' }).html(ret["fig"])); } ); }); // --- Delete Uploaded File --- $('#confirmDeleteButton').on('click', function () { const fileName = $(this).data('file'); const uploaded_dataset = $("input:radio[name=uploaded_file]:checked").val(); hideElement($("#cancel_delete_buttons_modal_delete")); showElement($("#loader_modal_delete")); postData( '', { action: 'delete_uploaded_file', dataset_name: fileName, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val() }, function () { hideElement($("#loader_modal_delete")); $(`[data-file="${fileName}"]`).closest('.form-check').remove(); if ($('#radio_buttons .form-check').length === 0) showElement($('#default-non-uploaded')); showElement($("#success-message-modal-delete")); if (fileName === uploaded_dataset) resetContainers(); } ); }); // --- Dismiss Alerts --- $(document).on('click', '.alert', function () { $(this).hide(); }); // --- Pre-trained Models Button (duplicate for legacy support) --- $('#viewModelsButton').on('click', function () { window.location.href = "/charts.html"; }); // --- Restore UI State on Reload --- const savedDataset = localStorage.getItem('selectedDatasetType'); if (savedDataset === 'tabular') { $("#df, #df_stats").show(); } else if (savedDataset === 'timeseries') { $("#ts_confidence, #ts_stats").show(); } showOrHideViewModelsButton(); });