base.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. {% load i18n static tz %}
  2. {% get_current_language as LANGUAGE_CODE %}
  3. {% get_current_language_bidi as LANGUAGE_BIDI %}
  4. <!DOCTYPE html>
  5. <html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
  6. <head>
  7. <title>{% block title %}Home{% endblock %} | ArchiveBox</title>
  8. {% block blockbots %}
  9. <meta name="robots" content="NONE,NOARCHIVE">
  10. {% endblock %}
  11. <link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}">
  12. {% block extrastyle %}
  13. <style>
  14. #upgrade-banner {
  15. position: fixed;
  16. right: 20px;
  17. bottom: 20px;
  18. background-color: #f8f8f8;
  19. color: #333333;
  20. border: 2px solid #772948;
  21. padding: 10px 20px;
  22. z-index: 1000;
  23. text-align: center;
  24. }
  25. #dismiss-btn {
  26. background: #aa1e55;
  27. color: white;
  28. cursor: pointer;
  29. }
  30. </style>
  31. {% endblock %}
  32. {% if LANGUAGE_BIDI %}
  33. <link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}">
  34. {% endif %}
  35. {% block responsive %}
  36. <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
  37. <link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive.css" %}">
  38. {% if LANGUAGE_BIDI %}
  39. <link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive_rtl.css" %}">
  40. {% endif %}
  41. {% endblock %}
  42. <link rel="stylesheet" type="text/css" href="{% static "admin.css" %}">
  43. <script>
  44. function selectSnapshotListView(e) {
  45. e && e.stopPropagation()
  46. e && e.preventDefault()
  47. console.log('Switching to Snapshot list view...')
  48. localStorage.setItem('preferred_snapshot_view_mode', 'list')
  49. window.location = "{% url 'admin:core_snapshot_changelist' %}" + document.location.search
  50. return false
  51. }
  52. function selectSnapshotGridView(e) {
  53. e && e.stopPropagation()
  54. e && e.preventDefault()
  55. console.log('Switching to Snapshot grid view...')
  56. localStorage.setItem('preferred_snapshot_view_mode', 'grid')
  57. window.location = "{% url 'admin:grid' %}" + document.location.search
  58. return false
  59. }
  60. const preferred_view = localStorage.getItem('preferred_snapshot_view_mode') || 'unset'
  61. const current_view = (
  62. window.location.pathname === "{% url 'admin:core_snapshot_changelist' %}"
  63. ? 'list'
  64. : 'grid')
  65. console.log('Preferred snapshot view is:', preferred_view, 'Current view mode is:', current_view)
  66. if (preferred_view === 'grid' && current_view !== 'grid') {
  67. selectSnapshotGridView()
  68. }
  69. </script>
  70. {% block extrahead %}{% endblock %}
  71. </head>
  72. <body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}" data-admin-utc-offset="{% now "Z" %}">
  73. {% include 'progressbar.html' %}
  74. <div id="container">
  75. {% if not is_popup %}
  76. <div id="header">
  77. <div id="branding">
  78. <h1 id="site-name">
  79. <a href="{% url 'Home' %}">
  80. <img src="{% static 'archive.png' %}" id="logo">
  81. ArchiveBox
  82. </a>
  83. </h1>
  84. </div>
  85. {% block usertools %}
  86. {% if has_permission %}
  87. {% include 'navigation.html' %}
  88. {% endif %}
  89. {% endblock %}
  90. {% block nav-global %}{% endblock %}
  91. </div>
  92. {% block breadcrumbs %}
  93. <div class="breadcrumbs">
  94. <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
  95. {% if title %} &rsaquo; {{ title }}{% endif %}
  96. </div>
  97. {% endblock %}
  98. {% endif %}
  99. {% block messages %}
  100. {% if messages %}
  101. <ul class="messagelist">
  102. {% for message in messages %}
  103. <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
  104. {% endfor %}
  105. </ul>
  106. {% endif %}
  107. {% endblock messages %}
  108. <div id="content" class="{% block coltype %}colM{% endblock %}">
  109. {% if opts.model_name == 'snapshot' and cl %}
  110. <small id="snapshot-view-mode">
  111. <a href="#list" title="List view" id="snapshot-view-list">☰</a> |
  112. <a href="#grid" title="Grid view" id="snapshot-view-grid" style="letter-spacing: -.4em;">⣿⣿</a>
  113. </small>
  114. {% endif %}
  115. {% block pretitle %}{% endblock %}
  116. {% block content_title %}{# {% if title %}<h1>{{ title }}</h1>{% endif %} #}{% endblock %}
  117. {% block content %}
  118. {% block object-tools %}{% endblock %}
  119. {{ content }}
  120. {% endblock %}
  121. {% block sidebar %}{% endblock %}
  122. <br class="clear">
  123. </div>
  124. {% block footer %}<div id="footer"></div>{% endblock %}
  125. </div>
  126. {% if user.is_authenticated and user.is_superuser and CAN_UPGRADE %}
  127. <script>
  128. if (!localStorage.getItem("bannerDismissed")) {
  129. const upgradeVersionTag = "{{VERSIONS_AVAILABLE.recommended_version.tag_name}}"
  130. const upgradeVersionURL = "{{VERSIONS_AVAILABLE.recommended_version.html_url}}"
  131. const currentVersionTag = "{{VERSION}}"
  132. const currentVersionURL = "{{VERSIONS_AVAILABLE.recommended_version.html_url}}"
  133. createBanner(currentVersionTag, currentVersionURL, upgradeVersionTag, upgradeVersionURL)
  134. }
  135. function createBanner(currentVersionTag, currentVersionURL, upgradeVersionTag, upgradeVersionURL) {
  136. const banner = document.createElement('div')
  137. banner.setAttribute('id', 'upgrade-banner');
  138. banner.innerHTML = `
  139. <p>There's a new version of ArchiveBox available!</p>
  140. Your version: <a href=${currentVersionURL}>${currentVersionTag}</a> | New version: <a href=${upgradeVersionURL}>${upgradeVersionTag}</a>
  141. <p>
  142. <a href=https://github.com/ArchiveBox/ArchiveBox/wiki/Upgrading-or-Merging-Archives>Upgrade Instructions</a> | <a href=https://github.com/ArchiveBox/ArchiveBox/releases>Changelog</a> | <a href=https://github.com/ArchiveBox/ArchiveBox/wiki/Roadmap>Roadmap</a>
  143. </p>
  144. <button id="dismiss-btn">Dismiss</button>
  145. `
  146. document.body.appendChild(banner);
  147. const dismissButton = document.querySelector("#dismiss-btn")
  148. if (dismissButton) {
  149. dismissButton.addEventListener("click", dismissBanner)
  150. }
  151. }
  152. function dismissBanner() {
  153. const banner = document.getElementById("upgrade-banner")
  154. banner.style.display = "none"
  155. localStorage.setItem("bannerDismissed", "true")
  156. }
  157. </script>
  158. {% endif %}
  159. <script>
  160. $ = django.jQuery;
  161. $.fn.reverse = [].reverse;
  162. // hide images that fail to load
  163. document.querySelector('body').addEventListener('error', function (e) {
  164. e.target.style.opacity = 0;
  165. }, true)
  166. // setup timezone
  167. {% get_current_timezone as TIME_ZONE %}
  168. window.TIME_ZONE = '{{TIME_ZONE}}'
  169. window.setCookie = function(name, value, days) {
  170. let expires = ""
  171. if (days) {
  172. const date = new Date()
  173. date.setTime(date.getTime() + (days*24*60*60*1000))
  174. expires = "; expires=" + date.toUTCString()
  175. }
  176. document.cookie = name + "=" + (value || "") + expires + "; path=/"
  177. }
  178. function setTimeOffset() {
  179. if (window.GMT_OFFSET) return
  180. window.GMT_OFFSET = -(new Date).getTimezoneOffset()
  181. window.setCookie('GMT_OFFSET', window.GMT_OFFSET, 365)
  182. }
  183. // change the admin actions button from a dropdown to buttons across
  184. function fix_actions() {
  185. const container = $('div.actions')
  186. // too many actions to turn into buttons
  187. if (container.find('select[name=action] option').length >= 11) return
  188. // hide the empty default option thats just a placeholder with no value
  189. container.find('label:nth-child(1), button[value=0]').hide()
  190. const buttons = $('<div></div>')
  191. .insertAfter('div.actions button[type=submit]')
  192. .css('display', 'inline')
  193. .addClass('class', 'action-buttons');
  194. // for each action in the dropdown, turn it into a button instead
  195. container.find('select[name=action] option:gt(0)').each(function () {
  196. const action_type = this.value
  197. $('<button>')
  198. .attr('type', 'button')
  199. .attr('name', action_type)
  200. .addClass('button')
  201. .text(this.text)
  202. .click(function (e) {
  203. e.preventDefault()
  204. e.stopPropagation()
  205. const num_selected = document.querySelector('.action-counter').innerText.split(' ')[0]
  206. if (action_type === 'overwrite_snapshots') {
  207. const message = (
  208. 'Are you sure you want to re-archive (overwrite) ' + num_selected + ' Snapshots?\n\n' +
  209. 'This will delete all previously saved files from these Snapshots and re-archive them from scratch.\n\n'
  210. )
  211. if (!window.confirm(message)) return false
  212. }
  213. if (action_type === 'delete_snapshots') {
  214. const message = (
  215. 'Are you sure you want to permanently delete ' + num_selected + ' Snapshots?\n\n' +
  216. 'They will be removed from your index, and all their Snapshot content on disk will be permanently deleted.'
  217. )
  218. if (!window.confirm(message)) return false
  219. }
  220. // select the action button from the dropdown
  221. container.find('select[name=action]')
  222. .find('[selected]').removeAttr('selected').end()
  223. .find('[value=' + action_type + ']').attr('selected', 'selected').click()
  224. // click submit & replace the archivebox logo with a spinner
  225. $('#changelist-form button[name="index"]').click()
  226. document.querySelector('#logo').outerHTML = '<div class="loader"></div>'
  227. return false
  228. })
  229. .appendTo(buttons)
  230. })
  231. console.log('Converted', buttons.children().length, 'admin actions from dropdown to buttons')
  232. }
  233. function setupSnapshotGridListToggle() {
  234. $("#snapshot-view-list").click(selectSnapshotListView)
  235. $("#snapshot-view-grid").click(selectSnapshotGridView)
  236. $('#changelist-form .card input:checkbox').change(function() {
  237. if ($(this).is(':checked'))
  238. $(this).parents('.card').addClass('selected-card')
  239. else
  240. $(this).parents('.card').removeClass('selected-card')
  241. })
  242. };
  243. $(document).ready(function() {
  244. fix_actions()
  245. setupSnapshotGridListToggle()
  246. setTimeOffset()
  247. })
  248. </script>
  249. </body>
  250. </html>