Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • uffd/uffd
  • rixx/uffd
  • thies/uffd
  • leona/uffd
  • strifel/uffd
  • thies/uffd-2
6 results
Select Git revision
Loading items
Show changes
Showing
with 142 additions and 57 deletions
/**
* @popperjs/core v2.0.4 - MIT License
*/
"use strict";!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).Popper={})}(this,(function(e){function t(e){return{width:(e=e.getBoundingClientRect()).width,height:e.height,top:e.top,right:e.right,bottom:e.bottom,left:e.left,x:e.left,y:e.top}}function n(e){return"[object Window]"!=={}.toString.call(e)?(e=e.ownerDocument)?e.defaultView:window:e}function r(e){return{scrollLeft:(e=n(e)).pageXOffset,scrollTop:e.pageYOffset}}function o(e){return e instanceof n(e).Element}function i(e){return e instanceof n(e).HTMLElement}function a(e){return e?(e.nodeName||"").toLowerCase():null}function s(e,o,s){void 0===s&&(s=!1),e=t(e);var f={scrollLeft:0,scrollTop:0},p={x:0,y:0};return s||("body"!==a(o)&&(f=o!==n(o)&&i(o)?{scrollLeft:o.scrollLeft,scrollTop:o.scrollTop}:r(o)),i(o)&&((p=t(o)).x+=o.clientLeft,p.y+=o.clientTop)),{x:e.left+f.scrollLeft-p.x,y:e.top+f.scrollTop-p.y,width:e.width,height:e.height}}function f(e){return{x:e.offsetLeft,y:e.offsetTop,width:e.offsetWidth,height:e.offsetHeight}}function p(e){return"html"===a(e)?e:e.parentNode||e.host||document.ownerDocument||document.documentElement}function c(e){return n(e).getComputedStyle(e)}function u(e,t){void 0===t&&(t=[]);var r=function e(t){if(0<=["html","body","#document"].indexOf(a(t)))return t.ownerDocument.body;if(i(t)){var n=c(t);if(/auto|scroll|overlay|hidden/.test(n.overflow+n.overflowY+n.overflowX))return t}return e(p(t))}(e);return r=(e="body"===a(r))?n(r):r,t=t.concat(r),e?t:t.concat(u(p(r)))}function d(e){var t;return!i(e)||!(t=e.offsetParent)||void 0!==window.InstallTrigger&&"fixed"===c(t).position?null:t}function l(e){var t=n(e);for(e=d(e);e&&0<=["table","td","th"].indexOf(a(e));)e=d(e);return e&&"body"===a(e)&&"static"===c(e).position?t:e||t}function m(e){var t=new Map,n=new Set,r=[];return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||function e(o){n.add(o.name),[].concat(o.requires||[],o.requiresIfExists||[]).forEach((function(r){n.has(r)||(r=t.get(r))&&e(r)})),r.push(o)}(e)})),r}function h(e){var t;return function(){return t||(t=new Promise((function(n){Promise.resolve().then((function(){t=void 0,n(e())}))}))),t}}function v(e){return e.split("-")[0]}function g(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];return!t.some((function(e){return!(e&&"function"==typeof e.getBoundingClientRect)}))}function b(e){void 0===e&&(e={});var t=e.defaultModifiers,n=void 0===t?[]:t,r=void 0===(e=e.defaultOptions)?H:e;return function(e,t,i){function a(){c.forEach((function(e){return e()})),c=[]}void 0===i&&(i=r);var p={placement:"bottom",orderedModifiers:[],options:Object.assign({},H,{},r),modifiersData:{},elements:{reference:e,popper:t},attributes:{},styles:{}},c=[],d=!1,v={state:p,setOptions:function(i){return a(),p.options=Object.assign({},r,{},p.options,{},i),p.scrollParents={reference:o(e)?u(e):[],popper:u(t)},i=function(e){var t=m(e);return A.reduce((function(e,n){return e.concat(t.filter((function(e){return e.phase===n})))}),[])}([].concat(p.options.modifiers.filter((function(e){return!n.find((function(t){return t.name===e.name}))})),n.map((function(e){return Object.assign({},e,{},p.options.modifiers.find((function(t){return t.name===e.name})))})))),p.orderedModifiers=i.filter((function(e){return e.enabled})),p.orderedModifiers.forEach((function(e){var t=e.name,n=e.options;n=void 0===n?{}:n,"function"==typeof(e=e.effect)&&(t=e({state:p,name:t,instance:v,options:n}),c.push(t||function(){}))})),v.update()},forceUpdate:function(){if(!d){var e=p.elements,t=e.reference;if(g(t,e=e.popper))for(p.rects={reference:s(t,l(e),"fixed"===p.options.strategy),popper:f(e)},p.reset=!1,p.placement=p.options.placement,p.orderedModifiers.forEach((function(e){return p.modifiersData[e.name]=Object.assign({},e.data)})),t=0;t<p.orderedModifiers.length;t++)if(!0===p.reset)p.reset=!1,t=-1;else{var n=p.orderedModifiers[t];e=n.fn;var r=n.options;r=void 0===r?{}:r,n=n.name,"function"==typeof e&&(p=e({state:p,options:r,name:n,instance:v})||p)}}},update:h((function(){return new Promise((function(e){v.forceUpdate(),e(p)}))})),destroy:function(){a(),d=!0}};return g(e,t)?(v.setOptions(i).then((function(e){!d&&i.onFirstUpdate&&i.onFirstUpdate(e)})),v):v}}function y(e){return 0<=["top","bottom"].indexOf(e)?"x":"y"}function x(e){var t=e.reference,n=e.element,r=(e=e.placement)?v(e):null;e=e?e.split("-")[1]:null;var o=t.x+t.width/2-n.width/2,i=t.y+t.height/2-n.height/2;switch(r){case"top":o={x:o,y:t.y-n.height};break;case"bottom":o={x:o,y:t.y+t.height};break;case"right":o={x:t.x+t.width,y:i};break;case"left":o={x:t.x-n.width,y:i};break;default:o={x:t.x,y:t.y}}if(null!=(r=r?y(r):null))switch(i="y"===r?"height":"width",e){case"start":o[r]=Math.floor(o[r])-Math.floor(t[i]/2-n[i]/2);break;case"end":o[r]=Math.floor(o[r])+Math.ceil(t[i]/2-n[i]/2)}return o}function w(e){var t,r=e.popper,o=e.popperRect,i=e.placement,a=e.offsets,s=e.position,f=e.gpuAcceleration,p=e.adaptive,c=window.devicePixelRatio||1;e=Math.round(a.x*c)/c||0,c=Math.round(a.y*c)/c||0;var u=a.hasOwnProperty("x");a=a.hasOwnProperty("y");var d,m="left",h="top";if(p){var v=l(r);v===n(r)&&(v=r.ownerDocument.documentElement),"top"===i&&(h="bottom",c-=v.clientHeight-o.height,c*=f?1:-1),"left"===i&&(m="right",e-=v.clientWidth-o.width,e*=f?1:-1)}return r=Object.assign({position:s},p&&F),f?Object.assign({},r,((d={})[h]=a?"0":"",d[m]=u?"0":"",d.transform=2>(window.devicePixelRatio||1)?"translate("+e+"px, "+c+"px)":"translate3d("+e+"px, "+c+"px, 0)",d)):Object.assign({},r,((t={})[h]=a?c+"px":"",t[m]=u?e+"px":"",t.transform="",t))}function O(e){return e.replace(/left|right|bottom|top/g,(function(e){return I[e]}))}function M(e){return e.replace(/start|end/g,(function(e){return N[e]}))}function D(e,t){var n=!(!t.getRootNode||!t.getRootNode().host);if(e.contains(t))return!0;if(n)do{if(t&&e.isSameNode(t))return!0;t=t.parentNode||t.host}while(t);return!1}function j(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function E(e,o){if("viewport"===o)e=j({width:(e=n(e)).innerWidth,height:e.innerHeight,x:0,y:0});else if(i(o))e=t(o);else{var a=e.ownerDocument.documentElement;e=n(a),o=r(a),(a=s(a.ownerDocument.documentElement,e)).height=Math.max(a.height,e.innerHeight),a.width=Math.max(a.width,e.innerWidth),a.x=-o.scrollLeft,a.y=-o.scrollTop,e=j(a)}return e}function k(e,t,r){return t="clippingParents"===t?function(e){var t=u(e),n=0<=["absolute","fixed"].indexOf(c(e).position)&&i(e)?l(e):e;return o(n)?t.filter((function(e){return o(e)&&D(e,n)})):[]}(e):[].concat(t),(r=(r=[].concat(t,[r])).reduce((function(t,r){var o=E(e,r),s=n(r=i(r)?r:e.ownerDocument.documentElement),f=i(r)?c(r):{};parseFloat(f.borderTopWidth);var p=parseFloat(f.borderRightWidth)||0,u=parseFloat(f.borderBottomWidth)||0,d=parseFloat(f.borderLeftWidth)||0;f="html"===a(r);var l=r.clientWidth+p,m=r.clientHeight+u;return u=r.clientTop,p=r.clientLeft>d?p:f?s.innerWidth-l:r.offsetWidth-l,s=f?s.innerHeight-m:r.offsetHeight-m,r=r.clientLeft,t.top=Math.max(o.top+u,t.top),t.right=Math.min(o.right-p,t.right),t.bottom=Math.min(o.bottom-s,t.bottom),t.left=Math.max(o.left+r,t.left),t}),E(e,r[0]))).width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}function P(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},{},e)}function L(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function W(e,n){void 0===n&&(n={});var r=n;n=void 0===(n=r.placement)?e.placement:n;var i=r.boundary,a=void 0===i?"clippingParents":i,s=void 0===(i=r.rootBoundary)?"viewport":i;i=void 0===(i=r.elementContext)?"popper":i;var f=r.altBoundary,p=void 0!==f&&f;r=P("number"!=typeof(r=void 0===(r=r.padding)?0:r)?r:L(r,T));var c=e.elements.reference;f=e.rects.popper,a=k(o(p=e.elements[p?"popper"===i?"reference":"popper":i])?p:e.elements.popper.ownerDocument.documentElement,a,s),p=x({reference:s=t(c),element:f,strategy:"absolute",placement:n}),f=j(Object.assign({},f,{},p)),s="popper"===i?f:s;var u={top:a.top-s.top+r.top,bottom:s.bottom-a.bottom+r.bottom,left:a.left-s.left+r.left,right:s.right-a.right+r.right};if(e=e.modifiersData.offset,"popper"===i&&e){var d=e[n];Object.keys(u).forEach((function(e){var t=0<=["right","bottom"].indexOf(e)?1:-1,n=0<=["top","bottom"].indexOf(e)?"y":"x";u[e]+=d[n]*t}))}return u}function B(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function R(e){return["top","right","bottom","left"].some((function(t){return 0<=e[t]}))}var T=["top","bottom","right","left"],q=T.reduce((function(e,t){return e.concat([t+"-start",t+"-end"])}),[]),S=[].concat(T,["auto"]).reduce((function(e,t){return e.concat([t,t+"-start",t+"-end"])}),[]),A="beforeRead read afterRead beforeMain main afterMain beforeWrite write afterWrite".split(" "),H={placement:"bottom",modifiers:[],strategy:"absolute"},C={passive:!0},F={top:"auto",right:"auto",bottom:"auto",left:"auto"},I={left:"right",right:"left",bottom:"top",top:"bottom"},N={start:"end",end:"start"},_=[{name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(e){var t=e.state,r=e.instance,o=(e=e.options).scroll,i=void 0===o||o,a=void 0===(e=e.resize)||e,s=n(t.elements.popper),f=[].concat(t.scrollParents.reference,t.scrollParents.popper);return i&&f.forEach((function(e){e.addEventListener("scroll",r.update,C)})),a&&s.addEventListener("resize",r.update,C),function(){i&&f.forEach((function(e){e.removeEventListener("scroll",r.update,C)})),a&&s.removeEventListener("resize",r.update,C)}},data:{}},{name:"popperOffsets",enabled:!0,phase:"read",fn:function(e){var t=e.state;t.modifiersData[e.name]=x({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})},data:{}},{name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(e){var t=e.state,n=e.options;e=void 0===(e=n.gpuAcceleration)||e,n=void 0===(n=n.adaptive)||n,e={placement:v(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:e},t.styles.popper=Object.assign({},t.styles.popper,{},w(Object.assign({},e,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:n}))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,{},w(Object.assign({},e,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})},data:{}},{name:"applyStyles",enabled:!0,phase:"write",fn:function(e){var t=e.state;Object.keys(t.elements).forEach((function(e){var n=t.styles[e]||{},r=t.attributes[e]||{},o=t.elements[e];i(o)&&a(o)&&(Object.assign(o.style,n),Object.keys(r).forEach((function(e){var t=r[e];!1===t?o.removeAttribute(e):o.setAttribute(e,!0===t?"":t)})))}))},effect:function(e){var t=e.state,n={position:"absolute",left:"0",top:"0",margin:"0"};return Object.assign(t.elements.popper.style,n),function(){Object.keys(t.elements).forEach((function(e){var r=t.elements[e],o=Object.keys(t.styles.hasOwnProperty(e)?Object.assign({},t.styles[e]):n);e=t.attributes[e]||{},o=o.reduce((function(e,t){var n;return Object.assign({},e,((n={})[String(t)]="",n))}),{}),i(r)&&a(r)&&(Object.assign(r.style,o),Object.keys(e).forEach((function(e){return r.removeAttribute(e)})))}))}},requires:["computeStyles"]},{name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(e){var t=e.state,n=e.name,r=void 0===(e=e.options.offset)?[0,0]:e,o=(e=S.reduce((function(e,n){var o=t.rects,i=v(n),a=0<=["left","top"].indexOf(i)?-1:1,s="function"==typeof r?r(Object.assign({},o,{placement:n})):r;return o=(o=s[0])||0,s=((s=s[1])||0)*a,i=0<=["left","right"].indexOf(i)?{x:s,y:o}:{x:o,y:s},e[n]=i,e}),{}))[t.placement],i=o.y;t.modifiersData.popperOffsets.x+=o.x,t.modifiersData.popperOffsets.y+=i,t.modifiersData[n]=e}},{name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options;if(e=e.name,!t.modifiersData[e]._skip){var r=n.fallbackPlacements,o=n.padding,i=n.boundary,a=n.rootBoundary,s=void 0===(n=n.flipVariations)||n,f=v(n=t.options.placement);r=r||(f!==n&&s?function(e){if("auto"===v(e))return[];var t=O(e);return[M(e),t,M(t)]}(n):[O(n)]);var p=function(e,t){var n=new Set;return e.filter((function(e){if(e=t(e),!n.has(e))return n.add(e),!0}))}([n].concat(r).reduce((function(e,n){return"auto"===v(n)?e.concat(function(e,t){void 0===t&&(t={});var n=t.boundary,r=t.rootBoundary,o=t.padding,i=t.flipVariations,a=t.placement.split("-")[1],s=(a?i?q:q.filter((function(e){return e.split("-")[1]===a})):T).reduce((function(t,i){return t[i]=W(e,{placement:i,boundary:n,rootBoundary:r,padding:o})[v(i)],t}),{});return Object.keys(s).sort((function(e,t){return s[e]-s[t]}))}(t,{placement:n,boundary:i,rootBoundary:a,padding:o,flipVariations:s})):e.concat(n)}),[]),(function(e){return e}));r=t.rects.reference,n=t.rects.popper;var c=new Map;f=!0;for(var u=p[0],d=0;d<p.length;d++){var l=p[d],m=v(l),h="start"===l.split("-")[1],g=0<=["top","bottom"].indexOf(m),b=g?"width":"height",y=W(t,{placement:l,boundary:i,rootBoundary:a,padding:o});if(h=g?h?"right":"left":h?"bottom":"top",r[b]>n[b]&&(h=O(h)),b=O(h),(m=[0>=y[m],0>=y[h],0>=y[b]]).every((function(e){return e}))){u=l,f=!1;break}c.set(l,m)}if(f)for(r=function(e){var t=p.find((function(t){if(t=c.get(t))return t.slice(0,e).every((function(e){return e}))}));if(t)return u=t,"break"},n=s?3:1;0<n&&"break"!==r(n);n--);t.placement!==u&&(t.modifiersData[e]._skip=!0,t.placement=u,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}},{name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options;e=e.name;var r=n.mainAxis,o=void 0===r||r;r=void 0!==(r=n.altAxis)&&r;var i=n.tether;i=void 0===i||i;var a=n.tetherOffset,s=void 0===a?0:a;n=W(t,{boundary:n.boundary,rootBoundary:n.rootBoundary,padding:n.padding}),a=v(t.placement);var p=t.placement.split("-")[1],c=!p,u=y(a);a="x"===u?"y":"x";var d=t.modifiersData.popperOffsets,l=t.rects.reference,m=t.rects.popper,h="function"==typeof s?s(Object.assign({},t.rects,{placement:t.placement})):s;if(s={x:0,y:0},o){var g="y"===u?"top":"left",b="y"===u?"bottom":"right",x="y"===u?"height":"width";o=d[u];var w=d[u]+n[g],O=d[u]-n[b],M=i?-m[x]/2:0,D="start"===p?l[x]:m[x];p="start"===p?-m[x]:-l[x],m=t.elements.arrow,m=i&&m?f(m):{width:0,height:0};var j=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0};g=j[g],b=j[b],m=Math.max(0,Math.min(Math.abs(l[x]-m[x]),m[x])),j=t.modifiersData.offset?t.modifiersData.offset[t.placement][u]:0,D=t.modifiersData.popperOffsets[u]+(c?l[x]/2-M-m-g-h:D-m-g-h)-j,c=t.modifiersData.popperOffsets[u]+(c?-l[x]/2+M+m+b+h:p+m+b+h)-j,i=Math.max(i?Math.min(w,D):w,Math.min(o,i?Math.max(O,c):O)),t.modifiersData.popperOffsets[u]=i,s[u]=i-o}r&&(r=d[a],i=Math.max(r+n["x"===u?"top":"left"],Math.min(r,r-n["x"===u?"bottom":"right"])),t.modifiersData.popperOffsets[a]=i,s[a]=i-r),t.modifiersData[e]=s},requiresIfExists:["offset"]},{name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state;e=e.name;var r=n.elements.arrow,o=n.modifiersData.popperOffsets,i=v(n.placement),a=y(i);if(i=0<=["left","right"].indexOf(i)?"height":"width",r){var s=n.modifiersData[e+"#persistent"].padding;r=f(r),o=Math.max(s["y"===a?"top":"left"],Math.min(n.rects.popper[i]/2-r[i]/2+((n.rects.reference[i]+n.rects.reference[a]-o[a]-n.rects.popper[i])/2-(o[a]-n.rects.reference[a])/2),n.rects.popper[i]-r[i]-s["y"===a?"bottom":"right"])),n.modifiersData[e]=((t={})[a]=o,t)}},effect:function(e){var t=e.state,n=e.options;e=e.name;var r=n.element;r=void 0===r?"[data-popper-arrow]":r,n=void 0===(n=n.padding)?0:n,("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&D(t.elements.popper,r)&&(t.elements.arrow=r,t.modifiersData[e+"#persistent"]={padding:P("number"!=typeof n?n:L(n,T))})},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]},{name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state;e=e.name;var n=t.rects.reference,r=t.rects.popper,o=t.modifiersData.preventOverflow,i=W(t,{elementContext:"reference"}),a=W(t,{altBoundary:!0});n=B(i,n),r=B(a,r,o),o=R(n),a=R(r),t.modifiersData[e]={referenceClippingOffsets:n,popperEscapeOffsets:r,isReferenceHidden:o,hasPopperEscaped:a},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":o,"data-popper-escaped":a})}}],U=b({defaultModifiers:_});e.createPopper=U,e.defaultModifiers=_,e.popperGenerator=b,Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=popper.min.js.map
.footer {
position: fixed;
bottom: 0;
width: 100%;
height: 2em;
line-height: 2em;
background-color: #f5f5f5;
}
.narrow-card {
background: #f7f7f7;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
padding: 30px;
}
.qrcode {
background: #ffffff;
}
@media (prefers-color-scheme: dark) {
.footer {
background-color: #23282d;
}
.narrow-card {
background: #292e33;
}
a {
color: #3395ff;
background-color: transparent
}
a:hover {
color: #0d82ff
}
.btn-link {
color: #3395ff;
}
.btn-link:hover {
color: #0d82ff;
}
.btn-link.disabled,
.btn-link:disabled {
color: #3395ff;
}
/* Dark theme breaks spinners (appears as full ring without animation) */
.spinner-border {
display: inline-block;
width: 2rem;
height: 2rem;
vertical-align: text-bottom;
border: 0.25em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
-webkit-animation: spinner-border .75s linear infinite;
animation: spinner-border .75s linear infinite;
}
.spinner-border-sm {
width: 1rem;
height: 1rem;
border-width: 0.2em;
}
}
.footer {
position: fixed;
bottom: 0;
width: 100%;
height: 2em;
line-height: 2em;
background-color: #f5f5f5;
}
class CleanupTask:
def __init__(self):
self.handlers = []
def handler(self, func):
self.handlers.append(func)
return func
def delete_by_attribute(self, attribute):
def decorator(cls):
@self.handler
def handler():
cls.query.filter(getattr(cls, attribute)).delete()
return cls
return decorator
def run(self):
for handler in self.handlers:
handler()
cleanup_task = CleanupTask()
......@@ -15,13 +15,18 @@ def register_template_helper(app):
@app.template_filter()
def qrcode_svg(content, **attrs): #pylint: disable=unused-variable
img = qrcode.make(content, image_factory=qrcode.image.svg.SvgPathImage, border=0)
img = qrcode.make(content, image_factory=qrcode.image.svg.SvgPathImage, border=4)
svg = img.get_image()
for key, value, in attrs.items():
svg.set(key, value)
buf = io.BytesIO()
img.save(buf)
return Markup(buf.getvalue().decode().replace('<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n', '').replace(' id="qr-path" ', ' '))
return Markup(
buf.getvalue().decode()
.replace('<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n', '')
.replace(' id="qr-path" ', ' ')
.replace('<svg ', '<svg class="qrcode" ')
)
@app.template_filter()
def datauri(data, mimetype='text/plain'): #pylint: disable=unused-variable
......
......@@ -2,7 +2,7 @@
{% block body %}
<div class="row mt-2 justify-content-center">
<div class="col-lg-6 col-md-10" style="background: #f7f7f7; box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); padding: 30px;">
<div class="col-lg-6 col-md-10 narrow-card">
<div class="text-center">
<img alt="branding logo" src="{{ config.get("BRANDING_LOGO_URL") }}" class="col-lg-8 col-md-12" >
</div>
......
......@@ -4,13 +4,14 @@
{% block head %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{% block title %}uffd{% endblock %}</title>
<title>{% block title %}{{ config['SITE_TITLE'] }}{% endblock %}</title>
<link href="{{ url_for('static', filename="bootstrap/bootstrap.min.css") }}" rel="stylesheet">
<link href="{{ url_for('static', filename="bootstrap/bootstrap-prefers-dark-color-only.min.css") }}" rel="stylesheet">
<link href="{{ url_for('static', filename="fa/css/all.css") }}" rel="stylesheet">
<link href="{{ url_for('static', filename="style.css") }}" rel="stylesheet">
<link href="{{ url_for('static', filename="style-1.css") }}" rel="stylesheet">
<script src="{{ url_for('static', filename="jquery/jquery-3.4.1.min.js") }}"></script>
<script src="{{ url_for('static', filename="popper/popper.min.js") }}"></script>
<script src="{{ url_for('static', filename="popper/popper-1.16.0.min.js") }}"></script>
<script src="{{ url_for('static', filename="bootstrap/bootstrap.min.js") }}"></script>
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/png">
......@@ -35,8 +36,8 @@
{%- endmacro %}
<nav class="navbar navbar-expand-md navbar-dark bg-dark static-top" >
<a class="navbar-brand" href="{{ url_for('index') }}">uffd</a>
{% if getnavbar() or request.user or config['LANGUAGES']|length > 1 %}
<a class="navbar-brand" href="{{ url_for('index') }}">{{ config['SITE_TITLE'] }}</a>
{% if getnavbar() or request.user or request.endpoint != 'session.login' or config['LANGUAGES']|length > 1 %}
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#baseNavbar" aria-controls="baseNavbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
......@@ -69,7 +70,7 @@
</ul>
{% endif %}
{% if request.user or config['LANGUAGES']|length > 1 %}
{% if request.user or request.endpoint != 'session.login' or config['LANGUAGES']|length > 1 %}
<ul class="navbar-nav ml-auto">
{% if config['LANGUAGES']|length > 1 %}
<li class="nav-item">
......@@ -99,6 +100,13 @@
{{_("Logout")}}
</a>
</li>
{% elif request.endpoint != 'session.login' %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for("session.login", ref=request.full_path) }}">
<span aria-hidden="true" class="fa fa-sign-in-alt"></span>
{{ _("Login") }}
</a>
</li>
{% endif %}
</ul>
{% endif %}
......@@ -110,9 +118,9 @@
{% block main %}
<main role="main" class="container mt-3">
<div class="row">
{% for message in get_flashed_messages() %}
{% for category, message in get_flashed_messages(with_categories=true) %}
<div class="col-12">
<div class="alert alert-primary" role="alert">{{ message }}</div>
<div class="alert alert-{{ 'danger' if category == 'error' else 'warning' if category == 'warning' else 'primary' }}" role="alert">{{ message }}</div>
</div>
{% endfor %}
</div>
......
......@@ -5,16 +5,16 @@
<div class="row justify-content-center">
<div class="col-lg-6 col-md-10 px-0">
<div class="row">
{% for message in get_flashed_messages() %}
{% for category, message in get_flashed_messages(with_categories=true) %}
<div class="col-12">
<div class="alert alert-primary" role="alert">{{ message }}</div>
<div class="alert alert-{{ 'danger' if category == 'error' else 'warning' if category == 'warning' else 'primary' }}" role="alert">{{ message }}</div>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-6 col-md-10" style="background: #f7f7f7; box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); padding: 30px;">
<div class="col-lg-6 col-md-10 narrow-card">
<div class="text-center">
<img alt="branding logo" src="{{ config.get("BRANDING_LOGO_URL") }}" class="col-lg-8 col-md-12" >
</div>
......
{% extends 'base.html' %}
{% block body %}
<form action="{{ url_for("group.update", id=group.id) }}" method="POST">
<form action="{{ url_for("group.update", id=group.id) }}" method="POST" autocomplete="off">
<div class="align-self-center">
<div class="clearfix pb-2 col">
<div class="float-sm-right">
......@@ -24,7 +24,10 @@
</div>
<div class="form-group col">
<label for="group-loginname">{{_("Name")}}</label>
<input type="text" class="form-control" id="group-loginname" name="name" value="{{ group.name or '' }}" {{ 'readonly' if group.id }}>
<input type="text" class="form-control" id="group-loginname" name="name" minlength=1 maxlength=32 pattern="[a-z0-9_-]*" value="{{ group.name or '' }}" {{ 'readonly' if group.id }}>
<small class="form-text text-muted">
{{_('At least one and at most 32 lower-case characters, digits, dashes ("-") or underscores ("_"). <b>Cannot be changed later!</b>')|safe}}
</small>
</div>
<div class="form-group col">
<label for="group-description">{{_("Description")}}</label>
......
......@@ -41,7 +41,7 @@
{% for role in invite.roles %}{{ ', ' if loop.index != 1 }}<i class="fas fa-key"></i>&thinsp;{{ role.name }}{% endfor %}
</td>
<td>
<span style="white-space: nowrap;">{{ invite.signups|selectattr('completed')|list|length }} <i class="fas fa-users" title="user registrations"></i></span>,
<span style="white-space: nowrap;">{{ invite.signups|selectattr('completed')|list|length }} <i class="fas fa-users" title="{{ _('user signups') }}"></i></span>,
<span style="white-space: nowrap;">{{ invite.grants|length }} <i class="fas fa-key" title="role grants"></i></span>
</td>
<td>
......@@ -56,9 +56,9 @@
{% elif not invite.active %}
{{_('Invalid')}}
{% elif invite.single_use %}
{{ _('Valid once, expires %(expiry_date)s', expiry_date=invite.valid_until.strftime('%Y-%m-%d')) }}
{{ _('Valid once, expires %(expiry_date)s', expiry_date=invite.valid_until|dateformat) }}
{% else %}
{{ _('Valid, expires %(expiry_date)s',expiry_date=invite.valid_until.strftime('%Y-%m-%d')) }}
{{ _('Valid, expires %(expiry_date)s', expiry_date=invite.valid_until|dateformat) }}
{% endif %}
</td>
<td class="text-right">
......@@ -83,8 +83,8 @@
<div class="modal-body">
<ul class="list-unstyled">
<li><b>{{_('Type:')}}</b> {% if invite.single_use %}{{_('Single-use')}}{% else %}{{_('Multi-use')}}{% endif %}</li>
<li><b>{{_('Created:')}}</b> {{ invite.created.strftime('%Y-%m-%d %H:%M:%S') }}</li>
<li><b>{{_('Expires:')}}</b> {{ invite.valid_until.strftime('%Y-%m-%d %H:%M:%S') }}</li>
<li><b>{{_('Created:')}}</b> {{ invite.created|datetimeformat }}</li>
<li><b>{{_('Expires:')}}</b> {{ invite.valid_until|datetimeformat }}</li>
<li><b>{{_('Permissions:')}}</b>
<ul>
{% if invite.allow_signup %}
......
{% extends 'base.html' %}
{% block body %}
<form action="{{ url_for("invite.new_submit") }}" method="POST" class="form">
<form action="{{ url_for("invite.new_submit") }}" method="POST" autocomplete="off" class="form">
<div class="form-group">
<label for="single-use">{{_('Link Type')}}</label>
<select class="form-control" id="single-use" name="single-use">
<option value="1">{{_('Valid for a single successful use')}}</option>
<option value="0">{{_('Multi-use')}}</option>
<option value="1" {{ 'selected' if request.values.get('single-use', '1') == '1' }}>{{_('Valid for a single successful use')}}</option>
<option value="0" {{ 'selected' if request.values.get('single-use', '1') == '0' }}>{{_('Multi-use')}}</option>
</select>
</div>
<div class="form-group">
<label for="valid-until">{{_('Valid Until')}}</label>
<input class="form-control" type="datetime-local" id="valid-until" name="valid-until" value="{{ (datetime.now() + timedelta(hours=36)).replace(hour=23, minute=59, second=59, microsecond=0).isoformat(timespec='minutes') }}">
<input class="form-control" type="datetime-local" id="valid-until" name="valid-until" value="{{ request.values.get('valid-until') or (datetime.now() + timedelta(hours=36)).replace(hour=23, minute=59).isoformat(timespec='minutes') }}" min="{{ datetime.now().isoformat(timespec='minutes') }}" max="{{ (datetime.now() + timedelta(days=config['INVITE_MAX_VALID_DAYS'])).isoformat(timespec='minutes') }}">
<small class="text-muted">{{_('Must be within the next %(max_valid_days)d days', max_valid_days=config['INVITE_MAX_VALID_DAYS'])}}</small>
</div>
{% if allow_signup %}
<div class="form-group">
<label for="allow-signup">{{_('Account Registration')}}</label>
<select class="form-control" id="allow-signup" name="allow-signup">
<option value="1">{{_('Link allows account registration')}}</option>
<option value="0">{{_('No account registration allowed')}}</option>
<option value="1" {{ 'selected' if request.values.get('allow-signup', '1') == '1' }}>{{_('Link allows account registration')}}</option>
<option value="0" {{ 'selected' if request.values.get('allow-signup', '1') == '0' }}>{{_('No account registration allowed')}}</option>
</select>
</div>
{% else %}
......
......@@ -18,9 +18,9 @@
</thead>
<tbody>
{% for mail in mails|sort(attribute="uid") %}
<tr id="mail-{{ mail.uid }}">
<tr id="mail-{{ mail.id }}">
<th scope="row">
<a href="{{ url_for("mail.show", uid=mail.uid) }}">
<a href="{{ url_for("mail.show", mail_id=mail.id) }}">
{{ mail.uid }}
</a>
</th>
......
{% extends 'base.html' %}
{% block body %}
<form action="{{ url_for("mail.update", uid=mail.uid) }}" method="POST">
<form action="{{ url_for("mail.update", mail_id=mail.id) }}" method="POST" autocomplete="off">
<div class="align-self-center">
<div class="form-group col">
<label for="mail-name">{{_('Name')}}</label>
<input type="text" class="form-control" id="mail-name" name="mail-uid" {% if mail.uid %} value="{{ mail.uid }}" readonly {% else %} value=""{% endif %}>
<input type="text" class="form-control" id="mail-name" name="mail-uid" {% if mail.id %} value="{{ mail.uid }}" readonly {% else %} value=""{% endif %}>
<small class="form-text text-muted">
</small>
</div>
......@@ -13,7 +13,7 @@
<label for="mail-receivers">{{_('Receiving addresses')}}</label>
<textarea rows="10" class="form-control" id="mail-receivers" name="mail-receivers">{{ mail.receivers|join('\n') }}</textarea>
<small class="form-text text-muted">
{{_('One address per line')}}
{{_('One address pattern (local+ext@domain, local@domain, local, @domain) per line. Only lower-case ASCII letters, digits and symbols.')}}
</small>
</div>
<div class="form-group col">
......@@ -26,8 +26,8 @@
<div class="form-group col">
<button type="submit" class="btn btn-primary"><i class="fa fa-save" aria-hidden="true"></i> {{_('Save')}}</button>
<a href="{{ url_for("mail.index") }}" class="btn btn-secondary">{{_('Cancel')}}</a>
{% if mail.uid %}
<a href="{{ url_for("mail.delete", uid=mail.uid) }}" class="btn btn-danger"><i class="fa fa-trash" aria-hidden="true"></i> {{_('Delete')}}</a>
{% if mail.id %}
<a href="{{ url_for("mail.delete", mail_id=mail.id) }}" class="btn btn-danger"><i class="fa fa-trash" aria-hidden="true"></i> {{_('Delete')}}</a>
{% else %}
<a href="#" class="btn btn-danger disabled"><i class="fa fa-trash" aria-hidden="true"></i> {{_('Delete')}}</a>
{% endif %}
......
......@@ -11,9 +11,9 @@
</noscript>
<p>{{_('While you successfully logged out of the Single-Sign-On service, you may still be logged in on these services:')}}</p>
<ul>
{% for client in clients if client.logout_urls %}
<li class="client" data-urls='{{ client.logout_urls|tojson }}'>
{{ client.client_id }}
{% for client in clients if client.logout_uris %}
<li class="client" data-urls='{{ client.logout_uris_json }}'>
{{ client.service.name }}
<span class="status-active spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<i class="status-success fas fa-check d-none"></i>
<i class="status-failed fas fa-exclamation d-none"></i>
......@@ -53,7 +53,6 @@ function logout_services() {
});
});
p = p.then(function () {
console.log('done', elem);
elem.find('.status-active').addClass('d-none');
elem.find('.status-success').removeClass('d-none');
elem.removeClass('client');
......@@ -61,13 +60,11 @@ function logout_services() {
.catch(function (err) {
elem.find('.status-active').addClass('d-none');
elem.find('.status-failed').removeClass('d-none');
console.log(err);
throw err;
});
all_promises.push(p);
});
Promise.allSettled(all_promises).then(function (results) {
console.log(results);
for (result of results) {
if (result.status == 'rejected')
throw result.reason;
......
......@@ -7,9 +7,9 @@
</div>
{% endif %}
<form action="{{ url_for("role.update", roleid=role.id) }}" method="POST">
<form action="{{ url_for("role.update", roleid=role.id) }}" method="POST" autocomplete="off">
<div class="align-self-center">
<div class="float-sm-right pb-2">
<div class="clearfix pb-2"><div class="float-sm-right">
<button type="submit" class="btn btn-primary"><i class="fa fa-save" aria-hidden="true"></i> {{_("Save")}}</button>
<a href="{{ url_for("role.index") }}" class="btn btn-secondary">{{_("Cancel")}}</a>
{% if role.id %}
......@@ -23,7 +23,7 @@
<a href="#" class="btn btn-secondary disabled">{{_("Set as default")}}</a>
<a href="#" class="btn btn-danger disabled"><i class="fa fa-trash" aria-hidden="true"></i> {{_("Delete")}}</a>
{% endif %}
</div>
</div></div>
<ul class="nav nav-tabs pt-2 border-0" id="tablist" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="settings-tab" data-toggle="tab" href="#settings" role="tab" aria-controls="settings" aria-selected="true">{{_("Settings")}}</a>
......