Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Julien Jerphanion
Rex Dri
Commits
6cc84c53
Commit
6cc84c53
authored
Sep 03, 2018
by
Florent Chehab
Browse files
Search Countries ok
parent
9a0cded3
Changes
2
Hide whitespace changes
Inline
Side-by-side
frontend/src/components/search/DownshiftMultiple.js
0 → 100644
View file @
6cc84c53
// Inspired by : https://material-ui.com/demos/autocomplete/
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
deburr
from
'
lodash/deburr
'
;
import
keycode
from
'
keycode
'
;
import
Downshift
from
'
downshift
'
;
import
{
withStyles
}
from
'
@material-ui/core/styles
'
;
import
TextField
from
'
@material-ui/core/TextField
'
;
import
Paper
from
'
@material-ui/core/Paper
'
;
import
MenuItem
from
'
@material-ui/core/MenuItem
'
;
import
Chip
from
'
@material-ui/core/Chip
'
;
import
_
from
'
underscore
'
;
function
renderInput
(
inputProps
)
{
const
{
InputProps
,
classes
,
ref
,
...
other
}
=
inputProps
;
return
(
<
TextField
InputProps
=
{{
inputRef
:
ref
,
classes
:
{
root
:
classes
.
inputRoot
,
},
...
InputProps
,
}}
{...
other
}
/
>
);
}
function
renderSuggestion
({
suggestion
,
index
,
itemProps
,
highlightedIndex
,
selectedItem
})
{
const
isHighlighted
=
highlightedIndex
===
index
;
const
isSelected
=
(
selectedItem
||
''
).
indexOf
(
suggestion
)
>
-
1
;
return
(
<
MenuItem
{...
itemProps
}
key
=
{
suggestion
.
label
}
selected
=
{
isHighlighted
}
component
=
"
div
"
style
=
{{
fontWeight
:
isSelected
?
500
:
400
,
}}
>
{
suggestion
.
label
}
<
/MenuItem
>
);
}
renderSuggestion
.
propTypes
=
{
highlightedIndex
:
PropTypes
.
number
,
index
:
PropTypes
.
number
,
itemProps
:
PropTypes
.
object
,
selectedItem
:
PropTypes
.
string
,
suggestion
:
PropTypes
.
shape
({
label
:
PropTypes
.
string
,
id
:
PropTypes
.
number
}).
isRequired
,
};
class
DownshiftMultiple
extends
React
.
Component
{
state
=
{
inputValue
:
''
,
selectedItems
:
[],
};
componentDidUpdate
(
prevProps
,
prevState
,
snapshot
)
{
if
(
this
.
state
.
selectedItems
!=
prevState
.
selectedItems
)
{
this
.
props
.
onChange
(
this
.
state
.
selectedItems
);
}
}
getSuggestions
(
value
)
{
const
{
options
}
=
this
.
props
;
const
{
selectedItems
}
=
this
.
state
;
const
inputValue
=
deburr
(
value
.
trim
()).
toLowerCase
();
const
inputLength
=
inputValue
.
length
;
let
count
=
0
;
if
(
inputLength
===
0
)
{
return
[]
}
else
{
let
out
=
_
.
difference
(
options
,
selectedItems
).
filter
(
suggestion
=>
{
const
keep
=
count
<
5
&&
suggestion
.
label
.
slice
(
0
,
inputLength
).
toLowerCase
()
===
inputValue
;
if
(
keep
)
{
count
+=
1
;
}
return
keep
;
});
return
out
;
}
}
handleKeyDown
=
event
=>
{
const
{
inputValue
,
selectedItems
}
=
this
.
state
;
if
(
selectedItems
.
length
&&
!
inputValue
.
length
&&
keycode
(
event
)
===
'
backspace
'
)
{
this
.
setState
({
selectedItems
:
selectedItems
.
slice
(
0
,
selectedItems
.
length
-
1
),
});
}
};
handleInputChange
=
event
=>
{
this
.
setState
({
inputValue
:
event
.
target
.
value
});
};
handleChange
=
item
=>
{
const
{
options
}
=
this
.
props
;
let
{
selectedItems
}
=
this
.
state
;
if
(
selectedItems
.
indexOf
(
item
)
===
-
1
)
{
for
(
let
ind
in
options
)
{
let
el
=
options
[
ind
]
if
(
el
.
id
==
item
)
{
selectedItems
=
[...
selectedItems
,
el
];
break
;
}
}
}
this
.
setState
({
inputValue
:
''
,
selectedItems
,
});
};
handleDelete
=
item
=>
()
=>
{
this
.
setState
(
state
=>
{
const
selectedItems
=
[...
state
.
selectedItems
];
selectedItems
.
splice
(
selectedItems
.
indexOf
(
item
),
1
);
return
{
selectedItems
};
});
};
render
()
{
const
{
classes
,
field_label
,
field_placeholder
}
=
this
.
props
;
const
{
inputValue
,
selectedItems
}
=
this
.
state
;
return
(
<
div
className
=
{
classes
.
root
}
>
<
Downshift
id
=
"
downshift-multiple
"
inputValue
=
{
inputValue
}
onChange
=
{
this
.
handleChange
}
selectedItem
=
{
selectedItems
}
>
{({
getInputProps
,
getItemProps
,
isOpen
,
inputValue
:
inputValue2
,
selectedItem
:
selectedItem2
,
highlightedIndex
,
})
=>
(
<
div
className
=
{
classes
.
container
}
>
{
renderInput
({
fullWidth
:
true
,
classes
,
InputProps
:
getInputProps
({
startAdornment
:
selectedItems
.
map
(
item
=>
(
<
Chip
key
=
{
item
.
id
}
tabIndex
=
{
-
1
}
label
=
{
item
.
label
}
className
=
{
classes
.
chip
}
onDelete
=
{
this
.
handleDelete
(
item
.
id
)}
variant
=
"
outlined
"
color
=
"
primary
"
/>
)),
onChange
:
this
.
handleInputChange
,
onKeyDown
:
this
.
handleKeyDown
,
placeholder
:
field_placeholder
,
}),
label
:
field_label
,
})}
{
isOpen
?
(
<
Paper
className
=
{
classes
.
paper
}
square
>
{
this
.
getSuggestions
(
inputValue2
).
map
((
suggestion
,
index
)
=>
renderSuggestion
({
suggestion
,
index
,
itemProps
:
getItemProps
({
item
:
suggestion
.
id
}),
highlightedIndex
,
selectedItem
:
selectedItem2
,
}),
)}
<
/Paper
>
)
:
null
}
<
/div
>
)}
<
/Downshift
>
<
/div
>
);
}
}
DownshiftMultiple
.
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
};
DownshiftMultiple
.
defaultProps
=
{
options
:
[
{
label
:
'
Item 1
'
,
id
:
1
},
{
label
:
'
Item 2
'
,
id
:
2
},
{
label
:
'
Item 3
'
,
id
:
3
},
{
label
:
'
Item 4
'
,
id
:
4
},
],
field_label
:
"
label
"
,
field_placeholder
:
"
placeholder
"
};
const
styles
=
theme
=>
({
root
:
{
flexGrow
:
1
,
height
:
250
,
},
container
:
{
flexGrow
:
1
,
position
:
'
relative
'
,
},
paper
:
{
position
:
'
absolute
'
,
zIndex
:
1
,
marginTop
:
theme
.
spacing
.
unit
,
left
:
0
,
right
:
0
,
},
chip
:
{
margin
:
`
${
theme
.
spacing
.
unit
/
2
}
px
${
theme
.
spacing
.
unit
/
4
}
px`
,
},
inputRoot
:
{
flexWrap
:
'
wrap
'
,
}
});
export
default
withStyles
(
styles
)(
DownshiftMultiple
);
frontend/src/components/search/Search.js
View file @
6cc84c53
// Inspired by : https://material-ui.com/demos/autocomplete/
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
deburr
from
'
lodash/deburr
'
;
import
keycode
from
'
keycode
'
;
import
Downshift
from
'
downshift
'
;
import
{
withStyles
}
from
'
@material-ui/core/styles
'
;
import
TextField
from
'
@material-ui/core/TextField
'
;
import
Paper
from
'
@material-ui/core/Paper
'
;
import
MenuItem
from
'
@material-ui/core/MenuItem
'
;
import
Chip
from
'
@material-ui/core/Chip
'
;
import
_
from
'
underscore
'
function
renderInput
(
inputProps
)
{
const
{
InputProps
,
classes
,
ref
,
...
other
}
=
inputProps
;
return
(
<
TextField
InputProps
=
{{
inputRef
:
ref
,
classes
:
{
root
:
classes
.
inputRoot
,
},
...
InputProps
,
}}
{...
other
}
/
>
);
}
function
renderSuggestion
({
suggestion
,
index
,
itemProps
,
highlightedIndex
,
selectedItem
})
{
const
isHighlighted
=
highlightedIndex
===
index
;
const
isSelected
=
(
selectedItem
||
''
).
indexOf
(
suggestion
)
>
-
1
;
return
(
<
MenuItem
{...
itemProps
}
key
=
{
suggestion
.
label
}
selected
=
{
isHighlighted
}
component
=
"
div
"
style
=
{{
fontWeight
:
isSelected
?
500
:
400
,
}}
>
{
suggestion
.
label
}
<
/MenuItem
>
);
}
renderSuggestion
.
propTypes
=
{
highlightedIndex
:
PropTypes
.
number
,
index
:
PropTypes
.
number
,
itemProps
:
PropTypes
.
object
,
selectedItem
:
PropTypes
.
string
,
suggestion
:
PropTypes
.
shape
({
label
:
PropTypes
.
string
,
id
:
PropTypes
.
number
}).
isRequired
,
};
class
DownshiftMultiple
extends
React
.
Component
{
state
=
{
inputValue
:
''
,
selectedItems
:
[],
};
componentDidUpdate
(
prevProps
,
prevState
,
snapshot
)
{
if
(
this
.
state
.
selectedItems
!=
prevState
.
selectedItems
)
{
this
.
props
.
onChange
(
this
.
state
.
selectedItems
);
}
import
DownshiftMultiple
from
'
./DownshiftMultiple
'
;
import
MyComponent
from
'
../MyComponent
'
import
{
connect
}
from
"
react-redux
"
;
import
_
from
'
underscore
'
;
import
{
universitiesFetchData
,
mainCampusesFetchData
,
citiesFetchData
,
countriesFetchData
}
from
'
../../generated/actions
'
;
class
Search
extends
MyComponent
{
constructor
()
{
super
();
this
.
state
=
{
leaflet_instance
:
null
};
}
componentWillUnmount
()
{
getSuggestions
(
value
)
{
const
{
options
}
=
this
.
props
;
const
{
selectedItems
}
=
this
.
state
;
const
inputValue
=
deburr
(
value
.
trim
()).
toLowerCase
();
const
inputLength
=
inputValue
.
length
;
let
count
=
0
;
if
(
inputLength
===
0
)
{
return
[]
}
else
{
let
out
=
_
.
difference
(
options
,
selectedItems
).
filter
(
suggestion
=>
{
const
keep
=
count
<
5
&&
suggestion
.
label
.
slice
(
0
,
inputLength
).
toLowerCase
()
===
inputValue
;
if
(
keep
)
{
count
+=
1
;
}
return
keep
;
});
return
out
;
}
}
handleKeyDown
=
event
=>
{
const
{
inputValue
,
selectedItems
}
=
this
.
state
;
if
(
selectedItems
.
length
&&
!
inputValue
.
length
&&
keycode
(
event
)
===
'
backspace
'
)
{
this
.
setState
({
selectedItems
:
selectedItems
.
slice
(
0
,
selectedItems
.
length
-
1
),
});
}
};
handleInputChange
=
event
=>
{
this
.
setState
({
inputValue
:
event
.
target
.
value
});
};
handleChange
=
item
=>
{
const
{
options
}
=
this
.
props
;
let
{
selectedItems
}
=
this
.
state
;
if
(
selectedItems
.
indexOf
(
item
)
===
-
1
)
{
for
(
let
ind
in
options
)
{
let
el
=
options
[
ind
]
if
(
el
.
id
==
item
)
{
selectedItems
=
[...
selectedItems
,
el
];
break
;
}
getCountriesWhereThereAreUniversities
()
{
const
{
universities
,
mainCampuses
,
countries
,
cities
}
=
this
.
getAllFetchedData
();
let
res
=
[];
_
.
each
(
mainCampuses
,
(
campus
)
=>
{
let
univ
=
universities
[
campus
.
university
]
if
(
univ
&&
campus
)
{
let
city
=
cities
[
campus
.
city
]
let
country
=
countries
[
city
.
country
]
res
.
push
(
country
)
}
}
this
.
setState
({
inputValue
:
''
,
selectedItems
,
});
};
handleDelete
=
item
=>
()
=>
{
this
.
setState
(
state
=>
{
const
selectedItems
=
[...
state
.
selectedItems
];
selectedItems
.
splice
(
selectedItems
.
indexOf
(
item
),
1
);
return
{
selectedItems
};
});
};
return
_
.
uniq
(
res
,
false
,
_
.
iteratee
((
val
)
=>
{
return
val
.
iso_alpha2_code
}));
}
render
()
{
const
{
classes
}
=
this
.
props
;
const
{
inputValue
,
selectedItems
}
=
this
.
state
;
myRender
()
{
let
options
=
[];
this
.
getCountriesWhereThereAreUniversities
().
forEach
(
country
=>
{
options
.
push
({
id
:
country
.
iso_alpha2_code
,
label
:
country
.
name
});
})
return
(
<
Downshift
id
=
"
downshift-multiple
"
inputValue
=
{
inputValue
}
onChange
=
{
this
.
handleChange
}
selectedItem
=
{
selectedItems
}
>
{({
getInputProps
,
getItemProps
,
isOpen
,
inputValue
:
inputValue2
,
selectedItem
:
selectedItem2
,
highlightedIndex
,
})
=>
(
<
div
className
=
{
classes
.
container
}
>
{
renderInput
({
fullWidth
:
true
,
classes
,
InputProps
:
getInputProps
({
startAdornment
:
selectedItems
.
map
(
item
=>
(
<
Chip
key
=
{
item
.
id
}
tabIndex
=
{
-
1
}
label
=
{
item
.
label
}
className
=
{
classes
.
chip
}
onDelete
=
{
this
.
handleDelete
(
item
.
id
)}
variant
=
"
outlined
"
color
=
"
primary
"
/>
)),
onChange
:
this
.
handleInputChange
,
onKeyDown
:
this
.
handleKeyDown
,
placeholder
:
'
Select multiple countries
'
,
}),
label
:
'
Label
'
,
})}
{
isOpen
?
(
<
Paper
className
=
{
classes
.
paper
}
square
>
{
this
.
getSuggestions
(
inputValue2
).
map
((
suggestion
,
index
)
=>
renderSuggestion
({
suggestion
,
index
,
itemProps
:
getItemProps
({
item
:
suggestion
.
id
}),
highlightedIndex
,
selectedItem
:
selectedItem2
,
}),
)}
<
/Paper
>
)
:
null
}
<
/div
>
)}
<
/Downshift
>
<
DownshiftMultiple
options
=
{
options
}
onChange
=
{(
selection
)
=>
console
.
log
(
selection
)}
/
>
);
}
}
DownshiftMultiple
.
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
};
DownshiftMultiple
.
defaultProps
=
{
options
:
[
{
label
:
'
Afghanistan
'
,
id
:
1
},
{
label
:
'
Aland Islands
'
,
id
:
2
},
{
label
:
'
Albania
'
,
id
:
3
},
{
label
:
'
Algeria
'
,
id
:
4
},
],
};
const
styles
=
theme
=>
({
root
:
{
flexGrow
:
1
,
height
:
250
,
},
container
:
{
flexGrow
:
1
,
position
:
'
relative
'
,
},
paper
:
{
position
:
'
absolute
'
,
zIndex
:
1
,
marginTop
:
theme
.
spacing
.
unit
,
left
:
0
,
right
:
0
,
},
chip
:
{
margin
:
`
${
theme
.
spacing
.
unit
/
2
}
px
${
theme
.
spacing
.
unit
/
4
}
px`
,
},
inputRoot
:
{
flexWrap
:
'
wrap
'
,
},
divider
:
{
height
:
theme
.
spacing
.
unit
*
2
,
},
});
function
IntegrationDownshift
(
props
)
{
const
{
classes
}
=
props
;
return
(
<
div
className
=
{
classes
.
root
}
>
<
div
className
=
{
classes
.
divider
}
/
>
<
DownshiftMultiple
classes
=
{
classes
}
onChange
=
{(
selection
)
=>
console
.
log
(
selection
)}
/
>
<
div
className
=
{
classes
.
divider
}
/
>
<
/div
>
);
}
const
mapStateToProps
=
(
state
)
=>
{
return
{
universities
:
state
.
universities
,
mainCampuses
:
state
.
mainCampuses
,
cities
:
state
.
cities
,
countries
:
state
.
countries
};
};
IntegrationDownshift
.
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
const
mapDispatchToProps
=
(
dispatch
)
=>
{
return
{
fetchData
:
{
universities
:
()
=>
dispatch
(
universitiesFetchData
()),
mainCampuses
:
()
=>
dispatch
(
mainCampusesFetchData
()),
cities
:
()
=>
dispatch
(
citiesFetchData
()),
countries
:
()
=>
dispatch
(
countriesFetchData
())
}
};
};
export
default
withStyles
(
styles
)(
IntegrationDownshift
);
export
default
connect
(
mapStateToProps
,
mapDispatchToProps
)(
Search
);
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment