Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proof of concept: Versioning MK2 #329

Open
wants to merge 57 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
38dea2a
fix import of workflow
zmsdev Oct 28, 2024
1b10a6a
versioning markdown
zmsdev Oct 29, 2024
4471313
more doc
drfho Nov 11, 2024
2cb8f3d
more doc
drfho Nov 11, 2024
7933ddc
editing
drfho Nov 11, 2024
52bf2e8
get_tags/get_tag
zmsdev Nov 11, 2024
c33b162
Merge branch 'fb_versioning' of https://github.com/zms-publishing/ZMS…
zmsdev Nov 11, 2024
5a7b459
more doc
drfho Nov 11, 2024
d2f9efa
more editing
drfho Nov 12, 2024
36ad245
preview tags
zmsdev Nov 12, 2024
450ca87
diff
zmsdev Nov 12, 2024
a30fc67
diff pretty json
zmsdev Nov 12, 2024
8bb853a
diff pretty json and preview
zmsdev Nov 12, 2024
9d1a356
fixed tests
zmsdev Nov 13, 2024
af1e148
revised wf zmi
drfho Nov 13, 2024
ff4266d
wf-zmi: disable htmx temporarily
drfho Nov 13, 2024
88c2f9e
fix form name
drfho Nov 13, 2024
6cfeab1
fixed form names after refact
drfho Nov 13, 2024
2c95418
gui spacing, version pattern
drfho Nov 15, 2024
99d6ff1
manage_UndoVersionForm: spacing
drfho Nov 15, 2024
2bbf406
added more doc
drfho Nov 15, 2024
2990b89
added more doc
drfho Nov 15, 2024
8477d28
added more doc
drfho Nov 15, 2024
c3f881e
ensure wf-tab context after save
drfho Nov 15, 2024
e875863
added preview toggle to history selector
drfho Nov 15, 2024
8fbbd2c
added toggle html vs. json
drfho Nov 15, 2024
32ddb99
added btn-func toggle_view for switching json/preview
drfho Nov 16, 2024
be9c036
typo
drfho Nov 16, 2024
db644f2
added notebook for difflib
drfho Nov 16, 2024
6c6ca87
eval htmldiff2
drfho Nov 16, 2024
f31ffe8
added rest-api get_htmldiff
drfho Nov 16, 2024
1219c2c
added POST method to rest-api
drfho Nov 17, 2024
c621b47
cleaning
drfho Nov 17, 2024
e5d91a7
prepared for genshi processing
drfho Nov 17, 2024
b4af435
cleaning, show primarily diff view
drfho Nov 17, 2024
b5f6a3d
doc: version vector
drfho Nov 18, 2024
ffdc188
added draft for implementation
drfho Nov 18, 2024
b7afbdd
diff json based on change_dt
zmsdev Nov 18, 2024
c2c0715
fixed view toggeling
drfho Nov 18, 2024
a44bca5
added htmldiff2 to requirements-full
drfho Nov 18, 2024
9a61b24
get_body_content_diff
zmsdev Nov 18, 2024
f81c084
refactoring htmldiff
zmsdev Nov 18, 2024
3fe3862
fix body_content_diff
zmsdev Nov 18, 2024
5c176cf
diff version_container
zmsdev Nov 18, 2024
c05dd0a
rehderShort atoms
zmsdev Nov 18, 2024
09e62f3
version-items if not version-container
zmsdev Nov 19, 2024
3351b10
added lang to ajax-request. styled zmi block links
drfho Nov 19, 2024
fb57c47
diff: added JS-function show_old_src_images()
drfho Nov 20, 2024
b7bab74
added style to tagdiff_replaced img
drfho Nov 20, 2024
47e3940
added readme files to docker examples
drfho Nov 21, 2024
ffd7cad
squash item-versions to container
zmsdev Nov 21, 2024
91f0019
fixed version over-filtering
drfho Nov 23, 2024
662318b
workaround the race condition on versions loading
drfho Nov 25, 2024
639afca
diff when loaded
zmsdev Nov 25, 2024
dcdfa63
added change*-attribute fallback
drfho Nov 26, 2024
467e4e2
added lang-request param to get_tags: @TODO implement correct version…
zmsdev Nov 26, 2024
5815635
version-tags retrieval
zmsdev Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions Products/zms/ZMSWorkflowProvider.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,13 +316,13 @@ def doAutocommit(self, lang, REQUEST):

Change workflow.
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
def manage_changeWorkflow(self, lang, btn='', key='properties', REQUEST=None, RESPONSE=None):
def manage_changeWorkflow(self, lang, btn='', key='workflow_properties', REQUEST=None, RESPONSE=None):
""" ZMSWorkflowProvider.manage_changeWorkflow """
message = ''

# Version Control.
# -----------
if key == 'history':
if key == 'workflow_versioning':
old_active = self.getConfProperty('ZMS.Version.active',0)
new_active = REQUEST.get('active',0)
old_nodes = self.getConfProperty('ZMS.Version.nodes',['{$}'])
Expand All @@ -342,10 +342,19 @@ def manage_changeWorkflow(self, lang, btn='', key='properties', REQUEST=None, RE
except:
message += '[%s: %s]'%(node,'No history to pack')
message = self.getZMILangStr('MSG_CHANGED')+message


# Content Assignment.
# -----------
elif key == 'workflow_assignment':
# Save.
# ------
if btn == 'BTN_SAVE':
self.nodes = standard.string_list(REQUEST.get('nodes', ''))
message = self.getZMILangStr('MSG_CHANGED')

# Properties.
# -----------
elif key == 'properties':
elif key == 'workflow_properties':
# Save.
# ------
if btn == 'BTN_SAVE':
Expand All @@ -354,7 +363,6 @@ def manage_changeWorkflow(self, lang, btn='', key='properties', REQUEST=None, RE
new_autocommit = REQUEST.get('workflow', 0) == 0
self.revision = REQUEST.get('revision', '0.0.0')
self.autocommit = new_autocommit
self.nodes = standard.string_list(REQUEST.get('nodes', ''))
if old_autocommit == 0 and new_autocommit == 1:
self.doAutocommit(lang, REQUEST)
message = self.getZMILangStr('MSG_CHANGED')
Expand Down Expand Up @@ -383,10 +391,10 @@ def manage_changeWorkflow(self, lang, btn='', key='properties', REQUEST=None, RE
else:
filename = REQUEST['init']
self.importConf(filename)
message = self.getZMILangStr('MSG_IMPORTED')%('<i>%s</i>'%f.filename)
message = self.getZMILangStr('MSG_IMPORTED')%('<i>%s</i>'%filename)

# Return with message.
message = standard.url_quote(message)
return RESPONSE.redirect('manage_main?lang=%s&key=%s&manage_tabs_message=%s#_properties'%(lang, key, message))
return RESPONSE.redirect('manage_main?lang=%s&key=%s&manage_tabs_message=%s#%s'%(lang, key, message, key))

################################################################################
28 changes: 14 additions & 14 deletions Products/zms/import/_language.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6406,23 +6406,23 @@
</Row>
<Row>
<Cell><Data ss:Type="String">TAB_WORKFLOW_ASSIGNMENT</Data></Cell>
<Cell><Data ss:Type="String">Workflow-Aktivierung</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Workflow Assignment</Data></Cell>
<Cell><Data ss:Type="String">Zuweisung</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
<Cell><Data ss:Type="String">Assignment</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">TAB_WORKFLOW_MODEL</Data></Cell>
<Cell><Data ss:Type="String">Ablauf-Modell</Data></Cell>
<Cell><Data ss:Type="String">Workflow-Modell</Data></Cell>
<Cell><Data ss:Type="String">Workflow Model</Data></Cell>
<Cell><Data ss:Type="String">Workflow Model</Data></Cell>
<Cell><Data ss:Type="String">Workflow Model</Data></Cell>
Expand Down
2 changes: 1 addition & 1 deletion Products/zms/import/example1.workflow.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<item type="dictionary">
<dictionary>
<item key="icon"></item>
<item key="icon_clazz"><![CDATA[icon-reply text-danger wf-icon]]></item>
<item key="icon_clazz"><![CDATA[fas fa-reply text-danger wf-icon]]></item>
<item key="id"><![CDATA[AC_ROLLEDBACK]]></item>
<item key="name"><![CDATA[Rolled back]]></item>
</dictionary>
Expand Down
121 changes: 119 additions & 2 deletions Products/zms/rest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ def __bobo_traverse__(self, TraversalRequest, name):
def __call__(self, REQUEST=None, **kw):
""""""
standard.writeBlock(self.context,'__call__: %s'%str(self.ids))
if self.method == 'POST':
if self.ids == ['get_htmldiff']:
decoration, data = self.get_htmldiff(self.context, content_type=True)
return data
else:
return None
if self.method == 'GET':
decoration, data = {'content_type':'text/plain'}, {}
if self.ids == [] and self.context.meta_type == 'ZMSIndex':
Expand All @@ -190,12 +196,22 @@ def __call__(self, REQUEST=None, **kw):
decoration, data = self.get_child_nodes(self.context, content_type=True)
elif self.ids == ['get_tree_nodes']:
decoration, data = self.get_tree_nodes(self.context, content_type=True)
elif self.ids == ['get_tags']:
decoration, data = self.get_tags(self.context, content_type=True)
elif self.ids == ['get_tag']:
decoration, data = self.get_tag(self.context, content_type=True)
elif self.ids == ['body_content']:
decoration, data = self.body_content(self.context, content_type=True)
elif self.ids == [] or self.ids == ['get']:
decoration, data = self.get(self.context, content_type=True)
else:
data = {'ERROR':'Not Found','context':str(self.context),'path_to_handle':self.path_to_handle,'ids':self.ids}
REQUEST.RESPONSE.setHeader('Content-Type',decoration['content_type'])
return json.dumps(data)
ct = decoration['content_type']
REQUEST.RESPONSE.setHeader('Content-Type',ct)
REQUEST.RESPONSE.setHeader('Content-Disposition', 'inline;filename="%s.%s"'%((self.ids+['get'])[-1],ct.split('/')[-1]))
if ct == 'application/json':
return json.dumps(data)
return data
return None

@api(tag="zmsindex", pattern="/zmsindex", content_type="application/json")
Expand Down Expand Up @@ -265,3 +281,104 @@ def get_tree_nodes(self, context):
request = _get_request(context)
nodes = context.getTreeNodes(request)
return [get_attrs(x) for x in nodes]

@api(tag="version", pattern="/{path}/get_tags", method="GET", content_type="application/json")
def get_tags(self, context):
request = _get_request(context)
lang = request.get('lang')
tags = []
version_container = context.getVersionContainer()
version_items = ([version_container] + version_container.getVersionItems(request)) if context.isVersionContainer() else [context]
for version_item in version_items:
for obj_version in version_item.getObjVersions():
request.set('ZMS_VERSION_%s'%version_item.id,obj_version.id)
change_dt = obj_version.attr('change_dt')
change_uid = obj_version.attr('change_uid')
if change_dt and change_uid:
dt = standard.getLangFmtDate(version_item,change_dt,'eng','DATETIME_FMT')
if not [1 for tag in tags if tag[0] == dt]:
tags.append(
(dt
,'r%i.%i.%i'%(obj_version.attr('master_version'), obj_version.attr('major_version'), obj_version.attr('minor_version'))
,'/'.join(version_item.getPhysicalPath())
))
tags = sorted(list(set(tags)),key=lambda x:x[0])
tags.reverse()
physical_path = '/'.join(context.getPhysicalPath())
if context.isVersionContainer():
physical_path = '/'.join(version_container.getPhysicalPath())
rtn = []
for i in range(len(tags)):
tag = list(tags[i])
if i == 0 and not tag[2] == physical_path:
dt = tag[0]
rtn.append(
[dt
,'r*.*.*'
, physical_path
])
if tag[2] == physical_path:
rtn.append(tag)
return [(x[0],x[1]) for x in rtn]

@api(tag="version", pattern="/{path}/get_tag", method="GET", content_type="application/json")
def get_tag(self, context):
request = _get_request(context)
tag = request.get('tag').split(",")
dt = tag[0]
data = []
version_container = context.getVersionContainer()
version_items = ([version_container] + version_container.getVersionItems(request)) if context.isVersionContainer() else [context]
for version_item in version_items:
d = {}
for obj_version in version_item.getObjVersions():
request.set('ZMS_VERSION_%s'%version_item.id,obj_version.id)
change_dt = obj_version.attr('change_dt') or obj_version.attr('created_dt')
change_uid = obj_version.attr('change_uid') or obj_version.attr('created_uid')
if change_dt and change_uid:
d[standard.getLangFmtDate(version_item,change_dt,'eng','DATETIME_FMT')] = obj_version.id
tags = list(reversed(sorted(list(d.keys()))))
tags = [x for x in tags if x <= dt]
if tags:
request.set('ZMS_VERSION_%s'%version_item.id,d[tags[0]])
attrs = get_attrs(version_item)
data.append(attrs)
return data

@api(tag="version", pattern="/{path}/body_content", method="GET", content_type="text/html")
def body_content(self, context):
request = _get_request(context)
tag = request.get('tag').split(",")
dt = tag[0]
html = []
version_container = context.getVersionContainer()
version_items = ([version_container] + version_container.getVersionItems(request)) if context.isVersionContainer() else [context]
for version_item in version_items:
d = {}
for obj_version in version_item.getObjVersions():
request.set('ZMS_VERSION_%s'%version_item.id,obj_version.id)
change_dt = obj_version.attr('change_dt') or obj_version.attr('created_dt')
change_uid = obj_version.attr('change_uid') or obj_version.attr('created_uid')
if change_dt and change_uid:
d[standard.getLangFmtDate(version_item,change_dt,'eng','DATETIME_FMT')] = obj_version.id
tags = list(reversed(sorted(list(d.keys()))))
tags = [x for x in tags if x <= dt]
if tags:
request.set('ZMS_VERSION_%s'%version_item.id,d[tags[0]])
html.append('<div><a href="%s/manage_main"><small>%s</div></small></a></div>'%(version_item.absolute_url(),'/'.join(version_item.getPhysicalPath())))
if version_item == version_container:
html.append('<div class="%s"><h1>%s<small>%s</small></h1></div>'%(version_item.meta_id,version_item.getTitle(request),version_item.getDCDescription(request)))
else:
html.append(version_item.renderShort(request))
return '\n'.join(html)

@api(tag="standard", pattern="/{path}/get_htmldiff", method="POST", content_type="text/html")
def get_htmldiff(self, context):
decoration, data = {'content_type':'text/html'}, {}
request = _get_request(context)
original = request.get('original','<pre>original</pre>')
changed = request.get('changed','<pre>changed</pre>')
data = standard.htmldiff(original, changed)
ct = decoration['content_type']
request.RESPONSE.setHeader('Content-Type',ct)
return data
24 changes: 24 additions & 0 deletions Products/zms/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,30 @@ def processData(context, processId, data, trans=None):
return _filtermanager.processData(context, processId, data, trans)


security.declarePublic('htmldiff')
def htmldiff(original, changed):
"""
Wrapper for htmldiff2.render_html_diff.
@param original: html-file-0
@type context: C{str}
@param changed: html-file-1
@type changed: C{str}
"""
try:
from htmldiff2 import render_html_diff
def remove_curly_braces(s):
return re.sub(r'/[\{\}]', '', s, flags=re.IGNORECASE)
def remove_html_comments(s):
return re.sub(r'<!--.*?-->', '', s, flags=re.DOTALL)
# Remove html comments for processing with htmldiff2/genshi.
original = remove_html_comments(remove_curly_braces(original))
changed = remove_html_comments(remove_curly_braces(changed))
diff = render_html_diff(original,changed)
except:
diff = '<pre>ERROR: Cannot load or work with htmldiff2</pre>'
return diff


############################################################################
#
#{ Executable
Expand Down
2 changes: 1 addition & 1 deletion Products/zms/zpt/ZMSMetacmdProvider/manage_main.zpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<label for="el_id" class="col-sm-3 control-label mandatory"><span tal:content="python:here.getZMILangStr('ATTR_ID')">Id</span></label>
<div class="col-sm-6"><input type="text" name="el_id" class="form-control form-control-sm" tal:attributes="value python:metaCmd['id']"/></div>
<label for="el_revision" class="col-sm-1 control-label mandatory"><span tal:content="python:here.getZMILangStr('ATTR_VERSION')">Version</span></label>
<div class="col-sm-2"><input type="text" name="el_revision" class="form-control form-control-sm" tal:attributes="value python:metaCmd.get('revision','0.0.0')"/></div>
<div class="col-sm-2"><input type="text" name="el_revision" placeholder="0.0.0" pattern="^\d+\.\d+\.\d+$" class="form-control form-control-sm" tal:attributes="value python:metaCmd.get('revision','0.0.0')"/></div>
</div>

<div class="form-group row">
Expand Down
Loading