umap-project 3.1.2__py3-none-any.whl → 3.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/locale/en/LC_MESSAGES/django.mo +0 -0
- umap/locale/en/LC_MESSAGES/django.po +22 -18
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +21 -17
- umap/management/commands/export_pictogram.py +29 -0
- umap/management/commands/migrate_to_S3.py +5 -1
- umap/management/commands/purge_old_versions.py +8 -6
- umap/settings/__init__.py +21 -0
- umap/settings/base.py +3 -0
- umap/static/umap/content.css +7 -2
- umap/static/umap/css/contextmenu.css +58 -2
- umap/static/umap/css/form.css +175 -45
- umap/static/umap/css/icon.css +97 -3
- umap/static/umap/css/panel.css +31 -1
- umap/static/umap/img/16-white.svg +21 -40
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/24-white.svg +9 -9
- umap/static/umap/img/24.svg +23 -10
- umap/static/umap/img/source/16-white.svg +23 -41
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/img/source/24-white.svg +11 -11
- umap/static/umap/img/source/24.svg +25 -12
- umap/static/umap/js/modules/browser.js +1 -1
- umap/static/umap/js/modules/caption.js +8 -0
- umap/static/umap/js/modules/data/features.js +331 -202
- umap/static/umap/js/modules/data/layer.js +263 -152
- umap/static/umap/js/modules/facets.js +2 -2
- umap/static/umap/js/modules/form/builder.js +11 -7
- umap/static/umap/js/modules/form/fields.js +66 -26
- umap/static/umap/js/modules/formatter.js +78 -28
- umap/static/umap/js/modules/importer.js +6 -1
- umap/static/umap/js/modules/importers/opendata.js +138 -33
- umap/static/umap/js/modules/importers/openrouteservice.js +140 -0
- umap/static/umap/js/modules/managers.js +67 -0
- umap/static/umap/js/modules/printer.js +107 -0
- umap/static/umap/js/modules/rendering/controls.js +78 -2
- umap/static/umap/js/modules/rendering/icon.js +116 -87
- umap/static/umap/js/modules/rendering/layers/classified.js +8 -7
- umap/static/umap/js/modules/rendering/layers/cluster.js +199 -63
- umap/static/umap/js/modules/rendering/map.js +6 -2
- umap/static/umap/js/modules/rendering/template.js +71 -1
- umap/static/umap/js/modules/rendering/ui.js +111 -34
- umap/static/umap/js/modules/rules.js +76 -23
- umap/static/umap/js/modules/schema.js +27 -0
- umap/static/umap/js/modules/share.js +19 -12
- umap/static/umap/js/modules/slideshow.js +1 -1
- umap/static/umap/js/modules/sync/updaters.js +1 -6
- umap/static/umap/js/modules/tableeditor.js +13 -37
- umap/static/umap/js/modules/templates.js +7 -6
- umap/static/umap/js/modules/ui/bar.js +6 -1
- umap/static/umap/js/modules/ui/base.js +24 -9
- umap/static/umap/js/modules/ui/contextmenu.js +17 -7
- umap/static/umap/js/modules/ui/dialog.js +7 -4
- umap/static/umap/js/modules/ui/panel.js +7 -0
- umap/static/umap/js/modules/umap.js +84 -67
- umap/static/umap/js/modules/utils.js +8 -7
- umap/static/umap/js/umap.controls.js +22 -57
- umap/static/umap/locale/am_ET.js +81 -9
- umap/static/umap/locale/am_ET.json +81 -9
- umap/static/umap/locale/ar.js +81 -9
- umap/static/umap/locale/ar.json +81 -9
- umap/static/umap/locale/ast.js +81 -9
- umap/static/umap/locale/ast.json +81 -9
- umap/static/umap/locale/bg.js +81 -9
- umap/static/umap/locale/bg.json +81 -9
- umap/static/umap/locale/br.js +68 -29
- umap/static/umap/locale/br.json +68 -29
- umap/static/umap/locale/ca.js +88 -16
- umap/static/umap/locale/ca.json +88 -16
- umap/static/umap/locale/cs_CZ.js +81 -9
- umap/static/umap/locale/cs_CZ.json +81 -9
- umap/static/umap/locale/da.js +48 -9
- umap/static/umap/locale/da.json +48 -9
- umap/static/umap/locale/de.js +48 -9
- umap/static/umap/locale/de.json +48 -9
- umap/static/umap/locale/el.js +58 -13
- umap/static/umap/locale/el.json +58 -13
- umap/static/umap/locale/en.js +48 -9
- umap/static/umap/locale/en.json +48 -9
- umap/static/umap/locale/en_US.json +81 -9
- umap/static/umap/locale/es.js +48 -9
- umap/static/umap/locale/es.json +48 -9
- umap/static/umap/locale/et.js +81 -9
- umap/static/umap/locale/et.json +81 -9
- umap/static/umap/locale/eu.js +97 -25
- umap/static/umap/locale/eu.json +97 -25
- umap/static/umap/locale/fa_IR.js +81 -9
- umap/static/umap/locale/fa_IR.json +81 -9
- umap/static/umap/locale/fi.js +81 -9
- umap/static/umap/locale/fi.json +81 -9
- umap/static/umap/locale/fr.js +48 -9
- umap/static/umap/locale/fr.json +48 -9
- umap/static/umap/locale/gl.js +81 -9
- umap/static/umap/locale/gl.json +81 -9
- umap/static/umap/locale/he.js +81 -9
- umap/static/umap/locale/he.json +81 -9
- umap/static/umap/locale/hr.js +81 -9
- umap/static/umap/locale/hr.json +81 -9
- umap/static/umap/locale/hu.js +72 -27
- umap/static/umap/locale/hu.json +72 -27
- umap/static/umap/locale/id.js +81 -9
- umap/static/umap/locale/id.json +81 -9
- umap/static/umap/locale/is.js +81 -9
- umap/static/umap/locale/is.json +81 -9
- umap/static/umap/locale/it.js +48 -9
- umap/static/umap/locale/it.json +48 -9
- umap/static/umap/locale/ja.js +81 -9
- umap/static/umap/locale/ja.json +81 -9
- umap/static/umap/locale/ko.js +81 -9
- umap/static/umap/locale/ko.json +81 -9
- umap/static/umap/locale/lt.js +81 -9
- umap/static/umap/locale/lt.json +81 -9
- umap/static/umap/locale/ms.js +81 -9
- umap/static/umap/locale/ms.json +81 -9
- umap/static/umap/locale/nl.js +48 -9
- umap/static/umap/locale/nl.json +48 -9
- umap/static/umap/locale/no.js +81 -9
- umap/static/umap/locale/no.json +81 -9
- umap/static/umap/locale/pl.js +81 -9
- umap/static/umap/locale/pl.json +81 -9
- umap/static/umap/locale/pl_PL.json +81 -9
- umap/static/umap/locale/pt.js +81 -9
- umap/static/umap/locale/pt.json +81 -9
- umap/static/umap/locale/pt_BR.js +91 -19
- umap/static/umap/locale/pt_BR.json +91 -19
- umap/static/umap/locale/pt_PT.js +81 -9
- umap/static/umap/locale/pt_PT.json +81 -9
- umap/static/umap/locale/ro.js +81 -9
- umap/static/umap/locale/ro.json +81 -9
- umap/static/umap/locale/ru.js +81 -9
- umap/static/umap/locale/ru.json +81 -9
- umap/static/umap/locale/sk_SK.js +81 -9
- umap/static/umap/locale/sk_SK.json +81 -9
- umap/static/umap/locale/sl.js +81 -9
- umap/static/umap/locale/sl.json +81 -9
- umap/static/umap/locale/sr.js +81 -9
- umap/static/umap/locale/sr.json +81 -9
- umap/static/umap/locale/sv.js +81 -9
- umap/static/umap/locale/sv.json +81 -9
- umap/static/umap/locale/th_TH.js +81 -9
- umap/static/umap/locale/th_TH.json +81 -9
- umap/static/umap/locale/tr.js +81 -9
- umap/static/umap/locale/tr.json +81 -9
- umap/static/umap/locale/uk_UA.js +81 -9
- umap/static/umap/locale/uk_UA.json +81 -9
- umap/static/umap/locale/vi.js +81 -9
- umap/static/umap/locale/vi.json +81 -9
- umap/static/umap/locale/vi_VN.json +81 -9
- umap/static/umap/locale/zh.js +81 -9
- umap/static/umap/locale/zh.json +81 -9
- umap/static/umap/locale/zh_CN.json +81 -9
- umap/static/umap/locale/zh_TW.Big5.json +81 -9
- umap/static/umap/locale/zh_TW.js +98 -26
- umap/static/umap/locale/zh_TW.json +98 -26
- umap/static/umap/map.css +325 -102
- umap/static/umap/vars.css +1 -0
- umap/static/umap/vendors/betterknown/betterknown.mjs +287 -0
- umap/static/umap/vendors/editable/Leaflet.Editable.js +3 -1
- umap/static/umap/vendors/openrouteservice/ors-js-client.js +521 -0
- umap/static/umap/vendors/openrouteservice/ors-js-client.js.map +1 -0
- umap/static/umap/vendors/simple-elevation-chart/elevation.js +63 -0
- umap/static/umap/vendors/simple-elevation-chart/elevation.svg +8 -0
- umap/static/umap/vendors/snapdom/snapdom.min.mjs +3 -0
- umap/storage/fs.py +3 -2
- umap/storage/staticfiles.py +12 -0
- umap/templates/base.html +4 -1
- umap/templates/umap/css.html +0 -4
- umap/templates/umap/js.html +1 -3
- umap/tests/base.py +9 -1
- umap/tests/integration/test_basics.py +3 -1
- umap/tests/integration/test_conditional_rules.py +79 -37
- umap/tests/integration/test_datalayer.py +1 -1
- umap/tests/integration/test_draw_polygon.py +3 -5
- umap/tests/integration/test_draw_polyline.py +4 -6
- umap/tests/integration/test_draw_route.py +178 -0
- umap/tests/integration/test_edit_datalayer.py +1 -1
- umap/tests/integration/test_edit_map.py +1 -1
- umap/tests/integration/test_edit_marker.py +8 -8
- umap/tests/integration/test_edit_polygon.py +2 -2
- umap/tests/integration/test_export_map.py +84 -10
- umap/tests/integration/test_import.py +140 -0
- umap/tests/integration/test_map_preview.py +1 -1
- umap/tests/integration/test_optimistic_merge.py +72 -12
- umap/tests/integration/test_share.py +1 -1
- umap/tests/integration/test_tableeditor.py +10 -7
- umap/tests/integration/test_websocket_sync.py +4 -4
- umap/utils.py +37 -0
- umap/views.py +18 -2
- umap_project-3.3.0.dist-info/METADATA +76 -0
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/RECORD +194 -188
- umap/static/umap/vendors/markercluster/MarkerCluster.Default.css +0 -60
- umap/static/umap/vendors/markercluster/MarkerCluster.css +0 -14
- umap/static/umap/vendors/markercluster/leaflet.markercluster.js +0 -2
- umap/static/umap/vendors/markercluster/leaflet.markercluster.js.map +0 -1
- umap_project-3.1.2.dist-info/METADATA +0 -68
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/WHEEL +0 -0
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/entry_points.txt +0 -0
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var l={image:new Map,background:new Map,resource:new Map,defaultStyle:new Map,baseStyle:new Map,computedStyle:new WeakMap,font:new Set,snapshot:new WeakMap,snapshotKey:new Map,preStyleMap:new Map,preStyle:new WeakMap,preNodeMap:new Map,reset:Re};function Re(){l.computedStyle=new WeakMap,l.snapshot=new WeakMap,l.snapshotKey.clear(),l.preStyleMap.clear(),l.preStyle=new WeakMap,l.preNodeMap.clear()}var Ne=["div","span","p","a","img","ul","li","button","input","select","textarea","label","section","article","header","footer","nav","main","aside","h1","h2","h3","h4","h5","h6","svg","path","circle","rect","line","g","table","thead","tbody","tr","td","th"];function ie(){for(let e of Ne)ce(e)}function ce(e){if(l.defaultStyle.has(e))return l.defaultStyle.get(e);if(new Set(["script","style","meta","link","noscript","template","defs","symbol","title","metadata","desc"]).has(e)){let n={};return l.defaultStyle.set(e,n),n}let r=document.getElementById("snapdom-sandbox");r||(r=document.createElement("div"),r.id="snapdom-sandbox",r.style.position="absolute",r.style.left="-9999px",r.style.top="-9999px",r.style.width="0",r.style.height="0",r.style.overflow="hidden",document.body.appendChild(r));let c=document.createElement(e);c.style.all="initial",r.appendChild(c);let s=getComputedStyle(c),o={};for(let n of s)o[n]=s.getPropertyValue(n);return r.removeChild(c),l.defaultStyle.set(e,o),o}var Ae=new Set(["-webkit-locale"]);function D(e,t,r=!1){let c=[],s=ce(t);for(let[o,n]of Object.entries(e))if(!Ae.has(o))if(!r)n&&c.push(`${o}:${n}`);else{let a=s[o];n&&n!==a&&c.push(`${o}:${n}`)}return c.sort().join(";")}function le(e){let t=new Set;return e.nodeType!==Node.ELEMENT_NODE&&e.nodeType!==Node.DOCUMENT_FRAGMENT_NODE?[]:(e.tagName&&t.add(e.tagName.toLowerCase()),typeof e.querySelectorAll=="function"&&e.querySelectorAll("*").forEach(r=>t.add(r.tagName.toLowerCase())),Array.from(t))}function de(e){let t=new Map;for(let c of e){let s=l.defaultStyle.get(c);if(!s)continue;let o=Object.entries(s).map(([n,a])=>`${n}:${a};`).sort().join("");t.has(o)||t.set(o,[]),t.get(o).push(c)}let r="";for(let[c,s]of t.entries())r+=`${s.join(",")} { ${c} }
|
|
2
|
+
`;return r}function fe(){let e=new Set(l.preStyleMap.values()),t=new Map,r=1;for(let c of e)c.trim()&&t.set(c,`c${r++}`);return t}async function P(e,t={}){let r=O(e),c=/^((repeating-)?(linear|radial|conic)-gradient)\(/i.test(e);if(r){let s=H(r);if(l.background.has(s))return t.skipInline?void 0:`url(${l.background.get(s)})`;{let o=await M(s,{useProxy:t.useProxy});return l.background.set(s,o),t.skipInline?void 0:`url("${o}")`}}return e}function F(e,{fast:t=!1}={}){if(t)return e();"requestIdleCallback"in window?requestIdleCallback(e,{timeout:50}):setTimeout(e,1)}function I(e,t=null){if(!(e instanceof Element))return window.getComputedStyle(e,t);let r=l.computedStyle.get(e);if(r||(r=new Map,l.computedStyle.set(e,r)),!r.has(t)){let c=window.getComputedStyle(e,t);r.set(t,c)}return r.get(t)}function ue(e){let t=e.replace(/^['"]|['"]$/g,"");if(t.startsWith("\\"))try{return String.fromCharCode(parseInt(t.replace("\\",""),16))}catch{return t}return t}function O(e){let t=e.match(/url\((['"]?)(.*?)(\1)\)/);if(!t)return null;let r=t[2].trim();return r.startsWith("#")?null:r}function M(e,{timeout:t=3e3,useProxy:r=""}={}){function c(i){try{return new URL(i,window.location.href).origin===window.location.origin?"use-credentials":"anonymous"}catch{return"anonymous"}}async function s(i){let d=u=>fetch(u,{mode:"cors",credentials:c(u)==="use-credentials"?"include":"omit"}).then(f=>f.blob()).then(f=>new Promise((m,p)=>{let h=new FileReader;h.onloadend=()=>{let y=h.result;if(typeof y!="string"||!y.startsWith("data:image/")){p(new Error("Invalid image data URL"));return}m(y)},h.onerror=()=>p(new Error("FileReader error")),h.readAsDataURL(f)}));try{return await d(i)}catch{if(r&&typeof r=="string"){let f=r.replace(/\/$/,"")+H(i);try{return await d(f)}catch{throw new Error("[SnapDOM - fetchImage] CORS restrictions prevented image capture (even via proxy)")}}else throw new Error("[SnapDOM - fetchImage] Fetch fallback failed and no proxy provided")}}let o=c(e);return l.image.has(e)?Promise.resolve(l.image.get(e)):e.startsWith("data:image/")?(l.image.set(e,e),Promise.resolve(e)):/\.svg(\?.*)?$/i.test(e)?(async()=>{try{let d=await(await fetch(e,{mode:"cors",credentials:o==="use-credentials"?"include":"omit"})).text(),u=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(d)}`;return l.image.set(e,u),u}catch{return s(e)}})():new Promise((i,d)=>{let u=setTimeout(()=>{d(new Error("[SnapDOM - fetchImage] Image load timed out"))},t),f=new Image;f.crossOrigin=o,f.onload=async()=>{clearTimeout(u);try{await f.decode();let m=document.createElement("canvas");m.width=f.width,m.height=f.height,m.getContext("2d").drawImage(f,0,0,m.width,m.height);let h=m.toDataURL("image/png");l.image.set(e,h),i(h)}catch{try{let m=await s(e);l.image.set(e,m),i(m)}catch(m){d(m)}}},f.onerror=async()=>{clearTimeout(u),console.error(`[SnapDOM - fetchImage] Image failed to load: ${e}`);try{let m=await s(e);l.image.set(e,m),i(m)}catch(m){d(m)}},f.src=e})}function Q(e){let t={};for(let r of e)t[r]=e.getPropertyValue(r);return t}function me(){return/^((?!chrome|android).)*safari/i.test(navigator.userAgent)}function pe(e){if(!e||e==="none")return"";let t=e.replace(/translate[XY]?\([^)]*\)/g,"");return t=t.replace(/matrix\(([^)]+)\)/g,(r,c)=>{let s=c.split(",").map(o=>o.trim());return s.length!==6?`matrix(${c})`:(s[4]="0",s[5]="0",`matrix(${s.join(", ")})`)}),t=t.replace(/matrix3d\(([^)]+)\)/g,(r,c)=>{let s=c.split(",").map(o=>o.trim());return s.length!==16?`matrix3d(${c})`:(s[12]="0",s[13]="0",`matrix3d(${s.join(", ")})`)}),t.trim().replace(/\s{2,}/g," ")}function H(e){if(/%[0-9A-Fa-f]{2}/.test(e))return e;try{return encodeURI(e)}catch{return e}}function U(e){let t=[],r=0,c=0;for(let s=0;s<e.length;s++){let o=e[s];o==="("&&r++,o===")"&&r--,o===","&&r===0&&(t.push(e.slice(c,s).trim()),c=s+1)}return t.push(e.slice(c).trim()),t}function Te(e){let t={},r=e.getPropertyValue("visibility");for(let c=0;c<e.length;c++){let s=e[c],o=e.getPropertyValue(s);(s==="background-image"||s==="content")&&o.includes("url(")&&!o.includes("data:")&&(o="none"),t[s]=o}return r==="hidden"&&(t.opacity="0"),t}function z(e,t,r){if(e.tagName==="STYLE")return;l.preStyle.has(e)||l.preStyle.set(e,I(e));let c=l.preStyle.get(e);if(!l.snapshot.has(e)){let i=Te(c);l.snapshot.set(e,i)}let s=l.snapshot.get(e),o=Object.entries(s).sort(([i],[d])=>i.localeCompare(d)).map(([i,d])=>`${i}:${d}`).join(";");if(l.snapshotKey.has(o)){l.preStyleMap.set(t,l.snapshotKey.get(o));return}let n=e.tagName?.toLowerCase()||"div",a=D(s,n,r);l.snapshotKey.set(o,a),l.preStyleMap.set(t,a)}function j(e,t,r={},c){if(!e)throw new Error("Invalid node");let s=new Set,o=null;if(e.nodeType===Node.TEXT_NODE||e.nodeType!==Node.ELEMENT_NODE)return e.cloneNode(!0);if(e.getAttribute("data-capture")==="exclude"){let a=document.createElement("div"),i=e.getBoundingClientRect();return a.style.cssText=`display:inline-block;width:${i.width}px;height:${i.height}px;visibility:hidden;`,a}if(r.exclude&&Array.isArray(r.exclude))for(let a of r.exclude)try{if(e.matches?.(a)){let i=document.createElement("div"),d=e.getBoundingClientRect();return i.style.cssText=`display:inline-block;width:${d.width}px;height:${d.height}px;visibility:hidden;`,i}}catch(i){console.warn(`Invalid selector in exclude option: ${a}`,i)}if(typeof r.filter=="function")try{if(!r.filter(e,c||e)){let a=document.createElement("div"),i=e.getBoundingClientRect();return a.style.cssText=`display:inline-block;width:${i.width}px;height:${i.height}px;visibility:hidden;`,a}}catch(a){console.warn("Error in filter function:",a)}if(e.tagName==="IFRAME"){let a=document.createElement("div");return a.style.cssText=`width:${e.offsetWidth}px;height:${e.offsetHeight}px;background-image:repeating-linear-gradient(45deg,#ddd,#ddd 5px,#f9f9f9 5px,#f9f9f9 10px);display:flex;align-items:center;justify-content:center;font-size:12px;color:#555;border:1px solid #aaa;`,a}if(e.getAttribute("data-capture")==="placeholder"){let a=e.cloneNode(!1);l.preNodeMap.set(a,e),z(e,a,t);let i=document.createElement("div");return i.textContent=e.getAttribute("data-placeholder-text")||"",i.style.cssText="color:#666;font-size:12px;text-align:center;line-height:1.4;padding:0.5em;box-sizing:border-box;",a.appendChild(i),a}if(e.tagName==="CANVAS"){let a=e.toDataURL(),i=document.createElement("img");return i.src=a,i.width=e.width,i.height=e.height,l.preNodeMap.set(i,e),z(e,i,t),i}let n;try{n=e.cloneNode(!1),l.preNodeMap.set(n,e)}catch(a){throw console.error("[Snapdom] Failed to clone node:",e,a),a}if(e instanceof HTMLTextAreaElement){n.textContent=e.value,n.value=e.value;let a=e.getBoundingClientRect();return n.style.width=`${a.width}px`,n.style.height=`${a.height}px`,n}if(e instanceof HTMLInputElement&&(n.value=e.value,n.setAttribute("value",e.value),e.checked!==void 0&&(n.checked=e.checked,e.checked&&n.setAttribute("checked",""),e.indeterminate&&(n.indeterminate=e.indeterminate))),e instanceof HTMLSelectElement&&(o=e.value),z(e,n,t),e.shadowRoot)if(Array.from(e.shadowRoot.querySelectorAll("slot")).length>0){for(let i of e.shadowRoot.childNodes)if(i.nodeType===Node.ELEMENT_NODE&&i.tagName==="STYLE"){let d=i.textContent||"";d.trim()&&t&&(l.preStyle||(l.preStyle=new WeakMap),l.preStyle.set(i,d))}}else{let i=document.createDocumentFragment();for(let d of e.shadowRoot.childNodes){if(d.nodeType===Node.ELEMENT_NODE&&d.tagName==="STYLE"){let f=d.textContent||"";f.trim()&&t&&(l.preStyle||(l.preStyle=new WeakMap),l.preStyle.set(d,f));continue}let u=j(d,t,r,c||e);u&&i.appendChild(u)}n.appendChild(i)}if(e.tagName==="SLOT"){let a=e.assignedNodes?.({flatten:!0})||[],i=a.length>0?a:Array.from(e.childNodes),d=document.createDocumentFragment();for(let u of i){let f=j(u,t,r,c||e);f&&d.appendChild(f)}return d}for(let a of e.childNodes){if(s.has(a))continue;let i=j(a,t,r,c||e);i&&n.appendChild(i)}if(o!==null&&n instanceof HTMLSelectElement){n.value=o;for(let a of n.options)a.value===o?a.setAttribute("selected",""):a.removeAttribute("selected")}return n}var Me=[/font\s*awesome/i,/material\s*icons/i,/ionicons/i,/glyphicons/i,/feather/i,/bootstrap\s*icons/i,/remix\s*icons/i,/heroicons/i,/layui/i,/lucide/i],Z=[];function he(e){let t=Array.isArray(e)?e:[e];for(let r of t)r instanceof RegExp?Z.push(r):typeof r=="string"?Z.push(new RegExp(r,"i")):console.warn("[snapdom] Ignored invalid iconFont value:",r)}function k(e){let t=typeof e=="string"?e:"",r=[...Me,...Z];for(let c of r)if(c instanceof RegExp&&c.test(t))return!0;return!!(/icon/i.test(t)||/glyph/i.test(t)||/symbols/i.test(t)||/feather/i.test(t)||/fontawesome/i.test(t))}async function ge(e,t,r,c=32,s="#000"){t=t.replace(/^['"]+|['"]+$/g,"");let o=window.devicePixelRatio||1;await document.fonts.ready;let n=document.createElement("span");n.textContent=e,n.style.position="absolute",n.style.visibility="hidden",n.style.fontFamily=`"${t}"`,n.style.fontWeight=r||"normal",n.style.fontSize=`${c}px`,n.style.lineHeight="1",n.style.whiteSpace="nowrap",n.style.padding="0",n.style.margin="0",document.body.appendChild(n);let a=n.getBoundingClientRect(),i=Math.ceil(a.width),d=Math.ceil(a.height);document.body.removeChild(n);let u=document.createElement("canvas");u.width=i*o,u.height=d*o;let f=u.getContext("2d");return f.scale(o,o),f.font=r?`${r} ${c}px "${t}"`:`${c}px "${t}"`,f.textAlign="left",f.textBaseline="top",f.fillStyle=s,f.fillText(e,0,0),{dataUrl:u.toDataURL(),width:i,height:d}}function ye(e){return Array.from(document.styleSheets).some(t=>t.href===e)}function Le(e){return new Promise(t=>{if(ye(e))return t(null);let r=document.createElement("link");r.rel="stylesheet",r.href=e,r.setAttribute("data-snapdom","injected-import"),r.onload=()=>t(r),r.onerror=()=>t(null),document.head.appendChild(r)})}async function K({preCached:e=!1}={}){if(l.resource.has("fonts-embed-css")){if(e){let o=document.createElement("style");o.setAttribute("data-snapdom","embedFonts"),o.textContent=l.resource.get("fonts-embed-css"),document.head.appendChild(o)}return l.resource.get("fonts-embed-css")}let t=/@import\s+url\(["']?([^"')]+)["']?\)/g,r=[];for(let o of document.querySelectorAll("style")){let n=o.textContent||"",a=Array.from(n.matchAll(t));for(let i of a){let d=i[1];k(d)||ye(d)||r.push(d)}}await Promise.all(r.map(Le));let c=Array.from(document.querySelectorAll('link[rel="stylesheet"]')).filter(o=>o.href),s="";for(let o of c)try{let a=await(await fetch(o.href)).text();if(k(o.href)||k(a))continue;let i=/url\((["']?)([^"')]+)\1\)/g,d=await Promise.all(Array.from(a.matchAll(i)).map(async f=>{let m=O(f[0]);if(!m)return null;let p=m;if(!p.startsWith("http")&&!p.startsWith("data:")&&(p=new URL(p,o.href).href),k(p))return null;if(l.resource.has(p))return l.font.add(p),{original:f[0],inlined:`url(${l.resource.get(p)})`};if(l.font.has(p))return null;try{let y=await(await fetch(p)).blob(),w=await new Promise(g=>{let E=new FileReader;E.onload=()=>g(E.result),E.readAsDataURL(y)});return l.resource.set(p,w),l.font.add(p),{original:f[0],inlined:`url(${w})`}}catch{return console.warn("[snapdom] Failed to fetch font resource:",p),null}})),u=a;for(let f of d)f&&(u=u.replace(f.original,f.inlined));s+=u+`
|
|
3
|
+
`}catch{console.warn("[snapdom] Failed to fetch CSS:",o.href)}for(let o of document.styleSheets)try{if(!o.href||c.every(n=>n.href!==o.href)){for(let n of o.cssRules)if(n.type===CSSRule.FONT_FACE_RULE){let a=n.style.getPropertyValue("src"),i=n.style.getPropertyValue("font-family");if(!a||k(i))continue;let d=/url\((["']?)([^"')]+)\1\)/g,u=/local\((["']?)[^)]+?\1\)/g,f=!!a.match(d),m=!!a.match(u);if(!f&&m){s+=`@font-face{font-family:${i};src:${a};font-style:${n.style.getPropertyValue("font-style")||"normal"};font-weight:${n.style.getPropertyValue("font-weight")||"normal"};}`;continue}let p=a,h=Array.from(a.matchAll(d));for(let y of h){let w=y[2].trim();if(!w)continue;let g=w;if(!g.startsWith("http")&&!g.startsWith("data:")&&(g=new URL(g,o.href||location.href).href),!k(g)){if(l.resource.has(g)){l.font.add(g),p=p.replace(y[0],`url(${l.resource.get(g)})`);continue}if(!l.font.has(g))try{let $=await(await fetch(g)).blob(),R=await new Promise(N=>{let x=new FileReader;x.onload=()=>N(x.result),x.readAsDataURL($)});l.resource.set(g,R),l.font.add(g),p=p.replace(y[0],`url(${R})`)}catch{console.warn("[snapdom] Failed to fetch font URL:",g)}}}s+=`@font-face{font-family:${i};src:${p};font-style:${n.style.getPropertyValue("font-style")||"normal"};font-weight:${n.style.getPropertyValue("font-weight")||"normal"};}`}}}catch(n){console.warn("[snapdom] Cannot access stylesheet",o.href,n)}for(let o of document.fonts)if(o.family&&o.status==="loaded"&&o._snapdomSrc){if(k(o.family))continue;let n=o._snapdomSrc;if(!n.startsWith("data:")){if(l.resource.has(o._snapdomSrc))n=l.resource.get(o._snapdomSrc),l.font.add(o._snapdomSrc);else if(!l.font.has(o._snapdomSrc))try{let i=await(await fetch(o._snapdomSrc)).blob();n=await new Promise(d=>{let u=new FileReader;u.onload=()=>d(u.result),u.readAsDataURL(i)}),l.resource.set(o._snapdomSrc,n),l.font.add(o._snapdomSrc)}catch{console.warn("[snapdom] Failed to fetch dynamic font src:",o._snapdomSrc);continue}}s+=`@font-face{font-family:'${o.family}';src:url(${n});font-style:${o.style||"normal"};font-weight:${o.weight||"normal"};}`}if(s&&(l.resource.set("fonts-embed-css",s),e)){let o=document.createElement("style");o.setAttribute("data-snapdom","embedFonts"),o.textContent=s,document.head.appendChild(o)}return s}async function ee(e,t,r){if(!(e instanceof Element)||!(t instanceof Element))return;for(let o of["::before","::after","::first-letter"])try{let n=I(e,o);if(!n||typeof n[Symbol.iterator]!="function"||n.content==="none"&&n.backgroundImage==="none"&&n.backgroundColor==="transparent"&&(n.borderStyle==="none"||parseFloat(n.borderWidth)===0)&&(!n.transform||n.transform==="none")&&n.display==="inline")continue;if(o==="::first-letter"){let C=getComputedStyle(e);if(!(n.color!==C.color||n.fontSize!==C.fontSize||n.fontWeight!==C.fontWeight))continue;let T=Array.from(t.childNodes).find(se=>se.nodeType===Node.TEXT_NODE&&se.textContent?.trim().length>0);if(!T)continue;let L=T.textContent,_=L.match(/^([^\p{L}\p{N}\s]*[\p{L}\p{N}](?:['’])?)/u)?.[0],ke=L.slice(_?.length||0);if(!_||/[\uD800-\uDFFF]/.test(_))continue;let q=document.createElement("span");q.textContent=_,q.dataset.snapdomPseudo="::first-letter";let $e=Q(n),Ie=D($e,"span",r);l.preStyleMap.set(q,Ie);let ae=document.createTextNode(ke);t.replaceChild(ae,T),t.insertBefore(q,ae);continue}let i=n.content,d=/counter\s*\(|counters\s*\(/.test(i)?"- ":ue(i),u=n.backgroundImage,f=n.backgroundColor,m=n.fontFamily,p=parseInt(n.fontSize)||32,h=parseInt(n.fontWeight)||!1,y=n.color||"#000",w=n.display,g=parseFloat(n.width),E=parseFloat(n.height),$=n.borderStyle,R=parseFloat(n.borderWidth),N=n.transform,x=k(m),B=i!=="none"&&d!=="",V=u&&u!=="none",W=f&&f!=="transparent"&&f!=="rgba(0, 0, 0, 0)",Y=w!=="inline"&&(g>0||E>0),G=$&&$!=="none"&&R>0,A=N&&N!=="none";if(!(B||V||W||Y||G||A))continue;let S=document.createElement("span");S.dataset.snapdomPseudo=o,S.style.verticalAlign="middle";let X=Q(n),J=D(X,"span",r);if(l.preStyleMap.set(S,J),x&&d.length===1){let{dataUrl:C,width:v,height:T}=await ge(d,m,h,p,y),L=document.createElement("img");L.src=C,L.style=`height:${p}px;width:${v/T*p}px;object-fit:contain;`,S.appendChild(L),t.dataset.snapdomHasIcon="true"}else if(d.startsWith("url(")){let C=O(d);if(C?.trim())try{let v=document.createElement("img"),T=await M(H(C),r);v.src=T,v.style=`width:${p}px;height:auto;object-fit:contain;`,S.appendChild(v)}catch(v){console.error(`[snapdom] Error in pseudo ${o} for`,e,v)}}else!x&&B&&(S.textContent=d);if(V)try{let C=U(u),v=await Promise.all(C.map(P));S.style.backgroundImage=v.join(", ")}catch(C){console.warn(`[snapdom] Failed to inline background-image for ${o}`,C)}if(W&&(S.style.backgroundColor=f),!(S.childNodes.length>0||S.textContent?.trim()!==""||V||W||Y||G||A))continue;o==="::before"?t.insertBefore(S,t.firstChild):t.appendChild(S)}catch(n){console.warn(`[snapdom] Failed to capture ${o} for`,e,n)}let c=Array.from(e.children),s=Array.from(t.children).filter(o=>!o.dataset.snapdomPseudo);for(let o=0;o<Math.min(c.length,s.length);o++)await ee(c[o],s[o],r)}function we(e){if(!e)return;let t=new Set;if(e.querySelectorAll("use").forEach(a=>{let i=a.getAttribute("xlink:href")||a.getAttribute("href");i&&i.startsWith("#")&&t.add(i.slice(1))}),!t.size)return;let r=Array.from(document.querySelectorAll("svg > symbol, svg > defs")),c=r.filter(a=>a.tagName.toLowerCase()==="symbol"),s=r.filter(a=>a.tagName.toLowerCase()==="defs"),o=e.querySelector("svg.inline-defs-container");o||(o=document.createElementNS("http://www.w3.org/2000/svg","svg"),o.setAttribute("aria-hidden","true"),o.setAttribute("style","position: absolute; width: 0; height: 0; overflow: hidden;"),o.classList.add("inline-defs-container"),e.insertBefore(o,e.firstChild));let n=new Set;e.querySelectorAll("symbol[id], defs > *[id]").forEach(a=>{n.add(a.id)}),t.forEach(a=>{if(n.has(a))return;let i=c.find(d=>d.id===a);if(i){o.appendChild(i.cloneNode(!0)),n.add(a);return}for(let d of s){let u=d.querySelector(`#${CSS.escape(a)}`);if(u){let f=o.querySelector("defs");f||(f=document.createElementNS("http://www.w3.org/2000/svg","defs"),o.appendChild(f)),f.appendChild(u.cloneNode(!0)),n.add(a);break}}})}async function be(e,t=!1,r=!1,c={}){let s,o="";Pe(e);try{we(e)}catch(n){console.warn("inlineExternal defs or symbol failed:",n)}try{s=j(e,t,c,e)}catch(n){throw console.warn("deepClone failed:",n),n}try{await ee(e,s,t,r,c.useProxy)}catch(n){console.warn("inlinePseudoElements failed:",n)}if(t){let n=fe();o=Array.from(n.entries()).map(([a,i])=>`.${i}{${a}}`).join("");for(let[a,i]of l.preStyleMap.entries()){if(a.tagName==="STYLE")continue;if(a.getRootNode&&a.getRootNode()instanceof ShadowRoot){a.setAttribute("style",i.replace(/;/g,"; "));continue}let d=n.get(i);d&&a.classList.add(d);let u=a.style?.backgroundImage,f=a.dataset?.snapdomHasIcon;u&&u!=="none"&&(a.style.backgroundImage=u),f&&(a.style.verticalAlign="middle",a.style.display="inline")}}else for(let[n,a]of l.preStyleMap.entries())n.tagName!=="STYLE"&&n.setAttribute("style",a.replace(/;/g,"; "));for(let[n,a]of l.preNodeMap.entries()){let i=a.scrollLeft,d=a.scrollTop;if((i||d)&&n instanceof HTMLElement){n.style.overflow="hidden",n.style.scrollbarWidth="none",n.style.msOverflowStyle="none";let f=document.createElement("div");for(f.style.transform=`translate(${-i}px, ${-d}px)`,f.style.willChange="transform",f.style.display="inline-block",f.style.width="100%";n.firstChild;)f.appendChild(n.firstChild);n.appendChild(f)}}if(e===l.preNodeMap.get(s)){let n=l.preStyle.get(e)||window.getComputedStyle(e);l.preStyle.set(e,n);let a=pe(n.transform);s.style.margin="0",s.style.position="static",s.style.top="auto",s.style.left="auto",s.style.right="auto",s.style.bottom="auto",s.style.zIndex="auto",s.style.float="none",s.style.clear="none",s.style.transform=a||""}for(let[n,a]of l.preNodeMap.entries())a.tagName==="PRE"&&(n.style.marginTop="0",n.style.marginBlockStart="0");return{clone:s,classCSS:o}}function Pe(e){let t=getComputedStyle(e),r=t.outlineStyle,c=t.outlineWidth,s=t.borderStyle,o=t.borderWidth,n=r!=="none"&&parseFloat(c)>0,a=s==="none"||parseFloat(o)===0;n&&a&&(e.style.border=`${c} solid transparent`)}async function Se(e,t={}){let r=Array.from(e.querySelectorAll("img")),c=async s=>{let o=s.src;try{let n=await M(o,{useProxy:t.useProxy});s.src=n,s.width||(s.width=s.naturalWidth||100),s.height||(s.height=s.naturalHeight||100)}catch{let n=document.createElement("div");n.style=`width: ${s.width||100}px; height: ${s.height||100}px; background: #ccc; display: inline-block; text-align: center; line-height: ${s.height||100}px; color: #666; font-size: 12px;`,n.innerText="img",s.replaceWith(n)}};for(let s=0;s<r.length;s+=4){let o=r.slice(s,s+4).map(c);await Promise.allSettled(o)}}async function xe(e,t,r={}){let c=[[e,t]],s=["background-image","mask","mask-image","-webkit-mask-image","mask-source","mask-box-image-source","mask-border-source","-webkit-mask-box-image-source","border-image","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"];for(;c.length;){let[o,n]=c.shift(),a=l.preStyle.get(o)||I(o);l.preStyle.has(o)||l.preStyle.set(o,a);let i=(()=>{let m=a.getPropertyValue("border-image"),p=a.getPropertyValue("border-image-source");return m&&m!=="none"||p&&p!=="none"})();for(let m of s){if(["border-image-slice","border-image-width","border-image-outset","border-image-repeat"].includes(m)&&!i)continue;let p=a.getPropertyValue(m);if(!p||p==="none")continue;let h=U(p),y=await Promise.all(h.map(w=>P(w,r)));y.some(w=>w&&w!=="none"&&!/^url\(undefined/.test(w))&&n.style.setProperty(m,y.join(", "))}let d=a.getPropertyValue("background-color");d&&d!=="transparent"&&d!=="rgba(0, 0, 0, 0)"&&(n.style.backgroundColor=d);let u=Array.from(o.children),f=Array.from(n.children);for(let m=0;m<Math.min(u.length,f.length);m++)c.push([u[m],f[m]])}}async function Ce(e,t={}){if(!e)throw new Error("Element cannot be null or undefined");l.reset();let{compress:r=!0,embedFonts:c=!1,fast:s=!0,scale:o=1,useProxy:n=""}=t,a,i,d="",u="",f,m;if({clone:a,classCSS:i}=await be(e,r,c,t),await new Promise(h=>{F(async()=>{await Se(a,t),h()},{fast:s})}),await new Promise(h=>{F(async()=>{await xe(e,a,t),h()},{fast:s})}),c&&await new Promise(h=>{F(async()=>{d=await K(),h()},{fast:s})}),r){let h=le(a).sort(),y=h.join(",");l.baseStyle.has(y)?u=l.baseStyle.get(y):await new Promise(w=>{F(()=>{u=de(h),l.baseStyle.set(y,u),w()},{fast:s})})}await new Promise(h=>{F(()=>{let y=e.getBoundingClientRect(),w=y.width,g=y.height,E=Number.isFinite(t.width),$=Number.isFinite(t.height),R=typeof o=="number"&&o!==1;if(!R){let A=y.width/y.height;E&&$?(w=t.width,g=t.height):E?(w=t.width,g=w/A):$&&(g=t.height,w=g*A)}if(w=Math.ceil(w),g=Math.ceil(g),a.setAttribute("xmlns","http://www.w3.org/1999/xhtml"),a.style.transformOrigin="top left",!R&&(E||$)){let A=y.width,oe=y.height,S=w/A,X=g/oe,J=a.style.transform||"",re=`scale(${S}, ${X})`;a.style.transform=`${re} ${J}`.trim()}let N="http://www.w3.org/2000/svg",x=document.createElementNS(N,"foreignObject");x.setAttribute("width","100%"),x.setAttribute("height","100%");let B=document.createElement("style");B.textContent=u+d+"svg{overflow:visible;}"+i,x.appendChild(B),x.appendChild(a);let W=new XMLSerializer().serializeToString(x);m=`<svg xmlns="${N}" width="${w}" height="${g}" viewBox="0 0 ${w} ${g}">`+W+"</svg>",f=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(m)}`,h()},{fast:s})});let p=document.getElementById("snapdom-sandbox");return p&&p.style.position==="absolute"&&p.remove(),f}async function Fe(e,{scale:t=1}={}){let r=new Image;return r.src=e,await r.decode(),t!==1&&(r.style.width=`${r.naturalWidth*t}px`,r.style.height=`${r.naturalHeight*t}px`),r}async function Ee(e,{dpr:t=1,scale:r=1}={}){let c=new Image;c.src=e,c.crossOrigin="anonymous",c.loading="eager",c.decoding="sync";let s=me(),o=!1;if(s&&(document.body.appendChild(c),o=!0),await c.decode(),s&&await new Promise(u=>setTimeout(u,100)),c.width===0||c.height===0)throw o&&c.remove(),new Error("Image failed to load or has no dimensions");let n=c.naturalWidth*r,a=c.naturalHeight*r,i=document.createElement("canvas");i.width=Math.ceil(n*t),i.height=Math.ceil(a*t),i.style.width=`${n}px`,i.style.height=`${a}px`;let d=i.getContext("2d");return d.scale(t,t),d.drawImage(c,0,0,n,a),o&&c.remove(),i}async function ve(e,{type:t="svg",scale:r=1,backgroundColor:c="#fff",quality:s}={}){let o={jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp"}[t]||"image/png";if(t==="svg"){let a=decodeURIComponent(e.split(",")[1]);return new Blob([a],{type:"image/svg+xml"})}let n=await ne(e,{dpr:1,scale:r},c);return new Promise(a=>{n.toBlob(i=>a(i),`${o}`,s)})}async function ne(e,{dpr:t=1,scale:r=1},c){let s=await Ee(e,{dpr:t,scale:r});if(!c)return s;let o=document.createElement("canvas");o.width=s.width,o.height=s.height;let n=o.getContext("2d");return n.fillStyle=c,n.fillRect(0,0,o.width,o.height),n.drawImage(s,0,0),o}async function te(e,{dpr:t=1,scale:r=1,backgroundColor:c,quality:s},o="png"){let n=["jpg","jpeg","webp"].includes(o)?"#fff":void 0,i=await ne(e,{dpr:t,scale:r},c??n),d=new Image;return d.src=i.toDataURL(`image/${o}`,s),await d.decode(),d.style.width=`${i.width/t}px`,d.style.height=`${i.height/t}px`,d}async function Ue(e,{dpr:t=1,scale:r=1,backgroundColor:c,format:s="png",filename:o="snapDOM"}={}){if(s==="svg"){let m=await ve(e),p=URL.createObjectURL(m),h=document.createElement("a");h.href=p,h.download=`${o}.svg`,h.click(),URL.revokeObjectURL(p);return}let n=["jpg","jpeg","webp"].includes(s)?"#fff":void 0,i=await ne(e,{dpr:t,scale:r},c??n),d={jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp"}[s]||"image/png",u=i.toDataURL(d),f=document.createElement("a");f.href=u,f.download=`${o}.${s}`,f.click()}async function b(e,t={}){if(t={scale:1,...t},!e)throw new Error("Element cannot be null or undefined");return t.iconFonts&&he(t.iconFonts),await b.capture(e,t)}b.capture=async(e,t={})=>{let r=await Ce(e,t),c=t.dpr??(window.devicePixelRatio||1),s=t.scale||1;return{url:r,options:t,toRaw:()=>r,toImg:(o={})=>Fe(r,{dpr:c,scale:s,...o}),toCanvas:(o={})=>Ee(r,{dpr:c,scale:s,...o}),toBlob:(o={})=>ve(r,{dpr:c,scale:s,...o}),toPng:(o={})=>te(r,{dpr:c,scale:s,...o},"png"),toJpg:(o={})=>te(r,{dpr:c,scale:s,...o},"jpeg"),toWebp:(o={})=>te(r,{dpr:c,scale:s,...o},"webp"),download:({format:o="png",filename:n="snapDOM",backgroundColor:a,...i}={})=>Ue(r,{dpr:c,scale:s,format:o,filename:n,backgroundColor:a,...i})}};b.toRaw=async(e,t)=>(await b.capture(e,t)).toRaw();b.toImg=async(e,t)=>(await b.capture(e,t)).toImg();b.toCanvas=async(e,t)=>(await b.capture(e,t)).toCanvas();b.toBlob=async(e,t)=>(await b.capture(e,t)).toBlob(t);b.toPng=async(e,t)=>(await b.capture(e,t)).toPng(t);b.toJpg=async(e,t)=>(await b.capture(e,t)).toJpg(t);b.toWebp=async(e,t)=>(await b.capture(e,t)).toWebp(t);b.download=async(e,t={})=>{let{format:r="png",filename:c="capture",backgroundColor:s,...o}=t;return await(await b.capture(e,o)).download({format:r,filename:c,backgroundColor:s})};async function Be(e=document,t={}){let{embedFonts:r=!0,reset:c=!1}=t;if(c){l.reset();return}await document.fonts.ready,ie();let s=[],o=[];e?.querySelectorAll&&(s=Array.from(e.querySelectorAll("img[src]")),o=Array.from(e.querySelectorAll("*")));let n=[];for(let a of s){let i=a.src;l.image.has(i)||n.push(M(i,{useProxy:t.useProxy}).then(d=>l.image.set(i,d)).catch(()=>{}))}for(let a of o){let i=I(a).backgroundImage;if(i&&i!=="none"){let d=U(i);for(let u of d)u.startsWith("url(")&&n.push(P(u,t).catch(()=>{}))}}r&&await K({preCached:!0}),await Promise.all(n)}export{Be as preCache,b as snapdom};
|
umap/storage/fs.py
CHANGED
|
@@ -79,7 +79,7 @@ class FSDataStorage(FileSystemStorage):
|
|
|
79
79
|
"size": self.size(self._base_path(instance) / name),
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
def purge_old_versions(self, instance, keep=None):
|
|
82
|
+
def purge_old_versions(self, instance, keep=None, dry_run=False):
|
|
83
83
|
root = self._base_path(instance)
|
|
84
84
|
versions = self.list_versions(instance)
|
|
85
85
|
if keep is not None:
|
|
@@ -92,7 +92,8 @@ class FSDataStorage(FileSystemStorage):
|
|
|
92
92
|
if keep is not None and instance.geojson.name.endswith(name):
|
|
93
93
|
continue
|
|
94
94
|
try:
|
|
95
|
-
|
|
95
|
+
if not dry_run:
|
|
96
|
+
self.delete(root / name)
|
|
96
97
|
except FileNotFoundError:
|
|
97
98
|
pass
|
|
98
99
|
else:
|
umap/storage/staticfiles.py
CHANGED
|
@@ -43,6 +43,18 @@ class UmapManifestStaticFilesStorage(ManifestStaticFilesStorage):
|
|
|
43
43
|
),
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
+
patterns = ManifestStaticFilesStorage.patterns + (
|
|
47
|
+
(
|
|
48
|
+
"*.svg",
|
|
49
|
+
(
|
|
50
|
+
(
|
|
51
|
+
r'(?P<matched>xlink:href="(?P<url>.*\.js)")',
|
|
52
|
+
'xlink:href="%(url)s"',
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
|
|
46
58
|
def post_process(self, paths, **options):
|
|
47
59
|
collected = super().post_process(paths, **options)
|
|
48
60
|
for original_path, processed_path, processed in collected:
|
umap/templates/base.html
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{% load umap_tags i18n static %}
|
|
2
2
|
|
|
3
|
+
{% get_current_language as LANGUAGE_CODE %}
|
|
4
|
+
|
|
3
5
|
<!DOCTYPE html>
|
|
4
|
-
<html {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}
|
|
6
|
+
<html {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}
|
|
7
|
+
lang="{{ LANGUAGE_CODE }}">
|
|
5
8
|
<head>
|
|
6
9
|
<title>
|
|
7
10
|
{% block head_title %}
|
umap/templates/umap/css.html
CHANGED
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
<link rel="stylesheet"
|
|
6
6
|
href="{% static 'umap/vendors/leaflet/leaflet.css' %}" />
|
|
7
|
-
<link rel="stylesheet"
|
|
8
|
-
href="{% static 'umap/vendors/markercluster/MarkerCluster.css' %}" />
|
|
9
|
-
<link rel="stylesheet"
|
|
10
|
-
href="{% static 'umap/vendors/markercluster/MarkerCluster.Default.css' %}" />
|
|
11
7
|
<link rel="stylesheet"
|
|
12
8
|
href="{% static 'umap/vendors/editinosm/Leaflet.EditInOSM.css' %}" />
|
|
13
9
|
<link rel="stylesheet"
|
umap/templates/umap/js.html
CHANGED
|
@@ -7,17 +7,15 @@
|
|
|
7
7
|
<script type="module"
|
|
8
8
|
src="{% static 'umap/js/modules/leaflet-configure.js' %}"
|
|
9
9
|
defer></script>
|
|
10
|
-
<script src="{% static 'umap/vendors/markercluster/leaflet.markercluster.js' %}"
|
|
11
|
-
defer></script>
|
|
12
10
|
<script src="{% static 'umap/vendors/heat/leaflet-heat.js' %}" defer></script>
|
|
13
11
|
{% if locale %}
|
|
14
12
|
{% with "umap/locale/"|add:locale|add:".js" as path %}
|
|
15
13
|
<script src="{% static path %}" defer></script>
|
|
16
14
|
{% endwith %}
|
|
17
15
|
{% endif %}
|
|
18
|
-
<script type="module" src="{% static 'umap/js/modules/global.js' %}" defer></script>
|
|
19
16
|
<script src="{% static 'umap/vendors/editable/Path.Drag.js' %}" defer></script>
|
|
20
17
|
<script src="{% static 'umap/vendors/editable/Leaflet.Editable.js' %}" defer></script>
|
|
18
|
+
<script type="module" src="{% static 'umap/js/modules/global.js' %}" defer></script>
|
|
21
19
|
<script src="{% static 'umap/vendors/hash/leaflet-hash.js' %}" defer></script>
|
|
22
20
|
<script src="{% static 'umap/vendors/editinosm/Leaflet.EditInOSM.js' %}"
|
|
23
21
|
defer></script>
|
umap/tests/base.py
CHANGED
|
@@ -128,7 +128,15 @@ class DataLayerFactory(factory.django.DjangoModelFactory):
|
|
|
128
128
|
def _adjust_kwargs(cls, **kwargs):
|
|
129
129
|
if "data" in kwargs:
|
|
130
130
|
data = copy.deepcopy(kwargs.pop("data"))
|
|
131
|
-
data.setdefault(
|
|
131
|
+
data.setdefault(
|
|
132
|
+
"_umap_options",
|
|
133
|
+
{
|
|
134
|
+
"fields": [
|
|
135
|
+
{"key": "name", "type": "String"},
|
|
136
|
+
{"key": "description", "type": "Text"},
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
)
|
|
132
140
|
if "name" in data["_umap_options"] and kwargs["name"] == cls.name:
|
|
133
141
|
kwargs["name"] = data["_umap_options"]["name"]
|
|
134
142
|
kwargs.setdefault("settings", {})
|
|
@@ -42,8 +42,10 @@ def test_create_map_with_cursor(page, live_server, tilelayer):
|
|
|
42
42
|
(
|
|
43
43
|
"margin-left: -16px; "
|
|
44
44
|
"margin-top: -40px; "
|
|
45
|
+
"width: 12px; "
|
|
46
|
+
"height: 12px; "
|
|
45
47
|
"transform: translate3d(200px, 200px, 0px); "
|
|
46
|
-
"z-index:
|
|
48
|
+
"z-index: 0;"
|
|
47
49
|
),
|
|
48
50
|
)
|
|
49
51
|
|
|
@@ -27,6 +27,7 @@ DATALAYER_DATA1 = {
|
|
|
27
27
|
"myboolean": True,
|
|
28
28
|
"mydate": "2024/04/14 12:19:17",
|
|
29
29
|
"maybeempty": "not empty",
|
|
30
|
+
"onlyinone": "blah",
|
|
30
31
|
},
|
|
31
32
|
"geometry": {"type": "Point", "coordinates": [0.065918, 48.385442]},
|
|
32
33
|
},
|
|
@@ -39,6 +40,7 @@ DATALAYER_DATA1 = {
|
|
|
39
40
|
"myboolean": False,
|
|
40
41
|
"mydate": "2024/03/13 12:20:20",
|
|
41
42
|
"maybeempty": "",
|
|
43
|
+
"onlyinone": "ffff",
|
|
42
44
|
},
|
|
43
45
|
"geometry": {"type": "Point", "coordinates": [3.55957, 49.767074]},
|
|
44
46
|
},
|
|
@@ -95,13 +97,13 @@ DATALAYER_DATA2 = {
|
|
|
95
97
|
|
|
96
98
|
def test_simple_equal_rule_at_load(live_server, page, map):
|
|
97
99
|
map.settings["properties"]["rules"] = [
|
|
98
|
-
{"condition": "mytype=odd", "
|
|
100
|
+
{"condition": "mytype=odd", "properties": {"color": "aliceblue"}}
|
|
99
101
|
]
|
|
100
102
|
map.save()
|
|
101
103
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
102
104
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
103
105
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
104
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
106
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
105
107
|
expect(markers).to_have_count(5)
|
|
106
108
|
colors = getColors(markers)
|
|
107
109
|
assert colors.count("rgb(240, 248, 255)") == 3
|
|
@@ -109,13 +111,13 @@ def test_simple_equal_rule_at_load(live_server, page, map):
|
|
|
109
111
|
|
|
110
112
|
def test_simple_not_equal_rule_at_load(live_server, page, map):
|
|
111
113
|
map.settings["properties"]["rules"] = [
|
|
112
|
-
{"condition": "mytype!=even", "
|
|
114
|
+
{"condition": "mytype!=even", "properties": {"color": "aliceblue"}}
|
|
113
115
|
]
|
|
114
116
|
map.save()
|
|
115
117
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
116
118
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
117
119
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
118
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
120
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
119
121
|
expect(markers).to_have_count(5)
|
|
120
122
|
colors = getColors(markers)
|
|
121
123
|
assert colors.count("rgb(240, 248, 255)") == 3
|
|
@@ -123,13 +125,13 @@ def test_simple_not_equal_rule_at_load(live_server, page, map):
|
|
|
123
125
|
|
|
124
126
|
def test_gt_rule_with_number_at_load(live_server, page, map):
|
|
125
127
|
map.settings["properties"]["rules"] = [
|
|
126
|
-
{"condition": "mynumber>10", "
|
|
128
|
+
{"condition": "mynumber>10", "properties": {"color": "aliceblue"}}
|
|
127
129
|
]
|
|
128
130
|
map.save()
|
|
129
131
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
130
132
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
131
133
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
132
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
134
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
133
135
|
expect(markers).to_have_count(5)
|
|
134
136
|
colors = getColors(markers)
|
|
135
137
|
assert colors.count("rgb(240, 248, 255)") == 2
|
|
@@ -137,13 +139,13 @@ def test_gt_rule_with_number_at_load(live_server, page, map):
|
|
|
137
139
|
|
|
138
140
|
def test_lt_rule_with_number_at_load(live_server, page, map):
|
|
139
141
|
map.settings["properties"]["rules"] = [
|
|
140
|
-
{"condition": "mynumber<14", "
|
|
142
|
+
{"condition": "mynumber<14", "properties": {"color": "aliceblue"}}
|
|
141
143
|
]
|
|
142
144
|
map.save()
|
|
143
145
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
144
146
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
145
147
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
146
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
148
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
147
149
|
expect(markers).to_have_count(5)
|
|
148
150
|
colors = getColors(markers)
|
|
149
151
|
assert colors.count("rgb(240, 248, 255)") == 4
|
|
@@ -151,13 +153,13 @@ def test_lt_rule_with_number_at_load(live_server, page, map):
|
|
|
151
153
|
|
|
152
154
|
def test_lt_rule_with_float_at_load(live_server, page, map):
|
|
153
155
|
map.settings["properties"]["rules"] = [
|
|
154
|
-
{"condition": "mynumber<12.3", "
|
|
156
|
+
{"condition": "mynumber<12.3", "properties": {"color": "aliceblue"}}
|
|
155
157
|
]
|
|
156
158
|
map.save()
|
|
157
159
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
158
160
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
159
161
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
160
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
162
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
161
163
|
expect(markers).to_have_count(5)
|
|
162
164
|
colors = getColors(markers)
|
|
163
165
|
assert colors.count("rgb(240, 248, 255)") == 4
|
|
@@ -165,13 +167,13 @@ def test_lt_rule_with_float_at_load(live_server, page, map):
|
|
|
165
167
|
|
|
166
168
|
def test_equal_rule_with_boolean_at_load(live_server, page, map):
|
|
167
169
|
map.settings["properties"]["rules"] = [
|
|
168
|
-
{"condition": "myboolean=true", "
|
|
170
|
+
{"condition": "myboolean=true", "properties": {"color": "aliceblue"}}
|
|
169
171
|
]
|
|
170
172
|
map.save()
|
|
171
173
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
172
174
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
173
175
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
174
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
176
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
175
177
|
expect(markers).to_have_count(5)
|
|
176
178
|
colors = getColors(markers)
|
|
177
179
|
assert colors.count("rgb(240, 248, 255)") == 2
|
|
@@ -179,13 +181,13 @@ def test_equal_rule_with_boolean_at_load(live_server, page, map):
|
|
|
179
181
|
|
|
180
182
|
def test_equal_rule_with_boolean_not_true_at_load(live_server, page, map):
|
|
181
183
|
map.settings["properties"]["rules"] = [
|
|
182
|
-
{"condition": "myboolean!=true", "
|
|
184
|
+
{"condition": "myboolean!=true", "properties": {"color": "aliceblue"}}
|
|
183
185
|
]
|
|
184
186
|
map.save()
|
|
185
187
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
186
188
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
187
189
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
188
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
190
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
189
191
|
expect(markers).to_have_count(5)
|
|
190
192
|
colors = getColors(markers)
|
|
191
193
|
assert colors.count("rgb(240, 248, 255)") == 3
|
|
@@ -193,13 +195,13 @@ def test_equal_rule_with_boolean_not_true_at_load(live_server, page, map):
|
|
|
193
195
|
|
|
194
196
|
def test_equal_rule_with_boolean_false_at_load(live_server, page, map):
|
|
195
197
|
map.settings["properties"]["rules"] = [
|
|
196
|
-
{"condition": "myboolean=false", "
|
|
198
|
+
{"condition": "myboolean=false", "properties": {"color": "aliceblue"}}
|
|
197
199
|
]
|
|
198
200
|
map.save()
|
|
199
201
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
200
202
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
201
203
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
202
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
204
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
203
205
|
expect(markers).to_have_count(5)
|
|
204
206
|
colors = getColors(markers)
|
|
205
207
|
assert colors.count("rgb(240, 248, 255)") == 1
|
|
@@ -207,13 +209,13 @@ def test_equal_rule_with_boolean_false_at_load(live_server, page, map):
|
|
|
207
209
|
|
|
208
210
|
def test_equal_rule_with_boolean_not_false_at_load(live_server, page, map):
|
|
209
211
|
map.settings["properties"]["rules"] = [
|
|
210
|
-
{"condition": "myboolean!=false", "
|
|
212
|
+
{"condition": "myboolean!=false", "properties": {"color": "aliceblue"}}
|
|
211
213
|
]
|
|
212
214
|
map.save()
|
|
213
215
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
214
216
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
215
217
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
216
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
218
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
217
219
|
expect(markers).to_have_count(5)
|
|
218
220
|
colors = getColors(markers)
|
|
219
221
|
assert colors.count("rgb(240, 248, 255)") == 4
|
|
@@ -221,13 +223,13 @@ def test_equal_rule_with_boolean_not_false_at_load(live_server, page, map):
|
|
|
221
223
|
|
|
222
224
|
def test_empty_rule_at_load(live_server, page, map):
|
|
223
225
|
map.settings["properties"]["rules"] = [
|
|
224
|
-
{"condition": "maybeempty=", "
|
|
226
|
+
{"condition": "maybeempty=", "properties": {"color": "aliceblue"}}
|
|
225
227
|
]
|
|
226
228
|
map.save()
|
|
227
229
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
228
230
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
229
231
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
230
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
232
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
231
233
|
expect(markers).to_have_count(5)
|
|
232
234
|
colors = getColors(markers)
|
|
233
235
|
assert colors.count("rgb(240, 248, 255)") == 3
|
|
@@ -235,13 +237,13 @@ def test_empty_rule_at_load(live_server, page, map):
|
|
|
235
237
|
|
|
236
238
|
def test_not_empty_rule_at_load(live_server, page, map):
|
|
237
239
|
map.settings["properties"]["rules"] = [
|
|
238
|
-
{"condition": "maybeempty!=", "
|
|
240
|
+
{"condition": "maybeempty!=", "properties": {"color": "aliceblue"}}
|
|
239
241
|
]
|
|
240
242
|
map.save()
|
|
241
243
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
242
244
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
243
245
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
244
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
246
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
245
247
|
expect(markers).to_have_count(5)
|
|
246
248
|
colors = getColors(markers)
|
|
247
249
|
assert colors.count("rgb(240, 248, 255)") == 2
|
|
@@ -251,7 +253,7 @@ def test_can_create_new_rule(live_server, page, openmap):
|
|
|
251
253
|
DataLayerFactory(map=openmap, data=DATALAYER_DATA1)
|
|
252
254
|
DataLayerFactory(map=openmap, data=DATALAYER_DATA2)
|
|
253
255
|
page.goto(f"{live_server.url}{openmap.get_absolute_url()}#6/48.948/1.670")
|
|
254
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
256
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
255
257
|
expect(markers).to_have_count(5)
|
|
256
258
|
page.get_by_role("button", name="Edit").click()
|
|
257
259
|
page.get_by_role("button", name="Map advanced properties").click()
|
|
@@ -270,13 +272,13 @@ def test_can_create_new_rule(live_server, page, openmap):
|
|
|
270
272
|
|
|
271
273
|
def test_can_deactive_rule_from_list(live_server, page, openmap):
|
|
272
274
|
openmap.settings["properties"]["rules"] = [
|
|
273
|
-
{"condition": "mytype=odd", "
|
|
275
|
+
{"condition": "mytype=odd", "properties": {"color": "aliceblue"}}
|
|
274
276
|
]
|
|
275
277
|
openmap.save()
|
|
276
278
|
DataLayerFactory(map=openmap, data=DATALAYER_DATA1)
|
|
277
279
|
DataLayerFactory(map=openmap, data=DATALAYER_DATA2)
|
|
278
280
|
page.goto(f"{live_server.url}{openmap.get_absolute_url()}#6/48.948/1.670")
|
|
279
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
281
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
280
282
|
expect(markers).to_have_count(5)
|
|
281
283
|
colors = getColors(markers)
|
|
282
284
|
assert colors.count("rgb(240, 248, 255)") == 3
|
|
@@ -299,9 +301,17 @@ def test_autocomplete_datalist(live_server, page, openmap):
|
|
|
299
301
|
page.get_by_role("button", name="Add rule").click()
|
|
300
302
|
panel = page.locator(".panel.right.on")
|
|
301
303
|
datalist = panel.locator(".umap-field-condition datalist option")
|
|
302
|
-
expect(datalist).to_have_count(
|
|
304
|
+
expect(datalist).to_have_count(7)
|
|
303
305
|
values = {option.inner_text() for option in datalist.all()}
|
|
304
|
-
assert values == {
|
|
306
|
+
assert values == {
|
|
307
|
+
"myboolean",
|
|
308
|
+
"mytype",
|
|
309
|
+
"mynumber",
|
|
310
|
+
"mydate",
|
|
311
|
+
"name",
|
|
312
|
+
"maybeempty",
|
|
313
|
+
"onlyinone",
|
|
314
|
+
}
|
|
305
315
|
page.get_by_placeholder("key=value or key!=value").fill("mytype")
|
|
306
316
|
expect(datalist).to_have_count(4)
|
|
307
317
|
values = {option.inner_text() for option in datalist.all()}
|
|
@@ -314,15 +324,15 @@ def test_autocomplete_datalist(live_server, page, openmap):
|
|
|
314
324
|
|
|
315
325
|
def test_can_combine_rules(live_server, page, map):
|
|
316
326
|
map.settings["properties"]["rules"] = [
|
|
317
|
-
{"condition": "mytype=odd", "
|
|
318
|
-
{"condition": "mynumber>10", "
|
|
327
|
+
{"condition": "mytype=odd", "properties": {"color": "aliceblue"}},
|
|
328
|
+
{"condition": "mynumber>10", "properties": {"iconClass": "Drop"}},
|
|
319
329
|
]
|
|
320
330
|
map.save()
|
|
321
331
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
322
332
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
323
333
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
324
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
325
|
-
drops = page.locator(".umap-drop-icon .
|
|
334
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
335
|
+
drops = page.locator(".umap-drop-icon .icon-container")
|
|
326
336
|
expect(markers).to_have_count(5)
|
|
327
337
|
expect(drops).to_have_count(2)
|
|
328
338
|
colors = getColors(markers)
|
|
@@ -333,14 +343,14 @@ def test_can_combine_rules(live_server, page, map):
|
|
|
333
343
|
|
|
334
344
|
def test_first_matching_rule_wins_on_given_property(live_server, page, map):
|
|
335
345
|
map.settings["properties"]["rules"] = [
|
|
336
|
-
{"condition": "mytype=odd", "
|
|
337
|
-
{"condition": "mytype!=even", "
|
|
346
|
+
{"condition": "mytype=odd", "properties": {"color": "aliceblue"}},
|
|
347
|
+
{"condition": "mytype!=even", "properties": {"color": "darkred"}},
|
|
338
348
|
]
|
|
339
349
|
map.save()
|
|
340
350
|
DataLayerFactory(map=map, data=DATALAYER_DATA1)
|
|
341
351
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
342
352
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
343
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
353
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
344
354
|
expect(markers).to_have_count(5)
|
|
345
355
|
colors = getColors(markers)
|
|
346
356
|
assert colors.count("rgb(240, 248, 255)") == 3
|
|
@@ -348,20 +358,52 @@ def test_first_matching_rule_wins_on_given_property(live_server, page, map):
|
|
|
348
358
|
|
|
349
359
|
def test_rules_from_datalayer(live_server, page, map):
|
|
350
360
|
map.settings["properties"]["rules"] = [
|
|
351
|
-
{"condition": "mytype=odd", "
|
|
361
|
+
{"condition": "mytype=odd", "properties": {"color": "darkred"}}
|
|
352
362
|
]
|
|
353
363
|
map.save()
|
|
354
364
|
data = deepcopy(DATALAYER_DATA1)
|
|
355
365
|
data["_umap_options"]["rules"] = [
|
|
356
|
-
{"condition": "mytype=odd", "
|
|
366
|
+
{"condition": "mytype=odd", "properties": {"color": "aliceblue"}}
|
|
357
367
|
]
|
|
358
368
|
DataLayerFactory(map=map, data=data)
|
|
359
369
|
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
360
370
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
361
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
371
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
362
372
|
expect(markers).to_have_count(5)
|
|
363
373
|
colors = getColors(markers)
|
|
364
374
|
# Alice Blue should only affect layer 1
|
|
365
375
|
assert colors.count("rgb(240, 248, 255)") == 1
|
|
366
376
|
# Dark Red as for map global rules
|
|
367
377
|
assert colors.count("rgb(139, 0, 0)") == 2
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def test_rules_in_caption(live_server, page, map):
|
|
381
|
+
map.settings["properties"]["rules"] = [
|
|
382
|
+
{
|
|
383
|
+
"condition": "mytype=odd",
|
|
384
|
+
"name": "Rule shown twice",
|
|
385
|
+
"properties": {"color": "darkred"},
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"condition": "onlyinone=fff",
|
|
389
|
+
"name": "Rule shown once",
|
|
390
|
+
"properties": {"color": "darkred"},
|
|
391
|
+
},
|
|
392
|
+
]
|
|
393
|
+
map.settings["properties"]["onLoadPanel"] = "caption"
|
|
394
|
+
map.save()
|
|
395
|
+
data = deepcopy(DATALAYER_DATA1)
|
|
396
|
+
data["_umap_options"]["rules"] = [
|
|
397
|
+
{
|
|
398
|
+
"condition": "myboolean=true",
|
|
399
|
+
"name": "Rule shown also once",
|
|
400
|
+
"properties": {"color": "aliceblue"},
|
|
401
|
+
}
|
|
402
|
+
]
|
|
403
|
+
DataLayerFactory(map=map, data=data)
|
|
404
|
+
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
405
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670")
|
|
406
|
+
panel = page.locator(".panel.left.on")
|
|
407
|
+
expect(panel.get_by_text("Rule shown twice")).to_have_count(2)
|
|
408
|
+
expect(panel.get_by_text("Rule shown once")).to_have_count(1)
|
|
409
|
+
expect(panel.get_by_text("Rule shown also once")).to_have_count(1)
|
|
@@ -115,7 +115,7 @@ def test_should_honour_color_variable(live_server, map, page):
|
|
|
115
115
|
DataLayerFactory(map=map, data=data)
|
|
116
116
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/47.5/2.5")
|
|
117
117
|
expect(page.locator(".leaflet-overlay-pane path[fill='tomato']"))
|
|
118
|
-
markers = page.locator(".leaflet-marker-icon .
|
|
118
|
+
markers = page.locator(".leaflet-marker-icon .icon-container")
|
|
119
119
|
expect(markers).to_have_css("background-color", "rgb(240, 248, 255)")
|
|
120
120
|
|
|
121
121
|
|
|
@@ -154,9 +154,7 @@ def test_can_draw_multi(live_server, page, tilelayer):
|
|
|
154
154
|
expect(multi_button).to_be_hidden()
|
|
155
155
|
polygons.first.click(button="right", position={"x": 10, "y": 10})
|
|
156
156
|
expect(page.get_by_role("button", name="Transform to lines")).to_be_hidden()
|
|
157
|
-
expect(
|
|
158
|
-
page.get_by_role("button", name="Remove shape from the multi")
|
|
159
|
-
).to_be_visible()
|
|
157
|
+
expect(page.get_by_role("button", name="Delete this shape")).to_be_visible()
|
|
160
158
|
|
|
161
159
|
|
|
162
160
|
def test_can_draw_hole(page, live_server, tilelayer):
|
|
@@ -179,7 +177,7 @@ def test_can_draw_hole(page, live_server, tilelayer):
|
|
|
179
177
|
expect(vertices).to_have_count(4)
|
|
180
178
|
|
|
181
179
|
# First vertex of the hole will be created here
|
|
182
|
-
map.click(position={"x": 180, "y": 120})
|
|
180
|
+
map.click(position={"x": 180, "y": 120}, button="right")
|
|
183
181
|
page.get_by_role("button", name="Start a hole here").click()
|
|
184
182
|
map.click(position={"x": 180, "y": 180})
|
|
185
183
|
map.click(position={"x": 120, "y": 180})
|
|
@@ -474,7 +472,7 @@ def test_vertexmarker_not_shown_if_too_many(live_server, map, page, settings):
|
|
|
474
472
|
page.locator(".umap-import textarea").fill(geojson)
|
|
475
473
|
page.locator('select[name="format"]').select_option("geojson")
|
|
476
474
|
page.get_by_role("button", name="Import data", exact=True).click()
|
|
477
|
-
page.locator("path").click()
|
|
475
|
+
page.locator("path").click(button="right")
|
|
478
476
|
page.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
479
477
|
expect(page.locator(".umap-tooltip-container")).to_contain_text(
|
|
480
478
|
"Please zoom in to edit the geometry"
|
|
@@ -150,9 +150,7 @@ def test_can_draw_multi(live_server, page, tilelayer):
|
|
|
150
150
|
expect(add_shape).to_be_hidden()
|
|
151
151
|
lines.first.click(button="right", position={"x": 10, "y": 1})
|
|
152
152
|
expect(page.get_by_role("button", name="Transform to polygon")).to_be_hidden()
|
|
153
|
-
expect(
|
|
154
|
-
page.get_by_role("button", name="Remove shape from the multi")
|
|
155
|
-
).to_be_visible()
|
|
153
|
+
expect(page.get_by_role("button", name="Delete this shape")).to_be_visible()
|
|
156
154
|
|
|
157
155
|
|
|
158
156
|
def test_can_transfer_shape_from_simple_polyline(live_server, page, tilelayer):
|
|
@@ -328,11 +326,11 @@ def test_can_delete_shape_using_toolbar(live_server, page, tilelayer, settings):
|
|
|
328
326
|
map.click(position={"x": 100, "y": 200})
|
|
329
327
|
|
|
330
328
|
# Now split the line
|
|
331
|
-
map.click(position={"x": 100, "y": 100})
|
|
329
|
+
map.click(position={"x": 100, "y": 100}, button="right")
|
|
332
330
|
page.get_by_role("button", name="Split line").click()
|
|
333
331
|
|
|
334
332
|
# Delete part of it
|
|
335
|
-
map.click(position={"x": 125, "y": 100})
|
|
333
|
+
map.click(position={"x": 125, "y": 100}, button="right")
|
|
336
334
|
page.get_by_role("button", name="Delete this shape").click()
|
|
337
335
|
data = save_and_get_json(page)
|
|
338
336
|
assert len(data["features"]) == 1
|
|
@@ -369,7 +367,7 @@ def test_can_merge_lines(live_server, page, tilelayer, settings):
|
|
|
369
367
|
)
|
|
370
368
|
|
|
371
369
|
# Right click and merge nodes
|
|
372
|
-
map.click(button="right", position={"x": 100, "y":
|
|
370
|
+
map.click(button="right", position={"x": 100, "y": 120})
|
|
373
371
|
page.get_by_role("button", name="Merge lines").click()
|
|
374
372
|
data = save_and_get_json(page)
|
|
375
373
|
assert len(data["features"]) == 1
|