Skip to content

Commit

Permalink
HOSTSD-177 - Adding Server Allocation Table (#44)
Browse files Browse the repository at this point in the history
* adding allocation table component

* created sub-components for the allocation table dropdowns and table rows

* Adding proper table spacing for when 'tenant' is added to table

* removing placeholder for pagination
  • Loading branch information
wkaspryk authored Jan 8, 2024
1 parent 4585dbb commit 90732d8
Show file tree
Hide file tree
Showing 13 changed files with 485 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/dashboard/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@uidotdev/usehooks": "^2.4.1",
"axios": "^1.6.2",
"chart.js": "^4.4.1",
"classnames": "^2.5.1",
"cryptr": "^6.3.0",
"jsonwebtoken": "^9.0.2",
"jwk-to-pem": "^2.0.5",
Expand Down
2 changes: 2 additions & 0 deletions src/dashboard/src/app/hsb/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
SmallBarChart,
StorageTrendsChart,
TotalStorage,
AllocationTable
} from '@/components/charts';

export default function Page() {
Expand All @@ -14,6 +15,7 @@ export default function Page() {
<AllocationByStorageVolume />
<TotalStorage />
<SmallBarChart title="Allocation by OS" />
<AllocationTable />
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
@import '@/styles/utils.scss';

.panel {
@include panel-style(unset, unset, 1080px, 1310px);
padding-bottom: 34px;

>button {
@include export-btn;
}
}

.filter {
margin: 15px 0;

input {
min-width: 344px;
}
}

.header {
height: 35px;
background-color: $light-gray;
font-weight: bold;
color: $info-gray;
padding: 6px 14px;
display: flex;
}

.sortDropdown {
width: fit-content;
cursor: pointer;

&:first-child {
width: 18%;
}

&:nth-child(2) {
width: 25%;
}

p {
position: relative;
width: fit-content;

&::after {
content: "";
height: 6px;
width: 6px;
border-right: 1px solid $bc-black;
border-bottom: 1px solid $bc-black;
display: block;
position: absolute;
right: -16px;
bottom: 9px;
transform: rotate(45deg);
pointer-events: none;
}
}
}

.dropdown {
font-weight: normal;
background-color: $white;
padding: 0 15px;
width: 180px;
@include dropshadow;
position: relative;
top: 2px;
z-index: 2;
height: 0;
overflow: hidden;
opacity: 0;
transition: opacity, .3s;

&.visible {
height: auto;
opacity: 1;
visibility: visible;
}

ul {
padding: 0;
margin: 0;
list-style: none;

li {
height: 39px;
display: flex;
align-items: center;

&:hover {
font-weight: bold;
}
}
}
}

.visible {
.dropdown {
height: auto;
opacity: 1;
visibility: visible;
}

p::after {
transform: rotate(225deg);
bottom: 5px;
}
}

.chart {
max-height: 470px;
overflow-y: scroll;
padding-right: 10px;

@include scrollBar;
}

.row {
display: flex;
padding: 13px 0;
position: relative;
border-bottom: 1px solid $medium-gray;
}

.info,
.barChart {
display: flex;
}

.info {
width: 72%;

a {
width: 24%;
margin-left: 10px;
text-decoration: underline;
font-weight: bold;
color: $bc-black;
@include ellipsis;

&:hover {
opacity: 0.8;
}
}

p {
width: 21%;
@include ellipsis;

&:first-of-type {
width: 34.5%;
margin-left: 10px;
}

&:last-child {
width: unset;
}
}
}

.barChart {
width: 28%;
}

.bar {
height: 13px;
width: 100%;
border-radius: 10px;
margin-top: 12px;
background-color: $medium-gray;

.percentage {
height: 13px;
width: 60%;
border-radius: 10px 0 0 10px;
background-color: $chart-blue;
}
}

.used {
position: absolute;
right: 0;
top: 5px;
font-size: $font-size-12;
color: $info-gray;
}

.hasTenant {
.sortDropdown {
&:first-child {
width: 15%;
}

&:nth-child(2) {
width: 15%;
}
}

.info {
a {
width: 20%;
}

p {
width: 20%;

&:first-of-type {
width: 21%;
}

&:last-child {
width: unset;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
'use client';

import { Button } from '@/components/buttons';
import { Text } from '@/components/forms/text';
import React, { useState, useCallback } from 'react';
import styles from './AllocationTable.module.scss';
import classNames from 'classnames';
import { Dropdown } from './Dropdown';
import { TableRow } from './TableRow';
import defaultData from './defaultData';

const operatingSystem = 'Windows';

export const AllocationTable: React.FC = () => {
const [visibleDropdown, setVisibleDropdown] = useState<string | null>(null);

const toggleDropdown = useCallback((label: string) => {
setVisibleDropdown((prevVisibleDropdown) => (prevVisibleDropdown === label ? null : label));
}, []);

const onBlurHandler = useCallback(() => {
setVisibleDropdown(null);
}, []);

const hasTenant = defaultData.some((data) => data.tenant);

let dropdownConfigs = [
{ label: 'Server', options: ['A to Z', 'Z to A'] },
{ label: 'OS Version', options: ['Latest', 'Oldest'] },
{ label: 'Allocated Space', options: ['Ascending', 'Descending'] },
{ label: 'Unused', options: ['Ascending', 'Descending'] },
];

if (hasTenant) {
dropdownConfigs.splice(1, 0, { label: 'Tenant', options: ['A to Z', 'Z to A'] });
}

return (
<div className={styles.panel}>
<h1>Allocation by Storage Volume - All {operatingSystem} Servers</h1>
<div className={styles.filter}>
<Text placeholder="Filter by server name, OS version" iconType={'filter'} />
<Button variant="secondary">Apply</Button>
</div>
<div className={classNames(styles.tableContainer, { [styles.hasTenant]: hasTenant })}>
<div className={styles.header} onBlur={onBlurHandler}>
{dropdownConfigs.map((dropdown) => (
<Dropdown
key={dropdown.label}
label={dropdown.label}
options={dropdown.options}
visibleDropdown={visibleDropdown}
toggleDropdown={toggleDropdown}
/>
))}
<p>Total</p>
</div>
<div className={styles.chart}>
{defaultData.map((data, index) => (
<TableRow
key={index}
server={data.server}
tenant={data.tenant}
os={data.os}
allocated={data.allocated}
unused={data.unused}
/>
))}
</div>
</div>
<Button variant="secondary" iconPath="/images/download-icon.png">
Export to Excel
</Button>
</div>
);
};
36 changes: 36 additions & 0 deletions src/dashboard/src/components/charts/allocationTable/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use client';

import React from 'react';
import classNames from 'classnames';
import styles from './AllocationTable.module.scss';

interface DropdownProps {
label: string;
options: string[];
visibleDropdown: string | null;
toggleDropdown: (label: string) => void;
}

export const Dropdown: React.FC<DropdownProps> = ({
label,
options,
visibleDropdown,
toggleDropdown,
}) => (
<div
className={classNames(styles.sortDropdown, {
[styles.visible]: visibleDropdown === label,
})}
onClick={() => toggleDropdown(label)}
tabIndex={0}
>
<p>{label}</p>
<div className={styles.dropdown}>
<ul>
{options.map((option, index) => (
<li key={index}>{option}</li>
))}
</ul>
</div>
</div>
);
Loading

0 comments on commit 90732d8

Please sign in to comment.