浏览代码

[BS5] add whats new modal after update

FreddleSpl0it 3 年之前
父节点
当前提交
8987ebca36

+ 1 - 0
data/web/admin.php

@@ -112,6 +112,7 @@ $template_data = [
   'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
   'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
   'lang_admin' => json_encode($lang['admin']),
   'lang_admin' => json_encode($lang['admin']),
   'lang_datatables' => json_encode($lang['datatables']),
   'lang_datatables' => json_encode($lang['datatables']),
+  'last_login' => last_login('get', $_SESSION['mailcow_cc_username'], 7, 0)['ui']['time']
 ];
 ];
 
 
 require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
 require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';

+ 5 - 1
data/web/inc/footer.inc.php

@@ -27,7 +27,11 @@ if (is_array($alertbox_log_parser)) {
 $globalVariables = [
 $globalVariables = [
   'mailcow_info' => array(
   'mailcow_info' => array(
     'version_tag' => $GLOBALS['MAILCOW_GIT_VERSION'],
     'version_tag' => $GLOBALS['MAILCOW_GIT_VERSION'],
-    'git_project_url' => $GLOBALS['MAILCOW_GIT_URL']
+    'last_version_tag' => $GLOBALS['MAILCOW_LAST_GIT_VERSION'],
+    'project_url' => $GLOBALS['MAILCOW_GIT_URL'],
+    'project_owner' => $GLOBALS['MAILCOW_GIT_OWNER'],
+    'project_repo' => $GLOBALS['MAILCOW_GIT_REPO'],
+    'updatedAt' => $GLOBALS['MAILCOW_UPDATEDAT']
   ),
   ),
   'js_path' => '/cache/'.basename($JSPath),
   'js_path' => '/cache/'.basename($JSPath),
   'pending_tfa_method' => @$_SESSION['pending_tfa_method'],
   'pending_tfa_method' => @$_SESSION['pending_tfa_method'],

+ 6 - 3
data/web/inc/functions.inc.php

@@ -251,7 +251,7 @@ function password_check($password1, $password2) {
 
 
   return true;
   return true;
 }
 }
-function last_login($action, $username, $sasl_limit_days = 7) {
+function last_login($action, $username, $sasl_limit_days = 7, $ui_offset = 1) {
   global $pdo;
   global $pdo;
   global $redis;
   global $redis;
   $sasl_limit_days = intval($sasl_limit_days);
   $sasl_limit_days = intval($sasl_limit_days);
@@ -319,8 +319,11 @@ function last_login($action, $username, $sasl_limit_days = 7) {
         $stmt = $pdo->prepare('SELECT `remote`, `time` FROM `logs`
         $stmt = $pdo->prepare('SELECT `remote`, `time` FROM `logs`
           WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login"
           WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login"
             AND JSON_EXTRACT(`call`, "$[1]") = :username
             AND JSON_EXTRACT(`call`, "$[1]") = :username
-            AND `type` = "success" ORDER BY `time` DESC LIMIT 1 OFFSET 1');
-        $stmt->execute(array(':username' => $username));
+            AND `type` = "success" ORDER BY `time` DESC LIMIT 1 OFFSET :offset');
+        $stmt->execute(array(
+          ':username' => $username,
+          ':offset' => $ui_offset
+        ));
         $ui = $stmt->fetch(PDO::FETCH_ASSOC);
         $ui = $stmt->fetch(PDO::FETCH_ASSOC);
       }
       }
       else {
       else {

文件差异内容过多而无法显示
+ 1 - 0
data/web/js/build/013-markdown-it.min.js


+ 1 - 1
data/web/js/build/014-mailcow.js

@@ -346,6 +346,6 @@ $(document).ready(function() {
 });
 });
 
 
 
 
-// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
+// https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
 function escapeHtml(n){var entityMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
 function escapeHtml(n){var entityMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
 function unescapeHtml(t){var n={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'","&#x2F;":"/","&#x60;":"`","&#x3D;":"="};return String(t).replace(/&amp;|&lt;|&gt;|&quot;|&#39;|&#x2F|&#x60|&#x3D;/g,function(t){return n[t]})}
 function unescapeHtml(t){var n={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'","&#x2F;":"/","&#x60;":"`","&#x3D;":"="};return String(t).replace(/&amp;|&lt;|&gt;|&quot;|&#39;|&#x2F|&#x60|&#x3D;/g,function(t){return n[t]})}

+ 48 - 1
data/web/js/site/admin.js

@@ -56,6 +56,7 @@ jQuery(function($){
     $("#rspamd_global_filters").removeClass("d-none");
     $("#rspamd_global_filters").removeClass("d-none");
   });
   });
   $("#super_delete").click(function() { return confirm(lang.queue_ays); });
   $("#super_delete").click(function() { return confirm(lang.queue_ays); });
+  
   $(".refresh_table").on('click', function(e) {
   $(".refresh_table").on('click', function(e) {
     e.preventDefault();
     e.preventDefault();
     var table_name = $(this).data('table');
     var table_name = $(this).data('table');
@@ -793,5 +794,51 @@ jQuery(function($){
   $('#add_f2b_regex_row').click(function() {
   $('#add_f2b_regex_row').click(function() {
       add_table_row($('#f2b_regex_table'), "f2b_regex");
       add_table_row($('#f2b_regex_table'), "f2b_regex");
   });
   });
-});
 
 
+  // show whats new modal
+  if (mailcow_info.updatedAt > last_login){
+    var parsedSeenTimestamp = parseInt(localStorage.getItem("seenChangelog"));
+    if (!isNaN(parsedSeenTimestamp) && mailcow_info.updatedAt < parsedSeenTimestamp) {
+      console.log("changelog seen");
+      return;
+    }
+    $.ajax({
+      type: 'GET',
+      url: 'https://api.github.com/repos/' + mailcow_info.project_owner + '/' + mailcow_info.project_repo + '/releases/tags/' + mailcow_info.version_tag,
+      dataType: 'json',
+      success: function (data) { 
+        var md = window.markdownit();
+        var result = md.render(data.body);
+        result = parseGitHubLinks(result);
+
+        $('#showWhatsNew').find(".modal-body").html(`
+          <h3>` + data.name + `</h3>
+          <span class="mt-4">` + result + `</span>
+        `);
+
+        localStorage.setItem("seenChangelog", Math.floor(Date.now() / 1000).toString());
+      }
+    });
+
+    new bootstrap.Modal(document.getElementById("showWhatsNew"), {
+      backdrop: 'static',
+      keyboard: false
+    }).show();
+  }
+
+  function parseGitHubLinks(inputText) {
+    var replacedText, replacePattern1;
+  
+    replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
+    replacedText = inputText.replace(replacePattern1, (matched, index, original, input_string) => {
+        if (!matched.includes('github.com')) return matched;
+  
+        last_uri_path = matched.split('/');
+        last_uri_path = last_uri_path[last_uri_path.length - 1];
+        
+        return '<a href="' + matched + '" target="_blank">' + last_uri_path + '</a>';
+    });
+  
+    return replacedText;
+  }
+});

+ 1 - 1
data/web/templates/admin.twig

@@ -70,6 +70,6 @@ var admin_username = '{{ mailcow_cc_username }}';
 var csrf_token = '{{ csrf_token }}';
 var csrf_token = '{{ csrf_token }}';
 var pagination_size = '{{ pagination_size }}';
 var pagination_size = '{{ pagination_size }}';
 var log_pagination_size = '{{ log_pagination_size }}';
 var log_pagination_size = '{{ log_pagination_size }}';
-
+var last_login = '{{ last_login }}';
 </script>
 </script>
 {% endblock %}
 {% endblock %}

+ 16 - 0
data/web/templates/modals/admin.twig

@@ -261,3 +261,19 @@
     </div>
     </div>
   </div>
   </div>
 </div><!-- priv key modal -->
 </div><!-- priv key modal -->
+<!-- whats new modal -->
+<div class="modal fade show" id="showWhatsNew" tabindex="-1" role="dialog" aria-hidden="true">
+  <div class="modal-dialog modal-lg">
+    <div class="modal-content">
+      <div class="modal-header">
+        <h5 class="modal-title">What's new?</h5>
+        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
+      </div>
+      <div class="modal-body d-flex flex-column mt-2 p-4">
+        <div class="spinner-border mx-auto" role="status">
+          <span class="visually-hidden">Loading...</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</div><!-- whats new modal -->

部分文件因为文件数量过多而无法显示