at the end of the day, it was inevitable
This commit is contained in:
+118
@@ -0,0 +1,118 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { DateRangePicker } from 'react-dates'
|
||||
import moment from 'moment'
|
||||
import { getMomentObject } from '../../../../../../common/helper'
|
||||
|
||||
export class BetweenDatepickers extends React.Component {
|
||||
state = {}
|
||||
|
||||
static propTypes = {
|
||||
chosenSearchInterval: PropTypes.string.isRequired,
|
||||
chosenStartDate: PropTypes.string.isRequired,
|
||||
chosenEndDate: PropTypes.string.isRequired,
|
||||
setSearchInterval: PropTypes.func.isRequired,
|
||||
setSearchDate: PropTypes.func.isRequired,
|
||||
setStartDate: PropTypes.func.isRequired,
|
||||
minDate: PropTypes.object,
|
||||
setEndDate: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
swapDate = (startDate, endDate) => {
|
||||
if (startDate.isAfter(endDate)) {
|
||||
const temp = startDate
|
||||
startDate = endDate
|
||||
endDate = temp
|
||||
}
|
||||
return { startDate, endDate }
|
||||
}
|
||||
/*
|
||||
setDates = (date, isStartDate) => {
|
||||
const {
|
||||
chosenStartDate,
|
||||
chosenEndDate,
|
||||
setStartDate,
|
||||
setEndDate,
|
||||
setSearchDate
|
||||
} = this.props
|
||||
|
||||
const hasStartDate = !!chosenStartDate
|
||||
const hasEndDate = !!chosenEndDate
|
||||
let startDate = hasStartDate ? moment(chosenStartDate) : moment()
|
||||
let endDate = hasEndDate ? moment(chosenEndDate) : moment()
|
||||
|
||||
startDate = isStartDate ? date : startDate
|
||||
endDate = !isStartDate ? date : endDate
|
||||
|
||||
const swappedDate = this.swapDate(startDate, endDate)
|
||||
startDate = swappedDate.startDate.format('YYYY-MM-DD')
|
||||
endDate = swappedDate.endDate.format('YYYY-MM-DD')
|
||||
|
||||
setStartDate(startDate.format('YYYY-MM-DD'))
|
||||
setEndDate(endDate.format('YYYY-MM-DD'))
|
||||
|
||||
const endDateLabel = hasEndDate ? endDate : 'now'
|
||||
const startDateLabel = hasStartDate ? startDate : 'until'
|
||||
let label = isStartDate
|
||||
? `${startDate} - ${endDateLabel}`
|
||||
: `${startDateLabel} - ${endDate}`
|
||||
setSearchDate(label)
|
||||
} */
|
||||
|
||||
setBetweenInterval = () => {
|
||||
const { chosenSearchInterval, setSearchInterval } = this.props
|
||||
if (chosenSearchInterval === 'between') return false
|
||||
|
||||
setSearchInterval('between')
|
||||
}
|
||||
|
||||
handleDateChange = ({ startDate, endDate }) => {
|
||||
const { setStartDate, setEndDate } = this.props
|
||||
|
||||
setStartDate(startDate ? startDate.format('YYYY-MM-DD') : null)
|
||||
setEndDate(endDate ? endDate.format('YYYY-MM-DD') : null)
|
||||
|
||||
if (startDate && endDate) {
|
||||
this.setBetweenInterval()
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChange = (focus) => {
|
||||
this.setState({ focusedInput: focus })
|
||||
}
|
||||
|
||||
isOutsideRange = (date) => {
|
||||
const today = moment()
|
||||
return date.isAfter(today) || date.isBefore(this.props.minDate)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { chosenStartDate, chosenEndDate } = this.props
|
||||
const today = moment()
|
||||
const startDate = getMomentObject(chosenStartDate)
|
||||
const endDate = getMomentObject(chosenEndDate)
|
||||
|
||||
return (
|
||||
<div className="ml-3">
|
||||
<DateRangePicker
|
||||
startDateId="startDate"
|
||||
endDateId="endDate"
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onDatesChange={this.handleDateChange}
|
||||
focusedInput={this.state.focusedInput}
|
||||
onFocusChange={this.onFocusChange}
|
||||
displayFormat="MM/DD/YYYY"
|
||||
startDatePlaceholderText="Start Date"
|
||||
endDatePlaceholderText="End Date"
|
||||
numberOfMonths={1}
|
||||
maxDate={today}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
isOutsideRange={this.isOutsideRange}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default BetweenDatepickers
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Col, CustomInput, FormGroup } from 'reactstrap';
|
||||
|
||||
export class DuplicatesTab extends React.Component {
|
||||
static propTypes = {
|
||||
includeDuplicates: PropTypes.bool.isRequired,
|
||||
toggleIncludeDuplicates: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Col sm={12}>
|
||||
<FormGroup>
|
||||
<CustomInput
|
||||
className="checkbox-input-hidden"
|
||||
type="checkbox"
|
||||
id="duplicates-check"
|
||||
checked={this.props.includeDuplicates}
|
||||
onChange={this.props.toggleIncludeDuplicates}
|
||||
label={t('searchTab.searchBySection.duplicates.includeDuplicates')}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(DuplicatesTab);
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Col, FormGroup, Input, Label } from 'reactstrap';
|
||||
|
||||
export class EmphasisTab extends React.Component {
|
||||
static propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
include: PropTypes.string.isRequired,
|
||||
exclude: PropTypes.string.isRequired,
|
||||
setHeadlineIncluded: PropTypes.func.isRequired,
|
||||
setHeadlineExcluded: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
setHeadInclude = (e) => {
|
||||
const headline = e.target.value;
|
||||
this.props.setHeadlineIncluded(headline);
|
||||
};
|
||||
|
||||
setHeadExclude = (e) => {
|
||||
const headline = e.target.value;
|
||||
this.props.setHeadlineExcluded(headline);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, include, exclude } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Col sm="6">
|
||||
<FormGroup>
|
||||
<Label>
|
||||
{t('searchTab.searchBySection.emphasis.headlineLabel')}{' '}
|
||||
{t('searchTab.searchBySection.emphasis.include')}
|
||||
</Label>
|
||||
<Input type="text" value={include} onChange={this.setHeadInclude} />
|
||||
</FormGroup>
|
||||
</Col>
|
||||
<Col sm="6">
|
||||
<FormGroup>
|
||||
<Label>
|
||||
{t('searchTab.searchBySection.emphasis.headlineLabel')}{' '}
|
||||
{t('searchTab.searchBySection.emphasis.exclude')}
|
||||
</Label>
|
||||
<Input type="text" value={exclude} onChange={this.setHeadExclude} />
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(EmphasisTab);
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Col, CustomInput, FormGroup } from 'reactstrap';
|
||||
|
||||
function ExtrasTab({ t, hasImages, toggleHasImages }) {
|
||||
return (
|
||||
<Col sm={12}>
|
||||
<FormGroup>
|
||||
<CustomInput
|
||||
id="has-images-check"
|
||||
type="checkbox"
|
||||
className="d-flex"
|
||||
checked={hasImages}
|
||||
label={t('searchTab.searchBySection.extras.hasImages')}
|
||||
onChange={toggleHasImages}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
|
||||
ExtrasTab.propTypes = {
|
||||
hasImages: PropTypes.bool.isRequired,
|
||||
toggleHasImages: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(ExtrasTab);
|
||||
@@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Col, CustomInput } from 'reactstrap';
|
||||
|
||||
export class LangsTab extends React.Component {
|
||||
static propTypes = {
|
||||
chosenLanguages: PropTypes.array.isRequired,
|
||||
searchLanguages: PropTypes.array.isRequired,
|
||||
toggleLang: PropTypes.func.isRequired,
|
||||
toggleAllLangs: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
toggleLangs = ({ target: { id, checked } }) => {
|
||||
this.props.toggleLang(id, checked);
|
||||
};
|
||||
|
||||
toggleAllLangs = (e) => {
|
||||
this.props.toggleAllLangs(e.target.checked);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
const { searchLanguages, chosenLanguages } = this.props;
|
||||
return (
|
||||
<Col sm={12} className="search-by-lang">
|
||||
<CustomInput
|
||||
id="article-check-all"
|
||||
type="checkbox"
|
||||
label={t('common:language.all')}
|
||||
checked={searchLanguages.length === chosenLanguages.length}
|
||||
onChange={this.toggleAllLangs}
|
||||
/>
|
||||
|
||||
{searchLanguages.map((lang) => (
|
||||
<CustomInput
|
||||
key={lang}
|
||||
id={lang}
|
||||
type="checkbox"
|
||||
checked={chosenLanguages.indexOf(lang) !== -1}
|
||||
label={t('common:language.' + lang)}
|
||||
onChange={this.toggleLangs}
|
||||
/>
|
||||
))}
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(LangsTab);
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { DragSource } from 'react-dnd'
|
||||
|
||||
const Types = {
|
||||
LOC: 'location'
|
||||
}
|
||||
|
||||
const locationSource = {
|
||||
beginDrag (props) {
|
||||
// Return the data describing the dragged item
|
||||
return { oldDropTargetType: props.dropTargetType }
|
||||
},
|
||||
|
||||
endDrag (props, monitor, component) {
|
||||
// When dropped on a compatible target, do something
|
||||
if (monitor.getDropResult() !== null) {
|
||||
const locFrom = props.dropTargetType
|
||||
const locTo = monitor.getDropResult().newDropTargetType
|
||||
|
||||
const locationType = props.locationType
|
||||
const location = props.location
|
||||
|
||||
props.moveLocation(locFrom, locTo, locationType, location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies which props to inject into your component.
|
||||
*/
|
||||
function collectDragSource (connect) {
|
||||
return {
|
||||
// Call this function inside render()
|
||||
// to let React DnD handle the drag events:
|
||||
connectDragSource: connect.dragSource()
|
||||
}
|
||||
}
|
||||
|
||||
export class LocationsTabList extends React.Component {
|
||||
static propTypes = {
|
||||
location: PropTypes.object.isRequired,
|
||||
dropTargetType: PropTypes.string.isRequired,
|
||||
moveLocation: PropTypes.func.isRequired,
|
||||
connectDragSource: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render () {
|
||||
const { connectDragSource } = this.props
|
||||
const { location } = this.props
|
||||
|
||||
return connectDragSource(
|
||||
<li className="list-group-item cursor-move p-2">
|
||||
<span className="drag-handle" />
|
||||
{location.name}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default DragSource(Types.LOC, locationSource, collectDragSource)(LocationsTabList)
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import LocationsTabList from './LocationsTabList';
|
||||
import { Button, Col, Row } from 'reactstrap';
|
||||
|
||||
export class LocationsTab extends React.Component {
|
||||
static propTypes = {
|
||||
locations: PropTypes.array.isRequired,
|
||||
locationsToInclude: PropTypes.array.isRequired,
|
||||
locationsToExclude: PropTypes.array.isRequired,
|
||||
chosenLocationsType: PropTypes.string.isRequired,
|
||||
changeLocationsType: PropTypes.func.isRequired,
|
||||
moveLocation: PropTypes.func.isRequired,
|
||||
clearLocations: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
dropdownOpen: false,
|
||||
dropDownValue: 'country'
|
||||
};
|
||||
}
|
||||
|
||||
onClearLocations = () => {
|
||||
this.props.clearLocations();
|
||||
this.props.changeLocationsType('country');
|
||||
this.setState({ dropDownValue: 'country' });
|
||||
};
|
||||
|
||||
selectLocation = (value) => {
|
||||
this.props.changeLocationsType(value);
|
||||
this.setState({ dropDownValue: value });
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
locations,
|
||||
chosenLocationsType,
|
||||
locationsToInclude,
|
||||
locationsToExclude
|
||||
} = this.props;
|
||||
const { t } = this.props;
|
||||
const locationsMainList = locations.filter((loc) => {
|
||||
return loc.type === chosenLocationsType;
|
||||
});
|
||||
const includeList = locationsToInclude.filter((loc) => {
|
||||
return loc.type === chosenLocationsType;
|
||||
});
|
||||
const excludeList = locationsToExclude.filter((loc) => {
|
||||
return loc.type === chosenLocationsType;
|
||||
});
|
||||
|
||||
const { dropDownValue } = this.state;
|
||||
return (
|
||||
<Col sm={12}>
|
||||
<Button
|
||||
outline
|
||||
active={dropDownValue === 'country'}
|
||||
color="secondary"
|
||||
className="mr-2 mb-3"
|
||||
onClick={() => this.selectLocation('country')}
|
||||
>
|
||||
{t('searchTab.searchBySection.locations.countriesSelect')}
|
||||
</Button>
|
||||
<Button
|
||||
outline
|
||||
active={dropDownValue === 'state'}
|
||||
color="secondary"
|
||||
className="mb-3"
|
||||
onClick={() => this.selectLocation('state')}
|
||||
>
|
||||
{t('searchTab.searchBySection.locations.statesSelect')}
|
||||
</Button>
|
||||
|
||||
<Row className="draggable">
|
||||
<Col md={4}>
|
||||
<LocationsTabList
|
||||
locations={locationsMainList}
|
||||
chosenLocationsType={chosenLocationsType}
|
||||
dropTargetType="locations"
|
||||
moveLocation={this.props.moveLocation}
|
||||
/>
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<LocationsTabList
|
||||
locations={includeList}
|
||||
chosenLocationsType={chosenLocationsType}
|
||||
dropTargetType="locationsToInclude"
|
||||
moveLocation={this.props.moveLocation}
|
||||
/>
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<LocationsTabList
|
||||
locations={excludeList}
|
||||
chosenLocationsType={chosenLocationsType}
|
||||
dropTargetType="locationsToExclude"
|
||||
moveLocation={this.props.moveLocation}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(LocationsTab);
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { DropTarget } from 'react-dnd';
|
||||
import flow from 'lodash/flow';
|
||||
import LocationItem from './LocationItem';
|
||||
import {
|
||||
ListGroup
|
||||
} from 'reactstrap';
|
||||
|
||||
const targetTypes = ['location'];
|
||||
const locationListTarget = {
|
||||
drop(props, monitor, component) {
|
||||
if (monitor.didDrop()) {
|
||||
//check whether some nested
|
||||
// target already handled drop
|
||||
return;
|
||||
}
|
||||
|
||||
return { newDropTargetType: props.dropTargetType };
|
||||
},
|
||||
|
||||
canDrop(props, monitor) {
|
||||
return props.dropTargetType !== monitor.getItem().oldDropTargetType;
|
||||
}
|
||||
};
|
||||
|
||||
function collectDropTarget(connect, monitor) {
|
||||
return {
|
||||
// Call this function inside render()
|
||||
// to let React DnD handle the drag events:
|
||||
connectDropTarget: connect.dropTarget(),
|
||||
// You can ask the monitor about the current drag state:
|
||||
itemType: monitor.getItemType()
|
||||
};
|
||||
}
|
||||
|
||||
export class LocationsTabList extends React.Component {
|
||||
static propTypes = {
|
||||
locations: PropTypes.array.isRequired,
|
||||
chosenLocationsType: PropTypes.string.isRequired,
|
||||
dropTargetType: PropTypes.string.isRequired,
|
||||
moveLocation: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired,
|
||||
connectDropTarget: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const { locations, chosenLocationsType, dropTargetType } = this.props;
|
||||
const { t } = this.props;
|
||||
const { connectDropTarget } = this.props;
|
||||
|
||||
locations.forEach((location) => {
|
||||
location.name = t('common:' + location.type + '.' + location.code);
|
||||
});
|
||||
|
||||
const sortedLocations = locations.sort((a, b) => {
|
||||
const nameA = a.name.toLowerCase();
|
||||
const nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) {
|
||||
//sort string ascending
|
||||
return -1;
|
||||
}
|
||||
if (nameA > nameB) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return connectDropTarget(
|
||||
<div className="scroll-area-md border b-radius-5">
|
||||
<p className="text-muted border-bottom p-2">{t('searchTab.searchBySection.locations.' + dropTargetType)}</p>
|
||||
<ListGroup className="p-2">
|
||||
{sortedLocations.map((location, i) => {
|
||||
return (
|
||||
<LocationItem
|
||||
key={'location-' + i}
|
||||
location={location}
|
||||
dropTargetType={dropTargetType}
|
||||
locationType={chosenLocationsType}
|
||||
moveLocation={this.props.moveLocation}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ListGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default flow(
|
||||
DropTarget(targetTypes, locationListTarget, collectDropTarget),
|
||||
translate(['tabsContent'], { wait: true })
|
||||
)(LocationsTabList);
|
||||
@@ -0,0 +1,163 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import SearchByTabs from './SearchByTabs';
|
||||
import EmphasisTab from './EmphasisTab';
|
||||
import LangsTab from './LangsTab';
|
||||
import LocationsTab from './LocationsTab';
|
||||
import SourcesTab from './SourcesTab';
|
||||
import SourceListsTab from './SourceListsTab';
|
||||
import DuplicatesTab from './DuplicatesTab';
|
||||
import ExtrasTab from './ExtrasTab';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Button, Container, Row } from 'reactstrap';
|
||||
|
||||
export class SearchBy extends React.Component {
|
||||
static propTypes = {
|
||||
userSubscriptionDate: PropTypes.string.isRequired,
|
||||
userSubscription: PropTypes.string.isRequired,
|
||||
searchByFiltersState: PropTypes.object.isRequired,
|
||||
actions: PropTypes.object.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
animationDisabled: true,
|
||||
arrowPosition: true
|
||||
};
|
||||
}
|
||||
|
||||
onToggleSearchBy = () => {
|
||||
this.props.actions.toggleSearchBy();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
const { searchByFiltersState, actions } = this.props;
|
||||
const visibleClass = searchByFiltersState.isSearchByVisible
|
||||
? ' visible'
|
||||
: ' closed';
|
||||
|
||||
return (
|
||||
<div
|
||||
className={'search-by-container mb-3 mb-md-0' + visibleClass}
|
||||
data-tour="advanced-search"
|
||||
>
|
||||
<div className="search-by">
|
||||
<SearchByTabs
|
||||
searchByTabs={searchByFiltersState.searchByTabs}
|
||||
chooseSearchByTab={actions.chooseSearchByTab}
|
||||
chosenSearchByTab={searchByFiltersState.chosenSearchByTab}
|
||||
/>
|
||||
|
||||
<Container fluid>
|
||||
<Row className="mb-3" data-tour="advanced-search-content">
|
||||
{searchByFiltersState.chosenSearchByTab === 'emphasis' && (
|
||||
<EmphasisTab
|
||||
include={searchByFiltersState.headlineIncluded}
|
||||
exclude={searchByFiltersState.headlineExcluded}
|
||||
setHeadlineIncluded={actions.setHeadlineIncluded}
|
||||
setHeadlineExcluded={actions.setHeadlineExcluded}
|
||||
/>
|
||||
)}
|
||||
|
||||
{searchByFiltersState.chosenSearchByTab === 'languages' && (
|
||||
<LangsTab
|
||||
searchLanguages={searchByFiltersState.searchLanguages}
|
||||
chosenLanguages={searchByFiltersState.chosenLanguages}
|
||||
toggleLang={actions.toggleLang}
|
||||
toggleAllLangs={actions.toggleAllLangs}
|
||||
/>
|
||||
)}
|
||||
|
||||
{searchByFiltersState.chosenSearchByTab === 'locations' && (
|
||||
<LocationsTab
|
||||
locations={searchByFiltersState.locations}
|
||||
chosenLocationsType={searchByFiltersState.chosenLocationsType}
|
||||
locationsToInclude={searchByFiltersState.locationsToInclude}
|
||||
locationsToExclude={searchByFiltersState.locationsToExclude}
|
||||
changeLocationsType={actions.changeLocationsType}
|
||||
moveLocation={actions.moveLocation}
|
||||
clearLocations={actions.clearLocations}
|
||||
/>
|
||||
)}
|
||||
|
||||
{searchByFiltersState.chosenSearchByTab === 'sources' && (
|
||||
<SourcesTab
|
||||
chosenMediaTypes={searchByFiltersState.chosenMediaTypes}
|
||||
chosenLanguages={searchByFiltersState.chosenLanguages}
|
||||
searchBySources={searchByFiltersState.searchBySources}
|
||||
searchBySourcesType={searchByFiltersState.searchBySourcesType}
|
||||
selectedSearchBySources={
|
||||
searchByFiltersState.selectedSearchBySources
|
||||
}
|
||||
searchBySourcesQuery={
|
||||
searchByFiltersState.searchBySourcesQuery
|
||||
}
|
||||
setSearchBySourcesQuery={actions.setSearchBySourcesQuery}
|
||||
getSearchBySources={actions.getSearchBySources}
|
||||
addSelectedSearchBySource={actions.addSelectedSearchBySource}
|
||||
removeSelectedSearchBySource={
|
||||
actions.removeSelectedSearchBySource
|
||||
}
|
||||
clearSearchBySources={actions.clearSearchBySources}
|
||||
includeExcludeSearchBySources={
|
||||
actions.includeExcludeSearchBySources
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{searchByFiltersState.chosenSearchByTab === 'sourceLists' && (
|
||||
<SourceListsTab
|
||||
searchBySourceLists={
|
||||
searchByFiltersState.searchBySourceListsAvailable
|
||||
}
|
||||
searchBySourceListsToInclude={
|
||||
searchByFiltersState.searchBySourceListsToInclude
|
||||
}
|
||||
searchBySourceListsToExclude={
|
||||
searchByFiltersState.searchBySourceListsToExclude
|
||||
}
|
||||
getSourceLists={actions.getSearchBySourceLists}
|
||||
moveSourceList={actions.moveSourceList}
|
||||
/>
|
||||
)}
|
||||
|
||||
{searchByFiltersState.chosenSearchByTab === 'duplicates' && (
|
||||
<DuplicatesTab
|
||||
includeDuplicates={searchByFiltersState.includeDuplicates}
|
||||
toggleIncludeDuplicates={actions.toggleIncludeDuplicates}
|
||||
/>
|
||||
)}
|
||||
|
||||
{searchByFiltersState.chosenSearchByTab === 'extras' && (
|
||||
<ExtrasTab
|
||||
hasImages={searchByFiltersState.hasImages}
|
||||
toggleHasImages={actions.toggleHasImages}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
</Container>
|
||||
</div>
|
||||
<hr className="mt-0 mb-2" />
|
||||
<Button
|
||||
outline
|
||||
size="sm"
|
||||
className="font-size-xs"
|
||||
color="secondary"
|
||||
onClick={this.onToggleSearchBy}
|
||||
>
|
||||
{t('searchTab.searchBySection.searchByBtn')}
|
||||
{searchByFiltersState.isSearchByVisible ? (
|
||||
<i className="lnr-chevron-up btn-icon-wrapper"></i>
|
||||
) : (
|
||||
<i className="lnr-chevron-down btn-icon-wrapper"></i>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(SearchBy);
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Nav, NavLink, NavItem } from 'reactstrap';
|
||||
import { translate } from 'react-i18next';
|
||||
|
||||
export class SearchByTabs extends React.Component {
|
||||
static propTypes = {
|
||||
searchByTabs: PropTypes.array.isRequired,
|
||||
chosenSearchByTab: PropTypes.string.isRequired,
|
||||
chooseSearchByTab: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
chooseSearchByTab = (newTab) => () => {
|
||||
this.props.chooseSearchByTab(newTab);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { searchByTabs } = this.props;
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Nav tabs className="font-size-xs">
|
||||
{searchByTabs.map((tab, i) => (
|
||||
<NavItem key={tab}>
|
||||
<NavLink
|
||||
className="d-block"
|
||||
active={tab === this.props.chosenSearchByTab}
|
||||
onClick={this.chooseSearchByTab(tab)}
|
||||
>
|
||||
{t('searchTab.searchBySection.' + tab + '.title')}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
))}
|
||||
</Nav>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(SearchByTabs);
|
||||
@@ -0,0 +1,25 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export class SourceIcon extends React.Component {
|
||||
static propTypes = {
|
||||
type: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
acceptedTypes = ['blogs', 'clippings', 'forums', 'mixed', 'news', 'prints', 'socials', 'user-added', 'user-comments', 'videos'];
|
||||
|
||||
render () {
|
||||
const { type } = this.props
|
||||
|
||||
if (!this.acceptedTypes.includes(type)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<img src={require('../../../../../../images/feed-type-' + type + '.png')} className="source-icon" />
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SourceIcon
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import SourceListsTabList from './SourceListsTabList';
|
||||
import { Col } from 'reactstrap';
|
||||
|
||||
export class SourceListsTab extends React.Component {
|
||||
static propTypes = {
|
||||
searchBySourceLists: PropTypes.array.isRequired,
|
||||
searchBySourceListsToInclude: PropTypes.array.isRequired,
|
||||
searchBySourceListsToExclude: PropTypes.array.isRequired,
|
||||
getSourceLists: PropTypes.func.isRequired,
|
||||
moveSourceList: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
componentWillMount = () => {
|
||||
this.props.getSourceLists({ page: 1, limit: 25 });
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
searchBySourceLists,
|
||||
searchBySourceListsToInclude,
|
||||
searchBySourceListsToExclude
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Col md={4}>
|
||||
<SourceListsTabList
|
||||
sourceLists={searchBySourceLists}
|
||||
dropTargetType="searchBySourceListsAvailable"
|
||||
moveSourceList={this.props.moveSourceList}
|
||||
/>
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<SourceListsTabList
|
||||
sourceLists={searchBySourceListsToInclude}
|
||||
dropTargetType="searchBySourceListsToInclude"
|
||||
moveSourceList={this.props.moveSourceList}
|
||||
/>
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<SourceListsTabList
|
||||
sourceLists={searchBySourceListsToExclude}
|
||||
dropTargetType="searchBySourceListsToExclude"
|
||||
moveSourceList={this.props.moveSourceList}
|
||||
/>
|
||||
</Col>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(SourceListsTab);
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { DragSource } from 'react-dnd';
|
||||
|
||||
const Types = {
|
||||
SOURCE_LIST: 'sourceList'
|
||||
};
|
||||
|
||||
const sourceListSource = {
|
||||
beginDrag(props) {
|
||||
// Return the data describing the dragged item
|
||||
return { oldDropTargetType: props.dropTargetType };
|
||||
},
|
||||
|
||||
endDrag(props, monitor, component) {
|
||||
// When dropped on a compatible target, do something
|
||||
if (monitor.getDropResult() !== null) {
|
||||
const from = props.dropTargetType;
|
||||
const to = monitor.getDropResult().newDropTargetType;
|
||||
|
||||
const sourceList = props.sourceList;
|
||||
|
||||
props.moveSourceList(from, to, sourceList);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies which props to inject into your component.
|
||||
*/
|
||||
function collectDragSource(connect) {
|
||||
return {
|
||||
// Call this function inside render()
|
||||
// to let React DnD handle the drag events:
|
||||
connectDragSource: connect.dragSource()
|
||||
};
|
||||
}
|
||||
|
||||
export class SourceListsTabItem extends React.Component {
|
||||
static propTypes = {
|
||||
sourceList: PropTypes.func.isRequired,
|
||||
dropTargetType: PropTypes.string.isRequired,
|
||||
moveSourceList: PropTypes.func.isRequired,
|
||||
connectDragSource: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const { connectDragSource } = this.props;
|
||||
const { sourceList } = this.props;
|
||||
|
||||
return connectDragSource(
|
||||
<li className="list-group-item cursor-move p-2">
|
||||
<span className="drag-handle" />
|
||||
{sourceList.name}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DragSource(
|
||||
Types.SOURCE_LIST,
|
||||
sourceListSource,
|
||||
collectDragSource
|
||||
)(SourceListsTabItem);
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { DropTarget } from 'react-dnd';
|
||||
import flow from 'lodash/flow';
|
||||
import SourceListsTabItem from './SourceListsTabItem';
|
||||
import { ListGroup } from 'reactstrap';
|
||||
|
||||
const targetTypes = ['sourceList'];
|
||||
const sourceListTarget = {
|
||||
drop(props, monitor, component) {
|
||||
if (monitor.didDrop()) {
|
||||
//check whether some nested
|
||||
// target already handled drop
|
||||
return;
|
||||
}
|
||||
|
||||
return { newDropTargetType: props.dropTargetType };
|
||||
},
|
||||
|
||||
canDrop(props, monitor) {
|
||||
return props.dropTargetType !== monitor.getItem().oldDropTargetType;
|
||||
}
|
||||
};
|
||||
|
||||
function collectDropTarget(connect, monitor) {
|
||||
return {
|
||||
// Call this function inside render()
|
||||
// to let React DnD handle the drag events:
|
||||
connectDropTarget: connect.dropTarget(),
|
||||
// You can ask the monitor about the current drag state:
|
||||
itemType: monitor.getItemType()
|
||||
};
|
||||
}
|
||||
|
||||
export class SourceListsTabList extends React.Component {
|
||||
static propTypes = {
|
||||
sourceLists: PropTypes.array.isRequired,
|
||||
dropTargetType: PropTypes.string.isRequired,
|
||||
moveSourceList: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired,
|
||||
connectDropTarget: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const { sourceLists, dropTargetType } = this.props;
|
||||
const { t } = this.props;
|
||||
const { connectDropTarget } = this.props;
|
||||
|
||||
return connectDropTarget(
|
||||
<div className="draggable scroll-area-md border b-radius-5">
|
||||
<p className="text-muted border-bottom p-2">
|
||||
{t('searchTab.searchBySection.sourceLists.' + dropTargetType)}
|
||||
</p>
|
||||
<ListGroup className="p-2">
|
||||
{sourceLists.map((sourceList, i) => {
|
||||
return (
|
||||
<SourceListsTabItem
|
||||
key={'sourceList-' + i}
|
||||
sourceList={sourceList}
|
||||
dropTargetType={dropTargetType}
|
||||
moveSourceList={this.props.moveSourceList}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ListGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default flow(
|
||||
DropTarget(targetTypes, sourceListTarget, collectDropTarget),
|
||||
translate(['tabsContent'], { wait: true })
|
||||
)(SourceListsTabList);
|
||||
@@ -0,0 +1,67 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import SourcesTabAvailSources from './SourcesTabAvailSources';
|
||||
import SourcesTabSelectedSources from './SourcesTabSelectedSources';
|
||||
import { Col } from 'reactstrap';
|
||||
|
||||
export class SourcesTab extends React.Component {
|
||||
static propTypes = {
|
||||
chosenMediaTypes: PropTypes.array.isRequired,
|
||||
chosenLanguages: PropTypes.array.isRequired,
|
||||
searchBySources: PropTypes.array.isRequired,
|
||||
selectedSearchBySources: PropTypes.array.isRequired,
|
||||
searchBySourcesType: PropTypes.string.isRequired,
|
||||
searchBySourcesQuery: PropTypes.string.isRequired,
|
||||
setSearchBySourcesQuery: PropTypes.func.isRequired,
|
||||
getSearchBySources: PropTypes.func.isRequired,
|
||||
addSelectedSearchBySource: PropTypes.func.isRequired,
|
||||
removeSelectedSearchBySource: PropTypes.func.isRequired,
|
||||
clearSearchBySources: PropTypes.func.isRequired,
|
||||
includeExcludeSearchBySources: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
searchBySourcesQuery,
|
||||
setSearchBySourcesQuery,
|
||||
chosenMediaTypes,
|
||||
chosenLanguages,
|
||||
searchBySources,
|
||||
getSearchBySources,
|
||||
addSelectedSearchBySource,
|
||||
searchBySourcesType,
|
||||
clearSearchBySources,
|
||||
selectedSearchBySources,
|
||||
removeSelectedSearchBySource,
|
||||
includeExcludeSearchBySources
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Col sm={8}>
|
||||
<SourcesTabAvailSources
|
||||
searchBySourcesQuery={searchBySourcesQuery}
|
||||
selectedSources={selectedSearchBySources}
|
||||
setSearchBySourcesQuery={setSearchBySourcesQuery}
|
||||
chosenMediaTypes={chosenMediaTypes}
|
||||
chosenLanguages={chosenLanguages}
|
||||
availSources={searchBySources}
|
||||
getSearchBySources={getSearchBySources}
|
||||
addSelectedSearchBySource={addSelectedSearchBySource}
|
||||
/>
|
||||
</Col>
|
||||
<Col sm={4}>
|
||||
<SourcesTabSelectedSources
|
||||
searchBySourcesType={searchBySourcesType}
|
||||
clearSearchBySources={clearSearchBySources}
|
||||
selectedSources={selectedSearchBySources}
|
||||
removeSelectedSearchBySource={removeSelectedSearchBySource}
|
||||
includeExcludeSearchBySources={includeExcludeSearchBySources}
|
||||
/>
|
||||
</Col>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SourcesTab;
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
// import SourceIcon from './SourceIcon';
|
||||
import { Button, Input, InputGroup, InputGroupAddon, Table } from 'reactstrap';
|
||||
import { capitalize } from 'lodash';
|
||||
import { getTitle } from '../../../../../../common/helper';
|
||||
import cx from 'classnames';
|
||||
import { domainNames } from '../SearchSubTab';
|
||||
|
||||
export class SourcesTabAvailSources extends React.Component {
|
||||
static propTypes = {
|
||||
chosenMediaTypes: PropTypes.array.isRequired,
|
||||
chosenLanguages: PropTypes.array.isRequired,
|
||||
availSources: PropTypes.array.isRequired,
|
||||
selectedSources: PropTypes.array.isRequired,
|
||||
searchBySourcesQuery: PropTypes.string.isRequired,
|
||||
setSearchBySourcesQuery: PropTypes.func.isRequired,
|
||||
getSearchBySources: PropTypes.func.isRequired,
|
||||
addSelectedSearchBySource: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
componentDidMount = () => {
|
||||
this.searchSources();
|
||||
};
|
||||
|
||||
searchSources = () => {
|
||||
const {
|
||||
chosenLanguages,
|
||||
chosenMediaTypes,
|
||||
getSearchBySources,
|
||||
searchBySourcesQuery
|
||||
} = this.props;
|
||||
const query = searchBySourcesQuery;
|
||||
const dataToSend = {};
|
||||
dataToSend.page = 1;
|
||||
dataToSend.limit = 100;
|
||||
dataToSend.query = query;
|
||||
dataToSend.filters = {};
|
||||
|
||||
const source = []
|
||||
const domain = []
|
||||
chosenMediaTypes.map((v) => {
|
||||
if (domainNames.includes(v)) {
|
||||
domain.push(`${v}.com`);
|
||||
} else {
|
||||
source.push(v);
|
||||
}
|
||||
})
|
||||
dataToSend.filters.publisher = { source, domain };
|
||||
|
||||
dataToSend.filters.language = chosenLanguages;
|
||||
getSearchBySources(dataToSend);
|
||||
};
|
||||
|
||||
chooseSource = (e) => {
|
||||
const dataset = e.currentTarget.dataset;
|
||||
const sourceTitle = dataset.sourceTitle;
|
||||
const sourceType = dataset.sourceType;
|
||||
const sourceId = dataset.sourceId;
|
||||
this.props.addSelectedSearchBySource({
|
||||
title: sourceTitle,
|
||||
type: sourceType,
|
||||
id: sourceId
|
||||
});
|
||||
};
|
||||
|
||||
onChangeSearchInput = (e) => {
|
||||
const val = e.target.value;
|
||||
this.props.setSearchBySourcesQuery(val);
|
||||
};
|
||||
|
||||
onEnterSearchInput = (e) => {
|
||||
if (e.keyCode === 13) this.searchSources();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { availSources, selectedSources } = this.props;
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<InputGroup className="mb-3">
|
||||
<Input
|
||||
type="text"
|
||||
id="search-by-sources-input"
|
||||
value={this.props.searchBySourcesQuery}
|
||||
onChange={this.onChangeSearchInput}
|
||||
onKeyUp={this.onEnterSearchInput}
|
||||
/>
|
||||
<InputGroupAddon addonType="append">
|
||||
<Button
|
||||
color="primary"
|
||||
className="btn-icon btn-icon-only"
|
||||
onClick={this.searchSources}
|
||||
>
|
||||
<i className="lnr-magnifier btn-icon-wrapper"></i>
|
||||
</Button>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
|
||||
<p className="text-muted">
|
||||
{t('searchTab.searchBySection.sources.availSources')}
|
||||
</p>
|
||||
<div className="source-table-wrap border">
|
||||
<Table striped bordered className="mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t('searchTab.searchBySection.sources.source')}</th>
|
||||
<th>{t('searchTab.searchBySection.sources.siteType')}</th>
|
||||
<th>{t('searchTab.searchBySection.sources.mediatype')}</th>
|
||||
<th>{t('searchTab.searchBySection.sources.lang')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{availSources.length > 0 ? (
|
||||
availSources.map((source, i) => {
|
||||
return (
|
||||
<tr
|
||||
title="Click to select"
|
||||
className={cx('clickable', {
|
||||
active:
|
||||
selectedSources &&
|
||||
selectedSources.find((v) => v.id === source.id)
|
||||
})}
|
||||
data-source-title={source.title}
|
||||
data-source-type={source.type}
|
||||
data-source-id={source.id}
|
||||
onClick={this.chooseSource}
|
||||
key={i}
|
||||
>
|
||||
{/* <td>
|
||||
<SourceIcon type={source.type} />
|
||||
</td> */}
|
||||
<td>{getTitle(source.title)}</td>
|
||||
<td title={source.url}>
|
||||
{capitalize(source.siteType) || '-'}
|
||||
</td>
|
||||
<td>{capitalize(source.type) || '-'}</td>
|
||||
<td>{t(`common:language.${source.lang}`)}</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<tr className="p-4 text-center text-black-50">
|
||||
<td colSpan="4">{t('common:messages.noRows')}</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(
|
||||
SourcesTabAvailSources
|
||||
);
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Button, CustomInput, Table } from 'reactstrap';
|
||||
import { IoIosCloseCircleOutline } from 'react-icons/io';
|
||||
import { capitalize } from 'lodash';
|
||||
import { getTitle } from '../../../../../../common/helper';
|
||||
|
||||
export class SourcesTabSelectedSources extends React.Component {
|
||||
static propTypes = {
|
||||
searchBySourcesType: PropTypes.string.isRequired,
|
||||
selectedSources: PropTypes.array.isRequired,
|
||||
removeSelectedSearchBySource: PropTypes.func.isRequired,
|
||||
clearSearchBySources: PropTypes.func.isRequired,
|
||||
includeExcludeSearchBySources: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
removeSource = (sourceId) => {
|
||||
this.props.removeSelectedSearchBySource(sourceId);
|
||||
};
|
||||
|
||||
includeExclide = (type) => {
|
||||
this.props.includeExcludeSearchBySources(type);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { selectedSources } = this.props;
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="d-flex flex-wrap my-3">
|
||||
<CustomInput
|
||||
type="radio"
|
||||
name="include-exclude-source"
|
||||
className="d-flex mr-2"
|
||||
checked={this.props.searchBySourcesType === 'include'}
|
||||
id="include-sources-radio"
|
||||
onChange={() => this.includeExclide('include')}
|
||||
label={t('searchTab.searchBySection.sources.includeText')}
|
||||
/>
|
||||
|
||||
<CustomInput
|
||||
type="radio"
|
||||
name="include-exclude-source"
|
||||
checked={this.props.searchBySourcesType === 'exclude'}
|
||||
className="d-flex mr-2"
|
||||
id="exclude-sources-radio"
|
||||
onChange={() => this.includeExclide('exclude')}
|
||||
label={t('searchTab.searchBySection.sources.excludeText')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="text-muted">
|
||||
{t('searchTab.searchBySection.sources.selectedSources')}
|
||||
</p>
|
||||
|
||||
<div className="source-table-wrap border">
|
||||
<Table striped className="mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t('searchTab.searchBySection.sources.source')}</th>
|
||||
<th>{t('searchTab.searchBySection.sources.mediatype')}</th>
|
||||
<th style={{ width: '50px' }}></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{selectedSources.length > 0 ? (
|
||||
selectedSources.map((source, i) => {
|
||||
return (
|
||||
<tr key={i}>
|
||||
{/* <td>
|
||||
<SourceIcon type={source.type} />
|
||||
</td> */}
|
||||
<td>{getTitle(source.title)}</td>
|
||||
<td>{capitalize(source.type) || '-'}</td>
|
||||
<td>
|
||||
<button
|
||||
title="Remove"
|
||||
type="button"
|
||||
className="btn p-0"
|
||||
onClick={() => this.removeSource(source.id)}
|
||||
>
|
||||
<IoIosCloseCircleOutline
|
||||
size={22}
|
||||
className="text-danger ml-2"
|
||||
/>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<tr className="p-4 text-center text-black-50">
|
||||
<td colSpan="3">
|
||||
{t('common:messages.noRows')} <br />
|
||||
{t('searchTab.searchBySection.sources.selectSource')}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
{selectedSources.length > 0 && (
|
||||
<Button
|
||||
size="sm"
|
||||
className="d-block ml-auto mt-2 mb-2"
|
||||
onClick={this.props.clearSearchBySources}
|
||||
>
|
||||
{t('searchTab.clearBtn')}
|
||||
</Button>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(['tabsContent'], { wait: true })(
|
||||
SourcesTabSelectedSources
|
||||
);
|
||||
Reference in New Issue
Block a user