diff options
| -rw-r--r-- | public/app/controllers/Office.php | 77 | ||||
| -rw-r--r-- | public/app/extends/SendMail_service.php | 31 | ||||
| -rw-r--r-- | public/app/routes/user.php | 9 | ||||
| -rw-r--r-- | public/app/views/components/theme.php | 14 | ||||
| -rw-r--r-- | public/app/views/js/select2-supplementary.php | 19 | ||||
| -rw-r--r-- | public/app/views/templates/invite.php | 61 | ||||
| -rw-r--r-- | public/assets/css/class.css | 6 | ||||
| -rw-r--r-- | public/assets/css/themes/summer-01.css | 2 |
8 files changed, 154 insertions, 65 deletions
diff --git a/public/app/controllers/Office.php b/public/app/controllers/Office.php index be8919f..79f76d8 100644 --- a/public/app/controllers/Office.php +++ b/public/app/controllers/Office.php @@ -7,6 +7,7 @@ use Render; use app\controllers\Auth; use app\extends\App_manager; use app\models\Content_model; +use app\extends\SendMail_service; use app\extends\Cache_service; /** Office class @@ -333,6 +334,82 @@ class Office { } + ## SEND INVITATION + ## ------------------------------------------------------------------------- + + public static function send_invitation() + { + if (Auth::in_admin_group()) { + + $now = time(); // keep `now` and `expiration` timestamps + $expiration = $now + ( 3600 * 72 ); + + // prepare the prepare statement + $handler = []; + $binds = [ ':now' => $now ]; // sure value to bind + + foreach(Registry::get('REQUEST')->POST['ids'] as $key => $id) { + $handler[] = ':id'. $key; + $binds[':id'. $key] = $id; + } + + $all_handlers = implode(', ', $handler); + + $recipients = Registry::use('database')->runQuery( + "SELECT * FROM user + WHERE id IN ( $all_handlers ) AND ( + otp_expiration < :now OR otp_expiration IS NULL + )", + $binds + ); + + $sent = []; + + foreach($recipients as $key => $rec) { + $invitation = md5( + $rec['first_name'] + . $rec['last_name'] + . $rec['email'] + . rand(0, 999999) + ); + + /* + $gone = SendMail_service::send_invitation([ + 'email' => $rec['email'], + 'name' => $rec['last_name'] .' '. $rec['fisrt_name'], + 'code' => $invitation + ]) + + if ($gone) { + // update user record with invitation + Registry::use('database')->runQuery( + "UPDATE user SET invitatopm = :inv WHERE id = :id", + [ ':inv' => $invitation, ':id' => $rec['id'] ] + ); + + $sent[] = $rec['first_name'] + ." ". $rec['last_name'] + ." (". $rec['id'] .")" + .": ". $invitation; + } + */ + + $sent[] = $rec['first_name'] + ." ". $rec['last_name'] + ." (". $rec['id'] .")" + .": ". $invitation; + } + + return Render::json([ + 'success' => true, + 'sent' => implode(",\n\n", $sent), + ]); + + } + } + + + public static function petition_copy($sign) { if (Auth::in_admin_group()) { diff --git a/public/app/extends/SendMail_service.php b/public/app/extends/SendMail_service.php index c717e61..64366e0 100644 --- a/public/app/extends/SendMail_service.php +++ b/public/app/extends/SendMail_service.php @@ -32,26 +32,28 @@ class SendMail_service * + https://stackoverflow.com/questions/2391171/how-to-get-output-from-local-script-in-php * + https://stackoverflow.com/questions/171318/how-do-i-capture-php-output-into-a-variable */ - public static function send_activation_code($activator) + public static function send_invitation($memo) { - $activation_url = SITE_URL ."/account/activate?ticket=". $activator['code']; + $invitation = SITE_URL ."/invitation/". $memo['code']; $envelope = [ - 'email' => $activator['email'], - 'name' => $activator['name'], - 'subject' => 'Εγγραφή στο Classroom', + 'email' => $memo['email'], + 'name' => $memo['name'], + 'subject' => 'Πρόσκληση από το 1ο Γυμνάσιο Ραφήνας', 'body' => "Χαίρετε,<br> - το παρόν αυτοποιημένο email σάς έχει σταλεί - γιατί έχει γίνει αίτημα εγγραφής σας στο Classroom.<br> + Στο παρόν email θα βρείτε πληροφορίες για να + ενεργοποιήσετε την πρόσβασή σας στην Πλατφόρμα + ηλεκτρονικών αιτήσεων και δημιουργίας διαδικαστικών + εγγράφων του 1ου Γυμνάσιου Ραφήνας.<br> <br> - Όνομα επαφής: <b>". $activator['name'] ."</b><br> - Email : <b>". $activator['email'] ."</b><br> + Όνομα επαφής: <b>". $memo['name'] ."</b><br> + Email : <b>". $memo['email'] ."</b><br> <br> Για να ενεργοποιήσετε την πρόσβασή σας στο site - θα πρέπει ακολουθήσετε τον παρακάτω σύνδεσμο: - <a href=\"". $activation_url ."\">". $activation_url ."</a>. + θα πρέπει να ακολουθήσετε τον παρακάτω σύνδεσμο: + <a href=\"". $invitation ."\">". $invitation ."</a>. <br> <br> - Μετά την ενεργοποίηση θα έχετε πρόσσβαση + Μετά την ενεργοποίηση θα έχετε πρόσβαση στο περιεχόμενο του site.<br> Μην απαντήσετε στο email, δεν υπάρχει φυσική επαφή η οποία να λαμβάνει τυχόν replies." @@ -77,8 +79,8 @@ class SendMail_service * send email using phpMailer class; * optional SMTP server configuration; * - * @param $envelope - * @return success_starus (boolean) + * @param array $envelope: array with [ email, name, subject, body ] keys + * @return boolean success_starus */ public static function send_phpMailer($envelope) { @@ -115,7 +117,6 @@ class SendMail_service $mail->Body = $envelope['body']; return (!$mail->send()) ? false : true; - } diff --git a/public/app/routes/user.php b/public/app/routes/user.php index 67032e6..622dc57 100644 --- a/public/app/routes/user.php +++ b/public/app/routes/user.php @@ -193,10 +193,17 @@ if (Auth::in_admin_group()) { Route::add('/admin/invite', function() { $teachers = Registry::use('database')->runQuery( "SELECT id, concat(last_name, ' ', first_name) as TeacherName - FROM user ORDER BY TeacherName", [] + FROM user ORDER BY TeacherName + WHERE otp_expiration < :now OR otp_expiration IS NULL", + [ ':now' => time() ] ); Render::view('templates/invite', ['teachers' => $teachers]); }); + + // POST AJAX: set petition protocol + Route::add('/admin/send/invitation', function() { + Office::send_invitation(); + }, 'post'); } diff --git a/public/app/views/components/theme.php b/public/app/views/components/theme.php index 5a545e6..4e95193 100644 --- a/public/app/views/components/theme.php +++ b/public/app/views/components/theme.php @@ -31,15 +31,21 @@ switch ($month) { * ( ( (month*31 + day) % L*2 ) div 2 ) * this will allow theme exchange every 2 days * + * + * 4-day rollup: + * --- -- -- - - - + * supports up to 21 themes/season + * = 84 themes/year + * + * algo: * ( ( ( month*31 + day) % L*4 ) div 4 ) * change seasonal theme every 4 days - * - * Catch Exceptions + * ... Catch Exceptions: * if (month == 12) : month = 0 * if (month == 6 && day == 1) then day = 2 + * */ - $theme_def = [ # --- summer --- @@ -119,7 +125,7 @@ $themes = [ ]; -define('THEME', $theme_def[ $themes['fall'][3] ]); +define('THEME', $theme_def[ $themes['summer'][0] ]); ?> <!-- theme overides --> diff --git a/public/app/views/js/select2-supplementary.php b/public/app/views/js/select2-supplementary.php index a7aa7e2..5b52c5a 100644 --- a/public/app/views/js/select2-supplementary.php +++ b/public/app/views/js/select2-supplementary.php @@ -7,22 +7,17 @@ * --- -- -- - - - * Get selected value(s) of Select2 control * - * @param arg: source-element - * @return (string) value(s) comma-separated + * @param (selector) arg: source-element + * @return (array) value(s) */ function getValues(srcElm) { - var res; - var obj = srcElm.select2('data'); // get delected data array + var res = []; + var obj = srcElm.select2('data'); // get delected data array - if (obj.length === 0) return ''; // if empty list then nothig is selected - else { + if (!obj.length === 0); { var i = 0; - obj.forEach(function(elm){ // loop through object elements array - - if (i) res += ',' + elm.id; // if not first item, prepend ',' befor value(id) - else res = elm.id; // else set (first) checked value - - i++; + obj.forEach(function(elm) { + res.push(elm.id) }); } return res; diff --git a/public/app/views/templates/invite.php b/public/app/views/templates/invite.php index 637697f..d7947da 100644 --- a/public/app/views/templates/invite.php +++ b/public/app/views/templates/invite.php @@ -35,41 +35,43 @@ <form method="post"> - <div class='row'> - <div class='form-group '> - <label for='members'>Μέλη *</label> - - <select id='members' class='form-select form-select-sm' name='members[]' multiple='multiple' style='width:100%'> - <?php foreach($teachers as $key => $item) :?> - <option value="<?=$item['id']?>"><?=$item['TeacherName']?></option> - <?php endforeach; ?> - </select> - </div> - </div> - + <div class='row'> + <div class='form-group '> + <label for='members'>Προς *</label> + + <select id='members' class='form-select form-select-sm' name='members[]' multiple='multiple' style='width:100%'> + <?php foreach($teachers as $key => $item) :?> + <option value="<?=$item['id']?>"><?=$item['TeacherName']?></option> + <?php endforeach; ?> + </select> + </div> + </div> <br /> - - <div class="row justify-content-center"> - <div class="col-6"> - <button type="submit" class="btn btn-primary btn-sm col-12">Σύνδεση</button> - </div> + <div class="row"> + <div class='form-group '> + <button type="submit" class="btn btn-primary btn-sm col-12"> + Αποστολή προσκλήσεων + </button> + </div> </div> </form> </div> <div class="info"> - <!-- - <p>Αν ξεχάσατε τον κωδικό πρόσβασης μπορείτε να δημιουργήσετε ένα νέο (υπο κατασκευή).</p> - --> <p> - Εαν δικαιούστε αλλά δεν έχετε πρόσβαση στο site, παρακαλούμε επικοινωνήστε - με τη διεύθυνση του σχολείου προκειμένου να σας αποσταλεί σχετική πρόσκληση. + Χρησιμοποιήστε τη φόρμα για να προσκαλέσετε νέους χρήστες + ή για reset ενός account. + </p> + <p> + Κάθε πρόσκληση παραμένει ενεργή για 72 ώρες. + Στο διάστημα αυτό δεν μπορεί να σταλεί άλλη πρόσκληση στο ίδιο email. </p> <p> - Ο ιστότοπος χρησιμοποιεί cookies τα οποία έχουν αποκλειστικά λειτουργικό ρόλο. - Η χρήση των υπηρεσιών του site συνεπάγεται την αποδοχή διατήρησης αυτών των cookies. + Μην στέλνετε πολλές προσκλήσεις ταυτόχρονα. + Ένας καλός ρυθμός είναι οι 5 προσκλήσεις το λεπτό + και έως 30 προσκλήσες την ημέρα. </p> </div> @@ -97,30 +99,31 @@ $(document).ready(function() { // ------------------------------------------------------------------------- $('.content form').submit( event => { + event.preventDefault(); // prepare data to POST var data = { - email: $('input[name=email]').val(), - password: $('input[name=password]').val() + ids: getValues($('#members')) }; + console.log(data); // select action url (add or update) - var request = '/account/check-login'; + var request = '/admin/send/invitation'; // send POST request $.post(request, data) .done(function( data ) { if (data.status !== false) { - window.location.href = data.status.goto; + alert('Έχουν αποσταλεί οι προσλήσεις:\n\n'+ data.sent); + window.location.href = '/panel'; } else { alert('Τα στοιχεία πρόσβασης που δώσατε είναι λάθος. Παρακαλώ προσπαθήστε ξανά.'); } }); - }); }); diff --git a/public/assets/css/class.css b/public/assets/css/class.css index 8a8f51b..6c0c1bf 100644 --- a/public/assets/css/class.css +++ b/public/assets/css/class.css @@ -16,7 +16,6 @@ --light-grey-shade: 1px 5px 7px #7773; --form-content-font-size: .87rem; --form-input-height: 31px; - --table-head-bgr: #fff6; --table-row-bgr: #eee4; @@ -40,7 +39,8 @@ --img-credit-bgr: #fff5; --img-credit-bgr-hover: #fffa; --img-credit-color: #333e; - --img-credit-hover-color: #f77; + --img-credit-hover-color: #f77; + } @@ -123,7 +123,7 @@ html, body { } .info li.list-group-item.separator:hover { background: #fff; } -.info p { font-size: 14px; line-height: 200%; margin-bottom: .33em; } +.info p { font-size: 14px; line-height: 200%; margin-bottom: .5em; } .info h4 { font-size: 16px; font-weight: 400; } diff --git a/public/assets/css/themes/summer-01.css b/public/assets/css/themes/summer-01.css index d22d5d5..0f4affa 100644 --- a/public/assets/css/themes/summer-01.css +++ b/public/assets/css/themes/summer-01.css @@ -1,6 +1,6 @@ :root { --background-image: url(/assets/media/summer-01.webp); - --bs-heading-color: #230; + --bs-heading-color: #044; --menu-hover-bgr: #bee; --info-text-color: #334; --img-credit-hover-color: #334; |
