You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.1 KiB
144 lines
4.1 KiB
import React, { useCallback, useContext, useEffect, useMemo } from "react";
|
|
import chroma from "chroma-js";
|
|
import Select, { createFilter, Styles } from "react-select";
|
|
import LogListContext from "../../hooks/LogListContext";
|
|
import LogFilterChoiceContext from "../../hooks/LogFilterChoiceContext";
|
|
import { Config } from "react-select/src/filters";
|
|
|
|
import cssStyles from "./LogFilterSelector.module.sass";
|
|
|
|
export default function LogFilterSelector(props: {}) {
|
|
const {filter, updateFilter} = useContext(LogListContext);
|
|
const {channelNames, eventNames, characters} = useContext(LogFilterChoiceContext);
|
|
|
|
const options = useMemo(() => [
|
|
...channelNames.map(n => ({type: 0, color: "#77BB77", value: n, label: n})),
|
|
...eventNames.map(n => ({type: 1, color: "#BB7777", value: n, label: n})),
|
|
...characters.map(c => ({type: 2, color: "#3377BB", value: c.id, label: c.name})),
|
|
], [channelNames, eventNames, characters])
|
|
|
|
const value = useMemo(() => {
|
|
const value = [];
|
|
if (filter.characters && filter.characters.length > 0) {
|
|
value.push(...filter.characters.map(ch => options.find(c => c.type === 2 && c.value === ch)))
|
|
}
|
|
if (filter.events && filter.events.length > 0) {
|
|
value.push(...filter.events.map(v => options.find(c => c.type === 1 && c.value === v)))
|
|
}
|
|
if (filter.channels && filter.channels.length > 0) {
|
|
value.push(...filter.channels.map(v => options.find(c => c.type === 0 && c.value === v)))
|
|
}
|
|
|
|
return value
|
|
}, [filter, options])
|
|
|
|
const setValue = useCallback((value: {type:number, value:string}[] ) => {
|
|
if (value == null) {
|
|
value = [];
|
|
}
|
|
|
|
updateFilter({
|
|
...filter,
|
|
channels: value.filter(v => v.type === 0).map(v => v.value),
|
|
events: value.filter(v => v.type === 1).map(v => v.value),
|
|
characters: value.filter(v => v.type === 2).map(v => v.value),
|
|
})
|
|
}, [filter, updateFilter]);
|
|
|
|
return (
|
|
<Select
|
|
className={cssStyles.multiSelect}
|
|
closeMenuOnSelect={false}
|
|
styles={colourStyles}
|
|
filterOption={createFilter(filterConfig)}
|
|
defaultValue={[]}
|
|
isMulti={true}
|
|
options={options}
|
|
value={value}
|
|
onChange={setValue}
|
|
theme={defaultTheme => ({
|
|
...defaultTheme,
|
|
colors: {
|
|
...defaultTheme.colors,
|
|
...customTheme,
|
|
},
|
|
})}
|
|
/>
|
|
);
|
|
}
|
|
|
|
const customTheme = {
|
|
"primary": "#333333",
|
|
"primary75": "#333333",
|
|
"primary50": "#333333",
|
|
"primary25": "#333333",
|
|
"danger": "#000000",
|
|
"dangerLight": "#000000",
|
|
"neutral0": "#000000",
|
|
"neutral5": "#000000",
|
|
"neutral10": "#000000",
|
|
"neutral20": "#000000",
|
|
"neutral30": "#000000",
|
|
"neutral40": "#000000",
|
|
"neutral50": "#000000",
|
|
"neutral60": "#000000",
|
|
"neutral70": "#000000",
|
|
"neutral80": "#000000",
|
|
"neutral90": "#000000",
|
|
}
|
|
|
|
const filterConfig: Config = {
|
|
ignoreCase: true,
|
|
ignoreAccents: true,
|
|
trim: true,
|
|
matchFrom: 'start',
|
|
};
|
|
|
|
const colourStyles: Styles = {
|
|
control: styles => ({ ...styles, backgroundColor: 'rgba(0, 0, 0, 0.25)' }),
|
|
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
|
|
const color = chroma(data.color);
|
|
return {
|
|
...styles,
|
|
backgroundColor: isDisabled
|
|
? null
|
|
: isSelected
|
|
? data.color
|
|
: isFocused
|
|
? color.alpha(0.1).css()
|
|
: null,
|
|
color: isDisabled
|
|
? '#ccc'
|
|
: isSelected
|
|
? chroma.contrast(color, 'white') > 2
|
|
? 'white'
|
|
: 'black'
|
|
: data.color,
|
|
cursor: isDisabled ? 'not-allowed' : 'default',
|
|
|
|
':active': {
|
|
...styles[':active'],
|
|
backgroundColor: !isDisabled && (isSelected ? data.color : color.alpha(0.3).css()),
|
|
},
|
|
};
|
|
},
|
|
multiValue: (styles, { data }) => {
|
|
const color = chroma(data.color);
|
|
return {
|
|
...styles,
|
|
backgroundColor: color.alpha(0.1).css(),
|
|
};
|
|
},
|
|
multiValueLabel: (styles, { data }) => ({
|
|
...styles,
|
|
color: data.color,
|
|
}),
|
|
multiValueRemove: (styles, { data }) => ({
|
|
...styles,
|
|
color: data.color,
|
|
':hover': {
|
|
backgroundColor: data.color,
|
|
color: 'white',
|
|
},
|
|
}),
|
|
};
|