Merge pull request #57648 from nextcloud/chore/drop-jquery

chore!: drop jQuery UI and jQuery
This commit is contained in:
Ferdinand Thiessen 2026-02-17 14:14:12 +01:00 committed by GitHub
commit b6d22f384b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
192 changed files with 538 additions and 6001 deletions

View file

@ -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',
})

View 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')
}
},
})

View file

@ -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
}

View file

@ -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');
}

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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",

View file

@ -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',

View file

@ -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'),

View file

@ -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') {

View file

@ -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;
}

View file

@ -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 */

View file

@ -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"}

View file

@ -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

View file

@ -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"}

View file

@ -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

View file

@ -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"}

View file

@ -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 {

View file

@ -1,4 +0,0 @@
[
"mimetypelist.js",
"select2-toggleselect.js"
]

View file

@ -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)

View file

@ -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

View file

@ -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
}
}

View file

@ -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

View file

@ -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

View file

@ -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,
/**

View file

@ -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()
}
}

View file

@ -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('&amp;')
.split('<').join('&lt;')
.split('>').join('&gt;')
.split('"').join('&quot;')
.split('\'').join('&#039;')
}
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
},
}

View file

@ -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('&amp;')
.split('<').join('&lt;')
.split('>').join('&gt;')
.split('"').join('&quot;')
.split('\'').join('&#039;')
},
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)
},
})
}
},
}

View file

@ -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')

View file

@ -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({

View file

@ -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')

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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()
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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
}

View file

@ -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
})
}

View file

@ -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() {
}

View file

@ -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()
},
})

View file

@ -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)
}
}

View file

@ -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')
}

View file

@ -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')
}
})

View file

@ -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()
}
})
}

View file

@ -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)
}
})
},
})

View file

@ -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())
}

View file

@ -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) {

View file

@ -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
View file

@ -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

View file

@ -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.

File diff suppressed because one or more lines are too long

View file

@ -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

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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

View file

@ -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

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

2
dist/7076-7076.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
7076-7076.js.license

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

4
dist/9281-9281.js vendored
View file

@ -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

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

2
dist/9906-9906.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

1
dist/9906-9906.js.map.license vendored Symbolic link
View file

@ -0,0 +1 @@
9906-9906.js.license

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

File diff suppressed because one or more lines are too long

4
dist/core-common.js vendored

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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

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