added the rest of the grid-view files

pull/4721/head
lianahus 7 months ago
parent 0a704c296f
commit 371926d6aa
  1. 4
      libs/remix-ui/grid-view/src/index.ts
  2. 42
      libs/remix-ui/grid-view/src/lib/components/customCheckbox.tsx
  3. 16
      libs/remix-ui/grid-view/src/lib/filtersContext.tsx
  4. 21
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.css
  5. 71
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.tsx
  6. 26
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.css
  7. 70
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.tsx
  8. 25
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-view.css
  9. 145
      libs/remix-ui/grid-view/src/lib/remix-ui-grid-view.tsx
  10. 16
      libs/remix-ui/grid-view/src/lib/themeContext.tsx

@ -0,0 +1,4 @@
export * from './lib/remix-ui-grid-view'
export * from './lib/remix-ui-grid-section'
export * from './lib/remix-ui-grid-cell'

@ -0,0 +1,42 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React from 'react'
import { useContext } from 'react'
import FiltersContext from ".././filtersContext"
interface CustomCheckboxProps {
label: string
color?: string
}
export const CustomCheckbox = (props: CustomCheckboxProps) => {
const filterCon = useContext(FiltersContext)
let textColor = props.color
let defChecked = true
if (filterCon.keyValueMap[props.label]) defChecked = filterCon.keyValueMap[props.label].enabled
if (!textColor || textColor == '') textColor = filterCon.keyValueMap[props.label].color
return (
<div className="h-80 mx-1 align-items-center custom-control custom-checkbox" style={{minWidth: '4rem'}}>
<input
className="custom-control-input"
id={"GVCheckbox" + props.label}
defaultChecked={defChecked}
onChange={e => {
if (props.label == 'no tag')
filterCon.showUntagged = ! filterCon.showUntagged
else filterCon.updateValue(props.label, e.target.checked, textColor)}}
type="checkbox"
/>
<label
className={"form-check-label custom-control-label text-nowrap text-" + textColor}
style={{ paddingTop: '0.125rem' }}
htmlFor={"GVCheckbox" + props.label}
data-id={"GVCheckboxLabel" + props.label}
>
{ props.label }
</label>
</div>
)
}
export default CustomCheckbox

@ -0,0 +1,16 @@
import React, { createContext, useState, useContext } from 'react';
interface FilterContextType {
showUntagged: boolean
keyValueMap: Record<string, { enabled: boolean; color: string; }>;
updateValue: (key: string, enabled: boolean, color: string) => void
addValue: (key: string, enabled: boolean, color: string) => void
}
const FiltersContext = createContext<FilterContextType>({
showUntagged: false,
keyValueMap: {},
updateValue: () => {},
addValue: () => {},
});
export default FiltersContext

@ -0,0 +1,21 @@
.remixui_grid_cell {
font-weight: normal;
}
.remixui_grid_cell_container {
width: fit-content;
}
.remixui_grid_cell_title{
font-size: 0.8rem;
font-style: italic;
}
.remixui_grid_cell_btn {
width: 32px;
}
.remixui_grid_cell_logo {
width: 3rem;
height: 3rem;
}

@ -0,0 +1,71 @@
import React, {useState, useEffect, useContext, useRef, ReactNode} from 'react' // eslint-disable-line
import './remix-ui-grid-cell.css'
import FiltersContext from "./filtersContext"
import { CustomTooltip } from '@remix-ui/helper'
declare global {
interface Window {
_paq: any
}
}
const _paq = window._paq = window._paq || []
interface RemixUIGridCellProps {
plugin: any
logo?: string
title?: string
tagList?: string[] // max 8, others will be ignored
classList?: string
styleList?: any
children?: ReactNode
}
export const RemixUIGridCell = (props: RemixUIGridCellProps) => {
const filterCon = useContext(FiltersContext)
const [anyEnabled, setAnyEnabled] = useState(false)
useEffect(() => {
if (props.tagList) setAnyEnabled(props.tagList.some((key) => filterCon.keyValueMap[key]?.enabled))
else setAnyEnabled(filterCon.showUntagged)
}, [filterCon, props.tagList])
return (
<div className='mr-2 mt-2'>
{ anyEnabled && <div className='d-flex flex-grid'>
<div className={"d-flex mx-0 p-2 bg-light border border-secondary remixui_grid_cell_container " + props.classList || ''} data-id={"remixUIGS" + props.title}>
<div className="d-flex remixui_grid_cell flex-column">
<div className='d-flex flex-row pb-1 align-items-end' style={{width: '4.4rem', height: '1rem'}}>
{ props.logo && <img className='remixui_grid_view_logo mr-1' src={props.logo} style={{width: '1rem', height: '1rem'}}/> }
{ props.title && <label className='m-0 p-0 align-items-left' style={{overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: 'xx-small'}}>{ props.title }</label> }
</div>
{ props.children }
</div>
</div>
{ props.tagList && <div className='d-flex flex-column align-items-begin' style={{position: 'relative', right: '0.4rem', top: '0.1rem'}}>
{ Object.keys(props.tagList).map((key) => (
filterCon.keyValueMap[props.tagList[key]].enabled && (
<CustomTooltip
placement="right"
tooltipId="pluginManagerInactiveTitleLinkToDoc"
tooltipClasses="text-nowrap"
tooltipText={props.tagList[key]}
>
<span key={props.tagList[key]}
className={'bg-' + filterCon.keyValueMap[props.tagList[key]].color}
style={{ fontSize: 'x-small', fontWeight: 'bolder' , width: '0.4rem', height: '1.2rem'}}>
</span>
</CustomTooltip>
)
)) }
</div> }
{ !props.tagList && <span
style={{ fontSize: 'x-small', fontWeight: 'bolder' , width: '0.4rem', height: '1.2rem'}}>
</span> }
</div> }
</div>
)
}
export default RemixUIGridCell

@ -0,0 +1,26 @@
.remixui_grid_section {
font-weight: normal;
}
.remixui_grid_section_container {
width: fit-content;
}
.remixui_grid_section_title{
font-size: 0.8rem;
font-style: italic;
}
.remixui_grid_section_btn {
width: 32px;
}
.remixui_grid_section_logo {
width: 3rem;
height: 3rem;
}
* {
scrollbar-width: thin;
scrollbar-color: var(--bg-dark) var(--bg-light);
}

@ -0,0 +1,70 @@
import React, {useState, useEffect, useContext, useRef, ReactNode} from 'react' // eslint-disable-line
import './remix-ui-grid-section.css'
import {ThemeContext, themes} from './themeContext'
declare global {
interface Window {
_paq: any
}
}
const _paq = window._paq = window._paq || []
interface RemixUIGridSectionProps {
plugin: any
title?: string
hScrollable: boolean
classList?: string
styleList?: any
children?: ReactNode
}
export const RemixUIGridSection = (props: RemixUIGridSectionProps) => {
const {plugin} = props.plugin
const searchInputRef = useRef(null)
console.log('props.hScrollable ', props.hScrollable)
const [state, setState] = useState<{
themeQuality: {filter: string; name: string}
}>({
themeQuality: themes.light
})
useEffect(() => {
plugin?.call('theme', 'currentTheme').then((theme) => {
// update theme quality. To be used for for images
setState((prevState) => {
return {
...prevState,
themeQuality: theme.quality === 'dark' ? themes.dark : themes.light
}
})
})
plugin?.on('theme', 'themeChanged', (theme) => {
// update theme quality. To be used for for images
setState((prevState) => {
return {
...prevState,
themeQuality: theme.quality === 'dark' ? themes.dark : themes.light
}
})
})
}, [plugin])
return (
<div
className={`d-flex px-4 py-2 flex-column w-100 remixui_grid_section_container ${props.classList}`}
data-id={"remixUIGS" + props.title}
style={{ overflowX: 'auto' }}
>
<div className="d-flex flex-column w-100 remixui_grid_section">
{ props.title && <h6 className='mt-1 mb-0 align-items-left '>{ props.title }</h6> }
<div className={(props.hScrollable) ? `d-flex flex-row pb-2 overflow-auto` : `d-flex flex-wrap`}>
{ props.children }
</div>
</div>
</div>
)
}
export default RemixUIGridSection

@ -0,0 +1,25 @@
.remixui_grid_view {
font-weight: normal;
}
.remixui_grid_view_container {
overflow: auto;
}
.remixui_grid_view_title{
font-size: 0.8rem;
font-style: italic;
}
.remixui_grid_view_btn {
width: 32px;
}
.remixui_grid_view_logo {
width: 3rem;
height: 3rem;
}
.remixui_grid_view_titlebar {
min-width: max-content;
}

@ -0,0 +1,145 @@
import React, {useState, useEffect, useContext, useRef, ReactNode} from 'react' // eslint-disable-line
import './remix-ui-grid-view.css'
import {ThemeContext, themes} from './themeContext'
import CustomCheckbox from './components/customCheckbox'
import FiltersContext from "./filtersContext"
declare global {
interface Window {
_paq: any
}
}
const _paq = window._paq = window._paq || []
interface RemixUIGridViewProps {
plugin: any
logo?: string
title?: string
enableFilter?: boolean
tagList?: [string, string][] // max 8, others will be ignored
showUntagged?: boolean
classList?: string
styleList?: any
description?: string
children?: ReactNode
}
export const RemixUIGridView = (props: RemixUIGridViewProps) => {
const [keyValueMap, setKeyValueMap] = useState<Record<string, { enabled: boolean; color: string; }>>({});
const showUntagged = props.showUntagged || false
const updateValue = (key: string, enabled: boolean, color?: string) => {
if (!color || color === '') color = setKeyValueMap[key].color
setKeyValueMap((prevMap) => ({
...prevMap,
[key]: {color, enabled},
}))
}
const addValue = (key: string, enabled: boolean, color: string) => {
// Check if the key already exists, if so, do not add
if (key in keyValueMap) {
return
}
// Add the new key-value pair
setKeyValueMap((prevMap) => ({
...prevMap,
[key]: { enabled, color },
}))
}
const {plugin} = props.plugin
const searchInputRef = useRef(null)
const [state, setState] = useState<{
themeQuality: {filter: string; name: string}
}>({
themeQuality: themes.light
})
// Initialize filters context with data from props
useEffect(() => {
if (props.tagList && Array.isArray(props.tagList)) {
const initialKeyValueMap: Record<string, { enabled: boolean; color: string; }> = {};
// Limit to first 8 elements, ignoring the rest
for (let i = 0; i < props.tagList.length; i++) {
const [key, color] = props.tagList[i]
initialKeyValueMap[key] = { enabled: true, color }
}
if (showUntagged) initialKeyValueMap['no tag'] = { enabled: true, color: 'primary' }
setKeyValueMap(initialKeyValueMap)
}
}, [])
useEffect(() => {
plugin?.call('theme', 'currentTheme').then((theme) => {
// update theme quality. To be used for for images
setState((prevState) => {
return {
...prevState,
themeQuality: theme.quality === 'dark' ? themes.dark : themes.light
}
})
})
plugin?.on('theme', 'themeChanged', (theme) => {
// update theme quality. To be used for for images
setState((prevState) => {
return {
...prevState,
themeQuality: theme.quality === 'dark' ? themes.dark : themes.light
}
})
})
}, [plugin])
return (
<FiltersContext.Provider value={{ showUntagged, keyValueMap, updateValue, addValue }}>
<div className={"d-flex flex-column bg-dark w-100 h-100 remixui_grid_view_container " + props.classList || ''} data-id="remixUIGV">
<ThemeContext.Provider value={state.themeQuality}>
<div className="d-flex flex-column w-100 remixui_grid_view">
<div className='d-flex p-4 bg-light flex-column remixui_grid_view_titlebar'>
<div className='d-flex flex-row align-items-center mb-2'>
{ props.logo && <img className='remixui_grid_view_logo mr-2' src={props.logo} /> }
{ props.title && <h3 className='mb-0'>{ props.title }</h3> }
</div>
{ props.description && <div className='pb-3 remixui_grid_view_title'>{ props.description }</div> }
{ props.enableFilter && <div className='d-flex flex-row'>
<div className="d-flex flex-row pr-2 pb-1 align-items-center justify-content-between">
<div className='d-flex' id="GVFilter">
<button
className="remixui_grid_view_btn text-secondary form-control bg-light border d-flex align-items-center p-2 justify-content-center fas fa-filter bg-light"
onClick={(e) => {
_paq.push(['trackEvent', 'GridView' + props.title ? props.title : '', 'filter', searchInputRef.current.value])
//setstate
}}
></button>
<input
ref={searchInputRef}
type="text"
style={{minWidth: '100px'}}
className="border form-control border-right-0 mr-4"
id="GVFilterInput"
placeholder={"Filter the list"}
data-id="RemixGVFilterInput"
/>
</div>
<div className='d-flex flex-row'>
{ Object.keys(keyValueMap).map((key) => (
<CustomCheckbox label={key} />
)) }
</div>
</div>
</div> }
</div>
{ props.children }
</div>
</ThemeContext.Provider>
</div>
</FiltersContext.Provider>
)
}
export default RemixUIGridView

@ -0,0 +1,16 @@
import React from 'react' // eslint-disable-line
export const themes = {
light: {
filter: 'invert(0)',
name: 'light'
},
dark: {
filter: 'invert(1)',
name: 'dark'
}
}
export const ThemeContext = React.createContext(
themes.dark // default value
)
Loading…
Cancel
Save