diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 8c7cd042..ff5b1bc9 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -14,6 +14,7 @@ "customize-cra": "^0.2.12", "less": "^3.9.0", "less-loader": "^5.0.0", + "node-sass": "^4.12.0", "react": "^16.8.6", "react-app-rewired": "^2.1.3", "react-dom": "^16.8.6", diff --git a/cvat-ui/public/cvat.min.js b/cvat-ui/public/cvat.min.js index 0722a8a6..66bc2712 100644 --- a/cvat-ui/public/cvat.min.js +++ b/cvat-ui/public/cvat.min.js @@ -1,22 +1,22 @@ -!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=79)}([function(e,t,r){(function(t){var r="object",n=function(e){return e&&e.Math==Math&&e};e.exports=n(typeof globalThis==r&&globalThis)||n(typeof window==r&&window)||n(typeof self==r&&self)||n(typeof t==r&&t)||Function("return this")()}).call(this,r(33))},function(e,t,r){var n=r(0),o=r(24),i=r(48),a=r(85),s=n.Symbol,c=o("wks");e.exports=function(e){return c[e]||(c[e]=a&&s[e]||(a?s:i)("Symbol."+e))}},function(e,t,r){var n=r(7);e.exports=function(e){if(!n(e))throw TypeError(String(e)+" is not an object");return e}},function(e,t,r){"use strict";var n=r(70),o=r(113),i=Object.prototype.toString;function a(e){return"[object Array]"===i.call(e)}function s(e){return null!==e&&"object"==typeof e}function c(e){return"[object Function]"===i.call(e)}function u(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),a(e))for(var r=0,n=e.length;r=t.length?(e.target=void 0,{value:void 0,done:!0}):"keys"==r?{value:n,done:!1}:"values"==r?{value:t[n],done:!1}:{value:[n,t[n]],done:!1}},"values"),i.Arguments=i.Array,o("keys"),o("values"),o("entries")},function(e,t,r){"use strict";var n,o,i,a=r(11),s=r(18),c=r(0),u=r(50),l=r(54),f=r(19),p=r(86),h=r(7),d=r(28),v=r(41),g=r(14),m=r(87),b=r(89),w=r(90),y=r(57).set,x=r(91),S=r(92),O=r(93),j=r(60),k=r(94),E=r(59),A=r(16),T=r(53),P=r(1)("species"),I="Promise",R=A.get,C=A.set,L=A.getterFor(I),N=c.Promise,$=c.TypeError,_=c.document,M=c.process,F=c.fetch,U=M&&M.versions,B=U&&U.v8||"",z=j.f,D=z,W="process"==g(M),q=!!(_&&_.createEvent&&c.dispatchEvent),G=T(I,function(){var e=N.resolve(1),t=function(){},r=(e.constructor={})[P]=function(e){e(t,t)};return!((W||"function"==typeof PromiseRejectionEvent)&&(!s||e.finally)&&e.then(t)instanceof r&&0!==B.indexOf("6.6")&&-1===E.indexOf("Chrome/66"))}),J=G||!b(function(e){N.all(e).catch(function(){})}),V=function(e){var t;return!(!h(e)||"function"!=typeof(t=e.then))&&t},X=function(e,t,r){if(!t.notified){t.notified=!0;var n=t.reactions;x(function(){for(var o=t.value,i=1==t.state,a=0;n.length>a;){var s,c,u,l=n[a++],f=i?l.ok:l.fail,p=l.resolve,h=l.reject,d=l.domain;try{f?(i||(2===t.rejection&&Z(e,t),t.rejection=1),!0===f?s=o:(d&&d.enter(),s=f(o),d&&(d.exit(),u=!0)),s===l.promise?h($("Promise-chain cycle")):(c=V(s))?c.call(s,p,h):p(s)):h(o)}catch(e){d&&!u&&d.exit(),h(e)}}t.reactions=[],t.notified=!1,r&&!t.rejection&&H(e,t)})}},K=function(e,t,r){var n,o;q?((n=_.createEvent("Event")).promise=t,n.reason=r,n.initEvent(e,!1,!0),c.dispatchEvent(n)):n={promise:t,reason:r},(o=c["on"+e])?o(n):"unhandledrejection"===e&&O("Unhandled promise rejection",r)},H=function(e,t){y.call(c,function(){var r,n=t.value;if(Y(t)&&(r=k(function(){W?M.emit("unhandledRejection",n,e):K("unhandledrejection",e,n)}),t.rejection=W||Y(t)?2:1,r.error))throw r.value})},Y=function(e){return 1!==e.rejection&&!e.parent},Z=function(e,t){y.call(c,function(){W?M.emit("rejectionHandled",e):K("rejectionhandled",e,t.value)})},Q=function(e,t,r,n){return function(o){e(t,r,o,n)}},ee=function(e,t,r,n){t.done||(t.done=!0,n&&(t=n),t.value=r,t.state=2,X(e,t,!0))},te=function(e,t,r,n){if(!t.done){t.done=!0,n&&(t=n);try{if(e===r)throw $("Promise can't be resolved itself");var o=V(r);o?x(function(){var n={done:!1};try{o.call(r,Q(te,e,n,t),Q(ee,e,n,t))}catch(r){ee(e,n,r,t)}}):(t.value=r,t.state=1,X(e,t,!1))}catch(r){ee(e,{done:!1},r,t)}}};G&&(N=function(e){v(this,N,I),d(e),n.call(this);var t=R(this);try{e(Q(te,this,t),Q(ee,this,t))}catch(e){ee(this,t,e)}},(n=function(e){C(this,{type:I,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=l(N.prototype,{then:function(e,t){var r=L(this),n=z(w(this,N));return n.ok="function"!=typeof e||e,n.fail="function"==typeof t&&t,n.domain=W?M.domain:void 0,r.parent=!0,r.reactions.push(n),0!=r.state&&X(this,r,!1),n.promise},catch:function(e){return this.then(void 0,e)}}),o=function(){var e=new n,t=R(e);this.promise=e,this.resolve=Q(te,e,t),this.reject=Q(ee,e,t)},j.f=z=function(e){return e===N||e===i?new o(e):D(e)},s||"function"!=typeof F||a({global:!0,enumerable:!0,forced:!0},{fetch:function(e){return S(N,F.apply(c,arguments))}})),a({global:!0,wrap:!0,forced:G},{Promise:N}),f(N,I,!1,!0),p(I),i=u.Promise,a({target:I,stat:!0,forced:G},{reject:function(e){var t=z(this);return t.reject.call(void 0,e),t.promise}}),a({target:I,stat:!0,forced:s||G},{resolve:function(e){return S(s&&this===i?N:this,e)}}),a({target:I,stat:!0,forced:J},{all:function(e){var t=this,r=z(t),n=r.resolve,o=r.reject,i=k(function(){var r=d(t.resolve),i=[],a=0,s=1;m(e,function(e){var c=a++,u=!1;i.push(void 0),s++,r.call(t,e).then(function(e){u||(u=!0,i[c]=e,--s||n(i))},o)}),--s||n(i)});return i.error&&o(i.value),r.promise},race:function(e){var t=this,r=z(t),n=r.reject,o=k(function(){var o=d(t.resolve);m(e,function(e){o.call(t,e).then(r.resolve,n)})});return o.error&&n(o.value),r.promise}})},function(e,t,r){var n=r(0),o=r(34).f,i=r(8),a=r(15),s=r(37),c=r(49),u=r(53);e.exports=function(e,t){var r,l,f,p,h,d=e.target,v=e.global,g=e.stat;if(r=v?n:g?n[d]||s(d,{}):(n[d]||{}).prototype)for(l in t){if(p=t[l],f=e.noTargetGet?(h=o(r,l))&&h.value:r[l],!u(v?l:d+(g?".":"#")+l,e.forced)&&void 0!==f){if(typeof p==typeof f)continue;c(p,f)}(e.sham||f&&f.sham)&&i(p,"sham",!0),a(r,l,p,e)}}},function(e,t,r){var n=r(6),o=r(46),i=r(2),a=r(35),s=Object.defineProperty;t.f=n?s:function(e,t,r){if(i(e),t=a(t,!0),i(r),o)try{return s(e,t,r)}catch(e){}if("get"in r||"set"in r)throw TypeError("Accessors not supported");return"value"in r&&(e[t]=r.value),e}},function(e,t,r){var n=r(0),o=r(100),i=r(9),a=r(8),s=r(1),c=s("iterator"),u=s("toStringTag"),l=i.values;for(var f in o){var p=n[f],h=p&&p.prototype;if(h){if(h[c]!==l)try{a(h,c,l)}catch(e){h[c]=l}if(h[u]||a(h,u,f),o[f])for(var d in i)if(h[d]!==i[d])try{a(h,d,i[d])}catch(e){h[d]=i[d]}}}},function(e,t){var r={}.toString;e.exports=function(e){return r.call(e).slice(8,-1)}},function(e,t,r){var n=r(0),o=r(24),i=r(8),a=r(5),s=r(37),c=r(47),u=r(16),l=u.get,f=u.enforce,p=String(c).split("toString");o("inspectSource",function(e){return c.call(e)}),(e.exports=function(e,t,r,o){var c=!!o&&!!o.unsafe,u=!!o&&!!o.enumerable,l=!!o&&!!o.noTargetGet;"function"==typeof r&&("string"!=typeof t||a(r,"name")||i(r,"name",t),f(r).source=p.join("string"==typeof t?t:"")),e!==n?(c?!l&&e[t]&&(u=!0):delete e[t],u?e[t]=r:i(e,t,r)):u?e[t]=r:s(t,r)})(Function.prototype,"toString",function(){return"function"==typeof this&&l(this).source||c.call(this)})},function(e,t,r){var n,o,i,a=r(80),s=r(0),c=r(7),u=r(8),l=r(5),f=r(38),p=r(39),h=s.WeakMap;if(a){var d=new h,v=d.get,g=d.has,m=d.set;n=function(e,t){return m.call(d,e,t),t},o=function(e){return v.call(d,e)||{}},i=function(e){return g.call(d,e)}}else{var b=f("state");p[b]=!0,n=function(e,t){return u(e,b,t),t},o=function(e){return l(e,b)?e[b]:{}},i=function(e){return l(e,b)}}e.exports={set:n,get:o,has:i,enforce:function(e){return i(e)?o(e):n(e,{})},getterFor:function(e){return function(t){var r;if(!c(t)||(r=o(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return r}}}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t){e.exports=!1},function(e,t,r){var n=r(12).f,o=r(5),i=r(1)("toStringTag");e.exports=function(e,t,r){e&&!o(e=r?e:e.prototype,i)&&n(e,i,{configurable:!0,value:t})}},function(e,t){e.exports={}},function(e,t,r){r(95),r(9),r(10),r(13),(()=>{const{PluginError:t}=r(68),n=[];e.exports=class{static async apiWrapper(e,...r){const n=await window.cvat.plugins.list.implementation();for(const o of n){const n=o.functions.filter(t=>t.callback===e)[0];if(n&&n.enter)try{await n.enter.call(this,o,...r)}catch(e){throw e instanceof t?e:new t(`Exception in plugin ${o.name}: ${e.toString()}`)}}let o=await e.implementation.call(this,...r);for(const i of n){const n=i.functions.filter(t=>t.callback===e)[0];if(n&&n.leave)try{o=await n.leave.call(this,i,o,...r)}catch(e){throw e instanceof t?e:new t(`Exception in plugin ${i.name}: ${e.toString()}`)}}return o}static async register(e){const r=[];if("object"!=typeof e)throw new t(`Plugin should be an object, but got "${typeof e}"`);if(!("name"in e)||"string"!=typeof e.name)throw new t('Plugin must contain a "name" field and it must be a string');if(!("description"in e)||"string"!=typeof e.description)throw new t('Plugin must contain a "description" field and it must be a string');if("functions"in e)throw new t('Plugin must not contain a "functions" field');!function e(t,n){const o={};for(const r in t)Object.prototype.hasOwnProperty.call(t,r)&&("object"==typeof t[r]?Object.prototype.hasOwnProperty.call(n,r)&&e(t[r],n[r]):["enter","leave"].includes(r)&&"function"==typeof n&&(t[r],1)&&(o.callback=n,o[r]=t[r]));Object.keys(o).length&&r.push(o)}(e,{cvat:window.cvat}),Object.defineProperty(e,"functions",{value:r,writable:!1}),n.push(e)}static async list(){return n}}})()},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,r){var n=r(45),o=r(17);e.exports=function(e){return n(o(e))}},function(e,t,r){var n=r(0),o=r(37),i=r(18),a=n["__core-js_shared__"]||o("__core-js_shared__",{});(e.exports=function(e,t){return a[e]||(a[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.1.3",mode:i?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t,r){var n=r(50),o=r(0),i=function(e){return"function"==typeof e?e:void 0};e.exports=function(e,t){return arguments.length<2?i(n[e])||i(o[e]):n[e]&&n[e][t]||o[e]&&o[e][t]}},function(e,t,r){var n=r(27),o=Math.min;e.exports=function(e){return e>0?o(n(e),9007199254740991):0}},function(e,t){var r=Math.ceil,n=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?n:r)(e)}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},function(e,t,r){var n=r(28);e.exports=function(e,t,r){if(n(e),void 0===t)return e;switch(r){case 0:return function(){return e.call(t)};case 1:return function(r){return e.call(t,r)};case 2:return function(r,n){return e.call(t,r,n)};case 3:return function(r,n,o){return e.call(t,r,n,o)}}return function(){return e.apply(t,arguments)}}},function(e,t,r){var n=r(88),o=r(20),i=r(1)("iterator");e.exports=function(e){if(null!=e)return e[i]||e["@@iterator"]||o[n(e)]}},function(e,t,r){var n=r(17);e.exports=function(e){return Object(n(e))}},function(e,t,r){r(9),r(10),r(105),r(13),(()=>{const t=new class{constructor(){const e=r(110),t=r(111);function n(e){t.defaults.headers.delete["X-CSRFToken"]=e,t.defaults.headers.patch["X-CSRFToken"]=e,t.defaults.headers.post["X-CSRFToken"]=e,t.defaults.headers.put["X-CSRFToken"]=e}async function o(e=""){const{backendAPI:r}=window.cvat.config;let n=null;try{n=await t.get(`${r}/tasks?${e}`,{proxy:window.cvat.config.proxy})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not get tasks from a server",t)}return n.data.results.count=n.data.count,n.data.results}async function i(e){const{backendAPI:r}=window.cvat.config;try{await t.delete(`${r}/tasks/${e}`)}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not delete the task from the server",t)}}const a=e.get("csrftoken");a&&n(a),Object.defineProperties(this,Object.freeze({server:{value:Object.freeze({about:async function(){const{backendAPI:e}=window.cvat.config;let r=null;try{r=await t.get(`${e}/server/about`,{proxy:window.cvat.config.proxy})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError('Could not get "about" information from the server',t)}return r.data},share:async function(e){const{backendAPI:r}=window.cvat.config;let n=null;try{n=await t.get(`${r}/server/share?directory=${e}`,{proxy:window.cvat.config.proxy})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError('Could not get "share" information from the server',t)}return n.data},exception:async function(e){const{backendAPI:r}=window.cvat.config;try{await t.post(`${r}/server/exception`,JSON.stringify(e),{proxy:window.cvat.config.proxy,headers:{"Content-Type":"application/json"}})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not send an exception to the server",t)}},login:async function(r,o){function i(r){if(r.headers["set-cookie"]){let o="";for(let t of r.headers["set-cookie"]){[t]=t.split(";");const r=t.split("=")[0],i=t.split("=")[1];"csrftoken"===r&&n(i),e.set(r,i),o+=`${t};`}t.defaults.headers.common.Cookie=o}else{const t=e.get("csrftoken");if(!t)throw new window.cvat.exceptions.ScriptingError("An environment has been detected as a browser, but CSRF token has not been found in cookies");n(t)}}const a=window.cvat.config.backendAPI.slice(0,-7);let s=null;try{s=await t.get(`${a}/auth/login`,{proxy:window.cvat.config.proxy})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not get CSRF token from a server",t)}i(s);const c=[`${encodeURIComponent("username")}=${encodeURIComponent(r)}`,`${encodeURIComponent("password")}=${encodeURIComponent(o)}`].join("&").replace(/%20/g,"+");let u=null;try{u=await t.post(`${a}/auth/login`,c,{"Content-Type":"application/x-www-form-urlencoded",proxy:window.cvat.config.proxy,maxRedirects:0})}catch(e){if(302!==e.response.status){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not login on a server",t)}u=e.response}if(u.data.includes("didn't match"))throw new window.cvat.exceptions.ServerError("The pair login/password is invalid",403);i(u)}}),writable:!1},tasks:{value:Object.freeze({getTasks:o,saveTask:async function(e,r){const{backendAPI:n}=window.cvat.config;try{await t.patch(`${n}/tasks/${e}`,JSON.stringify(r),{proxy:window.cvat.config.proxy,headers:{"Content-Type":"application/json"}})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not save the task on the server",t)}},createTask:async function(e,r,n){const{backendAPI:a}=window.cvat.config,s=new window.FormData;for(const e in r)if(Object.prototype.hasOwnProperty.call(r,e))for(let t=0;t{setTimeout(async function i(){try{const s=await t.get(`${a}/tasks/${e}/status`);["Queued","Started"].includes(s.data.state)?(""!==s.data.message&&n(s.data.message),setTimeout(i,1e3)):"Finished"===s.data.state?r():"Failed"===s.data.state?o(new window.cvat.exceptions.ServerError("Could not create the task on the server",400)):o(new window.cvat.exceptions.ServerError(`Unknown task state has been recieved: ${s.data.state}`,500))}catch(e){const t=e.response?e.response.status:e.code;o(new window.cvat.exceptions.ServerError("Data uploading error occured",t))}},1e3)})}(c.data.id)}catch(e){throw i(c.data.id),e}return(await o(`?id=${c.id}`))[0]},deleteTask:i}),writable:!1},jobs:{value:Object.freeze({getJob:async function(e){const{backendAPI:r}=window.cvat.config;let n=null;try{n=await t.get(`${r}/jobs/${e}`,{proxy:window.cvat.config.proxy})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not get jobs from a server",t)}return n.data},saveJob:async function(e,r){const{backendAPI:n}=window.cvat.config;try{await t.patch(`${n}/jobs/${e}`,JSON.stringify(r),{proxy:window.cvat.config.proxy,headers:{"Content-Type":"application/json"}})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not save the job on the server",t)}}}),writable:!1},users:{value:Object.freeze({getUsers:async function(){const{backendAPI:e}=window.cvat.config;let r=null;try{r=await t.get(`${e}/users`,{proxy:window.cvat.config.proxy})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not get users from a server",t)}return r.data.results},getSelf:async function(){const{backendAPI:e}=window.cvat.config;let r=null;try{r=await t.get(`${e}/users/self`,{proxy:window.cvat.config.proxy})}catch(e){const t=e.response?e.response.status:e.code;throw new window.cvat.exceptions.ServerError("Could not get users from a server",t)}return r.data}}),writable:!1},frames:{value:Object.freeze({getFrame:async function(e,r){const{backendAPI:n}=window.cvat.config;let o=null;try{o=await t.get(`${n}/tasks/${e}/frames/${r}`,{proxy:window.cvat.config.proxy,responseType:"blob"})}catch(t){const n=t.response?t.response.status:t.code;throw new window.cvat.exceptions.ServerError(`Could not get frame ${r} for a task ${e} from a server`,n)}return o.data},getMeta:async function(e){const{backendAPI:r}=window.cvat.config;let n=null;try{n=await t.get(`${r}/tasks/${e}/frames/meta`,{proxy:window.cvat.config.proxy})}catch(t){const r=t.response?t.response.status:t.code;throw new window.cvat.exceptions.ServerError(`Could not get frame meta info for a task ${e} from a server`,r)}return n.data}}),writable:!1}}))}};e.exports=t})()},function(e,t){var r;r=function(){return this}();try{r=r||new Function("return this")()}catch(e){"object"==typeof window&&(r=window)}e.exports=r},function(e,t,r){var n=r(6),o=r(44),i=r(22),a=r(23),s=r(35),c=r(5),u=r(46),l=Object.getOwnPropertyDescriptor;t.f=n?l:function(e,t){if(e=a(e),t=s(t,!0),u)try{return l(e,t)}catch(e){}if(c(e,t))return i(!o.f.call(e,t),e[t])}},function(e,t,r){var n=r(7);e.exports=function(e,t){if(!n(e))return e;var r,o;if(t&&"function"==typeof(r=e.toString)&&!n(o=r.call(e)))return o;if("function"==typeof(r=e.valueOf)&&!n(o=r.call(e)))return o;if(!t&&"function"==typeof(r=e.toString)&&!n(o=r.call(e)))return o;throw TypeError("Can't convert object to primitive value")}},function(e,t,r){var n=r(0),o=r(7),i=n.document,a=o(i)&&o(i.createElement);e.exports=function(e){return a?i.createElement(e):{}}},function(e,t,r){var n=r(0),o=r(8);e.exports=function(e,t){try{o(n,e,t)}catch(r){n[e]=t}return t}},function(e,t,r){var n=r(24),o=r(48),i=n("keys");e.exports=function(e){return i[e]||(i[e]=o(e))}},function(e,t){e.exports={}},function(e,t){e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(e,t){e.exports=function(e,t,r){if(!(e instanceof t))throw TypeError("Incorrect "+(r?r+" ":"")+"invocation");return e}},function(e,t,r){var n=r(27),o=r(17),i=function(e){return function(t,r){var i,a,s=String(o(t)),c=n(r),u=s.length;return c<0||c>=u?e?"":void 0:(i=s.charCodeAt(c))<55296||i>56319||c+1===u||(a=s.charCodeAt(c+1))<56320||a>57343?e?s.charAt(c):i:e?s.slice(c,c+2):a-56320+(i-55296<<10)+65536}};e.exports={codeAt:i(!1),charAt:i(!0)}},function(e,t,r){"use strict";(function(t){var n=r(3),o=r(116),i={"Content-Type":"application/x-www-form-urlencoded"};function a(e,t){!n.isUndefined(e)&&n.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var s,c={adapter:("undefined"!=typeof XMLHttpRequest?s=r(71):void 0!==t&&(s=r(71)),s),transformRequest:[function(e,t){return o(t,"Content-Type"),n.isFormData(e)||n.isArrayBuffer(e)||n.isBuffer(e)||n.isStream(e)||n.isFile(e)||n.isBlob(e)?e:n.isArrayBufferView(e)?e.buffer:n.isURLSearchParams(e)?(a(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):n.isObject(e)?(a(t,"application/json;charset=utf-8"),JSON.stringify(e)):e}],transformResponse:[function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,validateStatus:function(e){return e>=200&&e<300}};c.headers={common:{Accept:"application/json, text/plain, */*"}},n.forEach(["delete","get","head"],function(e){c.headers[e]={}}),n.forEach(["post","put","patch"],function(e){c.headers[e]=n.merge(i)}),e.exports=c}).call(this,r(115))},function(e,t,r){"use strict";var n={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!n.call({1:2},1);t.f=i?function(e){var t=o(this,e);return!!t&&t.enumerable}:n},function(e,t,r){var n=r(4),o=r(14),i="".split;e.exports=n(function(){return!Object("z").propertyIsEnumerable(0)})?function(e){return"String"==o(e)?i.call(e,""):Object(e)}:Object},function(e,t,r){var n=r(6),o=r(4),i=r(36);e.exports=!n&&!o(function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a})},function(e,t,r){var n=r(24);e.exports=n("native-function-to-string",Function.toString)},function(e,t){var r=0,n=Math.random();e.exports=function(e){return"Symbol("+String(void 0===e?"":e)+")_"+(++r+n).toString(36)}},function(e,t,r){var n=r(5),o=r(81),i=r(34),a=r(12);e.exports=function(e,t){for(var r=o(t),s=a.f,c=i.f,u=0;uc;)n(s,r=t[c++])&&(~i(u,r)||u.push(r));return u}},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t,r){var n=r(4),o=/#|\.prototype\./,i=function(e,t){var r=s[a(e)];return r==u||r!=c&&("function"==typeof t?n(t):!!t)},a=i.normalize=function(e){return String(e).replace(o,".").toLowerCase()},s=i.data={},c=i.NATIVE="N",u=i.POLYFILL="P";e.exports=i},function(e,t,r){var n=r(15);e.exports=function(e,t,r){for(var o in t)n(e,o,t[o],r);return e}},function(e,t,r){var n=r(1),o=r(20),i=n("iterator"),a=Array.prototype;e.exports=function(e){return void 0!==e&&(o.Array===e||a[i]===e)}},function(e,t,r){var n=r(2);e.exports=function(e,t,r,o){try{return o?t(n(r)[0],r[1]):t(r)}catch(t){var i=e.return;throw void 0!==i&&n(i.call(e)),t}}},function(e,t,r){var n,o,i,a=r(0),s=r(4),c=r(14),u=r(29),l=r(58),f=r(36),p=a.location,h=a.setImmediate,d=a.clearImmediate,v=a.process,g=a.MessageChannel,m=a.Dispatch,b=0,w={},y=function(e){if(w.hasOwnProperty(e)){var t=w[e];delete w[e],t()}},x=function(e){return function(){y(e)}},S=function(e){y(e.data)},O=function(e){a.postMessage(e+"",p.protocol+"//"+p.host)};h&&d||(h=function(e){for(var t=[],r=1;arguments.length>r;)t.push(arguments[r++]);return w[++b]=function(){("function"==typeof e?e:Function(e)).apply(void 0,t)},n(b),b},d=function(e){delete w[e]},"process"==c(v)?n=function(e){v.nextTick(x(e))}:m&&m.now?n=function(e){m.now(x(e))}:g?(i=(o=new g).port2,o.port1.onmessage=S,n=u(i.postMessage,i,1)):!a.addEventListener||"function"!=typeof postMessage||a.importScripts||s(O)?n="onreadystatechange"in f("script")?function(e){l.appendChild(f("script")).onreadystatechange=function(){l.removeChild(this),y(e)}}:function(e){setTimeout(x(e),0)}:(n=O,a.addEventListener("message",S,!1))),e.exports={set:h,clear:d}},function(e,t,r){var n=r(25);e.exports=n("document","documentElement")},function(e,t,r){var n=r(25);e.exports=n("navigator","userAgent")||""},function(e,t,r){"use strict";var n=r(28),o=function(e){var t,r;this.promise=new e(function(e,n){if(void 0!==t||void 0!==r)throw TypeError("Bad Promise constructor");t=e,r=n}),this.resolve=n(t),this.reject=n(r)};e.exports.f=function(e){return new o(e)}},function(e,t,r){var n=r(2),o=r(62),i=r(40),a=r(39),s=r(58),c=r(36),u=r(38)("IE_PROTO"),l=function(){},f=function(){var e,t=c("iframe"),r=i.length;for(t.style.display="none",s.appendChild(t),t.src=String("javascript:"),(e=t.contentWindow.document).open(),e.write(" diff --git a/cvat-ui/public/manifest.json b/cvat-ui/public/manifest.json index 1f2f141f..43611204 100644 --- a/cvat-ui/public/manifest.json +++ b/cvat-ui/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "CVAT", + "name": "Computer Vision Annotation Tool", "icons": [ { "src": "favicon.ico", diff --git a/cvat-ui/src/components/app/App.test.tsx b/cvat-ui/src/components/app/App.test.tsx index a754b201..e9957993 100644 --- a/cvat-ui/src/components/app/App.test.tsx +++ b/cvat-ui/src/components/app/App.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import App from './App'; +import App from './app'; it('renders without crashing', () => { const div = document.createElement('div'); diff --git a/cvat-ui/src/components/app/App.tsx b/cvat-ui/src/components/app/App.tsx index 680d3fc7..5c25e237 100644 --- a/cvat-ui/src/components/app/App.tsx +++ b/cvat-ui/src/components/app/App.tsx @@ -1,17 +1,42 @@ import React, { Component } from 'react'; import { BrowserRouter as Router, Route, Redirect } from 'react-router-dom'; -import Dashboard from '../dashboard/Dashboard'; +import Dashboard from '../dashboard/dashboard'; -import './App.css'; +import './app.scss'; + +declare const window: any; + +interface AppState { + isLoggedIn: boolean; +} + +class App extends Component { + constructor(props: any) { + super(props); + + this.state = { + isLoggedIn: false + }; + } + + componentDidMount() { + window.cvat.server.login('admin', 'admin').then( + (_response: any) => { + this.setState({ isLoggedIn: true }); + }, + (_error: any) => { + this.setState({ isLoggedIn: false }); + } + ); + } -class App extends Component { render() { return(
- +
); diff --git a/cvat-ui/src/components/app/App.css b/cvat-ui/src/components/app/app.scss similarity index 100% rename from cvat-ui/src/components/app/App.css rename to cvat-ui/src/components/app/app.scss diff --git a/cvat-ui/src/components/dashboard/Dashboard.css b/cvat-ui/src/components/dashboard/Dashboard.css deleted file mode 100644 index 27942e01..00000000 --- a/cvat-ui/src/components/dashboard/Dashboard.css +++ /dev/null @@ -1,3 +0,0 @@ -.Dashboard { - -} diff --git a/cvat-ui/src/components/dashboard/Dashboard.test.tsx b/cvat-ui/src/components/dashboard/Dashboard.test.tsx index 961a7d54..956dcb5f 100644 --- a/cvat-ui/src/components/dashboard/Dashboard.test.tsx +++ b/cvat-ui/src/components/dashboard/Dashboard.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import Dashboard from './Dashboard'; +import Dashboard from './dashboard'; it('renders without crashing', () => { const div = document.createElement('div'); diff --git a/cvat-ui/src/components/dashboard/Dashboard.tsx b/cvat-ui/src/components/dashboard/Dashboard.tsx index 17dba07a..1286181e 100644 --- a/cvat-ui/src/components/dashboard/Dashboard.tsx +++ b/cvat-ui/src/components/dashboard/Dashboard.tsx @@ -1,26 +1,58 @@ import React, { Component } from 'react'; -import './Dashboard.css'; +import { Layout } from 'antd'; -declare const window: any; +import DashboardHeader from './header/dashboard-header'; +import DashboardContent from './content/dashboard-content'; +import DashboardFooter from './footer/dashboard-footer'; -class Dashboard extends Component { +import './dashboard.scss'; + +interface DashboardState { + tasks: []; + tasksCount: number; +} + +class Dashboard extends Component { constructor(props: any) { super(props); + + this.state = { tasks: [], tasksCount: 0 }; + } + + componentDidMount() { + this.getTasks(); + } + + render() { + return ( + + + + + + ); } - componentWillMount() { - window.cvat.server.login('admin', 'admin').then( - (response: any) => { - console.log(response); + + private getTasks = (query?: string) => { + const queryObject = { + search: query + }; + + (window as any).cvat.tasks.get(query ? queryObject : {}).then( + (tasks: any) => { + this.setState({ tasks, tasksCount: tasks.count }); }, (error: any) => { console.log(error); } ); + } - window.cvat.tasks.get().then( - (response: any) => { - console.log(response); + private onPageChange = (page: number) => { + (window as any).cvat.tasks.get({ page }).then( + (tasks: any) => { + this.setState({ tasks }); }, (error: any) => { console.log(error); @@ -28,11 +60,20 @@ class Dashboard extends Component { ); } - render() { - return( -
+ private deleteTask = (task: any) => { + task.delete().then( + (_deleted: any) => { + setTimeout(() => { + + this.getTasks(); + }, 1000); + // const tasks = this.state.tasks.filter((taskToDelete: any) => taskToDelete.id !== task.id) as any; -
+ // this.setState({ tasks, tasksCount: this.state.tasksCount - 1 }); + }, + (error: any) => { + console.log(error); + } ); } } diff --git a/cvat-ui/src/components/dashboard/content/dashboard-content.scss b/cvat-ui/src/components/dashboard/content/dashboard-content.scss new file mode 100644 index 00000000..127eceff --- /dev/null +++ b/cvat-ui/src/components/dashboard/content/dashboard-content.scss @@ -0,0 +1,23 @@ +.dashboard-content-сard { + &__header { + + } + + &__content { + + .card-cover { + + img { + max-width: 300px; + } + } + + .card-actions { + + } + + .card-jobs { + + } + } +} diff --git a/cvat-ui/src/components/dashboard/content/dashboard-content.test.tsx b/cvat-ui/src/components/dashboard/content/dashboard-content.test.tsx new file mode 100644 index 00000000..37a04805 --- /dev/null +++ b/cvat-ui/src/components/dashboard/content/dashboard-content.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import DashboardContent from './dashboard-content'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); +}); diff --git a/cvat-ui/src/components/dashboard/content/dashboard-content.tsx b/cvat-ui/src/components/dashboard/content/dashboard-content.tsx new file mode 100644 index 00000000..937cbe18 --- /dev/null +++ b/cvat-ui/src/components/dashboard/content/dashboard-content.tsx @@ -0,0 +1,129 @@ +import React, { Component } from 'react'; + +import { Layout, Empty, Button, Col, Row } from 'antd'; + +import './dashboard-content.scss'; + +const { Content } = Layout; + +interface DashboardContentAction { + id: number, + name: string, + trigger: Function, +} + +class DashboardContent extends Component { + hostUrl: string; + apiUrl: string; + actions: DashboardContentAction[]; + + constructor(props: any) { + super(props); + + this.state = {}; + this.hostUrl = 'http://localhost:7000'; + this.apiUrl = 'http://localhost:7000/api/v1'; + + this.actions = [ + // { + // id: 1, + // name: 'Dump annotation', + // trigger: () => {}, + // }, + // { + // id: 2, + // name: 'Upload annotation', + // trigger: () => {}, + // }, + // { + // id: 3, + // name: 'Update task', + // trigger: () => {}, + // }, + { + id: 4, + name: 'Delete task', + trigger: (task: any) => { + this.props.deleteTask(task); + }, + }, + ]; + } + + render() { + return( + <> + { this.props.tasks.length ? this.renderTasks() : this.renderPlaceholder() } + + ); + } + + private renderPlaceholder() { + return ( + + No tasks in this workspace yet... + + } + > + + + ) + } + + private renderTasks() { + return( + + { + this.props.tasks.map( + (task: any) => ( +
+ + +

{ `${task.name}: ${task.mode}` }

+ +
+ + + + Task cover + + + + { + this.actions.map( + (action: DashboardContentAction) => ( + + + + ) + ) + } + + + + Jobs + { + task.jobs.map( + (job: any) => ( + + {`${this.hostUrl}?id=${job.id}`} + + ) + ) + } + + +
+ ) + ) + } +
+ ); + } +} + +export default DashboardContent; diff --git a/cvat-ui/src/components/dashboard/dashboard.scss b/cvat-ui/src/components/dashboard/dashboard.scss new file mode 100644 index 00000000..e69de29b diff --git a/cvat-ui/src/components/dashboard/footer/dashboard-footer.scss b/cvat-ui/src/components/dashboard/footer/dashboard-footer.scss new file mode 100644 index 00000000..e69de29b diff --git a/cvat-ui/src/components/dashboard/footer/dashboard-footer.test.tsx b/cvat-ui/src/components/dashboard/footer/dashboard-footer.test.tsx new file mode 100644 index 00000000..b52f6d91 --- /dev/null +++ b/cvat-ui/src/components/dashboard/footer/dashboard-footer.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import DashboardFooter from './dashboard-footer'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); +}); diff --git a/cvat-ui/src/components/dashboard/footer/dashboard-footer.tsx b/cvat-ui/src/components/dashboard/footer/dashboard-footer.tsx new file mode 100644 index 00000000..8d4c39c0 --- /dev/null +++ b/cvat-ui/src/components/dashboard/footer/dashboard-footer.tsx @@ -0,0 +1,25 @@ +import React, { Component } from 'react'; + +import { Layout, Pagination } from 'antd'; + +import './dashboard-footer.scss'; + +const { Footer } = Layout; + +class DashboardFooter extends Component { + constructor(props: any) { + super(props); + + this.state = {}; + } + + render() { + return( +
+ +
+ ); + } +} + +export default DashboardFooter; diff --git a/cvat-ui/src/components/dashboard/header/dashboard-header.scss b/cvat-ui/src/components/dashboard/header/dashboard-header.scss new file mode 100644 index 00000000..e69de29b diff --git a/cvat-ui/src/components/dashboard/header/dashboard-header.test.tsx b/cvat-ui/src/components/dashboard/header/dashboard-header.test.tsx new file mode 100644 index 00000000..417876ec --- /dev/null +++ b/cvat-ui/src/components/dashboard/header/dashboard-header.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import DashboardHeader from './dashboard-header'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); +}); diff --git a/cvat-ui/src/components/dashboard/header/dashboard-header.tsx b/cvat-ui/src/components/dashboard/header/dashboard-header.tsx new file mode 100644 index 00000000..4098925c --- /dev/null +++ b/cvat-ui/src/components/dashboard/header/dashboard-header.tsx @@ -0,0 +1,72 @@ +import React, { Component } from 'react'; + +import { Layout, Row, Col, Button, Input } from 'antd'; + +import './dashboard-header.scss'; + +const { Header } = Layout; +const { Search } = Input; + +interface DashboardHeaderAction { + id: number, + name: string, + trigger: any, +} + +class DashboardHeader extends Component { + actions: DashboardHeaderAction[]; + hostUrl: string; + + constructor(props: any) { + super(props); + + this.state = {}; + + this.hostUrl = 'http://localhost:7000'; + + this.actions = [ + // { + // id: 1, + // name: 'Create task', + // trigger: this.props.onSearch, + // }, + { + id: 2, + name: 'User guide', + trigger: this.openUserGuide, + }, + ]; + } + + render() { + return( +
+ + + Tasks + + + this.props.onSearch(query) } enterButton /> + + + { + this.actions.map( + (action: DashboardHeaderAction) => ( + + ) + ) + } + + +
+ ); + } + + private openUserGuide = () => { + window.open(`${this.hostUrl}/documentation/user_guide.html`, '_blank') + } +} + +export default DashboardHeader; diff --git a/cvat-ui/src/index.css b/cvat-ui/src/index.scss similarity index 100% rename from cvat-ui/src/index.css rename to cvat-ui/src/index.scss diff --git a/cvat-ui/src/index.tsx b/cvat-ui/src/index.tsx index c4a2ea7e..2d4986c5 100644 --- a/cvat-ui/src/index.tsx +++ b/cvat-ui/src/index.tsx @@ -3,13 +3,10 @@ import ReactDOM from 'react-dom'; import * as serviceWorker from './serviceWorker'; -import './index.css'; -import App from './components/app/App'; +import './index.scss'; +import App from './components/app/app'; -ReactDOM.render( - , - document.getElementById('root') -); +ReactDOM.render(, document.getElementById('root')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls.