Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
ef4575c5
Commit
ef4575c5
authored
Dec 17, 2020
by
Lyza Danger Gardner
Committed by
Lyza Gardner
Dec 18, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add FilterSelect component
parent
02d71ce4
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
183 additions
and
0 deletions
+183
-0
filter-select.js
src/sidebar/components/filter-select.js
+69
-0
filter-select-test.js
src/sidebar/components/test/filter-select-test.js
+92
-0
filter-select.scss
src/styles/sidebar/components/filter-select.scss
+21
-0
sidebar.scss
src/styles/sidebar/sidebar.scss
+1
-0
No files found.
src/sidebar/components/filter-select.js
0 → 100644
View file @
ef4575c5
import
{
createElement
}
from
'preact'
;
import
propTypes
from
'prop-types'
;
import
Menu
from
'./menu'
;
import
MenuItem
from
'./menu-item'
;
import
SvgIcon
from
'../../shared/components/svg-icon'
;
/**
* @typedef {import('../store/modules/filters').FilterOption} FilterOption
*/
/**
* @typedef FilterSelectProps
* @prop {FilterOption} defaultOption
* @prop {string} [icon]
* @prop {(selectedFilter: FilterOption) => any} onSelect
* @prop {FilterOption[]} options
* @prop {FilterOption} [selectedOption]
* @prop {string} title
*/
/**
* A select-element-like control for selecting one of a defined set of
* options.
*
* @param {FilterSelectProps} props
*/
function
FilterSelect
({
defaultOption
,
icon
,
onSelect
,
options
,
selectedOption
,
title
,
})
{
const
filterOptions
=
[
defaultOption
,
...
options
];
const
selected
=
selectedOption
??
defaultOption
;
const
menuLabel
=
(
<
span
className
=
"filter-select__menu-label"
>
{
icon
&&
<
SvgIcon
name
=
{
icon
}
className
=
"filter-select__menu-icon"
/>
}
{
selected
.
display
}
<
/span
>
);
return
(
<
Menu
label
=
{
menuLabel
}
title
=
{
title
}
>
{
filterOptions
.
map
(
filterOption
=>
(
<
MenuItem
onClick
=
{()
=>
onSelect
(
filterOption
)}
key
=
{
filterOption
.
value
}
isSelected
=
{
filterOption
.
value
===
selected
.
value
}
label
=
{
filterOption
.
display
}
/
>
))}
<
/Menu
>
);
}
FilterSelect
.
propTypes
=
{
defaultOption
:
propTypes
.
object
,
icon
:
propTypes
.
string
,
onSelect
:
propTypes
.
func
,
options
:
propTypes
.
array
,
selectedOption
:
propTypes
.
object
,
title
:
propTypes
.
string
,
};
export
default
FilterSelect
;
src/sidebar/components/test/filter-select-test.js
0 → 100644
View file @
ef4575c5
import
{
mount
}
from
'enzyme'
;
import
{
createElement
}
from
'preact'
;
import
FilterSelect
from
'../filter-select'
;
import
{
$imports
}
from
'../filter-select'
;
import
mockImportedComponents
from
'../../../test-util/mock-imported-components'
;
describe
(
'FilterSelect'
,
()
=>
{
let
someOptions
;
const
createComponent
=
props
=>
{
return
mount
(
<
FilterSelect
defaultOption
=
{{
value
:
''
,
display
:
'all'
}}
onSelect
=
{()
=>
null
}
options
=
{
someOptions
}
title
=
"Select one"
{...
props
}
/
>
);
};
beforeEach
(()
=>
{
someOptions
=
[
{
value
:
'onevalue'
,
display
:
'One Value'
},
{
value
:
'twovalue'
,
display
:
'Two Value'
},
];
$imports
.
$mock
(
mockImportedComponents
());
});
afterEach
(()
=>
{
$imports
.
$restore
();
});
it
(
'should render option display values'
,
()
=>
{
const
wrapper
=
createComponent
();
const
selectItems
=
wrapper
.
find
(
'MenuItem'
);
assert
.
equal
(
selectItems
.
length
,
3
);
// First, the default option
assert
.
deepEqual
(
selectItems
.
at
(
0
).
props
().
label
,
'all'
);
// Then the other options
assert
.
deepEqual
(
selectItems
.
at
(
1
).
props
().
label
,
'One Value'
);
assert
.
deepEqual
(
selectItems
.
at
(
2
).
props
().
label
,
'Two Value'
);
});
it
(
'should invoke `onSelect` callback when an option is selected'
,
()
=>
{
const
fakeOnSelect
=
sinon
.
stub
();
const
wrapper
=
createComponent
({
onSelect
:
fakeOnSelect
});
const
secondOption
=
wrapper
.
find
(
'MenuItem'
).
at
(
1
);
secondOption
.
props
().
onClick
();
assert
.
calledOnce
(
fakeOnSelect
);
assert
.
calledWith
(
fakeOnSelect
,
sinon
.
match
({
value
:
'onevalue'
,
display
:
'One Value'
})
);
});
it
(
'should render provided icon and selected option in label'
,
()
=>
{
const
wrapper
=
createComponent
({
icon
:
'profile'
});
const
label
=
mount
(
wrapper
.
find
(
'Menu'
).
props
().
label
);
const
icon
=
label
.
find
(
'SvgIcon'
);
assert
.
isTrue
(
icon
.
exists
());
assert
.
equal
(
icon
.
props
().
name
,
'profile'
);
// Default option should be selected as we didn't indicate a selected option
assert
.
equal
(
label
.
text
(),
'all'
);
});
it
(
'should render provided title'
,
()
=>
{
const
wrapper
=
createComponent
({
title
:
'Select something'
});
assert
.
equal
(
wrapper
.
find
(
'Menu'
).
props
().
title
,
'Select something'
);
});
it
(
'should denote the selected option as selected'
,
()
=>
{
const
wrapper
=
createComponent
({
selectedOption
:
{
value
:
'twovalue'
,
display
:
'Two Value'
},
});
const
label
=
mount
(
wrapper
.
find
(
'Menu'
).
props
().
label
);
assert
.
equal
(
label
.
text
(),
'Two Value'
);
assert
.
isFalse
(
wrapper
.
find
(
'MenuItem'
).
at
(
1
).
props
().
isSelected
);
assert
.
isTrue
(
wrapper
.
find
(
'MenuItem'
).
at
(
2
).
props
().
isSelected
);
});
});
src/styles/sidebar/components/filter-select.scss
0 → 100644
View file @
ef4575c5
@use
"../../mixins/utils"
;
@use
"../../variables"
as
var
;
.filter-select
{
&
__menu-label
{
@include
utils
.
font--large
;
align-items
:
center
;
color
:
var
.
$color-text
;
display
:
flex
;
// Prevent label from wrapping if top bar is too narrow to fit all of its
// items.
flex-shrink
:
0
;
font-weight
:
bold
;
}
&
__menu-icon
{
@include
utils
.
icon--medium
;
margin-right
:
var
.
$layout-space--xsmall
;
}
}
src/styles/sidebar/sidebar.scss
View file @
ef4575c5
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
@use
'./components/autocomplete-list'
;
@use
'./components/autocomplete-list'
;
@use
'./components/button'
;
@use
'./components/button'
;
@use
'./components/excerpt'
;
@use
'./components/excerpt'
;
@use
'./components/filter-select'
;
@use
'./components/filter-status'
;
@use
'./components/filter-status'
;
@use
'./components/group-list'
;
@use
'./components/group-list'
;
@use
'./components/group-list-item'
;
@use
'./components/group-list-item'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a 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