mirror of
https://github.com/nextcloud/server.git
synced 2026-02-20 00:12:30 -05:00
Merge pull request #57648 from nextcloud/chore/drop-jquery
chore!: drop jQuery UI and jQuery
This commit is contained in:
commit
b6d22f384b
192 changed files with 538 additions and 6001 deletions
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import { getCSPNonce } from '@nextcloud/auth'
|
||||
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
||||
window.OCP.Collaboration.registerType('file', {
|
||||
action: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
OC.dialogs.filepicker(t('files_sharing', 'Link to a file'), function(f) {
|
||||
const client = OC.Files.getClient()
|
||||
client.getFileInfo(f).then((status, fileInfo) => {
|
||||
resolve(fileInfo.id)
|
||||
}).fail(() => {
|
||||
reject(new Error('Cannot get fileinfo'))
|
||||
})
|
||||
}, false, null, false, OC.dialogs.FILEPICKER_TYPE_CHOOSE, '', { allowDirectoryChooser: true })
|
||||
})
|
||||
},
|
||||
typeString: t('files_sharing', 'Link to a file'),
|
||||
typeIconClass: 'icon-files-dark',
|
||||
})
|
||||
28
apps/files_sharing/src/collaborationresourceshandler.ts
Normal file
28
apps/files_sharing/src/collaborationresourceshandler.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { getCSPNonce } from '@nextcloud/auth'
|
||||
import { FilePickerType, getFilePickerBuilder } from '@nextcloud/dialogs'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
||||
window.OCP.Collaboration.registerType('file', {
|
||||
typeString: t('files_sharing', 'Link to a file'),
|
||||
typeIconClass: 'icon-files-dark',
|
||||
async action() {
|
||||
const filePicker = getFilePickerBuilder(t('files_sharing', 'Link to a file'))
|
||||
.setType(FilePickerType.Choose)
|
||||
.allowDirectories(true)
|
||||
.build()
|
||||
|
||||
try {
|
||||
const [node] = await filePicker.pickNodes()
|
||||
return node!.fileid
|
||||
} catch {
|
||||
throw new Error('Cannot get fileinfo')
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
import type { Attribute, INode } from '@nextcloud/files'
|
||||
|
||||
import { Permission } from '@nextcloud/files'
|
||||
|
||||
interface RawLegacyFileInfo {
|
||||
id: number
|
||||
path: string
|
||||
|
|
@ -57,13 +59,31 @@ export default function(node: INode): LegacyFileInfo {
|
|||
attributes: node.attributes,
|
||||
}
|
||||
|
||||
const fileInfo = new OC.Files.FileInfo(rawFileInfo)
|
||||
|
||||
// TODO remove when no more legacy backbone is used
|
||||
fileInfo.get = (key) => fileInfo[key]
|
||||
fileInfo.isDirectory = () => fileInfo.mimetype === 'httpd/unix-directory'
|
||||
fileInfo.canEdit = () => Boolean(fileInfo.permissions & OC.PERMISSION_UPDATE)
|
||||
fileInfo.node = node
|
||||
const fileInfo: LegacyFileInfo = {
|
||||
...rawFileInfo,
|
||||
node,
|
||||
|
||||
get(key) {
|
||||
return this[key]
|
||||
},
|
||||
isDirectory() {
|
||||
return this.mimetype === 'httpd/unix-directory'
|
||||
},
|
||||
canEdit() {
|
||||
return Boolean(this.permissions & Permission.UPDATE)
|
||||
},
|
||||
canDownload() {
|
||||
for (const i in this.shareAttributes) {
|
||||
const attr = this.shareAttributes[i]
|
||||
if (attr.scope === 'permissions' && attr.key === 'download') {
|
||||
return attr.value === true
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
return fileInfo
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ use OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent;
|
|||
/** @template-implements IEventListener<LoadSettingsScriptsEvent> */
|
||||
class LoadAdditionalSettingsScriptsListener implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
Util::addScript('core', 'files_fileinfo');
|
||||
Util::addScript('core', 'files_client');
|
||||
Util::addScript('core', 'systemtags');
|
||||
Util::addScript(Application::APP_ID, 'workflowengine');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,14 +60,6 @@
|
|||
"count": 1
|
||||
}
|
||||
},
|
||||
"core/src/OC/dialogs.js": {
|
||||
"camelcase": {
|
||||
"count": 33
|
||||
},
|
||||
"no-undef": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"core/src/views/Login.vue": {
|
||||
"vue/multi-word-component-names": {
|
||||
"count": 1
|
||||
|
|
|
|||
472
build/frontend-legacy/package-lock.json
generated
472
build/frontend-legacy/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -51,7 +51,6 @@
|
|||
"@vueuse/components": "^11.3.0",
|
||||
"@vueuse/core": "^11.3.0",
|
||||
"@vueuse/integrations": "^11.3.0",
|
||||
"backbone": "^1.6.1",
|
||||
"blurhash": "^2.0.5",
|
||||
"browserslist-useragent-regexp": "^4.1.3",
|
||||
"camelcase": "^9.0.0",
|
||||
|
|
@ -67,9 +66,6 @@
|
|||
"focus-trap": "^7.8.0",
|
||||
"handlebars": "^4.7.8",
|
||||
"is-svg": "^6.1.0",
|
||||
"jquery": "~3.7",
|
||||
"jquery-ui": "1.14.1",
|
||||
"jquery-ui-dist": "^1.13.3",
|
||||
"libphonenumber-js": "^1.12.36",
|
||||
"lodash": "^4.17.23",
|
||||
"marked": "^17.0.2",
|
||||
|
|
@ -81,9 +77,6 @@
|
|||
"pinia": "^2.3.1",
|
||||
"query-string": "^9.3.1",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"select2": "3.5.1",
|
||||
"snap.js": "^2.0.9",
|
||||
"strengthify": "github:nextcloud/strengthify#0.5.9",
|
||||
"throttle-debounce": "^5.0.2",
|
||||
"underscore": "1.13.7",
|
||||
"url-search-params-polyfill": "^8.2.5",
|
||||
|
|
|
|||
|
|
@ -197,12 +197,6 @@ const config = {
|
|||
new NodePolyfillPlugin({
|
||||
additionalAliases: ['process'],
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
// Provide jQuery to jquery plugins as some are loaded before $ is exposed globally.
|
||||
// We need to provide the path to node_moduels as otherwise npm link will fail due
|
||||
// to tribute.js checking for jQuery in @nextcloud/vue
|
||||
jQuery: require.resolve('jquery'),
|
||||
}),
|
||||
|
||||
new WorkboxPlugin.GenerateSW({
|
||||
swDest: 'preview-service-worker.js',
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ module.exports = {
|
|||
},
|
||||
core: {
|
||||
'ajax-cron': path.join(__dirname, 'core/src', 'ajax-cron.ts'),
|
||||
files_client: path.join(__dirname, 'core/src', 'files/client.js'),
|
||||
files_fileinfo: path.join(__dirname, 'core/src', 'files/fileinfo.js'),
|
||||
install: path.join(__dirname, 'core/src', 'install.ts'),
|
||||
login: path.join(__dirname, 'core/src', 'login.js'),
|
||||
login_flow: path.join(__dirname, 'core/src', 'login-flow.ts'),
|
||||
|
|
|
|||
|
|
@ -53,10 +53,7 @@ class BeforeTemplateRenderedListener implements IEventListener {
|
|||
Util::addTranslations('core');
|
||||
|
||||
if ($event->getResponse()->getRenderAs() !== TemplateResponse::RENDER_AS_ERROR) {
|
||||
Util::addScript('core', 'merged-template-prepend', 'core', true);
|
||||
Util::addScript('core', 'files_client', 'core', true);
|
||||
Util::addScript('core', 'files_fileinfo', 'core', true);
|
||||
|
||||
Util::addScript('core', 'mimetypelist', 'core', true);
|
||||
|
||||
// If installed and background job is set to ajax, add dedicated script
|
||||
if ($this->appConfig->getValueString('core', 'backgroundjobs_mode', 'ajax') === 'ajax') {
|
||||
|
|
|
|||
|
|
@ -798,7 +798,7 @@ $min-content-width: variables.$breakpoint-mobile - variables.$navigation-width -
|
|||
background: var(--color-main-background);
|
||||
border-inline-start: 1px solid var(--color-border);
|
||||
flex-shrink: 0;
|
||||
// no animations possible, use OC.Apps.showAppSidebar
|
||||
// no animations possible
|
||||
&.disappear {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/#skip-actions{position:absolute;overflow:hidden;z-index:9999;top:-999px;inset-inline-start:3px;padding:11px;display:flex;flex-wrap:wrap;gap:11px}#skip-actions:focus-within{top:var(--header-height)}#header{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#header:not(.header-guest){display:inline-flex;position:absolute;top:0;width:100%;z-index:2000;height:var(--header-height);box-sizing:border-box;justify-content:space-between}#header #nextcloud{padding:5px 0;padding-inline-start:86px;position:relative;height:calc(100% - var(--default-grid-baseline));box-sizing:border-box;opacity:1;align-items:center;display:flex;flex-wrap:wrap;overflow:hidden;margin:2px}#header #nextcloud:hover,#header #nextcloud:active{opacity:1}#header #nextcloud .logo{display:inline-flex;background-image:var(--image-logoheader, var(--image-logo, url("../img/logo/logo.svg")));background-repeat:no-repeat;background-size:contain;background-position:center;width:62px;position:absolute;inset-inline-start:12px;top:1px;bottom:1px;filter:var(--image-logoheader-custom, var(--background-image-invert-if-bright))}#header #nextcloud:focus-visible,#header .app-menu-entry a:focus-visible,#header .header-menu button:first-of-type:focus-visible{outline:none}#header #nextcloud:focus-visible::after,#header .app-menu-entry a:focus-visible::after,#header .header-menu button:first-of-type:focus-visible::after{content:" ";position:absolute;inset-block-end:2px;transform:translateX(-50%);width:12px;height:2px;border-radius:3px;background-color:var(--color-background-plain-text);inset-inline-start:50%;opacity:1}#header .header-start{display:inline-flex;align-items:center;flex:1 0;white-space:nowrap;min-width:0}#header .header-end{display:inline-flex;align-items:center;justify-content:flex-end;flex-shrink:1;margin-inline-end:calc(3*var(--default-grid-baseline))}#header .header-end>div,#header .header-end>form{height:100%;position:relative}#header .header-end>div>.menutoggle,#header .header-end>form>.menutoggle{display:flex;justify-content:center;align-items:center;width:var(--header-height);height:var(--header-menu-item-height);cursor:pointer;opacity:.85;padding:0;margin:2px 0}#header .header-end>div>.menutoggle:focus,#header .header-end>form>.menutoggle:focus{opacity:1}#header .header-end>div>.menutoggle:focus-visible,#header .header-end>form>.menutoggle:focus-visible{outline:none}#header .header-end>div>.menu,#header .header-end>form>.menu{background-color:var(--color-main-background);filter:drop-shadow(0 1px 5px var(--color-box-shadow));border-radius:var(--border-radius-large);box-sizing:border-box;z-index:2000;position:absolute;max-width:350px;min-height:calc(var(--default-clickable-area)*1.5);max-height:calc(100vh - var(--header-height) - 2*var(--default-grid-baseline));inset-inline-end:8px;top:var(--header-height);margin:0;overflow-y:auto}#header .header-end>div>.menu:not(.popovermenu),#header .header-end>form>.menu:not(.popovermenu){display:none}#header .header-end>div>.menu:after,#header .header-end>form>.menu:after{border:10px solid rgba(0,0,0,0);border-bottom-color:var(--color-main-background);bottom:100%;content:" ";height:0;width:0;position:absolute;pointer-events:none;inset-inline-end:10px}#header .header-end>div>.menu>div,#header .header-end>div>.menu>ul,#header .header-end>form>.menu>div,#header .header-end>form>.menu>ul{-webkit-overflow-scrolling:touch;min-height:calc(var(--default-clickable-area)*1.5);max-height:calc(100vh - var(--header-height) - 2*var(--default-grid-baseline))}#header .header-end>div .emptycontent h2,#header .header-end>form .emptycontent h2{font-weight:normal;font-size:16px}#header .header-end>div .emptycontent [class^=icon-],#header .header-end>div .emptycontent [class*=icon-],#header .header-end>form .emptycontent [class^=icon-],#header .header-end>form .emptycontent [class*=icon-]{background-size:48px;height:48px;width:48px}#header .header-appname{color:var(--color-background-plain-text);font-size:16px;font-weight:bold;margin:0;padding:0;padding-inline-end:5px;overflow:hidden;text-overflow:ellipsis;flex:1 1 100%}#header .header-appname .header-info{display:flex;flex-direction:column;overflow:hidden}#header .header-appname .header-info .header-title{overflow:hidden;text-overflow:ellipsis}#header .header-appname .header-info .header-shared-by{color:var(--color-background-plain-text);position:relative;font-weight:300;font-size:var(--font-size-small);line-height:var(--font-size-small);overflow:hidden;text-overflow:ellipsis}/*# sourceMappingURL=header.css.map */
|
||||
*/#skip-actions{position:absolute;overflow:hidden;z-index:9999;top:-999px;inset-inline-start:3px;padding:11px;display:flex;flex-wrap:wrap;gap:11px}#skip-actions:focus-within{top:var(--header-height)}#header{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#header:not(.header-guest){display:inline-flex;position:absolute;top:0;width:100%;z-index:2000;height:var(--header-height);box-sizing:border-box;justify-content:space-between}#header #nextcloud{padding:5px 0;padding-inline-start:86px;position:relative;height:calc(100% - var(--default-grid-baseline));box-sizing:border-box;opacity:1;align-items:center;display:flex;flex-wrap:wrap;overflow:hidden;margin:2px}#header #nextcloud:hover,#header #nextcloud:active{opacity:1}#header #nextcloud .logo{display:inline-flex;background-image:var(--image-logoheader, var(--image-logo, url("../img/logo/logo.svg")));background-repeat:no-repeat;background-size:contain;background-position:center;width:62px;position:absolute;inset-inline-start:12px;top:1px;bottom:1px;filter:var(--image-logoheader-custom, var(--background-image-invert-if-bright))}#header #nextcloud:focus-visible,#header .app-menu-entry a:focus-visible,#header .header-menu button:first-of-type:focus-visible{outline:none}#header #nextcloud:focus-visible::after,#header .app-menu-entry a:focus-visible::after,#header .header-menu button:first-of-type:focus-visible::after{content:" ";position:absolute;inset-block-end:2px;transform:translateX(-50%);width:12px;height:2px;border-radius:3px;background-color:var(--color-background-plain-text);inset-inline-start:50%;opacity:1}#header .header-start{display:inline-flex;align-items:center;flex:1 0;white-space:nowrap;min-width:0}#header .header-end{display:inline-flex;align-items:center;justify-content:flex-end;flex-shrink:1;margin-inline-end:calc(3*var(--default-grid-baseline))}#header .header-appname{color:var(--color-background-plain-text);font-size:16px;font-weight:bold;margin:0;padding:0;padding-inline-end:5px;overflow:hidden;text-overflow:ellipsis;flex:1 1 100%}#header .header-appname .header-info{display:flex;flex-direction:column;overflow:hidden}#header .header-appname .header-info .header-title{overflow:hidden;text-overflow:ellipsis}#header .header-appname .header-info .header-shared-by{color:var(--color-background-plain-text);position:relative;font-weight:300;font-size:var(--font-size-small);line-height:var(--font-size-small);overflow:hidden;text-overflow:ellipsis}/*# sourceMappingURL=header.css.map */
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["header.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA,GAYA,cACC,kBACA,gBACA,aACA,WACA,uBACA,aACA,aACA,eACA,SAEA,2BACC,yBAKF,QAEC,yBACA,sBACA,qBACA,iBAGA,2BACC,oBACA,kBACA,MACA,WACA,aACA,4BACA,sBACA,8BAID,mBACC,cACA,0BACA,kBACA,iDACA,sBACA,UACA,mBACA,aACA,eACA,gBACA,WAEA,mDACC,UAID,yBACC,oBACA,yFACA,4BACA,wBACA,2BACA,WACA,kBACA,wBACA,QACA,WAEA,gFAMF,iIAGC,aAEA,sJACC,YACA,kBACA,oBACA,2BACA,WACA,WACA,kBACA,oDACA,uBACA,UAOF,sBACC,oBACA,mBACA,SACA,mBACA,YAKD,oBACC,oBACA,mBACA,yBACA,cAEA,uDAIA,iDAEC,YACA,kBACA,yEACC,aACA,uBACA,mBACA,2BACA,sCACA,eACA,YACA,UACA,aAEA,qFACC,UAGD,qGACC,aAIF,6DACC,8CACA,sDACA,yCACA,sBACA,aACA,kBACA,gBAvJH,mDACA,+EAwJG,qBACA,yBACA,SACA,gBAEA,iGACC,aAID,yEACC,gCACA,iDACA,YACA,YACA,SACA,QACA,kBACA,oBACA,sBAGD,wIAEC,iCAjLJ,mDACA,+EAsLG,mFACC,mBACA,eAED,sNAEC,qBACA,YACA,WAQJ,wBACC,yCACA,eACA,iBACA,SACA,UACA,uBACA,gBACA,uBAEA,cAGA,qCACC,aACA,sBACA,gBAEA,mDACC,gBACA,uBAGD,uDACC,yCACA,kBACA,gBACA,iCACA,mCACA,gBACA","file":"header.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["header.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA,GAYA,cACC,kBACA,gBACA,aACA,WACA,uBACA,aACA,aACA,eACA,SAEA,2BACC,yBAKF,QAEC,yBACA,sBACA,qBACA,iBAGA,2BACC,oBACA,kBACA,MACA,WACA,aACA,4BACA,sBACA,8BAID,mBACC,cACA,0BACA,kBACA,iDACA,sBACA,UACA,mBACA,aACA,eACA,gBACA,WAEA,mDACC,UAID,yBACC,oBACA,yFACA,4BACA,wBACA,2BACA,WACA,kBACA,wBACA,QACA,WAEA,gFAMF,iIAGC,aAEA,sJACC,YACA,kBACA,oBACA,2BACA,WACA,WACA,kBACA,oDACA,uBACA,UAOF,sBACC,oBACA,mBACA,SACA,mBACA,YAKD,oBACC,oBACA,mBACA,yBACA,cAEA,uDAKD,wBACC,yCACA,eACA,iBACA,SACA,UACA,uBACA,gBACA,uBAEA,cAGA,qCACC,aACA,sBACA,gBAEA,mDACC,gBACA,uBAGD,uDACC,yCACA,kBACA,gBACA,iCACA,mCACA,gBACA","file":"header.css"}
|
||||
|
|
@ -122,84 +122,6 @@
|
|||
flex-shrink: 1;
|
||||
// Add some spacing so the last entry looks ok
|
||||
margin-inline-end: calc(3 * var(--default-grid-baseline));
|
||||
|
||||
// legacy JQuery header menus
|
||||
// TODO: we already migrated our own code and deprecated it - can be removed together with global jQuery
|
||||
> div,
|
||||
> form {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
> .menutoggle {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: var(--header-height);
|
||||
height: var(--header-menu-item-height);
|
||||
cursor: pointer;
|
||||
opacity: 0.85;
|
||||
padding: 0;
|
||||
margin: 2px 0;
|
||||
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
> .menu {
|
||||
background-color: var(--color-main-background);
|
||||
filter: drop-shadow(0 1px 5px var(--color-box-shadow));
|
||||
border-radius: var(--border-radius-large);
|
||||
box-sizing: border-box;
|
||||
z-index: 2000;
|
||||
position: absolute;
|
||||
max-width: 350px;
|
||||
@include header-menu-height();
|
||||
inset-inline-end: 8px; // relative to parent
|
||||
top: var(--header-height);
|
||||
margin: 0;
|
||||
overflow-y: auto;
|
||||
|
||||
&:not(.popovermenu) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Dropdown arrow */
|
||||
&:after {
|
||||
border: 10px solid transparent;
|
||||
border-bottom-color: var(--color-main-background);
|
||||
bottom: 100%;
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
inset-inline-end: 10px;
|
||||
}
|
||||
|
||||
& > div,
|
||||
& > ul {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
@include header-menu-height();
|
||||
}
|
||||
}
|
||||
|
||||
.emptycontent {
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
}
|
||||
[class^='icon-'],
|
||||
[class*='icon-'] {
|
||||
background-size: 48px;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Public layout related headers
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["inputs.scss","variables.scss","functions.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA,GCEA;AAAA;AAAA;AAAA,GCFA;AAAA;AAAA;AAAA,GFWA,kFACC,6BAGD,uGACC,wCAGD,sDACC,kCAMD,iHAUC,YACA,yCACA,sBAYA,oFACC,eACA,oCACA,sCACA,QA/BiB,GAmCnB,wBACC,aAID,yJAUC,iBACA,8CACA,6BACA,0CACA,mCACA,aACA,mCACA,YACA,uYACC,WACA,sBAOC,kxDAIC,oCACA,aAED,gmBACC,aACA,8CACA,6BAGF,maACC,6DACA,oDAGF,wNACC,8CACA,6BACA,eACA,WAED,wNACC,gBAED,oPACC,mDAGD,iNACC,8CACA,0CACA,wCACA,eAGA,kvBAEC,+CAIA,mjCAGC,oDACA,gDAED,gwBAEC,4CAED,2WACC,6CAGF,gRAEC,8CACA,6CACA,eAKH,2BACC,WACA,sBACA,gBACA,eACA,gDACA,aACA,mCAEA,8CACA,oCACA,eACA,WAKA,4KACC,6BACA,0BACA,qBAEA,qCAED,0EAIC,YACA,WAID,kBACC,WACA,cACA,gBACA,WACA,eAED,mBACC,SACA,QAED,iBACC,cAKF,6GASC,2FACA,mCACA,WACA,yCACA,eACA,sBACA,8CACA,oDACA,YAEA,kSAEC,0DAGD,mKACC,eAIF,qMAcC,WACA,sBACA,eACA,mCACA,8CACA,6BACA,iDACA,YACA,aACA,yCACA,uBACA,eACA,+0BACC,8CACA,kDAED,yRACC,YAIF,mCACC,8CACA,6BAGD,mCACC,aACA,YAID,OACC,iDACA,gBACA,8CACA,mCAGD,qBACC,qCAGD,qBACC,oCASA,2DACC,eAIA,sFACC,eAMH,sGAQC,iBACA,2CAGA,gMACC,SAGD,oIACC,+CACA,kDACA,yCACA,kKACC,qDACA,+CAaD,4MAEC,qBACA,2BACA,WASF,kGACC,qCACA,mDACA,mFACA,iBACA,4BAEA,yDACA,UACA,qCACA,oCACA,gBACA,eACA,oBACA,6HACC,eE1UF,+CFkVE,yOACC,uCAID,4qBAGC,qDACA,8CACA,6vBACC,uDAQH,+VACC,qDACA,mDAEA,UAOH,uBAEC,eAGD,2BAEC,mBASA,4GAEC,kBACA,4BACA,SACA,UACA,WACA,gBACA,oIACC,iBAED,4WAEC,eAED,gKACC,WACA,qBACA,OAvBmB,KAwBnB,MAxBmB,KAyBnB,sBACA,kBACA,aACA,sBACA,+CAED,oeAEC,0CAED,4LACC,oBACA,qCACA,kBACA,mBAED,4bAIC,8DACA,8CACA,0CAED,oMACC,+CACA,0DAED,oOACC,+CAID,gJACC,qBACA,yBAED,oMACC,cA/DmB,KAmEpB,mFACC,kBACA,OArEmB,KAsEnB,MAtEmB,KAuEnB,2BACA,2BAED,mGACC,yDAED,+GACC,0DAOD,gZAEC,2BAED,wUACC,aAzF0B,KA2F3B,4NACC,8DACA,+BACA,2BAED,gOACC,0CACA,2CAED,gQACC,8DACA,2CACA,+BAID,8OAEC,0CACA,6BACA,+DAED,6HACC,gEAED,mHACC,WAMH,iBACC,gBACA,8CACA,qCACC,sCAED,yBACC,qBACA,sBACA,sBACA,6BACC,eAGF,uCACC,gBACA,wDACA,yCAED,kCACC,iBACA,SACA,UACA,wDACC,mBACA,gBACA,uBACA,6DACC,eACA,gEACC,eACA,iBAIH,6JAGC,kBACA,kBACA,aACA,+BACA,eACA,oCAGA,mEACC,8CAGF,uDACE,8CACA,6BAKJ,qDACC,4CAGD,qDACC,2CAKA,oGAEC,eAKD,mHAEC,gBACA,mBACA,uBACA,wCACA,+CACA,uBACA,yCACA,0CACA,SACA,YACA,gBACA,6IACC,0CAED,iKACC,iBACA,yBACA,stBAIC,sBACA,8CACA,oCACA,0CAED,2NACC,aAGF,2KACC,iBACA,gBACA,gBACA,6BACA,yMACC,2BAMJ,sBACC,WACA,sBACA,+DACC,aACA,eACA,kEACC,WAGF,uCACC,gBACA,mBACA,uBACA,wCACA,+CACA,uBACA,yCACA,0CACA,SACA,iBACA,gBACA,oDACC,0CAED,8DACC,iBACA,yBACA,sBACA,8CACA,0CACA,2FACC,aAED,8JAEC,qCACA,iCAGF,sDACC,gBACA,gBACA,YACA,wDACC,mEACA,WAGF,2LAGC,WAED,mEACC,iBAMH,UACC,WACA,sBACA,qBACA,2BACC,wBACA,eACA,yCACC,iBACA,yBACA,sBACA,8CACA,oCACA,0CACA,oBACA,mBACA,gDACC,wBAIH,yBACC,UACA,4BACC,YACA,kBACA,kBACA,+BACA,eACA,oCACA,8BACC,mBACA,gBACA,uBACA,YACA,sBACA,uBACA,SACA,eACA,eACA,2BACA,yBACA,sBACA,qBACA,iBACA,oBACA,mBACA,0CACA,yBACA,sCACC,YACA,4CACA,4BACA,2BACA,eACA,gBACA,cACA,WACA,sBACA,kBAGF,sCACC,6BAED,qCACC,8CACA,6BACA,6CACC,mBAQL,mBACC,cACA,WACA,UACA,cACA,8CACA,mCACA,gBACA,WACA,gBAEC,2CACC,8BAED,gDACC,8BAGF,yCACC,yBAED,sCACC,mCACA,wCACA,iCAED,2CACC,mCACA,wCACA,iCAKF,iBACC,QAEC,0BAED,QAEC,yBAED,YAGC,0BAED,QAEC,0BAIF,OACC,qBACA,uBACA,mCAKD,cACC,kBACA,4BACA,aACA,UACA,WACA,gBAWD,cAJC,oCACA,mCAOD,wBARC,oCACA,mCAWD,4BAZC,oCACA","file":"inputs.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["inputs.scss","variables.scss","functions.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA,GCEA;AAAA;AAAA;AAAA,GCFA;AAAA;AAAA;AAAA,GFWA,kFACC,6BAMD,iHAUC,YACA,yCACA,sBAYA,oFACC,eACA,oCACA,sCACA,QA/BiB,GAmCnB,wBACC,aAID,kHASC,iBACA,8CACA,6BACA,0CACA,mCACA,aACA,mCACA,YACA,8TACC,WACA,sBAOC,49CAIC,oCACA,aAED,wfACC,aACA,8CACA,6BAGF,sVACC,6DACA,oDAGF,wKACC,8CACA,6BACA,eACA,WAED,wKACC,gBAED,gMACC,mDAGD,kKACC,8CACA,0CACA,wCACA,eAGA,omBAEC,+CAIA,s2BAGC,oDACA,gDAED,gnBAEC,4CAED,sSACC,6CAGF,wNAEC,8CACA,6CACA,eAKH,2BACC,WACA,sBACA,gBACA,eACA,gDACA,aACA,mCAEA,8CACA,oCACA,eACA,WAKA,4KACC,6BACA,0BACA,qBAEA,qCAED,0EAIC,YACA,WAID,kBACC,WACA,cACA,gBACA,WACA,eAED,mBACC,SACA,QAED,iBACC,cAKF,6GASC,2FACA,mCACA,WACA,yCACA,eACA,sBACA,8CACA,oDACA,YAEA,kSAEC,0DAGD,mKACC,eAIF,sLAaC,WACA,sBACA,eACA,mCACA,8CACA,6BACA,iDACA,YACA,aACA,yCACA,uBACA,eACA,kyBACC,8CACA,kDAED,0QACC,YAIF,mCACC,aACA,YAID,OACC,iDACA,gBACA,8CACA,mCAGD,qBACC,qCAGD,qBACC,oCASA,2DACC,eAIA,sFACC,eAMH,sGAQC,iBACA,2CAGA,gMACC,SAGD,oIACC,+CACA,kDACA,yCACA,kKACC,qDACA,+CAaD,4MAEC,qBACA,2BACA,WASF,kGACC,qCACA,mDACA,mFACA,iBACA,4BAEA,yDACA,UACA,qCACA,oCACA,gBACA,eACA,oBACA,6HACC,eE3TF,+CFmUE,yOACC,uCAID,4qBAGC,qDACA,8CACA,6vBACC,uDAQH,+VACC,qDACA,mDAEA,UAOH,uBAEC,eAGD,2BAEC,mBASA,4GAEC,kBACA,4BACA,SACA,UACA,WACA,gBACA,oIACC,iBAED,4WAEC,eAED,gKACC,WACA,qBACA,OAvBmB,KAwBnB,MAxBmB,KAyBnB,sBACA,kBACA,aACA,sBACA,+CAED,oeAEC,0CAED,4LACC,oBACA,qCACA,kBACA,mBAED,4bAIC,8DACA,8CACA,0CAED,oMACC,+CACA,0DAED,oOACC,+CAID,gJACC,qBACA,yBAED,oMACC,cA/DmB,KAmEpB,mFACC,kBACA,OArEmB,KAsEnB,MAtEmB,KAuEnB,2BACA,2BAED,mGACC,yDAED,+GACC,0DAOD,gZAEC,2BAED,wUACC,aAzF0B,KA2F3B,4NACC,8DACA,+BACA,2BAED,gOACC,0CACA,2CAED,gQACC,8DACA,2CACA,+BAID,8OAEC,0CACA,6BACA,+DAED,6HACC,gEAED,mHACC,WAMH,UACC,WACA,sBACA,qBACA,2BACC,wBACA,eACA,yCACC,iBACA,yBACA,sBACA,8CACA,oCACA,0CACA,oBACA,mBACA,gDACC,wBAIH,yBACC,UACA,4BACC,YACA,kBACA,kBACA,+BACA,eACA,oCACA,8BACC,mBACA,gBACA,uBACA,YACA,sBACA,uBACA,SACA,eACA,eACA,2BACA,yBACA,sBACA,qBACA,iBACA,oBACA,mBACA,0CACA,yBACA,sCACC,YACA,4CACA,4BACA,2BACA,eACA,gBACA,cACA,WACA,sBACA,kBAGF,sCACC,6BAED,qCACC,8CACA,6BACA,6CACC,mBAQL,mBACC,cACA,WACA,UACA,cACA,8CACA,mCACA,gBACA,WACA,gBAEC,2CACC,8BAED,gDACC,8BAGF,yCACC,yBAED,sCACC,mCACA,wCACA,iCAED,2CACC,mCACA,wCACA,iCAKF,iBACC,QAEC,0BAED,QAEC,yBAED,YAGC,0BAED,QAEC,0BAIF,OACC,qBACA,uBACA,mCAKD,cACC,kBACA,4BACA,aACA,UACA,WACA,gBAWD,cAJC,oCACA,mCAOD,wBARC,oCACA,mCAWD,4BAZC,oCACA","file":"inputs.css"}
|
||||
|
|
@ -13,14 +13,6 @@ input, textarea, select, button, div[contenteditable=true], div[contenteditable=
|
|||
font-family: var(--font-face);
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-choices .select2-search-field input, .select2-search input, .ui-widget {
|
||||
font-family: var(--font-face) !important;
|
||||
}
|
||||
|
||||
.select2-container.select2-drop-above .select2-choice {
|
||||
background-image: unset !important;
|
||||
}
|
||||
|
||||
$opacity-disabled: .7;
|
||||
|
||||
/* Simple selector to allow easy overriding */
|
||||
|
|
@ -61,7 +53,6 @@ input:not([type="range"]) {
|
|||
}
|
||||
|
||||
/* Default global values */
|
||||
div.select2-drop .select2-search input, // TODO: REMOVE WHEN DROPPING SELECT2
|
||||
input[type='submit'],
|
||||
input[type='button'],
|
||||
input[type='reset'],
|
||||
|
|
@ -241,7 +232,6 @@ input:not(
|
|||
[type='button'],
|
||||
[type='reset'],
|
||||
.multiselect__input,
|
||||
.select2-input,
|
||||
.action-input__input,
|
||||
[class^="vs__"]
|
||||
),
|
||||
|
|
@ -269,11 +259,6 @@ textarea {
|
|||
}
|
||||
}
|
||||
|
||||
.multiselect__input, .select2-input {
|
||||
background-color: var(--color-main-background);
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
textarea, div[contenteditable=true] {
|
||||
padding: 12px;
|
||||
height: auto;
|
||||
|
|
@ -548,185 +533,6 @@ input[type='radio'] {
|
|||
}
|
||||
}
|
||||
|
||||
/* Select2 overriding. Merged to core with vendor stylesheet */
|
||||
div.select2-drop {
|
||||
margin-top: -2px;
|
||||
background-color: var(--color-main-background);
|
||||
&.select2-drop-active {
|
||||
border-color: var(--color-border-dark);
|
||||
}
|
||||
.avatar {
|
||||
display: inline-block;
|
||||
margin-inline-end: 8px;
|
||||
vertical-align: middle;
|
||||
img {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.select2-search input {
|
||||
min-height: auto;
|
||||
background: var(--icon-search-dark) no-repeat !important;
|
||||
background-origin: content-box !important;
|
||||
}
|
||||
.select2-results {
|
||||
max-height: 250px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.select2-result-label {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
span {
|
||||
cursor: pointer;
|
||||
em {
|
||||
cursor: inherit;
|
||||
background: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
.select2-result,
|
||||
.select2-no-results,
|
||||
.select2-searching {
|
||||
position: relative;
|
||||
display: list-item;
|
||||
padding: 12px;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
color: var(--color-text-maxcontrast);
|
||||
}
|
||||
.select2-result {
|
||||
&.select2-selected {
|
||||
background-color: var(--color-background-dark);
|
||||
}
|
||||
}
|
||||
.select2-highlighted {
|
||||
background-color: var(--color-background-dark);
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body[dir='ltr'] div.select2-drop .select2-search input {
|
||||
background-position: right center !important;
|
||||
}
|
||||
|
||||
body[dir='rtl'] div.select2-drop .select2-search input {
|
||||
background-position: left center !important;
|
||||
}
|
||||
|
||||
.select2-chosen,
|
||||
#select2-drop {
|
||||
.avatar,
|
||||
.avatar img {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
div.select2-container-multi {
|
||||
.select2-choices,
|
||||
&.select2-container-active .select2-choices {
|
||||
box-shadow: none;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
background: var(--color-main-background);
|
||||
color: var(--color-text-maxcontrast) !important;
|
||||
box-sizing: content-box;
|
||||
border-radius: var(--border-radius-large);
|
||||
border: 2px solid var(--color-border-dark);
|
||||
margin: 0;
|
||||
padding: 6px;
|
||||
min-height: 44px;
|
||||
&:focus-within {
|
||||
border-color: var(--color-primary-element)
|
||||
}
|
||||
.select2-search-choice {
|
||||
line-height: 20px;
|
||||
padding-inline-start: 5px;
|
||||
&.select2-search-choice-focus,
|
||||
&:hover,
|
||||
&:active,
|
||||
& {
|
||||
background-image: none;
|
||||
background-color: var(--color-main-background);
|
||||
color: var(--color-text-maxcontrast);
|
||||
border: 1px solid var(--color-border-dark);
|
||||
}
|
||||
.select2-search-choice-close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.select2-search-field input {
|
||||
line-height: 20px;
|
||||
min-height: 28px;
|
||||
max-height: 28px;
|
||||
color: var(--color-main-text);
|
||||
&.select2-active {
|
||||
background: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.select2-container {
|
||||
margin: 3px;
|
||||
margin-inline-start: 0;
|
||||
&.select2-container-multi .select2-choices {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
li {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
a.select2-choice {
|
||||
box-shadow: none;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
background: var(--color-main-background);
|
||||
color: var(--color-text-maxcontrast) !important;
|
||||
box-sizing: content-box;
|
||||
border-radius: var(--border-radius-large);
|
||||
border: 2px solid var(--color-border-dark);
|
||||
margin: 0;
|
||||
padding: 6px 12px;
|
||||
min-height: 44px;
|
||||
&:focus-within {
|
||||
border-color: var(--color-primary-element)
|
||||
}
|
||||
.select2-search-choice {
|
||||
line-height: 20px;
|
||||
padding-inline-start: 5px;
|
||||
background-image: none;
|
||||
background-color: var(--color-background-dark);
|
||||
border-color: var(--color-background-dark);
|
||||
.select2-search-choice-close {
|
||||
display: none;
|
||||
}
|
||||
&.select2-search-choice-focus,
|
||||
&:hover {
|
||||
background-color: var(--color-border);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
}
|
||||
.select2-arrow {
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
b {
|
||||
background: var(--icon-triangle-s-dark) no-repeat center !important;
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
&:hover .select2-arrow b,
|
||||
&:focus .select2-arrow b,
|
||||
&:active .select2-arrow b {
|
||||
opacity: .7;
|
||||
}
|
||||
.select2-search-field input {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Vue v-select */
|
||||
.v-select {
|
||||
margin: 3px;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["styles.scss","variables.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA,GCEA;AAAA;AAAA;AAAA,GDOA,MACC,mCACA,uCAGD,yQACC,SACA,UACA,SACA,oBACA,eACA,oBACA,wBACA,eACA,uCAGD,6CACC,aAID,0CACC,wDACA,aAGD,UACC,YAEA,8BAGD,6DACC,cAGD,MACC,yBACA,iBACA,mBAGD,cACC,iBACA,mBAGD,YACC,sBAGD,EACC,SACA,6BACA,qBACA,eACA,IACC,eAIF,WACC,aACA,0BAGD,MACC,eACA,QACC,eAIF,0BACC,eAGD,GACC,gBAGD,KACC,mBAEA,mCACA,uCACA,6BACA,6BAGD,mBACC,kBAGD,qBACC,kBACA,sBACA,qBACA,2BACA,2DACA,uBAGD,iBACC,qBACA,aACA,oCAGD,eACC,YACA,aAGD,cACC,eACA,MACA,SACA,qBACA,YACA,WACA,aACA,kBACA,gDACA,wCACA,iBACA,eACA,kBACC,cACA,kBACA,UACA,QACA,gBAED,gBACC,wCACA,sDACA,4CACC,6CAOH,oBACC,WACA,YAGD,2BACC,+BAGD,gCACC,+BAGD,0BACC,kCACA,yCACA,+BACA,4BAMD,YACC,8CACA,wCAMD,kBACC,sBAKD,4BAEC,oCACA,kBACA,gBACA,WACA,sDACC,gBAED,sEACC,gBAED,kCACC,mBAED,oHAEC,qBACA,YACA,WACA,mBACA,gcAEC,WAOH,sBACC,WASD,oCACC,kBACA,yBACA,sBACA,qBACA,iBAID,kBAEC,kBACA,qBACA,SAEA,YAGD,8CAGC,WAGD,8BACC,sBACA,oBACA,wBACA,wBAGD,2EACC,WAGD,oGACC,kDACA,UACA,qBAGD,mDACC,6BACA,YACA,WACA,yCACA,4BACA,2BACA,WAOA,qEACC,UAED,qEACC,UAIF,wEACC,aAGD,2CACC,wBAGD,yBACC,kBACA,qBACA,sBAGD,qBACC,cACA,mBACA,iBACA,uBACA,aAKD,4CACC,eACA,YACA,mCACA,6BACA,qDAIA,2BACC,4BAKD,wBACC,sBACA,4BACA,+BACC,+CACA,qBACA,kBAGF,0BACC,qBACA,iBAIF,YACC,YACA,sCACA,oBACC,sBAIF,eACC,gDAUD,mBACC,kBACA,cACA,2BACC,kBACA,cAIF,UACC,gBAGD,8CACC,UAIA,WACC,WACA,YAGD,8CAEC,UAGD,oGAGC,WAIF,mBACC,WACA,kBACA,QAEA,kDACC,UAKD,kDACC,UAIF,eACC,WAEA,0CACC,UAKD,uGACC,8CAIF,KACC,mFAGD,OACC,gBACA,YACA,eACA,qBACA,UACC,qBAIF,2FACC,gBACA,uBAGD,2BACC,yDAGD,2BACC,6DAID,yBACC,gBACA,gBACA,WACA,mCACA,YACA,wBAEA,sKAGC,+BACA,mBAED,2CACC,YACA,eACA,YACA,8CACA,6BAEA,gEACC,cACA,mBAED,oDACC,WAEA,4JAEC,kCACA,4BAGF,oEACC,UAID,oDACC,mBACA,oCACA,WACA,WACA,YAED,0DACC,yBAGA,+FACC,gDAGD,wOAGC,8CACA,wCACA,iBAGD,yNAEC,oCACA,WAOH,4FACC,iDAED,4FACC,gDAKD,4FACC,gDAED,4FACC,iDAIF,wCACC,gCACA,wCAKD,yBACC,2BACA,sBACA,mCACA,wBAEA,4CACC,uBAGD,sKAGC,+BACA,mBAED,2CACC,YACA,eACA,YACA,8CACA,6BAEA,gEACC,cACA,mBAIF,qFACC,yBAGA,iDACC,mBACA,oCACA,WACA,yDACC,UACA,WACA,iBAGF,uDACC,yBAGA,0TAIC,8CACA,wCACA,iBAGD,4FACC,oCAGD,qEACC,gDASH,oGACC,aACA,iBACA,8BACA,0GACC,cACA,SACA,YACA,YACA,WACA,aACA,mBACA,uBACA,8GACC,kBACA,kBACA,mBACA,6BACA,cACA,iBACA,WACA,YACA,YACA,eAOJ,WACC,0BAGD,aACC,WACA,sBACA,oBAKD,YACC,kCAMA,qBACC,WACA,aAED,wBACC,cACA,gDACA,WACA,aAED,2BACC,WACA,YACA,6BACC,WAGF,wBACC,wCACA,kBACA,mBACA,gBACA,uBACA,0CACA,kCACA,6DACC,0CAGF,sBACC,UACA,WAKF,YACC,oBACA,YAGD,SACC,oBACA,kDACA,4BACA,iCACA,YACA,0BACA,cACA,QACA,uBACA,mBACC,QACA,kBACA,qBACC,WAIA,wFACC,cAIF,gCACC,SACA,sBACA,mCACC,iBACA,gBACA,kBACA,uBACA,+DACC,+EAGF,+CACC,aAIH,gBACC,aACA,uBACC,QAGF,yBAEC,kBACA,aACA,WACA,uBACA,mBACA,gBACA,cAEA,gBAEA,8FAGC,oBAGF,yBACC,UACA,WAGD,oBACC,iBACA,uBAEA,2BACC,uBAGF,+DACC,UAEA,0JAEC,WAOH,QACC,UACA,yCACA,sCACA,qCACA,oCACA,iCACA,oBACC,UAOD,+CACC,SACA,kBAED,mDACC,gBAKF,cACC,mBAMD,mBACC,aACA,QACA,SACA","file":"styles.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["styles.scss","variables.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA,GCEA;AAAA;AAAA;AAAA,GDOA,MACC,mCACA,uCAGD,yQACC,SACA,UACA,SACA,oBACA,eACA,oBACA,wBACA,eACA,uCAGD,6CACC,aAID,0CACC,wDACA,aAGD,UACC,YAEA,8BAGD,6DACC,cAGD,MACC,yBACA,iBACA,mBAGD,cACC,iBACA,mBAGD,YACC,sBAGD,EACC,SACA,6BACA,qBACA,eACA,IACC,eAIF,WACC,aACA,0BAGD,MACC,eACA,QACC,eAIF,0BACC,eAGD,GACC,gBAGD,KACC,mBAEA,mCACA,uCACA,6BACA,6BAGD,mBACC,kBAGD,qBACC,kBACA,sBACA,qBACA,2BACA,2DACA,uBAGD,iBACC,qBACA,aACA,oCAGD,eACC,YACA,aAGD,cACC,eACA,MACA,SACA,qBACA,YACA,WACA,aACA,kBACA,gDACA,wCACA,iBACA,eACA,kBACC,cACA,kBACA,UACA,QACA,gBAED,gBACC,wCACA,sDACA,4CACC,6CAOH,oBACC,WACA,YAGD,2BACC,+BAGD,gCACC,+BAGD,0BACC,kCACA,yCACA,+BACA,4BAMD,YACC,8CACA,wCAMD,kBACC,sBAKD,4BAEC,oCACA,kBACA,gBACA,WACA,sDACC,gBAED,sEACC,gBAED,kCACC,mBAED,oHAEC,qBACA,YACA,WACA,mBACA,gcAEC,WAOH,sBACC,WASD,oCACC,kBACA,yBACA,sBACA,qBACA,iBAID,kBAEC,kBACA,qBACA,SAEA,YAGD,8CAGC,WAGD,8BACC,sBACA,oBACA,wBACA,wBAGD,2EACC,WAGD,oGACC,kDACA,UACA,qBAGD,mDACC,6BACA,YACA,WACA,yCACA,4BACA,2BACA,WAOA,qEACC,UAED,qEACC,UAIF,wEACC,aAGD,2CACC,wBAGD,yBACC,kBACA,qBACA,sBAGD,qBACC,cACA,mBACA,iBACA,uBACA,aAKD,4CACC,eACA,YACA,mCACA,6BACA,qDAIA,2BACC,4BAKD,wBACC,sBACA,4BACA,+BACC,+CACA,qBACA,kBAGF,0BACC,qBACA,iBAIF,YACC,YACA,sCACA,oBACC,sBAIF,eACC,gDAUD,mBACC,kBACA,cACA,2BACC,kBACA,cAIF,UACC,gBAGD,8CACC,UAIA,WACC,WACA,YAGD,8CAEC,UAGD,oGAGC,WAIF,mBACC,WACA,kBACA,QAEA,kDACC,UAKD,kDACC,UAIF,eACC,WAEA,0CACC,UAKD,uGACC,8CAIF,KACC,mFAGD,OACC,gBACA,YACA,eACA,qBACA,UACC,qBAOD,qBACC,WACA,aAED,wBACC,cACA,gDACA,WACA,aAED,2BACC,WACA,YACA,6BACC,WAGF,wBACC,wCACA,kBACA,mBACA,gBACA,uBACA,0CACA,kCACA,6DACC,0CAGF,sBACC,UACA,WAKF,YACC,oBACA,YAGD,SACC,oBACA,kDACA,4BACA,iCACA,YACA,0BACA,cACA,QACA,uBACA,mBACC,QACA,kBACA,qBACC,WAIA,wFACC,cAIF,gCACC,SACA,sBACA,mCACC,iBACA,gBACA,kBACA,uBACA,+DACC,+EAGF,+CACC,aAIH,gBACC,aACA,uBACC,QAGF,yBAEC,kBACA,aACA,WACA,uBACA,mBACA,gBACA,cAEA,gBAEA,8FAGC,oBAGF,yBACC,UACA,WAGD,oBACC,iBACA,uBAEA,2BACC,uBAGF,+DACC,UAEA,0JAEC,WAOH,QACC,UACA,yCACA,sCACA,qCACA,oCACA,iCACA,oBACC,UAOD,+CACC,SACA,kBAED,mDACC,gBAKF,cACC,mBAMD,mBACC,aACA,QACA,SACA","file":"styles.css"}
|
||||
|
|
@ -445,232 +445,6 @@ code {
|
|||
}
|
||||
}
|
||||
|
||||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ui-icon-circle-triangle-e {
|
||||
background-image: url('../img/actions/play-next.svg?v=1');
|
||||
}
|
||||
|
||||
.ui-icon-circle-triangle-w {
|
||||
background-image: url('../img/actions/play-previous.svg?v=1');
|
||||
}
|
||||
|
||||
/* ---- jQuery UI datepicker ---- */
|
||||
.ui-widget.ui-datepicker {
|
||||
margin-top: 10px;
|
||||
padding: 4px 8px;
|
||||
width: auto;
|
||||
border-radius: var(--border-radius);
|
||||
border: none;
|
||||
z-index: 1600 !important; // above sidebar
|
||||
|
||||
.ui-state-default,
|
||||
.ui-widget-content .ui-state-default,
|
||||
.ui-widget-header .ui-state-default {
|
||||
border: 1px solid transparent;
|
||||
background: inherit;
|
||||
}
|
||||
.ui-widget-header {
|
||||
padding: 7px;
|
||||
font-size: 13px;
|
||||
border: none;
|
||||
background-color: var(--color-main-background);
|
||||
color: var(--color-main-text);
|
||||
|
||||
.ui-datepicker-title {
|
||||
line-height: 1;
|
||||
font-weight: normal;
|
||||
}
|
||||
.ui-icon {
|
||||
opacity: .5;
|
||||
|
||||
&.ui-icon-circle-triangle-e,
|
||||
&.ui-icon-circle-triangle-w {
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
.ui-state-hover .ui-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.ui-datepicker-calendar {
|
||||
th {
|
||||
font-weight: normal;
|
||||
color: var(--color-text-maxcontrast);
|
||||
opacity: .8;
|
||||
width: 26px;
|
||||
padding: 2px;
|
||||
}
|
||||
tr:hover {
|
||||
background-color: inherit;
|
||||
}
|
||||
td {
|
||||
&.ui-datepicker-today a:not(.ui-state-hover) {
|
||||
background-color: var(--color-background-darker);
|
||||
}
|
||||
|
||||
&.ui-datepicker-current-day a.ui-state-active,
|
||||
.ui-state-hover,
|
||||
.ui-state-focus {
|
||||
background-color: var(--color-primary-element);
|
||||
color: var(--color-primary-element-text);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.ui-datepicker-week-end:not(.ui-state-disabled) :not(.ui-state-hover),
|
||||
.ui-priority-secondary:not(.ui-state-hover) {
|
||||
color: var(--color-text-maxcontrast);
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body[dir='ltr'] .ui-widget.ui-datepicker .ui-widget-header .ui-icon {
|
||||
&.ui-icon-circle-triangle-e {
|
||||
background: url("../img/actions/arrow-right.svg");
|
||||
}
|
||||
&.ui-icon-circle-triangle-w {
|
||||
background: url("../img/actions/arrow-left.svg");
|
||||
}
|
||||
}
|
||||
|
||||
body[dir='rtl'] .ui-widget.ui-datepicker .ui-widget-header .ui-icon {
|
||||
&.ui-icon-circle-triangle-e {
|
||||
background: url("../img/actions/arrow-left.svg");
|
||||
}
|
||||
&.ui-icon-circle-triangle-w {
|
||||
background: url("../img/actions/arrow-right.svg");
|
||||
}
|
||||
}
|
||||
|
||||
.ui-datepicker-prev, .ui-datepicker-next {
|
||||
border: var(--color-border-dark);
|
||||
background: var(--color-main-background);
|
||||
}
|
||||
|
||||
|
||||
/* ---- jQuery UI timepicker ---- */
|
||||
.ui-widget.ui-timepicker {
|
||||
margin-top: 10px !important;
|
||||
width: auto !important;
|
||||
border-radius: var(--border-radius);
|
||||
z-index: 1600 !important;
|
||||
|
||||
.ui-widget-content {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.ui-state-default,
|
||||
.ui-widget-content .ui-state-default,
|
||||
.ui-widget-header .ui-state-default {
|
||||
border: 1px solid transparent;
|
||||
background: inherit;
|
||||
}
|
||||
.ui-widget-header {
|
||||
padding: 7px;
|
||||
font-size: 13px;
|
||||
border: none;
|
||||
background-color: var(--color-main-background);
|
||||
color: var(--color-main-text);
|
||||
|
||||
.ui-timepicker-title {
|
||||
line-height: 1;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
/* AM/PM fix */
|
||||
table.ui-timepicker tr .ui-timepicker-hour-cell:first-child {
|
||||
margin-inline-start: 30px;
|
||||
}
|
||||
.ui-timepicker-table {
|
||||
th {
|
||||
font-weight: normal;
|
||||
color: var(--color-text-maxcontrast);
|
||||
opacity: .8;
|
||||
&.periods {
|
||||
padding: 0;
|
||||
width: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
tr:hover {
|
||||
background-color: inherit;
|
||||
}
|
||||
td {
|
||||
&.ui-timepicker-hour-cell a.ui-state-active,
|
||||
&.ui-timepicker-minute-cell a.ui-state-active,
|
||||
.ui-state-hover,
|
||||
.ui-state-focus {
|
||||
background-color: var(--color-primary-element);
|
||||
color: var(--color-primary-element-text);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.ui-timepicker-minutes:not(.ui-state-hover) {
|
||||
color: var(--color-text-maxcontrast);
|
||||
}
|
||||
|
||||
&.ui-timepicker-hours {
|
||||
border-inline-end: 1px solid var(--color-border);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- jQuery UI datepicker & timepicker global rules ---- */
|
||||
.ui-widget.ui-datepicker .ui-datepicker-calendar,
|
||||
.ui-widget.ui-timepicker table.ui-timepicker {
|
||||
tr {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
td {
|
||||
flex: 1 1 auto;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> * {
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
color: var(--color-main-text);
|
||||
display: block;
|
||||
line-height: 18px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
padding: 3px;
|
||||
font-size: .9em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- DIALOGS ---- */
|
||||
.ui-dialog {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
span.ui-icon {
|
||||
float: left;
|
||||
margin-block: 3px 30px;
|
||||
margin-inline: 0 7px;
|
||||
}
|
||||
|
||||
/* ---- TOOLTIPS ---- */
|
||||
|
||||
.extra-data {
|
||||
padding-inline-end: 5px !important;
|
||||
}
|
||||
|
||||
/* ---- TAGS ---- */
|
||||
|
||||
#tagsdialog {
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
[
|
||||
"mimetypelist.js",
|
||||
"select2-toggleselect.js"
|
||||
]
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/* global Select2 */
|
||||
|
||||
/**
|
||||
* Select2 extension for toggling values in a multi-select dropdown
|
||||
*
|
||||
* @param Select2
|
||||
*/
|
||||
(function(Select2) {
|
||||
const Select2FindHighlightableChoices = Select2.class.multi.prototype.findHighlightableChoices
|
||||
Select2.class.multi.prototype.findHighlightableChoices = function() {
|
||||
if (this.opts.toggleSelect) {
|
||||
return this.results.find('.select2-result-selectable:not(.select2-disabled)')
|
||||
}
|
||||
return Select2FindHighlightableChoices.apply(this, arguments)
|
||||
}
|
||||
|
||||
const Select2TriggerSelect = Select2.class.multi.prototype.triggerSelect
|
||||
Select2.class.multi.prototype.triggerSelect = function(data) {
|
||||
if (this.opts.toggleSelect && this.val().indexOf(this.id(data)) !== -1) {
|
||||
const self = this
|
||||
const val = this.id(data)
|
||||
|
||||
const selectionEls = this.container.find('.select2-search-choice').filter(function() {
|
||||
return (self.id($(this).data('select2-data')) === val)
|
||||
})
|
||||
|
||||
if (this.unselect(selectionEls)) {
|
||||
// also unselect in dropdown
|
||||
this.results.find('.select2-result.select2-selected').each(function() {
|
||||
const $this = $(this)
|
||||
if (self.id($this.data('select2-data')) === val) {
|
||||
$this.removeClass('select2-selected')
|
||||
}
|
||||
})
|
||||
this.clearSearch()
|
||||
}
|
||||
|
||||
return false
|
||||
} else {
|
||||
return Select2TriggerSelect.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
})(Select2)
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2014 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
|
||||
let dynamicSlideToggleEnabled = false
|
||||
|
||||
const Apps = {
|
||||
enableDynamicSlideToggle() {
|
||||
dynamicSlideToggleEnabled = true
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the #app-sidebar and add .with-app-sidebar to subsequent siblings
|
||||
*
|
||||
* @param {object} [$el] sidebar element to show, defaults to $('#app-sidebar')
|
||||
*/
|
||||
Apps.showAppSidebar = function($el) {
|
||||
const $appSidebar = $el || $('#app-sidebar')
|
||||
$appSidebar.removeClass('disappear').show()
|
||||
$('#app-content').trigger(new $.Event('appresized'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the #app-sidebar and removes .with-app-sidebar from subsequent
|
||||
* siblings
|
||||
*
|
||||
* @param {object} [$el] sidebar element to hide, defaults to $('#app-sidebar')
|
||||
*/
|
||||
Apps.hideAppSidebar = function($el) {
|
||||
const $appSidebar = $el || $('#app-sidebar')
|
||||
$appSidebar.hide().addClass('disappear')
|
||||
$('#app-content').trigger(new $.Event('appresized'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a way to slide down a target area through a button and slide it
|
||||
* up if the user clicks somewhere else. Used for the news app settings and
|
||||
* add new field.
|
||||
*
|
||||
* Usage:
|
||||
* <button data-apps-slide-toggle=".slide-area">slide</button>
|
||||
* <div class=".slide-area" class="hidden">I'm sliding up</div>
|
||||
*/
|
||||
export function registerAppsSlideToggle() {
|
||||
let buttons = $('[data-apps-slide-toggle]')
|
||||
|
||||
if (buttons.length === 0) {
|
||||
$('#app-navigation').addClass('without-app-settings')
|
||||
}
|
||||
|
||||
$(document).click(function(event) {
|
||||
if (dynamicSlideToggleEnabled) {
|
||||
buttons = $('[data-apps-slide-toggle]')
|
||||
}
|
||||
|
||||
buttons.each(function(index, button) {
|
||||
const areaSelector = $(button).data('apps-slide-toggle')
|
||||
const area = $(areaSelector)
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function hideArea() {
|
||||
area.slideUp(OC.menuSpeed * 4, function() {
|
||||
area.trigger(new $.Event('hide'))
|
||||
})
|
||||
area.removeClass('opened')
|
||||
$(button).removeClass('opened')
|
||||
$(button).attr('aria-expanded', 'false')
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function showArea() {
|
||||
area.slideDown(OC.menuSpeed * 4, function() {
|
||||
area.trigger(new $.Event('show'))
|
||||
})
|
||||
area.addClass('opened')
|
||||
$(button).addClass('opened')
|
||||
$(button).attr('aria-expanded', 'true')
|
||||
const input = $(areaSelector + ' [autofocus]')
|
||||
if (input.length === 1) {
|
||||
input.focus()
|
||||
}
|
||||
}
|
||||
|
||||
// do nothing if the area is animated
|
||||
if (!area.is(':animated')) {
|
||||
// button toggles the area
|
||||
if ($(button).is($(event.target).closest('[data-apps-slide-toggle]'))) {
|
||||
if (area.is(':visible')) {
|
||||
hideArea()
|
||||
} else {
|
||||
showArea()
|
||||
}
|
||||
|
||||
// all other areas that have not been clicked but are open
|
||||
// should be slid up
|
||||
} else {
|
||||
const closest = $(event.target).closest(areaSelector)
|
||||
if (area.is(':visible') && closest[0] !== area[0]) {
|
||||
hideArea()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default Apps
|
||||
|
|
@ -1,355 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { dav } from 'davclient.js'
|
||||
import _ from 'underscore'
|
||||
import logger from '../logger.js'
|
||||
|
||||
const methodMap = {
|
||||
create: 'POST',
|
||||
update: 'PROPPATCH',
|
||||
patch: 'PROPPATCH',
|
||||
delete: 'DELETE',
|
||||
read: 'PROPFIND',
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error when a URL is needed, and none is supplied.
|
||||
*/
|
||||
function urlError() {
|
||||
throw new Error('A "url" property or function must be specified')
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a single propfind result to JSON
|
||||
*
|
||||
* @param {object} result
|
||||
* @param {object} davProperties properties mapping
|
||||
*/
|
||||
function parsePropFindResult(result, davProperties) {
|
||||
if (_.isArray(result)) {
|
||||
return _.map(result, function(subResult) {
|
||||
return parsePropFindResult(subResult, davProperties)
|
||||
})
|
||||
}
|
||||
const props = {
|
||||
href: result.href,
|
||||
}
|
||||
|
||||
_.each(result.propStat, function(propStat) {
|
||||
if (propStat.status !== 'HTTP/1.1 200 OK') {
|
||||
return
|
||||
}
|
||||
|
||||
for (const key in propStat.properties) {
|
||||
let propKey = key
|
||||
if (key in davProperties) {
|
||||
propKey = davProperties[key]
|
||||
}
|
||||
props[propKey] = propStat.properties[key]
|
||||
}
|
||||
})
|
||||
|
||||
if (!props.id) {
|
||||
// parse id from href
|
||||
props.id = parseIdFromLocation(props.href)
|
||||
}
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ID from location
|
||||
*
|
||||
* @param {string} url url
|
||||
* @return {string} id
|
||||
*/
|
||||
function parseIdFromLocation(url) {
|
||||
const queryPos = url.indexOf('?')
|
||||
if (queryPos > 0) {
|
||||
url = url.substr(0, queryPos)
|
||||
}
|
||||
|
||||
const parts = url.split('/')
|
||||
let result
|
||||
do {
|
||||
result = parts[parts.length - 1]
|
||||
parts.pop()
|
||||
// note: first result can be empty when there is a trailing slash,
|
||||
// so we take the part before that
|
||||
} while (!result && parts.length > 0)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} status
|
||||
*/
|
||||
function isSuccessStatus(status) {
|
||||
return status >= 200 && status <= 299
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param attrs
|
||||
* @param davProperties
|
||||
*/
|
||||
function convertModelAttributesToDavProperties(attrs, davProperties) {
|
||||
const props = {}
|
||||
let key
|
||||
for (key in attrs) {
|
||||
let changedProp = davProperties[key]
|
||||
let value = attrs[key]
|
||||
if (!changedProp) {
|
||||
logger.warn('No matching DAV property for property "' + key)
|
||||
changedProp = key
|
||||
}
|
||||
if (_.isBoolean(value) || _.isNumber(value)) {
|
||||
// convert to string
|
||||
value = '' + value
|
||||
}
|
||||
props[changedProp] = value
|
||||
}
|
||||
return props
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client
|
||||
* @param options
|
||||
* @param model
|
||||
* @param headers
|
||||
*/
|
||||
function callPropFind(client, options, model, headers) {
|
||||
return client.propFind(
|
||||
options.url,
|
||||
_.values(options.davProperties) || [],
|
||||
options.depth,
|
||||
headers,
|
||||
).then(function(response) {
|
||||
if (isSuccessStatus(response.status)) {
|
||||
if (_.isFunction(options.success)) {
|
||||
const propsMapping = _.invert(options.davProperties)
|
||||
const results = parsePropFindResult(response.body, propsMapping)
|
||||
if (options.depth > 0) {
|
||||
// discard root entry
|
||||
results.shift()
|
||||
}
|
||||
|
||||
options.success(results)
|
||||
}
|
||||
} else if (_.isFunction(options.error)) {
|
||||
options.error(response)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client
|
||||
* @param options
|
||||
* @param model
|
||||
* @param headers
|
||||
*/
|
||||
function callPropPatch(client, options, model, headers) {
|
||||
return client.propPatch(
|
||||
options.url,
|
||||
convertModelAttributesToDavProperties(model.changed, options.davProperties),
|
||||
headers,
|
||||
).then(function(result) {
|
||||
if (isSuccessStatus(result.status)) {
|
||||
if (_.isFunction(options.success)) {
|
||||
// pass the object's own values because the server
|
||||
// does not return the updated model
|
||||
options.success(model.toJSON())
|
||||
}
|
||||
} else if (_.isFunction(options.error)) {
|
||||
options.error(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client
|
||||
* @param options
|
||||
* @param model
|
||||
* @param headers
|
||||
*/
|
||||
function callMkCol(client, options, model, headers) {
|
||||
// call MKCOL without data, followed by PROPPATCH
|
||||
return client.request(
|
||||
options.type,
|
||||
options.url,
|
||||
headers,
|
||||
null,
|
||||
).then(function(result) {
|
||||
if (!isSuccessStatus(result.status)) {
|
||||
if (_.isFunction(options.error)) {
|
||||
options.error(result)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
callPropPatch(client, options, model, headers)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client
|
||||
* @param options
|
||||
* @param model
|
||||
* @param headers
|
||||
*/
|
||||
function callMethod(client, options, model, headers) {
|
||||
headers['Content-Type'] = 'application/json'
|
||||
return client.request(
|
||||
options.type,
|
||||
options.url,
|
||||
headers,
|
||||
options.data,
|
||||
).then(function(result) {
|
||||
if (!isSuccessStatus(result.status)) {
|
||||
if (_.isFunction(options.error)) {
|
||||
options.error(result)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (_.isFunction(options.success)) {
|
||||
if (options.type === 'PUT' || options.type === 'POST' || options.type === 'MKCOL') {
|
||||
// pass the object's own values because the server
|
||||
// does not return anything
|
||||
const responseJson = result.body || model.toJSON()
|
||||
const locationHeader = result.xhr.getResponseHeader('Content-Location')
|
||||
if (options.type === 'POST' && locationHeader) {
|
||||
responseJson.id = parseIdFromLocation(locationHeader)
|
||||
}
|
||||
options.success(responseJson)
|
||||
return
|
||||
}
|
||||
// if multi-status, parse
|
||||
if (result.status === 207) {
|
||||
const propsMapping = _.invert(options.davProperties)
|
||||
options.success(parsePropFindResult(result.body, propsMapping))
|
||||
} else {
|
||||
options.success(result.body)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param options
|
||||
* @param model
|
||||
*/
|
||||
export function davCall(options, model) {
|
||||
const client = new dav.Client({
|
||||
baseUrl: options.url,
|
||||
xmlNamespaces: _.extend({
|
||||
'DAV:': 'd',
|
||||
'http://owncloud.org/ns': 'oc',
|
||||
}, options.xmlNamespaces || {}),
|
||||
})
|
||||
client.resolveUrl = function() {
|
||||
return options.url
|
||||
}
|
||||
const headers = _.extend({
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
requesttoken: OC.requestToken,
|
||||
}, options.headers)
|
||||
if (options.type === 'PROPFIND') {
|
||||
return callPropFind(client, options, model, headers)
|
||||
} else if (options.type === 'PROPPATCH') {
|
||||
return callPropPatch(client, options, model, headers)
|
||||
} else if (options.type === 'MKCOL') {
|
||||
return callMkCol(client, options, model, headers)
|
||||
} else {
|
||||
return callMethod(client, options, model, headers)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DAV transport
|
||||
*
|
||||
* @param Backbone
|
||||
*/
|
||||
export function davSync(Backbone) {
|
||||
return (method, model, options) => {
|
||||
const params = { type: methodMap[method] || method }
|
||||
const isCollection = (model instanceof Backbone.Collection)
|
||||
|
||||
if (method === 'update') {
|
||||
// if a model has an inner collection, it must define an
|
||||
// attribute "hasInnerCollection" that evaluates to true
|
||||
if (model.hasInnerCollection) {
|
||||
// if the model itself is a Webdav collection, use MKCOL
|
||||
params.type = 'MKCOL'
|
||||
} else if (model.usePUT || (model.collection && model.collection.usePUT)) {
|
||||
// use PUT instead of PROPPATCH
|
||||
params.type = 'PUT'
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that we have a URL.
|
||||
if (!options.url) {
|
||||
params.url = _.result(model, 'url') || urlError()
|
||||
}
|
||||
|
||||
// Ensure that we have the appropriate request data.
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
|
||||
params.data = JSON.stringify(options.attrs || model.toJSON(options))
|
||||
}
|
||||
|
||||
// Don't process data on a non-GET request.
|
||||
if (params.type !== 'PROPFIND') {
|
||||
params.processData = false
|
||||
}
|
||||
|
||||
if (params.type === 'PROPFIND' || params.type === 'PROPPATCH') {
|
||||
let davProperties = model.davProperties
|
||||
if (!davProperties && model.model) {
|
||||
// use dav properties from model in case of collection
|
||||
davProperties = model.model.prototype.davProperties
|
||||
}
|
||||
if (davProperties) {
|
||||
if (_.isFunction(davProperties)) {
|
||||
params.davProperties = davProperties.call(model)
|
||||
} else {
|
||||
params.davProperties = davProperties
|
||||
}
|
||||
}
|
||||
|
||||
params.davProperties = _.extend(params.davProperties || {}, options.davProperties)
|
||||
|
||||
if (_.isUndefined(options.depth)) {
|
||||
if (isCollection) {
|
||||
options.depth = 1
|
||||
} else {
|
||||
options.depth = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass along `textStatus` and `errorThrown` from jQuery.
|
||||
const error = options.error
|
||||
options.error = function(xhr, textStatus, errorThrown) {
|
||||
options.textStatus = textStatus
|
||||
options.errorThrown = errorThrown
|
||||
if (error) {
|
||||
error.call(options.context, xhr, textStatus, errorThrown)
|
||||
}
|
||||
}
|
||||
|
||||
// Make the request, allowing the user to override any Ajax options.
|
||||
const xhr = options.xhr = Backbone.davCall(_.extend(params, options), model)
|
||||
model.trigger('request', model, xhr, options)
|
||||
return xhr
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import VendorBackbone from 'backbone'
|
||||
import { davCall, davSync } from './backbone-webdav.js'
|
||||
|
||||
const Backbone = VendorBackbone.noConflict()
|
||||
|
||||
// Patch Backbone for DAV
|
||||
Object.assign(Backbone, {
|
||||
davCall,
|
||||
davSync: davSync(Backbone),
|
||||
})
|
||||
|
||||
export default Backbone
|
||||
|
|
@ -9,14 +9,12 @@ import IconCopy from '@mdi/svg/svg/folder-multiple-outline.svg?raw'
|
|||
import { DialogBuilder, FilePickerType, getFilePickerBuilder } from '@nextcloud/dialogs'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { spawnDialog } from '@nextcloud/vue/functions/dialog'
|
||||
import $ from 'jquery'
|
||||
import { basename } from 'path'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import logger from '../logger.js'
|
||||
import OC from './index.js'
|
||||
|
||||
/**
|
||||
* this class to ease the usage of jquery dialogs
|
||||
* this class to ease the usage of dialogs
|
||||
*/
|
||||
const Dialogs = {
|
||||
// dialog button types
|
||||
|
|
@ -410,396 +408,6 @@ const Dialogs = {
|
|||
}
|
||||
return buttonList
|
||||
},
|
||||
|
||||
_fileexistsshown: false,
|
||||
/**
|
||||
* Displays file exists dialog
|
||||
*
|
||||
* @param {object} data upload object
|
||||
* @param {object} original file with name, size and mtime
|
||||
* @param {object} replacement file with name, size and mtime
|
||||
* @param {object} controller with onCancel, onSkip, onReplace and onRename methods
|
||||
* @return {Promise} jquery promise that resolves after the dialog template was loaded
|
||||
*
|
||||
* @deprecated 29.0.0 Use openConflictPicker from the @nextcloud/upload package instead
|
||||
*/
|
||||
fileexists: function(data, original, replacement, controller) {
|
||||
const self = this
|
||||
const dialogDeferred = new $.Deferred()
|
||||
|
||||
const getCroppedPreview = function(file) {
|
||||
const deferred = new $.Deferred()
|
||||
// Only process image files.
|
||||
const type = file.type && file.type.split('/').shift()
|
||||
if (window.FileReader && type === 'image') {
|
||||
const reader = new FileReader()
|
||||
reader.onload = function(e) {
|
||||
const blob = new Blob([e.target.result])
|
||||
window.URL = window.URL || window.webkitURL
|
||||
const originalUrl = window.URL.createObjectURL(blob)
|
||||
const image = new Image()
|
||||
image.src = originalUrl
|
||||
image.onload = function() {
|
||||
const url = crop(image)
|
||||
deferred.resolve(url)
|
||||
}
|
||||
}
|
||||
reader.readAsArrayBuffer(file)
|
||||
} else {
|
||||
deferred.reject()
|
||||
}
|
||||
return deferred
|
||||
}
|
||||
|
||||
/**
|
||||
* @param img
|
||||
*/
|
||||
function crop(img) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const targetSize = 96
|
||||
const width = img.width
|
||||
const height = img.height
|
||||
let x
|
||||
let y
|
||||
|
||||
// Calculate the width and height, constraining the proportions
|
||||
if (width > height) {
|
||||
y = 0
|
||||
x = (width - height) / 2
|
||||
} else {
|
||||
y = (height - width) / 2
|
||||
x = 0
|
||||
}
|
||||
const size = Math.min(width, height)
|
||||
|
||||
// Set canvas size to the cropped area
|
||||
canvas.width = size
|
||||
canvas.height = size
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.drawImage(img, x, y, size, size, 0, 0, size, size)
|
||||
|
||||
// Resize the canvas to match the destination (right size uses 96px)
|
||||
resampleHermite(canvas, size, size, targetSize, targetSize)
|
||||
|
||||
return canvas.toDataURL('image/png', 0.7)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast image resize/resample using Hermite filter with JavaScript.
|
||||
*
|
||||
* @author ViliusL
|
||||
*
|
||||
* @param {*} canvas
|
||||
* @param {number} W
|
||||
* @param {number} H
|
||||
* @param {number} W2
|
||||
* @param {number} H2
|
||||
*/
|
||||
function resampleHermite(canvas, W, H, W2, H2) {
|
||||
W2 = Math.round(W2)
|
||||
H2 = Math.round(H2)
|
||||
const img = canvas.getContext('2d').getImageData(0, 0, W, H)
|
||||
const img2 = canvas.getContext('2d').getImageData(0, 0, W2, H2)
|
||||
const data = img.data
|
||||
const data2 = img2.data
|
||||
const ratio_w = W / W2
|
||||
const ratio_h = H / H2
|
||||
const ratio_w_half = Math.ceil(ratio_w / 2)
|
||||
const ratio_h_half = Math.ceil(ratio_h / 2)
|
||||
|
||||
for (let j = 0; j < H2; j++) {
|
||||
for (let i = 0; i < W2; i++) {
|
||||
const x2 = (i + j * W2) * 4
|
||||
let weight = 0
|
||||
let weights = 0
|
||||
let weights_alpha = 0
|
||||
let gx_r = 0
|
||||
let gx_g = 0
|
||||
let gx_b = 0
|
||||
let gx_a = 0
|
||||
const center_y = (j + 0.5) * ratio_h
|
||||
for (let yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++) {
|
||||
const dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half
|
||||
const center_x = (i + 0.5) * ratio_w
|
||||
const w0 = dy * dy // pre-calc part of w
|
||||
for (let xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++) {
|
||||
let dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half
|
||||
const w = Math.sqrt(w0 + dx * dx)
|
||||
if (w >= -1 && w <= 1) {
|
||||
// hermite filter
|
||||
weight = 2 * w * w * w - 3 * w * w + 1
|
||||
if (weight > 0) {
|
||||
dx = 4 * (xx + yy * W)
|
||||
// alpha
|
||||
gx_a += weight * data[dx + 3]
|
||||
weights_alpha += weight
|
||||
// colors
|
||||
if (data[dx + 3] < 255) {
|
||||
weight = weight * data[dx + 3] / 250
|
||||
}
|
||||
gx_r += weight * data[dx]
|
||||
gx_g += weight * data[dx + 1]
|
||||
gx_b += weight * data[dx + 2]
|
||||
weights += weight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data2[x2] = gx_r / weights
|
||||
data2[x2 + 1] = gx_g / weights
|
||||
data2[x2 + 2] = gx_b / weights
|
||||
data2[x2 + 3] = gx_a / weights_alpha
|
||||
}
|
||||
}
|
||||
canvas.getContext('2d').clearRect(0, 0, Math.max(W, W2), Math.max(H, H2))
|
||||
canvas.width = W2
|
||||
canvas.height = H2
|
||||
canvas.getContext('2d').putImageData(img2, 0, 0)
|
||||
}
|
||||
|
||||
const addConflict = function($conflicts, original, replacement) {
|
||||
const $conflict = $conflicts.find('.template').clone().removeClass('template').addClass('conflict')
|
||||
const $originalDiv = $conflict.find('.original')
|
||||
const $replacementDiv = $conflict.find('.replacement')
|
||||
|
||||
$conflict.data('data', data)
|
||||
|
||||
$conflict.find('.filename').text(original.name)
|
||||
$originalDiv.find('.size').text(OC.Util.humanFileSize(original.size))
|
||||
$originalDiv.find('.mtime').text(OC.Util.formatDate(original.mtime))
|
||||
// ie sucks
|
||||
if (replacement.size && replacement.lastModified) {
|
||||
$replacementDiv.find('.size').text(OC.Util.humanFileSize(replacement.size))
|
||||
$replacementDiv.find('.mtime').text(OC.Util.formatDate(replacement.lastModified))
|
||||
}
|
||||
let path = original.directory + '/' + original.name
|
||||
const urlSpec = {
|
||||
file: path,
|
||||
x: 96,
|
||||
y: 96,
|
||||
c: original.etag,
|
||||
forceIcon: 0,
|
||||
}
|
||||
let previewpath = Files.generatePreviewUrl(urlSpec)
|
||||
// Escaping single quotes
|
||||
previewpath = previewpath.replace(/'/g, '%27')
|
||||
$originalDiv.find('.icon').css({ 'background-image': "url('" + previewpath + "')" })
|
||||
getCroppedPreview(replacement).then(function(path) {
|
||||
$replacementDiv.find('.icon').css('background-image', 'url(' + path + ')')
|
||||
}, function() {
|
||||
path = OC.MimeType.getIconUrl(replacement.type)
|
||||
$replacementDiv.find('.icon').css('background-image', 'url(' + path + ')')
|
||||
})
|
||||
// connect checkboxes with labels
|
||||
const checkboxId = $conflicts.find('.conflict').length
|
||||
$originalDiv.find('input:checkbox').attr('id', 'checkbox_original_' + checkboxId)
|
||||
$replacementDiv.find('input:checkbox').attr('id', 'checkbox_replacement_' + checkboxId)
|
||||
|
||||
$conflicts.append($conflict)
|
||||
|
||||
// set more recent mtime bold
|
||||
// ie sucks
|
||||
if (replacement.lastModified > original.mtime) {
|
||||
$replacementDiv.find('.mtime').css('font-weight', 'bold')
|
||||
} else if (replacement.lastModified < original.mtime) {
|
||||
$originalDiv.find('.mtime').css('font-weight', 'bold')
|
||||
} else {
|
||||
// TODO add to same mtime collection?
|
||||
}
|
||||
|
||||
// set bigger size bold
|
||||
if (replacement.size && replacement.size > original.size) {
|
||||
$replacementDiv.find('.size').css('font-weight', 'bold')
|
||||
} else if (replacement.size && replacement.size < original.size) {
|
||||
$originalDiv.find('.size').css('font-weight', 'bold')
|
||||
} else {
|
||||
// TODO add to same size collection?
|
||||
}
|
||||
|
||||
// TODO show skip action for files with same size and mtime in bottom row
|
||||
|
||||
// always keep readonly files
|
||||
|
||||
if (original.status === 'readonly') {
|
||||
$originalDiv
|
||||
.addClass('readonly')
|
||||
.find('input[type="checkbox"]')
|
||||
.prop('checked', true)
|
||||
.prop('disabled', true)
|
||||
$originalDiv.find('.message')
|
||||
.text(t('core', 'read-only'))
|
||||
}
|
||||
}
|
||||
|
||||
const dialogName = 'oc-dialog-fileexists-content'
|
||||
const dialogId = '#' + dialogName
|
||||
if (this._fileexistsshown) {
|
||||
// add conflict
|
||||
|
||||
const $conflicts = $(dialogId + ' .conflicts')
|
||||
addConflict($conflicts, original, replacement)
|
||||
|
||||
const count = $(dialogId + ' .conflict').length
|
||||
const title = n(
|
||||
'core',
|
||||
'{count} file conflict',
|
||||
'{count} file conflicts',
|
||||
count,
|
||||
{ count },
|
||||
)
|
||||
$(dialogId).parent().children('.oc-dialog-title').text(title)
|
||||
|
||||
// recalculate dimensions
|
||||
$(window).trigger('resize')
|
||||
dialogDeferred.resolve()
|
||||
} else {
|
||||
// create dialog
|
||||
this._fileexistsshown = true
|
||||
$.when(this._getFileExistsTemplate()).then(function($tmpl) {
|
||||
const title = t('core', 'One file conflict')
|
||||
const $dlg = $tmpl.octemplate({
|
||||
dialog_name: dialogName,
|
||||
title,
|
||||
type: 'fileexists',
|
||||
|
||||
allnewfiles: t('core', 'New Files'),
|
||||
allexistingfiles: t('core', 'Already existing files'),
|
||||
|
||||
why: t('core', 'Which files do you want to keep?'),
|
||||
what: t('core', 'If you select both versions, the copied file will have a number added to its name.'),
|
||||
})
|
||||
$('body').append($dlg)
|
||||
|
||||
if (original && replacement) {
|
||||
const $conflicts = $dlg.find('.conflicts')
|
||||
addConflict($conflicts, original, replacement)
|
||||
}
|
||||
|
||||
const buttonlist = [{
|
||||
text: t('core', 'Cancel'),
|
||||
classes: 'cancel',
|
||||
click: function() {
|
||||
if (typeof controller.onCancel !== 'undefined') {
|
||||
controller.onCancel(data)
|
||||
}
|
||||
$(dialogId).ocdialog('close')
|
||||
},
|
||||
}, {
|
||||
text: t('core', 'Continue'),
|
||||
classes: 'continue',
|
||||
click: function() {
|
||||
if (typeof controller.onContinue !== 'undefined') {
|
||||
controller.onContinue($(dialogId + ' .conflict'))
|
||||
}
|
||||
$(dialogId).ocdialog('close')
|
||||
},
|
||||
}]
|
||||
|
||||
$(dialogId).ocdialog({
|
||||
width: 500,
|
||||
closeOnEscape: true,
|
||||
modal: true,
|
||||
buttons: buttonlist,
|
||||
closeButton: null,
|
||||
close: function() {
|
||||
self._fileexistsshown = false
|
||||
try {
|
||||
$(this).ocdialog('destroy').remove()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
$(dialogId).css('height', 'auto')
|
||||
|
||||
const $primaryButton = $dlg.closest('.oc-dialog').find('button.continue')
|
||||
$primaryButton.prop('disabled', true)
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function updatePrimaryButton() {
|
||||
const checkedCount = $dlg.find('.conflicts .checkbox:checked').length
|
||||
$primaryButton.prop('disabled', checkedCount === 0)
|
||||
}
|
||||
|
||||
// add checkbox toggling actions
|
||||
$(dialogId).find('.allnewfiles').on('click', function() {
|
||||
const $checkboxes = $(dialogId).find('.conflict .replacement input[type="checkbox"]')
|
||||
$checkboxes.prop('checked', $(this).prop('checked'))
|
||||
})
|
||||
$(dialogId).find('.allexistingfiles').on('click', function() {
|
||||
const $checkboxes = $(dialogId).find('.conflict .original:not(.readonly) input[type="checkbox"]')
|
||||
$checkboxes.prop('checked', $(this).prop('checked'))
|
||||
})
|
||||
$(dialogId).find('.conflicts').on('click', '.replacement,.original:not(.readonly)', function() {
|
||||
const $checkbox = $(this).find('input[type="checkbox"]')
|
||||
$checkbox.prop('checked', !$checkbox.prop('checked'))
|
||||
})
|
||||
$(dialogId).find('.conflicts').on('click', '.replacement input[type="checkbox"],.original:not(.readonly) input[type="checkbox"]', function() {
|
||||
const $checkbox = $(this)
|
||||
$checkbox.prop('checked', !$checkbox.prop('checked'))
|
||||
})
|
||||
|
||||
// update counters
|
||||
$(dialogId).on('click', '.replacement,.allnewfiles', function() {
|
||||
const count = $(dialogId).find('.conflict .replacement input[type="checkbox"]:checked').length
|
||||
if (count === $(dialogId + ' .conflict').length) {
|
||||
$(dialogId).find('.allnewfiles').prop('checked', true)
|
||||
$(dialogId).find('.allnewfiles + .count').text(t('core', '(all selected)'))
|
||||
} else if (count > 0) {
|
||||
$(dialogId).find('.allnewfiles').prop('checked', false)
|
||||
$(dialogId).find('.allnewfiles + .count').text(t('core', '({count} selected)', { count }))
|
||||
} else {
|
||||
$(dialogId).find('.allnewfiles').prop('checked', false)
|
||||
$(dialogId).find('.allnewfiles + .count').text('')
|
||||
}
|
||||
updatePrimaryButton()
|
||||
})
|
||||
$(dialogId).on('click', '.original,.allexistingfiles', function() {
|
||||
const count = $(dialogId).find('.conflict .original input[type="checkbox"]:checked').length
|
||||
if (count === $(dialogId + ' .conflict').length) {
|
||||
$(dialogId).find('.allexistingfiles').prop('checked', true)
|
||||
$(dialogId).find('.allexistingfiles + .count').text(t('core', '(all selected)'))
|
||||
} else if (count > 0) {
|
||||
$(dialogId).find('.allexistingfiles').prop('checked', false)
|
||||
$(dialogId).find('.allexistingfiles + .count')
|
||||
.text(t('core', '({count} selected)', { count }))
|
||||
} else {
|
||||
$(dialogId).find('.allexistingfiles').prop('checked', false)
|
||||
$(dialogId).find('.allexistingfiles + .count').text('')
|
||||
}
|
||||
updatePrimaryButton()
|
||||
})
|
||||
|
||||
dialogDeferred.resolve()
|
||||
})
|
||||
.fail(function() {
|
||||
dialogDeferred.reject()
|
||||
alert(t('core', 'Error loading file exists template'))
|
||||
})
|
||||
}
|
||||
// }
|
||||
return dialogDeferred.promise()
|
||||
},
|
||||
|
||||
_getFileExistsTemplate: function() {
|
||||
const defer = $.Deferred()
|
||||
if (!this.$fileexistsTemplate) {
|
||||
const self = this
|
||||
$.get(OC.filePath('core', 'templates/legacy', 'fileexists.html'), function(tmpl) {
|
||||
self.$fileexistsTemplate = $(tmpl)
|
||||
defer.resolve(self.$fileexistsTemplate)
|
||||
})
|
||||
.fail(function() {
|
||||
defer.reject()
|
||||
})
|
||||
} else {
|
||||
defer.resolve(this.$fileexistsTemplate)
|
||||
}
|
||||
return defer.promise()
|
||||
},
|
||||
}
|
||||
|
||||
export default Dialogs
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@ import {
|
|||
import logger from '../logger.js'
|
||||
import { isUserAdmin } from './admin.js'
|
||||
import { appConfig } from './appconfig.js'
|
||||
import Apps from './apps.js'
|
||||
import appswebroots from './appswebroots.js'
|
||||
import Backbone from './backbone.js'
|
||||
import { getCapabilities } from './capabilities.js'
|
||||
import Config from './config.js'
|
||||
import {
|
||||
|
|
@ -50,15 +48,8 @@ import { debug } from './debug.js'
|
|||
import Dialogs from './dialogs.js'
|
||||
import EventSource from './eventsource.js'
|
||||
import L10N from './l10n.js'
|
||||
import {
|
||||
hideMenus,
|
||||
registerMenu,
|
||||
showMenu,
|
||||
unregisterMenu,
|
||||
} from './menu.js'
|
||||
import * as MimeType from './mimeType.js'
|
||||
import msg from './msg.js'
|
||||
import Notification from './notification.js'
|
||||
import PasswordConfirmation from './password-confirmation.js'
|
||||
import Plugins from './plugins.js'
|
||||
import {
|
||||
|
|
@ -69,7 +60,6 @@ import { getRequestToken } from './requesttoken.ts'
|
|||
import {
|
||||
linkToRemoteBase,
|
||||
} from './routing.js'
|
||||
import Settings from './settings.js'
|
||||
import { theme } from './theme.js'
|
||||
import Util from './util.js'
|
||||
import webroot from './webroot.js'
|
||||
|
|
@ -93,10 +83,8 @@ export default {
|
|||
/*
|
||||
* Deprecated helpers to be removed
|
||||
*/
|
||||
Apps,
|
||||
appConfig,
|
||||
appswebroots,
|
||||
Backbone,
|
||||
config: Config,
|
||||
/**
|
||||
* Currently logged in user or null if none
|
||||
|
|
@ -134,14 +122,6 @@ export default {
|
|||
*/
|
||||
getCapabilities,
|
||||
|
||||
/*
|
||||
* Legacy menu helpers
|
||||
*/
|
||||
hideMenus,
|
||||
registerMenu,
|
||||
showMenu,
|
||||
unregisterMenu,
|
||||
|
||||
/*
|
||||
* Path helpers
|
||||
*/
|
||||
|
|
@ -184,16 +164,11 @@ export default {
|
|||
parseQueryString,
|
||||
|
||||
msg,
|
||||
Notification,
|
||||
/**
|
||||
* @deprecated 28.0.0 use methods from '@nextcloud/password-confirmation'
|
||||
*/
|
||||
PasswordConfirmation,
|
||||
Plugins,
|
||||
/**
|
||||
* @deprecated 25.0.0 Use Vue based (`@nextcloud/vue`) settings components instead
|
||||
*/
|
||||
Settings,
|
||||
theme,
|
||||
Util,
|
||||
debug,
|
||||
|
|
@ -202,7 +177,7 @@ export default {
|
|||
*/
|
||||
filePath: generateFilePath,
|
||||
/**
|
||||
* @deprecated 19.0.0 use `generateUrl` from https://www.npmjs.com/package/@nextcloud/router
|
||||
* @deprecated 19.0.0 use `WgenerateUrl` from https://www.npmjs.com/package/@nextcloud/router
|
||||
*/
|
||||
generateUrl,
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/** @typedef {import('jquery')} jQuery */
|
||||
import $ from 'jquery'
|
||||
import _ from 'underscore'
|
||||
import { menuSpeed } from './constants.js'
|
||||
|
||||
export let currentMenu = null
|
||||
export let currentMenuToggle = null
|
||||
|
||||
/**
|
||||
* For menu toggling
|
||||
*
|
||||
* @param {jQuery} $toggle the toggle element
|
||||
* @param {jQuery} $menuEl the menu container element
|
||||
* @param {Function | undefined} toggle callback invoked everytime the menu is opened
|
||||
* @param {boolean} headerMenu is this a top right header menu?
|
||||
* @return {void}
|
||||
*/
|
||||
export function registerMenu($toggle, $menuEl, toggle, headerMenu) {
|
||||
$menuEl.addClass('menu')
|
||||
const isClickableElement = $toggle.prop('tagName') === 'A' || $toggle.prop('tagName') === 'BUTTON'
|
||||
|
||||
// On link and button, the enter key trigger a click event
|
||||
// Only use the click to avoid two fired events
|
||||
$toggle.on(isClickableElement ? 'click.menu' : 'click.menu keyup.menu', function(event) {
|
||||
// prevent the link event (append anchor to URL)
|
||||
event.preventDefault()
|
||||
|
||||
// allow enter key as a trigger
|
||||
if (event.key && event.key !== 'Enter') {
|
||||
return
|
||||
}
|
||||
|
||||
if ($menuEl.is(currentMenu)) {
|
||||
hideMenus()
|
||||
return
|
||||
} else if (currentMenu) {
|
||||
// another menu was open?
|
||||
// close it
|
||||
hideMenus()
|
||||
}
|
||||
|
||||
if (headerMenu === true) {
|
||||
$menuEl.parent().addClass('openedMenu')
|
||||
}
|
||||
|
||||
// Set menu to expanded
|
||||
$toggle.attr('aria-expanded', true)
|
||||
|
||||
$menuEl.slideToggle(menuSpeed, toggle)
|
||||
currentMenu = $menuEl
|
||||
currentMenuToggle = $toggle
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a previously registered menu
|
||||
*
|
||||
* @param {jQuery} $toggle the toggle element
|
||||
* @param {jQuery} $menuEl the menu container element
|
||||
*/
|
||||
export function unregisterMenu($toggle, $menuEl) {
|
||||
// close menu if opened
|
||||
if ($menuEl.is(currentMenu)) {
|
||||
hideMenus()
|
||||
}
|
||||
$toggle.off('click.menu').removeClass('menutoggle')
|
||||
$menuEl.removeClass('menu')
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides any open menus
|
||||
*
|
||||
* @param {Function} complete callback when the hiding animation is done
|
||||
*/
|
||||
export function hideMenus(complete) {
|
||||
if (currentMenu) {
|
||||
const lastMenu = currentMenu
|
||||
currentMenu.trigger(new $.Event('beforeHide'))
|
||||
currentMenu.slideUp(menuSpeed, function() {
|
||||
lastMenu.trigger(new $.Event('afterHide'))
|
||||
if (complete) {
|
||||
complete.apply(this, arguments)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set menu to closed
|
||||
$('.menutoggle').attr('aria-expanded', false)
|
||||
if (currentMenuToggle) {
|
||||
currentMenuToggle.attr('aria-expanded', false)
|
||||
}
|
||||
|
||||
$('.openedMenu').removeClass('openedMenu')
|
||||
currentMenu = null
|
||||
currentMenuToggle = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a given element as menu
|
||||
*
|
||||
* @param {object} [$toggle] menu toggle
|
||||
* @param {object} $menuEl menu element
|
||||
* @param {Function} complete callback when the showing animation is done
|
||||
*/
|
||||
export function showMenu($toggle, $menuEl, complete) {
|
||||
if ($menuEl.is(currentMenu)) {
|
||||
return
|
||||
}
|
||||
hideMenus()
|
||||
currentMenu = $menuEl
|
||||
currentMenuToggle = $toggle
|
||||
$menuEl.trigger(new $.Event('beforeShow'))
|
||||
$menuEl.show()
|
||||
$menuEl.trigger(new $.Event('afterShow'))
|
||||
// no animation
|
||||
if (_.isFunction(complete)) {
|
||||
complete()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { showMessage, TOAST_DEFAULT_TIMEOUT, TOAST_PERMANENT_TIMEOUT } from '@nextcloud/dialogs'
|
||||
import $ from 'jquery'
|
||||
import _ from 'underscore'
|
||||
import logger from '../logger.js'
|
||||
|
||||
/** @typedef {import('jquery')} jQuery */
|
||||
|
||||
/**
|
||||
* @todo Write documentation
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package instead
|
||||
* @namespace OC.Notification
|
||||
*/
|
||||
export default {
|
||||
|
||||
updatableNotification: null,
|
||||
|
||||
getDefaultNotificationFunction: null,
|
||||
|
||||
/**
|
||||
* @param {Function} callback callback function
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
|
||||
*/
|
||||
setDefault(callback) {
|
||||
this.getDefaultNotificationFunction = callback
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides a notification.
|
||||
*
|
||||
* If a row is given, only hide that one.
|
||||
* If no row is given, hide all notifications.
|
||||
*
|
||||
* @param {jQuery} [$row] notification row
|
||||
* @param {Function} [callback] callback
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
|
||||
*/
|
||||
hide($row, callback) {
|
||||
if (_.isFunction($row)) {
|
||||
// first arg is the callback
|
||||
callback = $row
|
||||
$row = undefined
|
||||
}
|
||||
|
||||
if (!$row) {
|
||||
logger.error('Missing argument $row in OC.Notification.hide() call, caller needs to be adjusted to only dismiss its own notification')
|
||||
return
|
||||
}
|
||||
|
||||
// remove the row directly
|
||||
$row.each(function() {
|
||||
if ($(this)[0].toastify) {
|
||||
$(this)[0].toastify.hideToast()
|
||||
} else {
|
||||
logger.error('cannot hide toast because object is not set')
|
||||
}
|
||||
if (this === this.updatableNotification) {
|
||||
this.updatableNotification = null
|
||||
}
|
||||
})
|
||||
if (callback) {
|
||||
callback.call()
|
||||
}
|
||||
if (this.getDefaultNotificationFunction) {
|
||||
this.getDefaultNotificationFunction()
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows a notification as HTML without being sanitized before.
|
||||
* If you pass unsanitized user input this may lead to a XSS vulnerability.
|
||||
* Consider using show() instead of showHTML()
|
||||
*
|
||||
* @param {string} html Message to display
|
||||
* @param {object} [options] options
|
||||
* @param {string} [options.type] notification type
|
||||
* @param {number} [options.timeout] timeout value, defaults to 0 (permanent)
|
||||
* @return {jQuery} jQuery element for notification row
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
|
||||
*/
|
||||
showHtml(html, options) {
|
||||
options = options || {}
|
||||
options.isHTML = true
|
||||
options.timeout = (!options.timeout) ? TOAST_PERMANENT_TIMEOUT : options.timeout
|
||||
const toast = showMessage(html, options)
|
||||
toast.toastElement.toastify = toast
|
||||
return $(toast.toastElement)
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows a sanitized notification
|
||||
*
|
||||
* @param {string} text Message to display
|
||||
* @param {object} [options] options
|
||||
* @param {string} [options.type] notification type
|
||||
* @param {number} [options.timeout] timeout value, defaults to 0 (permanent)
|
||||
* @return {jQuery} jQuery element for notification row
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
|
||||
*/
|
||||
show(text, options) {
|
||||
const escapeHTML = function(text) {
|
||||
return text.toString()
|
||||
.split('&').join('&')
|
||||
.split('<').join('<')
|
||||
.split('>').join('>')
|
||||
.split('"').join('"')
|
||||
.split('\'').join(''')
|
||||
}
|
||||
|
||||
options = options || {}
|
||||
options.timeout = (!options.timeout) ? TOAST_PERMANENT_TIMEOUT : options.timeout
|
||||
const toast = showMessage(escapeHTML(text), options)
|
||||
toast.toastElement.toastify = toast
|
||||
return $(toast.toastElement)
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates (replaces) a sanitized notification.
|
||||
*
|
||||
* @param {string} text Message to display
|
||||
* @return {jQuery} JQuery element for notification row
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
|
||||
*/
|
||||
showUpdate(text) {
|
||||
if (this.updatableNotification) {
|
||||
this.updatableNotification.hideToast()
|
||||
}
|
||||
this.updatableNotification = showMessage(text, { timeout: TOAST_PERMANENT_TIMEOUT })
|
||||
this.updatableNotification.toastElement.toastify = this.updatableNotification
|
||||
return $(this.updatableNotification.toastElement)
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows a notification that disappears after x seconds, default is
|
||||
* 7 seconds
|
||||
*
|
||||
* @param {string} text Message to show
|
||||
* @param {Array} [options] options array
|
||||
* @param {number} [options.timeout] timeout in seconds, if this is 0 it will show the message permanently
|
||||
* @param {boolean} [options.isHTML] an indicator for HTML notifications (true) or text (false)
|
||||
* @param {string} [options.type] notification type
|
||||
* @return {jQuery} the toast element
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
|
||||
*/
|
||||
showTemporary(text, options) {
|
||||
options = options || {}
|
||||
options.timeout = options.timeout || TOAST_DEFAULT_TIMEOUT
|
||||
const toast = showMessage(text, options)
|
||||
toast.toastElement.toastify = toast
|
||||
return $(toast.toastElement)
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a notification is hidden.
|
||||
*
|
||||
* @return {boolean}
|
||||
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
|
||||
*/
|
||||
isHidden() {
|
||||
return !$('#content').find('.toastify').length
|
||||
},
|
||||
}
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import axios from '@nextcloud/axios'
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { generateOcsUrl } from '@nextcloud/router'
|
||||
import $ from 'jquery'
|
||||
import _ from 'underscore'
|
||||
import logger from '../logger.js'
|
||||
|
||||
/**
|
||||
* @deprecated 25.0.0 Use Vue based (`@nextcloud/vue`) settings components instead
|
||||
*/
|
||||
export default {
|
||||
_cachedGroups: null,
|
||||
|
||||
escapeHTML: function(text) {
|
||||
return text.toString()
|
||||
.split('&').join('&')
|
||||
.split('<').join('<')
|
||||
.split('>').join('>')
|
||||
.split('"').join('"')
|
||||
.split('\'').join(''')
|
||||
},
|
||||
|
||||
async rebuildNavigation() {
|
||||
const { data } = await axios.get(generateOcsUrl('core/navigation', 2) + '/apps?format=json')
|
||||
if (data.ocs.meta.statuscode !== 200) {
|
||||
return
|
||||
}
|
||||
|
||||
emit('nextcloud:app-menu.refresh', { apps: data.ocs.data })
|
||||
window.dispatchEvent(new Event('resize'))
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup selection box for group selection.
|
||||
*
|
||||
* Values need to be separated by a pipe "|" character.
|
||||
* (mostly because a comma is more likely to be used
|
||||
* for groups)
|
||||
*
|
||||
* @param $elements jQuery element (hidden input) to setup select2 on
|
||||
* @param {Array} [extraOptions] extra options hash to pass to select2
|
||||
* @param {Array} [options] extra options
|
||||
* @param {Array} [options.excludeAdmins] flag whether to exclude admin groups
|
||||
*/
|
||||
setupGroupsSelect: function($elements, extraOptions, options) {
|
||||
const self = this
|
||||
options = options || {}
|
||||
if ($elements.length > 0) {
|
||||
// Let's load the data and THEN init our select
|
||||
$.ajax({
|
||||
url: generateOcsUrl('cloud/groups/details'),
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
const results = []
|
||||
|
||||
if (data.ocs.data.groups && data.ocs.data.groups.length > 0) {
|
||||
data.ocs.data.groups.forEach(function(group) {
|
||||
if (!options.excludeAdmins || group.id !== 'admin') {
|
||||
results.push({ id: group.id, displayname: group.displayname })
|
||||
}
|
||||
})
|
||||
|
||||
// note: settings are saved through a "change" event registered
|
||||
// on all input fields
|
||||
$elements.select2(_.extend({
|
||||
placeholder: t('core', 'Groups'),
|
||||
allowClear: true,
|
||||
multiple: true,
|
||||
toggleSelect: true,
|
||||
separator: '|',
|
||||
data: { results, text: 'displayname' },
|
||||
initSelection: function(element, callback) {
|
||||
const groups = $(element).val()
|
||||
let selection
|
||||
if (groups && results.length > 0) {
|
||||
selection = _.map(_.filter((groups || []).split('|').sort(), function(groupId) {
|
||||
return results.find(function(group) {
|
||||
return group.id === groupId
|
||||
}) !== undefined
|
||||
}), function(groupId) {
|
||||
return {
|
||||
id: groupId,
|
||||
displayname: results.find(function(group) {
|
||||
return group.id === groupId
|
||||
}).displayname,
|
||||
}
|
||||
})
|
||||
} else if (groups) {
|
||||
selection = _.map((groups || []).split('|').sort(), function(groupId) {
|
||||
return {
|
||||
id: groupId,
|
||||
displayname: groupId,
|
||||
}
|
||||
})
|
||||
}
|
||||
callback(selection)
|
||||
},
|
||||
formatResult: function(element) {
|
||||
return self.escapeHTML(element.displayname)
|
||||
},
|
||||
formatSelection: function(element) {
|
||||
return self.escapeHTML(element.displayname)
|
||||
},
|
||||
escapeMarkup: function(m) {
|
||||
// prevent double markup escape
|
||||
return m
|
||||
},
|
||||
}, extraOptions || {}))
|
||||
} else {
|
||||
OC.Notification.show(t('core', 'Group list is empty'), { type: 'error' })
|
||||
logger.debug(data)
|
||||
}
|
||||
},
|
||||
error: function(data) {
|
||||
OC.Notification.show(t('core', 'Unable to retrieve the group list'), { type: 'error' })
|
||||
logger.debug(data)
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -8,7 +8,8 @@ import ContactsMenu from '../views/ContactsMenu.vue'
|
|||
import ContactsMenuService from '../services/ContactsMenuService.ts'
|
||||
|
||||
/**
|
||||
* @todo move to contacts menu code https://github.com/orgs/nextcloud/projects/31#card-21213129
|
||||
* Set up the contacts menu component ("ContactsMenu")
|
||||
* This is the menu where users can access their contacts or other users on this instance.
|
||||
*/
|
||||
export function setUp() {
|
||||
const mountPoint = document.getElementById('contactsmenu')
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import Vue from 'vue'
|
|||
import AppMenu from './AppMenu.vue'
|
||||
|
||||
/**
|
||||
*
|
||||
* Set up the main menu component ("AppMenu")
|
||||
* This is the top left menu where users can navigate between different apps.
|
||||
*/
|
||||
export function setUp() {
|
||||
Vue.mixin({
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import Vue from 'vue'
|
|||
import AccountMenu from '../views/AccountMenu.vue'
|
||||
|
||||
/**
|
||||
*
|
||||
* Set up the user menu component ("AccountMenu")
|
||||
* This is the top right menu where users can access their settings, profile, logout, etc.
|
||||
*/
|
||||
export function setUp() {
|
||||
const mountPoint = document.getElementById('user-menu')
|
||||
|
|
|
|||
|
|
@ -1,972 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import escapeHTML from 'escape-html'
|
||||
import $ from 'jquery'
|
||||
import _ from 'underscore'
|
||||
import logger from '../logger.js'
|
||||
|
||||
/* global dav */
|
||||
|
||||
(function(OC, FileInfo) {
|
||||
/**
|
||||
* @class OC.Files.Client
|
||||
* @classdesc Client to access files on the server
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {string} options.host host name
|
||||
* @param {number} [options.port] port
|
||||
* @param {boolean} [options.useHTTPS] whether to use https
|
||||
* @param {string} [options.root] root path
|
||||
* @param {string} [options.userName] user name
|
||||
* @param {string} [options.password] password
|
||||
*
|
||||
* @since 8.2
|
||||
*/
|
||||
const Client = function(options) {
|
||||
this._root = options.root
|
||||
if (this._root.charAt(this._root.length - 1) === '/') {
|
||||
this._root = this._root.substr(0, this._root.length - 1)
|
||||
}
|
||||
|
||||
let url = Client.PROTOCOL_HTTP + '://'
|
||||
if (options.useHTTPS) {
|
||||
url = Client.PROTOCOL_HTTPS + '://'
|
||||
}
|
||||
|
||||
url += options.host + this._root
|
||||
this._host = options.host
|
||||
this._defaultHeaders = options.defaultHeaders || {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
requesttoken: OC.requestToken,
|
||||
}
|
||||
this._baseUrl = url
|
||||
|
||||
const clientOptions = {
|
||||
baseUrl: this._baseUrl,
|
||||
xmlNamespaces: {
|
||||
'DAV:': 'd',
|
||||
'http://owncloud.org/ns': 'oc',
|
||||
'http://nextcloud.org/ns': 'nc',
|
||||
'http://open-collaboration-services.org/ns': 'ocs',
|
||||
},
|
||||
}
|
||||
if (options.userName) {
|
||||
clientOptions.userName = options.userName
|
||||
}
|
||||
if (options.password) {
|
||||
clientOptions.password = options.password
|
||||
}
|
||||
this._client = new dav.Client(clientOptions)
|
||||
this._client.xhrProvider = _.bind(this._xhrProvider, this)
|
||||
this._fileInfoParsers = []
|
||||
}
|
||||
|
||||
Client.NS_OWNCLOUD = 'http://owncloud.org/ns'
|
||||
Client.NS_NEXTCLOUD = 'http://nextcloud.org/ns'
|
||||
Client.NS_DAV = 'DAV:'
|
||||
Client.NS_OCS = 'http://open-collaboration-services.org/ns'
|
||||
|
||||
Client.PROPERTY_GETLASTMODIFIED = '{' + Client.NS_DAV + '}getlastmodified'
|
||||
Client.PROPERTY_GETETAG = '{' + Client.NS_DAV + '}getetag'
|
||||
Client.PROPERTY_GETCONTENTTYPE = '{' + Client.NS_DAV + '}getcontenttype'
|
||||
Client.PROPERTY_RESOURCETYPE = '{' + Client.NS_DAV + '}resourcetype'
|
||||
Client.PROPERTY_INTERNAL_FILEID = '{' + Client.NS_OWNCLOUD + '}fileid'
|
||||
Client.PROPERTY_PERMISSIONS = '{' + Client.NS_OWNCLOUD + '}permissions'
|
||||
Client.PROPERTY_SIZE = '{' + Client.NS_OWNCLOUD + '}size'
|
||||
Client.PROPERTY_GETCONTENTLENGTH = '{' + Client.NS_DAV + '}getcontentlength'
|
||||
Client.PROPERTY_ISENCRYPTED = '{' + Client.NS_DAV + '}is-encrypted'
|
||||
Client.PROPERTY_SHARE_PERMISSIONS = '{' + Client.NS_OCS + '}share-permissions'
|
||||
Client.PROPERTY_SHARE_ATTRIBUTES = '{' + Client.NS_NEXTCLOUD + '}share-attributes'
|
||||
Client.PROPERTY_QUOTA_AVAILABLE_BYTES = '{' + Client.NS_DAV + '}quota-available-bytes'
|
||||
|
||||
Client.PROTOCOL_HTTP = 'http'
|
||||
Client.PROTOCOL_HTTPS = 'https'
|
||||
|
||||
Client._PROPFIND_PROPERTIES = [
|
||||
/**
|
||||
* Modified time
|
||||
*/
|
||||
[Client.NS_DAV, 'getlastmodified'],
|
||||
/**
|
||||
* Etag
|
||||
*/
|
||||
[Client.NS_DAV, 'getetag'],
|
||||
/**
|
||||
* Mime type
|
||||
*/
|
||||
[Client.NS_DAV, 'getcontenttype'],
|
||||
/**
|
||||
* Resource type "collection" for folders, empty otherwise
|
||||
*/
|
||||
[Client.NS_DAV, 'resourcetype'],
|
||||
/**
|
||||
* File id
|
||||
*/
|
||||
[Client.NS_OWNCLOUD, 'fileid'],
|
||||
/**
|
||||
* Letter-coded permissions
|
||||
*/
|
||||
[Client.NS_OWNCLOUD, 'permissions'],
|
||||
// [Client.NS_OWNCLOUD, 'downloadURL'],
|
||||
/**
|
||||
* Folder sizes
|
||||
*/
|
||||
[Client.NS_OWNCLOUD, 'size'],
|
||||
/**
|
||||
* File sizes
|
||||
*/
|
||||
[Client.NS_DAV, 'getcontentlength'],
|
||||
[Client.NS_DAV, 'quota-available-bytes'],
|
||||
/**
|
||||
* Preview availability
|
||||
*/
|
||||
[Client.NS_NEXTCLOUD, 'has-preview'],
|
||||
/**
|
||||
* Mount type
|
||||
*/
|
||||
[Client.NS_NEXTCLOUD, 'mount-type'],
|
||||
/**
|
||||
* Encryption state
|
||||
*/
|
||||
[Client.NS_NEXTCLOUD, 'is-encrypted'],
|
||||
/**
|
||||
* Share permissions
|
||||
*/
|
||||
[Client.NS_OCS, 'share-permissions'],
|
||||
/**
|
||||
* Share attributes
|
||||
*/
|
||||
[Client.NS_NEXTCLOUD, 'share-attributes'],
|
||||
]
|
||||
|
||||
/**
|
||||
* @memberof OC.Files
|
||||
*/
|
||||
Client.prototype = {
|
||||
|
||||
/**
|
||||
* Root path of the Webdav endpoint
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
_root: null,
|
||||
|
||||
/**
|
||||
* Client from the library
|
||||
*
|
||||
* @type dav.Client
|
||||
*/
|
||||
_client: null,
|
||||
|
||||
/**
|
||||
* Array of file info parsing functions.
|
||||
*
|
||||
* @type Array<OC.Files.Client~parseFileInfo>
|
||||
*/
|
||||
_fileInfoParsers: [],
|
||||
|
||||
/**
|
||||
* Returns the configured XHR provider for davclient
|
||||
*
|
||||
* @return {XMLHttpRequest}
|
||||
*/
|
||||
_xhrProvider: function() {
|
||||
const headers = this._defaultHeaders
|
||||
const xhr = new XMLHttpRequest()
|
||||
const oldOpen = xhr.open
|
||||
// override open() method to add headers
|
||||
xhr.open = function() {
|
||||
const result = oldOpen.apply(this, arguments)
|
||||
_.each(headers, function(value, key) {
|
||||
xhr.setRequestHeader(key, value)
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
OC.registerXHRForErrorProcessing(xhr)
|
||||
return xhr
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepends the base url to the given path sections
|
||||
*
|
||||
* @param {...string} path sections
|
||||
*
|
||||
* @return {string} base url + joined path, any leading or trailing slash
|
||||
* will be kept
|
||||
*/
|
||||
_buildUrl: function() {
|
||||
let path = this._buildPath.apply(this, arguments)
|
||||
if (path.charAt([path.length - 1]) === '/') {
|
||||
path = path.substr(0, path.length - 1)
|
||||
}
|
||||
if (path.charAt(0) === '/') {
|
||||
path = path.substr(1)
|
||||
}
|
||||
return this._baseUrl + '/' + path
|
||||
},
|
||||
|
||||
/**
|
||||
* Append the path to the root and also encode path
|
||||
* sections
|
||||
*
|
||||
* @param {...string} path sections
|
||||
*
|
||||
* @return {string} joined path, any leading or trailing slash
|
||||
* will be kept
|
||||
*/
|
||||
_buildPath: function() {
|
||||
let path = OC.joinPaths.apply(this, arguments)
|
||||
const sections = path.split('/')
|
||||
let i
|
||||
for (i = 0; i < sections.length; i++) {
|
||||
sections[i] = encodeURIComponent(sections[i])
|
||||
}
|
||||
path = sections.join('/')
|
||||
return path
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse headers string into a map
|
||||
*
|
||||
* @param {string} headersString headers list as string
|
||||
*
|
||||
* @return {Object<string, Array>} map of header name to header contents
|
||||
*/
|
||||
_parseHeaders: function(headersString) {
|
||||
const headerRows = headersString.split('\n')
|
||||
const headers = {}
|
||||
for (let i = 0; i < headerRows.length; i++) {
|
||||
const sepPos = headerRows[i].indexOf(':')
|
||||
if (sepPos < 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
const headerName = headerRows[i].substr(0, sepPos)
|
||||
const headerValue = headerRows[i].substr(sepPos + 2)
|
||||
|
||||
if (!headers[headerName]) {
|
||||
// make it an array
|
||||
headers[headerName] = []
|
||||
}
|
||||
|
||||
headers[headerName].push(headerValue)
|
||||
}
|
||||
return headers
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses the etag response which is in double quotes.
|
||||
*
|
||||
* @param {string} etag etag value in double quotes
|
||||
*
|
||||
* @return {string} etag without double quotes
|
||||
*/
|
||||
_parseEtag: function(etag) {
|
||||
if (etag.charAt(0) === '"') {
|
||||
return etag.split('"')[1]
|
||||
}
|
||||
return etag
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse Webdav result
|
||||
*
|
||||
* @param {object} response XML object
|
||||
*
|
||||
* @return {Array.<FileInfo>} array of file info
|
||||
*/
|
||||
_parseFileInfo: function(response) {
|
||||
let path = decodeURIComponent(response.href)
|
||||
if (path.substr(0, this._root.length) === this._root) {
|
||||
path = path.substr(this._root.length)
|
||||
}
|
||||
|
||||
if (path.charAt(path.length - 1) === '/') {
|
||||
path = path.substr(0, path.length - 1)
|
||||
}
|
||||
|
||||
if (response.propStat.length === 0 || response.propStat[0].status !== 'HTTP/1.1 200 OK') {
|
||||
return null
|
||||
}
|
||||
|
||||
const props = response.propStat[0].properties
|
||||
|
||||
const data = {
|
||||
id: props[Client.PROPERTY_INTERNAL_FILEID],
|
||||
path: OC.dirname(path) || '/',
|
||||
name: OC.basename(path),
|
||||
mtime: (new Date(props[Client.PROPERTY_GETLASTMODIFIED])).getTime(),
|
||||
}
|
||||
|
||||
const etagProp = props[Client.PROPERTY_GETETAG]
|
||||
if (!_.isUndefined(etagProp)) {
|
||||
data.etag = this._parseEtag(etagProp)
|
||||
}
|
||||
|
||||
let sizeProp = props[Client.PROPERTY_GETCONTENTLENGTH]
|
||||
if (!_.isUndefined(sizeProp)) {
|
||||
data.size = parseInt(sizeProp, 10)
|
||||
}
|
||||
|
||||
sizeProp = props[Client.PROPERTY_SIZE]
|
||||
if (!_.isUndefined(sizeProp)) {
|
||||
data.size = parseInt(sizeProp, 10)
|
||||
}
|
||||
|
||||
const hasPreviewProp = props['{' + Client.NS_NEXTCLOUD + '}has-preview']
|
||||
if (!_.isUndefined(hasPreviewProp)) {
|
||||
data.hasPreview = hasPreviewProp === 'true'
|
||||
} else {
|
||||
data.hasPreview = true
|
||||
}
|
||||
|
||||
const isEncryptedProp = props['{' + Client.NS_NEXTCLOUD + '}is-encrypted']
|
||||
if (!_.isUndefined(isEncryptedProp)) {
|
||||
data.isEncrypted = isEncryptedProp === '1'
|
||||
} else {
|
||||
data.isEncrypted = false
|
||||
}
|
||||
|
||||
const isFavouritedProp = props['{' + Client.NS_OWNCLOUD + '}favorite']
|
||||
if (!_.isUndefined(isFavouritedProp)) {
|
||||
data.isFavourited = isFavouritedProp === '1'
|
||||
} else {
|
||||
data.isFavourited = false
|
||||
}
|
||||
|
||||
const contentType = props[Client.PROPERTY_GETCONTENTTYPE]
|
||||
if (!_.isUndefined(contentType)) {
|
||||
data.mimetype = contentType
|
||||
}
|
||||
|
||||
const resType = props[Client.PROPERTY_RESOURCETYPE]
|
||||
if (!data.mimetype && resType) {
|
||||
const xmlvalue = resType[0]
|
||||
if (xmlvalue.namespaceURI === Client.NS_DAV && xmlvalue.nodeName.split(':')[1] === 'collection') {
|
||||
data.mimetype = 'httpd/unix-directory'
|
||||
}
|
||||
}
|
||||
|
||||
data.permissions = OC.PERMISSION_NONE
|
||||
const permissionProp = props[Client.PROPERTY_PERMISSIONS]
|
||||
if (!_.isUndefined(permissionProp)) {
|
||||
const permString = permissionProp || ''
|
||||
data.mountType = null
|
||||
for (let i = 0; i < permString.length; i++) {
|
||||
const c = permString.charAt(i)
|
||||
switch (c) {
|
||||
// FIXME: twisted permissions
|
||||
case 'C':
|
||||
case 'K':
|
||||
data.permissions |= OC.PERMISSION_CREATE
|
||||
break
|
||||
case 'G':
|
||||
data.permissions |= OC.PERMISSION_READ
|
||||
break
|
||||
case 'W':
|
||||
case 'N':
|
||||
case 'V':
|
||||
data.permissions |= OC.PERMISSION_UPDATE
|
||||
break
|
||||
case 'D':
|
||||
data.permissions |= OC.PERMISSION_DELETE
|
||||
break
|
||||
case 'R':
|
||||
data.permissions |= OC.PERMISSION_SHARE
|
||||
break
|
||||
case 'M':
|
||||
if (!data.mountType) {
|
||||
// TODO: how to identify external-root ?
|
||||
data.mountType = 'external'
|
||||
}
|
||||
break
|
||||
case 'S':
|
||||
// TODO: how to identify shared-root ?
|
||||
data.mountType = 'shared'
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sharePermissionsProp = props[Client.PROPERTY_SHARE_PERMISSIONS]
|
||||
if (!_.isUndefined(sharePermissionsProp)) {
|
||||
data.sharePermissions = parseInt(sharePermissionsProp)
|
||||
}
|
||||
|
||||
const shareAttributesProp = props[Client.PROPERTY_SHARE_ATTRIBUTES]
|
||||
if (!_.isUndefined(shareAttributesProp)) {
|
||||
try {
|
||||
data.shareAttributes = JSON.parse(shareAttributesProp)
|
||||
} catch {
|
||||
logger.warn('Could not parse share attributes returned by server: "' + shareAttributesProp + '"')
|
||||
data.shareAttributes = []
|
||||
}
|
||||
} else {
|
||||
data.shareAttributes = []
|
||||
}
|
||||
|
||||
const mounTypeProp = props['{' + Client.NS_NEXTCLOUD + '}mount-type']
|
||||
if (!_.isUndefined(mounTypeProp)) {
|
||||
data.mountType = mounTypeProp
|
||||
}
|
||||
|
||||
const quotaAvailableBytes = props['{' + Client.NS_DAV + '}quota-available-bytes']
|
||||
if (!_.isUndefined(quotaAvailableBytes)) {
|
||||
data.quotaAvailableBytes = quotaAvailableBytes
|
||||
}
|
||||
|
||||
// extend the parsed data using the custom parsers
|
||||
_.each(this._fileInfoParsers, function(parserFunction) {
|
||||
_.extend(data, parserFunction(response, data) || {})
|
||||
})
|
||||
|
||||
return new FileInfo(data)
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse Webdav multistatus
|
||||
*
|
||||
* @param {Array} responses
|
||||
*/
|
||||
_parseResult: function(responses) {
|
||||
const self = this
|
||||
return _.map(responses, function(response) {
|
||||
return self._parseFileInfo(response)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether the given status code means success
|
||||
*
|
||||
* @param {number} status status code
|
||||
*
|
||||
* @return true if status code is between 200 and 299 included
|
||||
*/
|
||||
_isSuccessStatus: function(status) {
|
||||
return status >= 200 && status <= 299
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse the Sabre exception out of the given response, if any
|
||||
*
|
||||
* @param {object} response object
|
||||
* @return {object} array of parsed message and exception (only the first one)
|
||||
*/
|
||||
_getSabreException: function(response) {
|
||||
const result = {}
|
||||
const xml = response.xhr.responseXML
|
||||
if (xml === null) {
|
||||
return result
|
||||
}
|
||||
const messages = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'message')
|
||||
const exceptions = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'exception')
|
||||
if (messages.length) {
|
||||
result.message = messages[0].textContent
|
||||
}
|
||||
if (exceptions.length) {
|
||||
result.exception = exceptions[0].textContent
|
||||
}
|
||||
return result
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the default PROPFIND properties to use during a call.
|
||||
*
|
||||
* @return {Array.<object>} array of properties
|
||||
*/
|
||||
getPropfindProperties: function() {
|
||||
if (!this._propfindProperties) {
|
||||
this._propfindProperties = _.map(Client._PROPFIND_PROPERTIES, function(propDef) {
|
||||
return '{' + propDef[0] + '}' + propDef[1]
|
||||
})
|
||||
}
|
||||
return this._propfindProperties
|
||||
},
|
||||
|
||||
/**
|
||||
* Lists the contents of a directory
|
||||
*
|
||||
* @param {string} path path to retrieve
|
||||
* @param {object} [options] options
|
||||
* @param {boolean} [options.includeParent] set to true to keep
|
||||
* the parent folder in the result list
|
||||
* @param {Array} [options.properties] list of Webdav properties to retrieve
|
||||
*
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
getFolderContents: function(path, options) {
|
||||
if (!path) {
|
||||
path = ''
|
||||
}
|
||||
options = options || {}
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
let properties
|
||||
if (_.isUndefined(options.properties)) {
|
||||
properties = this.getPropfindProperties()
|
||||
} else {
|
||||
properties = options.properties
|
||||
}
|
||||
|
||||
this._client.propFind(
|
||||
this._buildUrl(path),
|
||||
properties,
|
||||
1,
|
||||
).then(function(result) {
|
||||
if (self._isSuccessStatus(result.status)) {
|
||||
const results = self._parseResult(result.body)
|
||||
if (!options || !options.includeParent) {
|
||||
// remove root dir, the first entry
|
||||
results.shift()
|
||||
}
|
||||
deferred.resolve(result.status, results)
|
||||
} else {
|
||||
result = _.extend(result, self._getSabreException(result))
|
||||
deferred.reject(result.status, result)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches a flat list of files filtered by a given filter criteria.
|
||||
* (currently system tags and circles are supported)
|
||||
*
|
||||
* @param {object} filter filter criteria
|
||||
* @param {object} [filter.systemTagIds] list of system tag ids to filter by
|
||||
* @param {boolean} [filter.favorite] set it to filter by favorites
|
||||
* @param {object} [options] options
|
||||
* @param {Array} [options.properties] list of Webdav properties to retrieve
|
||||
*
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
getFilteredFiles: function(filter, options) {
|
||||
options = options || {}
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
let properties
|
||||
if (_.isUndefined(options.properties)) {
|
||||
properties = this.getPropfindProperties()
|
||||
} else {
|
||||
properties = options.properties
|
||||
}
|
||||
|
||||
if (!filter
|
||||
|| (!filter.systemTagIds && _.isUndefined(filter.favorite) && !filter.circlesIds)) {
|
||||
throw 'Missing filter argument'
|
||||
}
|
||||
|
||||
// root element with namespaces
|
||||
let body = '<oc:filter-files '
|
||||
let namespace
|
||||
for (namespace in this._client.xmlNamespaces) {
|
||||
body += ' xmlns:' + this._client.xmlNamespaces[namespace] + '="' + namespace + '"'
|
||||
}
|
||||
body += '>\n'
|
||||
|
||||
// properties query
|
||||
body += ' <' + this._client.xmlNamespaces['DAV:'] + ':prop>\n'
|
||||
_.each(properties, function(prop) {
|
||||
const property = self._client.parseClarkNotation(prop)
|
||||
body += ' <' + self._client.xmlNamespaces[property.namespace] + ':' + property.name + ' />\n'
|
||||
})
|
||||
|
||||
body += ' </' + this._client.xmlNamespaces['DAV:'] + ':prop>\n'
|
||||
|
||||
// rules block
|
||||
body += ' <oc:filter-rules>\n'
|
||||
_.each(filter.systemTagIds, function(systemTagIds) {
|
||||
body += ' <oc:systemtag>' + escapeHTML(systemTagIds) + '</oc:systemtag>\n'
|
||||
})
|
||||
_.each(filter.circlesIds, function(circlesIds) {
|
||||
body += ' <oc:circle>' + escapeHTML(circlesIds) + '</oc:circle>\n'
|
||||
})
|
||||
if (filter.favorite) {
|
||||
body += ' <oc:favorite>' + (filter.favorite ? '1' : '0') + '</oc:favorite>\n'
|
||||
}
|
||||
body += ' </oc:filter-rules>\n'
|
||||
|
||||
// end of root
|
||||
body += '</oc:filter-files>\n'
|
||||
|
||||
this._client.request(
|
||||
'REPORT',
|
||||
this._buildUrl(),
|
||||
{},
|
||||
body,
|
||||
).then(function(result) {
|
||||
if (self._isSuccessStatus(result.status)) {
|
||||
const results = self._parseResult(result.body)
|
||||
deferred.resolve(result.status, results)
|
||||
} else {
|
||||
result = _.extend(result, self._getSabreException(result))
|
||||
deferred.reject(result.status, result)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the file info of a given path.
|
||||
*
|
||||
* @param {string} path path
|
||||
* @param {Array} [options.properties] list of Webdav properties to retrieve
|
||||
*
|
||||
* @param options
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
getFileInfo: function(path, options) {
|
||||
if (!path) {
|
||||
path = ''
|
||||
}
|
||||
options = options || {}
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
let properties
|
||||
if (_.isUndefined(options.properties)) {
|
||||
properties = this.getPropfindProperties()
|
||||
} else {
|
||||
properties = options.properties
|
||||
}
|
||||
|
||||
// TODO: headers
|
||||
this._client.propFind(
|
||||
this._buildUrl(path),
|
||||
properties,
|
||||
0,
|
||||
).then(function(result) {
|
||||
if (self._isSuccessStatus(result.status)) {
|
||||
deferred.resolve(result.status, self._parseResult([result.body])[0])
|
||||
} else {
|
||||
result = _.extend(result, self._getSabreException(result))
|
||||
deferred.reject(result.status, result)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the contents of the given file.
|
||||
*
|
||||
* @param {string} path path to file
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
getFileContents: function(path) {
|
||||
if (!path) {
|
||||
throw 'Missing argument "path"'
|
||||
}
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
|
||||
this._client.request(
|
||||
'GET',
|
||||
this._buildUrl(path),
|
||||
).then(function(result) {
|
||||
if (self._isSuccessStatus(result.status)) {
|
||||
deferred.resolve(result.status, result.body)
|
||||
} else {
|
||||
result = _.extend(result, self._getSabreException(result))
|
||||
deferred.reject(result.status, result)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
/**
|
||||
* Puts the given data into the given file.
|
||||
*
|
||||
* @param {string} path path to file
|
||||
* @param {string} body file body
|
||||
* @param {object} [options]
|
||||
* @param {string} [options.contentType] content type
|
||||
* @param {boolean} [options.overwrite] whether to overwrite an existing file
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
putFileContents: function(path, body, options) {
|
||||
if (!path) {
|
||||
throw 'Missing argument "path"'
|
||||
}
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
options = options || {}
|
||||
const headers = {}
|
||||
let contentType = 'text/plain;charset=utf-8'
|
||||
if (options.contentType) {
|
||||
contentType = options.contentType
|
||||
}
|
||||
|
||||
headers['Content-Type'] = contentType
|
||||
|
||||
if (_.isUndefined(options.overwrite) || options.overwrite) {
|
||||
// will trigger 412 precondition failed if a file already exists
|
||||
headers['If-None-Match'] = '*'
|
||||
}
|
||||
|
||||
this._client.request(
|
||||
'PUT',
|
||||
this._buildUrl(path),
|
||||
headers,
|
||||
body || '',
|
||||
).then(function(result) {
|
||||
if (self._isSuccessStatus(result.status)) {
|
||||
deferred.resolve(result.status)
|
||||
} else {
|
||||
result = _.extend(result, self._getSabreException(result))
|
||||
deferred.reject(result.status, result)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
_simpleCall: function(method, path, headers) {
|
||||
if (!path) {
|
||||
throw 'Missing argument "path"'
|
||||
}
|
||||
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
|
||||
this._client.request(
|
||||
method,
|
||||
this._buildUrl(path),
|
||||
headers ? headers : {},
|
||||
).then(function(result) {
|
||||
if (self._isSuccessStatus(result.status)) {
|
||||
deferred.resolve(result.status)
|
||||
} else {
|
||||
result = _.extend(result, self._getSabreException(result))
|
||||
deferred.reject(result.status, result)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a directory
|
||||
*
|
||||
* @param {string} path path to create
|
||||
*
|
||||
* @param headers
|
||||
* @return {Promise}
|
||||
*/
|
||||
createDirectory: function(path, headers) {
|
||||
return this._simpleCall('MKCOL', path, headers)
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a file or directory
|
||||
*
|
||||
* @param {string} path path to delete
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
remove: function(path) {
|
||||
return this._simpleCall('DELETE', path)
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves path to another path
|
||||
*
|
||||
* @param {string} path path to move
|
||||
* @param {string} destinationPath destination path
|
||||
* @param {boolean} [allowOverwrite] true to allow overwriting,
|
||||
* false otherwise
|
||||
* @param {object} [headers] additional headers
|
||||
*
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
move: function(path, destinationPath, allowOverwrite, headers) {
|
||||
if (!path) {
|
||||
throw 'Missing argument "path"'
|
||||
}
|
||||
if (!destinationPath) {
|
||||
throw 'Missing argument "destinationPath"'
|
||||
}
|
||||
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
headers = _.extend({}, headers, {
|
||||
Destination: this._buildUrl(destinationPath),
|
||||
})
|
||||
|
||||
if (!allowOverwrite) {
|
||||
headers.Overwrite = 'F'
|
||||
}
|
||||
|
||||
this._client.request(
|
||||
'MOVE',
|
||||
this._buildUrl(path),
|
||||
headers,
|
||||
).then(function(result) {
|
||||
if (self._isSuccessStatus(result.status)) {
|
||||
deferred.resolve(result.status)
|
||||
} else {
|
||||
result = _.extend(result, self._getSabreException(result))
|
||||
deferred.reject(result.status, result)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
/**
|
||||
* Copies path to another path
|
||||
*
|
||||
* @param {string} path path to copy
|
||||
* @param {string} destinationPath destination path
|
||||
* @param {boolean} [allowOverwrite] true to allow overwriting,
|
||||
* false otherwise
|
||||
*
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
copy: function(path, destinationPath, allowOverwrite) {
|
||||
if (!path) {
|
||||
throw 'Missing argument "path"'
|
||||
}
|
||||
if (!destinationPath) {
|
||||
throw 'Missing argument "destinationPath"'
|
||||
}
|
||||
|
||||
const self = this
|
||||
const deferred = $.Deferred()
|
||||
const promise = deferred.promise()
|
||||
const headers = {
|
||||
Destination: this._buildUrl(destinationPath),
|
||||
}
|
||||
|
||||
if (!allowOverwrite) {
|
||||
headers.Overwrite = 'F'
|
||||
}
|
||||
|
||||
this._client.request(
|
||||
'COPY',
|
||||
this._buildUrl(path),
|
||||
headers,
|
||||
).then(function(response) {
|
||||
if (self._isSuccessStatus(response.status)) {
|
||||
deferred.resolve(response.status)
|
||||
} else {
|
||||
deferred.reject(response.status)
|
||||
}
|
||||
})
|
||||
return promise
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a file info parser function
|
||||
*
|
||||
* @param {OC.Files.Client~parseFileInfo} parserFunction
|
||||
*/
|
||||
addFileInfoParser: function(parserFunction) {
|
||||
this._fileInfoParsers.push(parserFunction)
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the dav.Client instance used internally
|
||||
*
|
||||
* @since 11.0.0
|
||||
* @return {dav.Client}
|
||||
*/
|
||||
getClient: function() {
|
||||
return this._client
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the user name
|
||||
*
|
||||
* @since 11.0.0
|
||||
* @return {string} userName
|
||||
*/
|
||||
getUserName: function() {
|
||||
return this._client.userName
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the password
|
||||
*
|
||||
* @since 11.0.0
|
||||
* @return {string} password
|
||||
*/
|
||||
getPassword: function() {
|
||||
return this._client.password
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the base URL
|
||||
*
|
||||
* @since 11.0.0
|
||||
* @return {string} base URL
|
||||
*/
|
||||
getBaseUrl: function() {
|
||||
return this._client.baseUrl
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the host
|
||||
*
|
||||
* @since 13.0.0
|
||||
* @return {string} base URL
|
||||
*/
|
||||
getHost: function() {
|
||||
return this._host
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* File info parser function
|
||||
*
|
||||
* This function receives a list of Webdav properties as input and
|
||||
* should return a hash array of parsed properties, if applicable.
|
||||
*
|
||||
* @callback OC.Files.Client~parseFileInfo
|
||||
* @param {object} XML Webdav properties
|
||||
* @return {Array} array of parsed property values
|
||||
*/
|
||||
|
||||
if (!OC.Files) {
|
||||
/**
|
||||
* @namespace OC.Files
|
||||
*
|
||||
* @since 8.2
|
||||
*/
|
||||
OC.Files = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default instance of the files client
|
||||
*
|
||||
* @return {OC.Files.Client} default client
|
||||
*
|
||||
* @since 8.2
|
||||
*/
|
||||
OC.Files.getClient = function() {
|
||||
if (OC.Files._defaultClient) {
|
||||
return OC.Files._defaultClient
|
||||
}
|
||||
|
||||
const client = new OC.Files.Client({
|
||||
host: window.location.host,
|
||||
port: window.location.port,
|
||||
root: OC.linkToRemoteBase('dav') + '/files/' + getCurrentUser().uid,
|
||||
useHTTPS: window.location.protocol.startsWith('https'),
|
||||
})
|
||||
OC.Files._defaultClient = client
|
||||
return client
|
||||
}
|
||||
|
||||
OC.Files.Client = Client
|
||||
})(OC, OC.Files.FileInfo)
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import _ from 'underscore'
|
||||
|
||||
(function(OC) {
|
||||
/**
|
||||
* @class OC.Files.FileInfo
|
||||
* @classdesc File information
|
||||
*
|
||||
* @param {object} data file data, see attributes for details
|
||||
*
|
||||
* @since 8.2
|
||||
*/
|
||||
const FileInfo = function(data) {
|
||||
const self = this
|
||||
_.each(data, function(value, key) {
|
||||
if (!_.isFunction(value)) {
|
||||
self[key] = value
|
||||
}
|
||||
})
|
||||
|
||||
if (!_.isUndefined(this.id)) {
|
||||
this.id = parseInt(data.id, 10)
|
||||
}
|
||||
|
||||
// TODO: normalize path
|
||||
this.path = data.path || ''
|
||||
|
||||
if (this.type === 'dir') {
|
||||
this.mimetype = 'httpd/unix-directory'
|
||||
} else {
|
||||
this.mimetype = this.mimetype || 'application/octet-stream'
|
||||
}
|
||||
|
||||
if (!this.type) {
|
||||
if (this.mimetype === 'httpd/unix-directory') {
|
||||
this.type = 'dir'
|
||||
} else {
|
||||
this.type = 'file'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @memberof OC.Files
|
||||
*/
|
||||
FileInfo.prototype = {
|
||||
/**
|
||||
* File id
|
||||
*
|
||||
* @type int
|
||||
*/
|
||||
id: null,
|
||||
|
||||
/**
|
||||
* File name
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
name: null,
|
||||
|
||||
/**
|
||||
* Path leading to the file, without the file name,
|
||||
* and with a leading slash.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
path: null,
|
||||
|
||||
/**
|
||||
* Mime type
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
mimetype: null,
|
||||
|
||||
/**
|
||||
* Icon URL.
|
||||
*
|
||||
* Can be used to override the mime type icon.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
icon: null,
|
||||
|
||||
/**
|
||||
* File type. 'file' for files, 'dir' for directories.
|
||||
*
|
||||
* @type String
|
||||
* @deprecated rely on mimetype instead
|
||||
*/
|
||||
type: null,
|
||||
|
||||
/**
|
||||
* Permissions.
|
||||
*
|
||||
* @see OC#PERMISSION_ALL for permissions
|
||||
* @type int
|
||||
*/
|
||||
permissions: null,
|
||||
|
||||
/**
|
||||
* Modification time
|
||||
*
|
||||
* @type int
|
||||
*/
|
||||
mtime: null,
|
||||
|
||||
/**
|
||||
* Etag
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
etag: null,
|
||||
|
||||
/**
|
||||
* Mount type.
|
||||
*
|
||||
* One of null, "external-root", "shared" or "shared-root"
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
mountType: null,
|
||||
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
hasPreview: true,
|
||||
|
||||
/**
|
||||
* @type int
|
||||
*/
|
||||
sharePermissions: null,
|
||||
|
||||
/**
|
||||
* @type Array
|
||||
*/
|
||||
shareAttributes: [],
|
||||
|
||||
quotaAvailableBytes: -1,
|
||||
|
||||
canDownload: function() {
|
||||
for (const i in this.shareAttributes) {
|
||||
const attr = this.shareAttributes[i]
|
||||
if (attr.scope === 'permissions' && attr.key === 'download') {
|
||||
return attr.value === true
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
if (!OC.Files) {
|
||||
OC.Files = {}
|
||||
}
|
||||
OC.Files.FileInfo = FileInfo
|
||||
})(OC)
|
||||
|
|
@ -4,12 +4,9 @@
|
|||
*/
|
||||
|
||||
/* eslint-disable @nextcloud/no-deprecations */
|
||||
// END TODO
|
||||
import Backbone from 'backbone'
|
||||
import ClipboardJS from 'clipboard'
|
||||
import { dav } from 'davclient.js'
|
||||
import Handlebars from 'handlebars'
|
||||
import $ from 'jquery'
|
||||
import moment from 'moment'
|
||||
import _ from 'underscore'
|
||||
import { initCore } from './init.js'
|
||||
|
|
@ -18,17 +15,6 @@ import { getRequestToken } from './OC/requesttoken.ts'
|
|||
import OCA from './OCA/index.js'
|
||||
import OCP from './OCP/index.js'
|
||||
|
||||
// TODO: switch to `jquery-ui` package and import widgets and effects individually
|
||||
// `jquery-ui-dist` is used as a workaround for the issue of missing effects
|
||||
import 'jquery-ui-dist/jquery-ui.js'
|
||||
import 'jquery-ui-dist/jquery-ui.css'
|
||||
import 'jquery-ui-dist/jquery-ui.theme.css'
|
||||
import 'select2'
|
||||
import 'select2/select2.css'
|
||||
import 'snap.js/dist/snap.js'
|
||||
import 'strengthify'
|
||||
import 'strengthify/strengthify.css'
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -39,25 +25,6 @@ function warnIfNotTesting() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a function as deprecated and automatically
|
||||
* warn if used!
|
||||
*
|
||||
* @param {Function} func the library to deprecate
|
||||
* @param {string} funcName the name of the library
|
||||
* @param {number} version the version this gets removed
|
||||
* @return {Function}
|
||||
*/
|
||||
function deprecate(func, funcName, version) {
|
||||
const oldFunc = func
|
||||
const newFunc = function() {
|
||||
warnIfNotTesting(`The ${funcName} library is deprecated! It will be removed in nextcloud ${version}.`)
|
||||
return oldFunc.apply(this, arguments)
|
||||
}
|
||||
Object.assign(newFunc, oldFunc)
|
||||
return newFunc
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param global
|
||||
|
|
@ -83,11 +50,9 @@ function setDeprecatedProp(global, cb, msg) {
|
|||
})
|
||||
}
|
||||
|
||||
window._ = _
|
||||
setDeprecatedProp(['$', 'jQuery'], () => $, 'The global jQuery is deprecated. It will be removed in a later versions without another warning. Please ship your own.')
|
||||
setDeprecatedProp('Backbone', () => Backbone, 'please ship your own, this will be removed in Nextcloud 20')
|
||||
setDeprecatedProp(['_'], () => _, 'The global underscore is deprecated. It will be removed in a later versions without another warning. Please ship your own.')
|
||||
setDeprecatedProp(['Clipboard', 'ClipboardJS'], () => ClipboardJS, 'please ship your own, this will be removed in Nextcloud 20')
|
||||
window.dav = dav
|
||||
setDeprecatedProp(['dav'], () => dav, 'please ship your own. It will be removed in a later versions without another warning. Please ship your own.')
|
||||
setDeprecatedProp('Handlebars', () => Handlebars, 'please ship your own, this will be removed in Nextcloud 20')
|
||||
setDeprecatedProp('moment', () => moment, 'please ship your own, this will be removed in Nextcloud 20')
|
||||
|
||||
|
|
@ -104,7 +69,6 @@ setDeprecatedProp('oc_webroot', () => OC.webroot, 'use OC.getRootPath() instead,
|
|||
setDeprecatedProp('OCDialogs', () => OC.dialogs, 'use OC.dialogs instead, this will be removed in Nextcloud 20')
|
||||
window.OCP = OCP
|
||||
window.OCA = OCA
|
||||
$.fn.select2 = deprecate($.fn.select2, 'select2', 19)
|
||||
|
||||
/**
|
||||
* translate a string
|
||||
|
|
|
|||
212
core/src/init.js
212
core/src/init.js
|
|
@ -3,35 +3,15 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { isRTL } from '@nextcloud/l10n'
|
||||
import $ from 'jquery'
|
||||
import { getLocale } from '@nextcloud/l10n'
|
||||
import moment from 'moment'
|
||||
/* globals Snap */
|
||||
import _ from 'underscore'
|
||||
import { setUp as setUpContactsMenu } from './components/ContactsMenu.js'
|
||||
import { setUp as setUpMainMenu } from './components/MainMenu.js'
|
||||
import { setUp as setUpUserMenu } from './components/UserMenu.js'
|
||||
import OC from './OC/index.js'
|
||||
import { initSessionHeartBeat } from './session-heartbeat.ts'
|
||||
import { initFallbackClipboardAPI } from './utils/ClipboardFallback.ts'
|
||||
import { interceptRequests } from './utils/xhr-request.js'
|
||||
|
||||
// keep in sync with core/css/variables.scss
|
||||
const breakpointMobileWidth = 1024
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function initLiveTimestamps() {
|
||||
// Update live timestamps every 30 seconds
|
||||
setInterval(() => {
|
||||
$('.live-relative-timestamp').each(function() {
|
||||
const timestamp = parseInt($(this).attr('data-timestamp'), 10)
|
||||
$(this).text(moment(timestamp).fromNow())
|
||||
})
|
||||
}, 30 * 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Moment doesn't have aliases for every locale and doesn't parse some locale IDs correctly so we need to alias them
|
||||
*/
|
||||
|
|
@ -47,7 +27,7 @@ const localeAliases = {
|
|||
zh_Hant_MO: 'zh-mo',
|
||||
zh_Hant_TW: 'zh-tw',
|
||||
}
|
||||
let locale = OC.getLocale()
|
||||
let locale = getLocale()
|
||||
if (Object.hasOwn(localeAliases, locale)) {
|
||||
locale = localeAliases[locale]
|
||||
}
|
||||
|
|
@ -61,200 +41,12 @@ moment.locale(locale)
|
|||
* Initializes core
|
||||
*/
|
||||
export function initCore() {
|
||||
const SNAPPER_OPEN = isRTL() ? 'right' : 'left'
|
||||
const SNAPPER_CLOSE = isRTL() ? 'left' : 'right'
|
||||
|
||||
interceptRequests()
|
||||
initFallbackClipboardAPI()
|
||||
|
||||
initSessionHeartBeat()
|
||||
|
||||
OC.registerMenu($('#expand'), $('#expanddiv'), false, true)
|
||||
|
||||
// toggle for menus
|
||||
$(document).on('mouseup.closemenus', (event) => {
|
||||
const $el = $(event.target)
|
||||
if ($el.closest('.menu').length || $el.closest('.menutoggle').length) {
|
||||
// don't close when clicking on the menu directly or a menu toggle
|
||||
return false
|
||||
}
|
||||
|
||||
OC.hideMenus()
|
||||
})
|
||||
|
||||
setUpMainMenu()
|
||||
setUpUserMenu()
|
||||
setUpContactsMenu()
|
||||
|
||||
// just add snapper for logged in users
|
||||
// and if the app doesn't handle the nav slider itself
|
||||
if ($('#app-navigation').length && !$('html').hasClass('lte9')
|
||||
&& !$('#app-content').hasClass('no-snapper')) {
|
||||
// App sidebar on mobile
|
||||
const snapper = new Snap({
|
||||
element: document.getElementById('app-content'),
|
||||
disable: SNAPPER_CLOSE,
|
||||
maxPosition: 300, // $navigation-width
|
||||
minPosition: -300, // $navigation-width for RTL
|
||||
minDragDistance: 100,
|
||||
})
|
||||
|
||||
$('#app-content').prepend('<div id="app-navigation-toggle" class="icon-menu" style="display:none" tabindex="0"></div>')
|
||||
|
||||
// keep track whether snapper is currently animating, and
|
||||
// prevent to call open or close while that is the case
|
||||
// to avoid duplicating events (snap.js doesn't check this)
|
||||
let animating = false
|
||||
snapper.on('animating', () => {
|
||||
// we need this because the trigger button
|
||||
// is also implicitly wired to close by snapper
|
||||
animating = true
|
||||
})
|
||||
snapper.on('animated', () => {
|
||||
animating = false
|
||||
})
|
||||
snapper.on('start', () => {
|
||||
// we need this because dragging triggers that
|
||||
animating = true
|
||||
})
|
||||
snapper.on('end', () => {
|
||||
// we need this because dragging stop triggers that
|
||||
animating = false
|
||||
})
|
||||
snapper.on('open', () => {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
$appNavigation.attr('aria-hidden', 'false')
|
||||
})
|
||||
snapper.on('close', () => {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
$appNavigation.attr('aria-hidden', 'true')
|
||||
})
|
||||
|
||||
// These are necessary because calling open or close
|
||||
// on snapper during an animation makes it trigger an
|
||||
// unfinishable animation, which itself will continue
|
||||
// triggering animating events and cause high CPU load,
|
||||
//
|
||||
// Ref https://github.com/jakiestfu/Snap.js/issues/216
|
||||
const oldSnapperOpen = snapper.open
|
||||
const oldSnapperClose = snapper.close
|
||||
const _snapperOpen = () => {
|
||||
if (animating || snapper.state().state !== 'closed') {
|
||||
return
|
||||
}
|
||||
oldSnapperOpen(SNAPPER_OPEN)
|
||||
}
|
||||
|
||||
const _snapperClose = () => {
|
||||
if (animating || snapper.state().state === 'closed') {
|
||||
return
|
||||
}
|
||||
oldSnapperClose()
|
||||
}
|
||||
|
||||
// Needs to be deferred to properly catch in-between
|
||||
// events that snap.js is triggering after dragging.
|
||||
//
|
||||
// Skipped when running unit tests as we are not testing
|
||||
// the snap.js workarounds...
|
||||
if (!window.TESTING) {
|
||||
snapper.open = () => {
|
||||
_.defer(_snapperOpen)
|
||||
}
|
||||
snapper.close = () => {
|
||||
_.defer(_snapperClose)
|
||||
}
|
||||
}
|
||||
|
||||
$('#app-navigation-toggle').click(() => {
|
||||
// close is implicit in the button by snap.js
|
||||
if (snapper.state().state !== SNAPPER_OPEN) {
|
||||
snapper.open(SNAPPER_OPEN)
|
||||
}
|
||||
})
|
||||
$('#app-navigation-toggle').keypress(() => {
|
||||
if (snapper.state().state === SNAPPER_OPEN) {
|
||||
snapper.close()
|
||||
} else {
|
||||
snapper.open(SNAPPER_OPEN)
|
||||
}
|
||||
})
|
||||
|
||||
// close sidebar when switching navigation entry
|
||||
const $appNavigation = $('#app-navigation')
|
||||
$appNavigation.attr('aria-hidden', 'true')
|
||||
$appNavigation.delegate('a, :button', 'click', (event) => {
|
||||
const $target = $(event.target)
|
||||
// don't hide navigation when changing settings or adding things
|
||||
if ($target.is('.app-navigation-noclose')
|
||||
|| $target.closest('.app-navigation-noclose').length) {
|
||||
return
|
||||
}
|
||||
if ($target.is('.app-navigation-entry-utils-menu-button')
|
||||
|| $target.closest('.app-navigation-entry-utils-menu-button').length) {
|
||||
return
|
||||
}
|
||||
if ($target.is('.add-new')
|
||||
|| $target.closest('.add-new').length) {
|
||||
return
|
||||
}
|
||||
if ($target.is('#app-settings')
|
||||
|| $target.closest('#app-settings').length) {
|
||||
return
|
||||
}
|
||||
snapper.close()
|
||||
})
|
||||
|
||||
let navigationBarSlideGestureEnabled = false
|
||||
let navigationBarSlideGestureAllowed = true
|
||||
let navigationBarSlideGestureEnablePending = false
|
||||
|
||||
OC.allowNavigationBarSlideGesture = () => {
|
||||
navigationBarSlideGestureAllowed = true
|
||||
|
||||
if (navigationBarSlideGestureEnablePending) {
|
||||
snapper.enable()
|
||||
|
||||
navigationBarSlideGestureEnabled = true
|
||||
navigationBarSlideGestureEnablePending = false
|
||||
}
|
||||
}
|
||||
|
||||
OC.disallowNavigationBarSlideGesture = () => {
|
||||
navigationBarSlideGestureAllowed = false
|
||||
|
||||
if (navigationBarSlideGestureEnabled) {
|
||||
const endCurrentDrag = true
|
||||
snapper.disable(endCurrentDrag)
|
||||
|
||||
navigationBarSlideGestureEnabled = false
|
||||
navigationBarSlideGestureEnablePending = true
|
||||
}
|
||||
}
|
||||
|
||||
const toggleSnapperOnSize = () => {
|
||||
if ($(window).width() > breakpointMobileWidth) {
|
||||
$appNavigation.attr('aria-hidden', 'false')
|
||||
snapper.close()
|
||||
snapper.disable()
|
||||
|
||||
navigationBarSlideGestureEnabled = false
|
||||
navigationBarSlideGestureEnablePending = false
|
||||
} else if (navigationBarSlideGestureAllowed) {
|
||||
snapper.enable()
|
||||
|
||||
navigationBarSlideGestureEnabled = true
|
||||
navigationBarSlideGestureEnablePending = false
|
||||
} else {
|
||||
navigationBarSlideGestureEnablePending = true
|
||||
}
|
||||
}
|
||||
|
||||
$(window).resize(_.debounce(toggleSnapperOnSize, 250))
|
||||
|
||||
// initial call
|
||||
toggleSnapperOnSize()
|
||||
}
|
||||
|
||||
initLiveTimestamps()
|
||||
}
|
||||
|
|
|
|||
148
core/src/jquery/avatar.js
vendored
148
core/src/jquery/avatar.js
vendored
|
|
@ -1,148 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import $ from 'jquery'
|
||||
|
||||
/**
|
||||
* This plugin inserts the right avatar for the user, depending on, whether a
|
||||
* custom avatar is uploaded - which it uses then - or not, and display a
|
||||
* placeholder with the first letter of the users name instead.
|
||||
* For this it queries the core_avatar_get route, thus this plugin is fit very
|
||||
* tightly for owncloud, and it may not work anywhere else.
|
||||
*
|
||||
* You may use this on any <div></div>
|
||||
* Here I'm using <div class="avatardiv"></div> as an example.
|
||||
*
|
||||
* There are 5 ways to call this:
|
||||
*
|
||||
* 1. $('.avatardiv').avatar('jdoe', 128);
|
||||
* This will make the div to jdoe's fitting avatar, with a size of 128px.
|
||||
*
|
||||
* 2. $('.avatardiv').avatar('jdoe');
|
||||
* This will make the div to jdoe's fitting avatar. If the div already has a
|
||||
* height, it will be used for the avatars size. Otherwise this plugin will
|
||||
* search for 'size' DOM data, to use for avatar size. If neither are available
|
||||
* it will default to 64px.
|
||||
*
|
||||
* 3. $('.avatardiv').avatar();
|
||||
* This will search the DOM for 'user' data, to use as the username. If there
|
||||
* is no username available it will default to a placeholder with the value of
|
||||
* "?". The size will be determined the same way, as the second example.
|
||||
*
|
||||
* 4. $('.avatardiv').avatar('jdoe', 128, true);
|
||||
* This will behave like the first example, except it will also append random
|
||||
* hashes to the custom avatar images, to force image reloading in IE8.
|
||||
*
|
||||
* 5. $('.avatardiv').avatar('jdoe', 128, undefined, true);
|
||||
* This will behave like the first example, but it will hide the avatardiv, if
|
||||
* it will display the default placeholder. undefined is the ie8fix from
|
||||
* example 4 and can be either true, or false/undefined, to be ignored.
|
||||
*
|
||||
* 6. $('.avatardiv').avatar('jdoe', 128, undefined, true, callback);
|
||||
* This will behave like the above example, but it will call the function
|
||||
* defined in callback after the avatar is placed into the DOM.
|
||||
*
|
||||
*/
|
||||
|
||||
$.fn.avatar = function(user, size, ie8fix, hidedefault, callback, displayname) {
|
||||
const setAvatarForUnknownUser = function(target) {
|
||||
target.imageplaceholder('?')
|
||||
target.css('background-color', '#b9b9b9')
|
||||
}
|
||||
|
||||
if (typeof (user) !== 'undefined') {
|
||||
user = String(user)
|
||||
}
|
||||
if (typeof (displayname) !== 'undefined') {
|
||||
displayname = String(displayname)
|
||||
}
|
||||
|
||||
if (typeof (size) === 'undefined') {
|
||||
if (this.height() > 0) {
|
||||
size = this.height()
|
||||
} else if (this.data('size') > 0) {
|
||||
size = this.data('size')
|
||||
} else {
|
||||
size = 64
|
||||
}
|
||||
}
|
||||
|
||||
this.height(size)
|
||||
this.width(size)
|
||||
|
||||
if (typeof (user) === 'undefined') {
|
||||
if (typeof (this.data('user')) !== 'undefined') {
|
||||
user = this.data('user')
|
||||
} else {
|
||||
setAvatarForUnknownUser(this)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// sanitize
|
||||
user = String(user).replace(/\//g, '')
|
||||
|
||||
const $div = this
|
||||
let url
|
||||
|
||||
// If this is our own avatar we have to use the version attribute
|
||||
if (user === getCurrentUser()?.uid) {
|
||||
url = generateUrl(
|
||||
'/avatar/{user}/{size}?v={version}',
|
||||
{
|
||||
user,
|
||||
size: Math.ceil(size * window.devicePixelRatio),
|
||||
version: window.oc_userconfig.avatar.version,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
url = generateUrl(
|
||||
'/avatar/{user}/{size}',
|
||||
{
|
||||
user,
|
||||
size: Math.ceil(size * window.devicePixelRatio),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const img = new Image()
|
||||
|
||||
// If the new image loads successfully set it.
|
||||
img.onload = function() {
|
||||
$div.clearimageplaceholder()
|
||||
$div.append(img)
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
// Fallback when avatar loading fails:
|
||||
// Use old placeholder when a displayname attribute is defined,
|
||||
// otherwise show the unknown user placeholder.
|
||||
img.onerror = function() {
|
||||
$div.clearimageplaceholder()
|
||||
if (typeof (displayname) !== 'undefined') {
|
||||
$div.imageplaceholder(user, displayname)
|
||||
} else {
|
||||
setAvatarForUnknownUser($div)
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
if (size < 32) {
|
||||
$div.addClass('icon-loading-small')
|
||||
} else {
|
||||
$div.addClass('icon-loading')
|
||||
}
|
||||
img.width = size
|
||||
img.height = size
|
||||
img.src = url
|
||||
img.alt = ''
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 157 B |
Binary file not shown.
|
Before Width: | Height: | Size: 86 B |
Binary file not shown.
|
Before Width: | Height: | Size: 86 B |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
|
|
@ -1,264 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget-content {
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-main-background) none;
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
.ui-widget-content a {
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
.ui-widget-header {
|
||||
border: none;
|
||||
color: var(--color-main-text);
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.ui-widget-header a {
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.ui-state-default,
|
||||
.ui-widget-content .ui-state-default,
|
||||
.ui-widget-header .ui-state-default {
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-main-background) none;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.ui-state-default a,
|
||||
.ui-state-default a:link,
|
||||
.ui-state-default a:visited {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.ui-state-hover,
|
||||
.ui-widget-content .ui-state-hover,
|
||||
.ui-widget-header .ui-state-hover,
|
||||
.ui-state-focus,
|
||||
.ui-widget-content .ui-state-focus,
|
||||
.ui-widget-header .ui-state-focus {
|
||||
border: 1px solid #ddd;
|
||||
background: var(--color-main-background) none;
|
||||
font-weight: bold;
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
.ui-state-hover a,
|
||||
.ui-state-hover a:hover,
|
||||
.ui-state-hover a:link,
|
||||
.ui-state-hover a:visited {
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
.ui-state-active,
|
||||
.ui-widget-content .ui-state-active,
|
||||
.ui-widget-header .ui-state-active {
|
||||
border: 1px solid var(--color-primary-element);
|
||||
background: var(--color-main-background) none;
|
||||
font-weight: bold;
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
.ui-state-active a,
|
||||
.ui-state-active a:link,
|
||||
.ui-state-active a:visited {
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-highlight,
|
||||
.ui-widget-content .ui-state-highlight,
|
||||
.ui-widget-header .ui-state-highlight {
|
||||
border: 1px solid var(--color-main-background);
|
||||
background: var(--color-main-background) none;
|
||||
color: var(--color-main-text);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ui-state-highlight a,
|
||||
.ui-widget-content .ui-state-highlight a,
|
||||
.ui-widget-header .ui-state-highlight a {
|
||||
color: var(--color-text-maxcontrast);
|
||||
}
|
||||
|
||||
.ui-state-error,
|
||||
.ui-widget-content .ui-state-error,
|
||||
.ui-widget-header .ui-state-error {
|
||||
border: var(--color-error);
|
||||
background: var(--color-error) none;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.ui-state-error a,
|
||||
.ui-widget-content .ui-state-error a,
|
||||
.ui-widget-header .ui-state-error a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.ui-state-error-text,
|
||||
.ui-widget-content .ui-state-error-text,
|
||||
.ui-widget-header .ui-state-error-text {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
.ui-state-default .ui-icon {
|
||||
background-image: url('images/ui-icons_1d2d44_256x240.png');
|
||||
}
|
||||
|
||||
.ui-state-hover .ui-icon,
|
||||
.ui-state-focus .ui-icon {
|
||||
background-image: url('images/ui-icons_1d2d44_256x240.png');
|
||||
}
|
||||
|
||||
.ui-state-active .ui-icon {
|
||||
background-image: url('images/ui-icons_1d2d44_256x240.png');
|
||||
}
|
||||
|
||||
.ui-state-highlight .ui-icon {
|
||||
background-image: url('images/ui-icons_ffffff_256x240.png');
|
||||
}
|
||||
|
||||
.ui-state-error .ui-icon,
|
||||
.ui-state-error-text .ui-icon {
|
||||
background-image: url('images/ui-icons_ffd27a_256x240.png');
|
||||
}
|
||||
|
||||
.ui-icon.ui-icon-none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
/* Overlays */
|
||||
.ui-widget-overlay {
|
||||
background: #666666 url('images/ui-bg_diagonals-thick_20_666666_40x40.png') 50% 50% repeat;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.ui-widget-shadow {
|
||||
margin: -5px 0 0 -5px;
|
||||
padding: 5px;
|
||||
background: #000000 url('images/ui-bg_flat_10_000000_40x100.png') 50% 50% repeat-x;
|
||||
opacity: .2;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Tabs customizations */
|
||||
.ui-tabs {
|
||||
border: none;
|
||||
|
||||
.ui-tabs-nav.ui-corner-all {
|
||||
border-end-start-radius: 0;
|
||||
border-end-end-radius: 0;
|
||||
}
|
||||
|
||||
.ui-tabs-nav {
|
||||
background: none;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.ui-state-default {
|
||||
border: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
font-weight: normal;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.ui-state-hover,
|
||||
.ui-state-active {
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--color-main-text);
|
||||
color: var(--color-main-text);
|
||||
a, a:link, a:hover, a:visited {
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
}
|
||||
.ui-state-active {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Select menus */
|
||||
.ui-autocomplete {
|
||||
&.ui-menu {
|
||||
padding: 0;
|
||||
|
||||
/* scrolling starts from three items,
|
||||
* so hide overflow and scrollbars for a clean layout */
|
||||
&.item-count-1,
|
||||
&.item-count-2 {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.ui-menu-item a {
|
||||
color: var(--color-text-maxcontrast);
|
||||
display: block;
|
||||
padding: 4px;
|
||||
padding-inline-start: 14px;
|
||||
|
||||
&.ui-state-focus, &.ui-state-active {
|
||||
box-shadow: inset 4px 0 var(--color-primary-element);
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.ui-widget-content {
|
||||
background: var(--color-main-background);
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
&.ui-corner-all {
|
||||
border-radius: 0;
|
||||
border-end-start-radius: var(--border-radius);
|
||||
border-end-end-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.ui-state-hover, .ui-widget-content .ui-state-hover,
|
||||
.ui-widget-header .ui-state-hover,
|
||||
.ui-state-focus,
|
||||
.ui-widget-content .ui-state-focus,
|
||||
.ui-widget-header .ui-state-focus {
|
||||
border: 1px solid transparent;
|
||||
background: inherit;
|
||||
color: var(--color-primary-element);
|
||||
}
|
||||
|
||||
.ui-menu-item {
|
||||
a {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ui-button.primary {
|
||||
background-color: var(--color-primary-element);
|
||||
color: var(--color-primary-element-text);
|
||||
border: 1px solid var(--color-primary-element-text);
|
||||
}
|
||||
|
||||
// fix ui-buttons on hover
|
||||
.ui-button:hover {
|
||||
font-weight:bold !important;
|
||||
}
|
||||
|
||||
|
||||
/* DRAGGABLE */
|
||||
.ui-draggable-handle,
|
||||
.ui-selectable {
|
||||
touch-action: pan-y;
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
.oc-dialog {
|
||||
background: var(--color-main-background);
|
||||
border-radius: var(--border-radius-large);
|
||||
box-shadow: 0 0 30px var(--color-box-shadow);
|
||||
color: var(--color-main-text);
|
||||
padding: 24px;
|
||||
z-index: 100001;
|
||||
font-size: 100%;
|
||||
box-sizing: border-box;
|
||||
min-width: 200px;
|
||||
top: 50%;
|
||||
inset-inline-start: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
max-height: calc(100% - 20px);
|
||||
max-width: calc(100% - 20px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.oc-dialog-title {
|
||||
background: var(--color-main-background);
|
||||
}
|
||||
|
||||
.oc-dialog-buttonrow {
|
||||
position: relative;
|
||||
display: flex;
|
||||
background: transparent;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
padding-top: 10px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
background-image: linear-gradient(rgba(255, 255, 255, 0.0), var(--color-main-background));
|
||||
|
||||
&.twobuttons {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&.onebutton,
|
||||
&.twobuttons.aside {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
button {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
height: 44px;
|
||||
min-width: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
.oc-dialog-close {
|
||||
position: absolute;
|
||||
width: 44px !important;
|
||||
height: 44px !important;
|
||||
top: 4px;
|
||||
inset-inline-end: 4px;
|
||||
padding: 25px;
|
||||
background: var(--icon-close-dark) no-repeat center;
|
||||
opacity: .5;
|
||||
border-radius: var(--border-radius-pill);
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.oc-dialog-dim {
|
||||
background-color: #000;
|
||||
opacity: .2;
|
||||
z-index: 100001;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body.theme--dark .oc-dialog-dim {
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.oc-dialog-content {
|
||||
width: 100%;
|
||||
max-width: 550px;
|
||||
}
|
||||
17
core/src/jquery/exists.js
vendored
17
core/src/jquery/exists.js
vendored
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
|
||||
/**
|
||||
* check if an element exists.
|
||||
* allows you to write if ($('#myid').exists()) to increase readability
|
||||
*
|
||||
* @see {@link http://stackoverflow.com/questions/31044/is-there-an-exists-function-for-jquery}
|
||||
* @return {boolean}
|
||||
*/
|
||||
$.fn.exists = function() {
|
||||
return this.length > 0
|
||||
}
|
||||
19
core/src/jquery/filterattr.js
vendored
19
core/src/jquery/filterattr.js
vendored
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
|
||||
/**
|
||||
* Filter jQuery selector by attribute value
|
||||
*
|
||||
* @param {string} attrName attribute name
|
||||
* @param {string} attrValue attribute value
|
||||
* @return {void}
|
||||
*/
|
||||
$.fn.filterAttr = function(attrName, attrValue) {
|
||||
return this.filter(function() {
|
||||
return $(this).attr(attrName) === attrValue
|
||||
})
|
||||
}
|
||||
44
core/src/jquery/index.js
vendored
44
core/src/jquery/index.js
vendored
|
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
|
||||
import './avatar.js'
|
||||
import './exists.js'
|
||||
import './filterattr.js'
|
||||
import './ocdialog.js'
|
||||
import './octemplate.js'
|
||||
import './placeholder.js'
|
||||
import './requesttoken.js'
|
||||
import './selectrange.js'
|
||||
import './showpassword.js'
|
||||
import './ui-fixes.js'
|
||||
import './css/jquery-ui-fixes.scss'
|
||||
import './css/jquery.ocdialog.scss'
|
||||
|
||||
/**
|
||||
* Disable automatic evaluation of responses for $.ajax() functions (and its
|
||||
* higher-level alternatives like $.get() and $.post()).
|
||||
*
|
||||
* If a response to a $.ajax() request returns a content type of "application/javascript"
|
||||
* JQuery would previously execute the response body. This is a pretty unexpected
|
||||
* behaviour and can result in a bypass of our Content-Security-Policy as well as
|
||||
* multiple unexpected XSS vectors.
|
||||
*/
|
||||
$.ajaxSetup({
|
||||
contents: {
|
||||
script: false,
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Disable execution of eval in jQuery. We do require an allowed eval CSP
|
||||
* configuration at the moment for handlebars et al. But for jQuery there is
|
||||
* not much of a reason to execute JavaScript directly via eval.
|
||||
*
|
||||
* This thus mitigates some unexpected XSS vectors.
|
||||
*/
|
||||
$.globalEval = function() {
|
||||
}
|
||||
289
core/src/jquery/ocdialog.js
vendored
289
core/src/jquery/ocdialog.js
vendored
|
|
@ -1,289 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { isA11yActivation } from '@nextcloud/vue/functions/a11y'
|
||||
import { createFocusTrap } from 'focus-trap'
|
||||
import $ from 'jquery'
|
||||
|
||||
$.widget('oc.ocdialog', {
|
||||
options: {
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
closeButton: true,
|
||||
closeOnEscape: true,
|
||||
closeCallback: null,
|
||||
modal: false,
|
||||
},
|
||||
_create() {
|
||||
const self = this
|
||||
|
||||
this.originalCss = {
|
||||
display: this.element[0].style.display,
|
||||
width: this.element[0].style.width,
|
||||
height: this.element[0].style.height,
|
||||
}
|
||||
|
||||
this.originalTitle = this.element.attr('title')
|
||||
this.options.title = this.options.title || this.originalTitle
|
||||
|
||||
this.$dialog = $('<div class="oc-dialog"></div>')
|
||||
.attr({
|
||||
// Setting tabIndex makes the div focusable
|
||||
tabIndex: -1,
|
||||
role: 'dialog',
|
||||
'aria-modal': true,
|
||||
})
|
||||
.insertBefore(this.element)
|
||||
this.$dialog.append(this.element.detach())
|
||||
this.element.removeAttr('title').addClass('oc-dialog-content').appendTo(this.$dialog)
|
||||
|
||||
// Activate the primary button on enter if there is a single input
|
||||
if (self.element.find('input').length === 1) {
|
||||
const $input = self.element.find('input')
|
||||
$input.on('keydown', function(event) {
|
||||
if (isA11yActivation(event)) {
|
||||
if (self.$buttonrow) {
|
||||
const $button = self.$buttonrow.find('button.primary')
|
||||
if ($button && !$button.prop('disabled')) {
|
||||
$button.click()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.$dialog.css({
|
||||
display: 'inline-block',
|
||||
position: 'fixed',
|
||||
})
|
||||
|
||||
this.enterCallback = null
|
||||
|
||||
$(document).on('keydown keyup', function(event) {
|
||||
if (
|
||||
event.target !== self.$dialog.get(0)
|
||||
&& self.$dialog.find($(event.target)).length === 0
|
||||
) {
|
||||
return
|
||||
}
|
||||
// Escape
|
||||
if (
|
||||
event.keyCode === 27
|
||||
&& event.type === 'keydown'
|
||||
&& self.options.closeOnEscape
|
||||
) {
|
||||
event.stopImmediatePropagation()
|
||||
self.close()
|
||||
return false
|
||||
}
|
||||
// Enter
|
||||
if (event.keyCode === 13) {
|
||||
event.stopImmediatePropagation()
|
||||
if (self.enterCallback !== null) {
|
||||
self.enterCallback()
|
||||
event.preventDefault()
|
||||
return false
|
||||
}
|
||||
if (event.type === 'keyup') {
|
||||
event.preventDefault()
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
this._setOptions(this.options)
|
||||
this._createOverlay()
|
||||
this._useFocusTrap()
|
||||
},
|
||||
_init() {
|
||||
this._trigger('open')
|
||||
},
|
||||
_setOption(key, value) {
|
||||
const self = this
|
||||
switch (key) {
|
||||
case 'title':
|
||||
if (this.$title) {
|
||||
this.$title.text(value)
|
||||
} else {
|
||||
const $title = $('<h2 class="oc-dialog-title">'
|
||||
+ value
|
||||
+ '</h2>')
|
||||
this.$title = $title.prependTo(this.$dialog)
|
||||
}
|
||||
this._setSizes()
|
||||
break
|
||||
case 'buttons':
|
||||
if (this.$buttonrow) {
|
||||
this.$buttonrow.empty()
|
||||
} else {
|
||||
const $buttonrow = $('<div class="oc-dialog-buttonrow"></div>')
|
||||
this.$buttonrow = $buttonrow.appendTo(this.$dialog)
|
||||
}
|
||||
if (value.length === 1) {
|
||||
this.$buttonrow.addClass('onebutton')
|
||||
} else if (value.length === 2) {
|
||||
this.$buttonrow.addClass('twobuttons')
|
||||
} else if (value.length === 3) {
|
||||
this.$buttonrow.addClass('threebuttons')
|
||||
}
|
||||
$.each(value, function(idx, val) {
|
||||
const $button = $('<button>').text(val.text)
|
||||
if (val.classes) {
|
||||
$button.addClass(val.classes)
|
||||
}
|
||||
if (val.defaultButton) {
|
||||
$button.addClass('primary')
|
||||
self.$defaultButton = $button
|
||||
}
|
||||
self.$buttonrow.append($button)
|
||||
$button.on('click keydown', function(event) {
|
||||
if (isA11yActivation(event)) {
|
||||
val.click.apply(self.element[0], arguments)
|
||||
}
|
||||
})
|
||||
})
|
||||
this.$buttonrow.find('button')
|
||||
.on('focus', function() {
|
||||
self.$buttonrow.find('button').removeClass('primary')
|
||||
$(this).addClass('primary')
|
||||
})
|
||||
this._setSizes()
|
||||
break
|
||||
case 'style':
|
||||
if (value.buttons !== undefined) {
|
||||
this.$buttonrow.addClass(value.buttons)
|
||||
}
|
||||
break
|
||||
case 'closeButton':
|
||||
if (value) {
|
||||
const $closeButton = $('<button class="oc-dialog-close"></button>')
|
||||
$closeButton.attr('aria-label', t('core', 'Close "{dialogTitle}" dialog', { dialogTitle: this.$title || this.options.title }))
|
||||
this.$dialog.prepend($closeButton)
|
||||
$closeButton.on('click keydown', function(event) {
|
||||
if (isA11yActivation(event)) {
|
||||
self.options.closeCallback && self.options.closeCallback()
|
||||
self.close()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$dialog.find('.oc-dialog-close').remove()
|
||||
}
|
||||
break
|
||||
case 'width':
|
||||
this.$dialog.css('width', value)
|
||||
break
|
||||
case 'height':
|
||||
this.$dialog.css('height', value)
|
||||
break
|
||||
case 'close':
|
||||
this.closeCB = value
|
||||
break
|
||||
}
|
||||
// this._super(key, value);
|
||||
$.Widget.prototype._setOption.apply(this, arguments)
|
||||
},
|
||||
_setOptions() {
|
||||
// this._super(options);
|
||||
$.Widget.prototype._setOptions.apply(this, arguments)
|
||||
},
|
||||
_setSizes() {
|
||||
let lessHeight = 0
|
||||
if (this.$title) {
|
||||
lessHeight += this.$title.outerHeight(true)
|
||||
}
|
||||
if (this.$buttonrow) {
|
||||
lessHeight += this.$buttonrow.outerHeight(true)
|
||||
}
|
||||
this.element.css({
|
||||
height: 'calc(100% - ' + lessHeight + 'px)',
|
||||
})
|
||||
},
|
||||
_createOverlay() {
|
||||
if (!this.options.modal) {
|
||||
return
|
||||
}
|
||||
|
||||
const self = this
|
||||
let contentDiv = $('#content')
|
||||
if (contentDiv.length === 0) {
|
||||
// nextcloud-vue compatibility
|
||||
contentDiv = $('.content')
|
||||
}
|
||||
this.overlay = $('<div>')
|
||||
.addClass('oc-dialog-dim')
|
||||
.insertBefore(this.$dialog)
|
||||
this.overlay.on('click keydown keyup', function(event) {
|
||||
if (event.target !== self.$dialog.get(0) && self.$dialog.find($(event.target)).length === 0) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
})
|
||||
},
|
||||
_destroyOverlay() {
|
||||
if (!this.options.modal) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.overlay) {
|
||||
this.overlay.off('click keydown keyup')
|
||||
this.overlay.remove()
|
||||
this.overlay = null
|
||||
}
|
||||
},
|
||||
_useFocusTrap() {
|
||||
// Create global stack if undefined
|
||||
Object.assign(window, { _nc_focus_trap: window._nc_focus_trap || [] })
|
||||
|
||||
const dialogElement = this.$dialog[0]
|
||||
this.focusTrap = createFocusTrap(dialogElement, {
|
||||
allowOutsideClick: true,
|
||||
trapStack: window._nc_focus_trap,
|
||||
fallbackFocus: dialogElement,
|
||||
})
|
||||
|
||||
this.focusTrap.activate()
|
||||
},
|
||||
_clearFocusTrap() {
|
||||
this.focusTrap?.deactivate()
|
||||
this.focusTrap = null
|
||||
},
|
||||
widget() {
|
||||
return this.$dialog
|
||||
},
|
||||
setEnterCallback(callback) {
|
||||
this.enterCallback = callback
|
||||
},
|
||||
unsetEnterCallback() {
|
||||
this.enterCallback = null
|
||||
},
|
||||
close() {
|
||||
this._clearFocusTrap()
|
||||
this._destroyOverlay()
|
||||
const self = this
|
||||
// Ugly hack to catch remaining keyup events.
|
||||
setTimeout(function() {
|
||||
self._trigger('close', self)
|
||||
}, 200)
|
||||
|
||||
self.$dialog.remove()
|
||||
this.destroy()
|
||||
},
|
||||
destroy() {
|
||||
if (this.$title) {
|
||||
this.$title.remove()
|
||||
}
|
||||
if (this.$buttonrow) {
|
||||
this.$buttonrow.remove()
|
||||
}
|
||||
|
||||
if (this.originalTitle) {
|
||||
this.element.attr('title', this.originalTitle)
|
||||
}
|
||||
this.element.removeClass('oc-dialog-content')
|
||||
.css(this.originalCss).detach().insertBefore(this.$dialog)
|
||||
this.$dialog.remove()
|
||||
},
|
||||
})
|
||||
111
core/src/jquery/octemplate.js
vendored
111
core/src/jquery/octemplate.js
vendored
|
|
@ -1,111 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import escapeHTML from 'escape-html'
|
||||
import $ from 'jquery'
|
||||
import logger from '../logger.js'
|
||||
|
||||
/**
|
||||
* jQuery plugin for micro templates
|
||||
*
|
||||
* Strings are automatically escaped, but that can be disabled by setting
|
||||
* escapeFunction to null.
|
||||
*
|
||||
* Usage examples:
|
||||
*
|
||||
* var htmlStr = '<p>Bake, uncovered, until the {greasystuff} is melted and the {pasta} is heated through, about {min} minutes.</p>'
|
||||
* $(htmlStr).octemplate({greasystuff: 'cheese', pasta: 'macaroni', min: 10});
|
||||
*
|
||||
* var htmlStr = '<p>Welcome back {user}</p>';
|
||||
* $(htmlStr).octemplate({user: 'John Q. Public'}, {escapeFunction: null});
|
||||
*
|
||||
* Be aware that the target string must be wrapped in an HTML element for the
|
||||
* plugin to work. The following won't work:
|
||||
*
|
||||
* var textStr = 'Welcome back {user}';
|
||||
* $(textStr).octemplate({user: 'John Q. Public'});
|
||||
*
|
||||
* For anything larger than one-liners, you can use a simple $.get() ajax
|
||||
* request to get the template, or you can embed them it the page using the
|
||||
* text/template type:
|
||||
*
|
||||
* <script id="contactListItemTemplate" type="text/template">
|
||||
* <tr class="contact" data-id="{id}">
|
||||
* <td class="name">
|
||||
* <input type="checkbox" name="id" value="{id}" /><span class="nametext">{name}</span>
|
||||
* </td>
|
||||
* <td class="email">
|
||||
* <a href="mailto:{email}">{email}</a>
|
||||
* </td>
|
||||
* <td class="phone">{phone}</td>
|
||||
* </tr>
|
||||
* </script>
|
||||
*
|
||||
* var $tmpl = $('#contactListItemTemplate');
|
||||
* var contacts = // fetched in some ajax call
|
||||
*
|
||||
* $.each(contacts, function(idx, contact) {
|
||||
* $contactList.append(
|
||||
* $tmpl.octemplate({
|
||||
* id: contact.getId(),
|
||||
* name: contact.getDisplayName(),
|
||||
* email: contact.getPreferredEmail(),
|
||||
* phone: contact.getPreferredPhone(),
|
||||
* });
|
||||
* );
|
||||
* });
|
||||
*/
|
||||
/**
|
||||
* Object Template
|
||||
* Inspired by micro templating done by e.g. underscore.js
|
||||
*/
|
||||
const Template = {
|
||||
init(vars, options, elem) {
|
||||
// Mix in the passed in options with the default options
|
||||
this.vars = vars
|
||||
this.options = $.extend({}, this.options, options)
|
||||
|
||||
this.elem = elem
|
||||
const self = this
|
||||
|
||||
if (typeof this.options.escapeFunction === 'function') {
|
||||
const keys = Object.keys(this.vars)
|
||||
for (let key = 0; key < keys.length; key++) {
|
||||
if (typeof this.vars[keys[key]] === 'string') {
|
||||
this.vars[keys[key]] = self.options.escapeFunction(this.vars[keys[key]])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const _html = this._build(this.vars)
|
||||
return $(_html)
|
||||
},
|
||||
// From stackoverflow.com/questions/1408289/best-way-to-do-variable-interpolation-in-javascript
|
||||
_build(o) {
|
||||
const data = this.elem.attr('type') === 'text/template' ? this.elem.html() : this.elem.get(0).outerHTML
|
||||
try {
|
||||
return data.replace(
|
||||
/{([^{}]*)}/g,
|
||||
function(a, b) {
|
||||
const r = o[b]
|
||||
return typeof r === 'string' || typeof r === 'number' ? r : a
|
||||
},
|
||||
)
|
||||
} catch (error) {
|
||||
logger.error('failed to build octemplate', { data, error })
|
||||
}
|
||||
},
|
||||
options: {
|
||||
escapeFunction: escapeHTML,
|
||||
},
|
||||
}
|
||||
|
||||
$.fn.octemplate = function(vars, options) {
|
||||
vars = vars || {}
|
||||
if (this.length) {
|
||||
const _template = Object.create(Template)
|
||||
return _template.init(vars, options, this)
|
||||
}
|
||||
}
|
||||
169
core/src/jquery/placeholder.js
vendored
169
core/src/jquery/placeholder.js
vendored
|
|
@ -1,169 +0,0 @@
|
|||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2013-2016 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { createHash } from 'crypto-browserify'
|
||||
import $ from 'jquery'
|
||||
import logger from '../logger.js'
|
||||
|
||||
/*
|
||||
* Adds a background color to the element called on and adds the first character
|
||||
* of the passed in string. This string is also the seed for the generation of
|
||||
* the background color.
|
||||
*
|
||||
* You have following HTML:
|
||||
*
|
||||
* <div id="albumart"></div>
|
||||
*
|
||||
* And call this from Javascript:
|
||||
*
|
||||
* $('#albumart').imageplaceholder('The Album Title');
|
||||
*
|
||||
* Which will result in:
|
||||
*
|
||||
* <div id="albumart" style="background-color: rgb(121, 90, 171); ... ">T</div>
|
||||
*
|
||||
* You may also call it like this, to have a different background, than the seed:
|
||||
*
|
||||
* $('#albumart').imageplaceholder('The Album Title', 'Album Title');
|
||||
*
|
||||
* Resulting in:
|
||||
*
|
||||
* <div id="albumart" style="background-color: rgb(121, 90, 171); ... ">A</div>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Alternatively, you can use the prototype function to convert your string to rgb colors:
|
||||
*
|
||||
* "a6741a86aded5611a8e46ce16f2ad646".toRgb()
|
||||
*
|
||||
* Will return the rgb parameters within the following object:
|
||||
*
|
||||
* Color {r: 208, g: 158, b: 109}
|
||||
*
|
||||
*/
|
||||
|
||||
function toRgb(s) {
|
||||
// Normalize hash
|
||||
let hash = s.toLowerCase()
|
||||
|
||||
// Already a md5 hash?
|
||||
if (hash.match(/^([0-9a-f]{4}-?){8}$/) === null) {
|
||||
createHash('md5')
|
||||
.update(hash)
|
||||
.digest('hex')
|
||||
}
|
||||
|
||||
hash = hash.replace(/[^0-9a-f]/g, '')
|
||||
|
||||
function Color(r, g, b) {
|
||||
this.r = r
|
||||
this.g = g
|
||||
this.b = b
|
||||
}
|
||||
|
||||
function stepCalc(steps, ends) {
|
||||
const step = new Array(3)
|
||||
step[0] = (ends[1].r - ends[0].r) / steps
|
||||
step[1] = (ends[1].g - ends[0].g) / steps
|
||||
step[2] = (ends[1].b - ends[0].b) / steps
|
||||
return step
|
||||
}
|
||||
|
||||
function mixPalette(steps, color1, color2) {
|
||||
const palette = []
|
||||
palette.push(color1)
|
||||
const step = stepCalc(steps, [color1, color2])
|
||||
for (let i = 1; i < steps; i++) {
|
||||
const r = parseInt(color1.r + (step[0] * i))
|
||||
const g = parseInt(color1.g + (step[1] * i))
|
||||
const b = parseInt(color1.b + (step[2] * i))
|
||||
palette.push(new Color(r, g, b))
|
||||
}
|
||||
return palette
|
||||
}
|
||||
|
||||
const red = new Color(182, 70, 157)
|
||||
const yellow = new Color(221, 203, 85)
|
||||
const blue = new Color(0, 130, 201) // Nextcloud blue
|
||||
// Number of steps to go from a color to another
|
||||
// 3 colors * 6 will result in 18 generated colors
|
||||
const steps = 6
|
||||
|
||||
const palette1 = mixPalette(steps, red, yellow)
|
||||
const palette2 = mixPalette(steps, yellow, blue)
|
||||
const palette3 = mixPalette(steps, blue, red)
|
||||
|
||||
const finalPalette = palette1.concat(palette2).concat(palette3)
|
||||
|
||||
// Convert a string to an integer evenly
|
||||
function hashToInt(hash, maximum) {
|
||||
let finalInt = 0
|
||||
const result = []
|
||||
|
||||
// Splitting evenly the string
|
||||
for (let i = 0; i < hash.length; i++) {
|
||||
// chars in md5 goes up to f, hex:16
|
||||
result.push(parseInt(hash.charAt(i), 16) % 16)
|
||||
}
|
||||
// Adds up all results
|
||||
for (const j in result) {
|
||||
finalInt += result[j]
|
||||
}
|
||||
// chars in md5 goes up to f, hex:16
|
||||
// make sure we're always using int in our operation
|
||||
return parseInt(parseInt(finalInt) % maximum)
|
||||
}
|
||||
|
||||
return finalPalette[hashToInt(hash, steps * 3)]
|
||||
}
|
||||
|
||||
String.prototype.toRgb = function() {
|
||||
logger.warn('String.prototype.toRgb is deprecated! It will be removed in Nextcloud 22.')
|
||||
|
||||
return toRgb(this)
|
||||
}
|
||||
|
||||
$.fn.imageplaceholder = function(seed, text, size) {
|
||||
text = text || seed
|
||||
|
||||
// Compute the hash
|
||||
const rgb = toRgb(seed)
|
||||
this.css('background-color', 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')')
|
||||
|
||||
// Placeholders are square
|
||||
const height = this.height() || size || 32
|
||||
this.height(height)
|
||||
this.width(height)
|
||||
|
||||
// CSS rules
|
||||
this.css('color', '#fff')
|
||||
this.css('font-weight', 'normal')
|
||||
this.css('text-align', 'center')
|
||||
|
||||
// calculate the height
|
||||
this.css('line-height', height + 'px')
|
||||
this.css('font-size', (height * 0.55) + 'px')
|
||||
|
||||
if (seed !== null && seed.length) {
|
||||
const placeholderText = text.replace(/\s+/g, ' ').trim().split(' ', 2).map((word) => word[0].toUpperCase()).join('')
|
||||
this.html(placeholderText)
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.clearimageplaceholder = function() {
|
||||
this.css('background-color', '')
|
||||
this.css('color', '')
|
||||
this.css('font-weight', '')
|
||||
this.css('text-align', '')
|
||||
this.css('line-height', '')
|
||||
this.css('font-size', '')
|
||||
this.html('')
|
||||
this.removeClass('icon-loading')
|
||||
this.removeClass('icon-loading-small')
|
||||
}
|
||||
14
core/src/jquery/requesttoken.js
vendored
14
core/src/jquery/requesttoken.js
vendored
|
|
@ -1,14 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
import { getRequestToken } from '../OC/requesttoken.ts'
|
||||
|
||||
$(document).on('ajaxSend', function(elm, xhr, settings) {
|
||||
if (settings.crossDomain === false) {
|
||||
xhr.setRequestHeader('requesttoken', getRequestToken())
|
||||
xhr.setRequestHeader('OCS-APIREQUEST', 'true')
|
||||
}
|
||||
})
|
||||
29
core/src/jquery/selectrange.js
vendored
29
core/src/jquery/selectrange.js
vendored
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
|
||||
/**
|
||||
* select a range in an input field
|
||||
*
|
||||
* @see {@link http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area}
|
||||
* @param {number} start start selection from
|
||||
* @param {number} end number of char from start
|
||||
* @return {void}
|
||||
*/
|
||||
$.fn.selectRange = function(start, end) {
|
||||
return this.each(function() {
|
||||
if (this.setSelectionRange) {
|
||||
this.focus()
|
||||
this.setSelectionRange(start, end)
|
||||
} else if (this.createTextRange) {
|
||||
const range = this.createTextRange()
|
||||
range.collapse(true)
|
||||
range.moveEnd('character', end)
|
||||
range.moveStart('character', start)
|
||||
range.select()
|
||||
}
|
||||
})
|
||||
}
|
||||
124
core/src/jquery/showpassword.js
vendored
124
core/src/jquery/showpassword.js
vendored
|
|
@ -1,124 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/** @typedef {import('jquery')} jQuery */
|
||||
import $ from 'jquery'
|
||||
|
||||
/**
|
||||
* @name Show Password
|
||||
* @description
|
||||
* @version 1.3.0
|
||||
* @requires jQuery 1.5
|
||||
*
|
||||
* @author Jan Jarfalk <jan.jarfalk@unwrongest.com>
|
||||
* author-website http://www.unwrongest.com
|
||||
*
|
||||
* special-thanks Michel Gratton
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
$.fn.extend({
|
||||
showPassword(c) {
|
||||
// Setup callback object
|
||||
const callback = { fn: null, args: {} }
|
||||
callback.fn = c
|
||||
|
||||
// Clones passwords and turn the clones into text inputs
|
||||
const cloneElement = function(element) {
|
||||
const $element = $(element)
|
||||
|
||||
const $clone = $('<input />')
|
||||
|
||||
// Name added for JQuery Validation compatibility
|
||||
// Element name is required to avoid script warning.
|
||||
$clone.attr({
|
||||
type: 'text',
|
||||
class: $element.attr('class'),
|
||||
style: $element.attr('style'),
|
||||
size: $element.attr('size'),
|
||||
name: $element.attr('name') + '-clone',
|
||||
tabindex: $element.attr('tabindex'),
|
||||
autocomplete: 'off',
|
||||
})
|
||||
|
||||
if ($element.attr('placeholder') !== undefined) {
|
||||
$clone.attr('placeholder', $element.attr('placeholder'))
|
||||
}
|
||||
|
||||
return $clone
|
||||
}
|
||||
|
||||
// Transfers values between two elements
|
||||
const update = function(a, b) {
|
||||
b.val(a.val())
|
||||
}
|
||||
|
||||
// Shows a or b depending on checkbox
|
||||
const setState = function(checkbox, a, b) {
|
||||
if (checkbox.is(':checked')) {
|
||||
update(a, b)
|
||||
b.show()
|
||||
a.hide()
|
||||
} else {
|
||||
update(b, a)
|
||||
b.hide()
|
||||
a.show()
|
||||
}
|
||||
}
|
||||
|
||||
return this.each(function() {
|
||||
const $input = $(this)
|
||||
const $checkbox = $($input.data('typetoggle'))
|
||||
|
||||
// Create clone
|
||||
const $clone = cloneElement($input)
|
||||
$clone.insertAfter($input)
|
||||
|
||||
// Set callback arguments
|
||||
if (callback.fn) {
|
||||
callback.args.input = $input
|
||||
callback.args.checkbox = $checkbox
|
||||
callback.args.clone = $clone
|
||||
}
|
||||
|
||||
$checkbox.bind('click', function() {
|
||||
setState($checkbox, $input, $clone)
|
||||
})
|
||||
|
||||
$input.bind('keyup', function() {
|
||||
update($input, $clone)
|
||||
})
|
||||
|
||||
$clone.bind('keyup', function() {
|
||||
update($clone, $input)
|
||||
|
||||
// Added for JQuery Validation compatibility
|
||||
// This will trigger validation if it's ON for keyup event
|
||||
$input.trigger('keyup')
|
||||
})
|
||||
|
||||
// Added for JQuery Validation compatibility
|
||||
// This will trigger validation if it's ON for blur event
|
||||
$clone.bind('blur', function() {
|
||||
$input.trigger('focusout')
|
||||
})
|
||||
|
||||
setState($checkbox, $input, $clone)
|
||||
|
||||
// set type of password field clone (type=text) to password right on submit
|
||||
// to prevent browser save the value of this field
|
||||
$clone.closest('form').submit(function() {
|
||||
// .prop has to be used, because .attr throws
|
||||
// an error while changing a type of an input
|
||||
// element
|
||||
$clone.prop('type', 'password')
|
||||
})
|
||||
|
||||
if (callback.fn) {
|
||||
callback.fn(callback.args)
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
13
core/src/jquery/ui-fixes.js
vendored
13
core/src/jquery/ui-fixes.js
vendored
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
|
||||
// Set autocomplete width the same as the related input
|
||||
// See http://stackoverflow.com/a/11845718
|
||||
$.ui.autocomplete.prototype._resizeMenu = function() {
|
||||
const ul = this.menu.element
|
||||
ul.outerWidth(this.element.outerWidth())
|
||||
}
|
||||
|
|
@ -8,19 +8,16 @@ import Axios from '@nextcloud/axios'
|
|||
import { generateUrl } from '@nextcloud/router'
|
||||
import _ from 'underscore'
|
||||
import { initCore } from './init.js'
|
||||
import { registerAppsSlideToggle } from './OC/apps.js'
|
||||
import OC from './OC/index.js'
|
||||
|
||||
import 'core-js/stable/index.js'
|
||||
import 'regenerator-runtime/runtime.js'
|
||||
import './globals.js'
|
||||
import './jquery/index.js'
|
||||
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
initCore()
|
||||
registerAppsSlideToggle()
|
||||
|
||||
// fallback to hashchange when no history support
|
||||
if (window.history.pushState) {
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
<div id="{dialog_name}" title="{title}" class="fileexists">
|
||||
<span class="why">{why}<!-- Which files do you want to keep --></span><br/>
|
||||
<span class="what">{what}<!-- If you select both versions, the copied file will have a number added to its name. --></span><br/>
|
||||
<br/>
|
||||
<table>
|
||||
<th><input id="checkbox-allnewfiles" class="allnewfiles checkbox" type="checkbox" /><label for="checkbox-allnewfiles">{allnewfiles}<span class="count"></span></label></th>
|
||||
<th><input id="checkbox-allexistingfiles" class="allexistingfiles checkbox" type="checkbox" /><label for="checkbox-allexistingfiles">{allexistingfiles}<span class="count"></span></label></th>
|
||||
</table>
|
||||
<div class="conflicts">
|
||||
<div class="template">
|
||||
<div class="filename"></div>
|
||||
<div class="replacement">
|
||||
<input type="checkbox" class="checkbox u-left"/>
|
||||
<label>
|
||||
<span class="svg icon"></span>
|
||||
<div class="mtime"></div>
|
||||
<div class="size"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="original">
|
||||
<input type="checkbox" class="checkbox u-left" />
|
||||
<label>
|
||||
<span class="svg icon"></span>
|
||||
<div class="mtime"></div>
|
||||
<div class="size"></div>
|
||||
<div class="message"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
150
core/vendor/.gitignore
vendored
150
core/vendor/.gitignore
vendored
|
|
@ -1,150 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
test/
|
||||
src/
|
||||
bower.json
|
||||
component.json
|
||||
.jshintrc
|
||||
CHANGELOG*
|
||||
Gemfile
|
||||
gruntfile.js
|
||||
Gruntfile.js
|
||||
Gulpfile.js
|
||||
Makefile
|
||||
package.json
|
||||
README*
|
||||
|
||||
# underscore
|
||||
underscore/**
|
||||
!underscore/.bower.json
|
||||
!underscore/underscore-min.js
|
||||
!underscore/LICENSE
|
||||
|
||||
# blueimp-md5
|
||||
blueimp-md5/css
|
||||
blueimp-md5/js/*
|
||||
!blueimp-md5/js/md5.min.js
|
||||
blueimp-md5/index.html
|
||||
|
||||
# momentjs - ignore all files except the two listed below
|
||||
moment/**
|
||||
!moment/.bower.json
|
||||
!moment/min
|
||||
!moment/LICENSE
|
||||
moment/min/**
|
||||
!moment/min/moment-with-locales.min.js
|
||||
|
||||
# jquery
|
||||
jquery/**
|
||||
!jquery/.bower.json
|
||||
!jquery/dist
|
||||
!jquery/dist/jquery.*
|
||||
!jquery/MIT-LICENSE.txt
|
||||
|
||||
# jquery-ui
|
||||
jquery-ui/**
|
||||
!jquery-ui/themes/base/jquery-ui.css
|
||||
!jquery-ui/jquery-ui.min.js
|
||||
!jquery-ui/.bower.json
|
||||
|
||||
# jcrop
|
||||
jcrop/index.html
|
||||
jcrop/demos
|
||||
jcrop/css/jquery.Jcrop.min.css
|
||||
jcrop/js/**
|
||||
!jcrop/js/jquery.Jcrop.js
|
||||
|
||||
# handlebars
|
||||
handlebars/**
|
||||
!handlebars/.bower.json
|
||||
!handlebars/handlebars.runtime.min.js
|
||||
|
||||
# select2
|
||||
select2/**
|
||||
!select2/.bower.json
|
||||
!select2/select2.js
|
||||
!select2/select2.css
|
||||
!select2/select2.png
|
||||
!select2/select2x2.png
|
||||
!select2/select2-spinner.gif
|
||||
!select2/LICENSE
|
||||
|
||||
#zxcvbn
|
||||
zxcvbn/**
|
||||
!zxcvbn/.bower.json
|
||||
!zxcvbn/dist
|
||||
zxcvbn/dist/**
|
||||
!zxcvbn/dist/zxcvbn.js
|
||||
!zxcvbn/LICENSE.txt
|
||||
|
||||
# snapjs
|
||||
snapjs/demo
|
||||
snapjs/dist/2.0.0-rc1
|
||||
snapjs/dist/latest/snap.css
|
||||
snapjs/dist/latest/snap.min.js
|
||||
snapjs/scripts
|
||||
|
||||
# bootstrap - only include the tooltip plugin
|
||||
bootstrap/**
|
||||
!bootstrap/.bower.json
|
||||
!bootstrap/js
|
||||
bootstrap/js/*
|
||||
!bootstrap/js/tooltip.js
|
||||
|
||||
# backbone
|
||||
backbone/backbone-min*
|
||||
|
||||
# davclient.js
|
||||
davclient.js/**
|
||||
!davclient.js/.bower.json
|
||||
!davclient.js/lib
|
||||
!davclient.js/lib/client.js
|
||||
!davclient.js/LICENSE
|
||||
|
||||
# es6-shim
|
||||
es6-shim/**
|
||||
!es6-shim/.bower.json
|
||||
!es6-shim/LICENSE
|
||||
!es6-shim/es6-shim.min.js
|
||||
|
||||
# base64
|
||||
base64/*min.js
|
||||
|
||||
# clipboard
|
||||
clipboard/**
|
||||
!clipboard/.bower.json
|
||||
!clipboard/dist
|
||||
!clipboard/dist/clipboard.min.js
|
||||
|
||||
# autosize
|
||||
autosize/**
|
||||
!autosize/dist
|
||||
!autosize/dist/autosize.min.js
|
||||
!autosize/.bower.json
|
||||
!autosize/LICENCE.md
|
||||
|
||||
#marked
|
||||
marked/bin
|
||||
marked/doc
|
||||
marked/index.js
|
||||
marked/lib
|
||||
marked/man
|
||||
|
||||
# DOMPurity
|
||||
DOMPurify/**
|
||||
!DOMPurify/dist
|
||||
!DOMPurify/dist/purify.min.js
|
||||
!DOMPurify/.bower.json
|
||||
!DOMPurify/LICENSE
|
||||
|
||||
# strengthify
|
||||
strengthify/examples.html
|
||||
strengthify/examples.png
|
||||
|
||||
# underscore
|
||||
css-vars-ponyfill/**
|
||||
!css-vars-ponyfill/dist
|
||||
!css-vars-ponyfill/dist/css-vars-ponyfill.min.js
|
||||
!css-vars-ponyfill/dist/css-vars-ponyfill.min.js.map
|
||||
!css-vars-ponyfill/LICENSE
|
||||
20
core/vendor/zxcvbn/LICENSE.txt
vendored
20
core/vendor/zxcvbn/LICENSE.txt
vendored
|
|
@ -1,20 +0,0 @@
|
|||
Copyright (c) 2012-2016 Dan Wheeler and Dropbox, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
39
core/vendor/zxcvbn/dist/zxcvbn.js
vendored
39
core/vendor/zxcvbn/dist/zxcvbn.js
vendored
File diff suppressed because one or more lines are too long
3
dist/1140-1140.js.license
vendored
3
dist/1140-1140.js.license
vendored
|
|
@ -191,9 +191,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
|
|
|
|||
9
dist/1764-1764.js.license
vendored
9
dist/1764-1764.js.license
vendored
|
|
@ -68,15 +68,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/dialogs
|
||||
- version: 6.4.2
|
||||
- license: AGPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/files
|
||||
- version: 3.12.2
|
||||
- license: AGPL-3.0-or-later
|
||||
|
|
@ -140,9 +134,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- inherits
|
||||
- version: 2.0.3
|
||||
- license: ISC
|
||||
|
|
|
|||
4
dist/2221-2221.js
vendored
4
dist/2221-2221.js
vendored
File diff suppressed because one or more lines are too long
3
dist/2221-2221.js.license
vendored
3
dist/2221-2221.js.license
vendored
|
|
@ -142,9 +142,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
|
|
|
|||
2
dist/2221-2221.js.map
vendored
2
dist/2221-2221.js.map
vendored
File diff suppressed because one or more lines are too long
9
dist/2457-2457.js.license
vendored
9
dist/2457-2457.js.license
vendored
|
|
@ -68,15 +68,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/dialogs
|
||||
- version: 6.4.2
|
||||
- license: AGPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/files
|
||||
- version: 3.12.2
|
||||
- license: AGPL-3.0-or-later
|
||||
|
|
@ -140,9 +134,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- inherits
|
||||
- version: 2.0.3
|
||||
- license: ISC
|
||||
|
|
|
|||
9
dist/4271-4271.js.license
vendored
9
dist/4271-4271.js.license
vendored
|
|
@ -51,18 +51,15 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/logger
|
||||
- version: 3.0.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/dialogs
|
||||
- version: 6.4.2
|
||||
- license: AGPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/files
|
||||
- version: 3.12.2
|
||||
- license: AGPL-3.0-or-later
|
||||
|
|
|
|||
4
dist/5528-5528.js.license
vendored
4
dist/5528-5528.js.license
vendored
|
|
@ -19,7 +19,6 @@ SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
|||
SPDX-FileCopyrightText: Richie Bendall
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorba.ch> (http://paul.vorba.ch)
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorb.de> (http://vorb.de)
|
||||
SPDX-FileCopyrightText: OpenJS Foundation and other contributors
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Max <max@nextcloud.com>
|
||||
SPDX-FileCopyrightText: Matt Zabriskie
|
||||
|
|
@ -196,9 +195,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- is-plain-obj
|
||||
- version: 4.1.0
|
||||
- license: MIT
|
||||
- jquery
|
||||
- version: 3.7.1
|
||||
- license: MIT
|
||||
- md5
|
||||
- version: 2.3.0
|
||||
- license: BSD-3-Clause
|
||||
|
|
|
|||
4
dist/6980-6980.js
vendored
4
dist/6980-6980.js
vendored
File diff suppressed because one or more lines are too long
3
dist/6980-6980.js.license
vendored
3
dist/6980-6980.js.license
vendored
|
|
@ -247,9 +247,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
|
|
|
|||
2
dist/6980-6980.js.map
vendored
2
dist/6980-6980.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/7076-7076.js
vendored
2
dist/7076-7076.js
vendored
File diff suppressed because one or more lines are too long
1
dist/7076-7076.js.map
vendored
1
dist/7076-7076.js.map
vendored
File diff suppressed because one or more lines are too long
1
dist/7076-7076.js.map.license
vendored
1
dist/7076-7076.js.map.license
vendored
|
|
@ -1 +0,0 @@
|
|||
7076-7076.js.license
|
||||
3
dist/7910-7910.js.license
vendored
3
dist/7910-7910.js.license
vendored
|
|
@ -166,9 +166,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
|
|
|
|||
4
dist/8192-8192.js
vendored
4
dist/8192-8192.js
vendored
File diff suppressed because one or more lines are too long
9
dist/8192-8192.js.license
vendored
9
dist/8192-8192.js.license
vendored
|
|
@ -68,15 +68,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/dialogs
|
||||
- version: 6.4.2
|
||||
- license: AGPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/files
|
||||
- version: 3.12.2
|
||||
- license: AGPL-3.0-or-later
|
||||
|
|
@ -140,9 +134,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- inherits
|
||||
- version: 2.0.3
|
||||
- license: ISC
|
||||
|
|
|
|||
2
dist/8192-8192.js.map
vendored
2
dist/8192-8192.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/9281-9281.js
vendored
4
dist/9281-9281.js
vendored
|
|
@ -1,2 +1,2 @@
|
|||
"use strict";(globalThis.webpackChunknextcloud_ui_legacy=globalThis.webpackChunknextcloud_ui_legacy||[]).push([[9281],{9281(e,l,c){c.d(l,{FilePickerVue:()=>i});const i=(0,c(85471).$V)(()=>Promise.all([c.e(4208),c.e(7076)]).then(c.bind(c,7076)))}}]);
|
||||
//# sourceMappingURL=9281-9281.js.map?v=b283bc58055ad056fd3b
|
||||
"use strict";(globalThis.webpackChunknextcloud_ui_legacy=globalThis.webpackChunknextcloud_ui_legacy||[]).push([[9281],{9281(e,l,c){c.d(l,{FilePickerVue:()=>i});const i=(0,c(85471).$V)(()=>Promise.all([c.e(4208),c.e(9906)]).then(c.bind(c,49906)))}}]);
|
||||
//# sourceMappingURL=9281-9281.js.map?v=29ef7f217a0c6b239922
|
||||
2
dist/9281-9281.js.map
vendored
2
dist/9281-9281.js.map
vendored
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"9281-9281.js?v=b283bc58055ad056fd3b","mappings":"gKACA,MAAMA,GAAgB,E,SAAA,IAAqB,IAAM,wD","sources":["webpack:///nextcloud/node_modules/@nextcloud/upload/node_modules/@nextcloud/dialogs/dist/chunks/index-BMbtc3xh.mjs"],"sourcesContent":["import { defineAsyncComponent } from \"vue\";\nconst FilePickerVue = defineAsyncComponent(() => import(\"./FilePicker-JKNLPCbR.mjs\"));\nexport {\n FilePickerVue\n};\n//# sourceMappingURL=index-BMbtc3xh.mjs.map\n"],"names":["FilePickerVue"],"sourceRoot":""}
|
||||
{"version":3,"file":"9281-9281.js?v=29ef7f217a0c6b239922","mappings":"gKACA,MAAMA,GAAgB,E,SAAA,IAAqB,IAAM,yD","sources":["webpack:///nextcloud/node_modules/@nextcloud/upload/node_modules/@nextcloud/dialogs/dist/chunks/index-BMbtc3xh.mjs"],"sourcesContent":["import { defineAsyncComponent } from \"vue\";\nconst FilePickerVue = defineAsyncComponent(() => import(\"./FilePicker-JKNLPCbR.mjs\"));\nexport {\n FilePickerVue\n};\n//# sourceMappingURL=index-BMbtc3xh.mjs.map\n"],"names":["FilePickerVue"],"sourceRoot":""}
|
||||
4
dist/9396-9396.js
vendored
4
dist/9396-9396.js
vendored
File diff suppressed because one or more lines are too long
4
dist/9396-9396.js.license
vendored
4
dist/9396-9396.js.license
vendored
|
|
@ -25,7 +25,6 @@ SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
|||
SPDX-FileCopyrightText: Richie Bendall
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorba.ch> (http://paul.vorba.ch)
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorb.de> (http://vorb.de)
|
||||
SPDX-FileCopyrightText: OpenJS Foundation and other contributors
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Max <max@nextcloud.com>
|
||||
SPDX-FileCopyrightText: Matt Zabriskie
|
||||
|
|
@ -224,9 +223,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- is-plain-obj
|
||||
- version: 4.1.0
|
||||
- license: MIT
|
||||
- jquery
|
||||
- version: 3.7.1
|
||||
- license: MIT
|
||||
- md5
|
||||
- version: 2.3.0
|
||||
- license: BSD-3-Clause
|
||||
|
|
|
|||
2
dist/9396-9396.js.map
vendored
2
dist/9396-9396.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/9906-9906.js
vendored
Normal file
2
dist/9906-9906.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0
|
|||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
|
||||
SPDX-FileCopyrightText: string_decoder developers
|
||||
SPDX-FileCopyrightText: p-queue developers
|
||||
SPDX-FileCopyrightText: inherits developers
|
||||
SPDX-FileCopyrightText: escape-html developers
|
||||
SPDX-FileCopyrightText: debounce developers
|
||||
|
|
@ -14,7 +15,6 @@ SPDX-FileCopyrightText: Varun A P
|
|||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)
|
||||
SPDX-FileCopyrightText: T. Jameson Little <t.jameson.little@gmail.com>
|
||||
SPDX-FileCopyrightText: Sindre Sorhus
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Perry Mitchell <perry@perrymitchell.net>
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorba.ch> (http://paul.vorba.ch)
|
||||
|
|
@ -83,24 +83,21 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/logger
|
||||
- version: 3.0.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/dialogs
|
||||
- version: 6.4.2
|
||||
- license: AGPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/files
|
||||
- version: 3.12.2
|
||||
- license: AGPL-3.0-or-later
|
||||
- @nextcloud/sharing
|
||||
- version: 0.3.0
|
||||
- license: GPL-3.0-or-later
|
||||
- eventemitter3
|
||||
- version: 5.0.1
|
||||
- license: MIT
|
||||
- @nextcloud/vue-select
|
||||
- version: 3.26.0
|
||||
- license: MIT
|
||||
|
|
@ -164,8 +161,11 @@ This file is generated from multiple sources. Included packages:
|
|||
- buffer
|
||||
- version: 6.0.3
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- eventemitter3
|
||||
- version: 5.0.1
|
||||
- license: MIT
|
||||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- inherits
|
||||
- version: 2.0.3
|
||||
1
dist/9906-9906.js.map
vendored
Normal file
1
dist/9906-9906.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/9906-9906.js.map.license
vendored
Symbolic link
1
dist/9906-9906.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
9906-9906.js.license
|
||||
4
dist/comments-comments-app.js
vendored
4
dist/comments-comments-app.js
vendored
File diff suppressed because one or more lines are too long
2
dist/comments-comments-app.js.map
vendored
2
dist/comments-comments-app.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/comments-comments-tab.js
vendored
4
dist/comments-comments-tab.js
vendored
File diff suppressed because one or more lines are too long
2
dist/comments-comments-tab.js.map
vendored
2
dist/comments-comments-tab.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/core-common.js
vendored
4
dist/core-common.js
vendored
File diff suppressed because one or more lines are too long
92
dist/core-common.js.license
vendored
92
dist/core-common.js.license
vendored
|
|
@ -32,11 +32,9 @@ SPDX-FileCopyrightText: Rubén Norte <ruben.norte@softonic.com>
|
|||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Rob Cresswell <robcresswell@pm.me>
|
||||
SPDX-FileCopyrightText: Richie Bendall
|
||||
SPDX-FileCopyrightText: Raynos <raynos2@gmail.com>
|
||||
SPDX-FileCopyrightText: Perry Mitchell <perry@perrymitchell.net>
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorba.ch> (http://paul.vorba.ch)
|
||||
SPDX-FileCopyrightText: Paul Vorbach <paul@vorb.de> (http://vorb.de)
|
||||
SPDX-FileCopyrightText: OpenJS Foundation and other contributors
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)
|
||||
SPDX-FileCopyrightText: Max <max@nextcloud.com>
|
||||
|
|
@ -44,11 +42,8 @@ SPDX-FileCopyrightText: Matt Zabriskie
|
|||
SPDX-FileCopyrightText: Mark <mark@remarkablemark.org>
|
||||
SPDX-FileCopyrightText: Mapbox
|
||||
SPDX-FileCopyrightText: Joyent
|
||||
SPDX-FileCopyrightText: Jordan Harband <ljharb@gmail.com>
|
||||
SPDX-FileCopyrightText: Jordan Harband
|
||||
SPDX-FileCopyrightText: Jonas Schade <derzade@gmail.com>
|
||||
SPDX-FileCopyrightText: John-David Dalton <john.david.dalton@gmail.com>
|
||||
SPDX-FileCopyrightText: Jeremy Ashkenas <jeremy@documentcloud.org>
|
||||
SPDX-FileCopyrightText: Jeff Sagal <sagalbot@gmail.com>
|
||||
SPDX-FileCopyrightText: James Halliday
|
||||
SPDX-FileCopyrightText: Jacob Clevenger<https://github.com/wheatjs>
|
||||
|
|
@ -216,15 +211,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/sharing
|
||||
- version: 0.4.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/dialogs
|
||||
- version: 6.4.2
|
||||
- license: AGPL-3.0-or-later
|
||||
- @nextcloud/paths
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/files
|
||||
- version: 3.12.2
|
||||
- license: AGPL-3.0-or-later
|
||||
|
|
@ -288,9 +277,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- @vueuse/shared
|
||||
- version: 11.3.0
|
||||
- license: MIT
|
||||
- available-typed-arrays
|
||||
- version: 1.0.7
|
||||
- license: MIT
|
||||
- axios-retry
|
||||
- version: 4.5.0
|
||||
- license: Apache-2.0
|
||||
|
|
@ -309,15 +295,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- blurhash
|
||||
- version: 2.0.5
|
||||
- license: MIT
|
||||
- call-bind-apply-helpers
|
||||
- version: 1.0.2
|
||||
- license: MIT
|
||||
- call-bind
|
||||
- version: 1.0.8
|
||||
- license: MIT
|
||||
- call-bound
|
||||
- version: 1.0.4
|
||||
- license: MIT
|
||||
- cancelable-promise
|
||||
- version: 4.3.1
|
||||
- license: MIT
|
||||
|
|
@ -345,30 +322,15 @@ This file is generated from multiple sources. Included packages:
|
|||
- decode-named-character-reference
|
||||
- version: 1.2.0
|
||||
- license: MIT
|
||||
- define-data-property
|
||||
- version: 1.1.4
|
||||
- license: MIT
|
||||
- devlop
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- dompurify
|
||||
- version: 3.3.1
|
||||
- license: (MPL-2.0 OR Apache-2.0)
|
||||
- dunder-proto
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- emoji-mart-vue-fast
|
||||
- version: 15.0.5
|
||||
- license: BSD-3-Clause
|
||||
- es-define-property
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- es-errors
|
||||
- version: 1.3.0
|
||||
- license: MIT
|
||||
- es-object-atoms
|
||||
- version: 1.1.1
|
||||
- license: MIT
|
||||
- escape-html
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
|
|
@ -387,33 +349,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- focus-trap
|
||||
- version: 7.8.0
|
||||
- license: MIT
|
||||
- for-each
|
||||
- version: 0.3.5
|
||||
- license: MIT
|
||||
- function-bind
|
||||
- version: 1.1.2
|
||||
- license: MIT
|
||||
- get-intrinsic
|
||||
- version: 1.3.0
|
||||
- license: MIT
|
||||
- get-proto
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- gopd
|
||||
- version: 1.2.0
|
||||
- license: MIT
|
||||
- has-property-descriptors
|
||||
- version: 1.0.2
|
||||
- license: MIT
|
||||
- has-symbols
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- has-tostringtag
|
||||
- version: 1.0.2
|
||||
- license: MIT
|
||||
- hasown
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- hast-to-hyperscript
|
||||
- version: 10.0.3
|
||||
- license: MIT
|
||||
|
|
@ -441,9 +376,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- is-buffer
|
||||
- version: 1.1.6
|
||||
- license: MIT
|
||||
- is-callable
|
||||
- version: 1.2.7
|
||||
- license: MIT
|
||||
- is-plain-obj
|
||||
- version: 4.1.0
|
||||
- license: MIT
|
||||
|
|
@ -453,21 +385,12 @@ This file is generated from multiple sources. Included packages:
|
|||
- is-svg
|
||||
- version: 6.1.0
|
||||
- license: MIT
|
||||
- is-typed-array
|
||||
- version: 1.1.15
|
||||
- license: MIT
|
||||
- jquery
|
||||
- version: 3.7.1
|
||||
- license: MIT
|
||||
- lodash
|
||||
- version: 4.17.23
|
||||
- license: MIT
|
||||
- marked
|
||||
- version: 17.0.2
|
||||
- license: MIT
|
||||
- math-intrinsics
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- md5
|
||||
- version: 2.3.0
|
||||
- license: BSD-3-Clause
|
||||
|
|
@ -564,9 +487,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- p-queue
|
||||
- version: 9.1.0
|
||||
- license: MIT
|
||||
- p-timeout
|
||||
- version: 7.0.1
|
||||
- license: MIT
|
||||
- inherits
|
||||
- version: 2.0.3
|
||||
- license: ISC
|
||||
|
|
@ -579,9 +499,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- pinia
|
||||
- version: 2.3.1
|
||||
- license: MIT
|
||||
- possible-typed-array-names
|
||||
- version: 1.1.0
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
|
|
@ -615,9 +532,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- sax
|
||||
- version: 1.4.1
|
||||
- license: ISC
|
||||
- set-function-length
|
||||
- version: 1.2.2
|
||||
- license: MIT
|
||||
- space-separated-tokens
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
|
|
@ -663,9 +577,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- typescript-event-target
|
||||
- version: 1.1.2
|
||||
- license: MIT
|
||||
- underscore
|
||||
- version: 1.13.7
|
||||
- license: MIT
|
||||
- unified
|
||||
- version: 11.0.5
|
||||
- license: MIT
|
||||
|
|
@ -723,9 +634,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- webdav
|
||||
- version: 5.9.0
|
||||
- license: MIT
|
||||
- which-typed-array
|
||||
- version: 1.1.19
|
||||
- license: MIT
|
||||
- base64-js
|
||||
- version: 1.5.1
|
||||
- license: MIT
|
||||
|
|
|
|||
2
dist/core-common.js.map
vendored
2
dist/core-common.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/core-files_client.js
vendored
2
dist/core-files_client.js
vendored
File diff suppressed because one or more lines are too long
48
dist/core-files_client.js.license
vendored
48
dist/core-files_client.js.license
vendored
|
|
@ -1,48 +0,0 @@
|
|||
SPDX-License-Identifier: MIT
|
||||
SPDX-License-Identifier: ISC
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-FileCopyrightText: escape-html developers
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: OpenJS Foundation and other contributors
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Jeremy Ashkenas <jeremy@documentcloud.org>
|
||||
SPDX-FileCopyrightText: GitHub Inc.
|
||||
SPDX-FileCopyrightText: Christoph Wurst
|
||||
|
||||
|
||||
This file is generated from multiple sources. Included packages:
|
||||
- @nextcloud/auth
|
||||
- version: 2.5.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/browser-storage
|
||||
- version: 0.5.0
|
||||
- license: GPL-3.0-or-later
|
||||
- semver
|
||||
- version: 7.7.2
|
||||
- license: ISC
|
||||
- @nextcloud/event-bus
|
||||
- version: 3.3.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/logger
|
||||
- version: 3.0.3
|
||||
- license: GPL-3.0-or-later
|
||||
- escape-html
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- jquery
|
||||
- version: 3.7.1
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
- underscore
|
||||
- version: 1.13.7
|
||||
- license: MIT
|
||||
- webpack
|
||||
- version: 5.105.2
|
||||
- license: MIT
|
||||
- nextcloud
|
||||
- version: 1.0.0
|
||||
- license: AGPL-3.0-or-later
|
||||
1
dist/core-files_client.js.map
vendored
1
dist/core-files_client.js.map
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue