Commit 5030cef6 authored by Romain Courteaud's avatar Romain Courteaud

romain_dev: forum improve post rendering

parent 32760fa7
......@@ -12,7 +12,6 @@
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!--link rel="stylesheet" href="gadget_erp5_page_nx_project_quality.css"-->
<!-- custom script -->
<script src="jiodev.js" type="text/javascript"></script>
......
......@@ -238,7 +238,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>989.1604.35674.62737</string> </value>
<value> <string>989.21729.29819.50124</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -256,7 +256,7 @@
</tuple>
<state>
<tuple>
<float>1609424915.53</float>
<float>1610632417.11</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -8,6 +8,8 @@
// XXX create topic by followup (allDocs group by follow up)
var DISPLAY_READER = 'display_reader',
DISPLAY_THREAD = 'display_thread',
DISPLAY_POST = 'display_post',
MAIN_SCOPE = 'child_scope';
function loadChildGadget(gadget, gadget_url, must_declare, callback) {
......@@ -117,7 +119,7 @@
}
function renderDiscussionThread(gadget, must_declare, jio_key) {
return loadChildGadget(gadget, "gadget_erp5_pt_form_dialog.html",
return loadChildGadget(gadget, "gadget_erp5_pt_form_view_editable.html",
must_declare, function (form_gadget) {
var thread_info_dict;
......@@ -209,7 +211,7 @@
"hidden": 0
};
group_list.push([
"center",
"bottom",
[["nutnut"]]
], [
"hidden", ["listbox_modification_date"]
......@@ -496,6 +498,10 @@
.allowPublicAcquisition("jio_allDocs", function (param_list, scope) {
// XXX Convert iso date to a DateTime field
// XXX Paginate message to last message on modification date column
if (this.state.display_step !== DISPLAY_READER) {
throw new rJS.AcquisitionError();
}
var gadget = this,
options = param_list[0];
console.log(scope, param_list);
......@@ -560,16 +566,26 @@
});
})
.setState({
display_step: DISPLAY_READER
})
.declareMethod('render', function (options) {
console.log(options);
var display_step,
jio_key = options.jio_key;
if (jio_key === undefined) {
display_step = DISPLAY_READER;
} else if ((jio_key.match(/\//g) || []).length === 1) {
// XXX HACK
display_step = DISPLAY_THREAD;
}
return this.changeState({
first_render: true,
// first_render: true,
page: options.page,
jio_key: options.jio_key,
options: options
jio_key: jio_key,
display_step: display_step,
options: options,
// Force display in any case
render_timestamp: new Date().getTime()
/*
display_step: DISPLAY_TREE,
// Only build the bt5 during the first query
......@@ -596,51 +612,28 @@
console.log('changestate', modification_dict);
var gadget = this;
// Always refresh the reader
if (gadget.state.display_step === DISPLAY_READER) {
if (gadget.state.jio_key === undefined) {
return renderDiscussionThreadList(
gadget,
modification_dict.hasOwnProperty('display_step') || modification_dict.first_render
);
}
// XXX HACK
if ((gadget.state.jio_key.match(/\//g) || []).length === 1) {
return renderDiscussionThread(
gadget,
modification_dict.hasOwnProperty('display_step') || modification_dict.first_render,
gadget.state.jio_key
);
}
return renderDiscussionThreadList(
gadget,
modification_dict.hasOwnProperty('display_step')
);
}
if (gadget.state.display_step === DISPLAY_THREAD) {
return renderDiscussionThread(
gadget,
modification_dict.hasOwnProperty('display_step'),
gadget.state.jio_key
);
}
/*
return renderDiscussionPost(
gadget,
modification_dict.hasOwnProperty('display_step') || modification_dict.first_render,
gadget.state.jio_key
);
}
/*
if (gadget.state.display_step === DISPLAY_TREE) {
console.log(modification_dict);
if (modification_dict.hasOwnProperty('display_step')) {
return renderTreeView(gadget,
modification_dict.hasOwnProperty('extract'));
}
if (modification_dict.hasOwnProperty('expand_tree')) {
return expandTreeView(gadget);
}
}
if (modification_dict.display_step === DISPLAY_DIFF) {
return renderDiffView(gadget);
}
if (modification_dict.display_step === DISPLAY_CHANGELOG) {
return renderChangelogView(gadget);
}
*/
if (modification_dict.hasOwnProperty('display_step')) {
throw new Error('Unhandled display step: ' + gadget.state.display_step);
}
throw new Error('Unhandled display step: ' + gadget.state.display_step);
});
}(window, rJS, RSVP, domsugar, SimpleQuery, ComplexQuery, Query));
\ No newline at end of file
......@@ -240,7 +240,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>989.18879.37912.30737</string> </value>
<value> <string>989.21570.59351.45277</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -258,7 +258,7 @@
</tuple>
<state>
<tuple>
<float>1610461438.43</float>
<float>1610622907.09</float>
<string>UTC</string>
</tuple>
</state>
......
div[data-gadget-url$="gadget_thread_reader.html"] > ol {
max-width: 50em;
}
div[data-gadget-url$="gadget_thread_reader.html"] > ol > li {
padding-bottom: 2em;
}
div[data-gadget-url$="gadget_thread_reader.html"] > ol > li:nth-child(even) {
background-color: rgba(230, 230, 230, 0.65);
}
div[data-gadget-url$="gadget_thread_reader.html"] > ol > li > div.post_content {
display: inline-block;
}
div[data-gadget-url$="gadget_thread_reader.html"] > ol > li > div.post_content > div {
margin-top: 1em;
}
div[data-gadget-url$="gadget_thread_reader.html"] > ol > li > div.post_avatar {
display: inline-block;
margin-right: 1em;
width: 3em;
height: 3em;
line-height: 3em;
text-align: center;
border-radius: 50%;
background: #0E81C2;
color: #FFFFFF;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
vertical-align: top;
text-transform: uppercase;
}
div[data-gadget-url$="gadget_thread_reader.html"] > ol > li + li {
padding-top: 1em;
}
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Style" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>gadget_thread_reader.css</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>romain_thread_reader_css</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value> <string>en</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Style</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Gadget Thread Reader CSS</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>document_publication_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>processing_status_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_alive</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1610631146.53</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>989.21822.53724.24473</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1610638751.46</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_processing_state</string> </key>
<value> <string>empty</string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1610631110.94</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -13,6 +13,7 @@
<title>Thread Reader</title>
<!-- renderjs -->
<link rel="stylesheet" href="gadget_thread_reader.css">
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<script src="domsugar.js" type="text/javascript"></script>
......
......@@ -238,7 +238,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>989.18650.40702.358</string> </value>
<value> <string>989.21729.52523.14404</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -256,7 +256,7 @@
</tuple>
<state>
<tuple>
<float>1610447694.2</float>
<float>1610632439.05</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -7,6 +7,37 @@
loading_class_list = ['ui-icon-spinner', 'ui-btn-icon-left'],
disabled_class = 'ui-disabled';
function getRelativeTimeString(current_date, date) {
var diff,
abs,
second = 1000,
minute = second * 60,
hour = minute * 60,
day = hour * 24,
week = day * 7,
time_format = new Intl.RelativeTimeFormat();
diff = date.getFullYear() - current_date.getFullYear();
if (diff !== 0) {
return time_format.format(diff, 'year');
}
diff = date - current_date;
abs = Math.abs(diff);
// "year", "quarter", "month", "week", "day", "hour", "minute", "second"
console.log(current_date, date, abs, week, day);
if (abs > (week * 2)) {
return time_format.format(Math.floor(diff / week), 'week');
} else if (abs > (day * 2)) {
return time_format.format(Math.floor(diff / day), 'day');
} else if (abs > (hour * 2)) {
return time_format.format(Math.floor(diff / hour), 'hour');
} else {
return time_format.format(Math.floor(diff / minute), 'minute');
}
return date;
}
function buildFieldGadgetParam(value) {
var field_gadget_param;
......@@ -386,13 +417,38 @@
})
))
.push(function (viewer_list) {
var now = new Date();
domsugar(gadget.element, [
domsugar('p', {text: 'Comments:'}),
domsugar('ol', allDocs_result.data.rows.map(function (entry, i) {
console.log(entry);
var source_title = entry.value.source_title || '',
word_list = source_title.split(' '),
source_short_title;
if (word_list.length === 1) {
source_short_title = (word_list[0][0] || '?') + (word_list[0][1] || '');
} else {
source_short_title = word_list[0][0] + word_list[1][0];
}
return domsugar('li', [
viewer_list[i].element,
domsugar('hr')
domsugar('div', {
class: 'post_avatar',
text: source_short_title
}),
domsugar('div', {
class: 'post_content',
}, [
domsugar('strong', {text: source_title}),
" ",
domsugar('time', {
datetime: entry.value.modification_date,
title: entry.value.modification_date,
text: getRelativeTimeString(
now, new Date(entry.value.modification_date)
)
}),
domsugar('br'),
viewer_list[i].element,
// domsugar('hr')
])
]);
}))
]);
......@@ -768,6 +824,19 @@
return result_queue;
})
.onLoop(function () {
// update relative time
var now = new Date();
this.element.querySelectorAll("div.post_content > time").forEach(
function (element) {
element.textContent = getRelativeTimeString(
now, new Date(element.getAttribute('datetime'))
);
}
);
// Loop every minute
}, 1000 * 60)
//////////////////////////////////////////////
// render the listbox in an asynchronous way
//////////////////////////////////////////////
......
......@@ -240,7 +240,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>989.20325.997.53486</string> </value>
<value> <string>989.21883.22115.61832</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -258,7 +258,7 @@
</tuple>
<state>
<tuple>
<float>1610548223.31</float>
<float>1610641779.85</float>
<string>UTC</string>
</tuple>
</state>
......
@colorheaderbackground: #085078;
@colorsubheaderbackground: #0E81C2;
@foreground-text-shadow: 0 1px 2px rgba(0, 0, 0, 0.20);
@white: #FFFFFF;
@avatar_size: 3em;
div[data-gadget-url$="gadget_thread_reader.html"] {
& > ol {
// Limit the width to make reading more pleasant on large screen
max-width: 50em;
& > li {
padding-bottom: 2em;
&:nth-child(even) {
background-color: rgba(230, 230, 230, 0.65);
}
& > div.post_content {
display: inline-block;
& > div {
// Separate post info (user and time) from content
margin-top: 1em;
}
}
& > div.post_avatar {
display: inline-block;
margin-right: 1em;
width: @avatar_size;
height: @avatar_size;
line-height: @avatar_size;
text-align: center;
border-radius: 50%;
background: @colorsubheaderbackground;
color: @white;
text-shadow: @foreground-text-shadow;
vertical-align: top;
text-transform: uppercase;
}
& + li {
// Separate posts
// border-top: solid 1px @colorsubheaderbackground;
padding-top: 1em;
}
}
}
}
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>gadget_thread_reader.less</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/plain</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment