Commit 12f6a67c authored by Roque's avatar Roque

erp5_web_project_ui: new front page gadget (WIP)

parent 84bd681e
......@@ -111,12 +111,15 @@ CACHE:\n
\n
gadget_erp5_page_project_controller.html\n
gadget_erp5_page_project_controller.js\n
gadget_project_info.html\n
gadget_project_info.js\n
gadget_erp5_page_project_redirector.html\n
gadget_erp5_page_project_redirector.js\n
gadget_erp5_project_panel.html\n
gadget_erp5_project_panel.js\n
gadget_erp5_page_project_front_page.html\n
gadget_erp5_page_project_front_page.js\n
gadget_project_info.html\n
gadget_project_info.js\n
gadget_project_info.css\n
\n
favicon.ico\n
font-awesome/font-awesome-webfont.eot\n
......@@ -405,7 +408,7 @@ NETWORK:\n
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>979.50747.65222.58094</string> </value>
<value> <string>981.52279.63159.55722</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -423,7 +426,7 @@ NETWORK:\n
</tuple>
<state>
<tuple>
<float>1577216049.89</float>
<float>1582797345.19</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -9,31 +9,18 @@
// Acquired methods
/////////////////////////////////////////////////////////////////
.declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("getSetting", "getSetting")
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod("render", function (options) {
var gadget = this;
return gadget.getSetting("hateoas_url")
.push(function (hateoas_url) {
return gadget.redirect({
'command': 'display',
'options': {
'page': 'form',
'jio_key': 'project_module',
'view': hateoas_url +
'/ERP5Document_getHateoas?mode=traverse&relative_url=' +
'project_module&view=ProjectModule_viewProjectManagementList',
'field_listbox_sort_list:json': [["title", "ascending"]],
'field_listbox_column_list:json': ["title",
"default_destination_section_title"],
'extended_search': 'selection_domain_state_project_domain: "started"'
}
});
});
return this.redirect({
'command': 'display',
'options': {
'page': 'project_front_page'
}
});
});
}(document, window, rJS));
\ No newline at end of file
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>980.38481.6518.61474</string> </value>
<value> <string>982.6887.63919.52804</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1577471606.29</float>
<float>1582796228.57</float>
<string>UTC</string>
</tuple>
</state>
......
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Project front page gadget</title>
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="gadget_erp5_page_project_front_page.js"></script>
<link rel="stylesheet" type="text/css" href="gadget_project_info.css">
</head>
<body>
<div id="js-spinner" class="ui-icon-spinner ui-btn-icon-notext loader"></div>
<div class="front-project-list">
<ul id="js-project-list">
</ul>
</div>
</body>
</html>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Page" 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> <string>text/html</string> </value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>gadget_erp5_page_project_front_page.html</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>project_gadget_page_project_front_page_html</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 Page</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Gadget Project Front Page</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>1582734852.83</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>982.6883.65420.42752</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>1582735082.33</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>1582734474.56</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*jslint nomen: true, indent: 2 */
/*global window, rJS, RSVP, document, SimpleQuery, ComplexQuery, Query, parseInt*/
(function (window, rJS, RSVP, document, SimpleQuery, ComplexQuery, Query, parseInt) {
"use strict";
/*jshint esnext: true */
const STATUS_OK = "green";
const STATUS_NOT_OK = "red";
const NONE_STATUS = "none";
const RADIX = 10;
const STATUS_SPAN = "status";
const TOTAL_SPAN = "total";
const OUTDATED_SPAN = "outdated";
const QUERY_LIMIT = 100000;
const SUPERVISOR_FIELD_TITLE = "Supervisor";
//XXX hardcoded one year old date to define outdated elements
//TODO Where to define/get the limit date? byt portal_type or the same for all documents?
const LIMIT_DATE = new Date(new Date().setFullYear(new Date().getFullYear() + 1));
//XXX hardcoded portal_types, states and titles dict
const PORTAL_TITLE_DICT = {"Task": "Tasks",
"Test Result" : "Test Results",
"Bug" : "Bugs",
"Project Milestone" : "Milestones",
"Task Report": "Task Reports"};
const PORTAL_TYPE_LIST = ["Task", "Bug", "Task Report"];
const VALID_STATE_LIST = ["planned", "auto_planned", "ordered", "confirmed", "ready", "stopped", "started", "submitted", "validated"];
function getProjectId(id) {
var segments = id.split("/");
if (segments.length === 2) {
return id;
}
return segments.slice(0, -1).join("/");
}
function getProjectSpanId(project_id, portal_type, span_title) {
return [project_id, portal_type, span_title].join("-").replace("/", "-").replace(" ", "-");
}
function getComplexQuery(query_dict, operator, extra_query) {
var key,
query_list = [];
for (key in query_dict) {
if (query_dict.hasOwnProperty(key)) {
query_list.push(new SimpleQuery({
key: key,
operator: "=",
type: "simple",
value: query_dict[key]
}));
}
}
if (extra_query) {
query_list.push(extra_query);
}
return new ComplexQuery({
operator: operator,
query_list: query_list,
type: "complex"
});
}
function getProjectDocumentList(gadget, limit_date) {
var document_query;
document_query = Query.objectToSearchText(new SimpleQuery({
key: "source_project__validation_state",
operator: "=",
type: "simple",
value: "validated"
}));
document_query += ' AND simulation_state: ("' + VALID_STATE_LIST.join('", "') + '")';
document_query += ' AND portal_type: ("' + PORTAL_TYPE_LIST.join('", "') + '")';
if (limit_date) {
document_query += ' AND modification_date: < "' + limit_date + '"';
}
return gadget.jio_allDocs({
query: document_query,
limit: QUERY_LIMIT,
select_list: ['source_project__relative_url', 'portal_type', 'count(*)'],
group_by: ['portal_type', 'source_project__relative_url'],
sort_on: [["modification_date", "descending"]]
})
.push(function (result) {
return result.data.rows;
});
}
function getProjectList(gadget) {
var project_query = Query.objectToSearchText(
getComplexQuery({"portal_type" : "Project",
"validation_state" : "validated"},
"AND"));
return gadget.jio_allDocs({
query: project_query,
limit: QUERY_LIMIT,
select_list: ['title', 'source_decision_title'],
sort_on: [["modification_date", "ascending"]]
})
.push(function (result) {
return result.data.rows;
});
}
function renderProjectLine(project_id, portal_type, total_count, outdated_count) {
var total_span = document.getElementById(getProjectSpanId(project_id, portal_type, TOTAL_SPAN)),
outdated_span = document.getElementById(getProjectSpanId(project_id, portal_type, OUTDATED_SPAN)),
status_span = document.getElementById(getProjectSpanId(project_id, portal_type, STATUS_SPAN));
total_span.textContent = parseInt(total_span.textContent, RADIX) + total_count;
outdated_span.textContent = parseInt(outdated_span.textContent, RADIX) + outdated_count;
if (outdated_count > 0) {
status_span.classList.remove(STATUS_OK);
status_span.classList.add(STATUS_NOT_OK);
} else if (!status_span.classList.value.includes(STATUS_NOT_OK)) {
status_span.classList.add(STATUS_OK);
}
}
function renderProjectList(gadget, project_list) {
var i,
item,
project_html,
left_div_html,
project_html_element_list,
left_line_html,
ul_list = document.getElementById("js-project-list"),
spinner = document.getElementById("js-spinner"),
url_parameter_list = [],
project_id,
project_dict,
outdated;
function createProjectHtmlElement(project_id, project_title, project_url, supervisor) {
var project_element = document.createElement('li'),
box_div = document.createElement('div'),
title_div = document.createElement('div'),
info_div = document.createElement('div'),
left_info_div = document.createElement('div'),
right_div = document.createElement('div'),
right_line_div = document.createElement('div'),
supervisor_line_div = document.createElement('div'),
project_link = document.createElement('a'),
forum_link = document.createElement('a');
if (supervisor) {
var supervisor_field_label = document.createElement('label'),
supervisor_value_span = document.createElement('span');
supervisor_line_div.classList.add("field", "project-line");
supervisor_field_label.innerHTML = SUPERVISOR_FIELD_TITLE;
supervisor_value_span.innerHTML = supervisor;
supervisor_line_div.appendChild(supervisor_field_label);
supervisor_line_div.appendChild(supervisor_value_span);
right_div.appendChild(supervisor_line_div);
}
box_div.classList.add("project-box");
title_div.classList.add("project-title");
project_link.href = project_url;
project_link.innerHTML = project_title;
title_div.appendChild(project_link);
info_div.classList.add("project-info");
left_info_div.classList.add("left");
right_line_div.classList.add("project-line");
//TODO
forum_link.href = "TODO";
forum_link.innerHTML = project_id + " forum link";
right_line_div.appendChild(forum_link);
right_div.appendChild(right_line_div);
info_div.appendChild(left_info_div);
info_div.appendChild(right_div);
box_div.appendChild(title_div);
box_div.appendChild(info_div);
project_element.appendChild(box_div);
return [project_element, left_info_div];
}
function createProjectLineHtmlElement(project_id, portal_type, title, total_count, out_count, status_color) {
var line_div = document.createElement('div'),
status = document.createElement('span'),
name = document.createElement('span'),
outdated = document.createElement('span'),
total = document.createElement('span'),
open_bracket = document.createElement('span'),
close_bracket = document.createElement('span');
line_div.classList.add("project-line");
status.classList.add(STATUS_SPAN);
status.classList.add(status_color);
status.classList.add("margined");
status.setAttribute("id", getProjectSpanId(project_id, portal_type, STATUS_SPAN));
name.classList.add("name");
name.classList.add("margined");
name.innerHTML = title;
total.classList.add("margined");
total.innerHTML = total_count;
total.setAttribute("id", getProjectSpanId(project_id, portal_type, TOTAL_SPAN));
outdated.innerHTML = out_count;
outdated.setAttribute("id", getProjectSpanId(project_id, portal_type, OUTDATED_SPAN));
line_div.appendChild(status);
line_div.appendChild(name);
line_div.appendChild(total);
open_bracket.innerHTML = "(";
close_bracket.innerHTML = ")";
line_div.appendChild(open_bracket);
line_div.appendChild(outdated);
line_div.appendChild(close_bracket);
return line_div;
}
return gadget.getSetting("hateoas_url")
.push(function (hateoas_url) {
for (i = 0; i < project_list.length; i += 1) {
url_parameter_list.push({
command: 'push_history',
options: {
'jio_key': project_list[i].id,
'page': 'form',
'view': hateoas_url +
'/ERP5Document_getHateoas?mode=traverse&relative_url=' +
project_list[i].id +
'&view=Project_viewQuickOverview'
}
});
}
return gadget.getUrlForList(url_parameter_list);
})
.push(function (url_list) {
spinner.classList.add("ui-hidden");
for (i = 0; i < project_list.length; i += 1) {
project_html_element_list = createProjectHtmlElement(project_list[i].id, project_list[i].value.title,
url_list[i], project_list[i].value.source_decision_title);
project_html = project_html_element_list[0];
left_div_html = project_html_element_list[1];
for (var type in PORTAL_TITLE_DICT) {
if (PORTAL_TITLE_DICT.hasOwnProperty(type)) {
left_line_html = createProjectLineHtmlElement(project_list[i].id, type,
((PORTAL_TITLE_DICT.hasOwnProperty(type)) ? PORTAL_TITLE_DICT[type] : type),
0, 0, NONE_STATUS);
left_div_html.appendChild(left_line_html);
}
}
ul_list.appendChild(project_html);
}
});
}
rJS(window)
/////////////////////////////////////////////////////////////////
// Acquired methods
/////////////////////////////////////////////////////////////////
.declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("getUrlForList", "getUrlForList")
.declareAcquiredMethod("jio_allDocs", "jio_allDocs")
.declareAcquiredMethod("getSetting", "getSetting")
.declareMethod('render', function (options) {
var gadget = this;
return getProjectList(gadget)
.push(function (project_list) {
options.project_list = project_list;
return gadget.changeState(options);
});
})
.onStateChange(function (modification_dict) {
var gadget = this;
return gadget.updateHeader({
page_title: 'Project Management'
});
})
.declareService(function () {
var gadget = this;
return renderProjectList(gadget, gadget.state.project_list)
.push(function () {
//run the rest of queries and render async
gadget.renderMilestoneInfo();
gadget.renderProjectDocumentInfo();
gadget.renderOutdatedDocumentInfo();
gadget.renderTestResultInfo();
});
})
.declareJob("renderMilestoneInfo", function () {
var gadget = this,
i, outdated,
milestone_list,
milestone_query = Query.objectToSearchText(
getComplexQuery({"portal_type" : "Project Milestone",
"validation_state" : "validated",
"parent__portal_type" : "Project"},
"AND"));
return new RSVP.Queue()
.push(function () {
return gadget.jio_allDocs({
query: milestone_query,
limit: QUERY_LIMIT,
select_list: ["title", 'portal_type', "parent__title", "parent__relative_url"],
sort_on: [["modification_date", "descending"]]
})
.push(function (result) {
milestone_list = result.data.rows;
for (i = 0; i < milestone_list.length; i += 1) {
outdated = (new Date(milestone_list[i].value.modification_date) < LIMIT_DATE) ? 1 : 0;
renderProjectLine(getProjectId(milestone_list[i].id),
milestone_list[i].value.portal_type,
1, outdated);
}
});
});
})
.declareJob("renderProjectDocumentInfo", function () {
var gadget = this,
i,
document_list;
return getProjectDocumentList(gadget)
.push(function (document_list) {
for (i = 0; i < document_list.length; i += 1) {
renderProjectLine(getProjectId(document_list[i].value.source_project__relative_url),
document_list[i].value.portal_type,
1, 0);
}
});
})
.declareJob("renderOutdatedDocumentInfo", function () {
var gadget = this,
i,
limit_date = LIMIT_DATE.toISOString()
.substring(0, LIMIT_DATE.toISOString().length - 5)
.replace("T", " "),
document_list;
//XXX For testing
limit_date = new Date().toISOString().substring(0, LIMIT_DATE.toISOString().length - 5).replace("T", " ");
return getProjectDocumentList(gadget, limit_date)
.push(function (document_list) {
for (i = 0; i < document_list.length; i += 1) {
renderProjectLine(getProjectId(document_list[i].value.source_project__relative_url),
document_list[i].value.portal_type,
0, 1);
}
});
})
.declareJob("renderTestResultInfo", function () {
var gadget = this,
i,
test_list,
test_result_query = Query.objectToSearchText(
getComplexQuery({"portal_type" : "Test Result",
"source_project__validation_state" : "validated"},
"AND")),
test_state_list = ["failed", "stopped", "public_stopped"];
test_result_query += ' AND simulation_state: ("' + test_state_list.join('", "') + '")';
return gadget.jio_allDocs({
query: test_result_query,
limit: QUERY_LIMIT,
select_list: ['source_project__relative_url', 'portal_type'],
group_by: ['source_project__relative_url'],
sort_on: [["modification_date", "descending"]]
})
.push(function (result) {
test_list = result.data.rows;
for (i = 0; i < test_list.length; i += 1) {
//TODO total and outdated values should come with the test-result-row
//(all_tests and failed) but those are _local_properties
renderProjectLine(test_list[i].value.source_project__relative_url,
test_list[i].value.portal_type,
//
1, //parseInt(test_list[i].value.all_test, RADIX)
0); //parseInt(test_list[i].value.failures, RADIX)
}
});
})
.declareMethod('getContent', function () {
return {};
})
.declareMethod('checkValidity', function () {
return true;
});
}(window, rJS, RSVP, document, SimpleQuery, ComplexQuery, Query, parseInt));
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Script" 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>default_reference</string> </key>
<value> <string>gadget_erp5_page_project_front_page.js</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>project_gadget_page_project_front_page_js</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 Script</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Gadget Project Front Page JS</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>1582735328.68</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>982.7901.64054.59665</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>1582796562.97</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> <string>detect_converted_file</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>external_processing_state</string> </key>
<value> <string>converted</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>1582735282.78</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>Base_doSelect</string> </value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>listbox</string>
</list>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list>
<string>listbox_delivery_start_date</string>
<string>listbox_delivery_stop_date</string>
</list>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ProjectModule_viewProjectManagementList</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>ProjectModule_viewProjectList</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_list</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Projects</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>all_columns</string>
<string>columns</string>
<string>domain_root_list</string>
<string>domain_tree</string>
<string>editable_columns</string>
<string>portal_types</string>
<string>search_columns</string>
<string>selection_name</string>
<string>title</string>
<string>url_columns</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>Base_viewSearchResultList</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>all_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>all_editable_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>columns</string> </key>
<value>
<list>
<tuple>
<string>title</string>
<string>Title</string>
</tuple>
<tuple>
<string>reference</string>
<string>Reference</string>
</tuple>
<tuple>
<string>default_destination_section_title</string>
<string>Billable Client</string>
</tuple>
<tuple>
<string>source_decision_title</string>
<string>Supervisor</string>
</tuple>
<tuple>
<string>delivery.start_date</string>
<string>Begin Date</string>
</tuple>
<tuple>
<string>delivery.stop_date</string>
<string>End Date</string>
</tuple>
<tuple>
<string>default_destination_title</string>
<string>Location</string>
</tuple>
<tuple>
<string>translated_validation_state_title</string>
<string>State</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>domain_root_list</string> </key>
<value>
<list>
<tuple>
<string>state_project_domain</string>
<string>Project Status</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>domain_tree</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>editable_columns</string> </key>
<value>
<list>
<tuple>
<string>delivery.start_date</string>
<string>Begin Date</string>
</tuple>
<tuple>
<string>delivery.stop_date</string>
<string>End Date</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_list_mode_listbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>portal_types</string> </key>
<value>
<list>
<tuple>
<string>Project</string>
<string>Project</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>search_columns</string> </key>
<value>
<list>
<tuple>
<string>title</string>
<string>Title</string>
</tuple>
<tuple>
<string>reference</string>
<string>Reference</string>
</tuple>
<tuple>
<string>default_destination_section_title</string>
<string>Billable Client</string>
</tuple>
<tuple>
<string>source_decision_title</string>
<string>Supervisor</string>
</tuple>
<tuple>
<string>delivery.start_date</string>
<string>Begin Date</string>
</tuple>
<tuple>
<string>delivery.stop_date</string>
<string>End Date</string>
</tuple>
<tuple>
<string>default_destination_title</string>
<string>Location</string>
</tuple>
<tuple>
<string>translated_validation_state_title</string>
<string>State</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>selection_name</string> </key>
<value> <string>project_module_project_management_selection</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Projects</string> </value>
</item>
<item>
<key> <string>url_columns</string> </key>
<value>
<list>
<tuple>
<string>title</string>
<string>Project_getQuickViewUrl</string>
</tuple>
<tuple>
<string>default_destination_section_title</string>
<string>Project_getQuickViewUrl</string>
</tuple>
</list>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>editable</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_delivery_start_date</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_start_date</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Project_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>editable</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_delivery_stop_date</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_stop_date</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Project_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
#generate-rss {
padding: 5.5pt;
margin-right: 12pt;
background-color: #FF6600;
border-color: #FF6600;
color: #FFFFFF;
border-radius: 0.325em;
border-width: 0.5px;
border-style: solid;
min-width: 6em;
line-height: 1.5;
display: none;
text-align: center;
width: fit-content;
/* FRONT PAGE */
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list {
margin-top: 10px;
}
.restore-button {
padding: 6pt;
margin-right: 12pt;
background-color: #FF6600;
color: #FFFFFF;
border-radius: 0.325em;
border-width: 0.5px;
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box {
margin-bottom: 10px;
border-style: solid;
min-width: 8em;
line-height: 1.5;
border-width: 1px;
border-radius: 5px;
padding: 5px;
padding: 5px;
padding-left: 15px;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] a {
color: #267B87;
text-decoration: none;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .project-info {
display: inline-flex;
width: 100%
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .project-info .left {
width: 35%;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .project-line {
margin-bottom: 5px;
font-family: "Roboto", Arial, sans-serif;
font-size: 1.25em;
line-height: 1.58em;
letter-spacing: -.003em;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .project-line.field {
display: flex;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .project-line.field label {
color: #767676;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .project-line.field span {
margin-left: 15px;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .project-title {
color: #19535F;
font-weight: normal;
font-size: 24px;
line-height: 33px;
font-weight: bold;
margin-bottom: 5px;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box span.margined {
margin-right: 5px;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .status {
padding-left: 21px;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .status.none {
background: #adadad !important;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .status.none.orange {
background: #f0ad4e !important;
}
#wrap1 iframe {
height: 100%;
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .status.none.red {
background: #de1e00 !important;
}
#wrap2 iframe {
height: 100%;
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .front-project-list .project-box .status.none.green {
background: #00b80c !important;
}
.gadget-content .ui-field-contain .graph-spinner {
position: relative;
top: 100px;
width: 120px;
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .loader {
position: fixed;
left: 50%;
top: 50%;
font-size: 300%;
animation-name: fadein;
animation-duration: 0.2s;
animation-delay: 0.3s;
animation-fill-mode: both;
animation-timing-function: ease-in;
}
.gadget-content .ui-field-contain .count-spinner {
top: 20px;
width: 120px;
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .ui-icon-spinner {
opacity: 1;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .ui-icon-spinner::before {
content: "\f110";
animation: spin 0.5s infinite linear;
}
div[data-gadget-url$="gadget_erp5_page_project_front_page.html"] .ui-icon-spinner.ui-hidden {
visibility: hidden;
}
/* PROJECT PAGE */
.gadget-content .ui-field-contain .bottom .first-line-buttons {
-webkit-appearance: none;
margin-top: 0;
......@@ -123,4 +187,38 @@ input[type="submit"] {
.worklist-title {
color: #777777;
margin-top: 10px;
}
/* PROJECT HOME PAGE */
body.cke_editable h1 {
margin-top: 1.5em;
font-family: "Roboto", Arial, sans-serif;
color: #19535F;
font-size: 2em;
margin: 0.67em 0;
}
body.cke_editable h2 {
font-family: "Roboto", Arial, sans-serif;
font-weight: normal;
font-size: 25px;
line-height: 33px;
color: #19535F;
}
body.cke_editable p, body.cke_editable li, body.cke_editable span {
font-family: 'Heuristica', 'Helvetica', Times, serif;
}
body.cke_editable ul li, body.cke_editable p {
font-size: 1.25em;
line-height: 1.58em;
letter-spacing: -.003em;
}
body.cke_editable a {
color: #267B87;
text-decoration: none;
}
\ No newline at end of file
......@@ -3,6 +3,10 @@
(function (window, rJS, RSVP, document, ensureArray, DOMParser, XMLSerializer, SimpleQuery, ComplexQuery, Query) {
"use strict";
/*jshint esnext: true */
const VALID_STATE_LIST = ["shared", "released", "published",
"shared_alive", "released_alive", "published_alive"];
function addRedirectionToReference(href, url) {
if (!href.startsWith("https") && !href.startsWith("http") &&
!href.startsWith("ftp") && !href.includes("/")
......@@ -14,13 +18,15 @@
function parseHTMLLinks(html, url) {
var parser = new DOMParser(), i,
//TODO create head and link html elements and prepend to doc instead of using text
styles_header = '<head><link rel="stylesheet" type="text/css" href="gadget_project_info.css"></head>',
oSerializer = new XMLSerializer(),
doc = parser.parseFromString(html, "text/html"),
link_list = doc.getElementsByTagName("a");
for (i = 0; i < link_list.length; i += 1) {
link_list[i].setAttribute('href', addRedirectionToReference(link_list[i].getAttribute('href'), url));
}
return oSerializer.serializeToString(doc);
return styles_header + oSerializer.serializeToString(doc);
}
function enableLink(link_element, url) {
......@@ -128,13 +134,6 @@
type: "simple",
value: "Web Page"
}));
query_list.push(new SimpleQuery({
key: "validation_state",
operator: "=",
type: "simple",
value: ("shared", "released", "published", "shared_alive",
"released_alive", "published_alive")
}));
query_list.push(new SimpleQuery({
key: "follow_up__relative_url",
operator: "=",
......@@ -152,6 +151,7 @@
query_list: query_list,
type: "complex"
}));
query += ' AND validation_state: ("' + VALID_STATE_LIST.join('", "') + '")';
return gadget.getUrlFor({command: 'push_history', options: {page: "project_redirector"}})
.push(function (url) {
redirector_ulr = url;
......@@ -220,7 +220,7 @@
gadget.getSetting("hateoas_url")
];
if (modification_dict.publication_section) {
promise_list.push(gadget.getDeclaredGadget("editor")),
promise_list.push(gadget.getDeclaredGadget("editor"));
promise_list.push(getWebPageInfo(gadget, modification_dict.jio_key, modification_dict.publication_section));
}
return RSVP.all(promise_list);
......
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