base.html 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530
  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. /* ============================================
  31. Modern card-based admin UI (shadcn-inspired)
  32. ============================================ */
  33. /* Base font improvements */
  34. body, html {
  35. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  36. -webkit-font-smoothing: antialiased;
  37. -moz-osx-font-smoothing: grayscale;
  38. font-size: 15px;
  39. line-height: 1.6;
  40. color: #0f172a;
  41. background: #f8fafc;
  42. }
  43. #container {
  44. background: #f8fafc;
  45. }
  46. #content {
  47. padding: 24px;
  48. }
  49. /* Main form container - flexbox grid */
  50. #content-main form > div,
  51. #content form > div {
  52. display: flex;
  53. flex-wrap: wrap;
  54. gap: 20px;
  55. align-items: stretch;
  56. }
  57. /* Each fieldset becomes a card */
  58. #content-main form fieldset,
  59. #content form fieldset,
  60. #content-main form .module:not(.inline-group),
  61. #content form .module:not(.inline-group) {
  62. background: #fff !important;
  63. border: 1px solid #e2e8f0 !important;
  64. border-top: 1px solid #e2e8f0 !important;
  65. border-left: 1px solid #e2e8f0 !important;
  66. border-right: 1px solid #e2e8f0 !important;
  67. border-bottom: 1px solid #e2e8f0 !important;
  68. border-radius: 12px !important;
  69. padding: 0 !important;
  70. margin: 0 !important;
  71. box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.06);
  72. flex: 1 1 340px;
  73. min-width: 320px;
  74. max-width: calc(33.33% - 14px);
  75. box-sizing: border-box;
  76. display: flex;
  77. flex-direction: column;
  78. transition: box-shadow 0.2s ease, border-color 0.2s ease;
  79. overflow: hidden;
  80. }
  81. /* Wide fieldsets MUST override card max-width - placed after card rules for specificity */
  82. #content-main form fieldset.wide,
  83. #content form fieldset.wide,
  84. #content-main form fieldset:has(.field-archiveresults_list),
  85. #content form fieldset:has(.field-archiveresults_list),
  86. #content-main form fieldset:has(.field-snapshots),
  87. #content form fieldset:has(.field-snapshots) {
  88. flex: 1 1 100% !important;
  89. max-width: 100% !important;
  90. min-width: 100% !important;
  91. width: 100% !important;
  92. flex-basis: 100% !important;
  93. }
  94. /* Inline groups should NOT have card constraints */
  95. #content-main form .inline-group,
  96. #content form .inline-group,
  97. .inline-group fieldset,
  98. .inline-group .module {
  99. flex: 1 1 100% !important;
  100. max-width: 100% !important;
  101. min-width: 100% !important;
  102. width: 100% !important;
  103. }
  104. #content-main form fieldset:hover,
  105. #content form fieldset:hover {
  106. box-shadow: 0 4px 6px rgba(0,0,0,0.05), 0 2px 4px rgba(0,0,0,0.06);
  107. border-color: #cbd5e1;
  108. }
  109. /* Archive results list content should take full width */
  110. .field-archiveresults_list,
  111. .field-archiveresults_list .readonly,
  112. .field-snapshots,
  113. .field-snapshots .readonly {
  114. width: 100% !important;
  115. max-width: 100% !important;
  116. background: transparent !important;
  117. border: none !important;
  118. padding: 0 !important;
  119. }
  120. /* Card headers - no borders, just background */
  121. #content-main form fieldset h2,
  122. #content form fieldset h2,
  123. #content-main form .module h2,
  124. #content form .module h2 {
  125. margin: 0 !important;
  126. padding: 8px 16px !important;
  127. background: #f1f5f9 !important;
  128. color: #334155 !important;
  129. font-size: 12px !important;
  130. font-weight: 600 !important;
  131. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
  132. border: none !important;
  133. border-top: none !important;
  134. border-left: none !important;
  135. border-right: none !important;
  136. border-bottom: none !important;
  137. border-radius: 0 !important;
  138. text-transform: uppercase;
  139. letter-spacing: 0.5px;
  140. flex-shrink: 0;
  141. -webkit-font-smoothing: antialiased;
  142. box-shadow: none !important;
  143. outline: none !important;
  144. }
  145. /* Collapse toggle styling */
  146. #content-main form fieldset h2 a.collapse-toggle,
  147. #content form fieldset h2 a.collapse-toggle {
  148. color: #64748b;
  149. }
  150. /* Card content area */
  151. #content-main form fieldset > div,
  152. #content form fieldset > div {
  153. padding: 20px;
  154. flex: 1;
  155. overflow-x: hidden;
  156. overflow-y: visible;
  157. min-width: 0;
  158. }
  159. /* Form rows inside cards */
  160. #content-main form fieldset .form-row,
  161. #content form fieldset .form-row {
  162. padding: 8px 0;
  163. border-bottom: 1px solid #f1f5f9;
  164. min-width: 0;
  165. min-height: auto;
  166. }
  167. #content-main form fieldset .form-row:first-child,
  168. #content form fieldset .form-row:first-child {
  169. padding-top: 0;
  170. }
  171. #content-main form fieldset .form-row:last-child,
  172. #content form fieldset .form-row:last-child {
  173. border-bottom: none;
  174. padding-bottom: 0;
  175. }
  176. /* Remove borders from nested fieldsets and flex-containers inside cards */
  177. #content-main form fieldset fieldset,
  178. #content form fieldset fieldset,
  179. #content-main form fieldset .flex-container,
  180. #content form fieldset .flex-container,
  181. #content-main form .module fieldset,
  182. #content form .module fieldset {
  183. background: transparent !important;
  184. border: none !important;
  185. border-radius: 0 !important;
  186. box-shadow: none !important;
  187. padding: 0 !important;
  188. margin: 0 !important;
  189. min-width: 0 !important;
  190. max-width: 94% !important;
  191. flex: none !important;
  192. display: block !important;
  193. }
  194. /* Nested fieldset headers should be invisible */
  195. #content-main form fieldset fieldset h2,
  196. #content form fieldset fieldset h2,
  197. #content-main form fieldset .flex-container legend,
  198. #content form fieldset .flex-container legend {
  199. background: transparent !important;
  200. padding: 0 0 4px 0 !important;
  201. font-size: 13px !important;
  202. color: #374151 !important;
  203. text-transform: none !important;
  204. letter-spacing: normal !important;
  205. }
  206. /* Ensure form elements inside cards don't overflow */
  207. #content-main form fieldset input,
  208. #content-main form fieldset select,
  209. #content-main form fieldset textarea,
  210. #content form fieldset input,
  211. #content form fieldset select,
  212. #content form fieldset textarea {
  213. max-width: 100%;
  214. box-sizing: border-box;
  215. }
  216. /* Related widget wrapper should fit within card */
  217. #content-main form fieldset .related-widget-wrapper,
  218. #content form fieldset .related-widget-wrapper {
  219. max-width: 100%;
  220. }
  221. #content-main form fieldset .related-widget-wrapper select,
  222. #content form fieldset .related-widget-wrapper select {
  223. min-width: 0;
  224. flex: 1;
  225. }
  226. /* Labels inside cards */
  227. #content-main form fieldset .form-row > label,
  228. #content form fieldset .form-row > label,
  229. #content-main form fieldset .form-row > .flex-container > label,
  230. #content form fieldset .form-row > .flex-container > label,
  231. #content-main form label,
  232. #content form label,
  233. .aligned label,
  234. legend {
  235. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  236. font-weight: 500;
  237. color: #374151;
  238. display: block;
  239. margin-bottom: 8px;
  240. float: none !important;
  241. width: auto !important;
  242. padding: 0 !important;
  243. font-size: 13px;
  244. letter-spacing: -0.01em;
  245. -webkit-font-smoothing: antialiased;
  246. -moz-osx-font-smoothing: grayscale;
  247. }
  248. /* Readonly fields styling */
  249. #content-main form fieldset .readonly,
  250. #content form fieldset .readonly {
  251. background: #f8fafc;
  252. padding: 12px 14px;
  253. border-radius: 8px;
  254. font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;
  255. font-size: 13px;
  256. word-break: break-word;
  257. line-height: 1.6;
  258. border: 1px solid #e2e8f0;
  259. color: #475569;
  260. }
  261. /* Long content in readonly */
  262. #content-main form fieldset .readonly pre,
  263. #content form fieldset .readonly pre {
  264. margin: 0;
  265. white-space: pre-wrap;
  266. word-break: break-word;
  267. font-family: inherit;
  268. }
  269. /* Input styling */
  270. #content-main form input[type="text"],
  271. #content-main form input[type="number"],
  272. #content-main form input[type="url"],
  273. #content-main form input[type="email"],
  274. #content-main form input[type="password"],
  275. #content form input[type="text"],
  276. #content form input[type="number"],
  277. #content form input[type="url"],
  278. #content form input[type="email"],
  279. #content form input[type="password"] {
  280. width: 100%;
  281. padding: 10px 14px;
  282. border: 1px solid #d1d5db;
  283. border-radius: 8px;
  284. font-size: 14px;
  285. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  286. box-sizing: border-box;
  287. background: #fff;
  288. color: #1e293b;
  289. transition: border-color 0.15s ease, box-shadow 0.15s ease;
  290. -webkit-font-smoothing: antialiased;
  291. }
  292. #content-main form select,
  293. #content form select {
  294. width: 100%;
  295. border: 1px solid #d1d5db;
  296. border-radius: 8px;
  297. font-size: 14px;
  298. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  299. box-sizing: border-box;
  300. background: #fff;
  301. color: #1e293b;
  302. transition: border-color 0.15s ease, box-shadow 0.15s ease;
  303. -webkit-font-smoothing: antialiased;
  304. }
  305. #content-main form input::placeholder,
  306. #content form input::placeholder {
  307. color: #94a3b8;
  308. }
  309. /* Focus states */
  310. #content-main form input:focus,
  311. #content-main form select:focus,
  312. #content-main form textarea:focus,
  313. #content form input:focus,
  314. #content form select:focus,
  315. #content form textarea:focus {
  316. border-color: #3b82f6;
  317. outline: none;
  318. box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
  319. }
  320. /* Textarea styling */
  321. #content-main form textarea,
  322. #content form textarea {
  323. width: 100%;
  324. box-sizing: border-box;
  325. border: 1px solid #d1d5db;
  326. border-radius: 8px;
  327. padding: 12px 14px;
  328. font-size: 14px;
  329. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  330. line-height: 1.6;
  331. resize: vertical;
  332. min-height: 80px;
  333. color: #1e293b;
  334. transition: border-color 0.15s ease, box-shadow 0.15s ease;
  335. -webkit-font-smoothing: antialiased;
  336. }
  337. /* Fix vTextField width */
  338. .vTextField {
  339. width: 100% !important;
  340. }
  341. /* ============================================
  342. Button styling (shadcn-inspired)
  343. ============================================ */
  344. /* Base button styles */
  345. input[type="submit"],
  346. button,
  347. .button,
  348. .btn,
  349. a.button,
  350. .submit-row input,
  351. .submit-row a.button {
  352. display: inline-flex;
  353. align-items: center;
  354. justify-content: center;
  355. gap: 8px;
  356. padding: 10px 18px;
  357. font-size: 14px;
  358. font-weight: 500;
  359. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  360. line-height: 1.4;
  361. border-radius: 8px;
  362. border: 1px solid transparent;
  363. cursor: pointer;
  364. transition: all 0.15s ease;
  365. text-decoration: none;
  366. white-space: nowrap;
  367. -webkit-font-smoothing: antialiased;
  368. }
  369. /* Primary button (default) */
  370. input[type="submit"],
  371. button[type="submit"],
  372. .button.default,
  373. .submit-row input[type="submit"] {
  374. background: #0f172a;
  375. color: #fff;
  376. border-color: #0f172a;
  377. }
  378. input[type="submit"]:hover,
  379. button[type="submit"]:hover,
  380. .button.default:hover,
  381. .submit-row input[type="submit"]:hover {
  382. background: #1e293b;
  383. border-color: #1e293b;
  384. }
  385. input[type="submit"]:active,
  386. button[type="submit"]:active {
  387. background: #334155;
  388. transform: translateY(1px);
  389. }
  390. /* Secondary/outline buttons */
  391. button:not([type="submit"]),
  392. .button:not(.default),
  393. a.button {
  394. background: #fff;
  395. color: #374151;
  396. border-color: #d1d5db;
  397. }
  398. button:not([type="submit"]):hover,
  399. .button:not(.default):hover,
  400. a.button:hover {
  401. background: #f9fafb;
  402. border-color: #9ca3af;
  403. color: #1f2937;
  404. }
  405. /* Danger button */
  406. .deletelink,
  407. a.deletelink,
  408. button.deletelink,
  409. input[name="delete"],
  410. .button.delete {
  411. background: #fff;
  412. color: #dc2626;
  413. border-color: #fecaca;
  414. }
  415. .deletelink:hover,
  416. a.deletelink:hover,
  417. button.deletelink:hover,
  418. input[name="delete"]:hover,
  419. .button.delete:hover {
  420. background: #fef2f2;
  421. border-color: #f87171;
  422. color: #b91c1c;
  423. }
  424. /* Small buttons */
  425. .btn-sm,
  426. .object-tools a,
  427. .datetimeshortcuts a {
  428. padding: 6px 12px;
  429. font-size: 13px;
  430. border-radius: 6px;
  431. }
  432. /* Object tools (top action buttons) */
  433. .object-tools {
  434. margin-bottom: 20px;
  435. }
  436. .object-tools li {
  437. margin-left: 10px;
  438. }
  439. .object-tools a {
  440. background: #fff;
  441. color: #374151;
  442. border: 1px solid #d1d5db;
  443. text-decoration: none;
  444. display: inline-flex;
  445. align-items: center;
  446. }
  447. .object-tools a:hover {
  448. background: #f9fafb;
  449. border-color: #9ca3af;
  450. }
  451. /* Submit row styling */
  452. .submit-row {
  453. margin-top: 24px;
  454. padding: 20px;
  455. background: #fff;
  456. border-radius: 12px;
  457. border: 1px solid #e2e8f0;
  458. box-shadow: 0 1px 3px rgba(0,0,0,0.04);
  459. clear: both;
  460. flex: 1 1 100%;
  461. display: flex;
  462. gap: 12px;
  463. flex-wrap: wrap;
  464. align-items: center;
  465. }
  466. .submit-row p {
  467. margin: 0;
  468. }
  469. .submit-row .deletelink-box {
  470. margin-left: auto;
  471. }
  472. /* Responsive: 2 columns on medium screens */
  473. @media (max-width: 1400px) {
  474. #content-main form fieldset,
  475. #content form fieldset {
  476. max-width: calc(50% - 10px);
  477. flex: 1 1 320px;
  478. }
  479. }
  480. /* Responsive: stack on smaller screens */
  481. @media (max-width: 900px) {
  482. #content-main form fieldset,
  483. #content form fieldset {
  484. flex: 1 1 100%;
  485. max-width: 100%;
  486. min-width: auto;
  487. }
  488. #content {
  489. padding: 16px;
  490. }
  491. }
  492. /* Module content padding */
  493. #content-main form .module > div,
  494. #content form .module > div {
  495. padding: 12px;
  496. }
  497. /* Fix for JSON/config editor */
  498. .field-config .readonly,
  499. .field-config textarea {
  500. width: 100%;
  501. min-height: 120px;
  502. max-height: none;
  503. }
  504. /* Related widget styling */
  505. .related-widget-wrapper {
  506. display: flex;
  507. align-items: center;
  508. gap: 8px;
  509. flex-wrap: wrap;
  510. }
  511. .related-widget-wrapper select {
  512. flex: 1;
  513. min-width: 150px;
  514. }
  515. .related-widget-wrapper a {
  516. flex-shrink: 0;
  517. padding: 8px;
  518. border-radius: 6px;
  519. color: #64748b;
  520. transition: color 0.15s ease, background 0.15s ease;
  521. }
  522. .related-widget-wrapper a:hover {
  523. color: #1e293b;
  524. background: #f1f5f9;
  525. }
  526. /* Help text styling */
  527. .help {
  528. font-size: 13px;
  529. color: #64748b;
  530. margin-top: 6px;
  531. line-height: 1.5;
  532. }
  533. /* Error styling */
  534. .errorlist {
  535. color: #dc2626;
  536. font-size: 13px;
  537. margin: 6px 0;
  538. padding: 0;
  539. list-style: none;
  540. }
  541. .errorlist li {
  542. background: #fef2f2;
  543. padding: 8px 12px;
  544. border-radius: 6px;
  545. border: 1px solid #fecaca;
  546. }
  547. /* Inline related objects - force full width */
  548. .inline-group,
  549. #archiveresult_set-group,
  550. #content-main form .inline-group,
  551. #content-main form > div > .inline-group,
  552. #content form > div > .inline-group,
  553. .change-form .inline-group,
  554. div.inline-group {
  555. flex: 1 1 100% !important;
  556. max-width: 100% !important;
  557. min-width: 100% !important;
  558. width: 100% !important;
  559. margin-top: 20px;
  560. flex-basis: 100% !important;
  561. }
  562. /* Ensure inline-group breaks out of card grid */
  563. #content-main form > div,
  564. #content form > div {
  565. flex-wrap: wrap;
  566. }
  567. /* TabularInline table full width */
  568. .inline-group .tabular,
  569. .inline-group table {
  570. width: 100% !important;
  571. }
  572. .inline-related {
  573. margin: 12px 0;
  574. padding: 16px;
  575. background: #fff;
  576. border-radius: 10px;
  577. border: 1px solid #e2e8f0;
  578. }
  579. .inline-related h3 {
  580. margin: -16px -16px 16px -16px;
  581. padding: 12px 16px;
  582. background: #f8fafc;
  583. border-radius: 9px 9px 0 0;
  584. border-bottom: 1px solid #e2e8f0;
  585. font-size: 13px;
  586. font-weight: 600;
  587. color: #374151;
  588. }
  589. /* Tabular inline styling */
  590. .tabular {
  591. border-radius: 8px;
  592. overflow: hidden;
  593. border: 1px solid #e2e8f0;
  594. }
  595. .tabular td, .tabular th {
  596. padding: 12px 14px;
  597. font-size: 13px;
  598. border-bottom: 1px solid #f1f5f9;
  599. }
  600. .tabular th {
  601. background: #f8fafc;
  602. font-weight: 600;
  603. color: #374151;
  604. text-align: left;
  605. }
  606. .tabular tr:last-child td {
  607. border-bottom: none;
  608. }
  609. /* Delete checkbox */
  610. .inline-deletelink {
  611. color: #dc2626;
  612. font-size: 13px;
  613. }
  614. /* Datetime widgets */
  615. .datetimeshortcuts {
  616. margin-left: 10px;
  617. }
  618. .datetimeshortcuts a {
  619. background: #f1f5f9;
  620. color: #475569;
  621. border: none;
  622. padding: 4px 10px;
  623. }
  624. .datetimeshortcuts a:hover {
  625. background: #e2e8f0;
  626. color: #1e293b;
  627. }
  628. /* Aligned forms - fix label positioning */
  629. .aligned .form-row > div {
  630. margin-left: 0 !important;
  631. }
  632. /* Checkbox styling */
  633. input[type="checkbox"] {
  634. width: 18px;
  635. height: 18px;
  636. border-radius: 4px;
  637. border: 1px solid #d1d5db;
  638. cursor: pointer;
  639. accent-color: #3b82f6;
  640. }
  641. /* Links styling */
  642. a {
  643. color: #2563eb;
  644. text-decoration: none;
  645. transition: color 0.15s ease;
  646. }
  647. a:hover {
  648. color: #1d4ed8;
  649. }
  650. /* Messages/alerts */
  651. .messagelist {
  652. padding: 0;
  653. margin: 0 0 20px 0;
  654. }
  655. .messagelist li {
  656. padding: 14px 18px;
  657. border-radius: 10px;
  658. font-size: 14px;
  659. margin-bottom: 10px;
  660. display: flex;
  661. align-items: center;
  662. gap: 10px;
  663. }
  664. ul.messagelist li.success {
  665. background: #f0fdf4 !important;
  666. background-image: none !important;
  667. border: 1px solid #bbf7d0;
  668. color: #166534;
  669. }
  670. .messagelist li.warning {
  671. background: #fffbeb !important;
  672. background-image: none !important;
  673. border: 1px solid #fde68a;
  674. color: #92400e;
  675. }
  676. .messagelist li.error {
  677. background: #fef2f2 !important;
  678. background-image: none !important;
  679. border: 1px solid #fecaca;
  680. color: #991b1b;
  681. }
  682. /* Breadcrumbs */
  683. .breadcrumbs {
  684. background: transparent;
  685. padding: 12px 24px;
  686. font-size: 13px;
  687. color: #64748b;
  688. }
  689. .breadcrumbs a {
  690. color: #64748b;
  691. }
  692. .breadcrumbs a:hover {
  693. color: #1e293b;
  694. }
  695. /* Action buttons in cards */
  696. .card .btn,
  697. .card button {
  698. margin-top: 10px;
  699. }
  700. /* Select2 overrides */
  701. .select2-container--default .select2-selection--single,
  702. .select2-container--default .select2-selection--multiple {
  703. border: 1px solid #d1d5db;
  704. border-radius: 8px;
  705. min-height: 42px;
  706. }
  707. .select2-container--default .select2-selection--single:focus,
  708. .select2-container--default .select2-selection--multiple:focus {
  709. border-color: #3b82f6;
  710. box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
  711. }
  712. /* ============================================
  713. Admin List/Changelist Page Styling
  714. ============================================ */
  715. /* Results table container */
  716. #changelist {
  717. background: #fff;
  718. border-radius: 12px;
  719. border: 1px solid #e2e8f0;
  720. box-shadow: 0 1px 3px rgba(0,0,0,0.04);
  721. overflow: hidden;
  722. }
  723. /* Table styling */
  724. #result_list {
  725. width: 100%;
  726. border-collapse: collapse;
  727. font-size: 14px;
  728. }
  729. #result_list thead th {
  730. background: #f8fafc;
  731. border-bottom: 2px solid #e2e8f0;
  732. padding: 12px 16px;
  733. font-weight: 600;
  734. font-size: 13px;
  735. color: #475569;
  736. text-align: left;
  737. text-transform: uppercase;
  738. letter-spacing: 0.025em;
  739. white-space: nowrap;
  740. }
  741. #result_list thead th a {
  742. color: #475569;
  743. text-decoration: none;
  744. }
  745. #result_list thead th a:hover {
  746. color: #1e293b;
  747. }
  748. #result_list thead th.sorted {
  749. background: #f1f5f9;
  750. }
  751. #result_list thead th .text span {
  752. padding-right: 5px;
  753. }
  754. #result_list tbody tr {
  755. border-bottom: 1px solid #f1f5f9;
  756. transition: background-color 0.15s ease;
  757. }
  758. #result_list tbody tr:hover {
  759. background-color: #f8fafc;
  760. }
  761. #result_list tbody tr.selected {
  762. background-color: #eff6ff;
  763. }
  764. #result_list tbody td {
  765. padding: 12px 16px;
  766. color: #334155;
  767. vertical-align: middle;
  768. }
  769. #result_list tbody td a {
  770. color: #2563eb;
  771. font-weight: 500;
  772. }
  773. #result_list tbody td a:hover {
  774. color: #1d4ed8;
  775. text-decoration: underline;
  776. }
  777. /* Checkbox column */
  778. #result_list .action-checkbox,
  779. #result_list th.action-checkbox-column {
  780. width: 40px;
  781. text-align: center;
  782. padding: 12px 8px;
  783. }
  784. /* Pagination */
  785. .paginator {
  786. background: #f8fafc;
  787. padding: 12px 16px;
  788. border-top: 1px solid #e2e8f0;
  789. font-size: 14px;
  790. color: #64748b;
  791. }
  792. .paginator a {
  793. color: #2563eb;
  794. padding: 6px 12px;
  795. border-radius: 6px;
  796. margin: 0 2px;
  797. text-decoration: none;
  798. }
  799. .paginator a:hover {
  800. background: #e2e8f0;
  801. }
  802. /* Toolbar / search bar */
  803. #toolbar {
  804. padding: 16px;
  805. background: #fff;
  806. border-bottom: 1px solid #e2e8f0;
  807. display: flex;
  808. align-items: center;
  809. gap: 12px;
  810. }
  811. #toolbar form,
  812. #changelist-search {
  813. display: flex;
  814. align-items: center;
  815. gap: 8px;
  816. flex: 0 1 auto;
  817. max-width: 500px;
  818. }
  819. #searchbar {
  820. flex: 1;
  821. max-width: 400px;
  822. padding: 10px 14px;
  823. border: 1px solid #d1d5db;
  824. border-radius: 8px;
  825. font-size: 14px;
  826. }
  827. #searchbar:focus {
  828. border-color: #3b82f6;
  829. outline: none;
  830. box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
  831. }
  832. /* Filter sidebar */
  833. #changelist-filter {
  834. background: #fff;
  835. border: 1px solid #e2e8f0;
  836. border-radius: 12px;
  837. box-shadow: 0 1px 3px rgba(0,0,0,0.04);
  838. overflow: hidden;
  839. }
  840. #changelist-filter h2 {
  841. background: #f8fafc;
  842. padding: 12px 16px;
  843. font-size: 13px;
  844. font-weight: 600;
  845. color: #475569;
  846. text-transform: uppercase;
  847. letter-spacing: 0.025em;
  848. margin: 0;
  849. border-bottom: 1px solid #e2e8f0;
  850. }
  851. #changelist-filter h3 {
  852. padding: 12px 16px 8px;
  853. font-size: 12px;
  854. font-weight: 600;
  855. color: #64748b;
  856. text-transform: uppercase;
  857. letter-spacing: 0.05em;
  858. margin: 0;
  859. }
  860. #changelist-filter ul {
  861. padding: 0 8px 12px;
  862. margin: 0;
  863. list-style: none;
  864. }
  865. #changelist-filter li {
  866. margin: 0;
  867. }
  868. #changelist-filter li a {
  869. display: block;
  870. padding: 8px 12px;
  871. color: #475569;
  872. text-decoration: none;
  873. border-radius: 6px;
  874. font-size: 14px;
  875. transition: background-color 0.15s ease;
  876. }
  877. #changelist-filter li a:hover {
  878. background: #f1f5f9;
  879. color: #1e293b;
  880. }
  881. #changelist-filter li.selected a {
  882. background: #eff6ff;
  883. color: #2563eb;
  884. font-weight: 500;
  885. }
  886. /* Actions bar */
  887. .actions {
  888. padding: 12px 16px;
  889. background: #f8fafc;
  890. border-bottom: 1px solid #e2e8f0;
  891. display: flex;
  892. align-items: center;
  893. gap: 12px;
  894. flex-wrap: wrap;
  895. }
  896. .actions label {
  897. font-size: 14px;
  898. color: #475569;
  899. }
  900. .actions select {
  901. padding: 8px 12px;
  902. border: 1px solid #d1d5db;
  903. border-radius: 6px;
  904. font-size: 14px;
  905. background: #fff;
  906. }
  907. .actions .button {
  908. padding: 8px 16px;
  909. font-size: 14px;
  910. }
  911. /* Object count */
  912. .actions .action-counter {
  913. color: #64748b;
  914. font-size: 14px;
  915. }
  916. /* Empty results */
  917. #changelist-form .results + p,
  918. .paginator + p {
  919. padding: 40px;
  920. text-align: center;
  921. color: #64748b;
  922. font-size: 15px;
  923. }
  924. /* Date hierarchy */
  925. .xfull {
  926. padding: 12px 16px;
  927. background: #f8fafc;
  928. border-bottom: 1px solid #e2e8f0;
  929. }
  930. .xfull a {
  931. color: #2563eb;
  932. margin-right: 8px;
  933. }
  934. /* ============================================
  935. Tag Editor Widget Styles
  936. ============================================ */
  937. /* Main container - acts as input field */
  938. .tag-editor-container {
  939. display: flex;
  940. flex-wrap: wrap;
  941. align-items: center;
  942. gap: 6px;
  943. padding: 8px 12px;
  944. min-height: 42px;
  945. background: #fff;
  946. border: 1px solid #d1d5db;
  947. border-radius: 8px;
  948. cursor: text;
  949. transition: border-color 0.15s ease, box-shadow 0.15s ease;
  950. }
  951. .tag-editor-container:focus-within {
  952. border-color: #3b82f6;
  953. box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
  954. }
  955. /* Pills container */
  956. .tag-pills {
  957. display: flex;
  958. flex-wrap: wrap;
  959. gap: 6px;
  960. align-items: center;
  961. }
  962. /* Individual tag pill */
  963. .tag-pill {
  964. display: inline-flex;
  965. align-items: center;
  966. gap: 4px;
  967. padding: 4px 8px 4px 10px;
  968. background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
  969. color: #fff;
  970. font-size: 13px;
  971. font-weight: 500;
  972. border-radius: 16px;
  973. white-space: nowrap;
  974. transition: all 0.15s ease;
  975. -webkit-font-smoothing: antialiased;
  976. }
  977. .tag-pill:hover {
  978. background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
  979. }
  980. .tag-pill a.tag-link {
  981. color: #fff;
  982. text-decoration: none;
  983. }
  984. .tag-pill a.tag-link:hover {
  985. text-decoration: underline;
  986. }
  987. /* Remove button on pills */
  988. .tag-remove-btn {
  989. display: inline-flex;
  990. align-items: center;
  991. justify-content: center;
  992. width: 16px;
  993. height: 16px;
  994. padding: 0;
  995. margin: 0;
  996. background: rgba(255, 255, 255, 0.2);
  997. border: none;
  998. border-radius: 50%;
  999. color: #fff;
  1000. font-size: 14px;
  1001. font-weight: 600;
  1002. line-height: 1;
  1003. cursor: pointer;
  1004. opacity: 0.7;
  1005. transition: all 0.15s ease;
  1006. }
  1007. .tag-remove-btn:hover {
  1008. background: rgba(255, 255, 255, 0.4);
  1009. opacity: 1;
  1010. }
  1011. /* Inline input for adding tags */
  1012. .tag-inline-input {
  1013. flex: 1;
  1014. min-width: 120px;
  1015. padding: 4px 0;
  1016. border: none;
  1017. outline: none;
  1018. font-size: 14px;
  1019. font-family: inherit;
  1020. background: transparent;
  1021. color: #1e293b;
  1022. }
  1023. .tag-inline-input::placeholder {
  1024. color: #94a3b8;
  1025. }
  1026. /* Inline editor for list view - more compact */
  1027. .tag-editor-inline {
  1028. display: inline-flex;
  1029. flex-wrap: wrap;
  1030. align-items: center;
  1031. gap: 4px;
  1032. padding: 2px 4px;
  1033. background: transparent;
  1034. border-radius: 4px;
  1035. cursor: text;
  1036. vertical-align: middle;
  1037. }
  1038. .tag-pills-inline {
  1039. display: inline-flex;
  1040. flex-wrap: wrap;
  1041. gap: 4px;
  1042. align-items: center;
  1043. }
  1044. .tag-editor-inline .tag-pill {
  1045. padding: 2px 6px 2px 8px;
  1046. font-size: 11px;
  1047. border-radius: 12px;
  1048. }
  1049. .tag-editor-inline .tag-remove-btn {
  1050. width: 14px;
  1051. height: 14px;
  1052. font-size: 12px;
  1053. }
  1054. .tag-inline-input-sm {
  1055. width: 24px;
  1056. min-width: 24px;
  1057. max-width: 100px;
  1058. padding: 2px 4px;
  1059. border: none;
  1060. outline: none;
  1061. font-size: 11px;
  1062. font-family: inherit;
  1063. background: transparent;
  1064. color: #64748b;
  1065. transition: width 0.15s ease;
  1066. }
  1067. .tag-inline-input-sm:focus {
  1068. width: 80px;
  1069. color: #1e293b;
  1070. }
  1071. .tag-inline-input-sm::placeholder {
  1072. color: #94a3b8;
  1073. }
  1074. /* Container in list view title column */
  1075. .tags-inline-editor {
  1076. display: inline;
  1077. margin-left: 8px;
  1078. }
  1079. /* Existing tag styles (keep for backwards compat) */
  1080. .tags .tag {
  1081. display: inline-block;
  1082. padding: 2px 8px;
  1083. margin: 1px 2px;
  1084. background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
  1085. color: #fff;
  1086. font-size: 11px;
  1087. font-weight: 500;
  1088. border-radius: 12px;
  1089. text-decoration: none;
  1090. transition: all 0.15s ease;
  1091. }
  1092. .tags .tag:hover {
  1093. background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
  1094. }
  1095. </style>
  1096. {% endblock %}
  1097. {% if LANGUAGE_BIDI %}
  1098. <link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}">
  1099. {% endif %}
  1100. {% block responsive %}
  1101. <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
  1102. <link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive.css" %}">
  1103. {% if LANGUAGE_BIDI %}
  1104. <link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive_rtl.css" %}">
  1105. {% endif %}
  1106. {% endblock %}
  1107. <script
  1108. src="{% static 'jquery-3.7.1.slim.min.js' %}"
  1109. integrity="sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8="
  1110. crossorigin="anonymous"></script>
  1111. <link href="{% static 'select2.min.css' %}" rel="stylesheet"/>
  1112. <script src="{% static 'select2.min.js' %}"></script>
  1113. <link rel="stylesheet" type="text/css" href="{% static "admin.css" %}">
  1114. <script>
  1115. function selectSnapshotListView(e) {
  1116. e && e.stopPropagation()
  1117. e && e.preventDefault()
  1118. console.log('Switching to Snapshot list view...')
  1119. localStorage.setItem('preferred_snapshot_view_mode', 'list')
  1120. window.location = "{% url 'admin:core_snapshot_changelist' %}" + document.location.search
  1121. return false
  1122. }
  1123. function selectSnapshotGridView(e) {
  1124. e && e.stopPropagation()
  1125. e && e.preventDefault()
  1126. console.log('Switching to Snapshot grid view...')
  1127. localStorage.setItem('preferred_snapshot_view_mode', 'grid')
  1128. window.location = "{% url 'admin:grid' %}" + document.location.search
  1129. return false
  1130. }
  1131. const preferred_view = localStorage.getItem('preferred_snapshot_view_mode') || 'unset'
  1132. const current_view = (
  1133. window.location.pathname === "{% url 'admin:core_snapshot_changelist' %}"
  1134. ? 'list'
  1135. : 'grid')
  1136. console.log('Preferred snapshot view is:', preferred_view, 'Current view mode is:', current_view)
  1137. if (preferred_view === 'grid' && current_view !== 'grid') {
  1138. selectSnapshotGridView()
  1139. }
  1140. </script>
  1141. {% block extrahead %}{% endblock %}
  1142. </head>
  1143. <body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}" data-admin-utc-offset="{% now "Z" %}">
  1144. {% include 'progressbar.html' %}
  1145. <div id="container">
  1146. {% if not is_popup %}
  1147. <div id="header">
  1148. <div id="branding">
  1149. <h1 id="site-name">
  1150. <a href="{% url 'Home' %}">
  1151. <img src="{% static 'archive.png' %}" id="logo">
  1152. ArchiveBox
  1153. </a>
  1154. </h1>
  1155. </div>
  1156. {% block usertools %}
  1157. {% if has_permission %}
  1158. {% include 'navigation.html' %}
  1159. {% endif %}
  1160. {% endblock %}
  1161. {% block nav-global %}{% endblock %}
  1162. </div>
  1163. {% if has_permission %}
  1164. {% include 'admin/progress_monitor.html' %}
  1165. {% endif %}
  1166. {% block breadcrumbs %}
  1167. <div class="breadcrumbs">
  1168. <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
  1169. {% if title %} &rsaquo; {{ title }}{% endif %}
  1170. </div>
  1171. {% endblock %}
  1172. {% endif %}
  1173. {% block messages %}
  1174. {% if messages %}
  1175. <ul class="messagelist">
  1176. {% for message in messages %}
  1177. <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
  1178. {% endfor %}
  1179. </ul>
  1180. {% endif %}
  1181. {% endblock messages %}
  1182. <div id="content" class="{% block coltype %}colM{% endblock %}">
  1183. {% if opts.model_name == 'snapshot' and cl %}
  1184. <small id="snapshot-view-mode">
  1185. <a href="#list" title="List view" id="snapshot-view-list">☰</a> |
  1186. <a href="#grid" title="Grid view" id="snapshot-view-grid" style="letter-spacing: -.4em;">⣿⣿</a>
  1187. </small>
  1188. {% endif %}
  1189. {% block pretitle %}{% endblock %}
  1190. {% block content_title %}{# {% if title %}<h1>{{ title }}</h1>{% endif %} #}{% endblock %}
  1191. {% block content %}
  1192. {% block object-tools %}{% endblock %}
  1193. {{ content }}
  1194. {% endblock %}
  1195. {% block sidebar %}{% endblock %}
  1196. <br class="clear">
  1197. </div>
  1198. {% block footer %}<div id="footer"></div>{% endblock %}
  1199. </div>
  1200. {% comment %}
  1201. {% if user.is_authenticated and user.is_superuser and CAN_UPGRADE %}
  1202. <script>
  1203. if (!localStorage.getItem("bannerDismissed")) {
  1204. const upgradeVersionTag = "{{VERSIONS_AVAILABLE.recommended_version.tag_name}}"
  1205. const upgradeVersionURL = "{{VERSIONS_AVAILABLE.recommended_version.html_url}}"
  1206. const currentVersionTag = "{{VERSION}}"
  1207. const currentVersionURL = "{{VERSIONS_AVAILABLE.recommended_version.html_url}}"
  1208. createBanner(currentVersionTag, currentVersionURL, upgradeVersionTag, upgradeVersionURL)
  1209. }
  1210. function createBanner(currentVersionTag, currentVersionURL, upgradeVersionTag, upgradeVersionURL) {
  1211. const banner = document.createElement('div')
  1212. banner.setAttribute('id', 'upgrade-banner');
  1213. banner.innerHTML = `
  1214. <p>There's a new version of ArchiveBox available!</p>
  1215. Your version: <a href=${currentVersionURL}>${currentVersionTag}</a> | New version: <a href=${upgradeVersionURL}>${upgradeVersionTag}</a>
  1216. <p>
  1217. <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>
  1218. </p>
  1219. <button id="dismiss-btn">Dismiss</button>
  1220. `
  1221. document.body.appendChild(banner);
  1222. const dismissButton = document.querySelector("#dismiss-btn")
  1223. if (dismissButton) {
  1224. dismissButton.addEventListener("click", dismissBanner)
  1225. }
  1226. }
  1227. function dismissBanner() {
  1228. const banner = document.getElementById("upgrade-banner")
  1229. banner.style.display = "none"
  1230. localStorage.setItem("bannerDismissed", "true")
  1231. }
  1232. </script>
  1233. {% endif %}
  1234. {% endcomment %}
  1235. <script>
  1236. $ = django.jQuery;
  1237. $.fn.reverse = [].reverse;
  1238. // hide images that fail to load
  1239. document.querySelector('body').addEventListener('error', function (e) {
  1240. e.target.style.opacity = 0;
  1241. }, true)
  1242. // setup timezone
  1243. {% get_current_timezone as TIME_ZONE %}
  1244. window.TIME_ZONE = '{{TIME_ZONE}}'
  1245. window.setCookie = function(name, value, days) {
  1246. let expires = ""
  1247. if (days) {
  1248. const date = new Date()
  1249. date.setTime(date.getTime() + (days*24*60*60*1000))
  1250. expires = "; expires=" + date.toUTCString()
  1251. }
  1252. document.cookie = name + "=" + (value || "") + expires + "; path=/"
  1253. }
  1254. function setTimeOffset() {
  1255. if (window.GMT_OFFSET) return
  1256. window.GMT_OFFSET = -(new Date).getTimezoneOffset()
  1257. window.setCookie('GMT_OFFSET', window.GMT_OFFSET, 365)
  1258. }
  1259. // change the admin actions button from a dropdown to buttons across
  1260. function fix_actions() {
  1261. const container = $('div.actions')
  1262. // too many actions to turn into buttons
  1263. if (container.find('select[name=action] option').length >= 11) return
  1264. // hide the empty default option thats just a placeholder with no value
  1265. container.find('label:nth-child(1), button[value=0]').hide()
  1266. const buttons = $('<div></div>')
  1267. .insertAfter('div.actions button[type=submit]')
  1268. .css('display', 'inline')
  1269. .addClass('class', 'action-buttons');
  1270. // for each action in the dropdown, turn it into a button instead
  1271. container.find('select[name=action] option:gt(0)').each(function () {
  1272. const action_type = this.value
  1273. $('<button>')
  1274. .attr('type', 'button')
  1275. .attr('name', action_type)
  1276. .addClass('button')
  1277. .text(this.text)
  1278. .click(function (e) {
  1279. e.preventDefault()
  1280. e.stopPropagation()
  1281. const num_selected = document.querySelector('.action-counter').innerText.split(' ')[0]
  1282. if (action_type === 'overwrite_snapshots') {
  1283. const message = (
  1284. 'Are you sure you want to re-archive (overwrite) ' + num_selected + ' Snapshots?\n\n' +
  1285. 'This will delete all previously saved files from these Snapshots and re-archive them from scratch.\n\n'
  1286. )
  1287. if (!window.confirm(message)) return false
  1288. }
  1289. if (action_type === 'delete_snapshots') {
  1290. const message = (
  1291. 'Are you sure you want to permanently delete ' + num_selected + ' Snapshots?\n\n' +
  1292. 'They will be removed from your index, and all their Snapshot content on disk will be permanently deleted.'
  1293. )
  1294. if (!window.confirm(message)) return false
  1295. }
  1296. // select the action button from the dropdown
  1297. container.find('select[name=action]')
  1298. .find('[selected]').removeAttr('selected').end()
  1299. .find('[value=' + action_type + ']').attr('selected', 'selected').click()
  1300. // click submit & replace the archivebox logo with a spinner
  1301. $('#changelist-form button[name="index"]').click()
  1302. document.querySelector('#logo').outerHTML = '<div class="loader"></div>'
  1303. return false
  1304. })
  1305. .appendTo(buttons)
  1306. })
  1307. console.log('Converted', buttons.children().length, 'admin actions from dropdown to buttons')
  1308. jQuery('select[multiple]').select2();
  1309. }
  1310. function fixInlineAddRow() {
  1311. $('#id_snapshottag-MAX_NUM_FORMS').val('1000')
  1312. $('.add-row').show()
  1313. }
  1314. function setupSnapshotGridListToggle() {
  1315. $("#snapshot-view-list").click(selectSnapshotListView)
  1316. $("#snapshot-view-grid").click(selectSnapshotGridView)
  1317. $('#changelist-form .card input:checkbox').change(function() {
  1318. if ($(this).is(':checked'))
  1319. $(this).parents('.card').addClass('selected-card')
  1320. else
  1321. $(this).parents('.card').removeClass('selected-card')
  1322. })
  1323. };
  1324. function selectSnapshotIfHotlinked() {
  1325. // if we arrive at the index with a url like ??id__startswith=...
  1326. // we were hotlinked here with the intention of making it easy for the user to perform some
  1327. // actions on the given snapshot. therefore we should preselect the snapshot to save them a click
  1328. if (window.location.search.startsWith('?')) {
  1329. const result_checkboxes = [...document.querySelectorAll('#result_list .action-checkbox input[type=checkbox]')]
  1330. if (result_checkboxes.length === 1) {
  1331. result_checkboxes[0].click()
  1332. }
  1333. }
  1334. }
  1335. $(document).ready(function() {
  1336. fix_actions()
  1337. fixInlineAddRow()
  1338. setupSnapshotGridListToggle()
  1339. setTimeOffset()
  1340. selectSnapshotIfHotlinked()
  1341. })
  1342. </script>
  1343. </body>
  1344. </html>