summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opendc-web/opendc-web-ui/src/api/users.js32
-rw-r--r--opendc-web/opendc-web-ui/src/components/AppHeaderUser.js32
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js1
-rw-r--r--opendc-web/opendc-web-ui/src/data/query.js2
-rw-r--r--opendc-web/opendc-web-ui/src/data/user.js40
5 files changed, 99 insertions, 8 deletions
diff --git a/opendc-web/opendc-web-ui/src/api/users.js b/opendc-web/opendc-web-ui/src/api/users.js
new file mode 100644
index 00000000..12a9be05
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/api/users.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import { request } from './index'
+
+/**
+ * Fetch information about the user from the web server.
+ *
+ * @param auth The authentication object.
+ */
+export function fetchUser(auth) {
+ return request(auth, `users/me`)
+}
diff --git a/opendc-web/opendc-web-ui/src/components/AppHeaderUser.js b/opendc-web/opendc-web-ui/src/components/AppHeaderUser.js
index e271accb..3a73d9ba 100644
--- a/opendc-web/opendc-web-ui/src/components/AppHeaderUser.js
+++ b/opendc-web/opendc-web-ui/src/components/AppHeaderUser.js
@@ -28,26 +28,44 @@ import {
DropdownItem,
DropdownGroup,
Avatar,
+ Progress,
+ ProgressSize,
+ DropdownSeparator,
} from '@patternfly/react-core'
import { useReducer } from 'react'
import { useAuth } from '../auth'
+import useUser from '../data/user'
export default function AppHeaderUser() {
const { logout, user, isAuthenticated, isLoading } = useAuth()
const username = isAuthenticated || isLoading ? user?.name : 'Anonymous'
const avatar = isAuthenticated || isLoading ? user?.picture : '/img/avatar.svg'
+ const { data } = useUser()
+ const simulationBudget = data?.accounting?.simulationTimeBudget ?? 3600
+ const simulationTime = data?.accounting?.simulationTime | 0
+
const [isDropdownOpen, toggleDropdown] = useReducer((t) => !t, false)
const userDropdownItems = [
- <DropdownGroup key="group 2">
- <DropdownItem
- key="group 2 logout"
- isDisabled={!isAuthenticated}
- onClick={() => logout({ returnTo: window.location.origin })}
- >
- Logout
+ <DropdownGroup key="budget" label="Monthly Simulation Budget">
+ <DropdownItem isDisabled>
+ <Progress
+ min={0}
+ max={simulationBudget}
+ value={simulationTime}
+ title={`${Math.ceil(simulationTime / 60)} of ${Math.ceil(simulationBudget / 60)} minutes`}
+ size={ProgressSize.sm}
+ />
</DropdownItem>
</DropdownGroup>,
+ <DropdownSeparator key="separator" />,
+ <DropdownItem
+ key="group 2 logout"
+ isDisabled={!isAuthenticated}
+ onClick={() => logout({ returnTo: window.location.origin })}
+ >
+ Logout
+ </DropdownItem>,
]
const avatarComponent = avatar ? (
diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js
index 8dc52f7a..64218a0a 100644
--- a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js
+++ b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js
@@ -64,7 +64,6 @@ function ScenarioTable({ portfolio, status }) {
) : (
'Unknown Topology'
)}
- ,
</Td>
<Td dataLabel="Workload">{`${scenario.workload.trace.name} (${
scenario.workload.samplingFraction * 100
diff --git a/opendc-web/opendc-web-ui/src/data/query.js b/opendc-web/opendc-web-ui/src/data/query.js
index 59eaa684..3e5423b9 100644
--- a/opendc-web/opendc-web-ui/src/data/query.js
+++ b/opendc-web/opendc-web-ui/src/data/query.js
@@ -26,6 +26,7 @@ import { useAuth } from '../auth'
import { configureExperimentClient } from './experiments'
import { configureProjectClient } from './project'
import { configureTopologyClient } from './topology'
+import { configureUserClient } from './user'
let queryClient
@@ -34,6 +35,7 @@ function createQueryClient(auth) {
configureProjectClient(client, auth)
configureExperimentClient(client, auth)
configureTopologyClient(client, auth)
+ configureUserClient(client, auth)
return client
}
diff --git a/opendc-web/opendc-web-ui/src/data/user.js b/opendc-web/opendc-web-ui/src/data/user.js
new file mode 100644
index 00000000..97c0e1e2
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/data/user.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import { useQuery } from 'react-query'
+import { fetchUser } from '../api/users'
+
+/**
+ * Configure the query defaults for the user client.
+ */
+export function configureUserClient(queryClient, auth) {
+ queryClient.setQueryDefaults('user', {
+ queryFn: () => fetchUser(auth),
+ })
+}
+
+/**
+ * Fetch the user data on the server.
+ */
+export default function useUser(options = {}) {
+ return useQuery('user', options)
+}