/home/ivoiecob/email.hirewise-va.com/modules/FilesWebclient/js/views/CFilesView.js
'use strict'
const _ = require('underscore'),
$ = require('jquery'),
ko = require('knockout')
const TextUtils = require('%PathToCoreWebclientModule%/js/utils/Text.js'),
Types = require('%PathToCoreWebclientModule%/js/utils/Types.js'),
Utils = require('%PathToCoreWebclientModule%/js/utils/Common.js'),
Api = require('%PathToCoreWebclientModule%/js/Api.js'),
App = require('%PathToCoreWebclientModule%/js/App.js'),
CJua = require('%PathToCoreWebclientModule%/js/CJua.js'),
CSelector = require('%PathToCoreWebclientModule%/js/CSelector.js'),
ModulesManager = require('%PathToCoreWebclientModule%/js/ModulesManager.js'),
Routing = require('%PathToCoreWebclientModule%/js/Routing.js'),
Screens = require('%PathToCoreWebclientModule%/js/Screens.js'),
UserSettings = require('%PathToCoreWebclientModule%/js/Settings.js'),
CAbstractScreenView = require('%PathToCoreWebclientModule%/js/views/CAbstractScreenView.js'),
Popups = require('%PathToCoreWebclientModule%/js/Popups.js'),
AlertPopup = require('%PathToCoreWebclientModule%/js/popups/AlertPopup.js'),
ConfirmPopup = require('%PathToCoreWebclientModule%/js/popups/ConfirmPopup.js')
const CreateFolderPopup = require('modules/%ModuleName%/js/popups/CreateFolderPopup.js'),
CreateLinkPopup = require('modules/%ModuleName%/js/popups/CreateLinkPopup.js'),
RenamePopup = require('modules/%ModuleName%/js/popups/RenamePopup.js'),
SharePopup = require('modules/%ModuleName%/js/popups/SharePopup.js'),
LinksUtils = require('modules/%ModuleName%/js/utils/Links.js'),
Ajax = require('modules/%ModuleName%/js/Ajax.js'),
Settings = require('modules/%ModuleName%/js/Settings.js'),
CFileModel = require('modules/%ModuleName%/js/models/CFileModel.js'),
CFolderModel = require('modules/%ModuleName%/js/models/CFolderModel.js'),
CStorageModel = require('modules/%ModuleName%/js/models/CStorageModel.js')
const FilesSharePopup = ModulesManager.run('SharedFiles', 'getFilesSharePopup'),
ComposeMessageWithAttachments = ModulesManager.run('MailWebclient', 'getComposeMessageWithAttachments')
const Enums = window.Enums
/**
* @constructor
* @param {boolean=} bPopup = false
* @param {boolean=} allowSelect = true
*/
function CFilesView(bPopup = false, allowSelect = true) {
CAbstractScreenView.call(this, '%ModuleName%')
this.disableRoute = false // can be changed outside
this.browserTitle = ko.observable(TextUtils.i18n('%MODULENAME%/HEADING_BROWSER_TAB'))
this.bAllowSendEmails = _.isFunction(ComposeMessageWithAttachments)
this.error = ko.observable(false)
this.loaded = ko.observable(false)
this.bPublic = App.isPublic()
this.storages = ko.observableArray([])
this.folders = ko.observableArray()
this.files = ko.observableArray()
this.uploadingFiles = ko.observableArray()
this.rootPath = ko.observable(
this.bPublic ? Settings.PublicFolderName : TextUtils.i18n('%MODULENAME%/LABEL_PERSONAL_STORAGE')
)
this.storageType = ko.observable(Enums.FileStorageType.Personal)
this.currentStorage = ko.computed(function () {
return this.getStorageByType(this.storageType())
}, this)
this.storageDroppable = ko.computed(function () {
return this.currentStorage() ? this.currentStorage().droppable() : ''
}, this)
this.storageDisplayName = ko.computed(function () {
return this.currentStorage() ? this.currentStorage().displayName : ''
}, this)
this.storageType.subscribe(function () {
if (this.bPublic) {
this.rootPath(Settings.PublicFolderName)
} else {
if (this.currentStorage()) {
this.rootPath(this.currentStorage().displayName)
}
this.selector.listCheckedAndSelected(false)
}
}, this)
this.createButtonsControllers = ko.observableArray([])
this.pathItems = ko.observableArray()
this.currentPath = ko.observable('')
this.isZipFolder = ko.computed(function () {
var aPath = this.currentPath().split('$ZIP:')
return Utils.getFileExtension(aPath[0]) === 'zip'
}, this)
this.dropPath = ko.observable('')
ko.computed(function () {
this.dropPath(this.currentPath())
}, this)
this.isCorporateStorage = ko.computed(function () {
return this.storageType() === Enums.FileStorageType.Corporate
}, this)
this.isSharedStorage = ko.computed(function () {
return this.storageType() === Enums.FileStorageType.Shared
}, this)
this.isEncryptedStorage = ko.computed(function () {
return this.storageType() === Enums.FileStorageType.Encrypted
}, this)
this.isExternalStorage = ko.computed(function () {
return this.currentStorage() && this.currentStorage().isExternal
}, this)
this.isTrashStorage = ko.computed(function () {
return this.storageType() === Enums.FileStorageType.Trash
}, this)
this.foldersCollection = ko.computed(function () {
var aFolders = this.folders()
aFolders.sort((left, right) => {
let sortValue
switch (this.sortBy()) {
case Enums.FilesSortField.Filename:
case Enums.FilesSortField.Size:
sortValue = left.fileName() === right.fileName() ? 0 : left.fileName() < right.fileName() ? -1 : 1
break
case Enums.FilesSortField.Modified:
sortValue = left.iLastModified === right.iLastModified ? 0 : left.iLastModified < right.iLastModified ? -1 : 1
break
}
if (this.sortBy() !== Enums.FilesSortField.Size) {
sortValue *= this.sortOrder() === Enums.SortOrder.Desc ? -1 : 1
}
return sortValue
})
return aFolders
}, this)
this.filesCollection = ko.computed(function () {
var aFiles = _.union(this.files(), this.getUploadingFiles())
aFiles.sort((left, right) => {
let sortValue
switch (this.sortBy()) {
case Enums.FilesSortField.Filename:
sortValue = left.fileName() === right.fileName() ? 0 : left.fileName() < right.fileName() ? -1 : 1
break
case Enums.FilesSortField.Size:
sortValue = left.size() === right.size() ? 0 : left.size() < right.size() ? -1 : 1
break
case Enums.FilesSortField.Modified:
sortValue = left.iLastModified === right.iLastModified ? 0 : left.iLastModified < right.iLastModified ? -1 : 1
break
}
return sortValue * (this.sortOrder() === Enums.SortOrder.Desc ? -1 : 1)
// return left.fileName() === right.fileName() ? 0 : (left.fileName() < right.fileName() ? -1 : 1);
})
// if (this.sortOrder() === Enums.SortOrder.Asc) {
// aFolderList = aFolderList.reverse();
// }
return aFiles
}, this)
this.collection = ko.computed(function () {
return _.union(this.foldersCollection(), this.filesCollection())
}, this)
this.columnCount = ko.observable(1)
this.selector = new CSelector(
this.collection,
_.bind(this.onItemSelect, this),
_.bind(this.onItemDelete, this),
_.bind(this.onItemDblClick, this),
_.bind(this.onEnter, this),
this.columnCount,
true,
true,
true,
false,
allowSelect
)
this.firstSelectedFile = ko.computed(function () {
return _.find(this.selector.listCheckedAndSelected(), function (oItem) {
return oItem.IS_FILE
})
}, this)
this.selectedOwnItems = ko.computed(function () {
return _.filter(this.selector.listCheckedAndSelected(), function (item) {
return !item.sharedWithMe()
})
}, this)
this.selectedHasShared = ko.computed(function () {
return !!_.find(this.selector.listCheckedAndSelected(), function (oItem) {
return oItem.sharedWithMe()
})
}, this)
this.searchPattern = ko.observable('')
this.newSearchPattern = ko.observable('')
this.isSearchFocused = ko.observable(false)
this.selectedFolders = ko.computed(function () {
return _.filter(
this.selector.listCheckedAndSelected(),
function (oItem) {
return oItem.IS_FOLDER
},
this
)
}, this)
this.selectedFiles = ko.computed(function () {
return _.filter(
this.selector.listCheckedAndSelected(),
function (oItem) {
return oItem.IS_FILE
},
this
)
}, this)
this.allSelectedFilesReady = ko.computed(function () {
return _.every(this.selectedFiles(), function (oItem) {
var bUploading = oItem.uploaded() === false,
bDownloading = oItem.downloading() === true
return !bUploading && !bDownloading
})
}, this)
this.sharedParentFolder = ko.computed(function () {
return _.find(this.pathItems(), function (oParentFolder) {
return oParentFolder.sharedWithMe()
})
}, this)
this.isDownloadAllowed = ko.computed(function () {
var oFile = this.getFileIfOnlyOneSelected()
return !!oFile && oFile.hasAction('download') && this.allSelectedFilesReady()
}, this)
this.downloadCommand = Utils.createCommand(this, this.executeDownload, this.isDownloadAllowed)
this.isSendAllowed = ko.computed(function () {
return !this.isZipFolder() && this.selectedFiles().length > 0 && this.allSelectedFilesReady()
}, this)
this.sendCommand = Utils.createCommand(this, this.executeSend, this.isSendAllowed)
this.isRenameAllowed = ko.computed(function () {
var oSharedParentFolder = this.sharedParentFolder(),
aItems = this.selector.listCheckedAndSelected(),
oSelectedItem = aItems.length === 1 ? aItems[0] : null
return (
!this.isZipFolder() &&
(!oSharedParentFolder || oSharedParentFolder.sharedWithMeAccessWrite()) &&
this.allSelectedFilesReady() &&
oSelectedItem
)
}, this)
this.renameCommand = Utils.createCommand(this, this.executeRename, this.isRenameAllowed)
this.bSortEnabled =
Settings.Sorting &&
Settings.Sorting.Allow &&
Settings.Sorting.DisplayOptions &&
Settings.Sorting.DisplayOptions.length > 0
this.sortBy = ko.observable(Settings.Sorting.DefaultSortBy)
this.sortOrder = ko.observable(Settings.Sorting.DefaultSortOrder)
this.aSortList = []
if (this.bSortEnabled) {
_.each(
Enums.FilesSortField,
function (iValue, sName) {
if (Settings.Sorting.DisplayOptions.indexOf(sName) >= 0) {
this.aSortList.push({
sText: TextUtils.i18n('%MODULENAME%/SORT_OPTION_' + sName.toUpperCase()),
sSortBy: iValue,
})
}
}.bind(this)
)
}
this.itemsToDeleteCount = ko.computed(function () {
var sharedParentFolder = this.sharedParentFolder()
if (!!sharedParentFolder && sharedParentFolder.sharedWithMeAccessWrite()) {
return this.selector.listCheckedAndSelected().length
}
return this.selectedOwnItems().length
}, this)
this.isDeleteAllowed = ko.computed(function () {
return !this.isZipFolder() && this.itemsToDeleteCount() > 0 && this.allSelectedFilesReady()
}, this)
this.deleteCommand = Utils.createCommand(this, this.executeDelete, this.isDeleteAllowed)
this.itemsToRestoreCount = ko.computed(function () {
return this.selector.listCheckedAndSelected().length
}, this)
this.isRestoreAllowed = ko.computed(function () {
return this.isTrashStorage() && this.itemsToRestoreCount() > 0 && this.allSelectedFilesReady()
}, this)
this.restoreCommand = Utils.createCommand(this, this.executeRestore, this.isRestoreAllowed)
this.needToCopyDraggedItems = ko.observable(false)
this.isCurrentStorageDroppable = ko.computed(function () {
return (
!this.sharedParentFolder() ||
this.needToCopyDraggedItems() ||
(this.sharedParentFolder() && this.sharedParentFolder().sharedWithMeAccessWrite())
)
}, this)
this.isCutAllowed = ko.computed(function () {
var oSharedParentFolder = this.sharedParentFolder(),
aItems = this.selector.listCheckedAndSelected()
return (
!this.isZipFolder() &&
((!oSharedParentFolder && !this.isSharedStorage()) ||
(!!oSharedParentFolder && oSharedParentFolder.sharedWithMeAccessWrite())) &&
this.allSelectedFilesReady() &&
aItems.length > 0
)
}, this)
this.isCopyAllowed = ko.computed(function () {
return this.allSelectedFilesReady() && this.selector.listCheckedAndSelected().length > 0
}, this)
this.isDragAllowed = ko.computed(function () {
return this.isCutAllowed() || (this.needToCopyDraggedItems() && this.isCopyAllowed())
}, this)
// is used for share and simple public link
this.isShareAllowed = ko.computed(function () {
const items = this.selector.listCheckedAndSelected(),
selectedItem = items.length === 1 ? items[0] : null,
extendedProps = selectedItem && selectedItem.oExtendedProps
return (
!this.isZipFolder() &&
selectedItem &&
!selectedItem.bIsLink &&
(!this.sharedParentFolder() ||
this.sharedParentFolder().sharedWithMeAccessReshare() ||
selectedItem.sharedWithMeAccessReshare()) &&
this.allSelectedFilesReady() &&
(selectedItem.IS_FILE || !this.isEncryptedStorage()) &&
(!selectedItem.sharedWithMe() || selectedItem.sharedWithMeAccessReshare())
)
}, this)
this.createPublicLinkCommand = Utils.createCommand(this, this.createPublicLink, this.isShareAllowed)
// Create in general for all kind of items
this.isCreateAllowed = ko.computed(function () {
var oSharedParentFolder = this.sharedParentFolder()
return (
!this.isTrashStorage() && !this.isZipFolder() &&
((oSharedParentFolder && oSharedParentFolder.sharedWithMeAccessWrite()) ||
(!oSharedParentFolder && !this.isSharedStorage()))
)
}, this)
this.createFolderCommand = Utils.createCommand(this, this.executeCreateFolder, this.isCreateAllowed)
this.isCreateShortcutAllowed = ko.computed(function () {
return this.isCreateAllowed() && !this.isExternalStorage() && !this.isEncryptedStorage()
}, this)
this.createShortcutCommand = Utils.createCommand(this, this.executeCreateShortcut, this.isCreateShortcutAllowed)
this.checkstateCommand = Utils.createCommand(this, this.executeCheckstate)
this.uploaderButton = ko.observable(null)
this.uploaderArea = ko.observable(null)
this.bDragActive = ko.observable(false)
this.isNewItemsMenuOpened = ko.observable(false)
this.bDragActiveComp = ko.computed(function () {
var bDrag = this.bDragActive()
return bDrag && this.searchPattern() === ''
}, this)
this.isDragAndDropSupported = ko.observable(false)
this.isCreateAllowed.subscribe(function () {
if (this.oJua) {
this.oJua.setDragAndDropEnabledStatus(this.isCreateAllowed())
}
}, this)
this.uploadError = ko.observable(false)
this.quota = ko.observable(0)
this.used = ko.observable(0)
this.quotaDesc = ko.observable('')
this.quotaProc = ko.observable(-1)
this.bShowQuotaBarTextAsTooltip = UserSettings.ShowQuotaBarTextAsTooltip
this.aBottomLeftCornerLinks = Settings.BottomLeftCornerLinks
ko.computed(function () {
if (!UserSettings.ShowQuotaBar) {
return true
}
var iQuota = this.quota(),
iUsed = this.used(),
iProc = 0 < iQuota ? Math.round((iUsed / iQuota) * 100) : -1
iProc = 100 < iProc ? 100 : iProc
this.quotaProc(iProc)
this.quotaDesc(
-1 < iProc
? TextUtils.i18n('COREWEBCLIENT/INFO_QUOTA', {
PROC: iProc,
QUOTA: TextUtils.getFriendlySize(iQuota),
})
: ''
)
if (UserSettings.QuotaWarningPerc > 0 && iProc !== -1 && UserSettings.QuotaWarningPerc > 100 - iProc) {
Screens.showError(TextUtils.i18n('COREWEBCLIENT/WARNING_QUOTA_ALMOST_REACHED'), true)
}
}, this)
this.dragover = ko.observable(false)
this.loading = ko.observable(false)
this.loadedFiles = ko.observable(false)
this.fileListInfoText = ko.computed(function () {
var sInfoText = ''
if (this.loading()) {
sInfoText = TextUtils.i18n('COREWEBCLIENT/INFO_LOADING')
} else if (this.loadedFiles()) {
if (this.collection().length === 0) {
if (this.searchPattern() !== '') {
sInfoText = TextUtils.i18n('%MODULENAME%/INFO_NOTHING_FOUND')
} else if (this.isSharedStorage()) {
sInfoText = TextUtils.i18n('%MODULENAME%/INFO_SHARED_FOLDER_IS_EMPTY')
} else if (this.currentPath() !== '' || this.bInPopup || this.bPublic) {
sInfoText = TextUtils.i18n('%MODULENAME%/INFO_FOLDER_IS_EMPTY')
} else if (this.isDragAndDropSupported()) {
sInfoText = TextUtils.i18n('%MODULENAME%/INFO_DRAGNDROP_FILES_OR_CREATE_FOLDER')
}
}
} else if (this.error()) {
sInfoText = TextUtils.i18n('%MODULENAME%/ERROR_FILES_NOT_RECEIVED')
}
return sInfoText
}, this)
this.bInPopup = !!bPopup
this.timerId = null
this.itemsViewTemplate = ko.observable('%ModuleName%_ItemsView')
App.subscribeEvent(
'Files::ShowList',
_.bind(function (oParams) {
if (this.shown() && oParams.Item) {
this.routeFiles(oParams.Item.storageType(), oParams.Item.fullPath())
}
}, this)
)
ConfirmPopup.opened.subscribe(
_.bind(function () {
if (this.shown()) {
this.selector.useKeyboardKeys(true)
}
}, this)
)
this.PublicLinksEnabled = Settings.PublicLinksEnabled
this.bAllowFavorites = Settings.AllowFavorites
this.currentFolderStatsString = ko
.computed(function () {
let iSizeSelected = 0,
iSizeOveral = 0,
sOUtput = ''
this.files().forEach((oFile) => {
iSizeSelected += oFile.selected() || oFile.checked() ? oFile.size() : 0
iSizeOveral += oFile.size()
})
sOUtput =
this.files().length === 0 && this.folders().length === 0
? ''
: TextUtils.i18n('%MODULENAME%/CURRENT_FOLDER_STATS', {
SIZE_OVERAL: TextUtils.getFriendlySize(iSizeOveral),
FILES_OVERAL: this.files().length,
FOLDERS_OVERAL: this.folders().length,
})
sOUtput +=
this.selectedFiles().length === 0
? ''
: ' | ' +
TextUtils.i18n('%MODULENAME%/CURRENT_FOLDER_STATS_SELECTED_FILES', {
SIZE_SELECTED: TextUtils.getFriendlySize(iSizeSelected),
FILES_SELECTED: this.selectedFiles().length,
})
sOUtput +=
this.selectedFolders().length === 0
? ''
: ' | ' +
TextUtils.i18n('%MODULENAME%/CURRENT_FOLDER_STATS_SELECTED_FOLDERS', {
FOLDERS_SELECTED: this.selectedFolders().length,
})
return sOUtput
}, this)
.extend({ rateLimit: { timeout: 100, method: 'notifyWhenChangesStop' } })
this.addToolbarButtons = ko.observableArray([])
this.storageControllers = ko.observableArray()
this.controllers = ko.computed(() => {
return [...this.addToolbarButtons(), ...this.storageControllers()]
})
App.broadcastEvent('%ModuleName%::RegisterFilesController', (controller, place) => {
this.registerController(controller, place)
})
App.broadcastEvent('%ModuleName%::ConstructView::after', { Name: this.ViewConstructorName, View: this })
}
_.extendOwn(CFilesView.prototype, CAbstractScreenView.prototype)
CFilesView.prototype.ViewTemplate = App.isPublic() ? '%ModuleName%_PublicFilesView' : '%ModuleName%_FilesView'
CFilesView.prototype.ViewConstructorName = 'CFilesView'
CFilesView.prototype.registerCreateButtonsController = function (oBigButtonView) {
this.createButtonsControllers.push(oBigButtonView)
}
/**
* @param {object} $popupDom
*/
CFilesView.prototype.onBind = function ($popupDom) {
var $dom = this.$viewDom || $popupDom
this.selector.initOnApplyBindings(
'.items_sub_list .item',
'.items_sub_list .selected.item',
'.items_sub_list .item .custom_checkbox',
$('.panel.files .items_list', $dom),
$('.panel.files .items_list .files_scroll.scroll-inner', $dom)
)
$('.files_scroll').on('click', (event) => {
const targetClassName = event.target?.className || ''
if (
targetClassName.includes('files_scroll') ||
targetClassName.includes('items_list') ||
targetClassName.includes('items_sub_list')
) {
this.selector.listCheckedAndSelected(false)
}
})
this.initUploader()
this.hotKeysBind()
}
CFilesView.prototype.hotKeysBind = function () {
$(document).on(
'keydown',
_.bind(function (ev) {
if (
this.shown() &&
ev &&
ev.keyCode === Enums.Key.s &&
this.selector.useKeyboardKeys() &&
!Utils.isTextFieldFocused()
) {
ev.preventDefault()
this.isSearchFocused(true)
}
}, this)
)
}
/**
* Initializes file uploader.
*/
CFilesView.prototype.initUploader = function () {
var self = this
if (!this.bPublic && this.uploaderButton() && this.uploaderArea()) {
this.oJua = new CJua({
action: '?/Api/',
name: 'jua-uploader',
queueSize: 2,
clickElement: this.uploaderButton(),
hiddenElementsPosition: UserSettings.IsRTL ? 'right' : 'left',
dragAndDropElement: this.uploaderArea(),
disableAjaxUpload: false,
disableFolderDragAndDrop: false,
disableDragAndDrop: false,
hidden: _.extendOwn(
{
Module: Settings.ServerModuleName,
Method: 'UploadFile',
Parameters: function (oFile) {
return JSON.stringify({
Type: self.storageType(),
SubPath: (oFile && oFile.Folder) || '',
Path: self.dropPath(),
Overwrite: false,
})
},
},
App.getCommonRequestParameters()
),
})
this.oJua
.on('onProgress', _.bind(this.onFileUploadProgress, this))
.on('onSelect', _.bind(this.onFileUploadSelect, this))
.on('onStart', _.bind(this.onFileUploadStart, this))
.on('onDrop', _.bind(this.onDrop, this))
.on('onEmptyFolderDrop', this.onEmptyFolderDrop.bind(this))
.on('onComplete', _.bind(this.onFileUploadComplete, this))
.on('onBodyDragEnter', _.bind(this.bDragActive, this, true))
.on('onBodyDragLeave', _.bind(this.bDragActive, this, false))
.on('onCancel', _.bind(this.onCancelUpload, this))
.on(
'onDialog',
_.bind(
function () {
setTimeout(_.bind(this.isNewItemsMenuOpened, this, false), 10)
},
this,
false
)
)
this.isDragAndDropSupported(this.oJua.isDragAndDropSupported())
}
}
/**
* Checks if the file can be uploaded
*
* @param {Object} oFileData
*/
CFilesView.prototype.isFileCanBeUploaded = function (oFileData) {
if (Settings.EnableUploadSizeLimit && oFileData.Size / (1024 * 1024) > Settings.UploadSizeLimitMb) {
Popups.showPopup(AlertPopup, [
TextUtils.i18n('%MODULENAME%/ERROR_SIZE_LIMIT', {
FILENAME: oFileData.FileName,
SIZE: Settings.UploadSizeLimitMb,
}),
])
return false
}
if (this.storageType() === Enums.FileStorageType.Personal && Types.isPositiveNumber(this.quota())) {
if (this.quota() > 0 && this.used() + oFileData.Size > this.quota()) {
Popups.showPopup(AlertPopup, [TextUtils.i18n('COREWEBCLIENT/ERROR_CANT_UPLOAD_FILE_QUOTA')])
return false
}
}
return true
}
/**
* Creates new attachment for upload.
*
* @param {string} sFileUid
* @param {Object} fileData
*/
CFilesView.prototype.onFileUploadSelect = function (sFileUid, fileData) {
if (!this.isFileCanBeUploaded(fileData)) {
return false
}
if (this.searchPattern() === '') {
const getFileByName = (fileName) => {
if (this.getFileByName(fileName)) {
return true
} else {
return !!_.find(this.getUploadingFiles(), function (oItem) {
return oItem.fileName() === fileName
})
}
},
storage = this.storageType(),
path = this.currentPath(),
correctedData = CFileModel.prepareUploadFileData(fileData, path, storage, getFileByName)
let file = this.getUploadFileByUid(sFileUid)
if (file) {
file.fileName(correctedData.Name)
file.fullPath(correctedData.FullPath)
} else {
file = new CFileModel(correctedData, this)
}
file.onUploadSelect(sFileUid, fileData, true)
this.uploadingFiles.push(file)
this.onFileFromSubfolderUploadSelect(fileData)
return true
}
return false
}
/**
* If selected for upload file is from subfolder increase uploading files count for this folder.
* @param {Object} oFileData
*/
CFilesView.prototype.onFileFromSubfolderUploadSelect = function (oFileData) {
if (Types.isNonEmptyString(oFileData.Folder)) {
var aPath = _.compact(oFileData.Folder.split('/')),
sFolderName = aPath[0],
oFolder = _.find(this.folders(), function (oTmpFolder) {
return oTmpFolder.fileName() === sFolderName
})
if (sFolderName && !oFolder) {
oFolder = new CFolderModel(this)
oFolder.parse({
Name: sFolderName,
})
this.folders.push(oFolder)
}
oFolder.increaseUploadingFiles()
}
}
/**
* Finds attachment by uid. Calls it's function to start upload.
*
* @param {string} sFileUid
*/
CFilesView.prototype.onFileUploadStart = function (sFileUid) {
var oFile = this.getUploadFileByUid(sFileUid)
if (oFile) {
oFile.onUploadStart()
}
}
/**
* Finds attachment by uid. Calls it's function to progress upload.
*
* @param {string} sFileUid
* @param {number} iUploadedSize
* @param {number} iTotalSize
*/
CFilesView.prototype.onFileUploadProgress = function (sFileUid, iUploadedSize, iTotalSize) {
if (this.searchPattern() === '') {
var oFile = this.getUploadFileByUid(sFileUid)
if (oFile) {
oFile.onUploadProgress(iUploadedSize, iTotalSize)
}
}
}
/**
* Finds attachment by uid. Calls it's function to complete upload.
*
* @param {string} sFileUid File identifier.
* @param {boolean} bResponseReceived Indicates if upload was successfull.
* @param {Object} oResult Response from the server.
*/
CFilesView.prototype.onFileUploadComplete = function (sFileUid, bResponseReceived, oResult) {
if (this.searchPattern() === '') {
var oFile = this.getUploadFileByUid(sFileUid),
bRequestFiles = false
if (oFile) {
oFile.onUploadComplete(sFileUid, bResponseReceived, oResult)
this.onFileWithSubfolderUploadComplete(oFile)
this.deleteUploadFileByUid(sFileUid)
if (oFile.uploadError()) {
this.uploadError(true)
if (oResult && oResult.ErrorCode === Enums.Errors.CanNotUploadFileQuota) {
Popups.showPopup(AlertPopup, [TextUtils.i18n('COREWEBCLIENT/ERROR_CANT_UPLOAD_FILE_QUOTA')])
bRequestFiles = true
} else if (oResult && oResult.ErrorCode === Enums.Errors.FileAlreadyExists) {
bRequestFiles = true
Screens.showError(TextUtils.i18n('COREWEBCLIENT/ERROR_FILE_ALREADY_EXISTS'))
} else if (oResult && oResult.ErrorCode === Enums.Errors.FileNotFound) {
bRequestFiles = true
Screens.showError(TextUtils.i18n('COREWEBCLIENT/ERROR_FILE_NOT_FOUND'))
} else {
Screens.showError(oFile.statusText())
}
} else {
if (oFile.path() === this.currentPath() && oFile.storageType() === this.storageType()) {
this.files.push(oFile)
}
if (this.uploadingFiles().length === 0) {
Screens.showReport(TextUtils.i18n('COREWEBCLIENT/REPORT_UPLOAD_COMPLETE'))
}
}
if (this.uploadingFiles().length === 0) {
bRequestFiles = true
}
} else {
bRequestFiles = true
}
if (bRequestFiles) {
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern(), true)
}
}
}
/**
* If uploaded file is from subfolder increase uploaded files count for this folder.
* @param {Object} oFile
*/
CFilesView.prototype.onFileWithSubfolderUploadComplete = function (oFile) {
if (oFile.sUploadSubFolder) {
var aPath = _.compact(oFile.sUploadSubFolder.split('/')),
sFolderName = aPath[0],
oFolder = _.find(this.folders(), function (oTmpFolder) {
return oTmpFolder.fileName() === sFolderName
})
if (oFolder) {
oFolder.increaseUploadedFiles()
}
}
}
CFilesView.prototype.onEmptyFolderDrop = function (folderData) {
if (folderData && folderData.fullPath) {
const folderName = folderData.fullPath.charAt(0) === '/' ? folderData.fullPath.substr(1) : folderData.fullPath
Ajax.send(
'CreateFolder',
{
Type: this.storageType(),
Path: this.currentPath(),
FolderName: folderData.fullPath,
},
this.onCreateFolderResponse,
this
)
}
}
/**
* @param {Object} oFile
* @param {Object} oEvent
*/
CFilesView.prototype.onDrop = function (oFile, oEvent) {
if (this.bPublic) {
return
}
if (oEvent && oEvent.target && this.searchPattern() === '') {
var oFolder = ko.dataFor(oEvent.target)
if (oFolder && oFolder instanceof CFolderModel) {
this.dropPath(oFolder.fullPath())
}
} else {
Screens.showReport(TextUtils.i18n('%MODULENAME%/INFO_CANNOT_UPLOAD_SEARCH_RESULT'))
}
}
/**
* @param {Object} oFolder
* @param {Object} oEvent
* @param {Object} oUi
*/
CFilesView.prototype.filesDrop = function (oFolder, oEvent, oUi) {
if (this.bPublic || !this.isDragAllowed()) {
return
}
if (oEvent) {
var aChecked = this.selector.listCheckedAndSelected(),
sMethod = this.needToCopyDraggedItems() ? 'Copy' : 'Move'
if (this.moveItems(sMethod, oFolder, aChecked)) {
Utils.uiDropHelperAnim(oEvent, oUi)
}
}
}
/**
* @param {string} sMethod
* @param {object} oFolder
* @param {array} aChecked
* @returns {boolean}
*/
CFilesView.prototype.moveItems = function (sMethod, oFolder, aChecked) {
if (this.bPublic) {
return false
}
var sFromPath = '',
sFromStorageType = '',
bFromAllSame = true,
bFolderIntoItself = false,
sToPath = oFolder instanceof CFolderModel ? oFolder.fullPath() : '',
aItems = [],
sStorageType = oFolder
? oFolder instanceof CFolderModel
? oFolder.storageType()
: oFolder.type
: this.storageType(),
oToStorage = this.getStorageByType(sStorageType),
oFromStorage = this.currentStorage(),
bSameStorage = oToStorage.type === oFromStorage.type,
iUsed = this.used(),
iQuota = this.quota(),
bAllowMove = true
if (
bSameStorage ||
(!bSameStorage &&
!oToStorage.isExternal &&
!oFromStorage.isExternal &&
Enums.FileStorageType.Shared !== oToStorage.type)
) {
if (oToStorage.type === Enums.FileStorageType.Personal && oFromStorage.type !== Enums.FileStorageType.Personal) {
bAllowMove = _.every(aChecked, function (oItem) {
if (oItem instanceof CFileModel) {
if (iQuota > 0 && iUsed + oItem.size() > iQuota) {
return false
}
iUsed = iUsed + oItem.size()
}
return true
})
if (!bAllowMove) {
Popups.showPopup(AlertPopup, [
TextUtils.i18n('%MODULENAME%/ERROR_CANT_MOVE_FILES_QUOTA_PLURAL', {}, '', aChecked.length),
])
return false
}
}
_.each(
aChecked,
_.bind(function (oItem) {
if (
(sFromPath !== '' && sFromPath !== oItem.path()) ||
(sFromStorageType !== '' && sFromStorageType !== oItem.storageType())
) {
bFromAllSame = false
}
sFromPath = oItem.path()
sFromStorageType = oItem.storageType()
bFolderIntoItself = oItem instanceof CFolderModel && sToPath === sFromPath + '/' + oItem.id()
if (!bFolderIntoItself) {
if (sMethod === 'Move') {
if (oItem instanceof CFileModel) {
this.deleteFileByName(oItem.id())
} else {
this.deleteFolderByName(oItem.fileName())
}
}
aItems.push({
FromType: sFromStorageType,
FromPath: sFromPath,
Name: oItem.id(),
IsFolder: oItem instanceof CFolderModel,
})
}
}, this)
)
if (aItems.length > 0) {
if (!bFromAllSame) {
sFromStorageType = ''
sFromPath = ''
}
Ajax.send(
sMethod,
{
FromType: sFromStorageType,
ToType: sStorageType,
FromPath: sFromPath,
ToPath: sToPath,
Files: aItems,
},
this.onMoveResponse,
this
)
if (oFolder instanceof CFolderModel) {
oFolder.recivedAnim(true)
}
return true
}
}
return false
}
/**
* @param {Object} oResponse
* @param {Object} oRequest
*/
CFilesView.prototype.onMoveResponse = function (oResponse, oRequest) {
if (!oResponse.Result) {
if (oResponse.ErrorCode === Enums.Errors.CanNotUploadFileQuota) {
Popups.showPopup(AlertPopup, [
TextUtils.i18n('%MODULENAME%/ERROR_CANT_MOVE_FILES_QUOTA_PLURAL', {}, '', oRequest.Parameters.Files.length),
])
} else {
Api.showErrorByCode(
oResponse,
TextUtils.i18n('%MODULENAME%/ERROR_FILES_MOVE_PLURAL', {}, '', oRequest.Parameters.Files.length)
)
}
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern())
} else {
if (this.storageType() === oRequest.Parameters.ToType && this.currentPath() === oRequest.Parameters.ToPath) {
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern())
} else {
this.getQuota()
}
}
}
/**
* @param {Object} oDraggedItem
* @param {boolean} ctrlOrCmdUsed
*/
CFilesView.prototype.dragAndDropHelper = function (oDraggedItem, ctrlOrCmdUsed) {
if (!oDraggedItem || !oDraggedItem.allowDrag()) {
return $('<span></span>')
}
oDraggedItem.checked(true)
this.needToCopyDraggedItems(ctrlOrCmdUsed)
if (!this.isDragAllowed()) {
return $('<span></span>')
}
var oHelper = Utils.draggableItems(),
aItems = this.selector.listCheckedAndSelected(),
oCounts = _.countBy(aItems, function (oItem) {
return oItem.IS_FILE ? 'file' : 'folder'
}),
sPlusPrefix = ctrlOrCmdUsed ? '+ ' : '',
sText = ''
if (!oCounts.file) {
sText = TextUtils.i18n(
'%MODULENAME%/LABEL_DRAG_FOLDERS_PLURAL',
{ COUNT: sPlusPrefix + oCounts.folder },
null,
oCounts.folder
)
} else if (!oCounts.folder) {
sText = TextUtils.i18n(
'%MODULENAME%/LABEL_DRAG_FILES_PLURAL',
{ COUNT: sPlusPrefix + oCounts.file },
null,
oCounts.file
)
} else {
sText = TextUtils.i18n(
'%MODULENAME%/LABEL_DRAG_ITEMS_PLURAL',
{ COUNT: sPlusPrefix + aItems.length },
null,
aItems.length
)
}
$('.count-text', oHelper).text(sText)
return oHelper
}
CFilesView.prototype.onItemDelete = function () {
if (this.isDeleteAllowed()) {
this.executeDelete()
}
}
CFilesView.prototype.onItemSelect = function (oItem) {
if (App.isMobile() && oItem instanceof CFolderModel) {
this.onItemDblClick(oItem)
}
}
/**
* @param {CFileModel|CFolderModel} oItem
*/
CFilesView.prototype.onEnter = function (oItem) {
this.onItemDblClick(oItem)
}
/**
* Executes on item double click.
* @param {CFileModel|CFolderModel} oItem
*/
CFilesView.prototype.onItemDblClick = function (oItem) {
if (oItem) {
var sMainAction = oItem.getMainAction()
switch (sMainAction) {
case 'view':
if (oItem instanceof CFileModel) {
if (this.onSelectClickPopupBound) {
this.onSelectClickPopupBound()
} else {
oItem.executeAction(sMainAction)
}
}
break
case 'list':
if (!(oItem instanceof CFolderModel) || !oItem.isIncomplete()) {
this.routeFiles(oItem.storageType(), oItem.fullPath())
}
break
}
}
}
/**
* @param {Object} oResponse
* @param {Object} oRequest
*/
CFilesView.prototype.onGetFilesResponse = function (oResponse, oRequest) {
var oResult = oResponse.Result,
oParameters = oRequest.Parameters
this.bNotLoading = false
if (
(oParameters.Type === this.storageType() || oParameters.Hash === Settings.PublicHash) &&
oParameters.Path === this.currentPath()
) {
if (oResult) {
var aNewFolderList = [],
aNewFileList = []
_.each(
oResult.Items,
function (oData) {
if (oData.IsFolder) {
var oFolder = new CFolderModel(this)
oFolder.parse(oData)
this.checkIfFolderUploading(oFolder)
aNewFolderList.push(oFolder)
} else {
var oFile = new CFileModel(oData, this)
if (oFile.oExtendedProps && oFile.oExtendedProps.Loading) {
// if file still loading - show warning in status
oFile.uploadError(true)
oFile.statusText(TextUtils.i18n('COREWEBCLIENT/LABEL_FILE_LOADING'))
}
oFile.index(aNewFileList.length)
aNewFileList.push(oFile)
}
},
this
)
// save status of files that are being loaded
_.each(this.files(), function (oTmpFile, iFileIndex, aFiles) {
if (oTmpFile.downloading()) {
var iNewIndex = _.findIndex(aNewFileList, function (oNewTmpFile) {
return oTmpFile.fileName() === oNewTmpFile.fileName()
})
if (iNewIndex !== -1) {
aFiles[iFileIndex].index(aNewFileList[iNewIndex].index())
aNewFileList[iNewIndex] = aFiles[iFileIndex]
}
}
})
this.folders(aNewFolderList)
this.files(aNewFileList)
this.newSearchPattern(oParameters.Pattern || '')
this.searchPattern(oParameters.Pattern || '')
this.loadedFiles(true)
clearTimeout(this.timerId)
this.parseQuota(oResult.Quota)
if (_.isArray(oResult.Path)) {
this.pathItems.removeAll()
_.each(
oResult.Path.reverse(),
_.bind(function (oPathItem) {
var oFolder = new CFolderModel(this)
oFolder.parse(oPathItem)
this.pathItems.push(oFolder)
}, this)
)
}
this.loading(false)
//If the current path does not contain information about access, we obtain such information from the response, if possible
if (oResult.Access && this.pathItems().length > 0) {
const iLastIndex = this.pathItems().length - 1,
lastItem = this.pathItems()[iLastIndex]
if (!lastItem.oExtendedProps || !lastItem.oExtendedProps.SharedWithMeAccess) {
this.pathItems()[iLastIndex].updateExtendedProps({
SharedWithMeAccess: oResult.Access,
})
this.pathItems.valueHasMutated() // for triggering sharedParentFolder computing
}
}
} else {
if (oResponse.ErrorCode !== Enums.Errors.NotDisplayedError) {
this.loading(false)
this.error(true)
Api.showErrorByCode(oResponse, TextUtils.i18n('%MODULENAME%/ERROR_FILES_NOT_RECEIVED'))
}
}
}
}
/**
* Checks if folder has uploding files and marks it as uploading.
* @param {Object} oFolder
*/
CFilesView.prototype.checkIfFolderUploading = function (oFolder) {
_.each(this.uploadingFiles(), function (oFile) {
if (oFile.sUploadSubFolder) {
var aPath = _.compact(oFile.sUploadSubFolder.split('/')),
sFolderName = aPath[0]
if (oFolder.fileName() === sFolderName) {
oFolder.increaseUploadingFiles()
}
}
})
}
/**
* Runs after getting quota information from the server. Fill quota values.
*
* @param {Object} oQuota
*/
CFilesView.prototype.parseQuota = function (oQuota) {
if (oQuota) {
this.quota(Types.pInt(oQuota.Limit))
this.used(Types.pInt(oQuota.Used))
}
}
/**
* @param {Object} oResponse
* @param {Object} oRequest
*/
CFilesView.prototype.onDeleteResponse = function (oResponse, oRequest) {
if (oResponse.Result) {
this.expungeFileItems()
this.getQuota()
} else {
Api.showErrorByCode(oResponse)
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern())
}
}
CFilesView.prototype.executeRename = function () {
var oItem = _.first(this.selector.listCheckedAndSelected()),
bSeparateExtension = Settings.EditFileNameWithoutExtension && oItem instanceof CFileModel,
sName = bSeparateExtension ? Utils.getFileNameWithoutExtension(oItem.fileName()) : oItem.fileName(),
sExtension = bSeparateExtension ? Utils.getFileExtension(oItem.fileName()) : ''
if (!this.bPublic && oItem) {
Popups.showPopup(RenamePopup, [sName, _.bind(this.renameItem, this, sExtension)])
}
}
/**
* @param {string} sExtension
* @param {string} sNamePart
* @returns {string}
*/
CFilesView.prototype.renameItem = function (sExtension, sNamePart) {
var sName = sExtension === '' ? sNamePart : sNamePart + '.' + sExtension,
oItem = _.first(this.selector.listCheckedAndSelected())
if (!Utils.validateFileOrFolderName(sName)) {
return oItem instanceof CFolderModel
? TextUtils.i18n('%MODULENAME%/ERROR_INVALID_FOLDER_NAME')
: TextUtils.i18n('%MODULENAME%/ERROR_INVALID_FILE_NAME')
} else {
Ajax.send(
'Rename',
{
Type: oItem.storageType(),
Path: oItem.path(),
Name: oItem.id() || oItem.fileName(),
NewName: sName,
IsLink: oItem.bIsLink,
IsFolder: !oItem.IS_FILE,
},
this.onRenameResponse,
this
)
}
return ''
}
CFilesView.prototype.executeSort = function (sValue) {
const sCurrentSort = this.sortBy()
this.sortBy(sValue)
if (sCurrentSort === sValue) {
this.sortOrder(this.sortOrder() === Enums.SortOrder.Asc ? Enums.SortOrder.Desc : Enums.SortOrder.Asc) // Asc: 0, Desc: 1
} else {
this.sortOrder(Settings.Sorting.DefaultSortOrder)
}
}
CFilesView.prototype.getFileIfOnlyOneSelected = function () {
var aItems = this.selector.listCheckedAndSelected()
return 1 === aItems.length && aItems[0] instanceof CFileModel ? aItems[0] : null
}
CFilesView.prototype.executeDownload = function () {
var oFile = this.getFileIfOnlyOneSelected()
if (oFile) {
oFile.executeAction('download')
}
}
CFilesView.prototype.createPublicLink = function () {
var oItem = _.first(this.selector.listCheckedAndSelected())
if (!this.bPublic && oItem) {
Popups.showPopup(SharePopup, [oItem])
}
}
CFilesView.prototype.executeSend = function () {
var aFilesData = _.map(this.selectedFiles(), function (oItem) {
return {
Storage: oItem.storageType(),
Path: oItem.path(),
Name: oItem.id() || oItem.fileName(),
}
})
if (this.bAllowSendEmails && aFilesData.length > 0) {
Ajax.send(
'SaveFilesAsTempFiles',
{ Files: aFilesData },
function (oResponse) {
if (oResponse.Result) {
ComposeMessageWithAttachments(oResponse.Result)
}
},
this
)
}
}
CFilesView.prototype.onFavoriteClick = function (oItem) {
if (oItem) {
const originalState = oItem.favorite()
oItem.favorite(!oItem.favorite())
Ajax.send(
originalState ? 'RemoveFromFavorites' : 'AddToFavorites',
{
Items: [
{
Type: 'personal',
Path: oItem.path(),
Name: oItem.fileName()
}
]
},
function (oResponse) {
if (originalState) {
oItem.favorite(!oResponse.Result)
} else {
oItem.favorite(!!oResponse.Result)
}
if (!oResponse.Result) {
Screens.showError(TextUtils.i18n('%MODULENAME%/ERROR_FAVORITE_NOT_SET'))
}
},
this
)
}
}
/**
* @param {Object} oItem
*/
CFilesView.prototype.onShareIconClick = function (oItem) {
if (oItem) {
Popups.showPopup(SharePopup, [oItem])
}
}
/**
* @param {Object} oItem
*/
CFilesView.prototype.onSecureIconClick = function (oItem) {
if (oItem && _.isFunction(oItem.onSecureIconClick)) {
oItem.onSecureIconClick(oItem)
}
}
/**
* @param {Object} oItem
*/
CFilesView.prototype.onFileShareIconClick = function (oItem) {
if (FilesSharePopup && oItem) {
Popups.showPopup(FilesSharePopup, [oItem, this.expungeFileItems.bind(this)])
}
}
/**
* @param {Object} oResponse
* @param {Object} oRequest
*/
CFilesView.prototype.onRenameResponse = function (oResponse, oRequest) {
if (!oResponse.Result) {
Api.showErrorByCode(oResponse, TextUtils.i18n('%MODULENAME%/ERROR_FILE_RENAME'))
}
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern(), true)
}
CFilesView.prototype.refresh = function () {
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern(), true)
}
CFilesView.prototype.executeDelete = function () {
var sharedParentFolder = this.sharedParentFolder(),
allowDeleteSharedItems = !!sharedParentFolder && sharedParentFolder.sharedWithMeAccessWrite(),
items = this.selector.listCheckedAndSelected() || [],
itemsToDelete = allowDeleteSharedItems ? items : this.selectedOwnItems(),
itemsToDeleteCount = itemsToDelete.length
if (!this.bPublic && itemsToDeleteCount > 0) {
const storagesThatSupportsTrash = [
Enums.FileStorageType.Personal,
Enums.FileStorageType.Shared,
Enums.FileStorageType.Corporate,
Enums.FileStorageType.Encrypted,
]
if(Settings.AllowTrash && storagesThatSupportsTrash.indexOf(this.storageType()) !== -1) {
var hasSharedWithOthers = !!_.find(itemsToDelete, function (item) {
return item.sharedWithOthers();
})
if (hasSharedWithOthers) {
this.selector.useKeyboardKeys(false)
Popups.showPopup(ConfirmPopup, [
TextUtils.i18n('%MODULENAME%/CONFIRM_SOME_ITEMS_SHARED_WITH_OTHERS'),
_.bind(this.deleteItems, this, itemsToDelete),
'',
TextUtils.i18n('COREWEBCLIENT/ACTION_DELETE'),
])
} else {
this.deleteItems(itemsToDelete, true)
}
} else {
var askAboutSharedItems = items.length !== itemsToDeleteCount,
hasFolder = !!_.find(itemsToDelete, function (item) {
return !item.IS_FILE
}),
hasFile = !!_.find(itemsToDelete, function (item) {
return item.IS_FILE
}),
confirmText = ''
if (askAboutSharedItems) {
confirmText = TextUtils.i18n('%MODULENAME%/CONFIRM_NOT_ALL_ITEMS_OWN')
} else if (hasFolder && hasFile) {
confirmText = TextUtils.i18n(
'%MODULENAME%/CONFIRM_DELETE_ITEMS_PLURAL',
{ COUNT: itemsToDeleteCount },
null,
itemsToDeleteCount
)
} else if (hasFolder) {
confirmText = TextUtils.i18n(
'%MODULENAME%/CONFIRM_DELETE_FOLDERS_PLURAL',
{ COUNT: itemsToDeleteCount },
null,
itemsToDeleteCount
)
} else {
confirmText = TextUtils.i18n(
'%MODULENAME%/CONFIRM_DELETE_FILES_PLURAL',
{ COUNT: itemsToDeleteCount },
null,
itemsToDeleteCount
)
}
this.selector.useKeyboardKeys(false)
Popups.showPopup(ConfirmPopup, [
confirmText,
_.bind(this.deleteItems, this, itemsToDelete),
'',
TextUtils.i18n('COREWEBCLIENT/ACTION_DELETE'),
])
}
}
}
CFilesView.prototype.executeRestore = function () {
var
itemsToRestore = this.selector.listCheckedAndSelected() || [],
itemsToRestoreCount = itemsToRestore.length,
confirmText = TextUtils.i18n(
'%MODULENAME%/CONFIRM_RESTORE_ITEMS_PLURAL',
{ COUNT: itemsToRestoreCount },
null,
itemsToRestoreCount
),
originalPaths = [],
originalPathsLength = 0
;
_.each(itemsToRestore, function(fileItem) {
if (fileItem && fileItem.oExtendedProps && fileItem.oExtendedProps.TrashOriginalPath) {
originalPaths.push(TextUtils.i18n('%MODULENAME%/LABEL_PERSONAL_STORAGE') + fileItem.oExtendedProps.TrashOriginalPath)
}
})
originalPathsLength = originalPaths.length
originalPaths = _.first(originalPaths, 3)
if (originalPathsLength > 0) {
confirmText = confirmText + '<br><br>' + originalPaths.join('<br>')
if (originalPathsLength > 3) {
confirmText = confirmText + '<br>...'
}
}
this.selector.useKeyboardKeys(false)
Popups.showPopup(ConfirmPopup, [
confirmText,
_.bind(this.restoreItems, this, itemsToRestore),
'',
TextUtils.i18n('%MODULENAME%/ACTION_RESTORE'),
])
}
CFilesView.prototype.onShow = function () {
this.loaded(true)
if (!this.bPublic) {
this.requestStorages()
}
this.selector.useKeyboardKeys(true)
if (this.oJua) {
this.oJua.setDragAndDropEnabledStatus(true)
}
this.controllers().forEach((controller) => {
if (typeof controller.onShow === 'function') {
controller.onShow()
}
})
}
CFilesView.prototype.onHide = function () {
this.selector.useKeyboardKeys(false)
if (this.oJua) {
this.oJua.setDragAndDropEnabledStatus(false)
}
this.controllers().forEach((controller) => {
if (typeof controller.onHide === 'function') {
controller.onHide()
}
})
}
CFilesView.prototype.getQuota = function () {
Ajax.send(
'GetQuota',
{
Type: this.storageType(),
},
function (oResponse) {
if (oResponse.Result) {
this.parseQuota(oResponse.Result)
}
},
this
)
}
/**
* @param {string} sStorageType
*/
CFilesView.prototype.getStorageByType = function (sStorageType) {
return _.find(this.storages(), function (oStorage) {
return oStorage.type === sStorageType
})
}
/**
* Requests storages from the server.
*/
CFilesView.prototype.requestStorages = function () {
Ajax.send('GetStorages', null, this.onGetStoragesResponse, this)
}
/**
* Parses server response to a request of storages.
* @param {Object} oResponse
* @param {Object} oRequest
*/
CFilesView.prototype.onGetStoragesResponse = function (oResponse, oRequest) {
var oResult = oResponse.Result
if (oResult) {
_.each(oResult, function (oStorage) {
if (oStorage.Type && !this.getStorageByType(oStorage.Type)) {
var oStorageModel = new CStorageModel(this.isCurrentStorageDroppable);
oStorageModel.parse(oStorage)
this.storages.push(oStorageModel);
}
}, this)
this.expungeExternalStorages(
_.map(
oResult,
function (oStorage) {
return oStorage.Type
},
this
)
)
}
if (!this.currentStorage()) {
this.storageType(Enums.FileStorageType.Personal)
this.pathItems.removeAll()
}
if (this.bInPopup) {
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern(), true)
}
}
/**
* Clears file/folder list and displays loading message.
*/
CFilesView.prototype.clearAndShowLoading = function () {
this.folders([])
this.files([])
this.loading(true)
}
CFilesView.prototype.currentGetFiles = function () {
var iPathItemsCount = this.pathItems().length,
oParameters = {
Type: this.storageType(),
Path: this.currentPath(),
Pattern: this.searchPattern(),
PathRequired: this.currentPath() !== '' && iPathItemsCount === 0,
}
Ajax.send('GetFiles', oParameters, this.onGetFilesResponse, this)
}
/**
* Sets routing hash.
* @param {string} sStorage Storage type.
* @param {string=} sFullPath = '' Path to files/folders to display.
* @param {string=} sSearch = '' Search string.
* @param {boolean=} bNotLoading = false Indicates if loading message should be displayed with delay.
*/
CFilesView.prototype.routeFiles = function (sStorage, sFullPath, sSearch, bNotLoading) {
if (this.disableRoute) {
return
}
var bSame = false
if (this.bPublic) {
bSame = Routing.setHash(LinksUtils.getFiles('', sFullPath, ''))
if (bSame) {
this.clearAndShowLoading()
Ajax.send(
'GetPublicFiles',
{
Hash: Settings.PublicHash,
Path: this.currentPath(),
},
this.onGetFilesResponse,
this
)
}
} else {
this.bNotLoading = bNotLoading
if (this.bInPopup) {
this.onUserRoute(LinksUtils.getParsedParams(sStorage, sFullPath, sSearch))
} else {
bSame = Routing.setHash(LinksUtils.getFiles(sStorage, sFullPath, sSearch))
if (bSame) {
this.clearAndShowLoading()
this.currentGetFiles()
}
}
}
}
/**
* Adds path item to path item list.
* @param {string} sStorage Storage type.
* @param {string} sPath Path of item.
* @param {string} sName Name of item.
*/
CFilesView.prototype.addPathItems = function (sStorage, sPath, sName) {
var oFolder = new CFolderModel(this)
oFolder.storageType(sStorage)
oFolder.fileName(sName)
oFolder.path(sPath)
oFolder.fullPath(sPath)
this.pathItems.unshift(oFolder)
}
/**
* Requests files after routing parse.
* @param {array} aParams
*/
CFilesView.prototype.onRoute = function (aParams) {
var oParams = LinksUtils.parseFiles(aParams)
if (this.bPublic) {
this.onPublicRoute(oParams)
} else {
this.onUserRoute(oParams)
}
this.controllers().forEach((controller) => {
if (typeof controller.onRoute === 'function') {
controller.onRoute(oParams)
}
})
}
/**
* Requests user files after routing parse.
* @param {object} oParams
*/
CFilesView.prototype.onUserRoute = function (oParams) {
var bStorageFound =
this.storages().length === 0 ||
!!_.find(this.storages(), function (oStorage) {
return oStorage.type === oParams.Storage
}),
sStorage = bStorageFound ? oParams.Storage : this.storages().length > 0 ? this.storages()[0].type : '',
sPath = oParams.Path
this.error(false)
this.storageType(sStorage)
this.currentPath(sPath)
this.searchPattern(Types.pString(oParams.Search))
this.loadedFiles(false)
this.populatePathItems(oParams)
if (this.bNotLoading && (this.files().length > 0 || this.folders().length > 0)) {
this.timerId = setTimeout(
_.bind(function () {
if (!this.loadedFiles() && !this.error()) {
this.clearAndShowLoading()
}
}, this),
3000
)
} else {
this.clearAndShowLoading()
}
this.currentGetFiles()
}
CFilesView.prototype.populatePathItems = function (oParams) {
var sPath = this.currentPath(),
aPath = oParams.PathParts.reverse(),
oFolder = _.find(this.folders(), function (oFld) {
return oFld.fullPath() === sPath
}),
iPathItemIndex = _.findIndex(this.pathItems(), function (oItem) {
return oItem.fullPath() === sPath
})
if (iPathItemIndex !== -1) {
this.pathItems(this.pathItems().slice(0, iPathItemIndex + 1))
} else if (oFolder) {
this.pathItems.push(oFolder)
} else if (this.storageType() !== 'google' || sPath === '') {
this.pathItems.removeAll()
_.each(
aPath,
_.bind(function (sPathItem) {
var iItemPos = sPath.lastIndexOf(sPathItem)
this.addPathItems(this.storageType(), sPath, sPathItem)
sPath = sPath.substr(0, iItemPos)
}, this)
)
var oParameters = {
Type: this.storageType(),
Path: this.currentPath(),
}
Ajax.send(
'GetAccessInfoForPath',
oParameters,
function (response) {
if (response && response.Result) {
_.each(this.pathItems(), function (pathItem) {
var itemPath = pathItem.fullPath()
if (itemPath.substr(itemPath.length - 1, 1) === '/') {
itemPath = itemPath.substr(0, itemPath.length - 1)
}
if (response.Result[itemPath]) {
pathItem.updateExtendedProps({
SharedWithMeAccess: response.Result[itemPath],
})
}
})
this.pathItems.valueHasMutated() // for triggering sharedParentFolder computing
}
},
this
)
}
}
/**
* Requests public files after routing parse.
* @param {object} oParams
*/
CFilesView.prototype.onPublicRoute = function (oParams) {
var sPath = oParams.Path,
aPath = oParams.PathParts.reverse(),
sFirstPathItem = ''
this.currentPath(sPath)
this.pathItems.removeAll()
_.each(
aPath,
_.bind(function (sPathItem) {
var iItemPos = sPath.lastIndexOf(sPathItem)
this.addPathItems(oParams.Storage, sPath, sPathItem)
sPath = sPath.substr(0, iItemPos)
sFirstPathItem = sPathItem
}, this)
)
if (sFirstPathItem !== this.rootPath()) {
this.addPathItems(oParams.Storage, '', this.rootPath())
}
this.clearAndShowLoading()
Ajax.send(
'GetPublicFiles',
{
Hash: Settings.PublicHash,
Path: this.currentPath(),
},
this.onGetFilesResponse,
this
)
}
/**
* @param {Array} aChecked
* @param {boolean} bOkAnswer
* @param {string} methodName
*/
CFilesView.prototype.deleteItems = function (aChecked, bOkAnswer, methodName = 'Delete') {
var sStorageType = this.storageType(),
sPath = this.currentPath()
if (bOkAnswer && 0 < aChecked.length) {
var aItems = _.compact(
_.map(aChecked, function (oItem) {
if (oItem.id() !== '') {
oItem.deleted(true)
sStorageType = oItem.storageType()
return {
Path: oItem.path(),
Name: oItem.id(),
IsFolder: !oItem.IS_FILE,
}
}
return null
})
)
if (aItems.length) {
Ajax.send(
methodName,
{
Type: sStorageType,
Path: sPath,
Items: aItems,
},
this.onDeleteResponse,
this
)
}
}
}
/**
* @param {Array} aChecked
* @param {boolean} bOkAnswer
*/
CFilesView.prototype.restoreItems = function (aChecked, bOkAnswer) {
if (bOkAnswer && 0 < aChecked.length) {
var aItems = _.compact(
_.map(aChecked, function (oItem) {
if (oItem.id() !== '') {
oItem.deleted(true)
return oItem.id()
}
return null
})
)
if (aItems.length) {
Ajax.send(
'Restore',
{
Items: aItems,
},
this.onDeleteResponse,
this
)
}
}
}
/**
* @param {string} sName
*
* @return {?}
*/
CFilesView.prototype.getFileByName = function (sName) {
return _.find(this.files(), function (oItem) {
return oItem.fileName() === sName
})
}
/**
* @param {object} oFile
*/
CFilesView.prototype.addFileToCurrentFolder = function (oFile) {
if (this.searchPattern() === '') {
this.files.push(oFile)
}
}
/**
* @param {string} sName
*/
CFilesView.prototype.deleteFileByName = function (sName) {
this.files(
_.filter(this.files(), function (oItem) {
return oItem.id() !== sName
})
)
}
/**
* @param {string} sName
*/
CFilesView.prototype.deleteFolderByName = function (sName) {
this.folders(
_.filter(this.folders(), function (oItem) {
return oItem.fileName() !== sName
})
)
}
CFilesView.prototype.expungeFileItems = function () {
this.folders(
_.filter(
this.folders(),
function (oFolder) {
return !oFolder.deleted()
},
this
)
)
this.files(
_.filter(
this.files(),
function (oFile) {
return !oFile.deleted()
},
this
)
)
}
/**
* @param {array} aStorageTypes
*/
CFilesView.prototype.expungeExternalStorages = function (aStorageTypes) {
this.storages(
_.filter(
this.storages(),
function (oStorage) {
return !oStorage.isExternal || _.include(aStorageTypes, oStorage.type)
},
this
)
)
}
/**
* @param {string} sFileUid
*
* @return {?}
*/
CFilesView.prototype.getUploadFileByUid = function (sFileUid) {
return _.find(this.uploadingFiles(), function (oItem) {
return oItem.uploadUid() === sFileUid
})
}
/**
* @param {string} sFileUid
*/
CFilesView.prototype.deleteUploadFileByUid = function (sFileUid) {
this.uploadingFiles(
_.filter(this.uploadingFiles(), function (oItem) {
return oItem.uploadUid() !== sFileUid
})
)
}
/**
* @return {Array}
*/
CFilesView.prototype.getUploadingFiles = function () {
return _.filter(
this.uploadingFiles(),
_.bind(function (oItem) {
return oItem.path() === this.currentPath() && oItem.storageType() === this.storageType()
}, this)
)
}
/**
* @param {string} sFileUid
*/
CFilesView.prototype.onCancelUpload = function (sFileUid) {
this.deleteUploadFileByUid(sFileUid)
if (this.oJua) {
this.oJua.cancel(sFileUid)
}
}
/**
* @param {Object} oResponse
* @param {Object} oRequest
*/
CFilesView.prototype.onCreateFolderResponse = function (oResponse, oRequest) {
if (!oResponse.Result) {
Api.showErrorByCode(oResponse)
}
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern(), true)
}
/**
* @param {string} sFolderName
*/
CFilesView.prototype.createFolder = function (sFolderName) {
sFolderName = $.trim(sFolderName)
if (!Utils.validateFileOrFolderName(sFolderName)) {
return TextUtils.i18n('%MODULENAME%/ERROR_INVALID_FOLDER_NAME')
} else {
Ajax.send(
'CreateFolder',
{
Type: this.storageType(),
Path: this.currentPath(),
FolderName: sFolderName,
},
this.onCreateFolderResponse,
this
)
}
return ''
}
CFilesView.prototype.executeCreateFolder = function () {
Popups.showPopup(CreateFolderPopup, [_.bind(this.createFolder, this)])
}
/**
* @param {Object} oResponse
* @param {Object} oRequest
*/
CFilesView.prototype.onCreateLinkResponse = function (oResponse, oRequest) {
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern(), true)
}
/**
* @param {Object} oFileItem
*/
CFilesView.prototype.createLink = function (oFileItem) {
Ajax.send(
'CreateLink',
{
Type: this.storageType(),
Path: this.currentPath(),
Link: oFileItem.sLinkUrl,
Name: oFileItem.fileName(),
},
this.onCreateLinkResponse,
this
)
}
CFilesView.prototype.executeCreateShortcut = function () {
var fCallBack = _.bind(this.createLink, this)
Popups.showPopup(CreateLinkPopup, [fCallBack])
}
CFilesView.prototype.onSearch = function () {
this.routeFiles(this.storageType(), this.currentPath(), this.newSearchPattern())
}
CFilesView.prototype.clearSearch = function () {
this.routeFiles(this.storageType(), this.currentPath())
}
CFilesView.prototype.executeCheckstate = function () {
this.routeFiles(this.storageType(), this.currentPath(), this.searchPattern())
}
CFilesView.prototype.getCurrentFolder = function () {
var oFolder = new CFolderModel(this)
oFolder.fullPath(this.currentPath())
oFolder.storageType(this.storageType())
return oFolder
}
CFilesView.prototype.registerToolbarButtons = function (toolbarButtonsControllers) {
if (Types.isNonEmptyArray(toolbarButtonsControllers)) {
toolbarButtonsControllers.forEach((toolbarButtonsController) => {
this.registerController(toolbarButtonsController, 'ToolbarButton')
})
}
}
/**
* @param {Object} controller
* @param {string} placeName
*/
CFilesView.prototype.registerController = function (controller, placeName) {
let isRegistered = false
switch (placeName) {
case 'Storage':
this.storageControllers.push(controller)
isRegistered = true
break
case 'ToolbarButton':
this.addToolbarButtons.push(controller)
isRegistered = true
break
}
if (isRegistered && typeof controller.useFilesViewData === 'function') {
controller.useFilesViewData(this)
}
}
CFilesView.prototype.onFileRemove = function (sFileUploadUid, oFile) {
var /**
* Send request for deleting file with sFileName
* @param {String} sFileUploadUid
* @param {String} sFileName
*/
fOnUploadCancelCallback = _.bind(function (sFileUploadUid, sFileName) {
var oParameters = {
Type: this.storageType(),
Path: this.currentPath(),
Items: [
{
Path: this.currentPath(),
Name: sFileName,
IsFolder: false,
},
],
}
Ajax.send(
'Delete',
oParameters,
function (oResponse) {
if (!oResponse.Result) {
Api.showErrorByCode(oResponse)
}
this.currentGetFiles()
},
this
)
this.onCancelUpload(sFileUploadUid)
}, this)
if (oFile.downloading()) {
App.broadcastEvent('CFilesView::FileDownloadCancel', { oFile: oFile })
} else if (!oFile.uploaded() && sFileUploadUid) {
var bEventCaught = App.broadcastEvent('CFilesView::FileUploadCancel', {
sFileUploadUid: sFileUploadUid,
sFileUploadName: oFile.fileName(),
fOnUploadCancelCallback: fOnUploadCancelCallback,
})
if (!bEventCaught) {
fOnUploadCancelCallback(sFileUploadUid, oFile.fileName())
}
}
}
module.exports = CFilesView