Skip to content

Commit

Permalink
[CP-3325] Memory Usage Bar Component developed
Browse files Browse the repository at this point in the history
  • Loading branch information
dkarski committed Dec 6, 2024
1 parent 0b8363d commit 036e112
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 16 deletions.
3 changes: 3 additions & 0 deletions libs/generic-view/models/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { formRadioInput } from "./lib/form-radio-input"
import { formCheckboxInput } from "./lib/form-checkbox-input"
import { tooltip } from "./lib/tooltip"
import { progressBar } from "./lib/progress-bar"
import { segmentBar } from "./lib/segment-bar"
import { tooltipAnchor } from "./lib/tooltip-anchor"
import { overviewOsVersion } from "./lib/overview-os-version"
import { tooltipContent } from "./lib/tooltip-content"
Expand Down Expand Up @@ -103,6 +104,7 @@ export * from "./lib/form-search-input"
export * from "./lib/form-search-input-results"
export * from "./lib/form-checkbox-input"
export * from "./lib/progress-bar"
export * from "./lib/segment-bar"
export * from "./lib/tooltip"
export * from "./lib/tooltip-anchor"
export * from "./lib/tooltip-content"
Expand Down Expand Up @@ -169,6 +171,7 @@ export default {
[formSearchInputResults.key]: formSearchInputResults,
[formCheckboxInput.key]: formCheckboxInput,
[progressBar.key]: progressBar,
[segmentBar.key]: segmentBar,
[tooltip.key]: tooltip,
[tooltipAnchor.key]: tooltipAnchor,
[tooltipContent.key]: tooltipContent,
Expand Down
29 changes: 29 additions & 0 deletions libs/generic-view/models/src/lib/segment-bar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Copyright (c) Mudita sp. z o.o. All rights reserved.
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import { z } from "zod"

const dataValidator = z.undefined()

const segmentBarItemSchema = z.object({
color: z.string(),
label: z.string(),
value: z.number(),
minWidth: z.number(),
})

export type SegmentBarItem = z.infer<typeof segmentBarItemSchema>

const configValidator = z.object({
segments: z.array(segmentBarItemSchema),
segmentBorderRadius: z.string().optional(),
})
export type SegmentBarConfig = z.infer<typeof configValidator>

export const segmentBar = {
key: "segment-bar",
dataValidator,
configValidator,
} as const
3 changes: 3 additions & 0 deletions libs/generic-view/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { blocks } from "./lib/blocks/blocks"
import { rows } from "./lib/data-rows/data-rows"
import { predefinedComponents } from "./lib/predefined/predefined"
import { segmentBar } from "./lib/segment-bar"
import { helpers } from "./lib/helpers/helpers"
import { interactive } from "./lib/interactive/interactive"
import { labels } from "./lib/labels"
Expand All @@ -31,6 +32,7 @@ export * from "./lib/predefined/backup-restore/backup-restore-error"
export * from "./lib/predefined/import-contacts/import-contacts-error"
export * from "./lib/predefined/data-migration/components/transfer-error-modal"
export { DataMigrationPage } from "./lib/predefined/data-migration/data-migration"
export * from "./lib/segment-bar"
export * from "./lib/buttons/button-text"
export * from "./lib/buttons/button-primary"
export * from "./lib/texts/paragraphs"
Expand All @@ -40,6 +42,7 @@ export * from "./lib/entities"

const apiComponents = {
...predefinedComponents,
...segmentBar,
...blocks,
...rows,
...helpers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import {
computeSegmentBarItems,
SegmentBarItem,
} from "./compute-segment-bar-items.helper"
import { SegmentBarItem } from "generic-view/models"
import { computeSegmentBarItems } from "./compute-segment-bar-items.helper"

describe("Single segments", () => {
test("handles a single segment without minWidth", () => {
Expand Down Expand Up @@ -148,6 +146,16 @@ describe("Multiple segments - with minWidth", () => {
})

describe("Edge cases", () => {
test("returns an empty array when containerWidth is 0", () => {
const segments: SegmentBarItem[] = [
{ color: "#000", label: "Segment 1", value: 100, minWidth: 50 },
{ color: "#111", label: "Segment 2", value: 50, minWidth: 25 },
]
const result = computeSegmentBarItems(segments, 0)

expect(result).toEqual([])
})

test("ignores segments with value = 0", () => {
const segments: SegmentBarItem[] = [
{ color: "#000", label: "Segment 1", value: 0, minWidth: 50 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,18 @@
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

export interface SegmentBarItem {
color: string
label: string
value: number
minWidth: number
}
import { SegmentBarItem } from "generic-view/models"

interface AdjustedSegment extends SegmentBarItem {
usesMinWidth: boolean
}

interface ComputedSegmentBarItem extends SegmentBarItem {
export interface ComputedSegmentBarItem extends SegmentBarItem {
width: string
left: string
zIndex: number
}

export interface SegmentBarProps {
segments: SegmentBarItem[]
}

const calculateTotalSegmentValue = (segments: SegmentBarItem[]): number =>
segments.reduce((sum, segment) => sum + segment.value, 0)

Expand Down Expand Up @@ -81,7 +72,6 @@ const calculateWidth = (
: (segment.value / remainingSegmentValue) * remainingWidth
}


const calculateSegmentPositions = (
segments: AdjustedSegment[],
totalSegmentValue: number,
Expand Down Expand Up @@ -128,6 +118,10 @@ export const computeSegmentBarItems = (
segments: SegmentBarItem[],
containerWidth: number
): ComputedSegmentBarItem[] => {
if(containerWidth === 0) {
return []
}

const filteredSegments = segments.filter((segment) => segment.value > 0)

const totalSegmentValue = calculateTotalSegmentValue(filteredSegments)
Expand Down
11 changes: 11 additions & 0 deletions libs/generic-view/ui/src/lib/segment-bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) Mudita sp. z o.o. All rights reserved.
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import { segmentBar as segmentBarWrapper } from "generic-view/models"
import { SegmentBar } from "./segment-bar"

export const segmentBar = {
[segmentBarWrapper.key]: SegmentBar,
}
42 changes: 42 additions & 0 deletions libs/generic-view/ui/src/lib/segment-bar/segment-bar-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) Mudita sp. z o.o. All rights reserved.
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import React from "react"
import styled from "styled-components"
import { ComputedSegmentBarItem } from "./compute-segment-bar-items.helper"
import { BaseGenericComponent } from "generic-view/utils"

interface SegmentBarItemProps extends ComputedSegmentBarItem {
borderRadius: string
isFirst: boolean
}

export const SegmentBarItem: BaseGenericComponent<
undefined,
undefined,
SegmentBarItemProps
> = React.memo(({ color, width, left, zIndex, label, ...props }) => (
<Wrapper
style={{
width,
left,
zIndex,
backgroundColor: color,
}}
{...props}
/>
))

const Wrapper = styled.div<{
borderRadius: string
isFirst: boolean
}>`
position: absolute;
height: 100%;
border-radius: ${(props) =>
props.isFirst
? `${props.borderRadius}`
: `0 ${props.borderRadius} ${props.borderRadius} 0`};
`
50 changes: 50 additions & 0 deletions libs/generic-view/ui/src/lib/segment-bar/segment-bar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Copyright (c) Mudita sp. z o.o. All rights reserved.
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import React from "react"
import styled from "styled-components"
import { APIFC } from "generic-view/utils"
import { SegmentBarConfig } from "generic-view/models"
import { computeSegmentBarItems } from "./compute-segment-bar-items.helper"
import { SegmentBarItem } from "./segment-bar-item"
import { useContainerWidth } from "./use-container-width.hook"

export const SegmentBar: APIFC<undefined, SegmentBarConfig> = ({
config,
data,
...props
}) => {
const { ref, containerWidth } = useContainerWidth()

const computeSegments = React.useCallback(() => {
return computeSegmentBarItems(config.segments, containerWidth)
}, [config.segments, containerWidth])

const computedSegments = computeSegments()

const segmentBorderRadius = config.segmentBorderRadius || "56px"

return (
<Wrapper ref={ref} width={"100%"} height={"14px"} {...props}>
{computedSegments.map((segment, index) => (
<SegmentBarItem
key={index}
{...segment}
borderRadius={segmentBorderRadius}
isFirst={index === 0}
/>
))}
</Wrapper>
)
}

const Wrapper = styled.div<{
width: string
height: string
}>`
position: relative;
width: ${(props) => props.width};
height: ${(props) => props.height};
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright (c) Mudita sp. z o.o. All rights reserved.
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import { useLayoutEffect, useRef, useState } from "react"

export const useContainerWidth = () => {
const ref = useRef<HTMLDivElement>(null)
const [containerWidth, setContainerWidth] = useState(0)

useLayoutEffect(() => {
if (ref.current) {
setContainerWidth(ref.current.offsetWidth)
}
}, [ref])

return { ref, containerWidth }
}

0 comments on commit 036e112

Please sign in to comment.