diff --git a/API.js b/API.js new file mode 100755 index 0000000..d5b8def --- /dev/null +++ b/API.js @@ -0,0 +1,77 @@ +/* classe API */ +function APIClass(){}; + +APIClass.prototype = { + xhr: [], // tableau d'objets pour les requêtes ajax + + + + /* transaction avec le serveur (API.php) + * + * @param pRequest l'objet passé en JSON à API.php + * @param pHandler fonction qui s'éxécutera lors de la réponse (1 argument -> réponse) + * + * @return answer l'objet retourné par API.php via pHandler (1er argument) + * + *************************************************************************************************** + * + * @usecase + * 1. var answerObject = sendRequest( + * 2. { var1: "exemple", var2: 198294 }, + * 3. function(rep){ alert(rep); } + * 4. ); + * @explain + * 1. on appelle la fonction <=> on créé la requête + * 2. on passe l'objet qui sera envoyé + * 3. on passe une fonction qui utilise un argument (sera la réponse de API.php) (sous forme d'objet) + * + */ + send: function(pRequest, pHandler){ + + // on efface les requêtes qui sont terminées (toutes celles de this.xhr) + for( var i = 0 ; i < this.xhr.length ; i++ ){ + if( this.xhr[i].readyState == 4 ) // si terminée + this.xhr = this.xhr.slice(0,i-1).concat(this.xhr.slice(i,this.xhr.length-1)); // suppression entrée + } + + // on créé une nouvelle entrée + this.xhr.push(null); + i = this.xhr.length-1; + + // création de l'objet AJAX + if(window.XMLHttpRequest) // IE7+, Firefox, Chrome, Opera, Safari + this.xhr[i] = new XMLHttpRequest(); + else // IE5, IE6 + this.xhr[i] = new ActiveXObject('Microsoft.XMLHttpRequest'); + + console.log(pRequest); + + var ptrAPI = this; + this.xhr[i].onreadystatechange = function(){ + if( ptrAPI.xhr[i].readyState == 4 ){ // si la requête est terminée + + /* DEBUG : affiche la réponse BRUTE de API.php */ + // console.log('API.php => '+ptrAPI.xhr[i].responseText); + console.log(JSON.parse(ptrAPI.xhr[i].responseText) ); + + /* si success de requête */ + if( [0,200].indexOf(ptrAPI.xhr[i].status) > -1 ){ // si fichier existe et reçu + try{ pHandler( JSON.parse(ptrAPI.xhr[i].responseText) ); } // si on peut parser, on envoie + catch(e){ pHandler({request:'corrupted'}); } // sinon on envoie obj.request = 'corrupted' + } + /* sinon retourne obj.request = 'unreachable' */ + else + pHandler({request: 'unreachable'}); + + } + } + + // on créé un formulaire POST (virtuel) + var form = new FormData(); + form.append('json', JSON.stringify(pRequest) ); // on créé la variable $_POST['json']=>request + + this.xhr[i].open('POST', 'API.php', true); + this.xhr[i].send( form ); + + } +}; diff --git a/API.php b/API.php new file mode 100755 index 0000000..08d527c --- /dev/null +++ b/API.php @@ -0,0 +1,99 @@ +level_0 ){ + + /***************/ + /* UTILISATEUR */ + /***************/ + case 'user': + if( isset($request->level_1) ){ include 'manager/user.php'; user_switch_level_1($request, $answer); } + else { $answer->request = 'missing_level_1'; } + break; + + + /***********/ + /* GROUPES */ + /***********/ + case 'groups': + $answer->type = "group"; + break; + + + /******/ + /* UE */ + /******/ + case 'ues': + break; + + + /**********/ + /* MODULE */ + /**********/ + case 'modules': + break; + + + /************/ + /* CONTRÔLE */ + /************/ + case 'tests': + break; + + + /**************/ + /* PARAMETRES */ + /**************/ + case 'settings': + break; + + + /***********/ + /* DEFAULT */ + /***********/ + default: + $answer->request = 'unknown_level_0'; + break; + } + + + if( $answer == null ) + $answer->request = 'no_level_0'; + + + + }else // si json corrompu (undécodable) + $answer->request = 'jsoncorrupted'; + + }else // $_POST vide [OU] $_POST['json'] pas défini + $answer->request = 'nopost'; + + + // on envoie (affiche) l'objet en JSON + echo json_encode($answer); + + } + +?> \ No newline at end of file diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 6ad259f..ae4adf0 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ # SID -Système d'Information du Département diff --git a/css/container.css b/css/container.css new file mode 100755 index 0000000..e69de29 diff --git a/css/global.css b/css/global.css new file mode 100755 index 0000000..af02993 --- /dev/null +++ b/css/global.css @@ -0,0 +1,293 @@ +/* +* +* Gestion des règles globales +* ------------------------------------- +* 1-1. sections +* 1-2. titres des sections +* 2-1. tableaux génériques +* 2-2. tableaux manuels +* 3. formulaires +* 4. paragraphes +* 5. liens +* 6. ... +* +*/ + + + + + +/*********************/ +/*** 1-1. Sections ***/ +/*********************/ +Hgroup + section{ + /* position */ + display: none; /* on cache par défaut si le titre n'est pas actif */ + position: absolute; + top: calc( 5px + 3em + 1px ); /* 1px pour que le border soit au même endroit que celui de Hgroup */ + left: 0; + width: calc( 100% - 2*2em ); + height: auto; + padding: 2em; /* top right/left bottom */ + + /* border */ + border-top: 1px solid #aaa; + + /* z axis */ + z-index: 7; +} + +/* on active le premier par défaut si aucun n'est .active*/ +/*Hgroup:nth-child(1) + section{ + display: block; + z-index: 8; +}*/ + +Hgroup.active + section{ + display: block; + z-index: 9; +} + + +/********************************/ +/*** 1-2. Titres des sections ***/ +/********************************/ +Hgroup{ + /* position */ + display: block; + position: relative; + float: left; + margin-top: 5px; + margin-left: 1em; + height: 3em; + padding: 0 2em; + + /* border */ + border-radius: 3px 3px 0 0; + border: 1px solid transparent; + border-bottom-color: #aaa; + + /* background */ + background-color: inherit; + + /* foreground */ + color: #666; + text-align: center; + line-height: 3em; + + /* Xtra */ + cursor: pointer; + + /* animation */ + transition: .1s ease-in-out; + -moz-transition: .1s ease-in-out; + -webkit-transition: .1s ease-in-out; + -ms-transition: .1s ease-in-out; + -o-transition: .1s ease-in-out; + + /* z axis */ + z-index: 10; +} + + +/*Hgroup:nth-child(1) ~ .active,*/ +Hgroup.active{ + /* border */ + border-color: #aaa; + border-bottom-color: inherit; + + /* foreground */ + color: #000; +} + + + + + + + + + + + + + +/********************************/ +/*** 2-1. Tableaux génériques ***/ +/********************************/ +table { + font-family:Arial, Helvetica, sans-serif; + color:#666; + font-size:12px; + text-shadow: 1px 1px 0px #fff; + background:#eaebec; + margin:20px; + border:#ccc 1px solid; + + border-spacing: 0; + + -moz-border-radius:3px; + -webkit-border-radius:3px; + border-radius:3px; + + -moz-box-shadow: 0 1px 2px #d1d1d1; + -webkit-box-shadow: 0 1px 2px #d1d1d1; + box-shadow: 0 1px 2px #d1d1d1; + + text-align: center; +} + +table th { + padding:21px 25px 22px 25px; + border-top:1px solid #fafafa; + border-bottom:1px solid #e0e0e0; + + background: #ededed; + background: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#ebebeb)); + background: -moz-linear-gradient(top, #ededed, #ebebeb); +} + +table tr:first-child th:first-child { + -moz-border-radius-topleft:3px; + -webkit-border-top-left-radius:3px; + border-top-left-radius:3px; +} + +table tr:first-child th:last-child { + -moz-border-radius-topright:3px; + -webkit-border-top-right-radius:3px; + border-top-right-radius:3px; +} + +table tr { + padding-left:20px; +} + +table td:first-child { + border-left: 0; +} + +table td { + padding:18px; + border-top: 1px solid #ffffff; + border-bottom:1px solid #e0e0e0; + border-left: 1px solid #e0e0e0; + + background: #fafafa; + background: -webkit-gradient(linear, left top, left bottom, from(#fbfbfb), to(#fafafa)); + background: -moz-linear-gradient(top, #fbfbfb, #fafafa); +} + +table tr.even td { + background: #f6f6f6; + background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#f6f6f6)); + background: -moz-linear-gradient(top, #f8f8f8, #f6f6f6); +} + +table tr:last-child td { + border-bottom:0; +} + +table tr:last-child td:first-child { + -moz-border-radius-bottomleft:3px; + -webkit-border-bottom-left-radius:3px; + border-bottom-left-radius:3px; +} + +table tr:last-child td:last-child { + -moz-border-radius-bottomright:3px; + -webkit-border-bottom-right-radius:3px; + border-bottom-right-radius:3px; +} + +table tr:hover td { + background: #f2f2f2; + background: -webkit-gradient(linear, left top, left bottom, from(#f2f2f2), to(#f0f0f0)); + background: -moz-linear-gradient(top, #f2f2f2, #f0f0f0); +} + +/* http://johnsardine.com/example/simple-little-table/ */ + + +/**********************/ +/*** 3. Formulaires ***/ +/**********************/ +/* champs de texte */ +section form input[type=text], +section form input[type=password]{ + /* position */ + display: block; + position: relative; + margin: 2em 0; + padding: .8em; + padding-left: 2.5em; + + /* border */ + border-radius: 3px; + border: 1px solid #aaa; + + /* foreground */ + font-family: inherit; + font-size: 1em; + color: #b1b1b1; + + /* background */ + background: #fff url(../src/input_icon/default_grayscale.svg) center left .35em no-repeat; + background-size: 1.8em 1.8em; + + transition: .2s ease-in-out; + -moz-transition: .2s ease-in-out; + -webkit-transition: .2s ease-in-out; + -ms-transition: .2s ease-in-out; + -o-transition: .2s ease-in-out; +} + +/* boutons */ +section form input[type=button]{ + /* position */ + display: block; + position: relative; + margin: 1em 0; + padding: .8em; + + /* border */ + border-radius: 3px; + border: 0; + box-shadow: 1px 1px 0 #207fa8, 2px 2px 0 #207fa8; + + /* foreground */ + font-family: inherit; + font-size: 1em; + color: #fff; + font-weight: bold; + + /* background */ + background: #29a2d6; + + /* Xtra */ + cursor: pointer; +} + +/* clic sur les boutons */ +section form input[type=button]:focus{ + box-shadow: 0 0 0 transparent; + margin-top: calc( 1em + 2px ); + margin-left: 2px; +} + + +/* quand on selectionne */ +section form input[type=text]:focus, +section form input[type=password]:focus{ + background-image: url(../src/input_icon/default.svg); + color: #000; + border-color: #29a2d6; +} + + +/* GESTION DES ICÔNES SPECIFIQUES */ +section form input[type=password] { background-image: url(../src/input_icon/password_grayscale.svg); } +section form input[type=password]:focus{ background-image: url(../src/input_icon/password.svg); } + +section form input.user { background-image: url(../src/input_icon/user_grayscale.svg); } +section form input.user:focus { background-image: url(../src/input_icon/user.svg); } diff --git a/css/header.css b/css/header.css new file mode 100755 index 0000000..abcdea3 --- /dev/null +++ b/css/header.css @@ -0,0 +1,10 @@ +/* +* +* Gestion complète du HEADER +* ------------------------------------- +* 1. icon +* 2. connection/inscription +* 3. mot de passe perdu +* 4. ... +* +*/ \ No newline at end of file diff --git a/css/layout.css b/css/layout.css new file mode 100755 index 0000000..290f42d --- /dev/null +++ b/css/layout.css @@ -0,0 +1,189 @@ +/* +* +* Positionnement global et mise en page +* ------------------------------------- +* 1. Propriétés globales +* 2. MENU +* 3. CONTAINER +* 4. msgBox +* +*/ + + + + + + + + +/******************************/ +/*** 1. Propriétés globales ***/ +/******************************/ +*{ /* on supprime le margin/padding par défaut */ + margin : 0; + padding: 0; +} + + +/* on initialise le body avec les valeurs par défaut [compatibilité] */ +body{ + /* position */ + display: block; + position: absolute; + top : 0; + left : 0; + width : 100%; + height: 100%; + + /* background */ + background: #fff; + + /* overflow */ + overflow-x: hidden; /* empêche la barre horizontale de scroll [précaution] */ + + /* foreground */ + font: 18px 'Open Sans', 'Helvetica', 'Arial', 'sans-serif'; + font-size: 16px; +} + + + + + + + +/***************/ +/*** 2. MENU ***/ +/***************/ +#MENU{ + /* position */ + display: flex; + position: fixed; + top : 0; + left : 0; + width : 5.5em; + height: 100%; + + /* flex */ + flex-direction : column; + justify-content: flex-start; + flex-wrap: nowrap; /* default, une seule colonne */ + + + /* background */ + /*background: #424c54 url(https://www.iut-tlse3.fr/static/ui/v1/icons/iut/iut.png) bottom .9em center no-repeat;*/ + background: #424c54; + + /* foreground */ + /*font-size: 1.7vh;*/ + + /* z axis */ + z-index: 2; + + /* list */ + list-style-type: none; +} + + + + + +/********************/ +/*** 3. CONTAINER ***/ +/********************/ +#CONTAINER{ + /* position */ + display: block; + position: absolute; + top : 0; + left : 5.5em; + width : calc( 100% - 5.5em ); + min-height: 100%; + + /* background */ + background: #fff; + + /* foreground */ + /*font-size: 1.7vh;*/ + + /* border < inherit < hgroup */ + border-color: #fff; + + /* z axis */ + z-index: 0; +} + + +/*****************/ +/*** 4. MSGBOX ***/ +/*****************/ +#MSGBOX{ + /* position */ + display: block; + position: fixed; + top: calc( 100% - 2*1em - 1em - 1em ); /* 100% - padding - taille - marge */ + left: 30%; + width: 40%; + height: 1em; + padding: 1em; + + /* border */ + border-radius: 3px; + border: 1px solid transparent; + + /* background */ + background-color: #f64b2f; + + /* foreground */ + color: #fff; + text-shadow: 1px 1px 1px #d33e27; + line-height: 1em; + + transition: all 0s ease 0s, top .3s ease-in-out; + -moz-transition: all 0s ease 0s, top .3s ease-in-out; + -webkit-transition: all 0s ease 0s, top .3s ease-in-out; + -ms-transition: all 0s ease 0s, top .3s ease-in-out; + -o-transition: all 0s ease 0s, top .3s ease-in-out; +} + +/* LES DIFFERENTES CLASSES */ + +/* validation ou réussite */ +#MSGBOX.success{ + border-color: #689525; + background-color: #7eb62e; + text-shadow: 1px 1px 1px #689525; +} + +/* information */ +#MSGBOX.info{ + border-color: #278fd0; + background-color: #2fa9f6; + text-shadow: 1px 1px 1px #278fd0; +} + +/* avertissement */ +#MSGBOX.warning{ + border-color: #d87620; + background-color: #f68725; + text-shadow: 1px 1px 1px #d87620; +} + +/* notice */ +#MSGBOX.error{ + border-color: #d33e27; + background-color: #f64b2f; + text-shadow: 1px 1px 1px #d33e27; +} + +/* LORSQUE PAS ACTIVE */ +#MSGBOX:not( [class] ), /* si n'a pas de classe */ +#MSGBOX[class='']{ /* ou qu'elle est vide */ + top: 100%; + + transition: all 0s ease .3s, top .3s ease-in-out; + -moz-transition: all 0s ease .3s, top .3s ease-in-out; + -webkit-transition: all 0s ease .3s, top .3s ease-in-out; + -ms-transition: all 0s ease .3s, top .3s ease-in-out; + -o-transition: all 0s ease .3s, top .3s ease-in-out; +} \ No newline at end of file diff --git a/css/menu.css b/css/menu.css new file mode 100755 index 0000000..1307ee8 --- /dev/null +++ b/css/menu.css @@ -0,0 +1,170 @@ + +* +* Gestion complète du MENU +* ------------------------------------- +* 1. propriétés complémentaires #MENU +* 2. position textes +* 3. icônes +* 4. Labels +* +*/ + + + + +/*******************************************/ +/*** 1. Propriétés complémentaires #MENU ***/ +/*******************************************/ +#MENU{} + + + +/**************************/ +/*** 2. Position textes ***/ +/**************************/ +#MENU li{ + /* position */ + display: block; + position: relative; + margin: .75em; + width: 4em; /* 5.5 - 1.5 */ + height: 4em; + + /* border */ + border-radius: .3em; + + /* background */ + background: center center no-repeat; + background-size: auto 2.2em; + + /* Xtra */ + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + /* animation */ + transition: all 0s, background-color .2s ease-in-out; + -moz-transition: all 0s, background-color .2s ease-in-out; + -webkit-transition: all 0s, background-color .2s ease-in-out; + -ms-transition: all 0s, background-color .2s ease-in-out; + -o-transition: all 0s, background-color .2s ease-in-out; +} + + + +/*****************/ +/*** 3. Icônes ***/ +/*****************/ +/* dernier en bas */ +#MENU li:last-child{ align-self: flex-start; } + +/* icônes de base */ +#MENU li[data-link='home'] { background-image: url(../src/menu_icon/home_grayscale.svg); } +#MENU li[data-link='groups'] { background-image: url(../src/menu_icon/groups_grayscale.svg); } +#MENU li[data-link='ue'] { background-image: url(../src/menu_icon/ue_grayscale.svg); } +#MENU li[data-link='modules'] { background-image: url(../src/menu_icon/modules_grayscale.svg); } +#MENU li[data-link='marks'] { background-image: url(../src/menu_icon/marks_grayscale.svg); } +#MENU li[data-link='settings'] { background-image: url(../src/menu_icon/settings_grayscale.svg); } +#MENU li[data-link='auth'] { background-image: url(../src/menu_icon/auth_grayscale.svg); } + +/* HOVER ou active (page courante) */ +#MENU li:hover, #MENU li.active{ + color: #fff; + background-color: rgba(0,0,0,.3); +} + +/* icône quand HOVER ou .active */ +#MENU li[data-link='home']:hover , #MENU li[data-link='home'].active { background-image: url(../src/menu_icon/home.svg); } +#MENU li[data-link='groups']:hover , #MENU li[data-link='groups'].active { background-image: url(../src/menu_icon/groups.svg); } +#MENU li[data-link='ue']:hover , #MENU li[data-link='ue'].active { background-image: url(../src/menu_icon/ue.svg); } +#MENU li[data-link='modules']:hover , #MENU li[data-link='modules'].active { background-image: url(../src/menu_icon/modules.svg); } +#MENU li[data-link='marks']:hover , #MENU li[data-link='marks'].active { background-image: url(../src/menu_icon/marks.svg); } +#MENU li[data-link='settings']:hover , #MENU li[data-link='settings'].active { background-image: url(../src/menu_icon/settings.svg); } +#MENU li[data-link='auth']:hover , #MENU li[data-link='auth'].active { background-image: url(../src/menu_icon/auth.svg); } + + +/* le séparateur qui remplit l'espace entre le haut et le bas */ +#MENU li.fill{ + flex-grow: 1; + opacity: 0; + cursor: default; +} + + + +/*****************/ +/*** 4. Labels ***/ +/*****************/ +#MENU li[data-text]::before{ /* affichage du texte */ + content: attr(data-text); + + /* position */ + display: block; + position: absolute; + top: .4em; + left: 6em; + width: auto; + width: 0; + height: 3em; + padding: 0 0; + + /* border */ + border-radius: 5px; + + /* background */ + background: #232323; + + /* foreground */ + line-height: 3em; + + /* animation */ + transition: .1s ease-out; + -moz-transition: .1s ease-out; + -webkit-transition: .1s ease-out; + -ms-transition: .1s ease-out; + -o-transition: .1s ease-out; + + /* overflow */ + overflow: hidden; + + /* z axis */ + z-index: -1; +} + + + +#MENU li[data-text]::after{ /* petite flèche */ + content: ''; + + /* position */ + display: none; + position: absolute; + top: 1.16em; + left: 5.7em; + + /* border */ + border-style: solid; + border-width: .8em .8em .8em 0; + border-color: transparent #232323 transparent transparent; + + /* animation */ + transition: .2s ease-in; + -moz-transition: .2s ease-in; + -webkit-transition: .2s ease-in; + -ms-transition: .2s ease-in; + -o-transition: .2s ease-in; + + /* z axis */ + z-index: -1; +} + + + +/* lors du survol */ + +#MENU li[data-text]:hover::before{ width: auto; left: 6em; padding: 0 1em; } /* affichage du texte */ + +#MENU li[data-text]:hover::after{ display: block; } /* affichage de la petite flèche \ No newline at end of file diff --git a/index.php b/index.php new file mode 100755 index 0000000..a25e302 --- /dev/null +++ b/index.php @@ -0,0 +1,78 @@ + + + + + + + Système d'Information du Département + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Hey! Your password is not the right one.
+ + + + + + + + + + + + + diff --git a/js/actionScript.js b/js/actionScript.js new file mode 100755 index 0000000..723d7b0 --- /dev/null +++ b/js/actionScript.js @@ -0,0 +1,264 @@ + + /*********************************************************** + * * + * SCRIPT POST-HTML - SCRIPT PRINCIPAL * + * * + ************************************************************ + * * + * [0] Variables * + * [1] Gestionnaires de navigation * + * [a] pageManager.js * + * [b] API.js * + * [2] Gestion des liens * + * [a] catégories * + * [b] sous-parties * + * [3] Gestion des formulaires * + * [4] Gestion de la messageBox * + * * + * * + * * + * * + * * + * * + * * + * * + * * + ***********************************************************/ + + +/* [0] VARIABLES +==============================================================*/ +var msgBoxTimeout = null; + +/* pageManager */ +var pageM; +/* API */ +var API; + +/* Structure de la page */ +var DOM = { + menu : document.getElementById('MENU'), + container : document.getElementById('CONTAINER'), + msgBox : document.getElementById('MSGBOX') +}; + + + + + + + +/* [1] GESTIONNAIRES DE NAVIGATION +==============================================================*/ + + + /* [a] pageManager.js + ==============================================================*/ + pageM = new pageManager(); // instance principale + + /* initialisation du gestionnaire */ + pageM.setPage(null, 'page', DOM.container, ['home', 'groups', 'ue', 'modules', 'marks', 'auth', 'settings'] ); + + + /* [b] API.js + ==============================================================*/ + API = new APIClass(); + + + + + + + +/* [2] GESTION DES LIENS +==============================================================*/ + + + /* [a] CATÉGORIES + ==============================================================*/ + /* GESTION DES CATEGORIES (SECTIONS) + * + * @param section l'élément à activer + * + * [1] selectionne l'élément, l'affichage de la page associée est géré par pageManager.js + * [2] déselectionne l'élément précédemment selectioné + * + */ + function selectSection(section){ + + // si @subSection est un de type
  • qui a la propriété "data-link" [ET] section pas déjà active + if( section instanceof Element && section.tagName == 'LI' && section.dataset.hasOwnProperty('link') && section.className != 'active' ){ + + // on charge la page + pageM.setPage( section.dataset.link ); + + // on récupère la section déja selectionnée si elle existe + var last = document.querySelector('#MENU li.active'); + + if( last != null ) // si une section est déjà activée + last.className = ''; // on désactive la courante + + section.className = 'active'; // on active @section + + }else // sinon on affiche l'erreur + console.log("[selectSection_Error] - ("+section+")"); + + } + + /* activation au chargement en fonction de la page courante de pageManager.js */ + lastSection = document.querySelector('[data-link='+pageM.page+']'); + lastSection.className = 'active'; // on l'active + + /* Gestion des liens du menu */ + DOM.menu.addEventListener('click', function(e){ selectSection( e.target ); }, false); + + + /* [b] SOUS-PARTIES + ==============================================================*/ + /* GESTION DES SOUS-PARTIES (SOUS-CATÉGORIES) + * + * @param subSection l'élément à activer + * + * [1] selectionne l'élément, l'affichage de la page associée est géré en CSS3 + * [2] déselectionne l'élément précédemment selectioné + * + */ + function selectSubSection(subSection){ + + // si @subSection est un de type HGROUP [ET] + if( subSection instanceof Element && subSection.tagName == 'HGROUP' ){ + + if( subSection.className != 'active' ){ // si @subSection pas déjà active + + // on récupère la sous-partie selectionnée en cours + var last = document.querySelector('hgroup.active'); + + if( last != null ) // si un sous-partie est déjà selectionnée + last.className = ''; // on la désactive + + subSection.className = 'active'; // on active @subSection + + }else // sinon on affiche l'erreur + console.log("[selectSubSection_Error] - ("+subSection+")"); + + } + + } + + /* gestion du clic sur les sous-parties */ + DOM.container.addEventListener('click', function(e){ selectSubSection(e.target); }, false); + + + + + + + + +/* [3] GESTION DES FORMULAIRES +==============================================================*/ +/* INITIALISE UN FORMULAIRE POUR QU'IL INTERPRETE UN OBJET LORS DE SA SOUMISSIONS +* +* @param pForm le formulaire cible +* @param pHandler fonction exécutée lors de la soumission du formulaire +* +* [1] parcourt les élements du formulaire @pForm et active un évènement lors du "submit" +* [2] retourne l'objet à @pHandler lors du "submit" +* +* +* @example +* +*
    +* +* +* +* +* +* +*
    +* +* @explaination +* +* Lors du clic sur le bouton [VALIDER], la fonction @pHandler s'exécutera avec pour paramètre un objet +* OBJ{ id: nomFormulaire, nomDuChamp1: valeurDuChamp1, nomDuChamp2: valeurDuChamp2 } +* +*/ +function initForm(pForm, pHandler){ + + // vérification des arguments + var isForm = pForm instanceof Element && pForm.tagName == 'FORM'; + var isFunc = pHandler instanceof Function; + + // si les arguments sont corrects + if( pForm instanceof Element && pForm.tagName == 'FORM' ){ + + var submitButton = null; // contiendra le bouton d'envoi du formulaire + + for( var i = 0 ; i < pForm.children.length ; i++ ) + if( pForm.children[i].type == 'button' && pForm.children[i].name == 'submit' ){ + submitButton = pForm.children[i]; // on définit le bouton + break; // on sort du for + } + + + // on définit l'évènement de validation du formulaie + function submitEvent(){ + + var obj = {} // on créé l'objet qui va être envoyé + + for( var i = 0 ; i < pForm.children.length ; i++ ) // on parcourt les enfants + if( pForm.children[i].tagName == 'INPUT' && pForm.children[i].name != 'submit' ) // si c'est un champ et que c'est pas le bouton + obj[pForm.children[i].name] = pForm.children[i].value; // alors on enregistre le champ dans l'objet + + // on exécute la fonction @pHandler en lui envoyant les arguments + pHandler(obj); + + } + + // on définit l'évènement du clic sur le bouton + submitButton.addEventListener('click', function(e){ + submitEvent(e.target.parentNode); // on envoie le formulaire + }, false); + + // on définit l'évènement de l'appui sur la touche [ENTRER] + pForm.addEventListener('keydown', function(e){ + if(e.keyCode==13) submitEvent(e.target); // si c'est la bonne touche, on submit le formulaire + }, false); + + + + }else + console.log('[initForm_Error] - ('+pForm+', '+pHandler+')'); + + +} + + + + + + + +/* [4] GESTION DE LA MESSAGEBOX +==============================================================*/ +function messageBox(message, type){ + + /* on affecte le message */ + DOM.msgBox.innerHTML = message; + + /* on définit le style s'il est correct */ + if( ['success', 'info', 'warning', 'error'].indexOf(type) > -1 ) + DOM.msgBox.className = type; + else + DOM.msgBox.className = 'info'; + + + + if( msgBoxTimeout != null ) // si une autre message box est en cours, on arrête son timeout + clearTimeout(msgBoxTimeout); + + msgBoxTimeout = setTimeout( function(){ + DOM.msgBox.className = ''; + }, 2000); + +} \ No newline at end of file diff --git a/js/pageManager.js b/js/pageManager.js new file mode 100755 index 0000000..44ce627 --- /dev/null +++ b/js/pageManager.js @@ -0,0 +1,237 @@ +function pageManager(){}; + +var ptrPageManager; // pointeur global pour l'utilisation de fonctions de fonctions + +pageManager.prototype = { + depJS: null, // la dépendance javascript + depCSS: null, // la dépendance css + xhr: [], // tableau d'objets pour les requêtes ajax + page: null, // l'indice de la page courante dans pagelist + vars: [], // les variables suivant le nom de la page dans l'URL + path: '', // le chemin du dossier contenant les pages (.php) + pagelist: null, // la liste des pages pouvant être chargées + container: null, // élément DOM qui contiendra le contenu des pages à charger + /* ======================================================================= + Cette fonction effectue une requête Ajax (compatible à partir de IE5) + PARAMETRES: + - pLink le lien à charger + - pHandler une fonction qui s'éxécutera avec la réponse de la requête passée en paramètre (voir exemples dessous pour pHandler) + - pMethod type de méthode, vaut 'POST' ou 'GET' et vaut 'POST' par défaut ou s'il n'est pas renseigné + - pForm formulaire de type FormData() contenant les données à envoyer (uniquement en POST), si pForm vaut GET les données doivent être passées dans l'URL + ========================================================================== */ + ajax: function(pLink, pHandler, pMethod, pForm){ + // on efface les requêtes qui sont terminées et on push une nouvelle + for( var i = 0 ; i < this.xhr.length ; i++ ){ + if( this.xhr[i].readyState == 4 ) // si terminée + this.xhr = this.xhr.slice(0,i-1).concat(this.xhr.slice(i,this.xhr.length-1)); // suppression entrée + } + + this.xhr.push(true); + i = this.xhr.length-1; + + if(window.XMLHttpRequest) // IE7+, Firefox, Chrome, Opera, Safari + this.xhr[i] = new XMLHttpRequest(); + else // IE5, IE6 + this.xhr[i] = new ActiveXObject('Microsoft.XMLHttpRequest'); + + var ptrPageManager = this; + this.xhr[i].onreadystatechange = function(){ + if( ptrPageManager.xhr[i].readyState == 4 ) // si la requête est terminée + if( [0,200].indexOf(ptrPageManager.xhr[i].status) > -1 ) // si fichier existe et reçu + pHandler(ptrPageManager.xhr[i].responseText); + else // si code d'erreur retourne null + pHandler(); + } + + // gestion de la méthode + var method = ( typeof pMethod == 'string' && /^POST|GET$/i.test(pMethod) ) ? pMethod.toUpperCase() : 'POST'; + + // gestion du formulaire si la méthode est POST + var form = ( method == 'POST' && typeof pForm == 'object' && pForm instanceof FormData ) ? pForm : null; + + this.xhr[i].open( method, pLink, true); + this.xhr[i].send( form ); + }, + /***************************************************** [APPLICATION] Ajax() ******************************************************/ + // EXEMPLES DE FONCTIONS POUR pHandler // + // 1. var a = function(param){ alert(param); } // les deux notations 1 et 2 sont équivalents + // 2. function a(param){ alert(param); } // les deux notations 1 et 2 sont équivalents + + // ajax( 'index.php', a ); // utilisation d'une fonction définie + + // ajax( 'index.php', alert ); // utilisation d'une fonction prédéfinie + // ajax( 'index.php', alert, 'GET' ); // utilisation de méthode + + // var fd = new FormData(); // création d'un formulaire + // fd.append('var', 100); // ajout de la variable VAR qui vaut 100 + + // ajax( 'index.php', alert, null, fd ); // saut de paramètre avec null + envoi formulaire + // ajax( 'index.php?var=10', alert, 'GET' ); // envoi formulaire en GET (dans l'url) + // ajax( 'index.php?var=10', alert, 'POST', fd ); // envoi formulaire en GET (dans l'url) + en POST via le formulaire FD + + + /* ======================================================================= + Cette fonction effectue une décomposition de l'URL sur le shéma spécifié dessous + Renvoie pour http://www.exemple.com/dirA/dirB/#/NOMPAGE/VARPAGE + - null si la page n'est pas référencée dans le tableau PAGELIST + - null si le lien ne contient pas /#/NOMPAGE à la fin + - null si NOMPAGE ne contient pas uniquement : lettres, chiffres, underscore + - null si VARPAGE ne contient pas uniquement : lettres, chiffres, underscore + - un objet contenant {page: valeur, var: valeur} + ========================================================================== */ + explodeURL: function(url_data){ + url_data = (arguments.length >= 1) ? url_data : document.URL; + // si pageList est correct et que l'URL correspond à un schéma de page => continue [sinon] return null + if( this.pagelist != null && /^(?:.+)\/#\/([a-z0-9_]+)\/?(?:\/((?:[a-z0-9_]+\/)+)\/?)?$/i.test(url_data) ){ + // si la page récupérée dans l'url est dans la liste => renvoi de l'objet [sinon] null + var vars = RegExp.$2.split('/'); + while( vars[vars.length-1] == '' ) // on supprime les dernières entrées vides + vars.pop(); + + return ( this.pagelist.indexOf(RegExp.$1) > -1 ) ? {page: RegExp.$1, var: vars} : null; + }else + return null; + }, + /* ======================================================================= + Cette fonction ajoute des dépendances (un js et un css) situés dans le répertoire des pages. + pageDir/ + _JS/ + page1.js + page2.js + _CSS/ + page1.css + page2.css + ========================================================================== */ + loadDependencies: function(){ + // si depCSS est un élément du DOM c'est à dire qu'il contient le fichier de la page précédente et qu'il est enfant de , on le détruit + if( typeof this.depCSS == 'object' && this.depCSS instanceof Element && this.depCSS.parentNode == document.head ) + document.head.removeChild( this.depCSS ); + + // si depJS est un élément du DOM c'est à dire qu'il contient le fichier de la page précédente, on le détruit + if( typeof this.depJS == 'object' && this.depJS instanceof Element && this.depJS.parentNode == document.head ) + document.head.removeChild( this.depJS ); + + ptrPageManager = this; + // si le fichier css existe + this.ajax(this.path+'/'+'_CSS'+'/'+this.page+'.css', function(e){ + if( e != null ){ // on charge la dépendance CSS si le fichier existe + ptrPageManager.depCSS = document.createElement('link'); + ptrPageManager.depCSS.rel = 'stylesheet'; + ptrPageManager.depCSS.type = 'text/css'; + ptrPageManager.depCSS.href = ptrPageManager.path+'/'+'_CSS'+'/'+ptrPageManager.page+'.css'; + document.head.appendChild(ptrPageManager.depCSS); + }else + console.log('[loadDependencies_Error] - ('+ptrPageManager.path+'/'+'_CSS'+'/'+ptrPageManager.page+'.css'+')'); + }); + + // si le fichier js existe + this.ajax(this.path+'/'+'_JS'+'/'+this.page+'.js', function(e){ + if( e != null ){ // on charge la dépendance JS si le fichier existe + ptrPageManager.depJS = document.createElement('script'); + ptrPageManager.depJS.type = 'text/javascript'; + ptrPageManager.depJS.src = ptrPageManager.path+'/'+'_JS'+'/'+ptrPageManager.page+'.js'; + document.head.appendChild(ptrPageManager.depJS); + }else + console.log('[loadDependencies_Error] - ('+ptrPageManager.path+'/'+'_JS'+'/'+ptrPageManager.page+'.js'+')'); + }); + }, + + /* ======================================================================= + Cette fonction est celle qui gère les 2 autres et celle que l'utilisateur utilisera + PARAMETRES: + - pName le nom de la page à charger (lettres, chiffres, underscore) (*) + - pPath chemin (relatif ou absolu) du dossier contenant les pages de même nom de fichier que le nom (extension .php) + - pContainer l'élément du DOM qui contiendra la page chargée (**) + - pPageList> tableau contenant la liste des pages sous forme de chaînes de caractères (**) (***) + * Le chemin du dossier sans le '/' final si c'est le dossier actuel le chemin est une chaîne vide + Si le dossier est 'page' et que l'on cherche la page 'accUe1l', la requête sera vers 'page/accUe1l.php' + le nom de la page est sensible à la casse + ** 1. pPageList et pContainer doivent être mis en paramètres uniquement à la première utilisation + et la première utilisation doit se faire au chargement de la page car elle permetra + de mettre l'URL à jour et/ou charger la page de l'URL + *** la première page du tableau est la page par défaut (qui est chargée si l'URL ne contient + pas la page ou si la page de l'URL ne correspond à aucune page de la liste) + ========================================================================== */ + setPage: function(pName, pPath, pContainer, pPageList){ + + // liste de pages si c'est un tableau + var pageList = ( typeof pPageList == 'object' && pPageList instanceof Array ) ? pPageList : null; // si this.pagelist n'est pas overwrite il vaut null + + if( pageList != null ){ // si c'est un tableau + for( var i = 0 ; i < pageList.length ; i++ ){ // on parcourt tout les éléments pour vérifier que chaque élément ne contient que : lettres, chiffres, underscore [non]> pageList = null + pageList = ( typeof pageList[i] == 'string' && /^[a-z0-9_]+$/i.test(pageList[i]) ) ? pageList : null; + if( pageList == null ) break; // si le tableau est null stoppe la boucle + } + } + /* on attribue la variable temporaire pageList à l'attribut de l'objet si la variable pageList temporaire n'est pas nulle */ + this.pagelist = ( pageList != null ) ? pageList : this.pagelist; + // affecte à l'attribut page la page par défaut (premier élément de pagelist) + this.page = this.pagelist[0]; + // affecte pPath à l'attribut path s'il est renseigné + this.path = ( typeof pPath == 'string' ) ? pPath : this.path; + /* on attribue le paramètre pContainer à l'attribut si il est spécifié */ + this.container = ( typeof pContainer == 'object' && pContainer instanceof Element ) ? pContainer : this.container; + + // si this.pagelist && this.container ne sont pas null && + if( this.pagelist != null && this.container != null ){ + // si le pName est renseigné et qu'il est dans pagelist + if( typeof pName == 'string' && this.pagelist.indexOf(pName) > -1 ){ + // affecte pName à l'attribut page + this.page = pName; + + // charge le contenu de la page dans le container + var ptrPageManager = this; + + // formulaire POST + var fd = new FormData(); + for( var i = 0 ; i < this.vars.length ; i++ ) + fd.append(this.vars[i], null); + + this.ajax(this.path+'/'+this.page+'.php', function(e){ + ptrPageManager.container.innerHTML = e; + ptrPageManager.loadDependencies(); + }, 'POST', fd); + + // change l'URL en conséquences(stateObj, titre, url) + if( this.vars.length > 0 ) // si il y a des variables + window.history.pushState(null, this.page, '#/'+this.page+'/'+this.vars.join('/')+'/'); + else // s'il n'y en a pas + window.history.pushState(null, this.page, '#/'+this.page+'/'); + + }else{ // si la page n'est pas spécifiée ou qu'elle n'est pas dans la liste des pages + var urlGet = this.explodeURL(); + + // si on a récupéré le numéro de la page dans l'URL et qu'elle fait partie de la liste des pages + if( urlGet != null ){ + this.page = urlGet.page; + // charge le contenu de la page dans le container + var ptrThis = this; + + // formulaire POST + var fd = new FormData(); + this.vars.length = 0; + + for( var i = 0 ; i < urlGet.var.length ; i++ ){ // replacing object variables with explodeURL variables + this.vars[i] = urlGet.var[i]; + fd.append(this.vars[i], null); + } + + this.ajax(this.path+'/'+this.page+'.php', function(e){ + ptrThis.container.innerHTML = e; + ptrThis.loadDependencies(); + }, 'POST', fd); + + // change l'URL en conséquences(stateObj, titre, url) + if( this.vars.length > 0 ) // si il y a des variables + window.history.pushState(null, this.page, '#/'+this.page+'/'+this.vars.join('/')+'/'); + else // s'il n'y en a pas + window.history.pushState(null, this.page, '#/'+this.page+'/'); + + }else // si l'url ne contient rien, on charge la page par défaut + this.setPage(this.pagelist[0]); + } + }else + console.log('pagelist et container manquant'); + } + +} \ No newline at end of file diff --git a/js/shortcut.js b/js/shortcut.js new file mode 100755 index 0000000..b032b03 --- /dev/null +++ b/js/shortcut.js @@ -0,0 +1,145 @@ +/* Retourne le keyCode correspondant à la chaîne +* +* @param keyStore enchaînement de touches sous forme de string +* @param handler function qui s'éxécute lors du raccourci +* +* return keyCode le code de la touche correspondante +*/ +function strToKeyCode(str){ + // on enregistre le keyCode du premier caractère + var keyCode = str.toUpperCase().charCodeAt(0); + + // s'il s'agit d'un caractère uniquement (entre "a" et "z") + if( str.length == 1 && keyCode >= 65 && keyCode <= 90 ) + return keyCode; // on retourne le keyCode associé + else + switch( str ){ + case 'ctrl': return 17; break; + case 'maj': return 16; break; + case 'alt': return 18; break; + case 'tab': return 9; break; + } + + return null; +} + + + + +var shortcutList = []; // contient les combinaisons de touches +var shortcutStep = []; // contient l'avancée d'un raccourcis + +/* Gestion des raccourcis claviers +* +* @param keyStore enchaînement de touches sous forme de string +* @param handler function qui s'éxécute lors du raccourci +* +*/ +function Shortcut(keyStore, handler){ + + var splittedString = keyStore.toLowerCase().split('+'), // découpe la chaîne (en minuscule) par "+" + splittedKeyCode = new Array(); // contiendra les keyCode de chaque touche + + + // pour chaque touche, on récupère le keyCode + for( var i = 0 ; i < splittedString.length ; i++ ) + splittedKeyCode[i] = strToKeyCode( splittedString[i] ); // on enregistre le keyCode correspondant + + + // on ajout à la liste globale + eventIndex = shortcutList.length; + shortcutList.push( splittedKeyCode ); + + // on initialise l'avancement + shortcutStep[eventIndex] = 0; + + + + // creation de la fonction d'évènement + shortcutList[eventIndex].push( function(k, f, h){ /* k ; f ; h */ + // on cherche l'avancée + var step = shortcutStep[f]; + + // on regarde si la touche est bonne + if( shortcutList[f][step] == k ){ // si c'est la touche suivante + + if( step >= shortcutList[f].length-2 ){ // si c'était la dernière touche + + // on initialise le tableau + for( var i = 0 ; i < shortcutStep[f].length ; i++ ) + shortcutStep[f][i] = 0; + + h(); // EXECUTION DE : handler(); + + }else // sinon on incrémente l'avancée + shortcutStep[f]++; + + }else // si c'est pas la bonne touche, on réinitialise le tableau + shortcutStep[f] = 0; + + }); + + console.log( shortcutList ); + + + // création de l'évènement + window.addEventListener( + 'keydown', + function(e){ e.preventDefault(); shortcutList[eventIndex][shortcutList[eventIndex].length-1](e.keyCode, eventIndex, handler); }, + false + ); + +} + +/* quand on lâche une touche, tout les raccourcis s'effacent */ +window.addEventListener('keyup', function(){ + for( var i = 0 ; i < shortcutStep.length ; i++ ) + shortcutStep[i] = 0; +}, false); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/*** UTILISATION ***/ + +// Shortcut( +// 'ctrl+s', +// function(){ alert('sauvegardé'); } +// ); \ No newline at end of file diff --git a/manager/database.php b/manager/database.php new file mode 100755 index 0000000..5b4c2cb --- /dev/null +++ b/manager/database.php @@ -0,0 +1,18 @@ +connection = new PDO("mysql:host=$host;dbname=$dbname", $username, $password); + } +} + +?> \ No newline at end of file diff --git a/manager/security.php b/manager/security.php new file mode 100755 index 0000000..6781c74 --- /dev/null +++ b/manager/security.php @@ -0,0 +1,76 @@ + 0; + $permissionsDefinedProperly = isset($_SESSION['permissions']) && !empty($_SESSION['permissions']) && gettype($_SESSION['permissions']) == 'string' && strlen($_SESSION['permissions']) > 0; + + // si les variables sessions ne sont pas toutes les 2 correctes + if( !($usernameDefinedProperly && $permissionsDefinedProperly) ){ + $_SESSION['username'] = null; // on les initialise à NULL + $_SESSION['permissions'] = null; + } + } + + + + + + + +?> \ No newline at end of file diff --git a/manager/user.php b/manager/user.php new file mode 100755 index 0000000..0d37fe9 --- /dev/null +++ b/manager/user.php @@ -0,0 +1,135 @@ +level_1 ){ + + /****************************/ + /* authentification (login) */ + /****************************/ + case 'authentification': + $areSetParam = isset($request->username) && isset($request->password); // les arguments existent + $typeOkParam = $areSetParam && is_string($request->username) && is_string($request->password); // ils sont tous 2 des string + $nEmptyParam = $typeOkParam && strlen($request->username) > 0 && strlen($request->password) > 0; // d'au moins 1 caractère + + if( $areSetParam && $typeOkParam && $nEmptyParam ) + $answer->request = user_authentification($request->username, $request->password); + else{ + if ( !$areSetParam ) $answer->request= 'missing_param'; + elseif( !$typeOkParam ) $answer->request = 'wrong_type'; + else $answer->request = 'empty_param'; + } + break; + + + + /***********/ + /* DEFAULT */ + /***********/ + default: + $answer->request = 'unknown_level_1'; + break; + } + + } + + + + + + + + + + + + + + + + + + + /* [2] AUTHENTIFICATION + ============================================================*/ + + /* [a] userlist */ + function user_getUserList(){ + $userlistFile = file_get_contents("src/userlist.json"); + return json_decode( $userlistFile ); + } + + + /* [b] CONNECTION + ========================================================*/ + /* GESTION DE L'AUTHENTIFICATION D'UN UTILISATEUR + * + * @param username Identifiant de l'utilisateur + * @param password Mot de passe de l'utilisateur + * + * si @username est référencé et que le mot de passe associé vaut @password + * alors @return TRUE sinon FALSE + * + mise ajout à @answer + * + * Les variables sessions suivantes sont définies : + * - $_SESSION['permissions'] + * - $_SESSION['userid'] + * - $_SESSION['username'] + * + * @return Boolean true si l'utilisateur est ok + */ + function user_authentification($username, $password){ + + // [1] On récupère la liste d'utilisateurs (/src/userlist.json) + $userList = user_getUserList(); + + // [2] On check l'existence de l'utilisateur + if( isset($userList->{$username}) ){ + + // [3] On check le mot de passe + if( $userList->{$username}->password == $password ){ + // on définit les variables session + $_SESSION['username'] = $username; + $_SESSION['permissions'] = $userList->{$username}->permissions; + return 'success'; + }else + return 'wrong_password'; + + }else + return 'unknown_user'; + } + + +?> \ No newline at end of file diff --git a/page/_JS/auth.js b/page/_JS/auth.js new file mode 100755 index 0000000..7e95c72 --- /dev/null +++ b/page/_JS/auth.js @@ -0,0 +1,80 @@ + + /*********************************************************** + * * + * SCRIPT LOCAL DE LA PAGE D'AUTHENTIFICATION * + * * + ************************************************************ + * * + * [0] Variables * + * [1] Gestion des formulaires * + * [a] Gestion des réponses * + * [b] Initialisation des formulaires * + * * + * * + * * + * * + * * + * * + * * + * * + * * + ***********************************************************/ + + /* [0] Variables + ==============================================================*/ + var subSections = document.querySelectorAll('hgroup'); + + + /* [1] Gestion des formulaires + ==============================================================*/ + + + /* [a] Gestion des réponses + ==============================================================*/ + /* GESTION DU COMPORTEMENT EN FONCTION DE LA REPONSE POUR LE [LOGIN] + * + * @param response + * + * Gestion de toutes les réponse possibles avec une "messageBox" ou de redirection + * + */ + function manageAuthentificationResponse(response){ + switch( response.request ){ + + case 'success': + messageBox('Vous êtes maintenant connecté', 'success'); // on affiche le message + selectSection( document.querySelector('#MENU li:first-child') ); // on redirige vers la page d'accueil + break; + + // case 'missing_param': messageBox('Un des champs requis n\'est pas présent', 'warning'); break; + // case 'empty_param': messageBox('Un des champs requis est vide', 'warning'); break; + // case 'unknown_user': messageBox('Nom d\'utilisateur inconnu', 'error'); break; + // case 'wrong_password': messageBox('Mot de passe incorrect', 'error'); break; + + + case 'empty_param': case 'missing_param': case 'unknown_user': case 'wrong_password': + messageBox('Identifiants incorrects', 'error'); + break; + + default: + messageBox('Erreur interne', 'error'); + break; + + } + } + + + + + /* [b] Initialisation des formulaires + ==============================================================*/ + initForm( // initialisation du formulaire de connection + document.querySelector('#user'), // formulaire (élément DOM) + function(request){ // handler + // ajout d'informations à la requête + request.level_0 = 'user'; + request.level_1 = 'authentification'; + + API.send(request, function(response){ manageAuthentificationResponse(response); }); + } + ); diff --git a/page/_JS/groups.js b/page/_JS/groups.js new file mode 100755 index 0000000..65848f2 --- /dev/null +++ b/page/_JS/groups.js @@ -0,0 +1,43 @@ +var subSections = document.querySelectorAll('hgroup'); + + + + +// si aucune sous-partie n'est active, on active la première +if( document.querySelector('#CONTAINER hgroup.active') == null ) + selectSubSection( document.querySelector('#CONTAINER hgroup') ); + + + + + + + + + + + + + + + + + +/*************************************************/ +/****************** EXEMPLE API ******************/ +/*************************************************/ + +/* objet envoyé à API.php */ +var request = { + level_0: 'groups', + level_1: 'visualiser', + group : 'ego' +}; + +// console.log( request ); + +// envoi de la requête +// @ on envoie l'objet +// @ quand réception: affichage de l'objet reçu +// +API.send(request, function(){} ); diff --git a/page/auth.php b/page/auth.php new file mode 100755 index 0000000..d0847f8 --- /dev/null +++ b/page/auth.php @@ -0,0 +1,42 @@ + + +
    Connection
    +
    + +
    + + + +
    + +
    + + + + + + +
    Mon Profil
    +
    + + username =
    + droits = + +
    + + + \ No newline at end of file diff --git a/page/career.php b/page/career.php new file mode 100755 index 0000000..12bea97 --- /dev/null +++ b/page/career.php @@ -0,0 +1 @@ +career.php \ No newline at end of file diff --git a/page/groups.php b/page/groups.php new file mode 100755 index 0000000..6420150 --- /dev/null +++ b/page/groups.php @@ -0,0 +1,145 @@ + +
    Mon Groupe
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NomPrénomBlablabla
    001002003
    001002003
    001002003
    001002003
    001002003
    001002003
    001002003
    001002003
    001002003
    001002003
    + +
    + + + + +
    Mes Groupe
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nom du groupeNombre d'élèvesNombre de modules
    A302
    B283
    D321
    F212
    + +
    + + + + +
    Tout les groupes
    +
    + Tout les groupes
    + bla
    + bla
    +
    + + + + +
    Mon Groupe 2
    +
    + Mon Groupe 2
    + bla
    + bla
    +
    \ No newline at end of file diff --git a/page/home.php b/page/home.php new file mode 100755 index 0000000..7abdfd5 --- /dev/null +++ b/page/home.php @@ -0,0 +1,42 @@ + +
    Présentation
    +
    + +Bienvenue sur la plateforme de gestion des élèves.

    +Seuls les membres du département y possède un accès, c'est à dire:
    +
      +
    • - Elèves
    • +
    • - Enseignants
    • +
    • - Personnel administratif
    • +
    + +Si vous faite partie de cette liste et que vous n'avez pas de compte, veuillez envoyer une requête au chef du département: Monsieur. Max Chevalier. + + +
    + + + + +
    Qui peut avoir accès à la plateforme
    +
    +blabla +
    \ No newline at end of file diff --git a/page/marks.php b/page/marks.php new file mode 100755 index 0000000..58569ea --- /dev/null +++ b/page/marks.php @@ -0,0 +1 @@ +Notes ici !!! \ No newline at end of file diff --git a/page/modules.php b/page/modules.php new file mode 100755 index 0000000..de1673c --- /dev/null +++ b/page/modules.php @@ -0,0 +1,4 @@ + + + +modules.php \ No newline at end of file diff --git a/page/semestre.php b/page/semestre.php new file mode 100755 index 0000000..83d0be7 --- /dev/null +++ b/page/semestre.php @@ -0,0 +1 @@ +semestre.php \ No newline at end of file diff --git a/page/settings.php b/page/settings.php new file mode 100755 index 0000000..3dd1e75 --- /dev/null +++ b/page/settings.php @@ -0,0 +1 @@ +settings.php \ No newline at end of file diff --git a/page/ue.php b/page/ue.php new file mode 100755 index 0000000..49446a4 --- /dev/null +++ b/page/ue.php @@ -0,0 +1 @@ +ue.php \ No newline at end of file diff --git a/src/input_icon/default.svg b/src/input_icon/default.svg new file mode 100755 index 0000000..405ca99 --- /dev/null +++ b/src/input_icon/default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/input_icon/default_grayscale.svg b/src/input_icon/default_grayscale.svg new file mode 100755 index 0000000..ed397a3 --- /dev/null +++ b/src/input_icon/default_grayscale.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/input_icon/password.svg b/src/input_icon/password.svg new file mode 100755 index 0000000..6f078a4 --- /dev/null +++ b/src/input_icon/password.svg @@ -0,0 +1,49 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/input_icon/password_grayscale.svg b/src/input_icon/password_grayscale.svg new file mode 100755 index 0000000..8f2447c --- /dev/null +++ b/src/input_icon/password_grayscale.svg @@ -0,0 +1,51 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/input_icon/user.svg b/src/input_icon/user.svg new file mode 100755 index 0000000..4a35e05 --- /dev/null +++ b/src/input_icon/user.svg @@ -0,0 +1,59 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/input_icon/user_grayscale.svg b/src/input_icon/user_grayscale.svg new file mode 100755 index 0000000..6a1d45f --- /dev/null +++ b/src/input_icon/user_grayscale.svg @@ -0,0 +1,61 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/auth.svg b/src/menu_icon/auth.svg new file mode 100755 index 0000000..b87b166 --- /dev/null +++ b/src/menu_icon/auth.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/auth_grayscale.svg b/src/menu_icon/auth_grayscale.svg new file mode 100755 index 0000000..9f3378c --- /dev/null +++ b/src/menu_icon/auth_grayscale.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/groups.svg b/src/menu_icon/groups.svg new file mode 100755 index 0000000..bf6f121 --- /dev/null +++ b/src/menu_icon/groups.svg @@ -0,0 +1,51 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/groups_grayscale.svg b/src/menu_icon/groups_grayscale.svg new file mode 100755 index 0000000..2eb2cd1 --- /dev/null +++ b/src/menu_icon/groups_grayscale.svg @@ -0,0 +1,51 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/home.svg b/src/menu_icon/home.svg new file mode 100755 index 0000000..5d68207 --- /dev/null +++ b/src/menu_icon/home.svg @@ -0,0 +1,151 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/menu_icon/home_grayscale.svg b/src/menu_icon/home_grayscale.svg new file mode 100755 index 0000000..6a9bc63 --- /dev/null +++ b/src/menu_icon/home_grayscale.svg @@ -0,0 +1,151 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/menu_icon/marks.svg b/src/menu_icon/marks.svg new file mode 100755 index 0000000..894e9ee --- /dev/null +++ b/src/menu_icon/marks.svg @@ -0,0 +1,57 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/marks_grayscale.svg b/src/menu_icon/marks_grayscale.svg new file mode 100755 index 0000000..0aafb63 --- /dev/null +++ b/src/menu_icon/marks_grayscale.svg @@ -0,0 +1,58 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/modules.svg b/src/menu_icon/modules.svg new file mode 100755 index 0000000..0882a93 --- /dev/null +++ b/src/menu_icon/modules.svg @@ -0,0 +1,71 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/menu_icon/modules_grayscale.svg b/src/menu_icon/modules_grayscale.svg new file mode 100755 index 0000000..6b2b773 --- /dev/null +++ b/src/menu_icon/modules_grayscale.svg @@ -0,0 +1,71 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/menu_icon/settings.svg b/src/menu_icon/settings.svg new file mode 100755 index 0000000..64f8cf1 --- /dev/null +++ b/src/menu_icon/settings.svg @@ -0,0 +1,49 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/settings_grayscale.svg b/src/menu_icon/settings_grayscale.svg new file mode 100755 index 0000000..6c7c89d --- /dev/null +++ b/src/menu_icon/settings_grayscale.svg @@ -0,0 +1,49 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/ue.svg b/src/menu_icon/ue.svg new file mode 100755 index 0000000..578cd4d --- /dev/null +++ b/src/menu_icon/ue.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/menu_icon/ue_grayscale.svg b/src/menu_icon/ue_grayscale.svg new file mode 100755 index 0000000..4c14e1e --- /dev/null +++ b/src/menu_icon/ue_grayscale.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/userlist.json b/src/userlist.json new file mode 100755 index 0000000..5b1059e --- /dev/null +++ b/src/userlist.json @@ -0,0 +1,32 @@ +{ + "eleve1": { + "permissions": "student", + "password" : "eleve1password" + }, + + "eleve2": { + "permissions": "student", + "password" : "eleve2password" + }, + + "prof1": { + "permissions": "teacher", + "password" : "prof1password" + }, + + "prof2": { + "permissions": "master", + "password" : "prof2password" + }, + + "admin1": { + "permissions": "admin", + "password" : "admin1password" + }, + + "admin2": { + "permissions": "admin", + "password" : "admin2password" + } + +} \ No newline at end of file diff --git a/xdoc/cdcf_droits b/xdoc/cdcf_droits new file mode 100755 index 0000000..7cab8f2 --- /dev/null +++ b/xdoc/cdcf_droits @@ -0,0 +1,35 @@ +ETUDIANT + Consulter son dossier (suivi des notes par semestre, UE, module) + Consulter ses notes + Consulter la composition de son groupe + Consulter la composition des autres groupes du même semestre + +ENSEIGNANT (sans droits spécifiques) + Consulter la composition des groupes du semestre actuel + +ENSEIGNANT + correcteur du contrôle "X" pour les groupes A, B, et F + Saisie des notes pour le contrôle X des groupes A, B, et F + Consultation et correction des notes du contrôle X des groupes A, B, et F + +ENSEIGNANT + droit d'accès au dossiers des étudiants du groupe D + Consulter le dossier des étudiants du groupe D + +ENSEIGNANT + droit de lecture des données étudiants + Consulter et importer au format Excel + la liste des élèves par groupe (groupes selectionnés) + les notes d'un contrôle (groupes selectionnés) + la liste des notes d'un module (groupes selectionnés) + la liste des notes d'un UE (groupes selectionnés) + la liste des notes d'un semestre (groupes selectionnés) + +ENSEIGNANT + droit de modification des données étudiant + Idem que précédemment + modification + Modification de la composition des groupes + Importation au format Excel de la liste des étudiants + +NOTE: Ces droits sont cummulables et selectionnés par l'administrateur + + +ADMINISTRATEUR: + Tous les droits vus précédemment + Possibilité d'octroyer, retirer des droits aux enseignants \ No newline at end of file diff --git a/xdoc/droits.svg b/xdoc/droits.svg new file mode 100755 index 0000000..6aec575 --- /dev/null +++ b/xdoc/droits.svg @@ -0,0 +1,123 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + étudiant + + + + enseignant + + + + administrateur + + + diff --git a/xdoc/login-page.png b/xdoc/login-page.png new file mode 100755 index 0000000..1c76b2e Binary files /dev/null and b/xdoc/login-page.png differ diff --git a/xdoc/rdv1_tutrice b/xdoc/rdv1_tutrice new file mode 100755 index 0000000..495540c --- /dev/null +++ b/xdoc/rdv1_tutrice @@ -0,0 +1 @@ +Dater les documents \ No newline at end of file diff --git a/xdoc/sid.rules b/xdoc/sid.rules new file mode 100755 index 0000000..46e7aaf --- /dev/null +++ b/xdoc/sid.rules @@ -0,0 +1,258 @@ +Organisation GIT +---------------- + + master o--------------o-------------------o-------------------o----> + | | | | + dev o----o----o----o----o----o----o----o----o----o----o----o----o----o----o + + perso ..................... + + [DEV] active tout le temps + MERGE des branches perso toutes les semaines (au moins) + MERGE de la branche DEV vers MASTER à chaque réunion des branches perso + + + + + + + +Organisation TRELLO +------------------- + [ A faire ] - tâches qu'il faut réaliser (1 seul language, un seul fichier) + [ En cours ] - Personne attribuée + [ A vérifier ] - Vérifier par qqn d'extérieur + [ A confirmer] - confirmation par client + W3C + [ Fini ] - ... + + + + + + + +Architecture Fichiers +--------------------- +├── index.php +├── API.js +├── API.php +├── css +│   ├── container.css +│   ├── footer.css +│   ├── header.css +│   ├── layout.css +│   ├── menu.css +│   ├── page1.css +│   ├── page2.css +│   └── pagen.css +├── js +├── manager +│   ├── controles.php +│   ├── DATABASE.php +│   ├── etudiant.php +│   ├── excel.php +│   ├── groups.php +│   ├── history.php +│   ├── MCC.php +│   └── users.php +└── src + + + + + +Commentaires d'entête des fonctions +----------------------------------- +/* NOM : Résumé +* +* @param nomParam1 Le nombre de bits.. +* @param nomParam2 Description param2 +* @param nomParam3 [OBLIGATOIRE] +* +* Explication plus précise mais en prenant en compte les params et le return +* @return = @nomParam1 concaté avec la chaîne @nomParam2 +* +* @return nomVar[] +* +*/ + + + +Vérification d'intégrité des paramètres +--------------------------------------- +1) Créer une fonction booléenne qui vérifie le type d'un paramètre +2) Créer un booléen de vérification pour chaque paramèter utilisant "1)" + +Types pris en compte: + number + int + double + float + strings + char + boolean + [] + int + .. + + +@FUNCTION verifType(variable:void, type:string) + +exemples de @type + 'int' - si entier + 'bool' - si booléen + 'int[]' - si tableau d'entier + 'string[10]' - si tableau de string de taille 10 + 'int[][10]' - si matrice de string de taille n*10 + + +function(p1, p2, p3){ + + verifType( + func_get_args(), + [ 'string', 'int', 'int[10]' ], + [ null, null, null ] + ); + + ........ + +} + + + + + + + +Liste des pages +--------------- + + +I. GROUPES + [eleve] Mon groupe + [tous] Tout les groupes + [admin] Modifier les groupes + + ajouter + + supprimer + [admin] Répartition d'élèves + + ajouter (drag&drop) + + retirer (drag&drop) + + déplacer (drag&drop) + +II. SEMESTRE/UE + [eleve ] Mon parcourt + [prof autorisé] Mes élèves + [admin ] Les élèves + +III. MODULE + [eleve ] Mes modules + + par semestre + + par ue + [prof autorisé] Mes modules + + modifier contenu + . créer/modifier section + . upload document + . rédiger paragraphe + [admin ] Les modules + + ajouter + + supprimer + + modifier + . titre + . section (ajouter/supprimer/modifier) + +IV. CONTRÔLE + [eleve ] Mes contrôles + + par semestre + + par ue + + par module + [prof autorisé] Mes contrôles + + saisir notes (par groupe) + + modifier notes (par groupe) + [admin ] Contrôles + + consulter + . par semestre + . par ue + . par module + + modifier + + +V. PARAMÈTRES + ... + + + +Groupes + Mon groupe + visualiser + Tous + visualiser + Administration + modifier la liste d'élèves (drag & drop) (par ordre alpha) + + +Parametres + Profil + visualiser + modifier + password + mail + description + + +VISUALISER LES NOTES CLASSÉES PAR MODULES +{ + 'level_0': 'visualiser', + 'level_1': 'notes', + 'affichage': 'module' +} + +VISUALISER TOUT LES GROUPES +{ + 'level_O': 'visualiser', + 'level_1': 'groupe', + 'affichage': 'tous' +} + +VISUALISER MON GROUPE +{ + 'level_O': 'visualiser', + 'level_1': 'groupe', + 'affichage': 'ego' +} + +MODIFIER UN GROUPE +{ + 'level_O': 'administrer', + 'level_1': 'groupe', + 'groupe': 'A', + 'action': 'supprimer', + 'membres': [123, 567] +} + +SAISIR LES NOTES D'UN PARTIEL +{ + 'level_O': 'saisir', + 'level_1': 'notes', + 'module': 'M3102', + 'groupe': 'A' +} + + + + +Chevalier RDV (2) + + Eleve peut consulter notes (semestre uniquement) + + pas de moyenne (règlement intérieur => uniquement sur relevé de notes) + + + Rôles cummulatifs (admin choice) + + Profs correcteurs n'accèdent + + Historique des notes (1 courant + 1 antécédent uniquement) + + PROF + [x] Visualiser les notes (choix des groupes/modules) + [x] Saisie des notes (choix des groupes/modules) + [x] visualiser parcourt étu (groupes/modules) diff --git a/xdoc/svg/API.png b/xdoc/svg/API.png new file mode 100755 index 0000000..ab587f2 Binary files /dev/null and b/xdoc/svg/API.png differ diff --git a/xdoc/svg/API.svg b/xdoc/svg/API.svg new file mode 100755 index 0000000..ef65224 --- /dev/null +++ b/xdoc/svg/API.svg @@ -0,0 +1,437 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + API.js + + + + JSON <String> + + + + JSON <String> + + + + + PARSE + + + + UNPARSE + + + + + JSON <Object> + + + + ROUTAGE + + + + + + + MANAGERS:TRAITEMENT + + + + + + + + + + + + + + + JSON <Object> + + + + JSON <Object> + + + API.php physique + + API.php réel + + diff --git a/xdoc/svg/architecture.png b/xdoc/svg/architecture.png new file mode 100755 index 0000000..c5fce10 Binary files /dev/null and b/xdoc/svg/architecture.png differ diff --git a/xdoc/svg/architecture.svg b/xdoc/svg/architecture.svg new file mode 100755 index 0000000..408d21a --- /dev/null +++ b/xdoc/svg/architecture.svg @@ -0,0 +1,341 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + index.php + + + + API.js + + + + API.php + + + + manager/*.php + + + + + + JSON <String> + JSON <String> + + + + + + js + css + + + + + + + + + + + DATABASE.php + + + + + + diff --git a/xdoc/test.php b/xdoc/test.php new file mode 100755 index 0000000..7d08495 --- /dev/null +++ b/xdoc/test.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/xdoc/verifType.php b/xdoc/verifType.php new file mode 100755 index 0000000..ce5d472 --- /dev/null +++ b/xdoc/verifType.php @@ -0,0 +1,34 @@ + Les variables respectives des paramètres +* @param typeArray< String[] > Les types respectifs des paramètres +* @param defaultArray< *[] > Les valeurs par défaut (respectives) +* +* Vérifie si le type @varArray[n] correspond au type spécifié par le chaîne @typeArray[n] +* si oui, la variable est inchangée +* si non, attribue la valeur @defaultArray[n] +* +*/ +function verifType($valueVar, $typeVar, $defaultVar){ + return ( gettype($valueVar) == $typeVar ) ? $valueVar : $defaultVar; +} + +// implémenter un format pour les types complexes !!! :P + + + + +function test1($arg1, $arg2, $arg3){ + $arg1 = verifType($arg1, 'integer', 0); + $arg2 = verifType($arg2, 'string', 'void'); + $arg3 = verifType($arg3, 'boolean', true); + + echo $arg1.' - '.$arg2.' - '.$arg3; +} + +// test1( Array(), Array(), Array() ); + + + +?> \ No newline at end of file