@ -1,13 +1,19 @@
import React from 'react' ;
import React , { useEffect } from 'react' ;
import Switch from '@material-ui/core/Switch' ;
import Box from '@material-ui/core/Box' ;
import FormControlLabel from '@material-ui/core/FormControlLabel' ;
import FormControl from '@material-ui/core/FormControl' ;
import Button from '@material-ui/core/Button' ;
import LabelIcon from '@material-ui/icons/Label' ;
import ImportContactsIcon from '@material-ui/icons/ImportContacts' ;
import PhotoIcon from '@material-ui/icons/Photo' ;
import SearchIcon from '@material-ui/icons/Search' ;
import Menu from '@material-ui/core/Menu' ;
import MenuItem from '@material-ui/core/MenuItem' ;
import DialogTitle from '@material-ui/core/DialogTitle' ;
import Dialog from '@material-ui/core/Dialog' ;
import Select from '@material-ui/core/Select' ;
import { makeStyles } from '@material-ui/core/styles' ;
@ -40,14 +46,110 @@ const useStyles = makeStyles(theme => ({
} ,
} ) ) ;
export function EditConstFilterExpression ( props ) {
const { onChange , filter } = props ;
var _ = require ( 'lodash' ) ;
function handleResultToggled ( ) {
var newfilter = _ . cloneDeep ( filter ) ;
newfilter . constval = ! filter . constval ;
onChange ( newfilter ) ;
}
return (
< FormControlLabel
control = {
< Switch
checked = { filter . constval }
onChange = { handleResultToggled }
color = "primary"
/ >
}
label = { filter . constval ? "TRUE" : "FALSE" }
/ >
) ;
}
export function EditLogicalOperatorFilterExpression ( props ) {
const { onChange , filter } = props ;
var _ = require ( 'lodash' ) ;
const id = _ . uniqueId ( "logic_op_" ) ;
const labelid = _ . uniqueId ( "logic_op_label_" ) ;
function handleChange ( e ) {
console . log ( "changing to value: " , e . target . value ) ;
var newfilter = _ . cloneDeep ( filter ) ;
newfilter . operator = e . target . value ;
onChange ( newfilter ) ;
}
return (
< FormControl >
< Select
labelId = { labelid }
id = { id }
value = { filter . operator }
onChange = { handleChange }
>
< MenuItem value = { LogicalOperatorEnum . AND } > AND < / M e n u I t e m >
< MenuItem value = { LogicalOperatorEnum . OR } > OR < / M e n u I t e m >
< / S e l e c t >
< / F o r m C o n t r o l >
) ;
}
export function EditFilterExpressionDialog ( props ) {
const classes = useStyles ( ) ;
const { onClose , startingFilter , open } = props ;
const [ filter , setFilter ] = React . useState ( startingFilter ) ;
useEffect ( ( ) => {
setFilter ( startingFilter ) ;
} , [ startingFilter ] ) ;
const handleClose = ( ) => {
onClose ( filter ) ;
} ;
var _ = require ( 'lodash' ) ;
const id = _ . uniqueId ( "simple_dialog_title_" ) ;
var control = < > < / > ;
var subprops = {
onChange : setFilter ,
filter : filter ,
} ;
if ( filter instanceof ConstFilter ) {
control = < EditConstFilterExpression { ... subprops } / >
} else if ( filter instanceof LogicalOperatorFilter ) {
control = < EditLogicalOperatorFilterExpression { ... subprops } / >
} / * else if ( expr instanceof MatchingFilter ) {
filter _elem = < MatchingFilterExpressionControl { ... props } onClick = { handleClick } / >
} * /
return (
< Dialog aria - labelledby = { id } open = { open } >
< DialogTitle id = { id } > Edit expression < / D i a l o g T i t l e >
{ control }
< Button onClick = { handleClose } >
Done
< / B u t t o n >
< / D i a l o g >
) ;
}
export function TagEqualsExpressionControl ( props ) {
const classes = useStyles ( ) ;
const { name } = props ;
const { name , onClick } = props ;
return (
< >
< Button
variant = "outlined"
className = { classes . filterexpcontrol }
aria - controls = "simple-menu" aria - haspopup = "true"
onClick = { onClick }
startIcon = { < LabelIcon / > } >
{ name }
< / B u t t o n >
@ -57,12 +159,14 @@ export function TagEqualsExpressionControl(props) {
export function AlbumEqualsExpressionControl ( props ) {
const classes = useStyles ( ) ;
const { name } = props ;
const { name , onClick } = props ;
return (
< >
< Button
variant = "outlined"
className = { classes . filterexpcontrol }
aria - controls = "simple-menu" aria - haspopup = "true"
onClick = { onClick }
startIcon = { < ImportContactsIcon / > } >
{ name }
< / B u t t o n >
@ -72,12 +176,14 @@ export function AlbumEqualsExpressionControl(props) {
export function ImageNameEqualsExpressionControl ( props ) {
const classes = useStyles ( ) ;
const { name } = props ;
const { name , onClick } = props ;
return (
< >
< Button
variant = "outlined"
className = { classes . filterexpcontrol }
aria - controls = "simple-menu" aria - haspopup = "true"
onClick = { onClick }
startIcon = { < PhotoIcon / > } >
{ name }
< / B u t t o n >
@ -87,12 +193,14 @@ export function ImageNameEqualsExpressionControl(props) {
export function ImageNameNaturalMatchExpressionControl ( props ) {
const classes = useStyles ( ) ;
const { name } = props ;
const { name , onClick } = props ;
return (
< >
< Button
variant = "outlined"
className = { classes . filterexpcontrol }
aria - controls = "simple-menu" aria - haspopup = "true"
onClick = { onClick }
startIcon = { < > < PhotoIcon / > < SearchIcon / > < / > } >
{ name }
< / B u t t o n >
@ -102,23 +210,23 @@ export function ImageNameNaturalMatchExpressionControl(props) {
export function MatchingFilterExpressionControl ( props ) {
const classes = useStyles ( ) ;
const { expr } = props ;
const { expr , onClick } = props ;
var pretty _name = expr . match _from
. replace ( /^"/g , '' )
. replace ( /"$/g , '' ) ;
if ( expr . match _type === MatchTypeEnum . MATCH _TAG _EQUALS ) {
return < TagEqualsExpressionControl name = { pretty _name } / >
return < TagEqualsExpressionControl name = { pretty _name } onClick = { onClick } / >
} else if ( expr . match _type === MatchTypeEnum . MATCH _ALBUM _EQUALS ) {
return < AlbumEqualsExpressionControl name = { pretty _name } / >
return < AlbumEqualsExpressionControl name = { pretty _name } onClick = { onClick } / >
} else if ( expr . match _type === MatchTypeEnum . MATCH _ALBUM _EQUALS _OR _CHILD ) {
return < AlbumEqualsExpressionControl name = { pretty _name + '(/...)' } / >
return < AlbumEqualsExpressionControl name = { pretty _name + '(/...)' } onClick = { onClick } / >
} else if ( expr . match _type === MatchTypeEnum . MATCH _IMAGE _NAME _EQUALS ) {
return < ImageNameEqualsExpressionControl name = { pretty _name } / >
return < ImageNameEqualsExpressionControl name = { pretty _name } onClick = { onClick } / >
} else if ( expr . match _type === MatchTypeEnum . MATCH _IMAGE _NAME _NATURAL ) {
return < ImageNameNaturalMatchExpressionControl name = { pretty _name } / >
return < ImageNameNaturalMatchExpressionControl name = { pretty _name } onClick = { onClick } / >
} else if ( expr . match _type === MatchTypeEnum . MATCH _ALBUM _NAME _EQUALS ) {
return < AlbumEqualsExpressionControl name = { '(.../)' + pretty _name + '(/...)' } / >
return < AlbumEqualsExpressionControl name = { '(.../)' + pretty _name + '(/...)' } onClick = { onClick } / >
}
throw new Error ( 'Cannot render matching filter control: unsupported type.' ) ;
@ -126,7 +234,7 @@ export function MatchingFilterExpressionControl(props) {
export function LogicalOperatorFilterExpressionControl ( props ) {
const classes = useStyles ( ) ;
const { expr } = props ;
const { expr , onClick , onChange } = props ;
var opstring = "" ;
if ( expr . operator === LogicalOperatorEnum . AND ) {
@ -135,24 +243,39 @@ export function LogicalOperatorFilterExpressionControl(props) {
opstring = " OR " ;
}
var _ = require ( 'lodash' ) ;
const handleAChanged = ( new _a ) => {
var new _me = _ . cloneDeep ( expr ) ;
new _me . sub _filter _a = new _a ;
onChange ( new _me ) ;
}
const handleBChanged = ( new _b ) => {
var new _me = _ . cloneDeep ( expr ) ;
new _me . sub _filter _b = new _b ;
onChange ( new _me ) ;
}
return (
< >
< Box className = { classes . logic _op _outer } >
< Box className = { classes . logic _op _sbs } >
< Box >
< Box className = { classes . logic _op _subexpr } >
< FilterExpressionControl expr = { expr . sub _filter _a } / >
< FilterExpressionControl expr = { expr . sub _filter _a } onChange = { handleAChanged } / >
< / B o x >
< / B o x >
< Box >
< Box className = { classes . logic _op _subexpr } >
< FilterExpressionControl expr = { expr . sub _filter _b } / >
< FilterExpressionControl expr = { expr . sub _filter _b } onChange = { handleBChanged } / >
< / B o x >
< / B o x >
< / B o x >
< Button
variant = "outlined"
className = { classes . filterexpcontrol + " " + classes . logic _op _sbs } >
className = { classes . filterexpcontrol + " " + classes . logic _op _sbs }
aria - controls = "simple-menu" aria - haspopup = "true"
onClick = { onClick }
>
{ opstring }
< / B u t t o n >
< / B o x >
@ -162,33 +285,84 @@ export function LogicalOperatorFilterExpressionControl(props) {
export function ConstFilterExpressionControl ( props ) {
const classes = useStyles ( ) ;
const { expr } = props ;
const { expr , onClick } = props ;
return (
< Button variant = "outlined" className = { classes . filterexpcontrol } >
< Button
variant = "outlined"
className = { classes . filterexpcontrol }
aria - controls = "simple-menu" aria - haspopup = "true"
onClick = { onClick }
>
{ JSON . stringify ( expr . constval ) }
< / B u t t o n >
) ;
}
export function FilterExpressionControl ( props ) {
const { expr } = props ;
const { expr , onChange } = props ;
const [ anchorEl , setAnchorEl ] = React . useState ( null ) ;
const [ editDialogOpen , setEditDialogOpen ] = React . useState ( false ) ;
var _ = require ( 'lodash' ) ;
const menu _id = _ . uniqueId ( "filter_menu_" ) ;
const handleClick = event => {
setAnchorEl ( event . currentTarget ) ;
} ;
const handleCloseMenu = ( ) => {
setAnchorEl ( null ) ;
} ;
const handleOpenEditDialog = ( filter ) => {
handleCloseMenu ( ) ;
setEditDialogOpen ( true ) ;
}
const handleCloseEditFilterDialog = ( filter ) => {
setEditDialogOpen ( false ) ;
onChange ( filter ) ;
} ;
var filter _elem = false ;
if ( expr instanceof ConstFilter ) {
return < ConstFilterExpressionControl { ... props } / >
filter _elem = < ConstFilterExpressionControl { ... props } onClick = { handleClick } / >
} else if ( expr instanceof LogicalOperatorFilter ) {
return < LogicalOperatorFilterExpressionControl { ... props } / >
filter _elem = < LogicalOperatorFilterExpressionControl { ... props } onClick = { handleClick } onChange = { onChange } / >
} else if ( expr instanceof MatchingFilter ) {
return < MatchingFilterExpressionControl { ... props } / >
filter _elem = < MatchingFilterExpressionControl { ... props } onClick = { handleClick } / >
} else {
throw new Error ( 'Unsupported filter expression' ) ;
}
throw new Error ( 'Unsupported filter expression' ) ;
return (
< >
{ filter _elem }
< Menu
id = { menu _id }
anchorEl = { anchorEl }
keepMounted
open = { Boolean ( anchorEl ) }
onClose = { handleCloseMenu }
>
< MenuItem onClick = { handleOpenEditDialog } > Edit < / M e n u I t e m >
< / M e n u >
< EditFilterExpressionDialog
onClose = { handleCloseEditFilterDialog }
startingFilter = { expr }
open = { editDialogOpen }
/ >
< / >
) ;
}
export function FilterControl ( props ) {
const classes = useStyles ( ) ;
const { filter , onChange , resultType , resultTypeString } = props ;
const enabled = ! filter _is _const _false ( filter ) ;
function handleResultToggled ( ) {
if ( enabled ) {
onChange ( new ConstFilter ( resultType , false ) ) ;
@ -198,7 +372,6 @@ export function FilterControl(props) {
}
}
const enabled = ! filter _is _const _false ( filter ) ;
return (
< >
< Box className = { classes . filtercontrol } >
@ -212,7 +385,7 @@ export function FilterControl(props) {
}
label = { resultTypeString + ':' }
/ >
< FilterExpressionControl expr = { filter } / >
< FilterExpressionControl expr = { filter } onChange = { onChange } / >
< / B o x >
< / >
) ;