/*
* Copyright 2018 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Abstract tool to display the history of a content in a timeline
* @private
*/
Ext.define('Ametys.plugins.odf.pilotage.tool.AbstractTimelineTool', {
extend: "Ametys.tool.SelectionTool",
/**
* @private
* @readonly
* @property {Number} MIN_WIDTH The min width
*/
MIN_WIDTH: 350,
constructor: function(config)
{
this.callParent(arguments);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onDeleted, this);
},
createPanel: function()
{
this._timeline = Ext.create('Ametys.timeline.Timeline', {
scrollable: true,
minInsideWidth: this.MIN_WIDTH,
dockedItems: {
dock: 'top',
ui: 'tool-hintmessage',
xtype: 'component',
html: ''
},
viewConfig: {
getRowClass: function(record) {
return record.get('live') ? 'row-live' : (record.get('valid') ? 'row-valid' : '');
},
},
cls: ['a-timeline', 'uitool-history'],
timelineItemHTML: ['<div class="step-wrap {stepCls} {additionalCls}"><div class="step">{step}</div></div>',
'<div class="timeline-item additionalCls">',
'<div class="profile-img-wrap" data-qtip="{userTooltip}">',
'<tpl if="profileImg"><img src="{profileImg}" alt=""/></tpl>',
'<tpl if="profileGlyph"><span style="height:46px; width: 46px; font-size: 46px" class="profile-img-glyph {profileGlyph}"></span></tpl>',
'</div>',
'<div class="version-line"></div>',
'<div class="contents-wrap" data-step="{stepId}">',
'<span class="vertical-line"></span>',
'<tpl if="topText && topText != \'\'">',
'<div class="top">toptext</div>',
'</tpl>',
'<div class="text" data-qtip="{userTooltip}">{text}</div>',
'<tpl if="comment && comment != \'\'">',
'<div class="comment"><span class="x-fa fa-quote-left"></span>{comment}</div>',
'</tpl>',
'<tpl if="icon && icon != \'\'">',
'<span class="icon"></span>',
'</tpl>',
'</div>',
'</div>']
});
return Ext.create('Ext.panel.Panel', {
scrollable: false,
border: false,
layout: 'card',
activeItem: 0,
items: [{
xtype: 'component',
cls: 'a-panel-text-empty',
border: false,
html: ''
},
this._timeline
]
});
},
refresh: function (manual)
{
this.showRefreshing();
var contentTarget = this.getCurrentSelectionTargets()[0];
this._contentId = contentTarget.getParameters().id;
this.getContentPanel().items.get(1).down("*[dock='top']").hide();
var params = {contentId: this._contentId};
Ametys.data.ServerComm.send({
plugin: this.getPluginName(),
url: this.getTimelineUrl(),
parameters: {contentId: this._contentId},
priority: Ametys.data.ServerComm.PRIORITY_MAJOR,
callback: {
handler: this._updateHistoryView,
scope: this,
arguments: [this._contentId]
},
responseType: 'text'
});
},
updateHintTpl: function(hintEl, result)
{
throw new Error('updateHintTpl is not a implemented!');
},
getTimelineUrl: function()
{
throw new Error('getTimelineUrl is not a implemented!');
},
/**
* @private
* Callback function to update the history view
* @param {Object} response the server response
* @param {Object} args the callback arguments
*/
_updateHistoryView : function (response, args)
{
var result = Ext.JSON.decode(Ext.dom.Query.selectValue("", response));
if (result != null)
{
var me = this;
var data = [];
var steps = result.workflow || [];
var precedeVersion = null;
var beyondIncompatibleVersion = false;
this.updateHintTpl(this.getContentPanel().items.get(1).down("*[dock='top']"), result);
this.getContentPanel().items.get(1).down("*[dock='top']").show();
for (var i=0; i < steps.length; i++)
{
var step = steps[i];
var d = me._convertStep2Timeline(step);
data.push(d);
}
this._timeline.getStore().loadData(data);
this.getContentPanel().getLayout().setActiveItem(1);
}
else
{
this.getContentPanel().getLayout().setActiveItem(0);
}
this.showRefreshed();
},
/**
* @private
* Convert a workflow step record to a timeline record
* @param {Object} step the workflow step
* @return {Object} the configuration of a timeline record
*/
_convertStep2Timeline: function (step)
{
var username = step.author ? step.author.fullname || step.author.login : "{{i18n plugin.core:PLUGINS_CORE_USERS_UNKNOWN_USER}}";
return {
id: this.getId() + '-' + Ext.id(),
date: step.date,
username: (step.author ? step.author.fullname : '') || "{{i18n plugin.core:PLUGINS_CORE_USERS_UNKNOWN_USER}}",
userTooltip: step.author ? this._getUserTooltip(step.author) : null,
profileImg: Ametys.helper.Users.getUserImage(step.author ? step.author.login : 'undefined', step.author ? step.author.populationId : 'undefined', 46),
icon: Ametys.CONTEXT_PATH + step.actionIconMedium,
text: Ext.String.format(step.actionLabel, username),
step: step.title,
comment: step.comment,
stepId: step.id,
topText: '',
stepCls: 'step'
}
},
/**
* @private
* Compute the tooltip
* @param {Object} user The user to display
* @returns {String} The tooltip
*/
_getUserTooltip: function(user)
{
var login = user.login;
var populationId = user.populationId;
var username = user.fullname || "{{i18n plugin.core:PLUGINS_CORE_USERS_UNKNOWN_USER}}";
var populationLabel = user.populationLabel || populationId;
return Ametys.helper.Users.renderUser(login, populationLabel, username);
},
/**
* Listener on {@link Ametys.message.Message#MODIFIED} message. If the current
* content is concerned, the tool will be out-of-date.
*
* @param {Ametys.message.Message} message The workflow changed message.
* @protected
*/
_onModified: function (message)
{
if (this.getTargetsInCurrentSelectionTargets(message).length > 0)
{
this.showOutOfDate();
}
},
/**
* Listener on {@link Ametys.message.Message#DELETED} message. If the current content is concerned, the tool will be set in no selection mode.
* @param {Ametys.message.Message} message The deleted message.
* @protected
*/
_onDeleted: function (message)
{
if (this.getTargetsInCurrentSelectionTargets(message).length > 0)
{
this.setNoSelectionMatchState();
}
},
setNoSelectionMatchState: function (message)
{
this.callParent(arguments);
var panel = this.getContentPanel().items.get(0);
panel.update(message);
this.getContentPanel().getLayout().setActiveItem(0);
this._contentId = null;
}
});