Newer
Older
import {createInstance} from './i18n';
Bekerle, Patrizio
committed
import {ScopedElementsMixin} from '@open-wc/scoped-elements';
import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element';
import {Icon, MiniSpinner, getShadowRootDocument} from '@dbp-toolkit/common';
Bekerle, Patrizio
committed
import * as commonUtils from '@dbp-toolkit/common/utils';
import * as commonStyles from '@dbp-toolkit/common/styles';
import {createClient, parseXML} from 'webdav/web';
import {classMap} from 'lit/directives/class-map.js';
Bekerle, Patrizio
committed
import {humanFileSize} from '@dbp-toolkit/common/i18next';
import {TabulatorFull as Tabulator} from 'tabulator-tables';
Bekerle, Patrizio
committed
import MicroModal from './micromodal.es';
import {name as pkgName} from './../package.json';
import * as fileHandlingStyles from './styles';
import {encrypt, decrypt, parseJwt} from './crypto.js';
Bekerle, Patrizio
committed
/**
* NextcloudFilePicker web component
*/
export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) {
constructor() {
super();
this._i18n = createInstance();
this.lang = this._i18n.language;
Steinwender, Tamara
committed
this.auth = {};
Bekerle, Patrizio
committed
this.authUrl = '';
this.webDavUrl = '';
this.nextcloudName = 'Nextcloud';
this.nextcloudFileURL = '';
this.loginWindow = null;
this.isPickerActive = false;
this.statusText = '';
this.lastDirectoryPath = '/';
this.directoryPath = '';
this.webDavClient = null;
this.tabulatorTable = null;
Bekerle, Patrizio
committed
this.directoriesOnly = false;
this.maxSelectedItems = Number.MAX_VALUE;
Bekerle, Patrizio
committed
this.loading = false;
this._onReceiveWindowMessage = this.onReceiveWindowMessage.bind(this);
this.folderIsSelected = this._i18n.t('nextcloud-file-picker.load-in-folder');
Bekerle, Patrizio
committed
this.generatedFilename = '';
this.replaceFilename = '';
this.customFilename = '';
this.uploadFileObject = null;
this.uploadFileDirectory = null;
this.fileList = [];
this.fileNameCounter = 1;
this.activeDirectoryRights = 'RGDNVCK';
this.activeDirectoryACL = '';
this.forAll = false;
this.uploadCount = 0;
this.abortUploadButton = false;
this.abortUpload = false;
this.authInfo = '';
this.selectBtnDisabled = true;
Steinwender, Tamara
committed
this.storeSession = false;

Tögl, Christina
committed
this.boundCloseAdditionalMenuHandler = this.hideAdditionalMenu.bind(this);
this.initateOpenAdditionalMenu = false;
this.isInFavorites = false;

Tögl, Christina
committed
this.isInFilteredRecent = false;
this.isInRecent = false;
this.userName = '';
this.menuHeightBreadcrumb = -1;

Tögl, Christina
committed
this.boundCloseBreadcrumbMenuHandler = this.hideBreadcrumbMenu.bind(this);
this.initateOpenBreadcrumbMenu = false;
this.boundClickOutsideNewFolderHandler = this.deleteNewFolderEntry.bind(this);
this.initateOpenNewFolder = false;

Tögl, Christina
committed
this.disableRowClick = false;
this.boundRefreshOnWindowSizeChange = this.refreshOnWindowSizeChange.bind(this);
this.boundCancelNewFolderHandler = this.cancelNewFolder.bind(this);
this.boundSelectHandler = this.selectAllFiles.bind(this);
Bekerle, Patrizio
committed
}
static get scopedElements() {
return {
'dbp-icon': Icon,
'dbp-mini-spinner': MiniSpinner,
};
}
/**
* See: https://lit-element.polymer-project.org/guide/properties#initialize
*/
static get properties() {
return {
...super.properties,
lang: {type: String},
Steinwender, Tamara
committed
auth: {type: Object},
Bekerle, Patrizio
committed
authUrl: {type: String, attribute: 'auth-url'},
webDavUrl: {type: String, attribute: 'web-dav-url'},
nextcloudFileURL: {type: String, attribute: 'nextcloud-file-url'},
nextcloudName: {type: String, attribute: 'nextcloud-name'},
isPickerActive: {type: Boolean, attribute: false},
statusText: {type: String, attribute: false},
folderIsSelected: {type: String, attribute: false},
authInfo: {type: String, attribute: 'auth-info'},
directoryPath: {type: String, attribute: 'directory-path'},
allowedMimeTypes: {type: String, attribute: 'allowed-mime-types'},
directoriesOnly: {type: Boolean, attribute: 'directories-only'},
maxSelectedItems: {type: Number, attribute: 'max-selected-items'},
loading: {type: Boolean, attribute: false},
replaceFilename: {type: String, attribute: false},
uploadFileObject: {type: Object, attribute: false},
uploadFileDirectory: {type: String, attribute: false},
activeDirectoryRights: {type: String, attribute: false},
activeDirectoryACL: {type: String, attribute: false},
abortUploadButton: {type: Boolean, attribute: false},
selectBtnDisabled: {type: Boolean, attribute: true},
Steinwender, Tamara
committed
storeSession: {type: Boolean, attribute: 'store-nextcloud-session'},
disableRowClick: {type: Boolean, attribute: false},
Bekerle, Patrizio
committed
};
}
update(changedProperties) {
changedProperties.forEach((oldValue, propName) => {
switch (propName) {
this._i18n.changeLanguage(this.lang);
Bekerle, Patrizio
committed
break;
Steinwender, Tamara
committed
this._updateAuth();
break;
case 'directoriesOnly':
if (this.directoriesOnly && this._('#select_all_wrapper')) {
this._('#select_all_wrapper').classList.remove('button-container');
this._('#select_all_wrapper').classList.add('hidden');
Bekerle, Patrizio
committed
}
if (!this.directoriesOnly && this._('#select_all_wrapper')) {
this._('#select_all_wrapper').classList.add('button-container');
this._('#select_all_wrapper').classList.remove('hidden');
Bekerle, Patrizio
committed
}
}
Bekerle, Patrizio
committed
super.update(changedProperties);
}
disconnectedCallback() {
window.removeEventListener('message', this._onReceiveWindowMessage);
window.removeEventListener('resize', this.boundRefreshOnWindowSizeChange);
// deregister tabulator table callback events
this.tabulatorTable.off("tableBuilt");
this.tabulatorTable.off("rowSelectionChanged");
this.tabulatorTable.off("rowClick");
this.tabulatorTable.off("rowAdded");
this.tabulatorTable.off("dataLoaded");
Bekerle, Patrizio
committed
super.disconnectedCallback();
}
connectedCallback() {
super.connectedCallback();
const that = this;
const i18n = this._i18n;
Steinwender, Tamara
committed
this._loginStatus = '';
this._loginState = [];
this._loginCalled = false;
Bekerle, Patrizio
committed
this.updateComplete.then(() => {
// see: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
window.addEventListener('message', this._onReceiveWindowMessage);
this.tabulatorTable = new Tabulator(this._('#directory-content-table'), {
layout: 'fitColumns',
Bekerle, Patrizio
committed
selectable: this.maxSelectedItems,
placeholder: this.directoriesOnly
? i18n.t('nextcloud-file-picker.no-data')
: i18n.t('nextcloud-file-picker.no-data-type'),
responsiveLayout: 'collapse',
Bekerle, Patrizio
committed
responsiveLayoutCollapseStartOpen: false,
Bekerle, Patrizio
committed
columns: [
{
Bekerle, Patrizio
committed
{
title:
'<label id="select_all_wrapper" class="button-container select-all-icon">' +
Bekerle, Patrizio
committed
'<input type="checkbox" id="select_all" name="select_all" value="select_all">' +
'<span class="checkmark" id="select_all_checkmark"></span>' +
'</label>',
Bekerle, Patrizio
committed
width: 50,
Bekerle, Patrizio
committed
responsive: 1,
formatter: (cell, formatterParams, onRendered) => {
const icon_tag = that.getScopedTagName('dbp-icon');
let disabled = this.directoriesOnly
? 'nextcloud-picker-icon-disabled'
: '';
let icon =
`<${icon_tag} name="empty-file" class="nextcloud-picker-icon ` +
disabled +
`"></${icon_tag}>`;
let html =
cell.getValue() === 'directory'
? `<${icon_tag} name="folder" class="nextcloud-picker-icon"></${icon_tag}>`
: icon;
let div = getShadowRootDocument(this).createElement('div');
Bekerle, Patrizio
committed
},
{
title: i18n.t('nextcloud-file-picker.filename'),
responsive: 0,
widthGrow: 5,
minWidth: 150,
Bekerle, Patrizio
committed
formatter: (cell) => {
var data = cell.getValue();
let div = getShadowRootDocument(this).createElement('div');
div.classList.add('filename');
div.innerHTML = cell.getValue();
return div;
Bekerle, Patrizio
committed
},
{
title: i18n.t('nextcloud-file-picker.size'),
responsive: 4,
widthGrow: 1,
Bekerle, Patrizio
committed
formatter: (cell, formatterParams, onRendered) => {
return cell.getRow().getData().type === 'directory'
? ''
: humanFileSize(cell.getValue());
},
Bekerle, Patrizio
committed
},
{
title: i18n.t('nextcloud-file-picker.mime-type'),
responsive: 2,
widthGrow: 1,
Bekerle, Patrizio
committed
formatter: (cell, formatterParams, onRendered) => {
if (typeof cell.getValue() === 'undefined') {
Bekerle, Patrizio
committed
}
const [, fileSubType] = cell.getValue().split('/');
return fileSubType;
Bekerle, Patrizio
committed
},
{
title: i18n.t('nextcloud-file-picker.last-modified'),
responsive: 3,
widthGrow: 1,
Bekerle, Patrizio
committed
sorter: (a, b, aRow, bRow, column, dir, sorterParams) => {
const a_timestamp = Date.parse(a);
const b_timestamp = Date.parse(b);
return a_timestamp - b_timestamp;
},
formatter: function (cell, formatterParams, onRendered) {
const d = Date.parse(cell.getValue());
const timestamp = new Date(d);
const year = timestamp.getFullYear();
const month = ('0' + (timestamp.getMonth() + 1)).slice(-2);
const date = ('0' + timestamp.getDate()).slice(-2);
const hours = ('0' + timestamp.getHours()).slice(-2);
const minutes = ('0' + timestamp.getMinutes()).slice(-2);
return date + '.' + month + '.' + year + ' ' + hours + ':' + minutes;
},
Bekerle, Patrizio
committed
},
{title: 'rights', field: 'props.permissions', visible: false},
{title: 'acl', field: 'props.acl-list.acl.acl-permissions', visible: false},
Bekerle, Patrizio
committed
],
initialSort: [
{column: 'basename', dir: 'asc'},
{column: 'type', dir: 'asc'},
Bekerle, Patrizio
committed
],
rowFormatter: (row) => {
let data = row.getData();
if (!this.checkFileType(data, this.allowedMimeTypes)) {
row.getElement().classList.add('no-select'); // TODO check this
row.getElement().classList.remove('tabulator-selectable');
Bekerle, Patrizio
committed
}
if (this.directoriesOnly && typeof data.mime !== 'undefined') {
row.getElement().classList.add('no-select');
row.getElement().classList.remove('tabulator-selectable');
Bekerle, Patrizio
committed
}
if (!this.directoriesOnly && typeof data.mime === 'undefined') {
row.getElement().classList.add('no-select-styles');
}
Bekerle, Patrizio
committed
},
});
this.tabulatorTable.on("tableBuilt", this.tableBuiltFunction.bind(this));
this.tabulatorTable.on("rowSelectionChanged", this.rowSelectionChangedFunction.bind(this));
this.tabulatorTable.on("rowClick", this.rowClickFunction.bind(this));
this.tabulatorTable.on("rowAdded", this.rowAddedFunction.bind(this));
this.tabulatorTable.on("dataLoaded", this.dataLoadedFunction.bind(this));
if (
typeof this.allowedMimeTypes !== 'undefined' &&
this.allowedMimeTypes !== '' &&
!this.directoriesOnly
) {
Bekerle, Patrizio
committed
this.tabulatorTable.setFilter(this.checkFileType, this.allowedMimeTypes);
}
window.addEventListener('resize', this.boundRefreshOnWindowSizeChange);
Bekerle, Patrizio
committed
});
}
tableBuiltFunction() {
if (this._('#select_all')) {
this._('#select_all').addEventListener('click', this.boundSelectHandler);
}
if (this.directoriesOnly && this._('#select_all_wrapper')) {
this._('#select_all_wrapper').classList.remove('button-container');
this._('#select_all_wrapper').classList.add('hidden');
}
}
rowSelectionChangedFunction(data, rows) {
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
if (!this.disableRowClick) {
if (data.length > 0 && this.directoriesOnly) {
this.folderIsSelected = i18n.t('nextcloud-file-picker.load-to-folder');
} else {
this.folderIsSelected = i18n.t('nextcloud-file-picker.load-in-folder');
}
if (
!this.directoriesOnly &&
this.tabulatorTable &&
this.tabulatorTable
.getSelectedRows()
.filter(
(row) =>
row.getData().type != 'directory' &&
this.checkFileType(row.getData(), this.allowedMimeTypes)
).length > 0
) {
this.selectBtnDisabled = false;
} else {
this.selectBtnDisabled = true;
}
if (this._('#select_all_checkmark')) {
this._('#select_all_checkmark').title = this.checkAllSelected()
? i18n.t('clipboard.select-nothing')
: i18n.t('clipboard.select-all');
}
this.requestUpdate();
}
}
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
const data = row.getData();
if (
!row.getElement().classList.contains('no-select') &&
!this.disableRowClick
) {
if (this.directoriesOnly) {
// comment out if you want to navigate through folders with double click
const data = row.getData();
this.directoryClicked(e, data);
this.folderIsSelected = i18n.t('nextcloud-file-picker.load-in-folder');
} else {
switch (data.type) {
case 'directory':
this.directoryClicked(e, data);
break;
case 'file':
if (
this.tabulatorTable !== null &&
this.tabulatorTable.getSelectedRows().length ===
this.tabulatorTable
.getRows()
.filter(
(row) =>
row.getData().type != 'directory' &&
this.checkFileType(
row.getData(),
this.allowedMimeTypes
)
).length
) {
this._('#select_all').checked = true;
} else {
this._('#select_all').checked = false;
}
break;
}
}
} else {
row.deselect();
}
}
if (!this.disableRowClick) {
row.getElement().classList.toggle('addRowAnimation');
}
}
if (this.tabulatorTable !== null) {
const that = this;
setTimeout(function () {
if (that._('.tabulator-responsive-collapse-toggle-open')) {
that._a('.tabulator-responsive-collapse-toggle-open').forEach(
(element) =>
element.addEventListener(
'click',
that.toggleCollapse.bind(that)
)
);
}
if (that._('.tabulator-responsive-collapse-toggle-close')) {
that._a('.tabulator-responsive-collapse-toggle-close').forEach(
(element) =>
element.addEventListener(
'click',
that.toggleCollapse.bind(that)
)
);
}
}, 0);
Bekerle, Patrizio
committed
/**
Steinwender, Tamara
committed
* Request a re-render every time isLoggedIn()/isLoading() changes
*/
_updateAuth() {
this._loginStatus = this.auth['login-status'];
let newLoginState = [this.isLoggedIn(), this.isLoading()];
if (this._loginState.toString() !== newLoginState.toString()) {
this.requestUpdate();
}
this._loginState = newLoginState;
Steinwender, Tamara
committed
this._loginCalled = true;
Steinwender, Tamara
committed
}
}
/**
* Returns if a person is set in or not
Bekerle, Patrizio
committed
*
Steinwender, Tamara
committed
* @returns {boolean} true or false
Bekerle, Patrizio
committed
*/
Steinwender, Tamara
committed
isLoggedIn() {
return this.auth.person !== undefined && this.auth.person !== null;
Steinwender, Tamara
committed
}
Bekerle, Patrizio
committed
Steinwender, Tamara
committed
/**
* Returns true if a person has successfully logged in
*
* @returns {boolean} true or false
*/
isLoading() {
if (this._loginStatus === 'logged-out') return false;
Steinwender, Tamara
committed
return !this.isLoggedIn() && this.auth.token !== undefined;
Steinwender, Tamara
committed
}
/**
*
*/
async checkLocalStorage() {
if (!this.isLoggedIn() || !this.auth) {
if (
key.includes('nextcloud-webdav-username-') ||
key.includes('nextcloud-webdav-password-')
) {
localStorage.removeItem(key);
}
}
Steinwender, Tamara
committed
return;
Steinwender, Tamara
committed
const publicId = this.auth['person-id'];
const token = parseJwt(this.auth.token);
const sessionId = token ? token.sid : '';
if (
this.storeSession &&
sessionId &&
localStorage.getItem('nextcloud-webdav-username-' + publicId) &&
localStorage.getItem('nextcloud-webdav-password-' + publicId)
) {
try {
const userName = await decrypt(
sessionId,
localStorage.getItem('nextcloud-webdav-username-' + publicId)
);
const password = await decrypt(
sessionId,
localStorage.getItem('nextcloud-webdav-password-' + publicId)
);
this.webDavClient = createClient(this.webDavUrl + '/' + userName, {
username: userName,
password: password,
});
Steinwender, Tamara
committed
this.isPickerActive = true;
this.loadDirectory(this.directoryPath);
} catch (e) {
localStorage.removeItem('nextcloud-webdav-username-' + publicId);
localStorage.removeItem('nextcloud-webdav-password-' + publicId);
return;
}
Steinwender, Tamara
committed
}
Bekerle, Patrizio
committed
}
/**
* check mime type of row
*
* @param data
* @param filterParams
*/
checkFileType(data, filterParams) {
Bekerle, Patrizio
committed
if (typeof data.mime === 'undefined') {
return true;
}
const [fileMainType, fileSubType] = data.mime.split('/');
const mimeTypes = filterParams.split(',');
let deny = true;
mimeTypes.forEach((str) => {
const [mainType, subType] = str.split('/');
deny =
deny &&
((mainType !== '*' && mainType !== fileMainType) ||
(subType !== '*' && subType !== fileSubType));
Bekerle, Patrizio
committed
});
return !deny;
}
Steinwender, Tamara
committed
async openFilePicker() {
const i18n = this._i18n;

Tögl, Christina
committed
this.disableRowClick = false;
Bekerle, Patrizio
committed
if (this.webDavClient === null) {
this.loading = true;
this.statusText = i18n.t('nextcloud-file-picker.auth-progress');
const authUrl =
this.authUrl + '?target-origin=' + encodeURIComponent(window.location.href);
this.loginWindow = window.open(
authUrl,
'Nextcloud Login',
'width=400,height=400,menubar=no,scrollbars=no,status=no,titlebar=no,toolbar=no'
);
Bekerle, Patrizio
committed
} else {
this.loadDirectory(this.directoryPath, this.webDavClient);
}
}
return this.shadowRoot === null
? this.querySelectorAll(selector)
: this.shadowRoot.querySelectorAll(selector);
Steinwender, Tamara
committed
async onReceiveWindowMessage(event) {
Bekerle, Patrizio
committed
if (this.webDavClient === null) {
const data = event.data;
Bekerle, Patrizio
committed
if (this.loginWindow !== null) {
this.loginWindow.close();
}
// See https://github.com/perry-mitchell/webdav-client/blob/master/API.md#module_WebDAV.createClient
Bekerle, Patrizio
committed
this.webDavClient = createClient(
data.webdavUrl || this.webDavUrl + '/' + data.loginName,
Bekerle, Patrizio
committed
{
username: data.loginName,
Bekerle, Patrizio
committed
}
);
if (
this.storeSession &&
this.isLoggedIn() &&
this._('#remember-checkbox') &&
this._('#remember-checkbox').checked
) {
Steinwender, Tamara
committed
const publicId = this.auth['person-id'];
const token = parseJwt(this.auth.token);
Steinwender, Tamara
committed
if (sessionId) {
const encrytedName = await encrypt(sessionId, data.loginName);
const encrytedToken = await encrypt(sessionId, data.token);
localStorage.setItem('nextcloud-webdav-username-' + publicId, encrytedName);
localStorage.setItem(
'nextcloud-webdav-password-' + publicId,
encrytedToken
);
Steinwender, Tamara
committed
}
Bekerle, Patrizio
committed
}
Steinwender, Tamara
committed
Bekerle, Patrizio
committed
this.loadDirectory(this.directoryPath);
this.userName = data.loginName;
}
}
}
toggleCollapse(e) {
const table = this.tabulatorTable;
// give a chance to draw the table
// this is for getting more hight in tabulator table, when toggle is called
table.redraw();
}, 0);
}
* @returns {Array} reduced list of objects, including users files

Tögl, Christina
committed
filterUserFilesOnly(data) {
// R = Share, S = Shared Folder, M = Group folder or external source, G = Read, D = Delete, NV / NVW = Write, CK = Create
let result = [];
for (let i = 0; i < data.length; i++) {
if (data) {
let file_perm = data[i].props.permissions;
if (!file_perm.includes('M') && !file_perm.includes('S')) {
result.push(data[i]);
}
Bekerle, Patrizio
committed
}
}
return result;
}
/**
*/
parseFileAndBaseName(path) {
if (path[0] !== '/') {
//TODO verify
path = '/' + path;
}
while (/^.+\/$/.test(path)) {
path = path.substr(0, path.length - 1);
}
path = decodeURIComponent(path);
let array1 = this.webDavUrl.split('/');
let array2 = path.split('/');
for (let i = 0; i < array2.length; i++) {
let item2 = array2[i];
if (item1 === item2) {
array2.shift();
i--;
}
});
}
array2.shift();
let basename = array2[array2.length - 1];
let filename = '/' + array2.join('/');
}
/**
* @returns {Array} list of file objects containing corresponding information
*/
mapResponseToObject(response) {
let results = [];
response.forEach((item) => {
const [filePath, baseName] = this.parseFileAndBaseName(item.href);
const prop = item.propstat.prop;
let etag = typeof prop.getetag === 'string' ? prop.getetag.replace(/"/g, '') : null;
let sizeVal = prop.getcontentlength ? prop.getcontentlength : '0';
let fileType =
prop.resourcetype &&
typeof prop.resourcetype === 'object' &&
typeof prop.resourcetype.collection !== 'undefined'
? 'directory'
: 'file';
let mimeType;
if (fileType === 'file') {
mimeType =
prop.getcontenttype && typeof prop.getcontenttype === 'string'
? prop.getcontenttype.split(';')[0]
: '';
}
let propsObject = {
getetag: etag,
getlastmodified: prop.getlastmodified,
getcontentlength: sizeVal,
permissions: prop.permissions,
resourcetype: fileType,
getcontenttype: prop.getcontenttype,
};
let statObject = {
basename: baseName,
etag: etag,
filename: filePath,
lastmod: prop.getlastmodified,
mime: mimeType,
props: propsObject,
size: parseInt(sizeVal, 10),
type: fileType,
};
results.push(statObject);
});
return results;
}
/**
* Loads the favorites from WebDAV
*
*/
loadFavorites() {

Tögl, Christina
committed
this.hideAdditionalMenu();
const i18n = this._i18n;
if (typeof this.directoryPath === 'undefined' || this.directoryPath === undefined) {
this.directoryPath = '';
}
this.selectAllButton = true;
this.loading = true;
this.statusText = i18n.t('nextcloud-file-picker.loadpath-nextcloud-file-picker', {
name: this.nextcloudName,
});
this.lastDirectoryPath = this.directoryPath;
this.directoryPath = '';
this.isInRecent = false;

Tögl, Christina
committed
this.isInFilteredRecent = false;
this.isInFavorites = true;
if (this.webDavClient === null) {
// client is broken reload try to reset & reconnect
this.tabulatorTable.clearData();
this.webDavClient = null;
'nextcloud-file-picker.something-went-wrong'
)}
<button class="button"
title="${i18n.t('nextcloud-file-picker.refresh-nextcloud-file-picker')}"
@click="${async () => {
this.openFilePicker();
}}">
<dbp-icon name="reload">
</button>`;
this.loading = false;
this.statusText = reloadButton;
}
//see https://github.com/perry-mitchell/webdav-client#customRequest
this.webDavClient
.customRequest('/', {
method: 'REPORT',
responseType: 'text/xml',
details: true,
data:
'<?xml version="1.0"?>' +
' <oc:filter-files xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">' +
' <oc:filter-rules>' +
' <oc:favorite>1</oc:favorite>' +
' </oc:filter-rules>' +
' <d:prop>' +
' <d:getlastmodified />' +
' <d:resourcetype />' +
' <d:getcontenttype />' +
' <d:getcontentlength />' +
' <d:getetag />' +
' <oc:permissions />' +
' </d:prop>' +
' </oc:filter-files>',
})
.then((contents) => {
parseXML(contents.data).then((davResp) => {
// console.log("-contents.data-----", davResp);
let dataObject = this.mapResponseToObject(davResp.multistatus.response);
this.loading = false;
this.tabulatorTable.setData(dataObject);
this.tabulatorTable.setSort([
{column: "basename", dir: "asc"},
{column: "type", dir: "asc"},
]);
if (
this._('#directory-content-table').querySelector(
'div.tabulator-tableHolder > div.tabulator-placeholder > span'
)
) {
this._('#directory-content-table').querySelector(
'div.tabulator-tableHolder > div.tabulator-placeholder > span'
).innerText = i18n.t('nextcloud-file-picker.no-favorites', {
name: this.nextcloudName,
});
this.isPickerActive = true;
this._('.nextcloud-content').scrollTop = 0;
this._('#download-button').setAttribute('disabled', 'true');
})
.catch((error) => {
//TODO verify error catching
console.error(error.message);
// on Error: try to reload with home directory
if (this.webDavClient !== null && error.message.search('401') === -1) {
console.log('error in load directory');
this.directoryPath = '';
this.loadDirectory('');
} else {
this.loading = false;
this.statusText = html`
<span class="error">
${i18n.t('nextcloud-file-picker.webdav-error', {error: error.message})}
</span>
`;
this.isPickerActive = false;
this.tabulatorTable.clearData();
this.webDavClient = null;
'nextcloud-file-picker.something-went-wrong'
)}
<button class="button"
title="${i18n.t(
'nextcloud-file-picker.refresh-nextcloud-file-picker'
)}"
@click="${async () => {
this.openFilePicker();
}}">
<dbp-icon name="reload">
</button>`;
this.loading = false;
this.statusText = reloadButton;
}
this.isInFavorites = false;
}
* Loads recent files and folders from WebDAV
*
*/

Tögl, Christina
committed
loadAllRecentFiles() {
this.hideAdditionalMenu();
const i18n = this._i18n;
if (typeof this.directoryPath === 'undefined' || this.directoryPath === undefined) {
this.directoryPath = '';
}
this.selectAllButton = true;
this.loading = true;
this.statusText = i18n.t('nextcloud-file-picker.loadpath-nextcloud-file-picker', {
name: this.nextcloudName,
});
this.lastDirectoryPath = this.directoryPath;
this.directoryPath = '';
this.isInFavorites = false;

Tögl, Christina
committed
this.isInFilteredRecent = false;
this.isInRecent = true;
let date = new Date();
date.setMonth(date.getMonth() - 3);
let searchDate = date.toISOString().split('.')[0] + 'Z';
if (this.webDavClient === null || this.userName === null) {
// client is broken reload try to reset & reconnect
this.tabulatorTable.clearData();
this.webDavClient = null;
'nextcloud-file-picker.something-went-wrong'
)}
<button class="button"
title="${i18n.t('nextcloud-file-picker.refresh-nextcloud-file-picker')}"
@click="${async () => {
this.openFilePicker();
}}">
<dbp-icon name="reload">
</button>`;
this.loading = false;
this.statusText = reloadButton;
}
//see https://github.com/perry-mitchell/webdav-client#customRequest
this.webDavClient
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
.customRequest('../..', {
method: 'SEARCH',
responseType: 'text/xml',
headers: {'Content-Type': 'text/xml'},
details: true,
data:
'<?xml version="1.0" encoding=\'UTF-8\'?>' +
' <d:searchrequest xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">' +
' <d:basicsearch>' +
' <d:select>' +
' <d:prop>' +
' <d:getlastmodified />' +
' <d:resourcetype />' +
' <d:getcontenttype />' +
' <d:getcontentlength />' +
' <d:getetag />' +
' <oc:permissions />' +
' <oc:size/>' +
' <oc:owner-id/>' +
' <oc:owner-display-name/>' +
' </d:prop>' +
' </d:select>' +
' <d:from>' +
' <d:scope>' +
' <d:href>/files/' +
this.userName +
'/</d:href>' +
' <d:depth>infinity</d:depth>' +
' </d:scope>' +
' </d:from>' +
' <d:where> ' +
' <d:gte>' +
' <d:prop>' +
' <d:getlastmodified/>' +
' </d:prop>' +
' <d:literal>' +
searchDate +
'</d:literal>' +
' </d:gte>' +
' </d:where>' +
' <d:orderby>' +
' <d:order>' +
' <d:prop>' +
' <d:getlastmodified/>' +
' </d:prop>' +
' <d:descending/>' +
' </d:order>' +
' </d:orderby>' +
' <d:limit>' +
' <d:nresults>15</d:nresults>' +
' </d:limit>' +
' </d:basicsearch>' +
' </d:searchrequest>',
.then((contents) => {
parseXML(contents.data).then((davResp) => {
let dataObject = this.mapResponseToObject(davResp.multistatus.response);
// console.log("-contents.data-----", dataObject);

Tögl, Christina
committed
this.loading = false;

Tögl, Christina
committed
this.tabulatorTable.setData(dataObject);
this.tabulatorTable.setSort([{column: 'lastmod', dir: 'desc'}]);
if (
this._('#directory-content-table').querySelector(
'div.tabulator-tableHolder > div.tabulator-placeholder > span'
)
) {
this._('#directory-content-table').querySelector(