N°330 Attachments display as table : portal

This commit is contained in:
Pierre Goiffon
2019-12-16 14:44:56 +01:00
parent 473a55bde6
commit 434ed0dd4e
5 changed files with 247 additions and 81 deletions

View File

@@ -20,6 +20,7 @@
namespace Combodo\iTop\Renderer\Bootstrap\FieldRenderer;
use AbstractAttachmentsRenderer;
use AttachmentPlugIn;
use Combodo\iTop\Renderer\RenderingOutput;
use DBObjectSearch;
@@ -29,7 +30,11 @@ use InlineImage;
use utils;
/**
* Description of BsFileUploadFieldRenderer
* This is the class used to render attachments in the user portal.
*
* In the iTop console this is handled in the itop-attachments module. Most of the code here is a duplicate of this module.
*
* @see \AbstractAttachmentsRenderer and its implementations for the iTop console
*
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
*/
@@ -43,8 +48,7 @@ class BsFileUploadFieldRenderer extends BsFieldRenderer
$oOutput = parent::Render();
$sObjectClass = get_class($this->oField->GetObject());
$sIsDeleteAllowed = ($this->oField->GetAllowDelete() && !$this->oField->GetReadOnly()) ? 'true' : 'false';
$sDeleteBtn = Dict::S('Portal:Button:Delete');
$bIsDeleteAllowed = ($this->oField->GetAllowDelete() && !$this->oField->GetReadOnly());
$sTempId = utils::GetUploadTempId($this->oField->GetTransactionId());
$sUploadDropZoneLabel = Dict::S('Portal:Attachments:DropZone:Message');
@@ -68,7 +72,7 @@ class BsFileUploadFieldRenderer extends BsFieldRenderer
$oOutput->AddHtml('<div class="fileupload_field_content">');
// Files list
$oOutput->AddHtml('<div class="attachments_container row">');
$this->PrepareExistingFiles($oOutput);
$this->PrepareExistingFiles($oOutput, $bIsDeleteAllowed);
$oOutput->Addhtml('</div>');
// Removing upload input if in read only
@@ -89,9 +93,24 @@ class BsFileUploadFieldRenderer extends BsFieldRenderer
$sMaxUploadLabel = AttachmentPlugIn::GetMaxUpload();
$sFileTooBigLabel = Dict::Format('Attachments:Error:FileTooLarge', $sMaxUploadLabel);
$sFileTooBigLabelForJS = addslashes($sFileTooBigLabel);
// Note : This is based on itop-attachement/main.attachments.php
// Note : This is based on itop-attachement/main.itop-attachments.php
$sAttachmentTableRowTemplate = json_encode(self::GetAttachmentTableRow(
'{{iAttId}}',
'{{sLineStyle}}',
'{{sDocDownloadUrl}}',
'{{sIconClass}}',
'{{sAttachmentThumbUrl}}',
'{{sFileName}}',
'{{sAttachmentMeta}}',
'{{sFileSize}}',
'{{sAttachmentDate}}',
'{{sAttachmentCreator}}',
'{{sFileType}}',
$bIsDeleteAllowed
));
$oOutput->AddJs(
<<<EOF
<<<JS
var attachmentRowTemplate = $sAttachmentTableRowTemplate;
var RemoveAttachment = function(sAttId)
{
$('#attachment_' + sAttId).attr('name', 'removed_attachments[]');
@@ -110,29 +129,41 @@ class BsFileUploadFieldRenderer extends BsFieldRenderer
}
else
{
var sDownloadLink = '{$this->oField->GetDownloadEndpoint()}'.replace(/-sAttachmentId-/, data.result.att_id);
var iAttId = data.result.att_id,
sDownloadLink = '{$this->oField->GetDownloadEndpoint()}'.replace(/-sAttachmentId-/, iAttId),
sIconClass = (data.result.preview == 'true') ? ' preview' : '',
sAttachmentMeta = '<input id="attachment_'+iAttId+'" type="hidden" name="attachments[]" value="'+iAttId+'"/>';
$(this).closest('.fileupload_field_content').find('.attachments_container').append(
'<div class="attachment col-xs-6 col-sm-3 col-md-2" id="display_attachment_'+data.result.att_id+'">'+
' <a data-preview="'+data.result.preview+'" href="'+sDownloadLink+'" target="_blank" title="'+data.result.msg+'">'+
' <div class="attachment_icon"><img src="'+data.result.icon+'"></div>'+
' <div class="attachment_name">'+data.result.msg+'</div>'+
' <input id="attachment_'+data.result.att_id+'" type="hidden" name="attachments[]" value="'+data.result.att_id+'"/>'+
' </a>'+
' <input type="button" class="btn btn-xs btn-danger hidden" value="{$sDeleteBtn}"/>'+
'</div>'
);
var replaces = [
{search: "{{iAttId}}", replace:iAttId },
{search: "{{lineStyle}}", replace:'' },
{search: "{{sDocDownloadUrl}}", replace:sDownloadLink },
{search: "{{sIconClass}}", replace:sIconClass },
{search: "{{sAttachmentThumbUrl}}", replace:data.result.icon },
{search: "{{sFileName}}", replace: data.result.msg },
{search: "{{sAttachmentMeta}}", replace:sAttachmentMeta },
{search: "{{sFileSize}}", replace:data.result.file_size },
{search: "{{sAttachmentDate}}", replace:data.result.creation_date },
{search: "{{sAttachmentCreator}}", replace:data.result.contact_id_friendlyname },
{search: "{{sFileType}}", replace:data.result.file_type }
];
var sAttachmentRow = attachmentRowTemplate;
$.each(replaces, function(indexInArray, value ) {
var re = new RegExp(value.search, 'gi');
sAttachmentRow = sAttachmentRow.replace(re, value.replace);
});
$(this).closest('.fileupload_field_content').find('.attachments_container table.attachmentsList>tbody').append(sAttachmentRow);
// Preview tooltip
if(data.result.preview){
$('#display_attachment_'+data.result.att_id).tooltip({
$('#display_attachment_'+data.result.att_id +' a.trigger-preview').tooltip({
container: 'body',
html: true,
title: function(){ return '<div style="width: 350px; height: 300px;"><img src="'+sDownloadLink+'" style="max-width: 100%; max-height: 100%;" /></div>'; }
title: function(){
return '<div style="width: 350px; height: 300px;"><img src="'+sDownloadLink+'" style="max-width: 100%; max-height: 100%;" /></div>';
}
});
}
// Showing remove button on hover
$('#display_attachment_'+data.result.att_id).hover( function(){
$(this).children(':button').toggleClass('hidden');
});
// Remove button handler
$('#display_attachment_'+data.result.att_id+' :button').click(function(oEvent){
oEvent.preventDefault();
@@ -174,24 +205,18 @@ class BsFileUploadFieldRenderer extends BsFieldRenderer
// Preview tooltip
$('.attachment [data-preview="true"]').each(function(iIndex, oElem){
$('table.attachmentsList>tbody>tr>td a.trigger-preview').each(function(iIndex, oElem){
$(oElem).parent().tooltip({
container: 'body',
html: true,
title: function(){ return '<div style="width: 350px; height: 300px;"><img src="'+$(oElem).attr('href')+'" style="max-width: 100%; max-height: 100%;" /></div>'; }
});
});
// Remove button handler
$('.attachments_container .attachment :button').click(function(oEvent){
$('.attachments_container table.attachmentsList>tbody>tr>td :button').click(function(oEvent){
oEvent.preventDefault();
RemoveAttachment($(this).closest('.attachment').find(':input[name="attachments[]"]').val());
});
// Remove button showing
if($sIsDeleteAllowed)
{
$('.attachment').hover( function(){
$(this).find(':button').toggleClass('hidden');
});
}
// Handles a drag / drop overlay
if($('#drag_overlay').length === 0)
@@ -236,8 +261,7 @@ class BsFileUploadFieldRenderer extends BsFieldRenderer
oDropZone.removeClass('drag_in').addClass('drag_out');
}, 200);
});
EOF
JS
);
return $oOutput;
@@ -246,12 +270,13 @@ EOF
/**
*
* @param \Combodo\iTop\Renderer\RenderingOutput $oOutput
* @param boolean $bIsDeleteAllowed
*
* @throws \Exception
* @throws \CoreException
* @throws \OQLException
*/
protected function PrepareExistingFiles(RenderingOutput &$oOutput)
protected function PrepareExistingFiles(RenderingOutput $oOutput, $bIsDeleteAllowed)
{
$sObjectClass = get_class($this->oField->GetObject());
$sDeleteBtn = Dict::S('Portal:Button:Delete');
@@ -268,29 +293,124 @@ EOF
}
else
{
$sTitleThumbnail = Dict::S('Attachments:File:Thumbnail');
$sTitleFileName = Dict::S('Attachments:File:Name');
$sTitleFileSize = Dict::S('Attachments:File:Size');
$sTitleFileDate = Dict::S('Attachments:File:Date');
$sTitleFileCreator = Dict::S('Attachments:File:Creator');
$sTitleFileType = Dict::S('Attachments:File:MimeType');
$oOutput->Addhtml(<<<HTML
<table class="table table-striped attachmentsList">
<thead>
<th>$sTitleThumbnail</th>
<th>$sTitleFileName</th>
<th>$sTitleFileSize</th>
<th>$sTitleFileDate</th>
<th>$sTitleFileCreator</th>
<th>$sTitleFileType</th>
<th></th>
</thead>
<tbody>
HTML
);
while ($oAttachment = $oSet->Fetch())
{
$iAttId = $oAttachment->GetKey();
$sLineStyle = '';
$sAttachmentMeta = '<input id="attachment_'.$iAttId.'" type="hidden" name="attachments[]" value="'.$iAttId.'">';
$oDoc = $oAttachment->Get('contents');
$sFileName = htmlentities($oDoc->GetFileName(), ENT_QUOTES, 'UTF-8');
$sIcon = utils::GetAbsoluteUrlAppRoot().'env-'.utils::GetCurrentEnvironment().'/itop-attachments/icons/image.png';
$sPreview = $oDoc->IsPreviewAvailable() ? 'true' : 'false';
$sDownloadLink = str_replace('-sAttachmentId-', $iAttId, $this->oField->GetDownloadEndpoint());
$oOutput->Addhtml(
<<<EOF
<div class="attachment col-xs-6 col-sm-3 col-md-2" id="display_attachment_{$iAttId}">
<a data-preview="{$sPreview}" href="{$sDownloadLink}" target="_blank" title="{$sFileName}" >
<div class="attachment_icon"><img src="{$sIcon}"></div>
<div class="attachment_name">{$sFileName}</div>
<input id="attachment_{$iAttId}" type="hidden" name="attachments[]" value="{$iAttId}"/>
</a>
<input id="btn_remove_{$iAttId}" type="button" class="btn btn-xs btn-danger hidden" value="{$sDeleteBtn}"/>
</div>
EOF
);
$sDocDownloadUrl = str_replace('-sAttachmentId-', $iAttId, $this->oField->GetDownloadEndpoint());
$sAttachmentThumbUrl = utils::GetAbsoluteUrlAppRoot().AttachmentPlugIn::GetFileIcon($sFileName);
$sIconClass = '';
if ($oDoc->IsPreviewAvailable())
{
$sIconClass = ' preview';
if ($oDoc->GetSize() <= AbstractAttachmentsRenderer::MAX_SIZE_FOR_PREVIEW)
{
$sAttachmentThumbUrl = $sDocDownloadUrl;
}
}
$sFileSize = $oDoc->GetFormatedSize();
$sFileType = $oDoc->GetMimeType();
$bIsTempAttachment = ($oAttachment->Get('item_id') === 0);
$sAttachmentDate = '';
if (!$bIsTempAttachment)
{
$sAttachmentDate = $oAttachment->Get('creation_date');
}
$sAttachmentCreator = $oAttachment->Get('contact_id_friendlyname');
$oOutput->Addhtml(self::GetAttachmentTableRow(
$iAttId,
$sLineStyle,
$sDocDownloadUrl,
$sIconClass,
$sAttachmentThumbUrl,
$sFileName,
$sAttachmentMeta,
$sFileSize,
$sAttachmentDate,
$sAttachmentCreator,
$sFileType,
$bIsDeleteAllowed
));
}
$oOutput->Addhtml(<<<HTML
</tbody>
</table>
HTML
);
}
}
/**
* @param $iAttId
* @param $sLineStyle
* @param $sDocDownloadUrl
* @param $sIconClass
* @param $sAttachmentThumbUrl
* @param $sFileName
* @param $sAttachmentMeta
* @param $sFileSize
* @param $sAttachmentDate
* @param $sAttachmentCreator
* @param $sFileType
* @param $bIsDeleteAllowed
*
* @return string
*/
protected static function GetAttachmentTableRow(
$iAttId, $sLineStyle, $sDocDownloadUrl, $sIconClass, $sAttachmentThumbUrl, $sFileName, $sAttachmentMeta, $sFileSize,
$sAttachmentDate, $sAttachmentCreator, $sFileType, $bIsDeleteAllowed
) {
$sDeleteButton = '';
if ($bIsDeleteAllowed)
{
$sDeleteBtnLabel = Dict::S('Portal:Button:Delete');
$sDeleteButton = '<input id="btn_remove_'.$iAttId.'" type="button" class="btn btn-xs btn-danger" value="'.$sDeleteBtnLabel.'">';
}
return <<<HTML
<tr id="display_attachment_{$iAttId}" class="attachment" $sLineStyle>
<td><a href="$sDocDownloadUrl" target="_blank" class="trigger-preview $sIconClass"><img $sIconClass style="max-height: 48px;" src="$sAttachmentThumbUrl"></a></td>
<td><a href="$sDocDownloadUrl" target="_blank" class="$sIconClass">$sFileName</a>$sAttachmentMeta</td>
<td>$sFileSize</td>
<td>$sAttachmentDate</td>
<td>$sAttachmentCreator</td>
<td>$sFileType</td>
<td>$sDeleteButton</td>
</tr>
HTML;
}
}