wurk 1.0.4 → 1.0.6
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.
- checksums.yaml +4 -4
- data/app/controllers/wurk/api/serializers.rb +2 -2
- data/lib/wurk/version.rb +1 -1
- data/vendor/assets/dashboard/apple-touch-icon.png +0 -0
- data/vendor/assets/dashboard/assets/AreaChart-CyZ2awLz.js +53 -0
- data/vendor/assets/dashboard/assets/ArgsValue-DkNZasfN.js +1 -0
- data/vendor/assets/dashboard/assets/BatchDetail-GNWN2Qa5.js +1 -0
- data/vendor/assets/dashboard/assets/Batches-CMHh4yl3.js +1 -0
- data/vendor/assets/dashboard/assets/Busy-DzPOMFHP.js +1 -0
- data/vendor/assets/dashboard/assets/Cron-CS11vEOM.js +1 -0
- data/vendor/assets/dashboard/assets/Dashboard-JZEYG_84.js +1 -0
- data/vendor/assets/dashboard/assets/Dead-CPyPEPZe.js +1 -0
- data/vendor/assets/dashboard/assets/Extension-C2iDCCej.js +1 -0
- data/vendor/assets/dashboard/assets/JobDetailModal-DokU_RzZ.js +2 -0
- data/vendor/assets/dashboard/assets/Limiters-B30yOq_H.js +1 -0
- data/vendor/assets/dashboard/assets/Metrics-D1N6qjkS.js +7 -0
- data/vendor/assets/dashboard/assets/Modal-pu_rlxM0.js +1 -0
- data/vendor/assets/dashboard/assets/PageHeader-Db9inHPu.js +1 -0
- data/vendor/assets/dashboard/assets/Profiles-CoDtYfSq.js +1 -0
- data/vendor/assets/dashboard/assets/Queues-Bv2j9UcA.js +1 -0
- data/vendor/assets/dashboard/assets/Retries-DulJz1La.js +1 -0
- data/vendor/assets/dashboard/assets/Scheduled-B7KZUYJf.js +1 -0
- data/vendor/assets/dashboard/assets/Search-_zL0GqzG.js +1 -0
- data/vendor/assets/dashboard/assets/fa-brands-400-BK5CuonO.woff2 +0 -0
- data/vendor/assets/dashboard/assets/fa-regular-400-WLfxSHV3.woff2 +0 -0
- data/vendor/assets/dashboard/assets/fa-solid-900-Iz_TytpP.woff2 +0 -0
- data/vendor/assets/dashboard/assets/fa-v4compatibility-CMhGCN2W.woff2 +0 -0
- data/vendor/assets/dashboard/assets/index-DdkkU3x4.css +1 -0
- data/vendor/assets/dashboard/assets/index-oCfJv9j0.js +126 -0
- data/vendor/assets/dashboard/assets/useJobSetActions-DixonfPh.js +1 -0
- data/vendor/assets/dashboard/assets/useMutation-DWBRM-DR.js +1 -0
- data/vendor/assets/dashboard/assets/usePageParam-h6ZwD64I.js +1 -0
- data/vendor/assets/dashboard/assets/useSort-k9b5fes0.js +1 -0
- data/vendor/assets/dashboard/assets/utils-DDJC7tJV.js +1 -0
- data/vendor/assets/dashboard/favicon-16.png +0 -0
- data/vendor/assets/dashboard/favicon-32.png +0 -0
- data/vendor/assets/dashboard/favicon.png +0 -0
- data/vendor/assets/dashboard/index.html +35 -6
- data/vendor/assets/dashboard/og-image.png +0 -0
- data/vendor/assets/dashboard/wurk-logo.webp +0 -0
- data/vendor/assets/dashboard/wurk-manifest.json +2 -2
- metadata +36 -6
- data/vendor/assets/dashboard/assets/fa-brands-400-BP5tdqmh.woff2 +0 -0
- data/vendor/assets/dashboard/assets/fa-regular-400-nyy7hhHF.woff2 +0 -0
- data/vendor/assets/dashboard/assets/fa-solid-900-DRAAbZTg.woff2 +0 -0
- data/vendor/assets/dashboard/assets/index-BCGWUExk.js +0 -143
- data/vendor/assets/dashboard/assets/index-MNiNmpDL.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./useMutation-DWBRM-DR.js";import{C as t,b as n,c as r,i,s as a}from"./index-oCfJv9j0.js";var o=r();function s({bulk:e,all:t,selectedCount:n,total:r,pending:a,onBulk:s,onAll:c}){let l=(e,t)=>!e.danger||window.confirm(i(`actions.confirm`,{action:e.label,scope:t}));return(0,o.jsxs)(`div`,{className:`action-bar`,children:[(0,o.jsxs)(`div`,{className:`action-bar-group`,children:[(0,o.jsx)(`span`,{className:`action-bar-count`,children:n>0?i(`actions.selected`,{n}):i(`actions.select_hint`)}),e.map(e=>(0,o.jsx)(`button`,{className:`btn btn-sm${e.danger?` btn-danger`:``}`,disabled:a||n===0,onClick:()=>l(e,i(`actions.scope_selected`,{n}))&&s(e.cmd),children:e.label},e.cmd))]}),(0,o.jsx)(`div`,{className:`action-bar-group`,children:t.map(e=>(0,o.jsx)(`button`,{className:`btn btn-sm btn-ghost${e.danger?` btn-danger`:``}`,disabled:a||r===0,onClick:()=>l(e,i(`actions.scope_all`))&&c(e.cmd),children:`${e.label} ${i(`actions.all_suffix`)}`},e.cmd))})]})}var c=t(n(),1);function l(){let[e,t]=(0,c.useState)(new Set),n=(0,c.useCallback)(e=>{t(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),r=(0,c.useCallback)(e=>{t(t=>e.length>0&&e.every(e=>t.has(e))?new Set:new Set(e))},[]),i=(0,c.useCallback)(()=>t(new Set),[]);return(0,c.useMemo)(()=>({selected:e,toggle:n,toggleAll:r,clear:i,count:e.size}),[e,n,r,i])}function u(e){return`${e.score}|${e.jid}`}async function d(e,t){let n=await fetch(e,{method:`POST`,headers:t?{"Content-Type":`application/json`}:{},body:t?JSON.stringify(t):void 0});if(!n.ok)throw Error(`Request failed (${n.status})`);return n}function f(t){let n=a(),r=()=>{n.invalidateQueries({queryKey:[t]}),n.invalidateQueries({queryKey:[`stats`]})};return{single:e({mutationFn:({key:e,cmd:n})=>d(`/wurk/api/${t}/${encodeURIComponent(e)}`,{cmd:n}),onSuccess:r}),bulk:e({mutationFn:({keys:e,cmd:n})=>d(`/wurk/api/${t}`,{keys:e,cmd:n}),onSuccess:r}),all:e({mutationFn:e=>d(`/wurk/api/${t}/all/${e}`),onSuccess:r})}}export{s as i,f as n,l as r,u as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{C as e,b as t,d as n,f as r,h as i,l as a,m as o,p as s,s as c,u as l}from"./index-oCfJv9j0.js";var u=class extends l{#e;#t=void 0;#n;#r;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#i()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),o(this.options,t)||this.#e.getMutationCache().notify({type:`observerOptionsUpdated`,mutation:this.#n,observer:this}),t?.mutationKey&&this.options.mutationKey&&r(t.mutationKey)!==r(this.options.mutationKey)?this.reset():this.#n?.state.status===`pending`&&this.#n.setOptions(this.options)}onUnsubscribe(){this.hasListeners()||this.#n?.removeObserver(this)}onMutationUpdate(e){this.#i(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#n?.removeObserver(this),this.#n=void 0,this.#i(),this.#a()}mutate(e,t){return this.#r=t,this.#n?.removeObserver(this),this.#n=this.#e.getMutationCache().build(this.#e,this.options),this.#n.addObserver(this),this.#n.execute(e)}#i(){let e=this.#n?.state??a();this.#t={...e,isPending:e.status===`pending`,isSuccess:e.status===`success`,isError:e.status===`error`,isIdle:e.status===`idle`,mutate:this.mutate,reset:this.reset}}#a(e){n.batch(()=>{if(this.#r&&this.hasListeners()){let t=this.#t.variables,n=this.#t.context,r={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type===`success`){try{this.#r.onSuccess?.(e.data,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(e.data,null,t,n,r)}catch(e){Promise.reject(e)}}else if(e?.type===`error`){try{this.#r.onError?.(e.error,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(void 0,e.error,t,n,r)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#t)})})}},d=e(t(),1);function f(e,t){let r=c(t),[a]=d.useState(()=>new u(r,e));d.useEffect(()=>{a.setOptions(e)},[a,e]);let o=d.useSyncExternalStore(d.useCallback(e=>a.subscribe(n.batchCalls(e)),[a]),()=>a.getCurrentResult(),()=>a.getCurrentResult()),l=d.useCallback((e,t)=>{a.mutate(e,t).catch(s)},[a]);if(o.error&&i(a.options.throwOnError,[o.error]))throw o.error;return{...o,mutate:l,mutateAsync:o.mutate}}export{f as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as e,i as t,v as n}from"./index-oCfJv9j0.js";var r=e();function i({page:e,total:n,count:i,onChange:a}){let o=Math.max(1,Math.ceil(n/i));return(0,r.jsxs)(`div`,{className:`pagination`,children:[(0,r.jsx)(`button`,{className:`btn`,disabled:e<=1,onClick:()=>a(e-1),style:{opacity:e<=1?.4:1},children:t(`actions.prev`)}),(0,r.jsxs)(`span`,{children:[t(`common.page`),` `,e,` `,t(`common.of`),` `,o]}),(0,r.jsx)(`button`,{className:`btn`,disabled:e>=o,onClick:()=>a(e+1),style:{opacity:e>=o?.4:1},children:t(`actions.next`)})]})}function a(){let[e,t]=n(),r=parseInt(e.get(`page`)??`1`,10);return[Number.isFinite(r)&&r>0?r:1,e=>{t(t=>{let n=new URLSearchParams(t);return e<=1?n.delete(`page`):n.set(`page`,String(e)),n},{replace:!1})}]}export{i as n,a as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{C as e,b as t,c as n}from"./index-oCfJv9j0.js";var r=n();function i({label:e,sortKey:t,sort:n,onSort:i,style:a}){let o=n.key===t,s=o?n.dir===`asc`?`fa-arrow-up-short-wide`:`fa-arrow-down-wide-short`:`fa-sort`;return(0,r.jsx)(`th`,{className:`th-sortable`,"aria-sort":o?n.dir===`asc`?`ascending`:`descending`:`none`,style:a,children:(0,r.jsxs)(`button`,{type:`button`,className:`th-sortable__btn`,onClick:()=>i(t),children:[e,(0,r.jsx)(`i`,{className:`fa-solid ${s} th-sortable__icon${o?` is-active`:``}`,"aria-hidden":`true`})]})})}var a=e(t(),1);function o(e,t,n){let[r,i]=(0,a.useState)(n??{key:null,dir:`asc`});return{sorted:(0,a.useMemo)(()=>{let n=r.key?t[r.key]:void 0;if(!n)return e;let i=[...e];return i.sort((e,t)=>{let i=n(e),a=n(t);if(i==null&&a==null)return 0;if(i==null)return 1;if(a==null)return-1;let o=typeof i==`number`&&typeof a==`number`?i-a:String(i).localeCompare(String(a),void 0,{numeric:!0,sensitivity:`base`});return r.dir===`asc`?o:-o}),i},[e,r,t]),sort:r,toggle:e=>i(t=>t.key===e?{key:e,dir:t.dir===`asc`?`desc`:`asc`}:{key:e,dir:`asc`})}}export{i as n,o as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){if(!Number.isFinite(e))return`—`;let t=Date.now()/1e3-e,n=Math.abs(t),r=t<0,i;return i=n<60?`${Math.round(n)}s`:n<3600?`${Math.round(n/60)}m`:n<86400?`${Math.round(n/3600)}h`:`${Math.round(n/86400)}d`,r?`${i} from now`:`${i} ago`}function t(e){let t=e*1e3;return Number.isFinite(t)?new Date(t).toISOString():``}function n(e){if(!Number.isFinite(e))return`—`;let t=Math.abs(e);if(t<1)return`${Math.round(t*1e3)}ms`;if(t<10)return`${t.toFixed(1)}s`;let n=Math.round(t);return n<60?`${n}s`:n<3600?`${Math.floor(n/60)}m ${n%60}s`:n<86400?`${Math.floor(n/3600)}h ${Math.floor(n%3600/60)}m`:`${Math.floor(n/86400)}d ${Math.floor(n%86400/3600)}h`}function r(e){if(!Number.isFinite(e)||e<=0)return`—`;if(e<1024)return`${Math.round(e)} KB`;let t=e/1024;return t<1024?`${Math.round(t)} MB`:`${(t/1024).toFixed(1)} GB`}function i(e,t=80){return e==null?``:e.length<=t?e:e.slice(0,t)+`…`}function a(e){try{return JSON.stringify(e)}catch{return String(e)}}export{e as a,t as i,n,i as o,r,a as t};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -2,17 +2,46 @@
|
|
|
2
2
|
<html lang="en" data-theme="dark">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<meta name="color-scheme" content="dark" />
|
|
7
|
-
<meta name="theme-color" content="#
|
|
7
|
+
<meta name="theme-color" content="#09090b" />
|
|
8
8
|
<!-- The dashboard is dark-only. Tell the Dark Reader extension not to
|
|
9
9
|
re-invert it — otherwise it washes the already-dark UI to white. -->
|
|
10
10
|
<meta name="darkreader-lock" />
|
|
11
|
-
<meta
|
|
11
|
+
<meta
|
|
12
|
+
name="description"
|
|
13
|
+
content="Wurk — a free, faster, 100% drop-in replacement for Sidekiq + Sidekiq Pro + Sidekiq Enterprise. Real fork-based parallelism, mountable Rails engine, live dashboard."
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
<!-- Icons (served by the engine under /wurk-assets/). -->
|
|
17
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/wurk-assets/favicon-32.png" />
|
|
18
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/wurk-assets/favicon-16.png" />
|
|
12
19
|
<link rel="icon" type="image/png" href="/wurk-assets/favicon.png" />
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/wurk-assets/apple-touch-icon.png" />
|
|
21
|
+
|
|
22
|
+
<!-- Open Graph. -->
|
|
23
|
+
<meta property="og:type" content="website" />
|
|
24
|
+
<meta property="og:title" content="Wurk — Background jobs dashboard" />
|
|
25
|
+
<meta
|
|
26
|
+
property="og:description"
|
|
27
|
+
content="Wurk — a free, faster, 100% drop-in replacement for Sidekiq + Sidekiq Pro + Sidekiq Enterprise. Real fork-based parallelism, mountable Rails engine, live dashboard."
|
|
28
|
+
/>
|
|
29
|
+
<meta property="og:image" content="/wurk-assets/og-image.png" />
|
|
30
|
+
<meta property="og:image:width" content="1200" />
|
|
31
|
+
<meta property="og:image:height" content="630" />
|
|
32
|
+
|
|
33
|
+
<!-- Twitter. -->
|
|
34
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
35
|
+
<meta name="twitter:title" content="Wurk — Background jobs dashboard" />
|
|
36
|
+
<meta
|
|
37
|
+
name="twitter:description"
|
|
38
|
+
content="Wurk — a free, faster, 100% drop-in replacement for Sidekiq + Sidekiq Pro + Sidekiq Enterprise. Real fork-based parallelism, mountable Rails engine, live dashboard."
|
|
39
|
+
/>
|
|
40
|
+
<meta name="twitter:image" content="/wurk-assets/og-image.png" />
|
|
41
|
+
|
|
42
|
+
<title>Wurk — Background Jobs</title>
|
|
43
|
+
<script type="module" crossorigin src="/wurk-assets/assets/index-oCfJv9j0.js"></script>
|
|
44
|
+
<link rel="stylesheet" crossorigin href="/wurk-assets/assets/index-DdkkU3x4.css">
|
|
16
45
|
</head>
|
|
17
46
|
<body>
|
|
18
47
|
<div id="wurk-root"></div>
|
|
Binary file
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wurk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- developerz.ai
|
|
@@ -269,9 +269,30 @@ files:
|
|
|
269
269
|
- lib/wurk/work_set.rb
|
|
270
270
|
- lib/wurk/worker.rb
|
|
271
271
|
- lib/wurk/worker/setter.rb
|
|
272
|
-
- vendor/assets/dashboard/
|
|
273
|
-
- vendor/assets/dashboard/assets/
|
|
274
|
-
- vendor/assets/dashboard/assets/
|
|
272
|
+
- vendor/assets/dashboard/apple-touch-icon.png
|
|
273
|
+
- vendor/assets/dashboard/assets/AreaChart-CyZ2awLz.js
|
|
274
|
+
- vendor/assets/dashboard/assets/ArgsValue-DkNZasfN.js
|
|
275
|
+
- vendor/assets/dashboard/assets/BatchDetail-GNWN2Qa5.js
|
|
276
|
+
- vendor/assets/dashboard/assets/Batches-CMHh4yl3.js
|
|
277
|
+
- vendor/assets/dashboard/assets/Busy-DzPOMFHP.js
|
|
278
|
+
- vendor/assets/dashboard/assets/Cron-CS11vEOM.js
|
|
279
|
+
- vendor/assets/dashboard/assets/Dashboard-JZEYG_84.js
|
|
280
|
+
- vendor/assets/dashboard/assets/Dead-CPyPEPZe.js
|
|
281
|
+
- vendor/assets/dashboard/assets/Extension-C2iDCCej.js
|
|
282
|
+
- vendor/assets/dashboard/assets/JobDetailModal-DokU_RzZ.js
|
|
283
|
+
- vendor/assets/dashboard/assets/Limiters-B30yOq_H.js
|
|
284
|
+
- vendor/assets/dashboard/assets/Metrics-D1N6qjkS.js
|
|
285
|
+
- vendor/assets/dashboard/assets/Modal-pu_rlxM0.js
|
|
286
|
+
- vendor/assets/dashboard/assets/PageHeader-Db9inHPu.js
|
|
287
|
+
- vendor/assets/dashboard/assets/Profiles-CoDtYfSq.js
|
|
288
|
+
- vendor/assets/dashboard/assets/Queues-Bv2j9UcA.js
|
|
289
|
+
- vendor/assets/dashboard/assets/Retries-DulJz1La.js
|
|
290
|
+
- vendor/assets/dashboard/assets/Scheduled-B7KZUYJf.js
|
|
291
|
+
- vendor/assets/dashboard/assets/Search-_zL0GqzG.js
|
|
292
|
+
- vendor/assets/dashboard/assets/fa-brands-400-BK5CuonO.woff2
|
|
293
|
+
- vendor/assets/dashboard/assets/fa-regular-400-WLfxSHV3.woff2
|
|
294
|
+
- vendor/assets/dashboard/assets/fa-solid-900-Iz_TytpP.woff2
|
|
295
|
+
- vendor/assets/dashboard/assets/fa-v4compatibility-CMhGCN2W.woff2
|
|
275
296
|
- vendor/assets/dashboard/assets/geist-sans-latin-400-normal-BOaIZNA2.woff
|
|
276
297
|
- vendor/assets/dashboard/assets/geist-sans-latin-400-normal-gapTbOY8.woff2
|
|
277
298
|
- vendor/assets/dashboard/assets/geist-sans-latin-500-normal-CN2lyvyL.woff
|
|
@@ -280,8 +301,8 @@ files:
|
|
|
280
301
|
- vendor/assets/dashboard/assets/geist-sans-latin-600-normal-DFOURf8L.woff2
|
|
281
302
|
- vendor/assets/dashboard/assets/geist-sans-latin-700-normal-BmN9tIp5.woff2
|
|
282
303
|
- vendor/assets/dashboard/assets/geist-sans-latin-700-normal-CjScfYeH.woff
|
|
283
|
-
- vendor/assets/dashboard/assets/index-
|
|
284
|
-
- vendor/assets/dashboard/assets/index-
|
|
304
|
+
- vendor/assets/dashboard/assets/index-DdkkU3x4.css
|
|
305
|
+
- vendor/assets/dashboard/assets/index-oCfJv9j0.js
|
|
285
306
|
- vendor/assets/dashboard/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff
|
|
286
307
|
- vendor/assets/dashboard/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2
|
|
287
308
|
- vendor/assets/dashboard/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff
|
|
@@ -291,9 +312,18 @@ files:
|
|
|
291
312
|
- vendor/assets/dashboard/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2
|
|
292
313
|
- vendor/assets/dashboard/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff
|
|
293
314
|
- vendor/assets/dashboard/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff
|
|
315
|
+
- vendor/assets/dashboard/assets/useJobSetActions-DixonfPh.js
|
|
316
|
+
- vendor/assets/dashboard/assets/useMutation-DWBRM-DR.js
|
|
317
|
+
- vendor/assets/dashboard/assets/usePageParam-h6ZwD64I.js
|
|
318
|
+
- vendor/assets/dashboard/assets/useSort-k9b5fes0.js
|
|
319
|
+
- vendor/assets/dashboard/assets/utils-DDJC7tJV.js
|
|
294
320
|
- vendor/assets/dashboard/assets/wurk-logo-Vy3xW4K0.png
|
|
321
|
+
- vendor/assets/dashboard/favicon-16.png
|
|
322
|
+
- vendor/assets/dashboard/favicon-32.png
|
|
295
323
|
- vendor/assets/dashboard/favicon.png
|
|
296
324
|
- vendor/assets/dashboard/index.html
|
|
325
|
+
- vendor/assets/dashboard/og-image.png
|
|
326
|
+
- vendor/assets/dashboard/wurk-logo.webp
|
|
297
327
|
- vendor/assets/dashboard/wurk-manifest.json
|
|
298
328
|
homepage: https://github.com/developerz-ai/wurk
|
|
299
329
|
licenses:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|