diff --git a/.idea/deployment.xml b/.idea/deployment.xml index 52e2038..57133a7 100644 --- a/.idea/deployment.xml +++ b/.idea/deployment.xml @@ -1,6 +1,6 @@ - + diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..db2378a --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ProjetProgWeb/api.php b/ProjetProgWeb/api.php index 736c61c..a1d77e3 100644 --- a/ProjetProgWeb/api.php +++ b/ProjetProgWeb/api.php @@ -2,8 +2,7 @@ require_once("class/dump.php"); -if (!isset($_GET['q']) || !isset($_GET['search']) || !isset($_GET['option']) || !isset($_GET['offset']) || - ($_GET['option'] == 'establishment' && $_GET['q'] == 'establishment')) { +if (!isset($_GET['q']) || !isset($_GET['search']) || !isset($_GET['option']) || !isset($_GET['offset'])) { print_r(json_encode(array("status" => 400, "message" => "Missing query type or attributes."))); exit(); } @@ -27,7 +26,7 @@ $json_object = match ($q) { "count" => dump::getThesesCount($search, $option), "years" => dump::getThesesYears($search, $option), "disciplines" => dump::getThesesDisciplines($search, $option), - "establishment" => dump::getThesesEstablishments($search, $option), + "establishments" => dump::getThesesEstablishments($search, $option), default => NULL, }; diff --git a/ProjetProgWeb/app.js b/ProjetProgWeb/app.js index 9cbad7b..b4390d7 100644 --- a/ProjetProgWeb/app.js +++ b/ProjetProgWeb/app.js @@ -24,6 +24,46 @@ let pagesNumbers = document.querySelector('.page-nav div') let resultsDiv = document.querySelector('#results') let resultsCount = document.querySelector('#results-count') let filters = document.querySelectorAll('.filters p') +let backgroundLoading = document.querySelector('.background-loading') +let charts = document.querySelector('#charts') + +let chartsState = false + +function hideLoading() { + loader.style.display = "none" + backgroundLoading.style.display = "none" + document.body.style.height = "auto" + document.body.style.overflow = "scroll" +} + +function showLoading() { + loader.style.display = "block" + backgroundLoading.style.display = "block" + document.body.style.height = "100%" + document.body.style.overflow = "hidden" +} + +function hideError() { + error.classList.replace('fade-in', 'fade-out') + let errorDisplay = window.setTimeout(function () { + error.style.display = "none" + }, 250) +} + +function showError(message) { + error.style.display = "flex" + error.classList.remove("fade-out"); + error.classList.add("fade-in"); + errorMessage.innerHTML = message +} + +function hideCharts() { + // TODO À faire notamment pour le toggle switch qui alterne le site avec et sans charts +} + +function showCharts() { + charts.style.display = "flex" +} function sanitize(chain) { return chain.replace(/[^a-zA-Z0-9\- ]/g, '') @@ -65,8 +105,8 @@ function apiRequestThese(search, offset) { lastRequest = new Date().getTime() emptyResults(true) pagesNumbers.innerHTML = "" - loader.style.display = "block" - pagesNumbersContainer.style.display = 'none' + showLoading() + pagesNumbersContainer.style.display = "none" searchString = sanitize(search) fetch(`api.php?q=theses&search=${searchString}&option=${queryOption}&offset=${offset}`) .then(response => response.json()) @@ -129,11 +169,10 @@ let currentPage = null function displayResults(results, aCount) { if (results.status === 400) { - loader.style.display = "none" - error.classList.remove("fade-out"); - error.classList.add("fade-in"); - errorMessage.innerHTML = results.message + hideLoading() + showError(results.message) } else if (results.status === 200) { + initCharts(searchString, queryOption) count = aCount resultsArray = [] pagesNumbersContainer.style.display = 'flex' @@ -144,12 +183,12 @@ function displayResults(results, aCount) { let header = document.createElement('div') - let qTitle = elem[3] + let qTitle = elem[2] let title = document.createElement('h3') let pre_replacement = new RegExp(searchString, 'gi').exec(qTitle) title.innerHTML = qTitle.replace(pre_replacement, `${pre_replacement}`) - let qAuthor = elem[1] + let qAuthor = elem[0] let author = document.createElement('p') pre_replacement = new RegExp(searchString, 'gi').exec(qAuthor) author.innerHTML = qAuthor.replace(pre_replacement, `${pre_replacement}`) @@ -159,11 +198,11 @@ function displayResults(results, aCount) { let onlineButton = document.createElement('button') onlineButton.innerHTML = "" - if (elem[15] === 'no') { + if (elem[14] === 'no') { onlineButton.disabled = true } else { onlineButton.onclick = function () { - window.open('https://www.theses.fr/' + elem[14] + '/document', ',_blank') + window.open('https://www.theses.fr/' + elem[13] + '/document', ',_blank') } } @@ -197,8 +236,6 @@ function displayResults(results, aCount) { ${new Intl.NumberFormat('fr-FR', {maximumSignificantDigits: 3}).format(count)}.` resultsCount.appendChild(nb) - loader.style.display = "none" - nbPages = Math.ceil(count / RESULTS_NUMBER) for (let i = 0; i < nbPages; i++) { @@ -223,6 +260,13 @@ function displayResults(results, aCount) { currentPage = (parseInt(urlOffset) + RESULTS_NUMBER) / RESULTS_NUMBER updatePageNumber(currentPage) fadeIn() + let waitForPageToLoad = setInterval(function() { + if (chartsState) { + hideLoading() + showCharts() + clearInterval(waitForPageToLoad); + } + }, 100) } } @@ -264,7 +308,7 @@ function realTimeDisplay() { name.innerHTML = elem name.addEventListener('click', () => { searchBar.value = elem - apiRequestThese(elem, 0) + submitForm(urlOffset) }) suggestions.appendChild(name) }) @@ -326,7 +370,7 @@ document.addEventListener('click', e => { } if (e.target === errorButton || e.target === errorButton.firstElementChild) { - error.classList.replace('fade-in', 'fade-out') + hideError() } let toggleSwitch = null diff --git a/ProjetProgWeb/charts.js b/ProjetProgWeb/charts.js new file mode 100644 index 0000000..6916f7a --- /dev/null +++ b/ProjetProgWeb/charts.js @@ -0,0 +1,182 @@ +let chart1State = false +let chart2State = false +let chart3State = false + +function initYearsChart(results) { + let categories = [] + let online = [] + let offline = [] + let total = [] + + results.data.forEach(elem => { + let year = Object.keys(elem)[0] + categories.push(year) + online.push(parseInt(elem[year].online)) + offline.push(parseInt(elem[year].offline)) + total.push(parseInt(elem[year].online) + parseInt(elem[year].offline)) + }) + + Highcharts.chart('years', { + "title": { + "text": "Nombre de thèses et leurs disponibilités en ligne selon leurs années de soutenance" + }, + "xAxis": { + "categories": categories, + "title": { + "text": "Années" + } + }, + "yAxis": { + "title": { + "text": "Thèses" + } + }, + "tooltip": { + "shared": true, + "valueSuffix": " thèses" + }, + "credits": { + "enabled": false + }, + "series": [ + { + "name": "Total", + "data": total, + "color": "#f4d03f", + "dashStyle": "longdash", + "marker": { + "enabled": false + } + }, + { + "name": "En ligne", + "data": online, + "color": "#5dade2", + "marker": { + "enabled": false + } + }, + { + "name": "Hors ligne", + "data": offline, + "color": "#cd6155", + "marker": { + "enabled": false + } + } + ] + }) + + chart1State = true +} + +function initDisciplinesChart(results) { + let data = [] + + results.data.forEach(elem => { + let disc = Object.keys(elem)[0] + let obj = { + "name" : disc, + "y" : parseInt(elem[disc]) + } + data.push(obj) + }) + + Highcharts.chart('disciplines', { + "chart": { + "type": "pie" + }, + "title": { + "text": "Nombre de thèses par disciplines" + }, + "plotOptions": { + "pie": { + "dataLabels": { + "enabled": (window.innerWidth >= SMALL) + }, + "showInLegend": (window.innerWidth < SMALL) + } + }, + "credits": { + "enabled": false + }, + "series": [ + { + "name": "Thèses", + "colorByPoint": true, + "data": data + } + ] + }) + + chart2State = true +} + +function initEstablishmentsChart(results) { + let data = [] + + results.data.forEach(elem => { + let disc = Object.keys(elem)[0] + let obj = { + "name" : disc, + "y" : parseInt(elem[disc]) + } + data.push(obj) + }) + + Highcharts.chart('establishments', { + "chart": { + "type": "pie" + }, + "title": { + "text": "Nombre de thèses soutenues par établissements" + }, + "plotOptions": { + "pie": { + "dataLabels": { + "enabled": (window.innerWidth >= SMALL) + }, + "showInLegend": (window.innerWidth < SMALL) + } + }, + "credits": { + "enabled": false + }, + "series": [ + { + "name": "Thèses", + "colorByPoint": true, + "data": data + } + ] + }) + + chart3State = true +} + +function initCharts(search, option) { + fetch(`api.php?q=years&search=${search}&option=${option}&offset=0`) + .then(response => response.json()) + .then(results => { + initYearsChart(results) + }) + + fetch(`api.php?q=disciplines&search=${search}&option=${option}&offset=0`) + .then(response => response.json()) + .then(results => { + initDisciplinesChart(results) + }) + + fetch(`api.php?q=establishments&search=${search}&option=${option}&offset=0`) + .then(response => response.json()) + .then(results => { + initEstablishmentsChart(results) + }) + + let waitForChartsToLoad = setInterval(function() { + if (chart1State && chart2State && chart2State) { + chartsState = true + clearInterval(waitForChartsToLoad); + } + }, 100) +} \ No newline at end of file diff --git a/ProjetProgWeb/class/dump.php b/ProjetProgWeb/class/dump.php index c4a8d1c..1684501 100644 --- a/ProjetProgWeb/class/dump.php +++ b/ProjetProgWeb/class/dump.php @@ -231,7 +231,7 @@ class dump { OR soutenance_establishment LIKE :search GROUP BY Discipline ORDER BY `Number` DESC - LIMIT 10 + LIMIT 10; "), 'author' => $pdo->prepare("SELECT discipline AS Discipline, COUNT(discipline) AS Number FROM theses WHERE author LIKE :search GROUP BY Discipline ORDER BY `Number` DESC LIMIT 10;"), 'title' => $pdo->prepare("SELECT discipline AS Discipline, COUNT(discipline) AS Number FROM theses WHERE title LIKE :search GROUP BY Discipline ORDER BY `Number` DESC LIMIT 10;"), @@ -276,7 +276,8 @@ class dump { "), 'author' => $pdo->prepare("SELECT soutenance_establishment AS Establishment, COUNT(soutenance_establishment) AS Number FROM theses WHERE author LIKE :search GROUP BY Establishment ORDER BY `Number` DESC LIMIT 10;"), 'title' => $pdo->prepare("SELECT soutenance_establishment AS Establishment, COUNT(soutenance_establishment) AS Number FROM theses WHERE title LIKE :search GROUP BY Establishment ORDER BY `Number` DESC LIMIT 10;"), - 'director' => $pdo->prepare("SELECT soutenance_establishment AS Establishment, COUNT(soutenance_establishment) AS Number FROM theses WHERE theses.these_director LIKE :search GROUP BY Establishment ORDER BY `Number` DESC LIMIT 10;"), + 'director' => $pdo->prepare("SELECT soutenance_establishment AS Establishment, COUNT(soutenance_establishment) AS Number FROM theses WHERE these_director LIKE :search GROUP BY Establishment ORDER BY `Number` DESC LIMIT 10;"), + 'establishment' => $pdo->prepare("SELECT soutenance_establishment AS Establishment, COUNT(soutenance_establishment) AS Number FROM theses WHERE soutenance_establishment LIKE :search GROUP BY Establishment ORDER BY `Number` DESC LIMIT 10;"), default => "", }; diff --git a/ProjetProgWeb/index.php b/ProjetProgWeb/index.php index 7585acd..6ee95ec 100644 --- a/ProjetProgWeb/index.php +++ b/ProjetProgWeb/index.php @@ -11,6 +11,8 @@ include("navbar.php"); ?> +
+ @@ -27,6 +29,12 @@ +
+
+
+
+
+