diff --git a/jsx/src/components/AddUser/AddUser.jsx b/jsx/src/components/AddUser/AddUser.jsx index 7cf5a955..b313195c 100644 --- a/jsx/src/components/AddUser/AddUser.jsx +++ b/jsx/src/components/AddUser/AddUser.jsx @@ -29,7 +29,16 @@ const AddUser = (props) => { {errorAlert != null ? (
-
{errorAlert}
+
+ {errorAlert} + +
) : ( @@ -94,7 +103,7 @@ const AddUser = (props) => { .then(() => history.push("/")) .catch((err) => console.log(err)) : setErrorAlert( - `[${data.status}] Failed to create user. ${ + `Failed to create user. ${ data.status == 409 ? "User already exists." : "" }` ) diff --git a/jsx/src/components/CreateGroup/CreateGroup.jsx b/jsx/src/components/CreateGroup/CreateGroup.jsx index 08f9aa5d..e873410e 100644 --- a/jsx/src/components/CreateGroup/CreateGroup.jsx +++ b/jsx/src/components/CreateGroup/CreateGroup.jsx @@ -28,7 +28,16 @@ const CreateGroup = (props) => { {errorAlert != null ? (
-
{errorAlert}
+
+ {errorAlert} + +
) : ( @@ -69,16 +78,18 @@ const CreateGroup = (props) => { ? updateGroups(0, limit) .then((data) => dispatchPageUpdate(data, 0)) .then(() => history.push("/groups")) - .catch((err) => console.log(err)) + .catch((err) => + setErrorAlert(`Could not update groups list.`) + ) : setErrorAlert( - `[${data.status}] Failed to create group. ${ + `Failed to create group. ${ data.status == 409 ? "Group already exists." : "" }` ); }) - .catch((err) => console.log(err)); + .catch((err) => setErrorAlert(`Could not create group.`)); }} > Create diff --git a/jsx/src/components/EditUser/EditUser.jsx b/jsx/src/components/EditUser/EditUser.jsx index d491a38d..785054aa 100644 --- a/jsx/src/components/EditUser/EditUser.jsx +++ b/jsx/src/components/EditUser/EditUser.jsx @@ -44,7 +44,16 @@ const EditUser = (props) => { {errorAlert != null ? (
-
{errorAlert}
+
+ {errorAlert} + +
) : ( @@ -89,12 +98,16 @@ const EditUser = (props) => { ? updateUsers(0, limit) .then((data) => dispatchPageChange(data, 0)) .then(() => history.push("/")) - .catch((err) => console.log(err)) - : setErrorAlert( - `[${data.status}] Failed to edit user.` - ); + .catch((err) => + setErrorAlert( + `Could not update users list.` + ) + ) + : setErrorAlert(`Failed to edit user.`); }) - .catch((err) => console.log(err)); + .catch((err) => { + setErrorAlert(`Failed to edit user.`); + }); }} > Delete user @@ -129,17 +142,20 @@ const EditUser = (props) => { ? updateUsers(0, limit) .then((data) => dispatchPageChange(data, 0)) .then(() => history.push("/")) - .catch((err) => console.log(err)) - : setErrorAlert( - `[${data.status}] Failed to edit user.` - ); + .catch((err) => + setErrorAlert( + `Could not update users list.` + ) + ) + : setErrorAlert(`Failed to edit user.`); }) .catch((err) => { - console.log(err); + setErrorAlert(`Failed to edit user.`); }); } else { - setUpdatedUsername(""); - failRegexEvent(); + setErrorAlert( + `Failed to edit user. Make sure the username does not contain special characters.` + ); } } else { editUser(username, username, admin) @@ -148,13 +164,13 @@ const EditUser = (props) => { ? updateUsers(0, limit) .then((data) => dispatchPageChange(data, 0)) .then(() => history.push("/")) - .catch((err) => console.log(err)) - : setErrorAlert( - `[${data.status}] Failed to edit user.` - ); + .catch((err) => + setErrorAlert(`Could not update users list.`) + ) + : setErrorAlert(`Failed to edit user.`); }) .catch((err) => { - console.log(err); + setErrorAlert(`Failed to edit user.`); }); } }} diff --git a/jsx/src/components/GroupEdit/GroupEdit.jsx b/jsx/src/components/GroupEdit/GroupEdit.jsx index 7b966fbd..9b404ce9 100644 --- a/jsx/src/components/GroupEdit/GroupEdit.jsx +++ b/jsx/src/components/GroupEdit/GroupEdit.jsx @@ -7,6 +7,7 @@ import GroupSelect from "../GroupSelect/GroupSelect"; const GroupEdit = (props) => { var [selected, setSelected] = useState([]), [changed, setChanged] = useState(false), + [errorAlert, setErrorAlert] = useState(null), limit = useSelector((state) => state.limit); var dispatch = useDispatch(); @@ -42,6 +43,24 @@ const GroupEdit = (props) => { return (
+ {errorAlert != null ? ( +
+
+
+ {errorAlert} + +
+
+
+ ) : ( + <> + )}

Editing Group {group_data.name}

@@ -89,12 +108,13 @@ const GroupEdit = (props) => { ); Promise.all(promiseQueue) + // TODO add error if res not ok .then(() => { updateGroups(0, limit) .then((data) => dispatchPageUpdate(data, 0)) .then(() => history.push("/groups")); }) - .catch((err) => console.log(err)); + .catch((err) => setErrorAlert(`Could not edit group.`)); }} > Apply @@ -106,12 +126,13 @@ const GroupEdit = (props) => { onClick={() => { var groupName = group_data.name; deleteGroup(groupName) + // TODO add error if res not ok .then(() => { updateGroups(0, limit) .then((data) => dispatchPageUpdate(data, 0)) .then(() => history.push("/groups")); }) - .catch((err) => console.log(err)); + .catch((err) => setErrorAlert(`Could not delete group.`)); }} > Delete Group diff --git a/jsx/src/components/ServerDashboard/ServerDashboard.jsx b/jsx/src/components/ServerDashboard/ServerDashboard.jsx index c2dd4fe2..80e3b6bb 100644 --- a/jsx/src/components/ServerDashboard/ServerDashboard.jsx +++ b/jsx/src/components/ServerDashboard/ServerDashboard.jsx @@ -27,6 +27,7 @@ const ServerDashboard = (props) => { runningAsc = (e) => e.sort((a) => (a.server == null ? -1 : 1)), runningDesc = (e) => e.sort((a) => (a.server == null ? 1 : -1)); + var [errorAlert, setErrorAlert] = useState(null); var [sortMethod, setSortMethod] = useState(null); var user_data = useSelector((state) => state.user_data), @@ -73,6 +74,24 @@ const ServerDashboard = (props) => { return (
+ {errorAlert != null ? ( +
+
+
+ {errorAlert} + +
+
+
+ ) : ( + <> + )}
{"> Manage Groups"}
@@ -127,15 +146,32 @@ const ServerDashboard = (props) => { className="start-all" onClick={() => { Promise.all(startAll(user_data.map((e) => e.name))) + .then((res) => { + let failedServers = res.filter((e) => !e.ok); + if (failedServers.length > 0) { + setErrorAlert( + `Could not start ${failedServers.length} ${ + failedServers.length > 1 ? "servers" : "server" + }. ${ + failedServers.length > 1 ? "Are they " : "Is it " + } already running?` + ); + } + return res; + }) .then((res) => { updateUsers(...slice) .then((data) => { dispatchPageUpdate(data, page); }) - .catch((err) => console.log(err)); + .catch((err) => + setErrorAlert(`Could not update users list.`) + ); return res; }) - .catch((err) => console.log(err)); + .catch((err) => + setErrorAlert(`Could not start servers.`) + ); }} > Start All @@ -147,15 +183,32 @@ const ServerDashboard = (props) => { className="stop-all" onClick={() => { Promise.all(stopAll(user_data.map((e) => e.name))) + .then((res) => { + let failedServers = res.filter((e) => !e.ok); + if (failedServers.length > 0) { + setErrorAlert( + `Could not stop ${failedServers.length} ${ + failedServers.length > 1 ? "servers" : "server" + }. ${ + failedServers.length > 1 ? "Are they " : "Is it " + } already stopped?` + ); + } + return res; + }) .then((res) => { updateUsers(...slice) .then((data) => { dispatchPageUpdate(data, page); }) - .catch((err) => console.log(err)); + .catch((err) => + setErrorAlert(`Could not update users list.`) + ); return res; }) - .catch((err) => console.log(err)); + .catch((err) => + setErrorAlert(`Could not stop all servers.`) + ); }} > Stop All @@ -187,12 +240,22 @@ const ServerDashboard = (props) => { onClick={() => stopServer(e.name) .then((res) => { - updateUsers(...slice).then((data) => { - dispatchPageUpdate(data, page); - }); + if (res.ok) return res; + throw new Error(res.status); + }) + .then((res) => { + updateUsers(...slice) + .then((data) => { + dispatchPageUpdate(data, page); + }) + .catch((err) => + setErrorAlert(`Could not update users list.`) + ); return res; }) - .catch((err) => console.log(err)) + .catch((err) => + setErrorAlert(`Could not stop server.`) + ) } > Stop Server @@ -204,12 +267,22 @@ const ServerDashboard = (props) => { onClick={() => startServer(e.name) .then((res) => { - updateUsers(...slice).then((data) => { - dispatchPageUpdate(data, page); - }); + if (res.ok) return res; + throw new Error(res.status); + }) + .then((res) => { + updateUsers(...slice) + .then((data) => { + dispatchPageUpdate(data, page); + }) + .catch((err) => + setErrorAlert(`Could not update users list.`) + ); return res; }) - .catch((err) => console.log(err)) + .catch((err) => { + setErrorAlert(`Could not start server.`); + }) } > Start Server diff --git a/jsx/src/util/withAPI.js b/jsx/src/util/withAPI.js index 37506004..c767fcdf 100644 --- a/jsx/src/util/withAPI.js +++ b/jsx/src/util/withAPI.js @@ -7,9 +7,10 @@ const withAPI = withProps(() => ({ data.json() ), updateGroups: (offset, limit) => - jhapiRequest(`/groups?offset=${offset}&limit=${limit}`, "GET").then( - (data) => data.json() - ), + jhapiRequest( + `/groups?offset=${offset}&limit=${limit}`, + "GET" + ).then((data) => data.json()), shutdownHub: () => jhapiRequest("/shutdown", "POST"), startServer: (name) => jhapiRequest("/users/" + name + "/server", "POST"), stopServer: (name) => jhapiRequest("/users/" + name + "/server", "DELETE"), @@ -36,13 +37,8 @@ const withAPI = withProps(() => ({ jhapiRequest("/users/" + username, "GET") .then((data) => data.status) .then((data) => (data > 200 ? false : true)), - failRegexEvent: () => - alert( - "Cannot change username - either contains special characters or is too short." - ), - noChangeEvent: () => { - returns; - }, + failRegexEvent: () => {}, + noChangeEvent: () => {}, refreshGroupsData: () => jhapiRequest("/groups", "GET").then((data) => data.json()), refreshUserData: () => diff --git a/share/jupyterhub/static/js/admin-react.js b/share/jupyterhub/static/js/admin-react.js index ff569d6a..7a104a33 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={733:(e,t,n)=>{"use strict";var r=n(294),a=n(935),o=n(697),l=n.n(o),i=r.createContext(null),u=function(e){e()},c=function(){return u},s={notify:function(){}},f=function(){function e(e,t){this.store=e,this.parentSub=t,this.unsubscribe=null,this.listeners=s,this.handleChangeWrapper=this.handleChangeWrapper.bind(this)}var t=e.prototype;return t.addNestedSub=function(e){return this.trySubscribe(),this.listeners.subscribe(e)},t.notifyNestedSubs=function(){this.listeners.notify()},t.handleChangeWrapper=function(){this.onStateChange&&this.onStateChange()},t.isSubscribed=function(){return Boolean(this.unsubscribe)},t.trySubscribe=function(){this.unsubscribe||(this.unsubscribe=this.parentSub?this.parentSub.addNestedSub(this.handleChangeWrapper):this.store.subscribe(this.handleChangeWrapper),this.listeners=function(){var e=c(),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)}}}}())},t.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null,this.listeners.clear(),this.listeners=s)},e}();const d=function(e){var t=e.store,n=e.context,a=e.children,o=(0,r.useMemo)((function(){var e=new f(t);return e.onStateChange=e.notifyNestedSubs,{store:t,subscription:e}}),[t]),l=(0,r.useMemo)((function(){return t.getState()}),[t]);(0,r.useEffect)((function(){var e=o.subscription;return e.trySubscribe(),l!==t.getState()&&e.notifyNestedSubs(),function(){e.tryUnsubscribe(),e.onStateChange=null}}),[o,l]);var u=n||i;return r.createElement(u.Provider,{value:o},a)};n(679),n(864);var p="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?r.useLayoutEffect:r.useEffect,h=n(121),m=function(){return Math.random().toString(36).substring(7).split("").join(".")},v={INIT:"@@redux/INIT"+m(),REPLACE:"@@redux/REPLACE"+m(),PROBE_UNKNOWN_ACTION:function(){return"@@redux/PROBE_UNKNOWN_ACTION"+m()}};function y(e){if("object"!=typeof e||null===e)return!1;for(var t=e;null!==Object.getPrototypeOf(t);)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function g(){return(g=Object.assign||function(e){for(var t=1;t200)}))},failRegexEvent:function(){return alert("Cannot change username - either contains special characters or is too short.")},noChangeEvent:function(){returns},refreshGroupsData:function(){return A("/groups","GET").then((function(e){return e.json()}))},refreshUserData:function(){return A("/users","GET").then((function(e){return e.json()}))}}},j=function(e){return g({},e,O())},function(e){var t=(0,r.createFactory)(e);return function(e){return t(j(e))}});var j;function z(e){return"/"===e.charAt(0)}function I(e,t){for(var n=t,r=n+1,a=e.length;r=0;s--){var f=a[s];"."===f?I(a,s):".."===f?(I(a,s),c++):c&&(I(a,s),c--)}if(!i)for(;c--;c)a.unshift("..");!i||""===a[0]||a[0]&&z(a[0])||a.unshift("");var d=a.join("/");return n&&"/"!==d.substr(-1)&&(d+="/"),d};"undefined"==typeof window||!window.document||window.document.createElement;var U=1073741823,F="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};function $(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 B=r.createContext||function(e,t){var n,a,o,i="__create-react-context-"+((F[o="__global_unique_id__"]=(F[o]||0)+1)+"__"),u=function(e){function n(){var t;return(t=e.apply(this,arguments)||this).emitter=$(t.props.value),t}P(n,e);var r=n.prototype;return r.getChildContext=function(){var e;return(e={})[i]=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):U,0!=(n|=0)&&this.emitter.set(e.value,n))}var o,l},r.render=function(){return this.props.children},n}(r.Component);u.childContextTypes=((n={})[i]=l().object.isRequired,n);var c=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?U:t},r.componentDidMount=function(){this.context[i]&&this.context[i].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?U:e},r.componentWillUnmount=function(){this.context[i]&&this.context[i].off(this.onUpdate)},r.getValue=function(){return this.context[i]?this.context[i].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 c.contextTypes=((a={})[i]=l().object,a),{Provider:u,Consumer:c}};const H=function(e,t){if(!e)throw new Error("Invariant failed")};var V=n(779),W=n.n(V);function G(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}var Q=function(e){var t=B();return t.displayName="Router-History",t}(),q=function(e){var t=B();return t.displayName="Router",t}(),K=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()},n.render=function(){return r.createElement(q.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},r.createElement(Q.Provider,{children:this.props.children||null,value:this.props.history}))},t}(r.Component);r.Component,r.Component;var Y={},X=0;function J(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=Y[n]||(Y[n]={});if(r[e])return r[e];var a=[],o={regexp:W()(e,a,t),keys:a};return X<1e4&&(r[e]=o,X++),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 Z=function(e){function t(){return e.apply(this,arguments)||this}return P(t,e),t.prototype.render=function(){var e=this;return r.createElement(q.Consumer,null,(function(t){t||H(!1);var n=e.props.location||t.location,a=g({},t,{location:n,match:e.props.computedMatch?e.props.computedMatch:e.props.path?J(n.pathname,e.props):t.match}),o=e.props,l=o.children,i=o.component,u=o.render;return Array.isArray(l)&&0===l.length&&(l=null),r.createElement(q.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 ee=function(e){function t(){return e.apply(this,arguments)||this}return P(t,e),t.prototype.render=function(){var e=this;return r.createElement(q.Consumer,null,(function(t){t||H(!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?J(o.pathname,g({},e.props,{path:l})):t.match}})),a?r.cloneElement(n,{location:o,computedMatch:a}):null}))},t}(r.Component);function te(e){return"/"===e.charAt(0)?e:"/"+e}function ne(e){return"/"===e.charAt(0)?e.substr(1):e}function re(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 ae(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function oe(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 le(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)).state=t:(void 0===(a=g({},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=D(a.pathname,r.pathname)):a.pathname=r.pathname:a.pathname||(a.pathname="/"),a}function ie(){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(ke,{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(ke,{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"))))};He.propTypes={endpoint:l().string,page:l().number,limit:l().number,numOffset:l().number,numElements:l().number};const Ve=He;function We(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e)){var n=[],r=!0,a=!1,o=void 0;try{for(var l,i=e[Symbol.iterator]();!(r=(l=i.next()).done)&&(n.push(l.value),!t||n.length!==t);r=!0);}catch(e){a=!0,o=e}finally{try{r||null==i.return||i.return()}finally{if(a)throw o}}return n}}(e,t)||function(e,t){if(e){if("string"==typeof e)return Ge(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)?Ge(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 Ge(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n Manage Groups")),r.createElement("div",{className:"server-dashboard-container"},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(qe,{sorts:{asc:function(e){return e.sort((function(e,t){return e.namet.name?1:-1}))}},callback:function(e){return a((function(){return e}))}})),r.createElement("th",{id:"admin-header"},"Admin"," ",r.createElement(qe,{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 a((function(){return e}))}})),r.createElement("th",{id:"last-activity-header"},"Last Activity"," ",r.createElement(qe,{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 a((function(){return e}))}})),r.createElement("th",{id:"running-status-header"},"Running"," ",r.createElement(qe,{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 a((function(){return e}))}})),r.createElement("th",{id:"actions-header"},"Actions"))),r.createElement("tbody",null,r.createElement("tr",{className:"noborder"},r.createElement("td",null,r.createElement(Ae,{variant:"light",className:"add-users-button"},r.createElement(ke,{to:"/add-users"},"Add Users"))),r.createElement("td",null),r.createElement("td",null),r.createElement("td",null,r.createElement(Ae,{variant:"primary",className:"start-all",onClick:function(){Promise.all(m(o.map((function(e){return e.name})))).then((function(e){return f.apply(void 0,c).then((function(e){g(e,u)})).catch((function(e){return console.log(e)})),e})).catch((function(e){return console.log(e)}))}},"Start All"),r.createElement("span",null," "),r.createElement(Ae,{variant:"danger",className:"stop-all",onClick:function(){Promise.all(v(o.map((function(e){return e.name})))).then((function(e){return f.apply(void 0,c).then((function(e){g(e,u)})).catch((function(e){return console.log(e)})),e})).catch((function(e){return console.log(e)}))}},"Stop All")),r.createElement("td",null,r.createElement(Ae,{variant:"danger",id:"shutdown-button",onClick:d},"Shutdown Hub"))),o.map((function(e,t){return r.createElement("tr",{key:t+"row",className:"user-row"},r.createElement("td",null,e.name),r.createElement("td",null,e.admin?"admin":""),r.createElement("td",null,e.last_activity?(n=e.last_activity,6e4,a=36e5,o=864e5,l=2592e6,i=31536e6,(s=Date.now()-Date.parse(n))<6e4?Math.round(s/1e3)+" seconds ago":s0?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(ke,{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(Ve,{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(ke,{to:"/"},"Back")),r.createElement("button",{className:"btn btn-primary adjacent-span-spacing",onClick:function(){s.push("/create-group")}},"New Group"))))))):r.createElement("div",null)};Ye.propTypes={user_data:l().array,groups_data:l().array,updateUsers:l().func,updateGroups:l().func,history:l().shape({push:l().func}),location:l().shape({search:l().string})};const Xe=Ye;function Je(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e)){var n=[],r=!0,a=!1,o=void 0;try{for(var l,i=e[Symbol.iterator]();!(r=(l=i.next()).done)&&(n.push(l.value),!t||n.length!==t);r=!0);}catch(e){a=!0,o=e}finally{try{r||null==i.return||i.return()}finally{if(a)throw o}}return n}}(e,t)||function(e,t){if(e){if("string"==typeof e)return Ze(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)?Ze(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 Ze(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(f(e,g.name)),t.length>0&&r.push(d(t,g.name)),Promise.all(r).then((function(){h(0,u).then((function(e){return s(e,0)})).then((function(){return v.push("/groups")}))})).catch((function(e){return console.log(e)}))}else v.push("/groups")}},"Apply"),r.createElement("button",{id:"delete-group",className:"btn btn-danger",style:{float:"right"},onClick:function(){var e=g.name;p(e).then((function(){h(0,u).then((function(e){return s(e,0)})).then((function(){return v.push("/groups")}))})).catch((function(e){return console.log(e)}))}},"Delete Group"),r.createElement("br",null),r.createElement("br",null)))):r.createElement("div",null)};at.propTypes={location:l().shape({state:l().shape({group_data:l().object,callback:l().func})}),history:l().shape({push:l().func}),addToGroup:l().func,removeFromGroup:l().func,deleteGroup:l().func,updateGroups:l().func,validateUser:l().func};const ot=at;function lt(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e)){var n=[],r=!0,a=!1,o=void 0;try{for(var l,i=e[Symbol.iterator]();!(r=(l=i.next()).done)&&(n.push(l.value),!t||n.length!==t);r=!0);}catch(e){a=!0,o=e}finally{try{r||null==i.return||i.return()}finally{if(a)throw o}}return n}}(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,E).then((function(e){e.status<300?d(0,t).then((function(e){return i(e,0)})).then((function(){return p.push("/")})).catch((function(e){return console.log(e)})):o("[".concat(e.status,"] Failed to edit user."))})).catch((function(e){console.log(e)})):(b(""),s()):u(m,m,E).then((function(e){e.status<300?d(0,t).then((function(e){return i(e,0)})).then((function(){return p.push("/")})).catch((function(e){return console.log(e)})):o("[".concat(e.status,"] Failed to edit user."))})).catch((function(e){console.log(e)})):f()}},"Apply")))))))};vt.propTypes={location:l().shape({state:l().shape({username:l().string,has_admin:l().bool})}),history:l().shape({push:l().func}),editUser:l().func,deleteUser:l().func,failRegexEvent:l().func,noChangeEvent:l().func,updateUsers:l().func};const yt=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("It looks like you are passing several store enhancers to createStore(). This is not supported. Instead, compose them together to a single function.");if("function"==typeof n&&void 0===r&&(r=n,n=void 0),void 0!==r){if("function"!=typeof r)throw new Error("Expected the enhancer to be a function.");return r(e)(t,n)}if("function"!=typeof t)throw new Error("Expected the reducer to be a function.");var o=t,l=n,i=[],u=i,c=!1;function s(){u===i&&(u=i.slice())}function f(){if(c)throw new Error("You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store.");return l}function d(e){if("function"!=typeof e)throw new Error("Expected the listener to be a function.");if(c)throw new Error("You may not call store.subscribe() while the reducer is executing. If you would like to be notified after the store has been updated, subscribe from a component and invoke store.getState() in the callback to access the latest state. See https://redux.js.org/api-reference/store#subscribelistener for more details.");var t=!0;return s(),u.push(e),function(){if(t){if(c)throw new Error("You may not unsubscribe from a store listener while the reducer is executing. See https://redux.js.org/api-reference/store#subscribelistener for more details.");t=!1,s();var n=u.indexOf(e);u.splice(n,1),i=null}}}function p(e){if(!y(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if(void 0===e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(c)throw new Error("Reducers may not dispatch actions.");try{c=!0,l=o(l,e)}finally{c=!1}for(var t=i=u,n=0;n0&&void 0!==arguments[0]?arguments[0]:R,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});case"GROUPS_PAGE":return Object.assign({},e,{groups_page:t.value.page,groups_data:t.value.data});default:return e}}),R),bt=function(){return(0,r.useEffect)((function(){var e=R.limit,t=R.groups_page;A("/users?offset=".concat(R.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)})),A("/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(d,{store:gt},r.createElement(ve,null,r.createElement(ee,null,r.createElement(Z,{exact:!0,path:"/",component:T(M)(Ke)}),r.createElement(Z,{exact:!0,path:"/groups",component:T(M)(Xe)}),r.createElement(Z,{exact:!0,path:"/group-edit",component:T(M)(ot)}),r.createElement(Z,{exact:!0,path:"/create-group",component:T(M)(ct)}),r.createElement(Z,{exact:!0,path:"/add-users",component:T(M)(pt)}),r.createElement(Z,{exact:!0,path:"/edit-user",component:T(M)(yt)})))))};a.render(r.createElement(bt,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(864),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,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var a=p(n);a&&a!==h&&e(t,a,r)}var l=s(n);f&&(l=l.concat(f(n)));for(var i=u(t),m=u(n),v=0;v{"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)}},703:(e,t,n)=>{"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,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