Piki is a minimal wiki
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. from django.conf import settings
  2. from django.contrib import messages as django_messages
  3. from django.shortcuts import render
  4. from django.http import HttpResponse, HttpResponseRedirect
  5. from django.utils.translation import gettext as _
  6. import logging
  7. from .access import access_control
  8. from . import messages
  9. from . import url_page
  10. from . import get_search_query
  11. import config
  12. from .context import context_adaption
  13. from .forms import EditForm, RenameForm
  14. from .help import help_pages
  15. from .models import PikiPage, page_list
  16. import mycreole
  17. from .search import whoosh_search, load_index, delete_item, add_item, update_item
  18. from themes import Context
  19. logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__)
  20. SUCCESS_PAGE = _("""= Default startpage
  21. **Congratulations!!!**
  22. Seeing this page means, that you installed Piki successfull.
  23. Edit this page to get your own first startpage.
  24. If you need need assistance to edit a page, visit the [[/helpview/main|help pages]].
  25. """)
  26. def root(request):
  27. return HttpResponseRedirect(url_page(config.STARTPAGE))
  28. def page(request, rel_path):
  29. context = Context(request) # needs to be executed first because of time mesurement
  30. #
  31. try:
  32. p = PikiPage.objects.get(rel_path=rel_path)
  33. except PikiPage.DoesNotExist:
  34. p = None
  35. meta = "meta" in request.GET
  36. history = request.GET.get("history")
  37. if history:
  38. history = int(history)
  39. #
  40. title = rel_path.split("/")[-1]
  41. #
  42. acc = access_control(request, rel_path)
  43. if acc.may_read() or (p is None and rel_path == config.STARTPAGE):
  44. if p is None or p.deleted:
  45. if rel_path == config.STARTPAGE:
  46. page_content = mycreole.render_simple(SUCCESS_PAGE)
  47. else:
  48. page_content = ""
  49. if p is not None and p.deleted:
  50. messages.deleted_page(request)
  51. else:
  52. messages.unavailable_msg_page(request, rel_path)
  53. else:
  54. title = p.title
  55. if meta:
  56. page_content = p.render_meta(request, history)
  57. else:
  58. page_content = p.render_to_html(request, history)
  59. if history:
  60. messages.history_version_display(request, rel_path, history)
  61. else:
  62. messages.permission_denied_msg_page(request, rel_path)
  63. page_content = ""
  64. #
  65. context_adaption(
  66. context,
  67. request,
  68. acc=acc,
  69. rel_path=rel_path,
  70. title=title,
  71. upload_path=rel_path,
  72. page_content=page_content,
  73. is_available=p is not None and not p.deleted
  74. )
  75. return render(request, 'pages/page.html', context=context)
  76. def edit(request, rel_path):
  77. acc = access_control(request, rel_path)
  78. if acc.may_write():
  79. context = Context(request) # needs to be executed first because of time mesurement
  80. #
  81. try:
  82. p = PikiPage.objects.get(rel_path=rel_path)
  83. is_available = True
  84. except PikiPage.DoesNotExist:
  85. p = PikiPage(rel_path=rel_path)
  86. is_available = False
  87. #
  88. if not request.POST:
  89. history = request.GET.get("history")
  90. if history:
  91. history = int(history)
  92. form = EditForm(instance=p.history.get(history_id=history))
  93. else:
  94. form = EditForm(instance=p)
  95. #
  96. context_adaption(
  97. context,
  98. request,
  99. acc=acc,
  100. rel_path=rel_path,
  101. is_available=is_available,
  102. form=form,
  103. # TODO: Add translation
  104. title=_("Edit page %s") % repr(p.title),
  105. upload_path=rel_path,
  106. )
  107. return render(request, 'pages/page_edit.html', context=context)
  108. else:
  109. form = EditForm(request.POST, instance=p)
  110. #
  111. save = request.POST.get("save")
  112. preview = request.POST.get("preview")
  113. #
  114. if save is not None:
  115. if form.is_valid():
  116. form.instance.prepare_save(request)
  117. page = form.save()
  118. if page.save_needed:
  119. messages.edit_success(request)
  120. # update search index
  121. update_item(page)
  122. else:
  123. messages.no_change(request)
  124. else:
  125. messages.internal_error(request)
  126. return HttpResponseRedirect(url_page(rel_path))
  127. elif preview is not None:
  128. context_adaption(
  129. context,
  130. request,
  131. acc=acc,
  132. rel_path=rel_path,
  133. is_available=is_available,
  134. form=form,
  135. # TODO: Add translation
  136. title=_("Edit page %s") % repr(p.title),
  137. upload_path=rel_path,
  138. page_content=p.render_text(request, form.data.get("page_txt"))
  139. )
  140. return render(request, 'pages/page_edit.html', context=context)
  141. else:
  142. return HttpResponseRedirect(url_page(rel_path))
  143. else:
  144. messages.permission_denied_msg_page(request, rel_path)
  145. return HttpResponseRedirect(url_page(rel_path))
  146. def delete(request, rel_path):
  147. acc = access_control(request, rel_path)
  148. if acc.may_write():
  149. context = Context(request) # needs to be executed first because of time mesurement
  150. #
  151. try:
  152. p = PikiPage.objects.get(rel_path=rel_path)
  153. is_available = True
  154. except PikiPage.DoesNotExist:
  155. p = PikiPage(rel_path=rel_path)
  156. is_available = False
  157. #
  158. if not request.POST:
  159. #
  160. # form = DeleteForm(page_data=p.raw_page_src, page_tags=p.tags)
  161. #
  162. context_adaption(
  163. context,
  164. request,
  165. acc=acc,
  166. rel_path=rel_path,
  167. is_available=is_available,
  168. # TODO: Add translation
  169. title=_("Delete page %s") % repr(p.title),
  170. upload_path=rel_path,
  171. page_content=p.render_to_html(request),
  172. )
  173. else:
  174. delete = request.POST.get("delete")
  175. #
  176. if delete:
  177. p.deleted = True
  178. p.save()
  179. # delete page from search index
  180. ix = load_index()
  181. delete_item(ix, p)
  182. # add delete message
  183. messages.page_deleted(request, p.title)
  184. return HttpResponseRedirect("/")
  185. else:
  186. messages.operation_canceled(request)
  187. return HttpResponseRedirect(url_page(rel_path))
  188. return render(request, 'pages/page_delete.html', context=context)
  189. else:
  190. messages.permission_denied_msg_page(request, rel_path)
  191. return HttpResponseRedirect(url_page(rel_path))
  192. def rename(request, rel_path):
  193. acc = access_control(request, rel_path)
  194. if acc.may_write():
  195. context = Context(request) # needs to be executed first because of time mesurement
  196. #
  197. try:
  198. p = PikiPage.objects.get(rel_path=rel_path)
  199. is_available = True
  200. except PikiPage.DoesNotExist:
  201. p = PikiPage(rel_path=rel_path)
  202. is_available = False
  203. #
  204. if not request.POST:
  205. form = RenameForm(page_name=p.rel_path)
  206. #
  207. context_adaption(
  208. context,
  209. request,
  210. acc=acc,
  211. rel_path=rel_path,
  212. is_available=is_available,
  213. form=form,
  214. # TODO: Add translation
  215. title=_("Delete page %s") % repr(p.title),
  216. upload_path=rel_path,
  217. page_content=p.render_to_html(request),
  218. )
  219. else:
  220. rename = request.POST.get("rename")
  221. page_name = request.POST.get("page_name")
  222. if rename:
  223. if page_name == p.rel_path:
  224. messages.no_change(request)
  225. else:
  226. # delete page from search index
  227. ix = load_index()
  228. delete_item(ix, p)
  229. # rename the storage folder
  230. p.rel_path = page_name
  231. p.save()
  232. # add the renamed page to the search index
  233. add_item(ix, p)
  234. # add rename message
  235. messages.page_renamed(request)
  236. else:
  237. messages.operation_canceled(request)
  238. return HttpResponseRedirect(url_page(p.rel_path))
  239. return render(request, 'pages/page_rename.html', context=context)
  240. else:
  241. messages.permission_denied_msg_page(request, rel_path)
  242. return HttpResponseRedirect(url_page(rel_path))
  243. def search(request):
  244. context = Context(request) # needs to be executed first because of time mesurement
  245. #
  246. search_txt = get_search_query(request)
  247. sr = whoosh_search(search_txt)
  248. if sr is None:
  249. django_messages.error(request, _('Invalid search pattern: %s') % repr(search_txt))
  250. sr = []
  251. if len(sr) == 1:
  252. return HttpResponseRedirect(url_page(sr[0]))
  253. else:
  254. pl = page_list([PikiPage.objects.get(rel_path=rel_path) for rel_path in set(sr)])
  255. #
  256. context_adaption(
  257. context,
  258. request,
  259. title=_("Searchresults"),
  260. page_content=mycreole.render_simple(pl.creole_list())
  261. )
  262. return render(request, 'pages/page.html', context=context)
  263. def helpview(request, page='main'):
  264. context = Context(request) # needs to be executed first because of time mesurement
  265. page_content = help_pages[page]
  266. context_adaption(
  267. context, # the base context
  268. request, # the request object to be used in context_adaption
  269. current_help_page=page, # the current help_page to identify which taskbar entry has to be highlighted
  270. page_content=page_content, # the help content itself (template)
  271. title=_('Help') # the title for the page (template)
  272. )
  273. return render(request, 'pages/page.html', context=context)