diff --git a/jsx/build/admin-react.js.LICENSE.txt b/jsx/build/admin-react.js.LICENSE.txt index 493c5041..9e7087bc 100644 --- a/jsx/build/admin-react.js.LICENSE.txt +++ b/jsx/build/admin-react.js.LICENSE.txt @@ -37,6 +37,15 @@ object-assign * LICENSE file in the root directory of this source tree. */ +/** @license React v17.0.2 + * react-jsx-runtime.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + /** @license React v17.0.2 * react.production.min.js * diff --git a/jsx/package.json b/jsx/package.json index 2488dbe8..4442d169 100644 --- a/jsx/package.json +++ b/jsx/package.json @@ -43,10 +43,11 @@ "lodash.debounce": "^4.0.8", "prop-types": "^15.7.2", "react": "^17.0.1", - "react-bootstrap": "^1.4.0", + "react-bootstrap": "^2.1.1", "react-dom": "^17.0.1", "react-icons": "^4.1.0", "react-multi-select-component": "^3.0.7", + "react-object-table-viewer": "^1.0.7", "react-redux": "^7.2.2", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", @@ -60,7 +61,6 @@ }, "devDependencies": { "@wojtekmaj/enzyme-adapter-react-17": "^0.6.5", - "sinon": "^13.0.1", "babel-jest": "^26.6.3", "enzyme": "^3.11.0", "eslint": "^7.18.0", @@ -68,6 +68,7 @@ "eslint-plugin-react": "^7.22.0", "identity-obj-proxy": "^3.0.0", "jest": "^26.6.3", - "prettier": "^2.2.1" + "prettier": "^2.2.1", + "sinon": "^13.0.1" } } diff --git a/jsx/src/components/ServerDashboard/ServerDashboard.jsx b/jsx/src/components/ServerDashboard/ServerDashboard.jsx index 9087ee2b..f927370a 100644 --- a/jsx/src/components/ServerDashboard/ServerDashboard.jsx +++ b/jsx/src/components/ServerDashboard/ServerDashboard.jsx @@ -4,6 +4,8 @@ import { useSelector, useDispatch } from "react-redux"; import PropTypes from "prop-types"; import { Button, Col, Row, FormControl } from "react-bootstrap"; +import ReactObjectTableViewer from "react-object-table-viewer"; + import { Link } from "react-router-dom"; import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa"; @@ -19,6 +21,15 @@ const AccessServerButton = ({ url }) => ( ); +const ToggleButton = ({ dataTarget }) => { + var [errorAlert, setErrorAlert] = useState(null); + return ( + + ); +}; + const ServerDashboard = (props) => { let base_url = window.base_url; // sort methods @@ -189,6 +200,91 @@ const ServerDashboard = (props) => { ); }; + const serverRow = (user, server) => { + const { servers, ...userNoServers } = user; + return [ + + + + {" "} + + {user.name} + + {user.admin ? "admin" : ""} + + + {server.name ? ( +

{server.name}

+ ) : ( +

[MAIN]

+ )} + + + {server.last_activity ? timeSince(server.last_activity) : "Never"} + + + {server.started ? ( + // Stop Single-user server + <> + + + + ) : ( + // Start Single-user server + <> + + + + + + )} + + + , + + +
+
+ +
+
+ + , + ]; + }; + let servers = user_data.flatMap((user) => { let userServers = Object.values({ "": user.server || {}, @@ -234,7 +330,7 @@ const ServerDashboard = (props) => { {"> Manage Groups"} - +
- {servers.map(([user, server], i) => { - server.name = server.name || ""; - return ( - - - - - - - - - - ); - })} + {servers.flatMap(([user, server]) => serverRow(user, server))}
@@ -373,63 +469,7 @@ const ServerDashboard = (props) => {
{user.name} - {user.admin ? "admin" : ""} - - {server.name ? ( -

{server.name}

- ) : ( -

[MAIN]

- )} -
- {server.last_activity - ? timeSince(server.last_activity) - : "Never"} - - {server.started ? ( - // Stop Single-user server - <> - - - - ) : ( - // Start Single-user server - <> - - - - - - )} -
=16.14.8" - "@types/react-transition-group" "^4.4.1" + "@types/react-transition-group" "^4.4.4" "@types/warning" "^3.0.0" classnames "^2.3.1" dom-helpers "^5.2.1" invariant "^2.2.4" - prop-types "^15.7.2" + prop-types "^15.8.1" prop-types-extra "^1.1.0" - react-overlays "^5.1.1" - react-transition-group "^4.4.1" + react-transition-group "^4.4.2" uncontrollable "^7.2.1" warning "^4.0.3" -react-dom@^17.0.1: +react-dom@17.0.2, react-dom@^17.0.1: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== @@ -6226,19 +6243,13 @@ react-multi-select-component@^3.0.7: dependencies: goober "^2.0.30" -react-overlays@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-5.1.1.tgz#2e7cf49744b56537c7828ccb94cfc63dd778ae4f" - integrity sha512-eCN2s2/+GVZzpnId4XVWtvDPYYBD2EtOGP74hE+8yDskPzFy9+pV1H3ZZihxuRdEbQzzacySaaDkR7xE0ydl4Q== +react-object-table-viewer@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/react-object-table-viewer/-/react-object-table-viewer-1.0.7.tgz#31816021fa4526641c6b66bd9433ec9b78c2e472" + integrity sha512-OezCet8+BmEdJJHO5WGPFPRWXxw4Ls6HsV4Uh1kRPlmRXLOTNqWt/ZHmH8NhTl1BA9HkdhEegKVqc2b61wDMLg== dependencies: - "@babel/runtime" "^7.13.8" - "@popperjs/core" "^2.8.6" - "@restart/hooks" "^0.3.26" - "@types/warning" "^3.0.0" - dom-helpers "^5.2.0" - prop-types "^15.7.2" - uncontrollable "^7.2.1" - warning "^4.0.3" + react "^17.0.2" + react-dom "17.0.2" react-redux@^7.2.2: version "7.2.6" @@ -6299,7 +6310,7 @@ react-test-renderer@^17.0.0: react-shallow-renderer "^16.13.1" scheduler "^0.20.2" -react-transition-group@^4.4.1: +react-transition-group@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470" integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg== @@ -6309,7 +6320,7 @@ react-transition-group@^4.4.1: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^17.0.1: +react@^17.0.1, react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== diff --git a/share/jupyterhub/static/js/admin-react.js b/share/jupyterhub/static/js/admin-react.js index 6bc10471..215dd3cb 100644 --- a/share/jupyterhub/static/js/admin-react.js +++ b/share/jupyterhub/static/js/admin-react.js @@ -1,2 +1,2 @@ /*! For license information please see admin-react.js.LICENSE.txt */ -(()=>{var e,t,n={966:(e,t,n)=>{"use strict";var r=n(294),a=n(935),o=r.createContext(null),l=function(e){e()},i=function(){return l},u={notify:function(){},get:function(){return[]}};function c(e,t){var n,r=u;function a(){l.onStateChange&&l.onStateChange()}function o(){n||(n=t?t.addNestedSub(a):e.subscribe(a),r=function(){var e=i(),t=null,n=null;return{clear:function(){t=null,n=null},notify:function(){e((function(){for(var e=t;e;)e.callback(),e=e.next}))},get:function(){for(var e=[],n=t;n;)e.push(n),n=n.next;return e},subscribe:function(e){var r=!0,a=n={callback:e,next:null,prev:n};return a.prev?a.prev.next=a:t=a,function(){r&&null!==t&&(r=!1,a.next?a.next.prev=a.prev:n=a.prev,a.prev?a.prev.next=a.next:t=a.next)}}}}())}var l={addNestedSub:function(e){return o(),r.subscribe(e)},notifyNestedSubs:function(){r.notify()},handleChangeWrapper:a,isSubscribed:function(){return Boolean(n)},trySubscribe:o,tryUnsubscribe:function(){n&&(n(),n=void 0,r.clear(),r=u)},getListeners:function(){return r}};return l}var s="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?r.useLayoutEffect:r.useEffect;const f=function(e){var t=e.store,n=e.context,a=e.children,l=(0,r.useMemo)((function(){var e=c(t);return e.onStateChange=e.notifyNestedSubs,{store:t,subscription:e}}),[t]),i=(0,r.useMemo)((function(){return t.getState()}),[t]);s((function(){var e=l.subscription;return e.trySubscribe(),i!==t.getState()&&e.notifyNestedSubs(),function(){e.tryUnsubscribe(),e.onStateChange=null}}),[l,i]);var u=n||o;return r.createElement(u.Provider,{value:l},a)};function d(){return d=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:"";return R("/users/"+e+"/servers/"+(t||""),"POST")},stopServer:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return R("/users/"+e+"/servers/"+(t||""),"DELETE")},startAll:function(e){return e.map((function(e){return R("/users/"+e+"/server","POST")}))},stopAll:function(e){return e.map((function(e){return R("/users/"+e+"/server","DELETE")}))},addToGroup:function(e,t){return R("/groups/"+t+"/users","POST",{users:e})},removeFromGroup:function(e,t){return R("/groups/"+t+"/users","DELETE",{users:e})},createGroup:function(e){return R("/groups/"+e,"POST")},deleteGroup:function(e){return R("/groups/"+e,"DELETE")},addUsers:function(e,t){return R("/users","POST",{usernames:e,admin:t})},editUser:function(e,t,n){return R("/users/"+e,"PATCH",{name:t,admin:n})},deleteUser:function(e){return R("/users/"+e,"DELETE")},findUser:function(e){return R("/users/"+e,"GET")},validateUser:function(e){return R("/users/"+e,"GET").then((function(e){return e.status})).then((function(e){return!(e>200)}))},failRegexEvent:function(){return null},noChangeEvent:function(){return null},refreshGroupsData:function(){return R("/groups","GET").then((function(e){return e.json()}))},refreshUserData:function(){return R("/users","GET").then((function(e){return e.json()}))}}},I=function(e){return d({},e,O())},function(e){var t=(0,r.createFactory)(e);return function(e){return t(I(e))}});var I;function M(e){return"/"===e.charAt(0)}function z(e,t){for(var n=t,r=n+1,a=e.length;r=0;s--){var f=a[s];"."===f?z(a,s):".."===f?(z(a,s),c++):c&&(z(a,s),c--)}if(!i)for(;c--;c)a.unshift("..");!i||""===a[0]||a[0]&&M(a[0])||a.unshift("");var d=a.join("/");return n&&"/"!==d.substr(-1)&&(d+="/"),d};"undefined"==typeof window||!window.document||window.document.createElement;var D=n(697),U=n.n(D),$=1073741823,B="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};function H(e){var t=[];return{on:function(e){t.push(e)},off:function(e){t=t.filter((function(t){return t!==e}))},get:function(){return e},set:function(n,r){e=n,t.forEach((function(t){return t(e,r)}))}}}const V=r.createContext||function(e,t){var n,a,o,l="__create-react-context-"+((B[o="__global_unique_id__"]=(B[o]||0)+1)+"__"),i=function(e){function n(){var t;return(t=e.apply(this,arguments)||this).emitter=H(t.props.value),t}P(n,e);var r=n.prototype;return r.getChildContext=function(){var e;return(e={})[l]=this.emitter,e},r.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,a=e.value;((o=r)===(l=a)?0!==o||1/o==1/l:o!=o&&l!=l)?n=0:(n="function"==typeof t?t(r,a):$,0!=(n|=0)&&this.emitter.set(e.value,n))}var o,l},r.render=function(){return this.props.children},n}(r.Component);i.childContextTypes=((n={})[l]=U().object.isRequired,n);var u=function(t){function n(){var e;return(e=t.apply(this,arguments)||this).state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}P(n,t);var r=n.prototype;return r.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?$:t},r.componentDidMount=function(){this.context[l]&&this.context[l].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?$:e},r.componentWillUnmount=function(){this.context[l]&&this.context[l].off(this.onUpdate)},r.getValue=function(){return this.context[l]?this.context[l].get():e},r.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(r.Component);return u.contextTypes=((a={})[l]=U().object,a),{Provider:i,Consumer:u}};function W(e,t){if(!e)throw new Error("Invariant failed")}var G=n(779),Q=n.n(G);function q(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r=0||(a[n]=e[n]);return a}n(663);var K=function(e){var t=V();return t.displayName=e,t},Y=K("Router-History"),X=K("Router"),J=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._isMounted?n.setState({location:e}):n._pendingLocation=e}))),n}P(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){this._isMounted=!0,this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return r.createElement(X.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},r.createElement(Y.Provider,{children:this.props.children||null,value:this.props.history}))},t}(r.Component);r.Component,r.Component;var Z={},ee=0;function te(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,a=n.exact,o=void 0!==a&&a,l=n.strict,i=void 0!==l&&l,u=n.sensitive,c=void 0!==u&&u;return[].concat(r).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=Z[n]||(Z[n]={});if(r[e])return r[e];var a=[],o={regexp:Q()(e,a,t),keys:a};return ee<1e4&&(r[e]=o,ee++),o}(n,{end:o,strict:i,sensitive:c}),a=r.regexp,l=r.keys,u=a.exec(e);if(!u)return null;var s=u[0],f=u.slice(1),d=e===s;return o&&!d?null:{path:n,url:"/"===n&&""===s?"/":s,isExact:d,params:l.reduce((function(e,t,n){return e[t.name]=f[n],e}),{})}}),null)}var ne=function(e){function t(){return e.apply(this,arguments)||this}return P(t,e),t.prototype.render=function(){var e=this;return r.createElement(X.Consumer,null,(function(t){t||W(!1);var n=e.props.location||t.location,a=d({},t,{location:n,match:e.props.computedMatch?e.props.computedMatch:e.props.path?te(n.pathname,e.props):t.match}),o=e.props,l=o.children,i=o.component,u=o.render;return Array.isArray(l)&&function(e){return 0===r.Children.count(e)}(l)&&(l=null),r.createElement(X.Provider,{value:a},a.match?l?"function"==typeof l?l(a):l:i?r.createElement(i,a):u?u(a):null:"function"==typeof l?l(a):null)}))},t}(r.Component);r.Component;var re=function(e){function t(){return e.apply(this,arguments)||this}return P(t,e),t.prototype.render=function(){var e=this;return r.createElement(X.Consumer,null,(function(t){t||W(!1);var n,a,o=e.props.location||t.location;return r.Children.forEach(e.props.children,(function(e){if(null==a&&r.isValidElement(e)){n=e;var l=e.props.path||e.props.from;a=l?te(o.pathname,d({},e.props,{path:l})):t.match}})),a?r.cloneElement(n,{location:o,computedMatch:a}):null}))},t}(r.Component);function ae(e){return"/"===e.charAt(0)?e:"/"+e}function oe(e){return"/"===e.charAt(0)?e.substr(1):e}function le(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function ie(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function ue(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function ce(e,t,n,r){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=d({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(e){throw e instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):e}return n&&(a.key=n),r?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=F(a.pathname,r.pathname)):a.pathname=r.pathname:a.pathname||(a.pathname="/"),a}function se(){var e=null,t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;r=1?r.createElement("button",{className:"btn btn-sm btn-light spaced"},r.createElement(_e,{to:"".concat(t,"?page=").concat(n-1)},r.createElement("span",{className:"active-pagination"},"Previous"))):r.createElement("button",{className:"btn btn-sm btn-light spaced"},r.createElement("span",{className:"inactive-pagination"},"Previous")),l>=a?r.createElement("button",{className:"btn btn-sm btn-light spaced"},r.createElement(_e,{to:"".concat(t,"?page=").concat(n+1)},r.createElement("span",{className:"active-pagination"},"Next"))):r.createElement("button",{className:"btn btn-sm btn-light spaced"},r.createElement("span",{className:"inactive-pagination"},"Next"))))};pt.propTypes={endpoint:U().string,page:U().number,limit:U().number,numOffset:U().number,numElements:U().number};const mt=pt;function ht(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function vt(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function yt(e,t,n,r,a,o,l){try{var i=e[o](l),u=i.value}catch(e){return void n(e)}i.done?t(u):Promise.resolve(u).then(r,a)}function gt(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],l=!0,i=!1;try{for(n=n.call(e);!(l=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);l=!0);}catch(e){i=!0,a=e}finally{try{l||null==n.return||n.return()}finally{if(i)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return bt(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?bt(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function bt(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);nt.name?1:-1}))},o=function(e){return e.sort((function(e,t){return e.name Manage Groups"))),r.createElement("table",{className:"table table-striped table-bordered table-hover"},r.createElement("thead",{className:"admin-table-head"},r.createElement("tr",null,r.createElement("th",{id:"user-header"},"User"," ",r.createElement(kt,{sorts:{asc:o,desc:a},callback:function(e){return f((function(){return e}))},testid:"user-sort"})),r.createElement("th",{id:"admin-header"},"Admin"," ",r.createElement(kt,{sorts:{asc:function(e){return e.sort((function(e){return e.admin?1:-1}))},desc:function(e){return e.sort((function(e){return e.admin?-1:1}))}},callback:function(e){return f((function(){return e}))},testid:"admin-sort"})),r.createElement("th",{id:"server-header"},"Server"," ",r.createElement(kt,{sorts:{asc:o,desc:a},callback:function(e){return f((function(){return e}))},testid:"server-sort"})),r.createElement("th",{id:"last-activity-header"},"Last Activity"," ",r.createElement(kt,{sorts:{asc:function(e){return e.sort((function(e,t){return new Date(e.last_activity)-new Date(t.last_activity)>0?1:-1}))},desc:function(e){return e.sort((function(e,t){return new Date(e.last_activity)-new Date(t.last_activity)>0?-1:1}))}},callback:function(e){return f((function(){return e}))},testid:"last-activity-sort"})),r.createElement("th",{id:"running-status-header"},"Running"," ",r.createElement(kt,{sorts:{asc:function(e){return e.sort((function(e){return null==e.server?-1:1}))},desc:function(e){return e.sort((function(e){return null==e.server?1:-1}))}},callback:function(e){return f((function(){return e}))},testid:"running-status-sort"})),r.createElement("th",{id:"actions-header"},"Actions"))),r.createElement("tbody",null,r.createElement("tr",{className:"noborder"},r.createElement("td",null,r.createElement(rt,{variant:"light",className:"add-users-button"},r.createElement(_e,{to:"/add-users"},"Add Users"))),r.createElement("td",null),r.createElement("td",null),r.createElement("td",null,r.createElement(rt,{variant:"primary",className:"start-all","data-testid":"start-all",onClick:function(){Promise.all(C(p.map((function(e){return e.name})))).then((function(e){var t=e.filter((function(e){return!e.ok}));return t.length>0&&u("Failed to start ".concat(t.length," ").concat(t.length>1?"servers":"server",". ").concat(t.length>1?"Are they ":"Is it "," already running?")),e})).then((function(e){return k.apply(void 0,b).then((function(e){O(e,g,v)})).catch((function(){return u("Failed to update users list.")})),e})).catch((function(){return u("Failed to start servers.")}))}},"Start All"),r.createElement("span",null," "),r.createElement(rt,{variant:"danger",className:"stop-all","data-testid":"stop-all",onClick:function(){Promise.all(N(p.map((function(e){return e.name})))).then((function(e){var t=e.filter((function(e){return!e.ok}));return t.length>0&&u("Failed to stop ".concat(t.length," ").concat(t.length>1?"servers":"server",". ").concat(t.length>1?"Are they ":"Is it "," already stopped?")),e})).then((function(e){return k.apply(void 0,b).then((function(e){O(e,g,v)})).catch((function(){return u("Failed to update users list.")})),e})).catch((function(){return u("Failed to stop servers.")}))}},"Stop All")),r.createElement("td",null,r.createElement(rt,{variant:"danger",id:"shutdown-button",onClick:S},"Shutdown Hub"))),A.map((function(e,n){var a,o,l,i,u,c,s=gt(e,2),f=s[0],d=s[1];return d.name=d.name||"",r.createElement("tr",{key:n+"row",className:"user-row"},r.createElement("td",{"data-testid":"user-row-name"},f.name),r.createElement("td",{"data-testid":"user-row-admin"},f.admin?"admin":""),r.createElement("td",{"data-testid":"user-row-server"},d.name?r.createElement("p",{class:"text-secondary"},d.name):r.createElement("p",{style:{color:"lightgrey"}},"[MAIN]")),r.createElement("td",{"data-testid":"user-row-last-activity"},d.last_activity?(a=d.last_activity,6e4,o=36e5,l=864e5,i=2592e6,u=31536e6,(c=Date.now()-Date.parse(a))<6e4?Math.round(c/1e3)+" seconds ago":c0?n.map((function(e,n){return r.createElement("li",{className:"list-group-item",key:"group-item"+n},r.createElement("span",{className:"badge badge-pill badge-success"},e.users.length+" users"),r.createElement(_e,{to:{pathname:"/group-edit",state:{group_data:e,user_data:t}}},e.name))})):r.createElement("div",null,r.createElement("h4",null,"no groups created..."))),r.createElement(mt,{endpoint:"/groups",page:i,limit:o,numOffset:u[0],numElements:n.length})),r.createElement("div",{className:"panel-footer"},r.createElement("button",{className:"btn btn-light adjacent-span-spacing"},r.createElement(_e,{to:"/"},"Back")),r.createElement("button",{className:"btn btn-primary adjacent-span-spacing",onClick:function(){s.push("/create-group")}},"New Group"))))))):r.createElement("div",{"data-testid":"no-show"})};xt.propTypes={user_data:U().array,groups_data:U().array,updateUsers:U().func,updateGroups:U().func,history:U().shape({push:U().func}),location:U().shape({search:U().string})};const _t=xt;function Ct(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],l=!0,i=!1;try{for(n=n.call(e);!(l=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);l=!0);}catch(e){i=!0,a=e}finally{try{l||null==n.return||n.return()}finally{if(i)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return Nt(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Nt(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Nt(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&r.push(m(e,S.name)),t.length>0&&r.push(h(t,S.name)),Promise.all(r).then((function(e){0==e.map((function(e){return e.status})).filter((function(e){return e>=300})).length?g(0,f).then((function(e){return p(e,0)})).then((function(){return w.push("/groups")})):s("Failed to edit group.")})).catch((function(){console.log("outer"),s("Failed to edit group.")}))}else w.push("/groups")}},"Apply"),r.createElement("button",{id:"delete-group","data-testid":"delete-group",className:"btn btn-danger",style:{float:"right"},onClick:function(){var e=S.name;v(e).then((function(e){e.status<300?g(0,f).then((function(e){return p(e,0)})).then((function(){return w.push("/groups")})):s("Failed to delete group.")})).catch((function(){return s("Failed to delete group.")}))}},"Delete Group"),r.createElement("br",null),r.createElement("br",null)))):r.createElement("div",null)};jt.propTypes={location:U().shape({state:U().shape({group_data:U().object,callback:U().func})}),history:U().shape({push:U().func}),addToGroup:U().func,removeFromGroup:U().func,deleteGroup:U().func,updateGroups:U().func,validateUser:U().func};const Rt=jt;function At(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],l=!0,i=!1;try{for(n=n.call(e);!(l=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);l=!0);}catch(e){i=!0,a=e}finally{try{l||null==n.return||n.return()}finally{if(i)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return It(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?It(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function It(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&0==/[!@#$%^&*(),.?":{}|<>]/g.test(e)}));e.lengthe.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&0==/[!@#$%^&*(),.?":{}|<>]/g.test(g)?u(m,""!=g?g:m,k).then((function(e){e.status<300?f(0,t).then((function(e){return i(e,0)})).then((function(){return d.push("/")})).catch((function(){return o("Could not update users list.")})):o("Failed to edit user.")})).catch((function(){o("Failed to edit user.")})):o("Failed to edit user. Make sure the username does not contain special characters."):u(m,m,k).then((function(e){e.status<300?f(0,t).then((function(e){return i(e,0)})).then((function(){return d.push("/")})).catch((function(){return o("Could not update users list.")})):o("Failed to edit user.")})).catch((function(){o("Failed to edit user.")})):s()}},"Apply")))))))};Vt.propTypes={location:U().shape({state:U().shape({username:U().string,has_admin:U().bool})}),history:U().shape({push:U().func}),editUser:U().func,deleteUser:U().func,failRegexEvent:U().func,noChangeEvent:U().func,updateUsers:U().func};const Wt=Vt;n(137);var Gt=function e(t,n,r){var a;if("function"==typeof n&&"function"==typeof r||"function"==typeof r&&"function"==typeof arguments[3])throw new Error(k(0));if("function"==typeof n&&void 0===r&&(r=n,n=void 0),void 0!==r){if("function"!=typeof r)throw new Error(k(1));return r(e)(t,n)}if("function"!=typeof t)throw new Error(k(2));var o=t,l=n,i=[],u=i,c=!1;function s(){u===i&&(u=i.slice())}function f(){if(c)throw new Error(k(3));return l}function d(e){if("function"!=typeof e)throw new Error(k(4));if(c)throw new Error(k(5));var t=!0;return s(),u.push(e),function(){if(t){if(c)throw new Error(k(6));t=!1,s();var n=u.indexOf(e);u.splice(n,1),i=null}}}function p(e){if(!C(e))throw new Error(k(7));if(void 0===e.type)throw new Error(k(8));if(c)throw new Error(k(9));try{c=!0,l=o(l,e)}finally{c=!1}for(var t=i=u,n=0;n0&&void 0!==arguments[0]?arguments[0]:j,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"USER_PAGE":return Object.assign({},e,{user_page:t.value.page,user_data:t.value.data,name_filter:t.value.name_filter});case"GROUPS_PAGE":return Object.assign({},e,{groups_page:t.value.page,groups_data:t.value.data});default:return e}}),j),Qt=function(){return(0,r.useEffect)((function(){var e=j.limit,t=j.groups_page;R("/users?offset=".concat(j.user_page*e,"&limit=").concat(e),"GET").then((function(e){return e.json()})).then((function(e){return Gt.dispatch({type:"USER_PAGE",value:{data:e,page:0}})})).catch((function(e){return console.log(e)})),R("/groups?offset=".concat(t*e,"&limit=").concat(e),"GET").then((function(e){return e.json()})).then((function(e){return Gt.dispatch({type:"GROUPS_PAGE",value:{data:e,page:0}})})).catch((function(e){return console.log(e)}))})),r.createElement("div",{className:"resets"},r.createElement(f,{store:Gt},r.createElement(be,null,r.createElement(re,null,r.createElement(ne,{exact:!0,path:"/",component:T(A)(St)}),r.createElement(ne,{exact:!0,path:"/groups",component:T(A)(_t)}),r.createElement(ne,{exact:!0,path:"/group-edit",component:T(A)(Rt)}),r.createElement(ne,{exact:!0,path:"/create-group",component:T(A)(zt)}),r.createElement(ne,{exact:!0,path:"/add-users",component:T(A)($t)}),r.createElement(ne,{exact:!0,path:"/edit-user",component:T(A)(Wt)})))))};a.render(r.createElement(Qt,null),document.getElementById("react-admin-hook"))},790:(e,t)=>{"use strict";t.E=function(){var e=[],t=e;function n(){t===e&&(t=e.slice())}return{listen:function(e){if("function"!=typeof e)throw new Error("Expected listener to be a function.");var r=!0;return n(),t.push(e),function(){if(r){r=!1,n();var a=t.indexOf(e);t.splice(a,1)}}},emit:function(){for(var n=e=t,r=0;r{var n;!function(){"use strict";var r={}.hasOwnProperty;function a(){for(var e=[],t=0;t{"use strict";n.r(t),n.d(t,{default:()=>i});var r=n(645),a=n.n(r),o=n(223),l=a()((function(e){return e[1]}));l.i(o.default),l.push([e.id,".users-container {\n width: 100%;\n position: relative;\n padding: 5px;\n overflow-x: scroll;\n}\n\n.users-container div {\n display: inline-block;\n}\n\n.users-container .item {\n padding: 3px;\n padding-left: 6px;\n padding-right: 6px;\n border-radius: 3px;\n font-size: 14px;\n margin-left: 4px;\n margin-right: 4px;\n transition: 30ms ease-in all;\n cursor: pointer;\n user-select: none;\n border: solid 1px #dfdfdf;\n}\n\n.users-container .item.unselected {\n background-color: #f7f7f7;\n color: #777;\n}\n\n.users-container .item.selected {\n background-color: orange;\n color: white;\n}\n\n.users-container .item:hover {\n opacity: 0.7;\n}\n",""]);const i=l},457:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var r=n(645),a=n.n(r),o=n(223),l=a()((function(e){return e[1]}));l.i(o.default),l.push([e.id,".pagination-footer * button {\n margin-right: 10px;\n}\n\n.pagination-footer * .inactive-pagination {\n color: gray;\n cursor: not-allowed;\n}\n\n.pagination-footer * button.spaced {\n color: var(--blue);\n}\n",""]);const i=l},642:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var r=n(645),a=n.n(r),o=n(223),l=a()((function(e){return e[1]}));l.i(o.default),l.push([e.id,".server-dashboard-container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.server-dashboard-container .add-users-button {\n border: 1px solid #ddd;\n}\n\n.server-dashboard-container tbody {\n color: #626262;\n}\n\n.admin-table-head {\n user-select: none;\n}\n\n.sort-icon {\n display: inline-block;\n top: 0.125em;\n position: relative;\n user-select: none;\n cursor: pointer;\n}\n\ntr.noborder > td {\n border: none !important;\n}\n",""]);const i=l},223:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(645),a=n.n(r)()((function(e){return e[1]}));a.push([e.id,":root {\n --red: #d7191e;\n --orange: #f1ad4e;\n --blue: #2e7ab6;\n --white: #ffffff;\n --gray: #f7f7f7;\n}\n\n/* Color Classes */\n.red {\n background-color: var(--red);\n}\n.orange {\n background-color: var(--orange);\n}\n.blue {\n background-color: var(--blue);\n}\n.white {\n background-color: var(--white);\n}\n\n/* Resets */\n\n.resets .modal {\n display: block;\n visibility: visible;\n z-index: 2000;\n}\n\n/* Global Util Classes */\n.adjacent-span-spacing {\n margin-right: 5px;\n margin-left: 5px;\n}\n",""]);const o=a},645:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var a={};if(r)for(var o=0;o{"use strict";var t=Object.prototype.hasOwnProperty;function n(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}e.exports=function(e,r){if(n(e,r))return!0;if("object"!=typeof e||null===e||"object"!=typeof r||null===r)return!1;var a=Object.keys(e),o=Object.keys(r);if(a.length!==o.length)return!1;for(var l=0;l{"use strict";var r=n(296),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},l={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},i={};function u(e){return r.isMemo(e)?l:i[e.$$typeof]||a}i[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},i[r.Memo]=l;var c=Object.defineProperty,s=Object.getOwnPropertyNames,f=Object.getOwnPropertySymbols,d=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=p(n);a&&a!==m&&e(t,a,r)}var l=s(n);f&&(l=l.concat(f(n)));for(var i=u(t),h=u(n),v=0;v{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,a=n?Symbol.for("react.portal"):60106,o=n?Symbol.for("react.fragment"):60107,l=n?Symbol.for("react.strict_mode"):60108,i=n?Symbol.for("react.profiler"):60114,u=n?Symbol.for("react.provider"):60109,c=n?Symbol.for("react.context"):60110,s=n?Symbol.for("react.async_mode"):60111,f=n?Symbol.for("react.concurrent_mode"):60111,d=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,h=n?Symbol.for("react.memo"):60115,v=n?Symbol.for("react.lazy"):60116,y=n?Symbol.for("react.block"):60121,g=n?Symbol.for("react.fundamental"):60117,b=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function E(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case s:case f:case o:case i:case l:case p:return e;default:switch(e=e&&e.$$typeof){case c:case d:case v:case h:case u:return e;default:return t}}case a:return t}}}function k(e){return E(e)===f}t.AsyncMode=s,t.ConcurrentMode=f,t.ContextConsumer=c,t.ContextProvider=u,t.Element=r,t.ForwardRef=d,t.Fragment=o,t.Lazy=v,t.Memo=h,t.Portal=a,t.Profiler=i,t.StrictMode=l,t.Suspense=p,t.isAsyncMode=function(e){return k(e)||E(e)===s},t.isConcurrentMode=k,t.isContextConsumer=function(e){return E(e)===c},t.isContextProvider=function(e){return E(e)===u},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return E(e)===d},t.isFragment=function(e){return E(e)===o},t.isLazy=function(e){return E(e)===v},t.isMemo=function(e){return E(e)===h},t.isPortal=function(e){return E(e)===a},t.isProfiler=function(e){return E(e)===i},t.isStrictMode=function(e){return E(e)===l},t.isSuspense=function(e){return E(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===f||e===i||e===l||e===p||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===v||e.$$typeof===h||e.$$typeof===u||e.$$typeof===c||e.$$typeof===d||e.$$typeof===g||e.$$typeof===b||e.$$typeof===w||e.$$typeof===y)},t.typeOf=E},296:(e,t,n)=>{"use strict";e.exports=n(103)},954:(e,t,n)=>{var r=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,o=/^0b[01]+$/i,l=/^0o[0-7]+$/i,i=parseInt,u="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g,c="object"==typeof self&&self&&self.Object===Object&&self,s=u||c||Function("return this")(),f=Object.prototype.toString,d=Math.max,p=Math.min,m=function(){return s.Date.now()};function h(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function v(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Symbol]"==f.call(e)}(e))return NaN;if(h(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=h(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(r,"");var n=o.test(e);return n||l.test(e)?i(e.slice(2),n?2:8):a.test(e)?NaN:+e}e.exports=function(e,t,n){var r,a,o,l,i,u,c=0,s=!1,f=!1,y=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function g(t){var n=r,o=a;return r=a=void 0,c=t,l=e.apply(o,n)}function b(e){return c=e,i=setTimeout(E,t),s?g(e):l}function w(e){var n=e-u;return void 0===u||n>=t||n<0||f&&e-c>=o}function E(){var e=m();if(w(e))return k(e);i=setTimeout(E,function(e){var n=t-(e-u);return f?p(n,o-(e-c)):n}(e))}function k(e){return i=void 0,y&&r?g(e):(r=a=void 0,l)}function S(){var e=m(),n=w(e);if(r=arguments,a=this,u=e,n){if(void 0===i)return b(u);if(f)return i=setTimeout(E,t),g(u)}return void 0===i&&(i=setTimeout(E,t)),l}return t=v(t)||0,h(n)&&(s=!!n.leading,o=(f="maxWait"in n)?d(v(n.maxWait)||0,t):o,y="trailing"in n?!!n.trailing:y),S.cancel=function(){void 0!==i&&clearTimeout(i),c=0,r=u=a=i=void 0},S.flush=function(){return void 0===i?l:k(m())},S}},418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,o){for(var l,i,u=a(e),c=1;c{var r=n(173);e.exports=function e(t,n,a){return r(n)||(a=n||a,n=[]),a=a||{},t instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},391:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){for(var e=arguments.length,t=Array(e),n=0;n{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){function t(t,n,r,a,o,l){var i=a||"<>",u=l||r;if(null==n[r])return t?new Error("Required "+o+" `"+u+"` was not specified in `"+i+"`."):null;for(var c=arguments.length,s=Array(c>6?c-6:0),f=6;f{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,l){if(l!==r){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},697:(e,t,n)=>{e.exports=n(703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},448:(e,t,n)=>{"use strict";var r=n(294),a=n(418),o=n(840);function l(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n