Compare commits
1 Commits
fdefdbd12e
...
5719743b57
| Author | SHA1 | Date | |
|---|---|---|---|
| 5719743b57 |
@@ -13,7 +13,7 @@ export const Table = styled.default.table`
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
background-color: ${Theme.blackWithOpacity};
|
background-color: ${Theme.colors.gray900};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Thead = styled.default.thead`
|
export const Thead = styled.default.thead`
|
||||||
|
|||||||
@@ -1,209 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
import {useState, useEffect, useRef} from 'react';
|
|
||||||
|
|
||||||
import {IChannel} from 'interfaces';
|
|
||||||
import {Label} from 'components/label';
|
|
||||||
|
|
||||||
import {DropdownContainer, DropdownInput, DropdownMenu, DropdownMenuItem} from './style';
|
|
||||||
|
|
||||||
const keys = ['ArrowDown', 'ArrowUp', 'Enter', 'Escape'];
|
|
||||||
|
|
||||||
interface IDropdown {
|
|
||||||
itemKey: string;
|
|
||||||
searchTerm?: string;
|
|
||||||
onSelect: (key: string) => void;
|
|
||||||
items: IChannel[];
|
|
||||||
label: string;
|
|
||||||
name: string;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
const maxNumOfItemsShown = 30;
|
|
||||||
|
|
||||||
export const Dropdown = (props: IDropdown): JSX.Element => {
|
|
||||||
const {itemKey, searchTerm, onSelect, items, label, name, className} = props;
|
|
||||||
const [showDropdownMenu, setShowDropdownMenu] = useState(false);
|
|
||||||
const [input, setInput] = useState(searchTerm || '');
|
|
||||||
const [filteredItems, setFilteredItems] = useState(items);
|
|
||||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
||||||
const allItemsRef = useRef([]);
|
|
||||||
const parentElementRef = useRef(null);
|
|
||||||
const scrollSelectedItemInView = index => {
|
|
||||||
if (!parentElementRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dropdownMenu = parentElementRef.current;
|
|
||||||
const menuItems = allItemsRef.current;
|
|
||||||
|
|
||||||
if (!menuItems) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const menuItem = menuItems[index];
|
|
||||||
|
|
||||||
if (!menuItem) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isOutOfUpperView = menuItem.offsetTop < dropdownMenu.scrollTop;
|
|
||||||
const isOutOfLowerView = (menuItem.offsetTop + menuItem.clientHeight) > (dropdownMenu.scrollTop + dropdownMenu.clientHeight);
|
|
||||||
|
|
||||||
if (isOutOfUpperView) {
|
|
||||||
dropdownMenu.scrollTop = menuItem.offsetTop;
|
|
||||||
} else if (isOutOfLowerView) {
|
|
||||||
dropdownMenu.scrollTop = (menuItem.offsetTop + menuItem.clientHeight) - dropdownMenu.clientHeight;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setSelectInput = value => {
|
|
||||||
setInput(value);
|
|
||||||
onSelect(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClickOutside = event => {
|
|
||||||
if (!parentElementRef.current || parentElementRef.current.contains(event.target)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filteredItems.length) {
|
|
||||||
setSelectInput('');
|
|
||||||
}
|
|
||||||
|
|
||||||
setShowDropdownMenu(false);
|
|
||||||
onSelect(input);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
scrollSelectedItemInView(selectedIndex);
|
|
||||||
}, [selectedIndex]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.addEventListener('click', handleClickOutside, true);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener('click', handleClickOutside, true);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const filteredItems = items.filter(item => {
|
|
||||||
if (item[itemKey].toLowerCase().indexOf(input.toLowerCase()) > -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (filteredItems.length > 0) {
|
|
||||||
setSelectedIndex(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFilteredItems(filteredItems);
|
|
||||||
}, [input, items, itemKey]);
|
|
||||||
|
|
||||||
const selectItemInFocusBy = offset => {
|
|
||||||
const lastIndex = filteredItems.length - 1;
|
|
||||||
const nextIndex = selectedIndex + offset;
|
|
||||||
|
|
||||||
if (nextIndex > lastIndex) {
|
|
||||||
setSelectedIndex(0);
|
|
||||||
} else if (nextIndex < 0) {
|
|
||||||
setSelectedIndex(lastIndex);
|
|
||||||
} else {
|
|
||||||
setSelectedIndex(nextIndex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleOnKeyDown = event => {
|
|
||||||
if (keys.indexOf(event.key) === -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [arrDown, arrUp, enter, escape] = keys;
|
|
||||||
const moves = {
|
|
||||||
[arrDown]: 1,
|
|
||||||
[arrUp]: -1
|
|
||||||
};
|
|
||||||
const move = moves[event.key];
|
|
||||||
|
|
||||||
if (move !== undefined) {
|
|
||||||
event.preventDefault();
|
|
||||||
selectItemInFocusBy(move);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === enter) {
|
|
||||||
if (filteredItems[selectedIndex]) {
|
|
||||||
setSelectInput(filteredItems[selectedIndex][itemKey]);
|
|
||||||
setShowDropdownMenu(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === escape) {
|
|
||||||
event.preventDefault();
|
|
||||||
setShowDropdownMenu(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectItem = (index: number) => {
|
|
||||||
setSelectInput(filteredItems[index][itemKey]);
|
|
||||||
setSelectedIndex(index);
|
|
||||||
setShowDropdownMenu(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateMenuOptions = () => {
|
|
||||||
return filteredItems.length
|
|
||||||
? filteredItems.slice(0, maxNumOfItemsShown).map((item, index) => {
|
|
||||||
return (
|
|
||||||
<DropdownMenuItem
|
|
||||||
ref={ref => allItemsRef.current[index] = ref}
|
|
||||||
selected={selectedIndex === index}
|
|
||||||
key={`dropdown-menu-item-${index}`}
|
|
||||||
onClick={() => selectItem(index)}
|
|
||||||
>
|
|
||||||
{item[itemKey]}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: (
|
|
||||||
<DropdownMenuItem disabled={true}>
|
|
||||||
No results found
|
|
||||||
</DropdownMenuItem>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInput = ({target}) => {
|
|
||||||
setInput(target.value);
|
|
||||||
|
|
||||||
if (!showDropdownMenu) {
|
|
||||||
setShowDropdownMenu(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleDropdownMenu = () => setShowDropdownMenu(!showDropdownMenu);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownContainer>
|
|
||||||
<Label
|
|
||||||
htmlFor="autocomplete"
|
|
||||||
text={label}
|
|
||||||
/>
|
|
||||||
<DropdownInput
|
|
||||||
onKeyDown={handleOnKeyDown}
|
|
||||||
showMenu={showDropdownMenu}
|
|
||||||
autoComplete="off"
|
|
||||||
name={name}
|
|
||||||
onChange={handleInput}
|
|
||||||
value={input}
|
|
||||||
onClick={toggleDropdownMenu}
|
|
||||||
className={className}
|
|
||||||
/>
|
|
||||||
{showDropdownMenu && (
|
|
||||||
<DropdownMenu ref={parentElementRef} className="testId-generatedMenuOptions">
|
|
||||||
{generateMenuOptions()}
|
|
||||||
</DropdownMenu>
|
|
||||||
)}
|
|
||||||
</DropdownContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
import * as styled from 'styled-components';
|
|
||||||
import Input from 'components/forms/Input';
|
|
||||||
import Theme from 'theme';
|
|
||||||
|
|
||||||
const {spacing, colors, typography, primaryBorderRadius} = Theme;
|
|
||||||
|
|
||||||
export const DropdownContainer = styled.default.div`
|
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
|
||||||
margin: ${spacing.xSmall} 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const DropdownInput = styled.default(Input)<{showMenu?: boolean}>`
|
|
||||||
${({showMenu}) => showMenu && styled.css`
|
|
||||||
border-bottom-left-radius: 0px;
|
|
||||||
border-bottom-right-radius: 0px;
|
|
||||||
border-bottom-width: 0;
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const DropdownMenu = styled.default.div`
|
|
||||||
width: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
top: calc(100% - 4px);
|
|
||||||
position: absolute;
|
|
||||||
height: auto;
|
|
||||||
max-height: 210px;
|
|
||||||
border: 1px solid ${colors.gray400};
|
|
||||||
border-top-width: 0;
|
|
||||||
z-index: 4;
|
|
||||||
background-color: ${colors.white};
|
|
||||||
border-bottom-left-radius: ${primaryBorderRadius};
|
|
||||||
border-bottom-right-radius: ${primaryBorderRadius};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const DropdownMenuItem = styled.default.div<{
|
|
||||||
active?: boolean;
|
|
||||||
disabled?: boolean;
|
|
||||||
selected?: boolean;
|
|
||||||
}>`
|
|
||||||
line-height: ${spacing.large};
|
|
||||||
padding: ${spacing.xsmall} ${spacing.medium};
|
|
||||||
font-size: ${typography.fontSizeS};
|
|
||||||
word-wrap: break-word;
|
|
||||||
${({active, selected, disabled}) => styled.css`
|
|
||||||
background-color: ${active || selected ? colors.gray300 : 'transparent'};
|
|
||||||
font-weight: ${selected ? 'bold' : 'normal'};
|
|
||||||
color: ${disabled ? colors.gray500 : colors.gray900}
|
|
||||||
|
|
||||||
:hover{
|
|
||||||
background-color: ${disabled ? colors.white : colors.gray300};
|
|
||||||
cursor: ${disabled ? 'text' : 'pointer'};
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
export * from './indicators';
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
import React from 'react';
|
|
||||||
import {LoadingWheel as Loader} from 'components';
|
|
||||||
import {SingleStreamSymbol, OfflineSymbol, MultipleStreamSymbol, Indicator} from './style';
|
|
||||||
|
|
||||||
export const OfflineIndicator = (): React.JSX.Element => (
|
|
||||||
<Indicator>
|
|
||||||
<OfflineSymbol />
|
|
||||||
</Indicator>
|
|
||||||
);
|
|
||||||
export const SingleStreamIndicator = (): React.JSX.Element => (
|
|
||||||
<Indicator className="single-stream-indicator">
|
|
||||||
<SingleStreamSymbol className="testId-singleStreamIndicator" />
|
|
||||||
</Indicator>
|
|
||||||
);
|
|
||||||
export const MultiStreamIndicator = (): React.JSX.Element => (
|
|
||||||
<Indicator className="multi-stream-indicator">
|
|
||||||
<MultipleStreamSymbol className="testId-multiStreamIndicator" />
|
|
||||||
</Indicator>
|
|
||||||
);
|
|
||||||
export const LoadingIndicator = (): React.JSX.Element => (
|
|
||||||
<Indicator>
|
|
||||||
<Loader size={'medium'} className="loading-wheel" />
|
|
||||||
</Indicator>
|
|
||||||
);
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
import * as styled from 'styled-components';
|
|
||||||
|
|
||||||
export const Indicator = styled.default.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
/* Target LoadingWheel component by class name */
|
|
||||||
.loading-wheel {
|
|
||||||
flex: 0;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
& span {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const IndicatorOutline = styled.default.div`
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border-radius: 50%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const OfflineSymbol = styled.default(IndicatorOutline)`
|
|
||||||
border: 3px solid #707070;
|
|
||||||
background-color: transparent;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const SingleStreamSymbol = styled.default(IndicatorOutline)`
|
|
||||||
background-color: #08BD0B;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const MultipleStreamSymbol = styled.default(SingleStreamSymbol)`
|
|
||||||
width: 1rem;
|
|
||||||
height: 1rem;
|
|
||||||
margin-left: -2px;
|
|
||||||
box-shadow: 9px 0 0 0 #08BD0B;
|
|
||||||
`;
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
import {JSX} from 'react';
|
|
||||||
import {useSelector} from 'react-redux';
|
|
||||||
import {AppStore} from 'store';
|
|
||||||
import {SingleStreamIndicator, OfflineIndicator, MultiStreamIndicator, LoadingIndicator} from './indicators';
|
|
||||||
|
|
||||||
interface IPublishingStateIndicator {
|
|
||||||
row: any;
|
|
||||||
publishingStateKey: string;
|
|
||||||
idKey: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PublishingStateIndicator = ({row, publishingStateKey, idKey}: IPublishingStateIndicator): JSX.Element => {
|
|
||||||
const id = row[idKey] as string;
|
|
||||||
const publishingState = useSelector((state: AppStore) => publishingStateKey && state[publishingStateKey as keyof AppStore]?.publishingState);
|
|
||||||
const rowPublishingState = publishingState.find((record: any) => record[idKey] === id);
|
|
||||||
|
|
||||||
if (!publishingState) {
|
|
||||||
return <LoadingIndicator />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rowPublishingState) {
|
|
||||||
return <LoadingIndicator />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rowPublishingState.isOnline) {
|
|
||||||
return <OfflineIndicator />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rowPublishingState.multipleStreams) {
|
|
||||||
return <MultiStreamIndicator />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <SingleStreamIndicator />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PublishingStateIndicator;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
import {createContext} from 'react';
|
|
||||||
|
|
||||||
export const ViewContext = createContext('');
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
export * from './contexts';
|
|
||||||
export * from './date';
|
export * from './date';
|
||||||
export * from './sort';
|
export * from './sort';
|
||||||
export * from './validators';
|
export * from './validators';
|
||||||
|
|||||||
Reference in New Issue
Block a user