|
@@ -60,7 +60,9 @@ class base_page(object):
|
60
|
60
|
HISTORY_FOLDER_NAME = 'history'
|
61
|
61
|
SPLITCHAR = ":"
|
62
|
62
|
|
63
|
|
- def __init__(self, path):
|
|
63
|
+ def __init__(self, path, history_version=None):
|
|
64
|
+ self._history_version = history_version
|
|
65
|
+ #
|
64
|
66
|
if path.startswith(settings.PAGES_ROOT):
|
65
|
67
|
self._path = path
|
66
|
68
|
else:
|
|
@@ -69,6 +71,10 @@ class base_page(object):
|
69
|
71
|
#
|
70
|
72
|
self._meta_data = meta_data(self._meta_filename, self.is_available())
|
71
|
73
|
|
|
74
|
+ @property
|
|
75
|
+ def modified_time(self):
|
|
76
|
+ return self._meta_data.get(self._meta_data.KEY_MODIFIED_TIME)
|
|
77
|
+
|
72
|
78
|
def _load_page_src(self):
|
73
|
79
|
if self._raw_page_src is None:
|
74
|
80
|
try:
|
|
@@ -77,47 +83,63 @@ class base_page(object):
|
77
|
83
|
except FileNotFoundError:
|
78
|
84
|
self._raw_page_src = ""
|
79
|
85
|
|
80
|
|
- def _store_history(self):
|
|
86
|
+ def history_numbers_list(self):
|
81
|
87
|
history_folder = os.path.join(self._path, self.HISTORY_FOLDER_NAME)
|
82
|
|
- # create folder if needed
|
83
|
88
|
fstools.mkdir(history_folder)
|
84
|
89
|
# identify last_history number
|
85
|
|
- flist = fstools.filelist(history_folder)
|
86
|
|
- flist.sort()
|
87
|
|
- if flist:
|
88
|
|
- hist_number = int(os.path.basename(flist[-1])[:5]) + 1
|
89
|
|
- else:
|
90
|
|
- hist_number = 1
|
|
90
|
+ return list(set([int(os.path.basename(filename)[:5]) for filename in fstools.filelist(history_folder)]))
|
|
91
|
+
|
|
92
|
+ def _store_history(self):
|
|
93
|
+ try:
|
|
94
|
+ hist_number = max(self.history_numbers_list()) + 1
|
|
95
|
+ except ValueError:
|
|
96
|
+ hist_number = 1 # no history yet
|
91
|
97
|
# copy file to history folder
|
92
|
|
- shutil.copy(self.filename, os.path.join(history_folder, "%05d_%s" % (hist_number, self.PAGE_FILE_NAME)))
|
93
|
|
- shutil.copy(self._meta_filename, os.path.join(history_folder, "%05d_%s" % (hist_number, self.META_FILE_NAME)))
|
|
98
|
+ shutil.copy(self.filename, self.history_filename(hist_number))
|
|
99
|
+ shutil.copy(self._meta_filename, self._history_meta_filename(hist_number))
|
94
|
100
|
|
95
|
101
|
def update_page(self, page_txt, tags):
|
96
|
|
- from .search import update_item
|
97
|
|
- if page_txt.replace("\r\n", "\n") != self.raw_page_src:
|
98
|
|
- # Store page history
|
99
|
|
- if self.raw_page_src:
|
100
|
|
- self._store_history()
|
101
|
|
- # save the new page content
|
102
|
|
- fstools.mkdir(os.path.dirname(self.filename))
|
103
|
|
- with open(self.filename, 'w') as fh:
|
104
|
|
- fh.write(page_txt)
|
105
|
|
- # update metadata
|
106
|
|
- page_changed = True
|
|
102
|
+ if self._history_version:
|
|
103
|
+ logger.error("A history version %05d can not be updated!", self._history_version)
|
|
104
|
+ return False
|
107
|
105
|
else:
|
108
|
|
- page_changed = False
|
109
|
|
- self._update_metadata(tags)
|
110
|
|
- # update search index
|
111
|
|
- update_item(self)
|
112
|
|
- return page_changed
|
|
106
|
+ from .search import update_item
|
|
107
|
+ if page_txt.replace("\r\n", "\n") != self.raw_page_src:
|
|
108
|
+ # Store page history
|
|
109
|
+ if self.raw_page_src:
|
|
110
|
+ self._store_history()
|
|
111
|
+ # save the new page content
|
|
112
|
+ fstools.mkdir(os.path.dirname(self.filename))
|
|
113
|
+ with open(self.filename, 'w') as fh:
|
|
114
|
+ fh.write(page_txt)
|
|
115
|
+ # update metadata
|
|
116
|
+ page_changed = True
|
|
117
|
+ else:
|
|
118
|
+ page_changed = False
|
|
119
|
+ self._update_metadata(tags)
|
|
120
|
+ # update search index
|
|
121
|
+ update_item(self)
|
|
122
|
+ return page_changed
|
113
|
123
|
|
114
|
124
|
@property
|
115
|
125
|
def filename(self):
|
116
|
|
- return os.path.join(self._path, self.PAGE_FILE_NAME)
|
|
126
|
+ if not self._history_version:
|
|
127
|
+ return os.path.join(self._path, self.PAGE_FILE_NAME)
|
|
128
|
+ else:
|
|
129
|
+ return self.history_filename(self._history_version)
|
|
130
|
+
|
|
131
|
+ def history_filename(self, history_version):
|
|
132
|
+ return os.path.join(self._path, self.HISTORY_FOLDER_NAME, "%05d_%s" % (history_version, self.PAGE_FILE_NAME))
|
117
|
133
|
|
118
|
134
|
@property
|
119
|
135
|
def _meta_filename(self):
|
120
|
|
- return os.path.join(self._path, self.META_FILE_NAME)
|
|
136
|
+ if not self._history_version:
|
|
137
|
+ return os.path.join(self._path, self.META_FILE_NAME)
|
|
138
|
+ else:
|
|
139
|
+ return self._history_meta_filename(self._history_version)
|
|
140
|
+
|
|
141
|
+ def _history_meta_filename(self, history_version):
|
|
142
|
+ return os.path.join(self._path, self.HISTORY_FOLDER_NAME, "%05d_%s" % (history_version, self.META_FILE_NAME))
|
121
|
143
|
|
122
|
144
|
@property
|
123
|
145
|
def rel_path(self):
|
|
@@ -160,9 +182,9 @@ class base_page(object):
|
160
|
182
|
class creole_page(base_page):
|
161
|
183
|
FOLDER_ATTACHMENTS = "attachments"
|
162
|
184
|
|
163
|
|
- def __init__(self, request, path) -> None:
|
|
185
|
+ def __init__(self, request, path, history_version=None) -> None:
|
164
|
186
|
self._request = request
|
165
|
|
- super().__init__(path)
|
|
187
|
+ super().__init__(path, history_version=history_version)
|
166
|
188
|
|
167
|
189
|
@property
|
168
|
190
|
def attachment_path(self):
|
|
@@ -181,12 +203,51 @@ class creole_page(base_page):
|
181
|
203
|
user = self._meta_data.get(self._meta_data.KEY_MODIFIED_USER)
|
182
|
204
|
tags = self._meta_data.get(self._meta_data.KEY_TAGS, "-")
|
183
|
205
|
#
|
184
|
|
- meta = f'|{_("Created")}:|{ctime}|\n'
|
|
206
|
+ meta = f'=== {_("Meta data")}\n'
|
|
207
|
+ meta += f'|{_("Created")}:|{ctime}|\n'
|
185
|
208
|
meta += f'|{_("Modified")}:|{mtime}|\n'
|
186
|
209
|
meta += f'|{_("Editor")}|{user}|\n'
|
187
|
210
|
meta += f'|{_("Tags")}|{tags}|\n'
|
|
211
|
+ #
|
|
212
|
+ hnl = self.history_numbers_list()
|
|
213
|
+ if hnl:
|
|
214
|
+ meta += f'=== {_("History")}\n'
|
|
215
|
+ meta += f'| ={_("Version")} | ={_("Date")} | ={_("Page")} | ={_("Meta data")} | \n'
|
|
216
|
+ # Current
|
|
217
|
+ name = _("Current")
|
|
218
|
+ meta += f"| {name} \
|
|
219
|
+ | {timestamp_to_datetime(self._request, self.modified_time)} \
|
|
220
|
+ | [[{url_page(self._request, self.rel_path)} | Page]] \
|
|
221
|
+ | [[{url_page(self._request, self.rel_path, meta=None)} | Meta]]\n"
|
|
222
|
+ # History
|
|
223
|
+ for num in reversed(hnl):
|
|
224
|
+ p = creole_page(self._request, self._path, history_version=num)
|
|
225
|
+ meta += f"| {num} \
|
|
226
|
+ | {timestamp_to_datetime(self._request, p.modified_time)} \
|
|
227
|
+ | [[{url_page(self._request, p.rel_path, history=num)} | Page]] \
|
|
228
|
+ | [[{url_page(self._request, p.rel_path, meta=None, history=num)} | Meta]]\n"
|
|
229
|
+ #
|
188
|
230
|
meta += f'=== {_("Page content")}\n'
|
189
|
|
- meta += '{{{\n%s\n}}}\n' % self.raw_page_src
|
|
231
|
+ if not self._history_version:
|
|
232
|
+ meta += '{{{\n%s\n}}}\n' % self.raw_page_src
|
|
233
|
+ else:
|
|
234
|
+ c = creole_page(self._request, self.rel_path)
|
|
235
|
+ meta += "| =Current | =This |\n"
|
|
236
|
+ left_lines = c.raw_page_src.splitlines()
|
|
237
|
+ right_lines = self.raw_page_src.splitlines()
|
|
238
|
+ while len(left_lines) + len(right_lines) > 0:
|
|
239
|
+ try:
|
|
240
|
+ left = left_lines.pop(0)
|
|
241
|
+ except IndexError:
|
|
242
|
+ left = ""
|
|
243
|
+ try:
|
|
244
|
+ right = right_lines.pop(0)
|
|
245
|
+ except IndexError:
|
|
246
|
+ right = ""
|
|
247
|
+ if left == right:
|
|
248
|
+ meta += "| {{{ %s }}} | {{{ %s }}} |\n" % (left, right)
|
|
249
|
+ else:
|
|
250
|
+ meta += "| **{{{ %s }}}** | **{{{ %s }}}** |\n" % (left, right)
|
190
|
251
|
#
|
191
|
252
|
return mycreole.render_simple(meta)
|
192
|
253
|
|