1
0

dashboard-main.js 43 KB

123
  1. /*! For license information please see dashboard-main.js.LICENSE.txt */
  2. (()=>{"use strict";var n,e={41701:(n,e,a)=>{var o=a(20144),s=a(79753),i=a(45994),r=a(79954),l=a(4820),d=a(10861),c=a.n(d),p=a(9980),A=a.n(p),u=a(70110),h=a.n(u),b=a(73229);const g={data(){return{isMobile:this._isMobile()}},beforeMount(){window.addEventListener("resize",this._onResize)},beforeDestroy(){window.removeEventListener("resize",this._onResize)},methods:{_onResize(){this.isMobile=this._isMobile()},_isMobile:()=>document.documentElement.clientWidth<768}};var m=a(25108);const v=(0,r.j)("dashboard","panels"),C=(0,r.j)("dashboard","firstRun"),f={weather:{text:t("dashboard","Weather"),icon:"icon-weather-status"},status:{text:t("dashboard","Status"),icon:"icon-user-status-online"}},x={name:"DashboardApp",components:{NcButton:c(),Draggable:A(),NcModal:h(),Pencil:b.default},mixins:[g],data(){var t,n;return{isAdmin:(0,i.ts)().isAdmin,timer:new Date,registeredStatus:[],callbacks:{},callbacksStatus:{},allCallbacksStatus:{},statusInfo:f,enabledStatuses:(0,r.j)("dashboard","statuses"),panels:v,firstRun:C,displayName:null===(t=(0,i.ts)())||void 0===t?void 0:t.displayName,uid:null===(n=(0,i.ts)())||void 0===n?void 0:n.uid,layout:(0,r.j)("dashboard","layout").filter((t=>v[t])),modal:!1,appStoreUrl:(0,s.generateUrl)("/settings/apps/dashboard"),statuses:{}}},computed:{greeting(){const n=this.timer.getHours();let e;e=n>=22||n<5?"night":n>=18?"evening":n>=12?"afternoon":"morning";const a={morning:{generic:t("dashboard","Good morning"),withName:t("dashboard","Good morning, {name}",{name:this.displayName},void 0,{escape:!1})},afternoon:{generic:t("dashboard","Good afternoon"),withName:t("dashboard","Good afternoon, {name}",{name:this.displayName},void 0,{escape:!1})},evening:{generic:t("dashboard","Good evening"),withName:t("dashboard","Good evening, {name}",{name:this.displayName},void 0,{escape:!1})},night:{generic:t("dashboard","Hello"),withName:t("dashboard","Hello, {name}",{name:this.displayName},void 0,{escape:!1})}};return{text:this.displayName&&this.uid!==this.displayName?a[e].withName:a[e].generic}},isActive(){return t=>this.layout.indexOf(t.id)>-1},isStatusActive(){return t=>!(t in this.enabledStatuses)||this.enabledStatuses[t]},sortedAllStatuses(){return Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)},sortedPanels(){return Object.values(this.panels).sort(((t,n)=>{const e=this.layout.indexOf(t.id),a=this.layout.indexOf(n.id);return-1===e||-1===a?a-e||t.id-n.id:e-a||t.id-n.id}))},sortedRegisteredStatus(){return this.registeredStatus.slice().sort(this.sortStatuses)}},watch:{callbacks(){this.rerenderPanels()},callbacksStatus(){for(const t in this.callbacksStatus){const n=this.$refs["status-"+t];this.statuses[t]&&this.statuses[t].mounted||(n?(this.callbacksStatus[t](n[0]),o.default.set(this.statuses,t,{mounted:!0})):m.error("Failed to register panel in the frontend as no backend data was provided for "+t))}}},mounted(){this.updateSkipLink(),window.addEventListener("scroll",this.handleScroll),setInterval((()=>{this.timer=new Date}),3e4),this.firstRun&&window.addEventListener("scroll",this.disableFirstrunHint)},destroyed(){window.removeEventListener("scroll",this.handleScroll)},methods:{register(t,n){o.default.set(this.callbacks,t,n)},registerStatus(t,n){o.default.set(this.allCallbacksStatus,t,n),this.isStatusActive(t)&&(this.registeredStatus.push(t),this.$nextTick((()=>{o.default.set(this.callbacksStatus,t,n)})))},rerenderPanels(){for(const t in this.callbacks){const n=this.$refs[t];-1!==this.layout.indexOf(t)&&(this.panels[t]&&this.panels[t].mounted||(n?(this.callbacks[t](n[0],{widget:this.panels[t]}),o.default.set(this.panels[t],"mounted",!0)):m.error("Failed to register panel in the frontend as no backend data was provided for "+t)))}},saveLayout(){l.default.post((0,s.generateUrl)("/apps/dashboard/layout"),{layout:this.layout.join(",")})},saveStatuses(){l.default.post((0,s.generateUrl)("/apps/dashboard/statuses"),{statuses:JSON.stringify(this.enabledStatuses)})},showModal(){this.modal=!0,this.firstRun=!1},closeModal(){this.modal=!1},updateCheckbox(t,n){const e=this.layout.indexOf(t.id);!n&&e>-1?this.layout.splice(e,1):this.layout.push(t.id),o.default.set(this.panels[t.id],"mounted",!1),this.saveLayout(),this.$nextTick((()=>this.rerenderPanels()))},disableFirstrunHint(){window.removeEventListener("scroll",this.disableFirstrunHint),setTimeout((()=>{this.firstRun=!1}),1e3)},updateSkipLink(){document.getElementsByClassName("skip-navigation")[0].setAttribute("href","#app-dashboard")},updateStatusCheckbox(t,n){n?this.enableStatus(t):this.disableStatus(t)},enableStatus(t){this.enabledStatuses[t]=!0,this.registerStatus(t,this.allCallbacksStatus[t]),this.saveStatuses()},disableStatus(t){this.enabledStatuses[t]=!1;const n=this.registeredStatus.findIndex((n=>n===t));-1!==n&&(this.registeredStatus.splice(n,1),o.default.set(this.statuses,t,{mounted:!1}),this.$nextTick((()=>{o.default.delete(this.callbacksStatus,t)}))),this.saveStatuses()},sortStatuses(t,n){const e=t.toLowerCase(),a=n.toLowerCase();return e>a?1:e<a?-1:0},handleScroll(){window.scrollY>70?document.body.classList.add("dashboard--scrolled"):document.body.classList.remove("dashboard--scrolled")}}};var k=a(93379),w=a.n(k),y=a(7795),_=a.n(y),S=a(90569),B=a.n(S),D=a(3565),O=a.n(D),N=a(19216),j=a.n(N),E=a(44589),F=a.n(E),T=a(71627),G={};G.styleTagTransform=F(),G.setAttributes=O(),G.insert=B().bind(null,"head"),G.domAPI=_(),G.insertStyleElement=j(),w()(T.Z,G),T.Z&&T.Z.locals&&T.Z.locals;var I=a(72144),z={};z.styleTagTransform=F(),z.setAttributes=O(),z.insert=B().bind(null,"head"),z.domAPI=_(),z.insertStyleElement=j(),w()(I.Z,z),I.Z&&I.Z.locals&&I.Z.locals;const M=(0,a(51900).Z)(x,(function(){var t=this,n=t._self._c;return n("div",{attrs:{id:"app-dashboard"}},[n("h2",[t._v(t._s(t.greeting.text))]),t._v(" "),n("ul",{staticClass:"statuses"},t._l(t.sortedRegisteredStatus,(function(t){return n("li",{key:t,attrs:{id:"status-"+t}},[n("div",{ref:"status-"+t,refInFor:!0})])})),0),t._v(" "),n("Draggable",t._b({staticClass:"panels",attrs:{handle:".panel--header"},on:{end:t.saveLayout},model:{value:t.layout,callback:function(n){t.layout=n},expression:"layout"}},"Draggable",{swapThreshold:.3,delay:500,delayOnTouchOnly:!0,touchStartThreshold:3},!1),t._l(t.layout,(function(e){return n("div",{key:t.panels[e].id,staticClass:"panel"},[n("div",{staticClass:"panel--header"},[n("h2",[n("div",{class:t.panels[e].iconClass,attrs:{"aria-labelledby":"panel--header--icon--description","aria-hidden":"true",role:"img"}}),t._v("\n\t\t\t\t\t"+t._s(t.panels[e].title)+"\n\t\t\t\t")]),t._v(" "),n("span",{staticClass:"hidden-visually",attrs:{id:"panel--header--icon--description"}},[t._v(" "+t._s(t.t("dashboard",'"{title} icon"',{title:t.panels[e].title}))+" ")])]),t._v(" "),n("div",{staticClass:"panel--content",class:{loading:!t.panels[e].mounted}},[n("div",{ref:t.panels[e].id,refInFor:!0,attrs:{"data-id":t.panels[e].id}})])])})),0),t._v(" "),n("div",{staticClass:"footer"},[n("NcButton",{on:{click:t.showModal},scopedSlots:t._u([{key:"icon",fn:function(){return[n("Pencil",{attrs:{size:20}})]},proxy:!0}])},[t._v("\n\t\t\t"+t._s(t.t("dashboard","Customize"))+"\n\t\t")])],1),t._v(" "),t.modal?n("NcModal",{attrs:{size:"large"},on:{close:t.closeModal}},[n("div",{staticClass:"modal__content"},[n("h3",[t._v(t._s(t.t("dashboard","Edit widgets")))]),t._v(" "),n("ol",{staticClass:"panels"},t._l(t.sortedAllStatuses,(function(e){return n("li",{key:e,class:"panel-"+e},[n("input",{staticClass:"checkbox",attrs:{id:"status-checkbox-"+e,type:"checkbox"},domProps:{checked:t.isStatusActive(e)},on:{input:function(n){return t.updateStatusCheckbox(e,n.target.checked)}}}),t._v(" "),n("label",{attrs:{for:"status-checkbox-"+e}},[n("div",{class:t.statusInfo[e].icon,attrs:{"aria-hidden":"true",role:"img"}}),t._v("\n\t\t\t\t\t\t"+t._s(t.statusInfo[e].text)+"\n\t\t\t\t\t")])])})),0),t._v(" "),n("Draggable",t._b({staticClass:"panels",attrs:{tag:"ol",handle:".draggable"},on:{end:t.saveLayout},model:{value:t.layout,callback:function(n){t.layout=n},expression:"layout"}},"Draggable",{swapThreshold:.3,delay:500,delayOnTouchOnly:!0,touchStartThreshold:3},!1),t._l(t.sortedPanels,(function(e){return n("li",{key:e.id,class:"panel-"+e.id},[n("input",{staticClass:"checkbox",attrs:{id:"panel-checkbox-"+e.id,type:"checkbox"},domProps:{checked:t.isActive(e)},on:{input:function(n){return t.updateCheckbox(e,n.target.checked)}}}),t._v(" "),n("label",{class:{draggable:t.isActive(e)},attrs:{for:"panel-checkbox-"+e.id}},[n("div",{class:e.iconClass,attrs:{"aria-hidden":"true",role:"img"}}),t._v("\n\t\t\t\t\t\t"+t._s(e.title)+"\n\t\t\t\t\t")])])})),0),t._v(" "),t.isAdmin?n("a",{staticClass:"button",attrs:{href:t.appStoreUrl}},[t._v(t._s(t.t("dashboard","Get more widgets from the App Store")))]):t._e(),t._v(" "),n("h3",[t._v(t._s(t.t("dashboard","Weather service")))]),t._v(" "),n("p",[t._v("\n\t\t\t\t"+t._s(t.t("dashboard","For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information."))+"\n\t\t\t")]),t._v(" "),n("p",{staticClass:"credits--end"},[n("a",{attrs:{href:"https://api.met.no/doc/TermsOfService",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","Weather data from Met.no")))]),t._v(",\n\t\t\t\t"),n("a",{attrs:{href:"https://wiki.osmfoundation.org/wiki/Privacy_Policy",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","geocoding with Nominatim")))]),t._v(",\n\t\t\t\t"),n("a",{attrs:{href:"https://www.opentopodata.org/#public-api",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","elevation data from OpenTopoData")))]),t._v(".\n\t\t\t")])],1)]):t._e()],1)}),[],!1,null,"4b63a425",null).exports;var L=a(31352),P=a(15168),U=a.n(P);a.nc=btoa((0,i.IH)()),o.default.directive("Tooltip",U()),o.default.prototype.t=L.Iu,window.OCA.Files||(window.OCA.Files={}),Object.assign(window.OCA.Files,{App:{fileList:{filesClient:OC.Files.getClient()}}},window.OCA.Files);const W=new(o.default.extend(M))({}).$mount("#app-content-vue");window.OCA.Dashboard={register:(t,n)=>W.register(t,n),registerStatus:(t,n)=>W.registerStatus(t,n)}},71627:(t,n,e)=>{e.d(n,{Z:()=>r});var a=e(87537),o=e.n(a),s=e(23645),i=e.n(s)()(o());i.push([t.id,"#app-dashboard[data-v-4b63a425]{width:100%;min-height:100%;background-size:cover;background-position:center center;background-repeat:no-repeat;background-attachment:fixed}#app-dashboard>h2[data-v-4b63a425]{color:var(--color-primary-text);text-align:center;font-size:32px;line-height:130%;padding:1rem 0}.panels[data-v-4b63a425]{width:auto;margin:auto;max-width:1800px;display:flex;justify-content:center;flex-direction:row;align-items:flex-start;flex-wrap:wrap}.panel[data-v-4b63a425],.panels>div[data-v-4b63a425]{width:320px;max-width:100%;margin:16px;align-self:stretch;background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);border-radius:var(--border-radius-large)}#body-user.theme--highcontrast .panel[data-v-4b63a425],#body-user.theme--highcontrast .panels>div[data-v-4b63a425]{border:2px solid var(--color-border)}.panel.sortable-ghost[data-v-4b63a425],.panels>div.sortable-ghost[data-v-4b63a425]{opacity:.1}.panel>.panel--header[data-v-4b63a425],.panels>div>.panel--header[data-v-4b63a425]{display:flex;z-index:1;top:50px;padding:16px;cursor:grab}.panel>.panel--header[data-v-4b63a425],.panel>.panel--header[data-v-4b63a425] *,.panels>div>.panel--header[data-v-4b63a425],.panels>div>.panel--header[data-v-4b63a425] *{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.panel>.panel--header[data-v-4b63a425]:active,.panels>div>.panel--header[data-v-4b63a425]:active{cursor:grabbing}.panel>.panel--header a[data-v-4b63a425],.panels>div>.panel--header a[data-v-4b63a425]{flex-grow:1}.panel>.panel--header>h2[data-v-4b63a425],.panels>div>.panel--header>h2[data-v-4b63a425]{display:block;align-items:center;flex-grow:1;margin:0;font-size:20px;line-height:24px;font-weight:bold;padding:16px 8px;height:56px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:grab}.panel>.panel--header>h2 div[data-v-4b63a425],.panels>div>.panel--header>h2 div[data-v-4b63a425]{background-size:32px;width:32px;height:32px;margin-right:16px;background-position:center;float:left}.panel>.panel--content[data-v-4b63a425],.panels>div>.panel--content[data-v-4b63a425]{margin:0 16px 16px 16px;height:424px;overflow:visible}@media only screen and (max-width: 709px){.panel>.panel--content[data-v-4b63a425],.panels>div>.panel--content[data-v-4b63a425]{height:auto}}.footer[data-v-4b63a425]{display:flex;justify-content:center;transition:bottom var(--animation-slow) ease-in-out;padding:1rem 0}.edit-panels[data-v-4b63a425]{display:inline-block;margin:auto;background-position:16px center;padding:12px 16px;padding-left:36px;border-radius:var(--border-radius-pill);max-width:200px;opacity:1;text-align:center}.button[data-v-4b63a425],.button-vue[data-v-4b63a425],.edit-panels[data-v-4b63a425],.statuses[data-v-4b63a425] .action-item .action-item__menutoggle,.statuses[data-v-4b63a425] .action-item.action-item--open .action-item__menutoggle{background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);opacity:1 !important}.button[data-v-4b63a425]:hover,.button[data-v-4b63a425]:focus,.button[data-v-4b63a425]:active,.button-vue[data-v-4b63a425]:hover,.button-vue[data-v-4b63a425]:focus,.button-vue[data-v-4b63a425]:active,.edit-panels[data-v-4b63a425]:hover,.edit-panels[data-v-4b63a425]:focus,.edit-panels[data-v-4b63a425]:active,.statuses[data-v-4b63a425] .action-item .action-item__menutoggle:hover,.statuses[data-v-4b63a425] .action-item .action-item__menutoggle:focus,.statuses[data-v-4b63a425] .action-item .action-item__menutoggle:active,.statuses[data-v-4b63a425] .action-item.action-item--open .action-item__menutoggle:hover,.statuses[data-v-4b63a425] .action-item.action-item--open .action-item__menutoggle:focus,.statuses[data-v-4b63a425] .action-item.action-item--open .action-item__menutoggle:active{background-color:var(--color-background-hover) !important}.button[data-v-4b63a425]:focus-visible,.button-vue[data-v-4b63a425]:focus-visible,.edit-panels[data-v-4b63a425]:focus-visible,.statuses[data-v-4b63a425] .action-item .action-item__menutoggle:focus-visible,.statuses[data-v-4b63a425] .action-item.action-item--open .action-item__menutoggle:focus-visible{box-shadow:0 0 0 2px var(--color-main-text) !important}.modal__content[data-v-4b63a425]{padding:32px 16px;text-align:center}.modal__content ol[data-v-4b63a425]{display:flex;flex-direction:row;justify-content:center;list-style-type:none;padding-bottom:16px}.modal__content li label[data-v-4b63a425]{position:relative;display:block;padding:48px 16px 14px 16px;margin:8px;width:140px;background-color:var(--color-background-hover);border:2px solid var(--color-main-background);border-radius:var(--border-radius-large);text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.modal__content li label div[data-v-4b63a425]{position:absolute;top:16px;width:24px;height:24px;background-size:24px}.modal__content li label[data-v-4b63a425]:hover{border-color:var(--color-primary)}.modal__content li:not(.panel-status) label div[data-v-4b63a425]{filter:var(--background-invert-if-dark)}.modal__content li input[type=checkbox].checkbox+label[data-v-4b63a425]:before{position:absolute;right:12px;top:16px}.modal__content li input:focus+label[data-v-4b63a425]{border-color:var(--color-primary)}.modal__content h3[data-v-4b63a425]{font-weight:bold}.modal__content h3[data-v-4b63a425]:not(:first-of-type){margin-top:64px}.modal__content .button[data-v-4b63a425]{display:inline-block;padding:10px 16px;margin:0}.modal__content p[data-v-4b63a425]{max-width:650px;margin:0 auto}.modal__content p a[data-v-4b63a425]:hover,.modal__content p a[data-v-4b63a425]:focus{border-bottom:2px solid var(--color-border)}.modal__content .credits--end[data-v-4b63a425]{padding-bottom:32px;color:var(--color-text-maxcontrast)}.modal__content .credits--end a[data-v-4b63a425]{color:var(--color-text-maxcontrast)}.flip-list-move[data-v-4b63a425]{transition:transform var(--animation-slow)}.statuses[data-v-4b63a425]{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap;margin-bottom:36px}.statuses>li[data-v-4b63a425]{margin:8px}","",{version:3,sources:["webpack://./apps/dashboard/src/DashboardApp.vue"],names:[],mappings:"AACA,gCACC,UAAA,CACA,eAAA,CACA,qBAAA,CACA,iCAAA,CACA,2BAAA,CACA,2BAAA,CAEA,mCACC,+BAAA,CACA,iBAAA,CACA,cAAA,CACA,gBAAA,CACA,cAAA,CAIF,yBACC,UAAA,CACA,WAAA,CACA,gBAAA,CACA,YAAA,CACA,sBAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CAGD,qDACC,WAAA,CACA,cAAA,CACA,WAAA,CACA,kBAAA,CACA,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,wCAAA,CAEA,mHACC,oCAAA,CAGD,mFACE,UAAA,CAGF,mFACC,YAAA,CACA,SAAA,CACA,QAAA,CACA,YAAA,CACA,WAAA,CAEA,0KACC,0BAAA,CACA,wBAAA,CACA,uBAAA,CACA,qBAAA,CACA,oBAAA,CACA,gBAAA,CAGD,iGACC,eAAA,CAGD,uFACC,WAAA,CAGD,yFACC,aAAA,CACA,kBAAA,CACA,WAAA,CACA,QAAA,CACA,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,gBAAA,CACA,WAAA,CACA,kBAAA,CACA,eAAA,CACA,sBAAA,CACA,WAAA,CACA,iGACC,oBAAA,CACA,UAAA,CACA,WAAA,CACA,iBAAA,CACA,0BAAA,CACA,UAAA,CAKH,qFACC,uBAAA,CACA,YAAA,CAEA,gBAAA,CAID,0CACC,qFACC,WAAA,CAAA,CAKH,yBACC,YAAA,CACA,sBAAA,CACA,mDAAA,CACA,cAAA,CAGD,8BACC,oBAAA,CACA,WAAA,CACA,+BAAA,CACA,iBAAA,CACA,iBAAA,CACA,uCAAA,CACA,eAAA,CACA,SAAA,CACA,iBAAA,CAGD,wOAKC,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,oBAAA,CAEA,uxBAGC,yDAAA,CAED,8SACC,sDAAA,CAIF,iCACC,iBAAA,CACA,iBAAA,CAEA,oCACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,oBAAA,CACA,mBAAA,CAGA,0CACC,iBAAA,CACA,aAAA,CACA,2BAAA,CACA,UAAA,CACA,WAAA,CACA,8CAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CACA,eAAA,CACA,sBAAA,CACA,kBAAA,CAEA,8CACC,iBAAA,CACA,QAAA,CACA,UAAA,CACA,WAAA,CACA,oBAAA,CAGD,gDACC,iCAAA,CAKF,iEACC,uCAAA,CAGD,+EACC,iBAAA,CACA,UAAA,CACA,QAAA,CAGD,sDACC,iCAAA,CAIF,oCACC,gBAAA,CAEA,wDACC,eAAA,CAKF,yCACC,oBAAA,CACA,iBAAA,CACA,QAAA,CAGD,mCACC,eAAA,CACA,aAAA,CAEA,sFAEC,2CAAA,CAIF,+CACC,mBAAA,CACA,mCAAA,CAEA,iDACC,mCAAA,CAKH,iCACC,0CAAA,CAGD,2BACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACA,kBAAA,CAEA,8BACC,UAAA",sourcesContent:["\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1800px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\talign-self: stretch;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > li {\n\t\tmargin: 8px;\n\t}\n}\n"],sourceRoot:""}]);const r=i},72144:(t,n,e)=>{e.d(n,{Z:()=>r});var a=e(87537),o=e.n(a),s=e(23645),i=e.n(s)()(o());i.push([t.id,"\nhtml, body {\n\tbackground-attachment: fixed;\n}\n#body-user #header {\n\tposition: fixed;\n}\n#content {\n\toverflow: auto;\n}\n","",{version:3,sources:["webpack://./apps/dashboard/src/DashboardApp.vue"],names:[],mappings:";AA2nBA;CACA,4BAAA;AACA;AAEA;CACA,eAAA;AACA;AAEA;CACA,cAAA;AACA",sourcesContent:["<template>\n\t<div id=\"app-dashboard\">\n\t\t<h2>{{ greeting.text }}</h2>\n\t\t<ul class=\"statuses\">\n\t\t\t<li v-for=\"status in sortedRegisteredStatus\"\n\t\t\t\t:id=\"'status-' + status\"\n\t\t\t\t:key=\"status\">\n\t\t\t\t<div :ref=\"'status-' + status\" />\n\t\t\t</li>\n\t\t</ul>\n\n\t\t<Draggable v-model=\"layout\"\n\t\t\tclass=\"panels\"\n\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\thandle=\".panel--header\"\n\t\t\t@end=\"saveLayout\">\n\t\t\t<div v-for=\"panelId in layout\" :key=\"panels[panelId].id\" class=\"panel\">\n\t\t\t\t<div class=\"panel--header\">\n\t\t\t\t\t<h2>\n\t\t\t\t\t\t<div aria-labelledby=\"panel--header--icon--description\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t:class=\"panels[panelId].iconClass\"\n\t\t\t\t\t\t\trole=\"img\" />\n\t\t\t\t\t\t{{ panels[panelId].title }}\n\t\t\t\t\t</h2>\n\t\t\t\t\t<span id=\"panel--header--icon--description\" class=\"hidden-visually\"> {{ t('dashboard', '\"{title} icon\"', { title: panels[panelId].title }) }} </span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"panel--content\" :class=\"{ loading: !panels[panelId].mounted }\">\n\t\t\t\t\t<div :ref=\"panels[panelId].id\" :data-id=\"panels[panelId].id\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Draggable>\n\n\t\t<div class=\"footer\">\n\t\t\t<NcButton @click=\"showModal\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('dashboard', 'Customize') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcModal v-if=\"modal\" size=\"large\" @close=\"closeModal\">\n\t\t\t<div class=\"modal__content\">\n\t\t\t\t<h3>{{ t('dashboard', 'Edit widgets') }}</h3>\n\t\t\t\t<ol class=\"panels\">\n\t\t\t\t\t<li v-for=\"status in sortedAllStatuses\" :key=\"status\" :class=\"'panel-' + status\">\n\t\t\t\t\t\t<input :id=\"'status-checkbox-' + status\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isStatusActive(status)\"\n\t\t\t\t\t\t\t@input=\"updateStatusCheckbox(status, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'status-checkbox-' + status\">\n\t\t\t\t\t\t\t<div :class=\"statusInfo[status].icon\" aria-hidden=\"true\" role=\"img\" />\n\t\t\t\t\t\t\t{{ statusInfo[status].text }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</ol>\n\t\t\t\t<Draggable v-model=\"layout\"\n\t\t\t\t\tclass=\"panels\"\n\t\t\t\t\ttag=\"ol\"\n\t\t\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\t\t\thandle=\".draggable\"\n\t\t\t\t\t@end=\"saveLayout\">\n\t\t\t\t\t<li v-for=\"panel in sortedPanels\" :key=\"panel.id\" :class=\"'panel-' + panel.id\">\n\t\t\t\t\t\t<input :id=\"'panel-checkbox-' + panel.id\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isActive(panel)\"\n\t\t\t\t\t\t\t@input=\"updateCheckbox(panel, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'panel-checkbox-' + panel.id\" :class=\"{ draggable: isActive(panel) }\">\n\t\t\t\t\t\t\t<div :class=\"panel.iconClass\" aria-hidden=\"true\" role=\"img\" />\n\t\t\t\t\t\t\t{{ panel.title }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</Draggable>\n\n\t\t\t\t<a v-if=\"isAdmin\" :href=\"appStoreUrl\" class=\"button\">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>\n\n\t\t\t\t<h3>{{ t('dashboard', 'Weather service') }}</h3>\n\t\t\t\t<p>\n\t\t\t\t\t{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}\n\t\t\t\t</p>\n\t\t\t\t<p class=\"credits--end\">\n\t\t\t\t\t<a href=\"https://api.met.no/doc/TermsOfService\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'Weather data from Met.no') }}</a>,\n\t\t\t\t\t<a href=\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,\n\t\t\t\t\t<a href=\"https://www.opentopodata.org/#public-api\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcModal>\n\t</div>\n</template>\n\n<script>\nimport { generateUrl } from '@nextcloud/router'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { loadState } from '@nextcloud/initial-state'\nimport axios from '@nextcloud/axios'\nimport NcButton from '@nextcloud/vue/dist/Components/NcButton.js'\nimport Draggable from 'vuedraggable'\nimport NcModal from '@nextcloud/vue/dist/Components/NcModal.js'\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\nimport Vue from 'vue'\n\nimport isMobile from './mixins/isMobile.js'\n\nconst panels = loadState('dashboard', 'panels')\nconst firstRun = loadState('dashboard', 'firstRun')\n\nconst statusInfo = {\n\tweather: {\n\t\ttext: t('dashboard', 'Weather'),\n\t\ticon: 'icon-weather-status',\n\t},\n\tstatus: {\n\t\ttext: t('dashboard', 'Status'),\n\t\ticon: 'icon-user-status-online',\n\t},\n}\n\nexport default {\n\tname: 'DashboardApp',\n\tcomponents: {\n\t\tNcButton,\n\t\tDraggable,\n\t\tNcModal,\n\t\tPencil,\n\t},\n\tmixins: [\n\t\tisMobile,\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tisAdmin: getCurrentUser().isAdmin,\n\t\t\ttimer: new Date(),\n\t\t\tregisteredStatus: [],\n\t\t\tcallbacks: {},\n\t\t\tcallbacksStatus: {},\n\t\t\tallCallbacksStatus: {},\n\t\t\tstatusInfo,\n\t\t\tenabledStatuses: loadState('dashboard', 'statuses'),\n\t\t\tpanels,\n\t\t\tfirstRun,\n\t\t\tdisplayName: getCurrentUser()?.displayName,\n\t\t\tuid: getCurrentUser()?.uid,\n\t\t\tlayout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),\n\t\t\tmodal: false,\n\t\t\tappStoreUrl: generateUrl('/settings/apps/dashboard'),\n\t\t\tstatuses: {},\n\t\t}\n\t},\n\tcomputed: {\n\t\tgreeting() {\n\t\t\tconst time = this.timer.getHours()\n\n\t\t\t// Determine part of the day\n\t\t\tlet partOfDay\n\t\t\tif (time >= 22 || time < 5) {\n\t\t\t\tpartOfDay = 'night'\n\t\t\t} else if (time >= 18) {\n\t\t\t\tpartOfDay = 'evening'\n\t\t\t} else if (time >= 12) {\n\t\t\t\tpartOfDay = 'afternoon'\n\t\t\t} else {\n\t\t\t\tpartOfDay = 'morning'\n\t\t\t}\n\n\t\t\t// Define the greetings\n\t\t\tconst good = {\n\t\t\t\tmorning: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good morning'),\n\t\t\t\t\twithName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tafternoon: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good afternoon'),\n\t\t\t\t\twithName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tevening: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good evening'),\n\t\t\t\t\twithName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tnight: {\n\t\t\t\t\t// Don't use \"Good night\" as it's not a greeting\n\t\t\t\t\tgeneric: t('dashboard', 'Hello'),\n\t\t\t\t\twithName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\t// Figure out which greeting to show\n\t\t\tconst shouldShowName = this.displayName && this.uid !== this.displayName\n\t\t\treturn { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }\n\t\t},\n\n\t\tisActive() {\n\t\t\treturn (panel) => this.layout.indexOf(panel.id) > -1\n\t\t},\n\t\tisStatusActive() {\n\t\t\treturn (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]\n\t\t},\n\n\t\tsortedAllStatuses() {\n\t\t\treturn Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)\n\t\t},\n\t\tsortedPanels() {\n\t\t\treturn Object.values(this.panels).sort((a, b) => {\n\t\t\t\tconst indexA = this.layout.indexOf(a.id)\n\t\t\t\tconst indexB = this.layout.indexOf(b.id)\n\t\t\t\tif (indexA === -1 || indexB === -1) {\n\t\t\t\t\treturn indexB - indexA || a.id - b.id\n\t\t\t\t}\n\t\t\t\treturn indexA - indexB || a.id - b.id\n\t\t\t})\n\t\t},\n\t\tsortedRegisteredStatus() {\n\t\t\treturn this.registeredStatus.slice().sort(this.sortStatuses)\n\t\t},\n\t},\n\n\twatch: {\n\t\tcallbacks() {\n\t\t\tthis.rerenderPanels()\n\t\t},\n\t\tcallbacksStatus() {\n\t\t\tfor (const app in this.callbacksStatus) {\n\t\t\t\tconst element = this.$refs['status-' + app]\n\t\t\t\tif (this.statuses[app] && this.statuses[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacksStatus[app](element[0])\n\t\t\t\t\tVue.set(this.statuses, app, { mounted: true })\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.updateSkipLink()\n\t\twindow.addEventListener('scroll', this.handleScroll)\n\n\t\tsetInterval(() => {\n\t\t\tthis.timer = new Date()\n\t\t}, 30000)\n\n\t\tif (this.firstRun) {\n\t\t\twindow.addEventListener('scroll', this.disableFirstrunHint)\n\t\t}\n\t},\n\tdestroyed() {\n\t\twindow.removeEventListener('scroll', this.handleScroll)\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Method to register panels that will be called by the integrating apps\n\t\t *\n\t\t * @param {string} app The unique app id for the widget\n\t\t * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter\n\t\t */\n\t\tregister(app, callback) {\n\t\t\tVue.set(this.callbacks, app, callback)\n\t\t},\n\t\tregisterStatus(app, callback) {\n\t\t\t// always save callbacks in case user enables the status later\n\t\t\tVue.set(this.allCallbacksStatus, app, callback)\n\t\t\t// register only if status is enabled or missing from config\n\t\t\tif (this.isStatusActive(app)) {\n\t\t\t\tthis.registeredStatus.push(app)\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.set(this.callbacksStatus, app, callback)\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\trerenderPanels() {\n\t\t\tfor (const app in this.callbacks) {\n\t\t\t\tconst element = this.$refs[app]\n\t\t\t\tif (this.layout.indexOf(app) === -1) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (this.panels[app] && this.panels[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacks[app](element[0], {\n\t\t\t\t\t\twidget: this.panels[app],\n\t\t\t\t\t})\n\t\t\t\t\tVue.set(this.panels[app], 'mounted', true)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsaveLayout() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/layout'), {\n\t\t\t\tlayout: this.layout.join(','),\n\t\t\t})\n\t\t},\n\t\tsaveStatuses() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/statuses'), {\n\t\t\t\tstatuses: JSON.stringify(this.enabledStatuses),\n\t\t\t})\n\t\t},\n\t\tshowModal() {\n\t\t\tthis.modal = true\n\t\t\tthis.firstRun = false\n\t\t},\n\t\tcloseModal() {\n\t\t\tthis.modal = false\n\t\t},\n\t\tupdateCheckbox(panel, currentValue) {\n\t\t\tconst index = this.layout.indexOf(panel.id)\n\t\t\tif (!currentValue && index > -1) {\n\t\t\t\tthis.layout.splice(index, 1)\n\n\t\t\t} else {\n\t\t\t\tthis.layout.push(panel.id)\n\t\t\t}\n\t\t\tVue.set(this.panels[panel.id], 'mounted', false)\n\t\t\tthis.saveLayout()\n\t\t\tthis.$nextTick(() => this.rerenderPanels())\n\t\t},\n\t\tdisableFirstrunHint() {\n\t\t\twindow.removeEventListener('scroll', this.disableFirstrunHint)\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.firstRun = false\n\t\t\t}, 1000)\n\t\t},\n\t\tupdateSkipLink() {\n\t\t\t// Make sure \"Skip to main content\" link points to the app content\n\t\t\tdocument.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')\n\t\t},\n\t\tupdateStatusCheckbox(app, checked) {\n\t\t\tif (checked) {\n\t\t\t\tthis.enableStatus(app)\n\t\t\t} else {\n\t\t\t\tthis.disableStatus(app)\n\t\t\t}\n\t\t},\n\t\tenableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = true\n\t\t\tthis.registerStatus(app, this.allCallbacksStatus[app])\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tdisableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = false\n\t\t\tconst i = this.registeredStatus.findIndex((s) => s === app)\n\t\t\tif (i !== -1) {\n\t\t\t\tthis.registeredStatus.splice(i, 1)\n\t\t\t\tVue.set(this.statuses, app, { mounted: false })\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.delete(this.callbacksStatus, app)\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tsortStatuses(a, b) {\n\t\t\tconst al = a.toLowerCase()\n\t\t\tconst bl = b.toLowerCase()\n\t\t\treturn al > bl\n\t\t\t\t? 1\n\t\t\t\t: al < bl\n\t\t\t\t\t? -1\n\t\t\t\t\t: 0\n\t\t},\n\t\thandleScroll() {\n\t\t\tif (window.scrollY > 70) {\n\t\t\t\tdocument.body.classList.add('dashboard--scrolled')\n\t\t\t} else {\n\t\t\t\tdocument.body.classList.remove('dashboard--scrolled')\n\t\t\t}\n\t\t},\n\t},\n}\n<\/script>\n\n<style lang=\"scss\" scoped>\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1800px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\talign-self: stretch;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > li {\n\t\tmargin: 8px;\n\t}\n}\n</style>\n<style>\nhtml, body {\n\tbackground-attachment: fixed;\n}\n\n#body-user #header {\n\tposition: fixed;\n}\n\n#content {\n\toverflow: auto;\n}\n</style>\n"],sourceRoot:""}]);const r=i}},a={};function o(t){var n=a[t];if(void 0!==n)return n.exports;var s=a[t]={id:t,loaded:!1,exports:{}};return e[t].call(s.exports,s,s.exports,o),s.loaded=!0,s.exports}o.m=e,n=[],o.O=(t,e,a,s)=>{if(!e){var i=1/0;for(c=0;c<n.length;c++){e=n[c][0],a=n[c][1],s=n[c][2];for(var r=!0,l=0;l<e.length;l++)(!1&s||i>=s)&&Object.keys(o.O).every((t=>o.O[t](e[l])))?e.splice(l--,1):(r=!1,s<i&&(i=s));if(r){n.splice(c--,1);var d=a();void 0!==d&&(t=d)}}return t}s=s||0;for(var c=n.length;c>0&&n[c-1][2]>s;c--)n[c]=n[c-1];n[c]=[e,a,s]},o.n=t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return o.d(n,{a:n}),n},o.d=(t,n)=>{for(var e in n)o.o(n,e)&&!o.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),o.o=(t,n)=>Object.prototype.hasOwnProperty.call(t,n),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.nmd=t=>(t.paths=[],t.children||(t.children=[]),t),o.j=4773,(()=>{o.b=document.baseURI||self.location.href;var t={4773:0};o.O.j=n=>0===t[n];var n=(n,e)=>{var a,s,i=e[0],r=e[1],l=e[2],d=0;if(i.some((n=>0!==t[n]))){for(a in r)o.o(r,a)&&(o.m[a]=r[a]);if(l)var c=l(o)}for(n&&n(e);d<i.length;d++)s=i[d],o.o(t,s)&&t[s]&&t[s][0](),t[s]=0;return o.O(c)},e=self.webpackChunknextcloud=self.webpackChunknextcloud||[];e.forEach(n.bind(null,0)),e.push=n.bind(null,e.push.bind(e))})(),o.nc=void 0;var s=o.O(void 0,[7874],(()=>o(41701)));s=o.O(s)})();
  3. //# sourceMappingURL=dashboard-main.js.map?v=e61bba8ae03598e46848