diff --git a/data/system-pages/tree/meta.json b/data/system-pages/tree/meta.json new file mode 100644 index 0000000..4f1c725 --- /dev/null +++ b/data/system-pages/tree/meta.json @@ -0,0 +1,5 @@ +{ + "modified_time": 1729022206, + "modified_user": "system-page", + "creation_time": 1729022206 +} diff --git a/data/system-pages/tree/page b/data/system-pages/tree/page new file mode 100644 index 0000000..e721642 --- /dev/null +++ b/data/system-pages/tree/page @@ -0,0 +1,2 @@ += Tree +<> diff --git a/pages/__init__.py b/pages/__init__.py index 5b581da..cd5e624 100644 --- a/pages/__init__.py +++ b/pages/__init__.py @@ -10,15 +10,15 @@ def params(**kwargs): return params -def url_page(request, rel_path, **kwargs): +def url_page(rel_path, **kwargs): return reverse('page-page', kwargs={'rel_path': rel_path}) + params(**kwargs) -def url_helpview(request, page): +def url_helpview(page): return reverse('page-helpview', kwargs={'page': page}) -def url_edit(request, rel_path, **kwargs): +def url_edit(rel_path, **kwargs): return reverse('page-edit', kwargs={'rel_path': rel_path}) + params(**kwargs) diff --git a/pages/context.py b/pages/context.py index 00a87d0..55a56b7 100644 --- a/pages/context.py +++ b/pages/context.py @@ -20,6 +20,7 @@ BACK_UID = 'back' EDIT_UID = 'edit' HELP_UID = 'help' INDEX_UID = 'index' +TREE_UID = 'tree' NAVIGATION_ENTRY_UID = 'navigation-%s' @@ -65,7 +66,7 @@ def menubar(context, request, caller_name, **kwargs): if not cms_mode_active(request): menubar_users(bar, request) add_help_menu(request, bar, "current_help_page" in kwargs) - add_index_menu(request, bar, kwargs.get("rel_path", '')) + add_nav_links(request, bar, kwargs.get("rel_path", '')) finalise_bar(request, bar) @@ -100,7 +101,7 @@ def navigation_entry_parameters(request, path): NAVIGATION_ENTRY_UID % os.path.basename(path), # uid '/' + os.path.basename(path), # name None, # icon - pages.url_page(request, path), # url + pages.url_page(path), # url False, # left False # active ) @@ -111,21 +112,29 @@ def add_help_menu(request, bar, active): HELP_UID, # uid _('Help'), # name color_icon_url(request, 'help.png'), # icon - pages.url_helpview(request, 'main'), # url + pages.url_helpview('main'), # url True, # left active # active ) -def add_index_menu(request, bar, rel_path): +def add_nav_links(request, bar, rel_path): bar.append_entry( INDEX_UID, # uid _('Index'), # name color_icon_url(request, 'edit.png'), # icon - pages.url_page(request, 'index'), # url + pages.url_page('index'), # url True, # left request.path == "/page/index" # active ) + bar.append_entry( + TREE_UID, # uid + _('Tree'), # name + color_icon_url(request, 'tree.png'), # icon + pages.url_page('tree'), # url + True, # left + request.path == "/page/tree" # active + ) def add_edit_menu(request, bar, rel_path): @@ -133,7 +142,7 @@ def add_edit_menu(request, bar, rel_path): EDIT_UID, # uid _('Edit'), # name color_icon_url(request, 'edit2.png'), # icon - pages.url_edit(request, rel_path), # url + pages.url_edit(rel_path), # url True, # left False # active ) @@ -156,7 +165,7 @@ def add_meta_menu(request, bar, rel_path): EDIT_UID, # uid _('Page'), # name color_icon_url(request, 'display.png'), # icon - pages.url_page(request, rel_path), # url + pages.url_page(rel_path), # url True, # left False # active ) @@ -165,7 +174,7 @@ def add_meta_menu(request, bar, rel_path): EDIT_UID, # uid _('Meta'), # name color_icon_url(request, 'info.png'), # icon - pages.url_page(request, rel_path, meta=None), # url + pages.url_page(rel_path, meta=None), # url True, # left False # active ) diff --git a/pages/help.py b/pages/help.py index 1fd9e6c..1c3ceec 100644 --- a/pages/help.py +++ b/pages/help.py @@ -131,7 +131,7 @@ def actionbar(context, request, current_help_page=None, **kwargs): HELP_UID + '-%s' % name.lower(), # uid _(name), # name color_icon_url(request, num + '.png'), # icon - pages.url_helpview(request, name.lower()), # url + pages.url_helpview(name.lower()), # url True, # left name.lower() == current_help_page, # active ) diff --git a/pages/page.py b/pages/page.py index 5499ecf..9c04a1c 100644 --- a/pages/page.py +++ b/pages/page.py @@ -22,6 +22,7 @@ def full_path_all_pages(expression="*"): system_pages = fstools.dirlist(settings.SYSTEM_PAGES_ROOT, expression=expression, rekursive=False) system_pages = [os.path.join(settings.PAGES_ROOT, os.path.basename(path)) for path in system_pages] pages = fstools.dirlist(settings.PAGES_ROOT, expression=expression, rekursive=False) + # TODO: strip path, if page or meta.json is missing return list(set(system_pages + pages)) @@ -197,15 +198,15 @@ class page_django(page_data): name = _("Current") meta += f"| {name} \ | {timestamp_to_datetime(self._request, mtime)} \ - | [[{url_page(self._request, self.rel_path)} | Page]] \ - | [[{url_page(self._request, self.rel_path, meta=None)} | Meta]]\n" + | [[{url_page(self.rel_path)} | Page]] \ + | [[{url_page(self.rel_path, meta=None)} | Meta]]\n" # History for num in reversed(hnl): p = page_wrapped(self._request, self._path, history_version=num) meta += f"| {num} \ | {timestamp_to_datetime(self._request, p.modified_time)} \ - | [[{url_page(self._request, p.rel_path, history=num)} | Page]] \ - | [[{url_page(self._request, p.rel_path, meta=None, history=num)} | Meta]] (with page changes)\n" + | [[{url_page(p.rel_path, history=num)} | Page]] \ + | [[{url_page(p.rel_path, meta=None, history=num)} | Meta]] (with page changes)\n" # Diff html_diff = "" if self._history_version: @@ -222,6 +223,8 @@ class page_django(page_data): macros = { "subpages": self.macro_subpages, "allpages": self.macro_allpages, + "subpagetree": self.macro_subpagetree, + "allpagestree": self.macro_allpagestree, } return mycreole.render(request, txt, self.attachment_path, macros=macros) @@ -231,6 +234,7 @@ class page_django(page_data): def macro_subpages(self, *args, **kwargs): allpages = kwargs.pop("allpages", False) + tree = kwargs.pop("tree", False) # def parse_depth(s: str): @@ -263,7 +267,19 @@ class page_django(page_data): self._request, [page_django(self._request, path) for path in full_path_all_pages(expression)] ) - return pl.html_list(depth=depth, filter_str=filter_str, parent_rel_path=parent_rel_path) + if tree: + return page_tree(pl).html() + else: + return pl.html_list(depth=depth, filter_str=filter_str, parent_rel_path=parent_rel_path) + + def macro_allpagestree(self, *args, **kwargs): + kwargs["allpages"] = True + kwargs["tree"] = True + return self.macro_subpages(*args, **kwargs) + + def macro_subpagetree(self, * args, **kwargs): + kwargs["tree"] = True + return self.macro_subpages(*args, **kwargs) class page_list(list): @@ -290,13 +306,50 @@ class page_list(list): if last_char != first_char: last_char = first_char rv += f"=== {first_char}\n" - rv += f"* [[{url_page(self._request, page.rel_path)} | {name} ]]\n" + rv += f"* [[{url_page(page.rel_path)} | {name} ]]\n" return rv def html_list(self, depth=9999, filter_str='', parent_rel_path=''): return mycreole.render_simple(self.creole_list(depth, filter_str, parent_rel_path)) +class page_tree(dict): + T_PATTERN = "├── " + L_PATTERN = "└── " + I_PATTERN = "│   " + D_PATTERN = "      " + + def __init__(self, pl: page_list): + super().__init__() + for page in pl: + store_item = self + for entry in page.rel_path.split("/"): + if not entry in store_item: + store_item[entry] = {} + store_item = store_item[entry] + + def html(self, rel_path=None, fill=""): + base = self + try: + for key in rel_path.split("/"): + base = base[key] + except AttributeError: + rel_path = '' + # + rv = "" + # + l = len(base) + for entry in sorted(list(base.keys())): + l -= 1 + page_path = os.path.join(rel_path, entry) + page = page_wrapped(None, page_path) + if page.is_available(): + entry = f'{entry}' + rv += fill + (self.L_PATTERN if l == 0 else self.T_PATTERN) + entry + "
\n" + rv += self.html(page_path, fill=fill+(self.D_PATTERN if l == 0 else self.I_PATTERN)) + return rv + + class page_wrapped(object): """ This class holds different page and meta instances and decides which will be used in which case. @@ -395,6 +448,9 @@ class page_wrapped(object): rv = page.attachment_path return rv + def is_available(self): + return self._page.is_available() or self._system_page.is_available() + @property def raw_page_src(self): page = self.__page_choose__() diff --git a/pages/views.py b/pages/views.py index 7186c99..287f7a8 100644 --- a/pages/views.py +++ b/pages/views.py @@ -23,7 +23,7 @@ logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__) def root(request): - return HttpResponseRedirect(url_page(request, config.STARTPAGE)) + return HttpResponseRedirect(url_page(config.STARTPAGE)) def page(request, rel_path): @@ -92,7 +92,7 @@ def edit(request, rel_path): messages.edit_success(request) else: messages.edit_no_change(request) - return HttpResponseRedirect(url_page(request, rel_path)) + return HttpResponseRedirect(url_page(rel_path)) elif preview is not None: form = EditForm(page_data=page_txt, page_tags=tags) # @@ -107,10 +107,10 @@ def edit(request, rel_path): ) return render(request, 'pages/page_form.html', context=context) else: - return HttpResponseRedirect(url_page(request, rel_path)) + return HttpResponseRedirect(url_page(rel_path)) else: messages.permission_denied_msg_page(request, rel_path) - return HttpResponseRedirect(url_page(request, rel_path)) + return HttpResponseRedirect(url_page(rel_path)) def search(request): diff --git a/themes b/themes index c63d873..c13b45a 160000 --- a/themes +++ b/themes @@ -1 +1 @@ -Subproject commit c63d8731fe85374ef74abf24b0d205bce24f66b1 +Subproject commit c13b45a7f736c0e8658fbd24ff826ad9b5d336e6