fnschool 20250109.80531.837__py3-none-any.whl → 20251011.80531.840__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fnschool might be problematic. Click here for more details.

Files changed (276) hide show
  1. fnschoo1/__init__.py +52 -0
  2. fnschoo1/canteen/admin.py +3 -0
  3. fnschoo1/canteen/apps.py +6 -0
  4. fnschoo1/canteen/forms.py +84 -0
  5. fnschoo1/canteen/migrations/0001_initial.py +119 -0
  6. fnschoo1/canteen/migrations/0002_ingredient_is_disabled.py +20 -0
  7. fnschoo1/canteen/migrations/0003_consumption_is_disabled_alter_ingredient_is_disabled.py +23 -0
  8. fnschoo1/canteen/migrations/0004_alter_ingredient_name_category_and_more.py +66 -0
  9. fnschoo1/canteen/migrations/0005_alter_category_created_at_alter_category_name_and_more.py +41 -0
  10. fnschoo1/canteen/migrations/0006_category_is_disabled_alter_category_user_and_more.py +49 -0
  11. fnschoo1/canteen/migrations/0007_alter_consumption_amount_used_and_more.py +30 -0
  12. fnschoo1/canteen/migrations/0008_category_abbreviation_mealtype.py +67 -0
  13. fnschoo1/canteen/migrations/0009_alter_category_abbreviation_and_more.py +55 -0
  14. fnschoo1/canteen/migrations/0010_alter_consumption_options_alter_ingredient_options_and_more.py +215 -0
  15. fnschoo1/canteen/migrations/0011_category_pin_to_consumptions_top.py +23 -0
  16. fnschoo1/canteen/migrations/0012_alter_ingredient_storage_date.py +18 -0
  17. fnschoo1/canteen/models.py +179 -0
  18. fnschoo1/canteen/templates/canteen/category/create.html +17 -0
  19. fnschoo1/canteen/templates/canteen/category/delete.html +61 -0
  20. fnschoo1/canteen/templates/canteen/category/list.html +63 -0
  21. fnschoo1/canteen/templates/canteen/category/update.html +23 -0
  22. fnschoo1/canteen/templates/canteen/close.html +11 -0
  23. fnschoo1/canteen/templates/canteen/consumption/_create.html +19 -0
  24. fnschoo1/canteen/templates/canteen/consumption/create.html +456 -0
  25. fnschoo1/canteen/templates/canteen/ingredient/close.html +11 -0
  26. fnschoo1/canteen/templates/canteen/ingredient/create.html +19 -0
  27. fnschoo1/canteen/templates/canteen/ingredient/create_one.html +17 -0
  28. fnschoo1/canteen/templates/canteen/ingredient/delete.html +41 -0
  29. fnschoo1/canteen/templates/canteen/ingredient/list.html +128 -0
  30. fnschoo1/canteen/templates/canteen/ingredient/update.html +23 -0
  31. fnschoo1/canteen/templates/canteen/meal_type/create.html +17 -0
  32. fnschoo1/canteen/templates/canteen/meal_type/delete.html +56 -0
  33. fnschoo1/canteen/templates/canteen/meal_type/list.html +59 -0
  34. fnschoo1/canteen/templates/canteen/meal_type/update.html +23 -0
  35. fnschoo1/canteen/tests.py +3 -0
  36. fnschoo1/canteen/urls.py +116 -0
  37. fnschoo1/canteen/views.py +814 -0
  38. fnschoo1/canteen/workbook/generate.py +2098 -0
  39. fnschoo1/db.sqlite3 +0 -0
  40. fnschoo1/fnschool/__init__.py +13 -0
  41. fnschoo1/fnschool/asgi.py +16 -0
  42. fnschoo1/fnschool/settings.py +167 -0
  43. fnschoo1/fnschool/templatetags/fnschool_tags.py +27 -0
  44. fnschoo1/fnschool/urls.py +30 -0
  45. fnschoo1/fnschool/views.py +9 -0
  46. fnschoo1/fnschool/wsgi.py +16 -0
  47. fnschoo1/locale/en/LC_MESSAGES/django.mo +0 -0
  48. fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  49. fnschoo1/manage.py +25 -0
  50. fnschoo1/profiles/admin.py +27 -0
  51. fnschoo1/profiles/apps.py +12 -0
  52. fnschoo1/profiles/forms.py +67 -0
  53. fnschoo1/profiles/migrations/0001_initial.py +192 -0
  54. fnschoo1/profiles/migrations/0002_alter_profile_bio.py +20 -0
  55. fnschoo1/profiles/migrations/0003_alter_profile_options_alter_profile_address_and_more.py +67 -0
  56. fnschoo1/profiles/migrations/0004_profile_gender.py +26 -0
  57. fnschoo1/profiles/migrations/0005_alter_profile_gender.py +23 -0
  58. fnschoo1/profiles/models.py +60 -0
  59. fnschoo1/profiles/signals.py +20 -0
  60. fnschoo1/profiles/templates/profiles/create.html +16 -0
  61. fnschoo1/profiles/templates/profiles/detail.html +14 -0
  62. fnschoo1/profiles/templates/profiles/edit.html +12 -0
  63. fnschoo1/profiles/templates/profiles/log_in.html +20 -0
  64. fnschoo1/profiles/templates/profiles/log_out.html +12 -0
  65. fnschoo1/profiles/tests.py +3 -0
  66. fnschoo1/profiles/urls.py +15 -0
  67. fnschoo1/profiles/views.py +63 -0
  68. fnschoo1/static/css/bootstrap.min.css +11776 -0
  69. fnschoo1/static/css/fnschool.css +26 -0
  70. fnschoo1/static/js/bootstrap.bundle.min.js +4223 -0
  71. fnschoo1/static/js/bootstrap.min.js +2919 -0
  72. fnschoo1/static/js/fnschool.js +84 -0
  73. fnschoo1/static/js/jquery.min.js +5413 -0
  74. fnschoo1/static/js/jquery.slim.min.js +4331 -0
  75. fnschoo1/static/js/popper.min.js +1306 -0
  76. fnschoo1/static_collected/admin/css/autocomplete.css +377 -0
  77. fnschoo1/static_collected/admin/css/base.css +1224 -0
  78. fnschoo1/static_collected/admin/css/changelists.css +334 -0
  79. fnschoo1/static_collected/admin/css/dark_mode.css +136 -0
  80. fnschoo1/static_collected/admin/css/dashboard.css +30 -0
  81. fnschoo1/static_collected/admin/css/forms.css +546 -0
  82. fnschoo1/static_collected/admin/css/login.css +62 -0
  83. fnschoo1/static_collected/admin/css/nav_sidebar.css +145 -0
  84. fnschoo1/static_collected/admin/css/responsive.css +1043 -0
  85. fnschoo1/static_collected/admin/css/responsive_rtl.css +84 -0
  86. fnschoo1/static_collected/admin/css/rtl.css +311 -0
  87. fnschoo1/static_collected/admin/css/vendor/select2/select2.css +708 -0
  88. fnschoo1/static_collected/admin/css/vendor/select2/select2.min.css +1 -0
  89. fnschoo1/static_collected/admin/css/widgets.css +639 -0
  90. fnschoo1/static_collected/admin/js/SelectBox.js +128 -0
  91. fnschoo1/static_collected/admin/js/SelectFilter2.js +503 -0
  92. fnschoo1/static_collected/admin/js/actions.js +232 -0
  93. fnschoo1/static_collected/admin/js/admin/DateTimeShortcuts.js +496 -0
  94. fnschoo1/static_collected/admin/js/admin/RelatedObjectLookups.js +276 -0
  95. fnschoo1/static_collected/admin/js/autocomplete.js +33 -0
  96. fnschoo1/static_collected/admin/js/calendar.js +251 -0
  97. fnschoo1/static_collected/admin/js/cancel.js +29 -0
  98. fnschoo1/static_collected/admin/js/change_form.js +21 -0
  99. fnschoo1/static_collected/admin/js/collapse.js +43 -0
  100. fnschoo1/static_collected/admin/js/core.js +174 -0
  101. fnschoo1/static_collected/admin/js/filters.js +37 -0
  102. fnschoo1/static_collected/admin/js/inlines.js +439 -0
  103. fnschoo1/static_collected/admin/js/jquery.init.js +8 -0
  104. fnschoo1/static_collected/admin/js/nav_sidebar.js +81 -0
  105. fnschoo1/static_collected/admin/js/popup_response.js +24 -0
  106. fnschoo1/static_collected/admin/js/prepopulate.js +43 -0
  107. fnschoo1/static_collected/admin/js/prepopulate_init.js +20 -0
  108. fnschoo1/static_collected/admin/js/theme.js +57 -0
  109. fnschoo1/static_collected/admin/js/urlify.js +529 -0
  110. fnschoo1/static_collected/admin/js/vendor/jquery/jquery.js +10913 -0
  111. fnschoo1/static_collected/admin/js/vendor/jquery/jquery.min.js +2 -0
  112. fnschoo1/static_collected/admin/js/vendor/select2/i18n/af.js +43 -0
  113. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ar.js +36 -0
  114. fnschoo1/static_collected/admin/js/vendor/select2/i18n/az.js +33 -0
  115. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bg.js +38 -0
  116. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bn.js +39 -0
  117. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bs.js +48 -0
  118. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ca.js +41 -0
  119. fnschoo1/static_collected/admin/js/vendor/select2/i18n/cs.js +62 -0
  120. fnschoo1/static_collected/admin/js/vendor/select2/i18n/da.js +37 -0
  121. fnschoo1/static_collected/admin/js/vendor/select2/i18n/de.js +41 -0
  122. fnschoo1/static_collected/admin/js/vendor/select2/i18n/dsb.js +51 -0
  123. fnschoo1/static_collected/admin/js/vendor/select2/i18n/el.js +43 -0
  124. fnschoo1/static_collected/admin/js/vendor/select2/i18n/en.js +41 -0
  125. fnschoo1/static_collected/admin/js/vendor/select2/i18n/es.js +41 -0
  126. fnschoo1/static_collected/admin/js/vendor/select2/i18n/et.js +38 -0
  127. fnschoo1/static_collected/admin/js/vendor/select2/i18n/eu.js +45 -0
  128. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fa.js +42 -0
  129. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fi.js +42 -0
  130. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fr.js +43 -0
  131. fnschoo1/static_collected/admin/js/vendor/select2/i18n/gl.js +40 -0
  132. fnschoo1/static_collected/admin/js/vendor/select2/i18n/he.js +44 -0
  133. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hi.js +40 -0
  134. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hr.js +45 -0
  135. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hsb.js +51 -0
  136. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hu.js +44 -0
  137. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hy.js +40 -0
  138. fnschoo1/static_collected/admin/js/vendor/select2/i18n/id.js +36 -0
  139. fnschoo1/static_collected/admin/js/vendor/select2/i18n/is.js +37 -0
  140. fnschoo1/static_collected/admin/js/vendor/select2/i18n/it.js +43 -0
  141. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ja.js +40 -0
  142. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ka.js +42 -0
  143. fnschoo1/static_collected/admin/js/vendor/select2/i18n/km.js +38 -0
  144. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ko.js +42 -0
  145. fnschoo1/static_collected/admin/js/vendor/select2/i18n/lt.js +45 -0
  146. fnschoo1/static_collected/admin/js/vendor/select2/i18n/lv.js +41 -0
  147. fnschoo1/static_collected/admin/js/vendor/select2/i18n/mk.js +42 -0
  148. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ms.js +38 -0
  149. fnschoo1/static_collected/admin/js/vendor/select2/i18n/nb.js +38 -0
  150. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ne.js +44 -0
  151. fnschoo1/static_collected/admin/js/vendor/select2/i18n/nl.js +46 -0
  152. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pl.js +43 -0
  153. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ps.js +41 -0
  154. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt-BR.js +39 -0
  155. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt.js +41 -0
  156. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ro.js +43 -0
  157. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ru.js +48 -0
  158. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sk.js +61 -0
  159. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sl.js +41 -0
  160. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sq.js +43 -0
  161. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr-Cyrl.js +48 -0
  162. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr.js +48 -0
  163. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sv.js +40 -0
  164. fnschoo1/static_collected/admin/js/vendor/select2/i18n/th.js +36 -0
  165. fnschoo1/static_collected/admin/js/vendor/select2/i18n/tk.js +36 -0
  166. fnschoo1/static_collected/admin/js/vendor/select2/i18n/tr.js +40 -0
  167. fnschoo1/static_collected/admin/js/vendor/select2/i18n/uk.js +59 -0
  168. fnschoo1/static_collected/admin/js/vendor/select2/i18n/vi.js +37 -0
  169. fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-CN.js +36 -0
  170. fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-TW.js +33 -0
  171. fnschoo1/static_collected/admin/js/vendor/select2/select2.full.js +7115 -0
  172. fnschoo1/static_collected/admin/js/vendor/select2/select2.full.min.js +2 -0
  173. fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.js +4993 -0
  174. fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.min.js +160 -0
  175. fnschoo1/static_collected/css/bootstrap.min.css +11776 -0
  176. fnschoo1/static_collected/css/fnschool.css +26 -0
  177. fnschoo1/static_collected/js/bootstrap.bundle.min.js +4223 -0
  178. fnschoo1/static_collected/js/bootstrap.min.js +2919 -0
  179. fnschoo1/static_collected/js/fnschool.js +84 -0
  180. fnschoo1/static_collected/js/jquery.min.js +5413 -0
  181. fnschoo1/static_collected/js/jquery.slim.min.js +4331 -0
  182. fnschoo1/static_collected/js/popper.min.js +1306 -0
  183. fnschoo1/templates/base/_css.html +1 -0
  184. fnschoo1/templates/base/_js.html +15 -0
  185. fnschoo1/templates/base/content.html +30 -0
  186. fnschoo1/templates/base/header_content_footer.html +35 -0
  187. fnschoo1/templates/close.html +11 -0
  188. fnschoo1/templates/home.html +51 -0
  189. fnschoo1/templates/includes/_footer.html +39 -0
  190. fnschoo1/templates/includes/_header.html +77 -0
  191. fnschoo1/templates/includes/_navigation.html +0 -0
  192. fnschoo1/templates/includes/_paginator.html +27 -0
  193. fnschoo1/templates/registration/logged_out.html +0 -0
  194. fnschoo1/templates/registration/login.html +0 -0
  195. fnschool-20251011.80531.840.dist-info/METADATA +179 -0
  196. fnschool-20251011.80531.840.dist-info/RECORD +207 -0
  197. {fnschool-20250109.80531.837.dist-info → fnschool-20251011.80531.840.dist-info}/WHEEL +1 -1
  198. fnschool-20251011.80531.840.dist-info/entry_points.txt +2 -0
  199. fnschool-20251011.80531.840.dist-info/top_level.txt +1 -0
  200. fnschool/__init__.py +0 -35
  201. fnschool/__main__.py +0 -16
  202. fnschool/app.py +0 -103
  203. fnschool/canteen/__init__.py +0 -3
  204. fnschool/canteen/__main__.py +0 -3
  205. fnschool/canteen/bill.py +0 -253
  206. fnschool/canteen/canteen.py +0 -1
  207. fnschool/canteen/canteen.toml +0 -61
  208. fnschool/canteen/config.py +0 -10
  209. fnschool/canteen/consuming.py +0 -53
  210. fnschool/canteen/currency.py +0 -17
  211. fnschool/canteen/data/bill.i18n.xlsx +0 -0
  212. fnschool/canteen/data/bill.xlsx +0 -0
  213. fnschool/canteen/data/consuming.xlsx +0 -0
  214. fnschool/canteen/data/purchase_list.xlsx +0 -0
  215. fnschool/canteen/entry.py +0 -40
  216. fnschool/canteen/food.py +0 -206
  217. fnschool/canteen/food_classes.py +0 -33
  218. fnschool/canteen/food_classes.toml +0 -64
  219. fnschool/canteen/operator.py +0 -91
  220. fnschool/canteen/path.py +0 -28
  221. fnschool/canteen/spreadsheet/base.py +0 -213
  222. fnschool/canteen/spreadsheet/consuming.py +0 -310
  223. fnschool/canteen/spreadsheet/consumingsum.py +0 -76
  224. fnschool/canteen/spreadsheet/cover.py +0 -64
  225. fnschool/canteen/spreadsheet/ctspreadsheet.py +0 -351
  226. fnschool/canteen/spreadsheet/food.py +0 -680
  227. fnschool/canteen/spreadsheet/inventory.py +0 -375
  228. fnschool/canteen/spreadsheet/merging.py +0 -340
  229. fnschool/canteen/spreadsheet/preconsuming.py +0 -329
  230. fnschool/canteen/spreadsheet/purchasing.py +0 -885
  231. fnschool/canteen/spreadsheet/purchasingsum.py +0 -110
  232. fnschool/canteen/spreadsheet/spreadsheet.py +0 -363
  233. fnschool/canteen/spreadsheet/translating.py +0 -12
  234. fnschool/canteen/spreadsheet/unwarehousing.py +0 -178
  235. fnschool/canteen/spreadsheet/unwarehousingsum.py +0 -11
  236. fnschool/canteen/spreadsheet/warehousing.py +0 -360
  237. fnschool/canteen/spreadsheet/workbook.py +0 -17
  238. fnschool/canteen/test.py +0 -97
  239. fnschool/config.py +0 -48
  240. fnschool/entry.py +0 -67
  241. fnschool/exam/__init__.py +0 -8
  242. fnschool/exam/data/parental_emails.xlsx +0 -0
  243. fnschool/exam/data/score.xlsx +0 -0
  244. fnschool/exam/email.py +0 -349
  245. fnschool/exam/entry.py +0 -36
  246. fnschool/exam/language.py +0 -19
  247. fnschool/exam/path.py +0 -24
  248. fnschool/exam/score.py +0 -1191
  249. fnschool/exam/subject.py +0 -20
  250. fnschool/exam/teacher.py +0 -54
  251. fnschool/external.py +0 -89
  252. fnschool/games/__init__.py +0 -1
  253. fnschool/games/__main__.py +0 -1
  254. fnschool/games/games.py +0 -1
  255. fnschool/inoutput.py +0 -97
  256. fnschool/language.py +0 -40
  257. fnschool/locales/en_US/LC_MESSAGES/fnschool.mo +0 -0
  258. fnschool/locales/zh_CN/LC_MESSAGES/fnschool.mo +0 -0
  259. fnschool/locales/zh_HK/LC_MESSAGES/fnschool.mo +0 -0
  260. fnschool/locales/zh_SG/LC_MESSAGES/fnschool.mo +0 -0
  261. fnschool/locales/zh_TW/LC_MESSAGES/fnschool.mo +0 -0
  262. fnschool/path.py +0 -45
  263. fnschool/test.py +0 -24
  264. fnschool/user.py +0 -262
  265. fnschool-20250109.80531.837.dist-info/METADATA +0 -342
  266. fnschool-20250109.80531.837.dist-info/RECORD +0 -78
  267. fnschool-20250109.80531.837.dist-info/entry_points.txt +0 -5
  268. fnschool-20250109.80531.837.dist-info/top_level.txt +0 -1
  269. /fnschool/canteen/consume.py → /fnschoo1/canteen/__init__.py +0 -0
  270. /fnschool/canteen/food_recount.toml → /fnschoo1/canteen/migrations/__init__.py +0 -0
  271. {fnschool/canteen/spreadsheet → fnschoo1/canteen/workbook}/__init__.py +0 -0
  272. /fnschool/exam/__main__.py → /fnschoo1/fnschool/templatetags/__init__.py +0 -0
  273. /fnschool/canteen/food_recounts.toml → /fnschoo1/profiles/__init__.py +0 -0
  274. /fnschool/canteen/warehouse.py → /fnschoo1/profiles/migrations/__init__.py +0 -0
  275. /fnschool/canteen/workbook.toml → /fnschoo1/templates/base/_content.html +0 -0
  276. {fnschool-20250109.80531.837.dist-info → fnschool-20251011.80531.840.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,276 @@
1
+ /*global SelectBox, interpolate*/
2
+ // Handles related-objects functionality: lookup link for raw_id_fields
3
+ // and Add Another links.
4
+ 'use strict'
5
+ {
6
+ const $ = django.jQuery
7
+ let popupIndex = 0
8
+ const relatedWindows = []
9
+
10
+ function dismissChildPopups() {
11
+ relatedWindows.forEach(function (win) {
12
+ if (!win.closed) {
13
+ win.dismissChildPopups()
14
+ win.close()
15
+ }
16
+ })
17
+ }
18
+
19
+ function setPopupIndex() {
20
+ if (document.getElementsByName('_popup').length > 0) {
21
+ const index = window.name.lastIndexOf('__') + 2
22
+ popupIndex = parseInt(window.name.substring(index))
23
+ } else {
24
+ popupIndex = 0
25
+ }
26
+ }
27
+
28
+ function addPopupIndex(name) {
29
+ return name + '__' + (popupIndex + 1)
30
+ }
31
+
32
+ function removePopupIndex(name) {
33
+ return name.replace(new RegExp('__' + (popupIndex + 1) + '$'), '')
34
+ }
35
+
36
+ function showAdminPopup(triggeringLink, name_regexp, add_popup) {
37
+ const name = addPopupIndex(triggeringLink.id.replace(name_regexp, ''))
38
+ const href = new URL(triggeringLink.href)
39
+ if (add_popup) {
40
+ href.searchParams.set('_popup', 1)
41
+ }
42
+ const win = window.open(
43
+ href,
44
+ name,
45
+ 'height=500,width=800,resizable=yes,scrollbars=yes'
46
+ )
47
+ relatedWindows.push(win)
48
+ win.focus()
49
+ return false
50
+ }
51
+
52
+ function showRelatedObjectLookupPopup(triggeringLink) {
53
+ return showAdminPopup(triggeringLink, /^lookup_/, true)
54
+ }
55
+
56
+ function dismissRelatedLookupPopup(win, chosenId) {
57
+ const name = removePopupIndex(win.name)
58
+ const elem = document.getElementById(name)
59
+ if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) {
60
+ elem.value += ',' + chosenId
61
+ } else {
62
+ document.getElementById(name).value = chosenId
63
+ }
64
+ const index = relatedWindows.indexOf(win)
65
+ if (index > -1) {
66
+ relatedWindows.splice(index, 1)
67
+ }
68
+ win.close()
69
+ }
70
+
71
+ function showRelatedObjectPopup(triggeringLink) {
72
+ return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false)
73
+ }
74
+
75
+ function updateRelatedObjectLinks(triggeringLink) {
76
+ const $this = $(triggeringLink)
77
+ const siblings = $this.nextAll(
78
+ '.view-related, .change-related, .delete-related'
79
+ )
80
+ if (!siblings.length) {
81
+ return
82
+ }
83
+ const value = $this.val()
84
+ if (value) {
85
+ siblings.each(function () {
86
+ const elm = $(this)
87
+ elm.attr(
88
+ 'href',
89
+ elm.attr('data-href-template').replace('__fk__', value)
90
+ )
91
+ })
92
+ } else {
93
+ siblings.removeAttr('href')
94
+ }
95
+ }
96
+
97
+ function updateRelatedSelectsOptions(
98
+ currentSelect,
99
+ win,
100
+ objId,
101
+ newRepr,
102
+ newId
103
+ ) {
104
+ // After create/edit a model from the options next to the current
105
+ // select (+ or :pencil:) update ForeignKey PK of the rest of selects
106
+ // in the page.
107
+
108
+ const path = win.location.pathname
109
+ // Extract the model from the popup url '.../<model>/add/' or
110
+ // '.../<model>/<id>/change/' depending the action (add or change).
111
+ const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)]
112
+ // Exclude autocomplete selects.
113
+ const selectsRelated = document.querySelectorAll(
114
+ `[data-model-ref="${modelName}"] select:not(.admin-autocomplete)`
115
+ )
116
+
117
+ selectsRelated.forEach(function (select) {
118
+ if (currentSelect === select) {
119
+ return
120
+ }
121
+
122
+ let option = select.querySelector(`option[value="${objId}"]`)
123
+
124
+ if (!option) {
125
+ option = new Option(newRepr, newId)
126
+ select.options.add(option)
127
+ return
128
+ }
129
+
130
+ option.textContent = newRepr
131
+ option.value = newId
132
+ })
133
+ }
134
+
135
+ function dismissAddRelatedObjectPopup(win, newId, newRepr) {
136
+ const name = removePopupIndex(win.name)
137
+ const elem = document.getElementById(name)
138
+ if (elem) {
139
+ const elemName = elem.nodeName.toUpperCase()
140
+ if (elemName === 'SELECT') {
141
+ elem.options[elem.options.length] = new Option(
142
+ newRepr,
143
+ newId,
144
+ true,
145
+ true
146
+ )
147
+ updateRelatedSelectsOptions(elem, win, null, newRepr, newId)
148
+ } else if (elemName === 'INPUT') {
149
+ if (
150
+ elem.classList.contains('vManyToManyRawIdAdminField') &&
151
+ elem.value
152
+ ) {
153
+ elem.value += ',' + newId
154
+ } else {
155
+ elem.value = newId
156
+ }
157
+ }
158
+ // Trigger a change event to update related links if required.
159
+ $(elem).trigger('change')
160
+ } else {
161
+ const toId = name + '_to'
162
+ const o = new Option(newRepr, newId)
163
+ SelectBox.add_to_cache(toId, o)
164
+ SelectBox.redisplay(toId)
165
+ }
166
+ const index = relatedWindows.indexOf(win)
167
+ if (index > -1) {
168
+ relatedWindows.splice(index, 1)
169
+ }
170
+ win.close()
171
+ }
172
+
173
+ function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
174
+ const id = removePopupIndex(win.name.replace(/^edit_/, ''))
175
+ const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id])
176
+ const selects = $(selectsSelector)
177
+ selects
178
+ .find('option')
179
+ .each(function () {
180
+ if (this.value === objId) {
181
+ this.textContent = newRepr
182
+ this.value = newId
183
+ }
184
+ })
185
+ .trigger('change')
186
+ updateRelatedSelectsOptions(selects[0], win, objId, newRepr, newId)
187
+ selects
188
+ .next()
189
+ .find('.select2-selection__rendered')
190
+ .each(function () {
191
+ // The element can have a clear button as a child.
192
+ // Use the lastChild to modify only the displayed value.
193
+ this.lastChild.textContent = newRepr
194
+ this.title = newRepr
195
+ })
196
+ const index = relatedWindows.indexOf(win)
197
+ if (index > -1) {
198
+ relatedWindows.splice(index, 1)
199
+ }
200
+ win.close()
201
+ }
202
+
203
+ function dismissDeleteRelatedObjectPopup(win, objId) {
204
+ const id = removePopupIndex(win.name.replace(/^delete_/, ''))
205
+ const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id])
206
+ const selects = $(selectsSelector)
207
+ selects
208
+ .find('option')
209
+ .each(function () {
210
+ if (this.value === objId) {
211
+ $(this).remove()
212
+ }
213
+ })
214
+ .trigger('change')
215
+ const index = relatedWindows.indexOf(win)
216
+ if (index > -1) {
217
+ relatedWindows.splice(index, 1)
218
+ }
219
+ win.close()
220
+ }
221
+
222
+ window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup
223
+ window.dismissRelatedLookupPopup = dismissRelatedLookupPopup
224
+ window.showRelatedObjectPopup = showRelatedObjectPopup
225
+ window.updateRelatedObjectLinks = updateRelatedObjectLinks
226
+ window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup
227
+ window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup
228
+ window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup
229
+ window.dismissChildPopups = dismissChildPopups
230
+
231
+ // Kept for backward compatibility
232
+ window.showAddAnotherPopup = showRelatedObjectPopup
233
+ window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup
234
+
235
+ window.addEventListener('unload', function (evt) {
236
+ window.dismissChildPopups()
237
+ })
238
+
239
+ $(document).ready(function () {
240
+ setPopupIndex()
241
+ $('a[data-popup-opener]').on('click', function (event) {
242
+ event.preventDefault()
243
+ opener.dismissRelatedLookupPopup(window, $(this).data('popup-opener'))
244
+ })
245
+ $('body').on(
246
+ 'click',
247
+ '.related-widget-wrapper-link[data-popup="yes"]',
248
+ function (e) {
249
+ e.preventDefault()
250
+ if (this.href) {
251
+ const event = $.Event('django:show-related', { href: this.href })
252
+ $(this).trigger(event)
253
+ if (!event.isDefaultPrevented()) {
254
+ showRelatedObjectPopup(this)
255
+ }
256
+ }
257
+ }
258
+ )
259
+ $('body').on('change', '.related-widget-wrapper select', function (e) {
260
+ const event = $.Event('django:update-related')
261
+ $(this).trigger(event)
262
+ if (!event.isDefaultPrevented()) {
263
+ updateRelatedObjectLinks(this)
264
+ }
265
+ })
266
+ $('.related-widget-wrapper select').trigger('change')
267
+ $('body').on('click', '.related-lookup', function (e) {
268
+ e.preventDefault()
269
+ const event = $.Event('django:lookup-related')
270
+ $(this).trigger(event)
271
+ if (!event.isDefaultPrevented()) {
272
+ showRelatedObjectLookupPopup(this)
273
+ }
274
+ })
275
+ })
276
+ }
@@ -0,0 +1,33 @@
1
+ 'use strict'
2
+ {
3
+ const $ = django.jQuery
4
+
5
+ $.fn.djangoAdminSelect2 = function () {
6
+ $.each(this, function (i, element) {
7
+ $(element).select2({
8
+ ajax: {
9
+ data: (params) => {
10
+ return {
11
+ term: params.term,
12
+ page: params.page,
13
+ app_label: element.dataset.appLabel,
14
+ model_name: element.dataset.modelName,
15
+ field_name: element.dataset.fieldName,
16
+ }
17
+ },
18
+ },
19
+ })
20
+ })
21
+ return this
22
+ }
23
+
24
+ $(function () {
25
+ // Initialize all autocomplete widgets except the one in the template
26
+ // form used when a new formset is added.
27
+ $('.admin-autocomplete').not('[name*=__prefix__]').djangoAdminSelect2()
28
+ })
29
+
30
+ document.addEventListener('formset:added', (event) => {
31
+ $(event.target).find('.admin-autocomplete').djangoAdminSelect2()
32
+ })
33
+ }
@@ -0,0 +1,251 @@
1
+ /*global gettext, pgettext, get_format, quickElement, removeChildren*/
2
+ /*
3
+ calendar.js - Calendar functions by Adrian Holovaty
4
+ depends on core.js for utility functions like removeChildren or quickElement
5
+ */
6
+ 'use strict'
7
+ {
8
+ // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
9
+ const CalendarNamespace = {
10
+ monthsOfYear: [
11
+ gettext('January'),
12
+ gettext('February'),
13
+ gettext('March'),
14
+ gettext('April'),
15
+ gettext('May'),
16
+ gettext('June'),
17
+ gettext('July'),
18
+ gettext('August'),
19
+ gettext('September'),
20
+ gettext('October'),
21
+ gettext('November'),
22
+ gettext('December'),
23
+ ],
24
+ monthsOfYearAbbrev: [
25
+ pgettext('abbrev. month January', 'Jan'),
26
+ pgettext('abbrev. month February', 'Feb'),
27
+ pgettext('abbrev. month March', 'Mar'),
28
+ pgettext('abbrev. month April', 'Apr'),
29
+ pgettext('abbrev. month May', 'May'),
30
+ pgettext('abbrev. month June', 'Jun'),
31
+ pgettext('abbrev. month July', 'Jul'),
32
+ pgettext('abbrev. month August', 'Aug'),
33
+ pgettext('abbrev. month September', 'Sep'),
34
+ pgettext('abbrev. month October', 'Oct'),
35
+ pgettext('abbrev. month November', 'Nov'),
36
+ pgettext('abbrev. month December', 'Dec'),
37
+ ],
38
+ daysOfWeek: [
39
+ pgettext('one letter Sunday', 'S'),
40
+ pgettext('one letter Monday', 'M'),
41
+ pgettext('one letter Tuesday', 'T'),
42
+ pgettext('one letter Wednesday', 'W'),
43
+ pgettext('one letter Thursday', 'T'),
44
+ pgettext('one letter Friday', 'F'),
45
+ pgettext('one letter Saturday', 'S'),
46
+ ],
47
+ firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')),
48
+ isLeapYear: function (year) {
49
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
50
+ },
51
+ getDaysInMonth: function (month, year) {
52
+ let days
53
+ if (
54
+ month === 1 ||
55
+ month === 3 ||
56
+ month === 5 ||
57
+ month === 7 ||
58
+ month === 8 ||
59
+ month === 10 ||
60
+ month === 12
61
+ ) {
62
+ days = 31
63
+ } else if (month === 4 || month === 6 || month === 9 || month === 11) {
64
+ days = 30
65
+ } else if (month === 2 && CalendarNamespace.isLeapYear(year)) {
66
+ days = 29
67
+ } else {
68
+ days = 28
69
+ }
70
+ return days
71
+ },
72
+ draw: function (month, year, div_id, callback, selected) {
73
+ // month = 1-12, year = 1-9999
74
+ const today = new Date()
75
+ const todayDay = today.getDate()
76
+ const todayMonth = today.getMonth() + 1
77
+ const todayYear = today.getFullYear()
78
+ let todayClass = ''
79
+
80
+ // Use UTC functions here because the date field does not contain time
81
+ // and using the UTC function variants prevent the local time offset
82
+ // from altering the date, specifically the day field. For example:
83
+ //
84
+ // ```
85
+ // var x = new Date('2013-10-02');
86
+ // var day = x.getDate();
87
+ // ```
88
+ //
89
+ // The day variable above will be 1 instead of 2 in, say, US Pacific time
90
+ // zone.
91
+ let isSelectedMonth = false
92
+ if (typeof selected !== 'undefined') {
93
+ isSelectedMonth =
94
+ selected.getUTCFullYear() === year &&
95
+ selected.getUTCMonth() + 1 === month
96
+ }
97
+
98
+ month = parseInt(month)
99
+ year = parseInt(year)
100
+ const calDiv = document.getElementById(div_id)
101
+ removeChildren(calDiv)
102
+ const calTable = document.createElement('table')
103
+ quickElement(
104
+ 'caption',
105
+ calTable,
106
+ CalendarNamespace.monthsOfYear[month - 1] + ' ' + year
107
+ )
108
+ const tableBody = quickElement('tbody', calTable)
109
+
110
+ // Draw days-of-week header
111
+ let tableRow = quickElement('tr', tableBody)
112
+ for (let i = 0; i < 7; i++) {
113
+ quickElement(
114
+ 'th',
115
+ tableRow,
116
+ CalendarNamespace.daysOfWeek[
117
+ (i + CalendarNamespace.firstDayOfWeek) % 7
118
+ ]
119
+ )
120
+ }
121
+
122
+ const startingPos = new Date(
123
+ year,
124
+ month - 1,
125
+ 1 - CalendarNamespace.firstDayOfWeek
126
+ ).getDay()
127
+ const days = CalendarNamespace.getDaysInMonth(month, year)
128
+
129
+ let nonDayCell
130
+
131
+ // Draw blanks before first of month
132
+ tableRow = quickElement('tr', tableBody)
133
+ for (let i = 0; i < startingPos; i++) {
134
+ nonDayCell = quickElement('td', tableRow, ' ')
135
+ nonDayCell.className = 'nonday'
136
+ }
137
+
138
+ function calendarMonth(y, m) {
139
+ function onClick(e) {
140
+ e.preventDefault()
141
+ callback(y, m, this.textContent)
142
+ }
143
+ return onClick
144
+ }
145
+
146
+ // Draw days of month
147
+ let currentDay = 1
148
+ for (let i = startingPos; currentDay <= days; i++) {
149
+ if (i % 7 === 0 && currentDay !== 1) {
150
+ tableRow = quickElement('tr', tableBody)
151
+ }
152
+ if (
153
+ currentDay === todayDay &&
154
+ month === todayMonth &&
155
+ year === todayYear
156
+ ) {
157
+ todayClass = 'today'
158
+ } else {
159
+ todayClass = ''
160
+ }
161
+
162
+ // use UTC function; see above for explanation.
163
+ if (isSelectedMonth && currentDay === selected.getUTCDate()) {
164
+ if (todayClass !== '') {
165
+ todayClass += ' '
166
+ }
167
+ todayClass += 'selected'
168
+ }
169
+
170
+ const cell = quickElement('td', tableRow, '', 'class', todayClass)
171
+ const link = quickElement('a', cell, currentDay, 'href', '#')
172
+ link.addEventListener('click', calendarMonth(year, month))
173
+ currentDay++
174
+ }
175
+
176
+ // Draw blanks after end of month (optional, but makes for valid code)
177
+ while (tableRow.childNodes.length < 7) {
178
+ nonDayCell = quickElement('td', tableRow, ' ')
179
+ nonDayCell.className = 'nonday'
180
+ }
181
+
182
+ calDiv.appendChild(calTable)
183
+ },
184
+ }
185
+
186
+ // Calendar -- A calendar instance
187
+ function Calendar(div_id, callback, selected) {
188
+ // div_id (string) is the ID of the element in which the calendar will
189
+ // be displayed
190
+ // callback (string) is the name of a JavaScript function that will be
191
+ // called with the parameters (year, month, day) when a day in the
192
+ // calendar is clicked
193
+ this.div_id = div_id
194
+ this.callback = callback
195
+ this.today = new Date()
196
+ this.currentMonth = this.today.getMonth() + 1
197
+ this.currentYear = this.today.getFullYear()
198
+ if (typeof selected !== 'undefined') {
199
+ this.selected = selected
200
+ }
201
+ }
202
+ Calendar.prototype = {
203
+ drawCurrent: function () {
204
+ CalendarNamespace.draw(
205
+ this.currentMonth,
206
+ this.currentYear,
207
+ this.div_id,
208
+ this.callback,
209
+ this.selected
210
+ )
211
+ },
212
+ drawDate: function (month, year, selected) {
213
+ this.currentMonth = month
214
+ this.currentYear = year
215
+
216
+ if (selected) {
217
+ this.selected = selected
218
+ }
219
+
220
+ this.drawCurrent()
221
+ },
222
+ drawPreviousMonth: function () {
223
+ if (this.currentMonth === 1) {
224
+ this.currentMonth = 12
225
+ this.currentYear--
226
+ } else {
227
+ this.currentMonth--
228
+ }
229
+ this.drawCurrent()
230
+ },
231
+ drawNextMonth: function () {
232
+ if (this.currentMonth === 12) {
233
+ this.currentMonth = 1
234
+ this.currentYear++
235
+ } else {
236
+ this.currentMonth++
237
+ }
238
+ this.drawCurrent()
239
+ },
240
+ drawPreviousYear: function () {
241
+ this.currentYear--
242
+ this.drawCurrent()
243
+ },
244
+ drawNextYear: function () {
245
+ this.currentYear++
246
+ this.drawCurrent()
247
+ },
248
+ }
249
+ window.Calendar = Calendar
250
+ window.CalendarNamespace = CalendarNamespace
251
+ }
@@ -0,0 +1,29 @@
1
+ 'use strict'
2
+ {
3
+ // Call function fn when the DOM is loaded and ready. If it is already
4
+ // loaded, call the function now.
5
+ // http://youmightnotneedjquery.com/#ready
6
+ function ready(fn) {
7
+ if (document.readyState !== 'loading') {
8
+ fn()
9
+ } else {
10
+ document.addEventListener('DOMContentLoaded', fn)
11
+ }
12
+ }
13
+
14
+ ready(function () {
15
+ function handleClick(event) {
16
+ event.preventDefault()
17
+ const params = new URLSearchParams(window.location.search)
18
+ if (params.has('_popup')) {
19
+ window.close() // Close the popup.
20
+ } else {
21
+ window.history.back() // Otherwise, go back.
22
+ }
23
+ }
24
+
25
+ document.querySelectorAll('.cancel-link').forEach(function (el) {
26
+ el.addEventListener('click', handleClick)
27
+ })
28
+ })
29
+ }
@@ -0,0 +1,21 @@
1
+ 'use strict'
2
+ {
3
+ const inputTags = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA']
4
+ const modelName = document.getElementById('django-admin-form-add-constants')
5
+ .dataset.modelName
6
+ if (modelName) {
7
+ const form = document.getElementById(modelName + '_form')
8
+ for (const element of form.elements) {
9
+ // HTMLElement.offsetParent returns null when the element is not
10
+ // rendered.
11
+ if (
12
+ inputTags.includes(element.tagName) &&
13
+ !element.disabled &&
14
+ element.offsetParent
15
+ ) {
16
+ element.focus()
17
+ break
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,43 @@
1
+ /*global gettext*/
2
+ 'use strict'
3
+ {
4
+ window.addEventListener('load', function () {
5
+ // Add anchor tag for Show/Hide link
6
+ const fieldsets = document.querySelectorAll('fieldset.collapse')
7
+ for (const [i, elem] of fieldsets.entries()) {
8
+ // Don't hide if fields in this fieldset have errors
9
+ if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) {
10
+ elem.classList.add('collapsed')
11
+ const h2 = elem.querySelector('h2')
12
+ const link = document.createElement('a')
13
+ link.id = 'fieldsetcollapser' + i
14
+ link.className = 'collapse-toggle'
15
+ link.href = '#'
16
+ link.textContent = gettext('Show')
17
+ h2.appendChild(document.createTextNode(' ('))
18
+ h2.appendChild(link)
19
+ h2.appendChild(document.createTextNode(')'))
20
+ }
21
+ }
22
+ // Add toggle to hide/show anchor tag
23
+ const toggleFunc = function (ev) {
24
+ if (ev.target.matches('.collapse-toggle')) {
25
+ ev.preventDefault()
26
+ ev.stopPropagation()
27
+ const fieldset = ev.target.closest('fieldset')
28
+ if (fieldset.classList.contains('collapsed')) {
29
+ // Show
30
+ ev.target.textContent = gettext('Hide')
31
+ fieldset.classList.remove('collapsed')
32
+ } else {
33
+ // Hide
34
+ ev.target.textContent = gettext('Show')
35
+ fieldset.classList.add('collapsed')
36
+ }
37
+ }
38
+ }
39
+ document.querySelectorAll('fieldset.module').forEach(function (el) {
40
+ el.addEventListener('click', toggleFunc)
41
+ })
42
+ })
43
+ }