Commit 3f3bdf7e authored by PDuarte's avatar PDuarte

refactory locations part 2

parent c29fe800
......@@ -3,3 +3,4 @@ REACT_APP_BASENAME=/cms
REACT_APP_API="http://192.168.99.100:8001/cms"
REACT_APP_API1="http://134.209.18.22/cmsapi"
REACT_APP_IMAGERY="http://192.168.99.100:8001/imagery"
REACT_APP_IMAGERY1="http://134.209.18.22/imagery"
......@@ -23,14 +23,14 @@ export default [
title: 'Page types',
icon: <HardDrive />,
navLink: '/settings/pagetypes'
},
{
id: 'locationsDash',
title: 'locations',
icon: <Globe />,
navLink: '/settings/locations'
}
// {
// id: 'locationsDash',
// title: 'locations',
// icon: <Globe />,
// navLink: '/settings/locations'
// },
// {
// id: 'contriesDash',
// title: 'Contries',
// icon: <Flag />,
......
......@@ -42,6 +42,11 @@ const SettingsRoutes = [
component: lazy(() => import('../../views/settings/locations')),
exact: true
},
{
path: '/settings/locations/add',
component: lazy(() => import('../../views/settings/locations/add')),
exact: true
},
{
path: '/settings/contries',
component: lazy(() => import('../../views/settings/contries')),
......
// ** React Imports
import { useState, Fragment } from 'react'
// ** Table Columns
import { data, advSearchColumns } from '../data'
// ** Third Party Components
import Flatpickr from 'react-flatpickr'
import ReactPaginate from 'react-paginate'
import { ChevronDown } from 'react-feather'
import DataTable from 'react-data-table-component'
import { Card, CardHeader, CardBody, CardTitle, Input, Label, FormGroup, Row, Col } from 'reactstrap'
// ** Styles
import '@styles/react/libs/flatpickr/flatpickr.scss'
const DataTableAdvSearch = () => {
// ** States
const [Picker, setPicker] = useState('')
const [searchName, setSearchName] = useState('')
const [searchPost, setSearchPost] = useState('')
const [searchCity, setSearchCity] = useState('')
const [currentPage, setCurrentPage] = useState(0)
const [searchEmail, setSearchEmail] = useState('')
const [searchSalary, setSearchSalary] = useState('')
const [filteredData, setFilteredData] = useState([])
// ** Function to handle Pagination
const handlePagination = page => setCurrentPage(page.selected)
// ** Table data to render
const dataToRender = () => {
if (
searchName.length ||
searchPost.length ||
searchEmail.length ||
searchCity.length ||
searchSalary.length ||
Picker.length
) {
return filteredData
} else {
return data
}
}
// ** Custom Pagination
const CustomPagination = () => (
<ReactPaginate
previousLabel={''}
nextLabel={''}
forcePage={currentPage}
onPageChange={page => handlePagination(page)}
pageCount={dataToRender().length / 7 || 1}
breakLabel={'...'}
pageRangeDisplayed={2}
marginPagesDisplayed={2}
activeClassName={'active'}
pageClassName={'page-item'}
nextLinkClassName={'page-link'}
nextClassName={'page-item next'}
previousClassName={'page-item prev'}
previousLinkClassName={'page-link'}
pageLinkClassName={'page-link'}
breakClassName='page-item'
breakLinkClassName='page-link'
containerClassName={'pagination react-paginate separated-pagination pagination-sm justify-content-end pr-1 mt-1'}
/>
)
// ** Function to handle name filter
const handleNameFilter = e => {
const value = e.target.value
let updatedData = []
const dataToFilter = () => {
if (searchEmail.length || searchPost.length || searchCity.length || searchSalary.length || Picker.length) {
return filteredData
} else {
return data
}
}
setSearchName(value)
if (value.length) {
updatedData = dataToFilter().filter(item => {
const startsWith = item.full_name.toLowerCase().startsWith(value.toLowerCase())
const includes = item.full_name.toLowerCase().includes(value.toLowerCase())
if (startsWith) {
return startsWith
} else if (!startsWith && includes) {
return includes
} else return null
})
setFilteredData([...updatedData])
setSearchName(value)
}
}
// ** Function to handle email filter
const handleEmailFilter = e => {
const value = e.target.value
let updatedData = []
const dataToFilter = () => {
if (searchName.length || searchPost.length || searchCity.length || searchSalary.length || Picker.length) {
return filteredData
} else {
return data
}
}
setSearchEmail(value)
if (value.length) {
updatedData = dataToFilter().filter(item => {
const startsWith = item.email.toLowerCase().startsWith(value.toLowerCase())
const includes = item.email.toLowerCase().includes(value.toLowerCase())
if (startsWith) {
return startsWith
} else if (!startsWith && includes) {
return includes
} else return null
})
setFilteredData([...updatedData])
setSearchEmail(value)
}
}
// ** Function to handle post filter
const handlePostFilter = e => {
const value = e.target.value
let updatedData = []
const dataToFilter = () => {
if (searchEmail.length || searchName.length || searchCity.length || searchSalary.length || Picker.length) {
return filteredData
} else {
return data
}
}
setSearchPost(value)
if (value.length) {
updatedData = dataToFilter().filter(item => {
const startsWith = item.post.toLowerCase().startsWith(value.toLowerCase())
const includes = item.post.toLowerCase().includes(value.toLowerCase())
if (startsWith) {
return startsWith
} else if (!startsWith && includes) {
return includes
} else return null
})
setFilteredData([...updatedData])
setSearchPost(value)
}
}
// ** Function to handle city filter
const handleCityFilter = e => {
const value = e.target.value
let updatedData = []
const dataToFilter = () => {
if (searchEmail.length || searchName.length || searchPost.length || searchSalary.length || Picker.length) {
return filteredData
} else {
return data
}
}
setSearchCity(value)
if (value.length) {
updatedData = dataToFilter().filter(item => {
const startsWith = item.city.toLowerCase().startsWith(value.toLowerCase())
const includes = item.city.toLowerCase().includes(value.toLowerCase())
if (startsWith) {
return startsWith
} else if (!startsWith && includes) {
return includes
} else return null
})
setFilteredData([...updatedData])
setSearchCity(value)
}
}
// ** Function to handle salary filter
const handleSalaryFilter = e => {
const value = e.target.value
let updatedData = []
const dataToFilter = () => {
if (searchEmail.length || searchName.length || searchPost.length || searchCity.length || Picker.length) {
return filteredData
} else {
return data
}
}
setSearchSalary(value)
if (value.length) {
updatedData = dataToFilter().filter(item => {
const startsWith = item.salary.toLowerCase().startsWith(value.toLowerCase())
const includes = item.salary.toLowerCase().includes(value.toLowerCase())
if (startsWith) {
return startsWith
} else if (!startsWith && includes) {
return includes
} else return null
})
setFilteredData([...updatedData])
setSearchSalary(value)
}
}
// ** Function to handle date filter
const handleDateFilter = range => {
const arr = []
let updatedData = []
const dataToFilter = () => {
if (searchEmail.length || searchName.length || searchPost.length || searchCity.length || searchSalary.length) {
return filteredData
} else {
return data
}
}
range.map(i => {
const date = new Date(i)
const year = date.getFullYear()
let month = (1 + date.getMonth()).toString()
month = month.length > 1 ? month : `0${month}`
let day = date.getDate().toString()
day = day.length > 1 ? day : `0${day}`
arr.push(`${month}/${day}/${year}`)
return true
})
setPicker(range)
if (range.length) {
updatedData = dataToFilter().filter(item => {
return (
new Date(item.start_date).getTime() >= new Date(arr[0]).getTime() &&
new Date(item.start_date).getTime() <= new Date(arr[1]).getTime()
)
})
setFilteredData([...updatedData])
setPicker(range)
}
}
return (
<Fragment>
<Card>
<CardHeader className='border-bottom'>
<CardTitle tag='h4'>Advance Search</CardTitle>
</CardHeader>
<CardBody>
<Row form className='mt-1 mb-50'>
<Col lg='4' md='6'>
<FormGroup>
<Label for='name'>Name:</Label>
<Input id='name' placeholder='Bruce Wayne' value={searchName} onChange={handleNameFilter} />
</FormGroup>
</Col>
<Col lg='4' md='6'>
<FormGroup>
<Label for='email'>Email:</Label>
<Input
type='email'
id='email'
placeholder='Bwayne@email.com'
value={searchEmail}
onChange={handleEmailFilter}
/>
</FormGroup>
</Col>
<Col lg='4' md='6'>
<FormGroup>
<Label for='post'>Post:</Label>
<Input id='post' placeholder='Web Designer' value={searchPost} onChange={handlePostFilter} />
</FormGroup>
</Col>
<Col lg='4' md='6'>
<FormGroup>
<Label for='city'>City:</Label>
<Input id='city' placeholder='San Diego' value={searchCity} onChange={handleCityFilter} />
</FormGroup>
</Col>
<Col lg='4' md='6'>
<FormGroup>
<Label for='date'>Date:</Label>
<Flatpickr
className='form-control'
id='date'
value={Picker}
options={{ mode: 'range', dateFormat: 'm/d/Y' }}
onChange={date => handleDateFilter(date)}
/>
</FormGroup>
</Col>
<Col lg='4' md='6'>
<FormGroup>
<Label for='salary'>Salary:</Label>
<Input id='salary' placeholder='10000' value={searchSalary} onChange={handleSalaryFilter} />
</FormGroup>
</Col>
</Row>
</CardBody>
<DataTable
noHeader
pagination
columns={advSearchColumns}
paginationPerPage={7}
className='react-dataTable'
sortIcon={<ChevronDown size={10} />}
paginationDefaultPage={currentPage + 1}
paginationComponent={CustomPagination}
data={dataToRender()}
/>
</Card>
</Fragment>
)
}
export default DataTableAdvSearch
// ** React Imports
import { Fragment, useState, useEffect, memo } from 'react'
// ** Table Columns
import { serverSideColumns } from '../data'
// ** Store & Actions
import { getData } from '../store/actions'
import { useSelector, useDispatch } from 'react-redux'
// ** Third Party Components
import ReactPaginate from 'react-paginate'
import { ChevronDown } from 'react-feather'
import DataTable from 'react-data-table-component'
import { Card, CardHeader, CardTitle, Input, Label, Row, Col } from 'reactstrap'
const DataTableServerSide = () => {
// ** Store Vars
const dispatch = useDispatch()
const store = useSelector(state => state.dataTables)
// ** States
const [currentPage, setCurrentPage] = useState(1)
const [rowsPerPage, setRowsPerPage] = useState(7)
const [searchValue, setSearchValue] = useState('')
// ** Get data on mount
useEffect(() => {
dispatch(
getData({
page: currentPage,
perPage: rowsPerPage,
q: searchValue
})
)
}, [dispatch])
// ** Function to handle filter
const handleFilter = e => {
setSearchValue(e.target.value)
dispatch(
getData({
page: currentPage,
perPage: rowsPerPage,
q: e.target.value
})
)
}
// ** Function to handle Pagination and get data
const handlePagination = page => {
dispatch(
getData({
page: page.selected + 1,
perPage: rowsPerPage,
q: searchValue
})
)
setCurrentPage(page.selected + 1)
}
// ** Function to handle per page
const handlePerPage = e => {
dispatch(
getData({
page: currentPage,
perPage: parseInt(e.target.value),
q: searchValue
})
)
setRowsPerPage(parseInt(e.target.value))
}
// ** Custom Pagination
const CustomPagination = () => {
const count = Number((store.total / rowsPerPage).toFixed(0))
return (
<ReactPaginate
previousLabel={''}
nextLabel={''}
breakLabel='...'
pageCount={count || 1}
marginPagesDisplayed={2}
pageRangeDisplayed={2}
activeClassName='active'
forcePage={currentPage !== 0 ? currentPage - 1 : 0}
onPageChange={page => handlePagination(page)}
pageClassName={'page-item'}
nextLinkClassName={'page-link'}
nextClassName={'page-item next'}
previousClassName={'page-item prev'}
previousLinkClassName={'page-link'}
pageLinkClassName={'page-link'}
breakClassName='page-item'
breakLinkClassName='page-link'
containerClassName={
'pagination react-paginate separated-pagination pagination-sm justify-content-end pr-1 mt-1'
}
/>
)
}
// ** Table data to render
const dataToRender = () => {
const filters = {
q: searchValue
}
const isFiltered = Object.keys(filters).some(function (k) {
return filters[k].length > 0
})
if (store.data.length > 0) {
return store.data
} else if (store.data.length === 0 && isFiltered) {
return []
} else {
return store.allData.slice(0, rowsPerPage)
}
}
return (
<Fragment>
<Card>
<CardHeader className='border-bottom'>
<CardTitle tag='h4'>Server Side</CardTitle>
</CardHeader>
<Row className='mx-0 mt-1 mb-50'>
<Col sm='6'>
<div className='d-flex align-items-center'>
<Label for='sort-select'>show</Label>
<Input
className='dataTable-select'
type='select'
id='sort-select'
value={rowsPerPage}
onChange={e => handlePerPage(e)}
>
<option value={7}>7</option>
<option value={10}>10</option>
<option value={25}>25</option>
<option value={50}>50</option>
<option value={75}>75</option>
<option value={100}>100</option>
</Input>
<Label for='sort-select'>entries</Label>
</div>
</Col>
<Col className='d-flex align-items-center justify-content-sm-end mt-sm-0 mt-1' sm='6'>
<Label className='mr-1' for='search-input'>
Search
</Label>
<Input
className='dataTable-filter'
type='text'
bsSize='sm'
id='search-input'
value={searchValue}
onChange={handleFilter}
/>
</Col>
</Row>
<DataTable
noHeader
pagination
paginationServer
className='react-dataTable'
columns={serverSideColumns}
sortIcon={<ChevronDown size={10} />}
paginationComponent={CustomPagination}
data={dataToRender()}
/>
</Card>
</Fragment>
)
}
export default memo(DataTableServerSide)
// ** React Imports
import { Fragment } from 'react'
import { Link } from 'react-router-dom'
// ** Store & Actions
import { addlocation } from '../../store/actions'
import { useDispatch, useSelector } from 'react-redux'
// ** Custom Components
import Breadcrumbs from '@components/breadcrumbs'
// ** Third Party Components
import { Row, Col } from 'reactstrap'
// module settings
import moduleSettings from '../module'
// ** Tables
import ElementCard from '../card'
// ** Styles
import '@styles/react/libs/tables/react-dataTable-component.scss'
const Tables = () => {
const dispatch = useDispatch()
const storeNavbar = useSelector(state => state.navbar)
const onSubmitHandler = (values, uploadFile) => {
dispatch(
addlocation({
projectid: values.projectid,
title: values.title,
parentid: values.parentid,
parenttype: values.parenttype,
external_id: values.external_id,
textual: values.textual,
availability: values.availability,
genres: values.genres,
subgenres: values.subgenres,
data: uploadFile
}
)
)
}
return (
<Fragment>
<Breadcrumbs breadCrumbTitle='Assets' breadCrumbParent='Assets' breadCrumbActive={moduleSettings.mainTitle} />
<Row>
<Col sm='12'>
<Link to={moduleSettings.baseURL}>Back to {moduleSettings.mainTitle}</Link>
</Col>
</Row>
<Row>
<Col sm='12'>
<div className="card">
<div className="card-header">
<h4 className="card-title">New {moduleSettings.mainTitleSingle}</h4>
</div>
<div className="card-body">
{storeNavbar.projectCurrent === null ? <div>
Select Project
</div> : <ElementCard selectedElement={{
id: '<generate>',
projectid: storeNavbar.projectCurrent.value,
title: '',
parentid: null,
parenttype: null,
external_id: '',
textual: [],
genres: [],
subgenres: [],
availability: [],
imagery: []
}}
onSubmitHandler={onSubmitHandler}
/>
}
</div>
</div>
</Col>
</Row>
</Fragment>
)
}
export default Tables
import { useState } from 'react'
import { Card, CardHeader, CardTitle, CardBody } from 'reactstrap'
import {
Circle,
CircleMarker,
MapContainer,
Marker,
Polygon,
Popup,
Rectangle,
TileLayer,
Tooltip
} from 'react-leaflet'
import { EditControl } from "react-leaflet-draw"
const center = [51.505, -0.09]
const multiPolygon = [
[
[51.51, -0.12],
[51.51, -0.13],
[51.53, -0.13]
],
[
[51.51, -0.05],
[51.51, -0.07],
[51.53, -0.07]
]
]
const rectangle = [
[51.49, -0.08],
[51.5, -0.06]
]
const MapTooltip = () => {
const [clicked, setClicked] = useState(0)
const onClickCircle = () => {
setClicked(clicked + 1)
}
const clickedText = clicked === 0 ? 'Click this Circle to change the Tooltip text' : `Circle click: ${clicked}`
return (
<Card>
<CardHeader>
<CardTitle tag='h4'>Map</CardTitle>
</CardHeader>
<CardBody>
<MapContainer center={center} zoom={13} className='leaflet-map'>
<TileLayer
attribution='&ampcopy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
/>
<Circle center={center} fillColor='blue' onClick={onClickCircle} radius={200}>
<Tooltip>{clickedText}</Tooltip>
</Circle>
<CircleMarker center={[51.51, -0.12]} color='red' radius={20}>
<Tooltip>Tooltip for CircleMarker</Tooltip>
</CircleMarker>
<Marker position={[51.51, -0.09]}>
<Popup>Popup for Marker</Popup>
<Tooltip>Tooltip for Marker</Tooltip>
</Marker>
<Polygon color='purple' positions={multiPolygon}>
<Tooltip sticky>sticky Tooltip for Polygon</Tooltip>
</Polygon>
<Rectangle bounds={rectangle} color='black'>
<Tooltip direction='bottom' offset={[0, 20]} opacity={1} permanent>
permanent Tooltip for Rectangle
</Tooltip>
</Rectangle>
</MapContainer>
</CardBody>
</Card>
)
}
export default MapTooltip
// ** React Imports
import { useState, useEffect, Fragment } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { toast } from 'react-toastify'
import Avatar from '@components/avatar'
import Select, { components } from 'react-select'
import {Media, Button, Label, Form, FormGroup, Input, Table, CustomInput, Card, CardBody, Row, Col, Nav, NavItem, NavLink, TabContent, TabPane, Alert, CardHeader, CardTitle, CardText } from 'reactstrap'
import { isObjEmpty, selectThemeColors } from '@utils'
import { Bell, Check, Hash, X, AlertTriangle, Info } from 'react-feather'
// ** Store & Actions
import {resetResults} from '../../store/actions'
import { getData_pagetypes } from '../../../settings/store/actions'
import { getData_layoutPlaylists } from '../../../screens/store/actions'
import { useForm } from 'react-hook-form'
import classnames from 'classnames'
import Swal from 'sweetalert2'
import withReactContent from 'sweetalert2-react-content'
import MapTooltip from './MapTooltip'
// ** Styles
import '@styles/react/apps/app-users.scss'
import '@styles/react/libs/flatpickr/flatpickr.scss'
import '@styles/react/libs/maps/map-leaflet.scss'
const SuccessProgressToast = () => (
<Fragment>
<div className='toastify-header'>
<div className='title-wrapper'>
<Avatar size='sm' color='success' icon={<Check size={12} />} />
<h6 className='toast-title'>Saved !</h6>
</div>
<small className='text-muted'></small>
</div>
<div className='toastify-body'>
<span role='img' aria-label='toast-text'>
👋 Good job.
</span>
</div>
</Fragment>
)
const ElementCard = ({ selectedElement, onSubmitHandler }) => {
const store = useSelector(state => state.projectsettings)
const [PlatformName, setPlatformName] = useState('Web')
const MySwal = withReactContent(Swal)
const handleError = (text) => {
return MySwal.fire({
title: 'Error!',
text,
icon: 'error',
customClass: {
confirmButton: 'btn btn-primary'
},
buttonsStyling: false
})
}
const [dataElement, setElementData] = useState(null),
[genresAllOptions, setGenresAllOptions] = useState([]),
[genresAsset, setGenresAsset] = useState([]),
[genresSubAsset, setGenresSubAsset] = useState([]),
{ register, errors, handleSubmit } = useForm(),
settingStore = useSelector(state => state.projectsettings),
screensStore = useSelector(state => state.screens),
[pagetypes, setPagetypes] = useState(null),
[layoutplaylists, setLayoutplaylists] = useState(null),
[activeTab, setActiveTab] = useState(0),
[uploadFiles, setUploadFile] = useState([]),
//
toggle = tab => setActiveTab(tab),
dispatch = useDispatch(),
notifySuccessProgress = () => toast.success(<SuccessProgressToast />),
onSubmit = values => {
if (isObjEmpty(errors)) {
const submitElement = {
...dataElement,
idproject: values.idproject,
title: values.title,
parentid: values.parentid,
parenttype: values.parenttype,
external_id: values.external_id
}
onSubmitHandler(submitElement, uploadFiles)
}
},
handleTextualChange = value => {
const newData = {
...dataElement,
textual: value
}
setElementData(newData)
},
handleAvalChange = value => {
// console.log(value)
const newData = {
...dataElement,
availability: value
}
setElementData(newData)
},
updateGenres = (value) => {
const newValue = value.map(elm => {
return {
id: elm.value,
idproject: dataElement.projectid,
name: elm.label,
pivot: {
idasset: dataElement.id,
idgenres:elm.value1
}
}
})
const newData = {
...dataElement,
genres: newValue
}
setElementData(newData)
},
updateSubGenres = (value) => {
const newValue = value.map(elm => {
return {
id: elm.value,
idproject: dataElement.projectid,
name: elm.label,
pivot: {
idasset: dataElement.id,
idgenres:elm.value1
}
}
})
const newData = {
...dataElement,
subgenres: newValue
}
setElementData(newData)
},
genreOnChange = (value, { action, removedValue }) => {
switch (action) {
case 'remove-value':
case 'pop-value':
if (removedValue.isFixed) {
return
}
setGenresAsset(value)
break
case 'clear':
value = genresAllOptions.filter(v => v.isFixed)
setGenresAsset(value)
break
default:
setGenresAsset(value)
break
}
updateGenres(value)
},
genreSubOnChange = (value, { action, removedValue }) => {
switch (action) {
case 'remove-value':
case 'pop-value':
if (removedValue.isFixed) {
return
}
setGenresSubAsset(value)
break
case 'clear':
value = genresAllOptions.filter(v => v.isFixed)
setGenresSubAsset(value)
break
default:
setGenresSubAsset(value)
break
}
updateSubGenres(value)
},
handleImageryChange = (prop, file, lang) => {
let newUpload = uploadFiles.filter(elm => elm.type !== prop || elm.langcode.langcode !== lang.langcode)
newUpload = newUpload.concat({
type: prop,
langcode: lang,
obj: file
})
setUploadFile(newUpload)
}
useEffect(() => {
if (selectedElement !== null || (selectedElement !== null && dataElement !== null && selectedElement.id !== dataElement.id)) {
const genres = selectedElement.genres.map(elm => {
return {
value: elm.id,
label: elm.name
}
})
setGenresAsset(genres)
const subgenres = selectedElement.subgenres.map(elm => {
return {
value: elm.id,
label: elm.name
}
})
setGenresSubAsset(subgenres)
return setElementData(selectedElement)
}
}, [selectedElement])
useEffect(() => {
if (store.errorMsg !== '') {
handleError(store.errorMsg)
dispatch(resetResults())
}
}, [store.errorMsg])
useEffect(() => {
if (store.saveSucces) {
notifySuccessProgress()
dispatch(resetResults())
}
}, [store.saveSucces])
// populate page types
useEffect(() => {
if (!settingStore.allDataPagetypes || settingStore.allDataPagetypes.length < 1) {
dispatch(getData_pagetypes({
start: 1,
length: 1000,
q: null
}))
}
}, [dispatch])
useEffect(() => {
setPagetypes(settingStore.allDataPagetypes)
}, [settingStore.allDataPagetypes])
useEffect(() => {
if (!settingStore.selectedProject) return
console.log(settingStore.selectedProject)
const genres = settingStore.selectedProject.genres.map(elm => {
return {
value: elm.id,
label: elm.name
}
})
setGenresAllOptions(genres)
}, [settingStore.selectedProject])
// populate layout menus
useEffect(() => {
if (!screensStore.allDataLayoutPlaylists || screensStore.allDataLayoutPlaylists.length < 1) {
dispatch(getData_layoutPlaylists({
start: 1,
length: 1000,
q: null
}))
}
}, [dispatch])
useEffect(() => {
setLayoutplaylists(screensStore.allDataLayoutPlaylists)
}, [screensStore.allDataLayoutPlaylists])
return (
<Fragment>
<Form
onSubmit={handleSubmit(onSubmit)}
>
<Row>
<Col md='4' sm='12'>
<FormGroup>
<Label for='id'>ID</Label>
<Input
readOnly={true}
type='text'
name='id'
id='id'
placeholder='id'
defaultValue={dataElement && dataElement.id}
/>
</FormGroup>
</Col>
<Col md='4' sm='12'>
<FormGroup>
<Label for='name'>Project ID</Label>
<Input
readOnly={true}
type='text'
name='projectid'
id='projectid'
innerRef={register({ required: true })}
placeholder='projectid'
defaultValue={dataElement && dataElement.projectid}
className={classnames({ 'is-invalid': errors['projectid'] })}
/>
</FormGroup>
</Col>
<Col md='4' sm='12'>
<FormGroup>
<Label for='name'>Name</Label>
<Input
type='text'
name='name'
id='name'
innerRef={register({ required: true })}
placeholder='name'
defaultValue={dataElement && dataElement.name}
className={classnames({ 'is-invalid': errors['name'] })}
/>
</FormGroup>
</Col>
<Col md='4' sm='12'>
<FormGroup>
<Label for='order'>Order</Label>
<Input
type='text'
name='order'
id='order'
innerRef={register({ required: false })}
placeholder='order'
defaultValue={dataElement && dataElement.order}
className={classnames({ 'is-invalid': errors['order'] })}
/>
</FormGroup>
</Col>
<Col md='4' sm='12'>
<FormGroup>
<Label for='country'>Country</Label>
<Input
type='text'
name='country'
id='country'
innerRef={register({ required: false })}
placeholder='country'
defaultValue={dataElement && dataElement.country}
className={classnames({ 'is-invalid': errors['country'] })}
/>
</FormGroup>
</Col>
<Col md='4' sm='12'>
<FormGroup>
<Label for='state'>State</Label>
<Input
type='text'
name='state'
id='state'
innerRef={register({ required: true })}
placeholder='state'
defaultValue={dataElement && dataElement.state}
className={classnames({ 'is-invalid': errors['state'] })}
/>
</FormGroup>
</Col>
<Col md='4' sm='12'>
<FormGroup>
<Label for='city'>City</Label>
<Input
type='text'
name='city'
id='city'
innerRef={register({ required: true })}
placeholder='city'
defaultValue={dataElement && dataElement.city}
className={classnames({ 'is-invalid': errors['city'] })}
/>
</FormGroup>
</Col>
<Col md='4' sm='12'>
<FormGroup>
<Label for='ip'>IP</Label>
<Input
type='text'
name='ip'
id='ip'
innerRef={register({ required: true })}
placeholder='ip'
defaultValue={dataElement && dataElement.ip}
className={classnames({ 'is-invalid': errors['ip'] })}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col sm='12'>
<MapTooltip />
</Col>
</Row>
<Row className='app-user-edit'>
<Col className='d-flex flex-sm-row flex-column mt-2' sm='12'>
<Button.Ripple className='mb-1 mb-sm-0 mr-0 mr-sm-1' type='submit' color='primary'>
Save Changes
</Button.Ripple>
{/* <Button.Ripple color='secondary' outline onClick={() => dispatch(getPlatform(selectedElement.id))} >
Reset
</Button.Ripple> */}
</Col>
</Row>
</Form>
</Fragment>
)
}
export default ElementCard
\ No newline at end of file
// ** React Imports
import { Link } from 'react-router-dom'
// ** Store & Actions
import { getProject, cleanProject } from '../store/actions'
import { store } from '@store/storeConfig/store'
// ** Custom Components
import Avatar from '@components/avatar'
// ** Third Party Components
import axios from 'axios'
import { MoreVertical, Edit, FileText, Archive, Trash } from 'react-feather'
import { Badge, UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'
import moduleSettings from './module'
// ** Vars
const states = ['success', 'danger', 'warning', 'info', 'dark', 'primary', 'secondary']
const status = {
1: { title: 'Current', color: 'light-primary' },
2: { title: 'Professional', color: 'light-success' },
3: { title: 'Rejected', color: 'light-danger' },
4: { title: 'Resigned', color: 'light-warning' },
5: { title: 'Applied', color: 'light-info' }
}
export let data
// ** Get initial Data
axios.get('/api/datatables/initial-data').then(response => {
data = response.data
})
// ** Table Zero Config Column
export const basicColumns = [
{
name: 'ID',
selector: 'id',
sortable: true,
maxWidth: '100px'
},
{
name: 'Name',
selector: 'full_name',
sortable: true,
minWidth: '225px'
},
{
name: 'Email',
selector: 'email',
sortable: true,
minWidth: '310px'
},
{
name: 'Position',
selector: 'post',
sortable: true,
minWidth: '250px'
},
{
name: 'Age',
selector: 'age',
sortable: true,
minWidth: '100px'
},
{
name: 'Salary',
selector: 'salary',
sortable: true,
minWidth: '175px'
}
]
// ** Expandable table component
const ExpandableTable = ({ data }) => {
return (
<div className='expandable-content p-2'>
<p>
<span className='font-weight-bold'>City:</span> {data.city}
</p>
<p>
<span className='font-weight-bold'>Experience:</span> {data.experience}
</p>
<p className='m-0'>
<span className='font-weight-bold'>Post:</span> {data.post}
</p>
</div>
)
}
// ** Table Common Column
export const columns = [
{
name: 'Name',
selector: 'full_name',
sortable: true,
minWidth: '250px',
cell: row => (
<div className='d-flex align-items-center'>
{row.avatar === '' ? (
<Avatar color={`light-${states[row.status]}`} content={row.full_name} initials />
) : (
<Avatar img={require(`@src/assets/images/portrait/small/avatar-s-${row.avatar}`).default} />
)}
<div className='user-info text-truncate ml-1'>
<span className='d-block font-weight-bold text-truncate'>{row.full_name}</span>
<small>{row.post}</small>
</div>
</div>
)
},
{
name: 'Email',
selector: 'email',
sortable: true,
minWidth: '250px'
},
{
name: 'Date',
selector: 'start_date',
sortable: true,
minWidth: '150px'
},
{
name: 'Salary',
selector: 'salary',
sortable: true,
minWidth: '150px'
},
{
name: 'Age',
selector: 'age',
sortable: true,
minWidth: '100px'
},
{
name: 'Status',
selector: 'status',
sortable: true,
minWidth: '150px',
cell: row => {
return (
<Badge color={status[row.status].color} pill>
{status[row.status].title}
</Badge>
)
}
},
{
name: 'Actions',
allowOverflow: true,
cell: row => {
return (
<div className='d-flex'>
<UncontrolledDropdown>
<DropdownToggle className='pr-1' tag='span'>
<MoreVertical size={15} />
</DropdownToggle>
<DropdownMenu right>
<DropdownItem tag='a' href='/' className='w-100' onClick={e => e.preventDefault()}>
<FileText size={15} />
<span className='align-middle ml-50'>Details</span>
</DropdownItem>
<DropdownItem tag='a' href='/' className='w-100' onClick={e => e.preventDefault()}>
<Archive size={15} />
<span className='align-middle ml-50'>Archive</span>
</DropdownItem>
<DropdownItem tag='a' href='/' className='w-100' onClick={e => e.preventDefault()}>
<Trash size={15} />
<span className='align-middle ml-50'>Delete</span>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
<Edit size={15} />
</div>
)
}
}
]
// ** Table Intl Column
export const multiLingColumns = [
{
name: 'Name',
selector: 'full_name',
sortable: true,
minWidth: '200px'
},
{
name: 'Position',
selector: 'post',
sortable: true,
minWidth: '250px'
},
{
name: 'Status',
selector: 'status',
sortable: true,
minWidth: '150px',
cell: row => {
return (
<Badge color={status[row.status].color} pill>
{status[row.status].title}
</Badge>
)
}
},
{
name: 'Actions',
allowOverflow: true,
cell: row => {
return (
<div className='d-flex'>
<UncontrolledDropdown>
<DropdownToggle className='pr-1' tag='span'>
<MoreVertical size={15} />
</DropdownToggle>
<DropdownMenu right>
<DropdownItem>
<FileText size={15} />
<span className='align-middle ml-50'>Details</span>
</DropdownItem>
<DropdownItem>
<Archive size={15} />
<span className='align-middle ml-50'>Archive</span>
</DropdownItem>
<DropdownItem>
<Trash size={15} />
<span className='align-middle ml-50'>Delete</span>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
<Edit size={15} />
</div>
)
}
}
]
// ** Table Server Side Column
export const serverSideColumns = [
{
name: 'Location ID',
selector: 'id',
sortable: true,
minWidth: '225px'
},
{
name: 'Location Name',
selector: 'name',
sortable: true,
minWidth: '225px',
cell: row => (
<div className='d-flex justify-content-left align-items-center'>
<div className='d-flex flex-column'>
<Link
to={`${moduleSettings.baseURL}/edit/${row.id}`}
className='user-name text-truncate mb-0'
onClick={() => store.dispatch(cleanProject(row.id))}
>
<span className='font-weight-bold'>{row.name}</span>
</Link>
<small className='text-truncate text-muted mb-0'>@{row.name}</small>
</div>
</div>
)
},
{
name: 'Order',
selector: 'order',
sortable: true,
minWidth: '225px'
}
]
// ** Table Adv Search Column
export const advSearchColumns = [
{
name: 'Name',
selector: 'full_name',
sortable: true,
minWidth: '200px'
},
{
name: 'Email',
selector: 'email',
sortable: true,
minWidth: '250px'
},
{
name: 'Post',
selector: 'post',
sortable: true,
minWidth: '250px'
},
{
name: 'City',
selector: 'city',
sortable: true,
minWidth: '150px'
},
{
name: 'Date',
selector: 'start_date',
sortable: true,
minWidth: '150px'
},
{
name: 'Salary',
selector: 'salary',
sortable: true,
minWidth: '100px'
}
]
export default ExpandableTable
// ** React Imports
import { Fragment } from 'react'
import { Link } from 'react-router-dom'
// ** Custom Components
import Breadcrumbs from '@components/breadcrumbs'
// ** Third Party Components
import { Row, Col } from 'reactstrap'
// ** Tables
import ElementEdit from './main'
// ** Styles
import '@styles/react/libs/tables/react-dataTable-component.scss'
// module settings
import moduleSettings from '../module'
const Tables = () => {
return (
<Fragment>
<Breadcrumbs breadCrumbTitle='Assets' breadCrumbParent='Assets' breadCrumbActive={moduleSettings.mainTitle} />
<Row>
<Col sm='12'>
<Link to={moduleSettings.baseURL}>Back to {moduleSettings.mainTitleSingle}</Link>
</Col>
</Row>
<Row>
<Col sm='12'>
<div className="card">
<div className="card-header">
<h4 className="card-title">{moduleSettings.mainTitleSingle}</h4>
</div>
<div className="card-body">
<ElementEdit />
</div>
</div>
</Col>
</Row>
</Fragment>
)
}
export default Tables
import { useState, useEffect, Fragment } from 'react'
import { useParams, Link } from 'react-router-dom'
// ** Store & Actions
import { getasset, updateasset } from '../../store/actions'
import { useSelector, useDispatch } from 'react-redux'
import { Alert } from 'reactstrap'
import ElementCard from '../card'
// module settings
import moduleSettings from '../module'
import { Upload } from 'react-feather'
import _ from 'lodash'
const ElementEdit = () => {
// ** States & Vars
const store = useSelector(state => state.assets),
[dataElement, setElementData] = useState(null),
dispatch = useDispatch(),
{ id } = useParams()
const onSubmitHandler = (values, uploadFile) => {
// console.log(values)
// console.log(uploadFile)
dispatch(
updateasset({
...dataElement,
idproject: values.idproject,
title: values.title,
parentid: values.parentid,
parenttype: values.parenttype,
external_id: values.external_id,
genres: values.genres,
subgenres: values.subgenres,
data: uploadFile
})
)
}
// ** Function to get user on mount
useEffect(() => {
dispatch(getasset(id))
}, [dispatch])
// ** Update user image on mount or change
useEffect(() => {
if (store.selectedAsset !== null || (store.selectedAsset !== null && dataElement !== null && store.selectedAsset.id !== dataElement.id)) {
return setElementData(store.selectedAsset)
}
}, [store.selectedAsset])
return store.selectedAsset !== null && store.selectedAsset !== undefined ? (
<ElementCard
selectedElement={store.selectedAsset}
onSubmitHandler={onSubmitHandler}
/>
) : (
<Alert color='info'>
<h4 className='alert-heading'>Loading {moduleSettings.mainTitleSingle}</h4>
<div className='alert-body'>
If {moduleSettings.mainTitleSingle} with id: {id} doesn't exist. Check list of all {moduleSettings.mainTitle}: <Link to={moduleSettings.baseURL}>{moduleSettings.mainTitle} List</Link>
</div>
</Alert>
)
}
export default ElementEdit
......@@ -8,8 +8,7 @@ import Breadcrumbs from '@components/breadcrumbs'
import { Row, Col } from 'reactstrap'
// ** Tables
import TableServerSide from './TableServerSide'
import TableAdvSearch from './TableAdvSearch'
import DataTable from './table'
// ** Styles
import '@styles/react/libs/tables/react-dataTable-component.scss'
......@@ -17,14 +16,11 @@ import '@styles/react/libs/tables/react-dataTable-component.scss'
const Tables = () => {
return (
<Fragment>
<Breadcrumbs breadCrumbTitle='Datatables' breadCrumbParent='Home' breadCrumbActive='Datatables Advance' />
<Breadcrumbs breadCrumbTitle='Settings' breadCrumbParent='Settings' breadCrumbActive='Location' />
<Row>
<Col sm='12'>
<TableServerSide />
</Col>
<Col sm='12'>
<TableAdvSearch />
</Col>
<DataTable />
</Col>
</Row>
</Fragment>
)
......
const moduleSettings = {
mainTitle: 'Locations',
mainTitleSingle: 'Location',
apiBaseURL: '/api/locations',
baseURL: '/settings/locations',
newElement: {
slug: 0,
type: 0
},
elementsOption: {
}
}
export default moduleSettings
\ No newline at end of file
import { Fragment, useState, useEffect, memo } from 'react'
// ** Table Columns
import { serverSideColumns } from './data'
// ** Store & Actions
import { getData_locations } from '../store/actions'
import { useSelector, useDispatch } from 'react-redux'
import DataTableServerSide from '@components/datatable'
const DataTable = () => {
// ** Store Vars
const dispatch = useDispatch()
const store = useSelector(state => state.projectsettings)
return (
<DataTableServerSide
cardTitle='Geo Locations'
allData={store.allDataLocations}
getData={getData_locations}
serverSideColumns={serverSideColumns}
linkAddButton='/settings/locations/add'
total={store.totalLocations}
/>
)
}
export default memo(DataTable)
......@@ -174,3 +174,39 @@ export const addPlatform = platform => {
})
}
}
// ** Get table Data locations
export const getData_locations = params => {
return async dispatch => {
await axios.get(`${process.env.REACT_APP_API}/api/locations`, {params}
).then(response => {
dispatch({
type: 'GET_DATA_LOCATIONS',
allData: response.data.data,
// data: response.data.invoices,
totalPages: response.data.recordsTotal,
params: response.data.params
})
})
}
}
export const addlocation = location => {
return (dispatch, getState) => {
axios
.post(`${process.env.REACT_APP_API}/api/locations`, location)
.then(response => {
dispatch({
type: 'ADD_LOCATION',
platform
})
})
.then(() => {
dispatch(setSaveSatus(true))
})
.catch(err => {
dispatch(setErrorMsg(err.response.data.message))
console.log(err.response.data)
})
}
}
......@@ -19,6 +19,12 @@ const initialState = {
allDataPlatforms: [],
selectedPlatform: null,
dataLocations: [],
totalLocations: 1,
paramsLocations: {},
allDataLocations: [],
selectedLocation: null,
dataPagetypes: [],
totalPagetypes: 1,
paramsPagetypes: {},
......@@ -100,7 +106,19 @@ const settings = (state = initialState, action) => {
case 'ADD_PAGETYPE':
return { ...state }
case 'GET_DATA_LOCATIONS':
return {
...state,
allDataLocations: action.allData,
dataLocations: action.data,
totalLocations: action.totalPages,
paramsLocations: action.params
}
case 'ADD_LOCATION':
return { ...state }
default:
return state
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment