[Automatic] Updated UI files
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
fc50e6ccc7
commit
2f4a6330cf
24 changed files with 27 additions and 27 deletions
|
@ -1 +1 @@
|
|||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/fonts/poppins.css"><title>platypush</title><script defer="defer" src="/static/js/chunk-vendors.4103dd5b.js"></script><script defer="defer" src="/static/js/app.1a17830d.js"></script><link href="/static/css/chunk-vendors.d510eff2.css" rel="stylesheet"><link href="/static/css/app.eb00bbd1.css" rel="stylesheet"><link rel="icon" type="image/svg+xml" href="/img/icons/favicon.svg"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#ffffff"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="Platypush"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#ffffff"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/fonts/poppins.css"><title>platypush</title><script defer="defer" src="/static/js/chunk-vendors.918726ad.js"></script><script defer="defer" src="/static/js/app.54130bae.js"></script><link href="/static/css/chunk-vendors.d510eff2.css" rel="stylesheet"><link href="/static/css/app.eb00bbd1.css" rel="stylesheet"><link rel="icon" type="image/svg+xml" href="/img/icons/favicon.svg"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#ffffff"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="Platypush"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#ffffff"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
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
2
platypush/backend/http/webapp/dist/static/js/7594.a27f56fd.js
vendored
Normal file
2
platypush/backend/http/webapp/dist/static/js/7594.a27f56fd.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platypush/backend/http/webapp/dist/static/js/7594.a27f56fd.js.map
vendored
Normal file
1
platypush/backend/http/webapp/dist/static/js/7594.a27f56fd.js.map
vendored
Normal file
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
File diff suppressed because one or more lines are too long
1
platypush/backend/http/webapp/dist/static/js/chunk-vendors.918726ad.js.map
vendored
Normal file
1
platypush/backend/http/webapp/dist/static/js/chunk-vendors.918726ad.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
(self["webpackChunkplatypush"]=self["webpackChunkplatypush"]||[]).push([[945],{4272:function(e,s,t){"use strict";t.r(s),t.d(s,{default:function(){return I}});var r=t(641),a=t(33);function n(e,s,t,n,o,l){const d=(0,r.g2)("Loading"),i=(0,r.g2)("Widget"),u=(0,r.g2)("Row");return(0,r.uX)(),(0,r.CE)(r.FK,null,[o.loading?((0,r.uX)(),(0,r.Wv)(d,{key:0})):(0,r.Q3)("",!0),(0,r.Lk)("div",{id:"dashboard",class:(0,a.C4)(["col-12",l.classes]),style:(0,a.Tr)(o.style)},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(o.rows,((e,s)=>((0,r.uX)(),(0,r.Wv)(u,{key:s,class:(0,a.C4)(e.class),style:(0,a.Tr)(e.style)},{default:(0,r.k6)((()=>[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.widgets,((e,s)=>((0,r.uX)(),(0,r.Wv)(r.PR,{key:s},[(0,r.bF)(i,{style:(0,a.Tr)(e.style),class:(0,a.C4)(e.class)},{default:(0,r.k6)((()=>[((0,r.uX)(),(0,r.Wv)((0,r.$y)(e.component),(0,r.v6)({ref_for:!0},l.getWidgetProps(e)),null,16))])),_:2},1032,["style","class"])],1024)))),128))])),_:2},1032,["class","style"])))),128))],6)],64)}var o=t(953),l=t(2002),d=t(9828);function i(e,s,t,n,o,l){return(0,r.uX)(),(0,r.CE)("div",{class:(0,a.C4)(["row",l.classes]),style:(0,a.Tr)(t.style)},[(0,r.RG)(e.$slots,"default",{},void 0,!0)],6)}var u={name:"Row",props:{class:{type:String,required:!1,default:""},style:{type:String,required:!1,default:""}},computed:{classes(){return this.class}}},c=t(6262);const p=(0,c.A)(u,[["render",i],["__scopeId","data-v-1b4663f2"]]);var h=p;function f(e,s,t,n,o,l){return(0,r.uX)(),(0,r.CE)("div",{style:(0,a.Tr)(t.style),class:(0,a.C4)(l.classes)},[(0,r.RG)(e.$slots,"default",{},void 0,!0)],6)}var m={name:"Widget",props:{style:{type:String,required:!1,default:""},class:{type:String,required:!1,default:""}},computed:{classes(){return(this.class?.length?this.class.split(" "):["col-3"]).concat(["widget","column"])}}};const y=(0,c.A)(m,[["render",f],["__scopeId","data-v-5df52982"]]);var g=y,v={name:"Dashboard",mixins:[l.A],components:{Widget:g,Loading:d.A,Row:h},props:{refreshSeconds:{type:Number,required:!1,default:0}},data(){return{rows:[],loading:!1,style:void 0,class:void 0}},computed:{classes(){return this.class},_refreshSeconds(){return parseFloat(this.refreshSeconds)||0}},methods:{getWidgetProps(e){const s={...e.props};return s.class&&delete s.class,s},parseTemplate(e){const s=(new DOMParser).parseFromString(e,"text/xml").childNodes[0],a=this;this.style=s.attributes.style?.nodeValue,this.class=s.attributes.class?.nodeValue,this.rows=[...s.getElementsByTagName("Row")].map((e=>({style:e.attributes.style?.nodeValue,class:e.attributes.class?.nodeValue,widgets:[...e.children].map((e=>{const s=(0,o.IJ)((0,r.$V)((()=>t(3422)(`./${e.nodeName}/Index`)))),n=e.attributes.style?.nodeValue,l=e.attributes.class?.nodeValue,d=[...e.attributes].reduce(((e,s)=>("style"!==s.nodeName&&(e[s.nodeName]=s.nodeValue),e)),{content:e.innerHTML}),i={component:s,style:n,class:l,props:d||{}};return a.$options.components[e.nodeName]=s,i}))}))),this.loading=!1},async refreshDashboard(){this.loading=!0,this.widgets=[];const e=this.$route.params.name,s=await this.request("config.get_dashboard",{name:e});s||this.notifyError(`Dashboard ${e} not found`),this.parseTemplate(s)}},mounted(){if(this.refreshDashboard(),this._refreshSeconds){const e=this;setInterval((()=>{e.refreshDashboard()}),parseInt((1e3*this._refreshSeconds).toFixed(0)))}}};const b=(0,c.A)(v,[["render",n],["__scopeId","data-v-462fad8c"]]);var I=b},3422:function(e,s,t){var r={"./Calendar/Index":[5953,5953],"./Camera/Index":[3851,3851],"./Component/Index":[8466,9769,5184,8466],"./DateTime/Index":[1391,5788,1391],"./DateTimeWeather/Index":[3923,5188,5788,3923],"./ImageCarousel/Index":[5688,5188,5788,3307],"./Music/Index":[9426,5184,6157,9426],"./Plugin/Index":[7896,7896],"./RssNews/Index":[7222,7222],"./Weather/Index":[5188,5188]};function a(e){if(!t.o(r,e))return Promise.resolve().then((function(){var s=new Error("Cannot find module '"+e+"'");throw s.code="MODULE_NOT_FOUND",s}));var s=r[e],a=s[0];return Promise.all(s.slice(1).map(t.e)).then((function(){return t(a)}))}a.keys=function(){return Object.keys(r)},a.id=3422,e.exports=a}}]);
|
||||
//# sourceMappingURL=dashboard.baaf75c5.js.map
|
||||
//# sourceMappingURL=dashboard.e7fad48a.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
"use strict";(self["webpackChunkplatypush"]=self["webpackChunkplatypush"]||[]).push([[6966],{3787:function(e,t,s){s.r(t),s.d(t,{default:function(){return A}});var r=s(641),a=s(33);const i={key:1,class:"login-container"},n={class:"row"},o=["type","disabled"],l={class:"row"},d=["type","disabled"],u={key:0,class:"row"},c=["disabled"],h={key:1,class:"row"},p=["disabled"],g={class:"row buttons"},k=["disabled"],m={key:2,class:"auth-error"};function y(e,t,s,y,b,f){const w=(0,r.g2)("Loading");return b.initialized?((0,r.uX)(),(0,r.CE)("div",i,[b.isAuthenticated?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.CE)("form",{key:0,class:"login",method:"POST",onSubmit:t[0]||(t[0]=(...e)=>f.submitForm&&f.submitForm(...e))},[t[1]||(t[1]=(0,r.Lk)("div",{class:"header"},[(0,r.Lk)("span",{class:"logo"},[(0,r.Lk)("img",{src:"/logo.svg",alt:"logo"})]),(0,r.Lk)("span",{class:"text"},"Platypush")],-1)),(0,r.Lk)("div",n,[(0,r.Lk)("label",null,[(0,r.Lk)("input",{type:b.requires2fa?"hidden":"text",name:"username",disabled:b.authenticating,placeholder:"Username",ref:"username"},null,8,o)])]),(0,r.Lk)("div",l,[(0,r.Lk)("label",null,[(0,r.Lk)("input",{type:b.requires2fa?"hidden":"password",name:"password",disabled:b.authenticating,placeholder:"Password"},null,8,d)])]),b.requires2fa?((0,r.uX)(),(0,r.CE)("div",u,[(0,r.Lk)("label",null,[(0,r.Lk)("input",{type:"text",name:"code",disabled:b.authenticating,placeholder:"2FA code",ref:"code"},null,8,c)])])):(0,r.Q3)("",!0),s.register?((0,r.uX)(),(0,r.CE)("div",h,[(0,r.Lk)("label",null,[(0,r.Lk)("input",{type:"password",name:"confirm_password",disabled:b.authenticating,placeholder:"Confirm password"},null,8,p)])])):(0,r.Q3)("",!0),(0,r.Lk)("div",g,[(0,r.Lk)("button",{type:"submit",class:(0,a.C4)(["btn btn-primary",{loading:b.authenticating}]),disabled:b.authenticating},[b.authenticating?((0,r.uX)(),(0,r.Wv)(w,{key:0})):(0,r.Q3)("",!0),(0,r.eW)(" "+(0,a.v_)(s.register?"Register":"Login"),1)],10,k)]),t[2]||(t[2]=(0,r.Lk)("div",{class:"row pull-right"},[(0,r.Lk)("label",{class:"checkbox"},[(0,r.Lk)("input",{type:"checkbox",name:"remember"}),(0,r.eW)(" Keep me logged in on this device ")])],-1)),b.authError?((0,r.uX)(),(0,r.CE)("div",m,(0,a.v_)(b.authError),1)):(0,r.Q3)("",!0)],32))])):((0,r.uX)(),(0,r.Wv)(w,{key:0}))}var b=s(9828),f=s(2002),w=s(4335),L={name:"Login",mixins:[f.A],components:{Loading:b.A},props:{register:{type:Boolean,required:!1,default:!1}},computed:{redirect(){return this.$route.query.redirect?.length?this.$route.query.redirect:"/"}},data(){return{authError:null,authenticating:!1,isAuthenticated:!1,initialized:!1,requires2fa:!1}},methods:{async submitForm(e){e.preventDefault();const t=e.target,s=new FormData(t),r="/auth?type="+(this.register?"register":"login");if(this.register&&s.get("password")!==s.get("confirm_password"))this.authError="Passwords don't match";else{this.authError=null;try{const e=await w.A.post(r,s),t=e?.data?.session_token;if(t){const s=e?.data?.expires_at?new Date(e.data.expires_at):null;this.isAuthenticated=!0,this.setCookie("session_token",t,{expires:s}),window.location.href=e.redirect||this.redirect}else this.authError="Invalid credentials"}catch(e){"MISSING_OTP_CODE"===e?.response?.data?.error?(this.requires2fa=!0,this.$nextTick((()=>{this.$refs.code?.focus()}))):(this.authError=e?.response?.data?.message||e?.response?.data?.error||e?.message||e?.toString(),401===e?.response?.status?this.authError=this.authError||"Invalid credentials":(this.authError=this.authError||"An error occurred while processing the request",e?.response?console.error(e.response.status,e.response.data):console.error(e)))}}},async checkAuth(){try{const e=await w.A.get("/auth");e.data.session_token&&(this.isAuthenticated=!0,window.location.href=e.redirect||this.redirect)}catch(e){this.isAuthenticated=!1}finally{this.initialized=!0}}},async created(){await this.checkAuth()},async mounted(){this.$nextTick((()=>{this.$refs.username?.focus()}))}},v=s(6262);const E=(0,v.A)(L,[["render",y],["__scopeId","data-v-60300e68"]]);var A=E}}]);
|
||||
//# sourceMappingURL=login.40a43dab.js.map
|
||||
//# sourceMappingURL=login.de738cfb.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
"use strict";(self["webpackChunkplatypush"]=self["webpackChunkplatypush"]||[]).push([[2178],{3554:function(n,u,t){t.r(u),t.d(u,{default:function(){return s}});var e=t(641);function r(n,u,t,r,a,c){return(0,e.uX)(),(0,e.CE)("h1",null,"Object not found")}var a={name:"NotFound"},c=t(6262);const o=(0,c.A)(a,[["render",r]]);var s=o}}]);
|
||||
//# sourceMappingURL=notfound.0257d086.js.map
|
||||
//# sourceMappingURL=notfound.baabd642.js.map
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"static/js/notfound.0257d086.js","mappings":"sNACEA,EAAAA,EAAAA,IAAyB,UAArB,mB,CAIN,OACEC,KAAM,Y,UCDR,MAAMC,GAA2B,OAAgB,EAAQ,CAAC,CAAC,SAASC,KAEpE,O","sources":["webpack://platypush/./src/views/NotFound.vue","webpack://platypush/./src/views/NotFound.vue?0aab"],"sourcesContent":["<template>\n <h1>Object not found</h1>\n</template>\n\n<script>\nexport default {\n name: \"NotFound\"\n}\n</script>\n\n","import { render } from \"./NotFound.vue?vue&type=template&id=49501f4d\"\nimport script from \"./NotFound.vue?vue&type=script&lang=js\"\nexport * from \"./NotFound.vue?vue&type=script&lang=js\"\n\nimport exportComponent from \"../../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__"],"names":["_createElementBlock","name","__exports__","render"],"sourceRoot":""}
|
||||
{"version":3,"file":"static/js/notfound.baabd642.js","mappings":"sNACEA,EAAAA,EAAAA,IAAyB,UAArB,mB,CAIN,OACEC,KAAM,Y,UCDR,MAAMC,GAA2B,OAAgB,EAAQ,CAAC,CAAC,SAASC,KAEpE,O","sources":["webpack://platypush/./src/views/NotFound.vue","webpack://platypush/./src/views/NotFound.vue?0aab"],"sourcesContent":["<template>\n <h1>Object not found</h1>\n</template>\n\n<script>\nexport default {\n name: \"NotFound\"\n}\n</script>\n\n","import { render } from \"./NotFound.vue?vue&type=template&id=49501f4d\"\nimport script from \"./NotFound.vue?vue&type=script&lang=js\"\nexport * from \"./NotFound.vue?vue&type=script&lang=js\"\n\nimport exportComponent from \"../../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__"],"names":["_createElementBlock","name","__exports__","render"],"sourceRoot":""}
|
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
|
@ -1,2 +1,2 @@
|
|||
"use strict";(self["webpackChunkplatypush"]=self["webpackChunkplatypush"]||[]).push([[8224,6966],{3787:function(e,t,r){r.r(t),r.d(t,{default:function(){return A}});var s=r(641),a=r(33);const i={key:1,class:"login-container"},n={class:"row"},o=["type","disabled"],u={class:"row"},d=["type","disabled"],l={key:0,class:"row"},c=["disabled"],h={key:1,class:"row"},p=["disabled"],g={class:"row buttons"},k=["disabled"],m={key:2,class:"auth-error"};function f(e,t,r,f,y,b){const w=(0,s.g2)("Loading");return y.initialized?((0,s.uX)(),(0,s.CE)("div",i,[y.isAuthenticated?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("form",{key:0,class:"login",method:"POST",onSubmit:t[0]||(t[0]=(...e)=>b.submitForm&&b.submitForm(...e))},[t[1]||(t[1]=(0,s.Lk)("div",{class:"header"},[(0,s.Lk)("span",{class:"logo"},[(0,s.Lk)("img",{src:"/logo.svg",alt:"logo"})]),(0,s.Lk)("span",{class:"text"},"Platypush")],-1)),(0,s.Lk)("div",n,[(0,s.Lk)("label",null,[(0,s.Lk)("input",{type:y.requires2fa?"hidden":"text",name:"username",disabled:y.authenticating,placeholder:"Username",ref:"username"},null,8,o)])]),(0,s.Lk)("div",u,[(0,s.Lk)("label",null,[(0,s.Lk)("input",{type:y.requires2fa?"hidden":"password",name:"password",disabled:y.authenticating,placeholder:"Password"},null,8,d)])]),y.requires2fa?((0,s.uX)(),(0,s.CE)("div",l,[(0,s.Lk)("label",null,[(0,s.Lk)("input",{type:"text",name:"code",disabled:y.authenticating,placeholder:"2FA code",ref:"code"},null,8,c)])])):(0,s.Q3)("",!0),r.register?((0,s.uX)(),(0,s.CE)("div",h,[(0,s.Lk)("label",null,[(0,s.Lk)("input",{type:"password",name:"confirm_password",disabled:y.authenticating,placeholder:"Confirm password"},null,8,p)])])):(0,s.Q3)("",!0),(0,s.Lk)("div",g,[(0,s.Lk)("button",{type:"submit",class:(0,a.C4)(["btn btn-primary",{loading:y.authenticating}]),disabled:y.authenticating},[y.authenticating?((0,s.uX)(),(0,s.Wv)(w,{key:0})):(0,s.Q3)("",!0),(0,s.eW)(" "+(0,a.v_)(r.register?"Register":"Login"),1)],10,k)]),t[2]||(t[2]=(0,s.Lk)("div",{class:"row pull-right"},[(0,s.Lk)("label",{class:"checkbox"},[(0,s.Lk)("input",{type:"checkbox",name:"remember"}),(0,s.eW)(" Keep me logged in on this device ")])],-1)),y.authError?((0,s.uX)(),(0,s.CE)("div",m,(0,a.v_)(y.authError),1)):(0,s.Q3)("",!0)],32))])):((0,s.uX)(),(0,s.Wv)(w,{key:0}))}var y=r(9828),b=r(2002),w=r(4335),v={name:"Login",mixins:[b.A],components:{Loading:y.A},props:{register:{type:Boolean,required:!1,default:!1}},computed:{redirect(){return this.$route.query.redirect?.length?this.$route.query.redirect:"/"}},data(){return{authError:null,authenticating:!1,isAuthenticated:!1,initialized:!1,requires2fa:!1}},methods:{async submitForm(e){e.preventDefault();const t=e.target,r=new FormData(t),s="/auth?type="+(this.register?"register":"login");if(this.register&&r.get("password")!==r.get("confirm_password"))this.authError="Passwords don't match";else{this.authError=null;try{const e=await w.A.post(s,r),t=e?.data?.session_token;if(t){const r=e?.data?.expires_at?new Date(e.data.expires_at):null;this.isAuthenticated=!0,this.setCookie("session_token",t,{expires:r}),window.location.href=e.redirect||this.redirect}else this.authError="Invalid credentials"}catch(e){"MISSING_OTP_CODE"===e?.response?.data?.error?(this.requires2fa=!0,this.$nextTick((()=>{this.$refs.code?.focus()}))):(this.authError=e?.response?.data?.message||e?.response?.data?.error||e?.message||e?.toString(),401===e?.response?.status?this.authError=this.authError||"Invalid credentials":(this.authError=this.authError||"An error occurred while processing the request",e?.response?console.error(e.response.status,e.response.data):console.error(e)))}}},async checkAuth(){try{const e=await w.A.get("/auth");e.data.session_token&&(this.isAuthenticated=!0,window.location.href=e.redirect||this.redirect)}catch(e){this.isAuthenticated=!1}finally{this.initialized=!0}}},async created(){await this.checkAuth()},async mounted(){this.$nextTick((()=>{this.$refs.username?.focus()}))}},L=r(6262);const E=(0,L.A)(v,[["render",f],["__scopeId","data-v-60300e68"]]);var A=E},3036:function(e,t,r){r.r(t),r.d(t,{default:function(){return d}});var s=r(641);function a(e,t,r,a,i,n){const o=(0,s.g2)("Login");return(0,s.uX)(),(0,s.Wv)(o,{register:!0})}var i=r(3787),n={name:"Register",mixins:[i["default"]],components:{Login:i["default"]},props:{register:{type:Boolean,required:!1,default:!0}}},o=r(6262);const u=(0,o.A)(n,[["render",a]]);var d=u}}]);
|
||||
//# sourceMappingURL=register.ae516b65.js.map
|
||||
//# sourceMappingURL=register.558a674a.js.map
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue