Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
C
cms
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
Pedro-dev_2
cms
Commits
e5549631
Commit
e5549631
authored
May 15, 2021
by
PDuarte
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* init playlist
* manage menu playlist fix
parent
97814c86
Changes
17
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1475 additions
and
51 deletions
+1475
-51
rootReducer.js
src/redux/reducers/rootReducer.js
+3
-1
index.js
src/views/menupages/mainpages/card/index.js
+15
-4
manageplaylist.js
src/views/menupages/mainpages/card/manageplaylist.js
+63
-46
index.js
src/views/playlists/projectplaylists/add/index.js
+79
-0
index.js
src/views/playlists/projectplaylists/card/index.js
+383
-0
manageplaylist.js
src/views/playlists/projectplaylists/card/manageplaylist.js
+148
-0
plataform.js
src/views/playlists/projectplaylists/card/plataform.js
+0
-0
tablayoutplaylists.js
...ews/playlists/projectplaylists/card/tablayoutplaylists.js
+122
-0
data.js
src/views/playlists/projectplaylists/data.js
+290
-0
index.js
src/views/playlists/projectplaylists/edit/index.js
+44
-0
main.js
src/views/playlists/projectplaylists/edit/main.js
+70
-0
index.js
src/views/playlists/projectplaylists/index.js
+30
-0
module.js
src/views/playlists/projectplaylists/module.js
+14
-0
table.js
src/views/playlists/projectplaylists/table.js
+31
-0
index.js
src/views/playlists/store/actions/index.js
+12
-0
playlists.js
src/views/playlists/store/actions/playlists.js
+100
-0
index.js
src/views/playlists/store/reducer/index.js
+71
-0
No files found.
src/redux/reducers/rootReducer.js
View file @
e5549631
...
@@ -17,6 +17,7 @@ import dataTables from '@src/views/tables/data-tables/store/reducer'
...
@@ -17,6 +17,7 @@ import dataTables from '@src/views/tables/data-tables/store/reducer'
import
projectsettings
from
'@src/views/settings/store/reducer'
import
projectsettings
from
'@src/views/settings/store/reducer'
import
screens
from
'@src/views/screens/store/reducer'
import
screens
from
'@src/views/screens/store/reducer'
import
menupages
from
'@src/views/menupages/store/reducer'
import
menupages
from
'@src/views/menupages/store/reducer'
import
playlists
from
'@src/views/playlists/store/reducer'
const
rootReducer
=
combineReducers
({
const
rootReducer
=
combineReducers
({
auth
,
auth
,
...
@@ -32,7 +33,8 @@ const rootReducer = combineReducers({
...
@@ -32,7 +33,8 @@ const rootReducer = combineReducers({
dataTables
,
dataTables
,
screens
,
screens
,
projectsettings
,
projectsettings
,
menupages
menupages
,
playlists
})
})
export
default
rootReducer
export
default
rootReducer
src/views/menupages/mainpages/card/index.js
View file @
e5549631
...
@@ -18,6 +18,7 @@ import TabLayoutPlaylist from './tablayoutplaylists'
...
@@ -18,6 +18,7 @@ import TabLayoutPlaylist from './tablayoutplaylists'
import
{
resetResults
}
from
'../../store/actions'
import
{
resetResults
}
from
'../../store/actions'
import
{
getData_pagetypes
}
from
'../../../settings/store/actions'
import
{
getData_pagetypes
}
from
'../../../settings/store/actions'
import
{
getData_layoutmenus
}
from
'../../../screens/store/actions'
import
{
getData_layoutmenus
}
from
'../../../screens/store/actions'
import
{
getData_playlists
}
from
'../../../playlists/store/actions'
import
{
useForm
}
from
'react-hook-form'
import
{
useForm
}
from
'react-hook-form'
...
@@ -49,7 +50,9 @@ const SuccessProgressToast = () => (
...
@@ -49,7 +50,9 @@ const SuccessProgressToast = () => (
const
ElementCard
=
({
selectedElement
,
onSubmitHandler
})
=>
{
const
ElementCard
=
({
selectedElement
,
onSubmitHandler
})
=>
{
const
store
=
useSelector
(
state
=>
state
.
projectsettings
)
const
store
=
useSelector
(
state
=>
state
.
projectsettings
)
const
[
PlatformName
,
setPlatformName
]
=
useState
(
'Web'
)
const
[
PlatformName
,
setPlatformName
]
=
useState
(
'Web'
),
[
projectPlaylists
,
setProjectPlaylists
]
=
useState
(
null
)
const
MySwal
=
withReactContent
(
Swal
)
const
MySwal
=
withReactContent
(
Swal
)
...
@@ -70,6 +73,7 @@ const handleError = (text) => {
...
@@ -70,6 +73,7 @@ const handleError = (text) => {
{
register
,
errors
,
handleSubmit
}
=
useForm
(),
{
register
,
errors
,
handleSubmit
}
=
useForm
(),
settingStore
=
useSelector
(
state
=>
state
.
projectsettings
),
settingStore
=
useSelector
(
state
=>
state
.
projectsettings
),
screensStore
=
useSelector
(
state
=>
state
.
screens
),
screensStore
=
useSelector
(
state
=>
state
.
screens
),
playlistsStore
=
useSelector
(
state
=>
state
.
playlists
),
[
pagetypes
,
setPagetypes
]
=
useState
(
null
),
[
pagetypes
,
setPagetypes
]
=
useState
(
null
),
[
layoumenu
,
setLayoumenu
]
=
useState
(
null
),
[
layoumenu
,
setLayoumenu
]
=
useState
(
null
),
[
activeTab
,
setActiveTab
]
=
useState
(
0
),
[
activeTab
,
setActiveTab
]
=
useState
(
0
),
...
@@ -102,7 +106,8 @@ const handleError = (text) => {
...
@@ -102,7 +106,8 @@ const handleError = (text) => {
id
:
'<generated>'
,
id
:
'<generated>'
,
layout_id
:
null
,
layout_id
:
null
,
order
:
1
,
order
:
1
,
page_id
:
dataElement
.
id
page_id
:
dataElement
.
id
,
playlists
:
[]
})
})
setElementData
(
newData
)
setElementData
(
newData
)
setActiveTab
(
newData
.
menu_page_layouts
.
length
-
1
)
setActiveTab
(
newData
.
menu_page_layouts
.
length
-
1
)
...
@@ -139,6 +144,13 @@ const handleError = (text) => {
...
@@ -139,6 +144,13 @@ const handleError = (text) => {
q
:
null
q
:
null
}))
}))
}
}
if
(
playlistsStore
.
allDataPlaylists
===
null
||
playlistsStore
.
allDataPlaylists
.
length
<
1
)
{
dispatch
(
getData_playlists
({
start
:
0
,
length
:
1000
,
q
:
''
}))
}
},
[
dispatch
])
},
[
dispatch
])
useEffect
(()
=>
{
useEffect
(()
=>
{
setPagetypes
(
settingStore
.
allDataPagetypes
)
setPagetypes
(
settingStore
.
allDataPagetypes
)
...
@@ -158,7 +170,6 @@ const handleError = (text) => {
...
@@ -158,7 +170,6 @@ const handleError = (text) => {
setLayoumenu
(
screensStore
.
allDataLayoutMenus
)
setLayoumenu
(
screensStore
.
allDataLayoutMenus
)
},
[
screensStore
.
allDataLayoutMenus
])
},
[
screensStore
.
allDataLayoutMenus
])
return
(
return
(
<
Fragment
>
<
Fragment
>
<
Form
<
Form
...
...
src/views/menupages/mainpages/card/manageplaylist.js
View file @
e5549631
...
@@ -6,7 +6,7 @@ import { Row, Col, FormGroup, Label, Input, Button } from 'reactstrap'
...
@@ -6,7 +6,7 @@ import { Row, Col, FormGroup, Label, Input, Button } from 'reactstrap'
import
{
useForm
}
from
'react-hook-form'
import
{
useForm
}
from
'react-hook-form'
import
classnames
from
'classnames'
import
classnames
from
'classnames'
import
{
getData_
menupagesplaylists
,
updatemenupages
}
from
'../..
/store/actions'
import
{
getData_
playlists
}
from
'../../../playlists
/store/actions'
import
DataTableServerSide
from
'@components/datatable'
import
DataTableServerSide
from
'@components/datatable'
import
{
element
}
from
'prop-types'
import
{
element
}
from
'prop-types'
...
@@ -28,7 +28,7 @@ const serverSideColumns = [
...
@@ -28,7 +28,7 @@ const serverSideColumns = [
const
ManagePlaylist
=
(
dataElement
)
=>
{
const
ManagePlaylist
=
(
dataElement
)
=>
{
const
store
=
useSelector
(
state
=>
state
.
menupage
s
),
const
store
=
useSelector
(
state
=>
state
.
playlist
s
),
[
avaliablePlaylists
,
setavaliablePlaylists
]
=
useState
([]),
[
avaliablePlaylists
,
setavaliablePlaylists
]
=
useState
([]),
[
selectedPlaylists
,
setSelectedPlaylists
]
=
useState
([]),
[
selectedPlaylists
,
setSelectedPlaylists
]
=
useState
([]),
dispatch
=
useDispatch
()
dispatch
=
useDispatch
()
...
@@ -44,7 +44,7 @@ const ManagePlaylist = (dataElement) => {
...
@@ -44,7 +44,7 @@ const ManagePlaylist = (dataElement) => {
}
}
const
getData_selectedPlaylists
=
(
params
)
=>
{
const
getData_selectedPlaylists
=
(
params
)
=>
{
return
(
dispatch
)
=>
{
return
(
dispatch
)
=>
{
if
(
params
.
q
===
''
)
{
if
(
params
.
q
===
null
||
params
.
q
===
''
)
{
setSelectedPlaylists
(
dataElement
.
dataElement
)
setSelectedPlaylists
(
dataElement
.
dataElement
)
return
return
}
}
...
@@ -52,6 +52,40 @@ const ManagePlaylist = (dataElement) => {
...
@@ -52,6 +52,40 @@ const ManagePlaylist = (dataElement) => {
setSelectedPlaylists
(
newValue
)
setSelectedPlaylists
(
newValue
)
}
}
}
}
const
getData_avaliablePlaylists
=
(
params
)
=>
{
return
(
dispatch
)
=>
{
const
Ids
=
selectedPlaylists
.
map
(
elem
=>
elem
.
id
),
tabPlaylists
=
store
.
allDataPlaylists
.
filter
(
element
=>
!
Ids
.
includes
(
element
.
id
))
if
(
params
.
q
===
null
||
params
.
q
===
''
)
{
setavaliablePlaylists
(
tabPlaylists
)
return
}
const
newValue
=
tabPlaylists
.
filter
(
element
=>
element
.
title
.
includes
(
params
.
q
))
setavaliablePlaylists
(
newValue
)
}
}
useEffect
(()
=>
{
const
Ids
=
selectedPlaylists
.
map
(
elem
=>
elem
.
id
)
const
filtered
=
store
.
allDataPlaylists
.
filter
(
element
=>
!
Ids
.
includes
(
element
.
id
))
setavaliablePlaylists
(
filtered
)
},
[
store
.
allDataPlaylists
])
useEffect
(()
=>
{
if
(
selectedPlaylists
===
null
)
return
const
Ids
=
selectedPlaylists
.
map
(
elem
=>
elem
.
id
)
const
filtered
=
store
.
allDataPlaylists
.
filter
(
element
=>
!
Ids
.
includes
(
element
.
id
))
setavaliablePlaylists
(
filtered
)
},
[
selectedPlaylists
])
useEffect
(()
=>
{
if
(
dataElement
!==
null
&&
dataElement
.
dataElement
!==
null
)
{
setSelectedPlaylists
(
dataElement
.
dataElement
)
}
},
[
dataElement
])
const
serverSideColumnsLeft
=
[
const
serverSideColumnsLeft
=
[
...
serverSideColumns
,
...
serverSideColumns
,
...
@@ -96,23 +130,6 @@ const ManagePlaylist = (dataElement) => {
...
@@ -96,23 +130,6 @@ const ManagePlaylist = (dataElement) => {
}
}
]
]
useEffect
(()
=>
{
const
Ids
=
selectedPlaylists
.
map
(
elem
=>
elem
.
id
)
const
filtered
=
store
.
allDataMenuPages
.
filter
(
element
=>
!
Ids
.
includes
(
element
.
id
))
setavaliablePlaylists
(
filtered
)
},
[
store
.
allDataMenuPages
])
useEffect
(()
=>
{
const
Ids
=
selectedPlaylists
.
map
(
elem
=>
elem
.
id
)
const
filtered
=
store
.
allDataMenuPages
.
filter
(
element
=>
!
Ids
.
includes
(
element
.
id
))
setavaliablePlaylists
(
filtered
)
},
[
selectedPlaylists
])
useEffect
(()
=>
{
if
(
dataElement
!==
null
&&
dataElement
.
dataElement
!==
null
)
{
setSelectedPlaylists
(
dataElement
.
dataElement
)
}
},
[
dataElement
])
return
<
div
className
=
"card"
>
return
<
div
className
=
"card"
>
<
div
className
=
"card-header"
>
<
div
className
=
"card-header"
>
<
h4
className
=
"card-title"
>
playlist
<
/h4
>
<
h4
className
=
"card-title"
>
playlist
<
/h4
>
...
@@ -120,23 +137,23 @@ const ManagePlaylist = (dataElement) => {
...
@@ -120,23 +137,23 @@ const ManagePlaylist = (dataElement) => {
<
div
className
=
"card-body"
>
<
div
className
=
"card-body"
>
<
Row
>
<
Row
>
<
Col
sm
=
'6'
>
<
Col
sm
=
'6'
>
<
DataTableServerSide
{
selectedPlaylists
&&
<
DataTableServerSide
cardTitle
=
'Content'
cardTitle
=
'Content'
allData
=
{
selectedPlaylists
}
allData
=
{
selectedPlaylists
}
getData
=
{
getData_selectedPlaylists
}
getData
=
{
getData_selectedPlaylists
}
serverSideColumns
=
{
serverSideColumnsLeft
}
serverSideColumns
=
{
serverSideColumnsLeft
}
// linkAddButton={`/add`}
// linkAddButton={`/add`}
total
=
{
selectedPlaylists
.
length
}
total
=
{
selectedPlaylists
.
length
}
/
>
/>
}
<
/Col
>
<
/Col
>
<
Col
sm
=
'6'
>
<
Col
sm
=
'6'
>
<
DataTableServerSide
<
DataTableServerSide
cardTitle
=
'List to add'
cardTitle
=
'List to add'
allData
=
{
avaliablePlaylists
}
allData
=
{
avaliablePlaylists
}
getData
=
{
getData_
menupagesp
laylists
}
getData
=
{
getData_
avaliableP
laylists
}
serverSideColumns
=
{
serverSideColumnsRight
}
serverSideColumns
=
{
serverSideColumnsRight
}
// linkAddButton={`/add`}
// linkAddButton={`/add`}
total
=
{
store
.
total
MenuPage
s
}
total
=
{
store
.
total
Playlist
s
}
/
>
/
>
<
/Col
>
<
/Col
>
...
...
src/views/playlists/projectplaylists/add/index.js
0 → 100644
View file @
e5549631
// ** React Imports
import
{
Fragment
}
from
'react'
import
{
Link
}
from
'react-router-dom'
// ** Store & Actions
import
{
addmenupages
}
from
'../../store/actions'
import
{
useDispatch
}
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
onSubmitHandler
=
values
=>
{
dispatch
(
addmenupages
({
idproject
:
values
.
idproject
,
system_name
:
values
.
system_name
,
last_seen
:
values
.
last_seen
,
layout_page_id
:
values
.
layout_page_id
,
type
:
values
.
type
,
display
:
values
.
display
,
pagetypeid
:
values
.
pagetypeid
,
order
:
values
.
order
,
menu_page_layouts
:
values
.
menu_page_layouts
})
)
}
return
(
<
Fragment
>
<
Breadcrumbs
breadCrumbTitle
=
'Pages'
breadCrumbParent
=
'Pages'
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"
>
<
ElementCard
selectedElement
=
{{
id
:
'<generate>'
,
idproject
:
'2'
,
system_name
:
''
,
last_seen
:
''
,
layout_page_id
:
''
,
type
:
''
,
display
:
''
,
pagetypeid
:
''
,
order
:
'0'
,
menu_page_layouts
:
[]
}}
onSubmitHandler
=
{
onSubmitHandler
}
/
>
<
/div
>
<
/div
>
<
/Col
>
<
/Row
>
<
/Fragment
>
)
}
export
default
Tables
src/views/playlists/projectplaylists/card/index.js
0 → 100644
View file @
e5549631
This diff is collapsed.
Click to expand it.
src/views/playlists/projectplaylists/card/manageplaylist.js
0 → 100644
View file @
e5549631
import
{
useState
,
useEffect
}
from
'react'
import
{
useSelector
,
useDispatch
}
from
'react-redux'
// ** Third Party Components
import
{
Row
,
Col
,
FormGroup
,
Label
,
Input
,
Button
}
from
'reactstrap'
import
{
useForm
}
from
'react-hook-form'
import
classnames
from
'classnames'
import
{
getData_menupagesplaylists
,
updatemenupages
}
from
'../../store/actions'
import
DataTableServerSide
from
'@components/datatable'
import
{
element
}
from
'prop-types'
// ** Table Server Side Column
const
serverSideColumns
=
[
{
name
:
'ID'
,
selector
:
'id'
,
sortable
:
true
,
minWidth
:
'25px'
},
{
name
:
'Title'
,
selector
:
'title'
,
sortable
:
true
,
minWidth
:
'225px'
}
]
const
ManagePlaylist
=
(
dataElement
)
=>
{
const
store
=
useSelector
(
state
=>
state
.
menupages
),
[
avaliablePlaylists
,
setavaliablePlaylists
]
=
useState
([]),
[
selectedPlaylists
,
setSelectedPlaylists
]
=
useState
([]),
dispatch
=
useDispatch
()
const
handleAdd
=
(
value
)
=>
{
const
newValue
=
selectedPlaylists
.
concat
(
value
)
setSelectedPlaylists
(
newValue
)
}
const
handleRemove
=
(
value
)
=>
{
const
newValue
=
selectedPlaylists
.
filter
(
element
=>
element
.
id
!==
value
.
id
)
setSelectedPlaylists
(
newValue
)
}
const
getData_selectedPlaylists
=
(
params
)
=>
{
return
(
dispatch
)
=>
{
if
(
params
.
q
===
''
)
{
setSelectedPlaylists
(
dataElement
.
dataElement
)
return
}
const
newValue
=
dataElement
.
dataElement
.
filter
(
element
=>
element
.
title
.
includes
(
params
.
q
))
setSelectedPlaylists
(
newValue
)
}
}
const
serverSideColumnsLeft
=
[
...
serverSideColumns
,
{
name
:
'Action'
,
selector
:
'Action'
,
sortable
:
true
,
minWidth
:
'25px'
,
cell
:
row
=>
(
<
div
className
=
'd-flex justify-content-left align-items-center'
>
<
div
className
=
'd-flex flex-column'
>
<
Button
className
=
'user-name text-truncate mb-0'
onClick
=
{()
=>
{
handleRemove
(
row
)
}}
>
<
span
className
=
'font-weight-bold'
>
Remove
<
/span
>
<
/Button
>
<
/div
>
<
/div
>
)
}
]
const
serverSideColumnsRight
=
[
...
serverSideColumns
,
{
name
:
'Action'
,
selector
:
'Action'
,
sortable
:
true
,
minWidth
:
'25px'
,
cell
:
row
=>
(
<
div
className
=
'd-flex justify-content-left align-items-center'
>
<
div
className
=
'd-flex flex-column'
>
<
Button
className
=
'user-name text-truncate mb-0'
onClick
=
{()
=>
{
handleAdd
(
row
)
}}
>
<
span
className
=
'font-weight-bold'
>
Add
<
/span
>
<
/Button
>
<
/div
>
<
/div
>
)
}
]
useEffect
(()
=>
{
const
Ids
=
selectedPlaylists
.
map
(
elem
=>
elem
.
id
)
const
filtered
=
store
.
allDataMenuPages
.
filter
(
element
=>
!
Ids
.
includes
(
element
.
id
))
setavaliablePlaylists
(
filtered
)
},
[
store
.
allDataMenuPages
])
useEffect
(()
=>
{
const
Ids
=
selectedPlaylists
.
map
(
elem
=>
elem
.
id
)
const
filtered
=
store
.
allDataMenuPages
.
filter
(
element
=>
!
Ids
.
includes
(
element
.
id
))
setavaliablePlaylists
(
filtered
)
},
[
selectedPlaylists
])
useEffect
(()
=>
{
if
(
dataElement
!==
null
&&
dataElement
.
dataElement
!==
null
)
{
setSelectedPlaylists
(
dataElement
.
dataElement
)
}
},
[
dataElement
])
return
<
div
className
=
"card"
>
<
div
className
=
"card-header"
>
<
h4
className
=
"card-title"
>
playlist
<
/h4
>
<
/div
>
<
div
className
=
"card-body"
>
<
Row
>
<
Col
sm
=
'6'
>
<
DataTableServerSide
cardTitle
=
'Content'
allData
=
{
selectedPlaylists
}
getData
=
{
getData_selectedPlaylists
}
serverSideColumns
=
{
serverSideColumnsLeft
}
// linkAddButton={`/add`}
total
=
{
selectedPlaylists
.
length
}
/
>
<
/Col
>
<
Col
sm
=
'6'
>
<
DataTableServerSide
cardTitle
=
'List to add'
allData
=
{
avaliablePlaylists
}
getData
=
{
getData_menupagesplaylists
}
serverSideColumns
=
{
serverSideColumnsRight
}
// linkAddButton={`/add`}
total
=
{
store
.
totalMenuPages
}
/
>
<
/Col
>
<
/Row
>
<
/div
>
<
/div>
}
export
default
ManagePlaylist
\ No newline at end of file
src/views/
menupages/mainpage
s/card/plataform.js
→
src/views/
playlists/projectplaylist
s/card/plataform.js
View file @
e5549631
File moved
src/views/playlists/projectplaylists/card/tablayoutplaylists.js
0 → 100644
View file @
e5549631
import
{
useState
,
useEffect
}
from
'react'
import
{
useSelector
,
useDispatch
}
from
'react-redux'
// ** Third Party Components
import
{
Row
,
Col
,
FormGroup
,
Label
,
Input
,
Button
}
from
'reactstrap'
import
{
useForm
}
from
'react-hook-form'
import
classnames
from
'classnames'
import
{
getData_layoutPlaylists
}
from
'../../../screens/store/actions'
import
{
DivideCircle
}
from
'react-feather'
// import { Button } from 'bootstrap'
import
ManagePlaylist
from
'./manageplaylist'
const
TabLayoutPlaylist
=
({
block
,
selectedDataElement
,
setElementData
})
=>
{
const
[
dataElement
,
setDataElement
]
=
useState
(
null
),
[
layoutPlaylists
,
setLayoutPlaylists
]
=
useState
(
null
),
dispatch
=
useDispatch
(),
screensStore
=
useSelector
(
state
=>
state
.
screens
),
{
register
,
errors
,
handleSubmit
}
=
useForm
()
const
handleDetailChange
=
(
value
,
field
)
=>
{
const
newData
=
selectedDataElement
.
menu_page_layouts
.
map
((
mpagelayout
)
=>
{
if
(
mpagelayout
.
id
===
block
.
id
)
{
mpagelayout
[
field
]
=
value
}
})
setElementData
(
{
...
selectedDataElement
})
}
useEffect
(()
=>
{
if
(
block
!==
null
||
(
block
!==
null
&&
dataElement
!==
null
&&
block
.
id
!==
dataElement
.
id
))
{
return
setDataElement
(
block
)
}
},
[
block
])
// populate layout playlist
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
(
<
Col
sm
=
'12'
>
<
div
className
=
"card"
>
<
div
className
=
"card-header"
>
<
h4
className
=
"card-title"
>
ElementCard
{
dataElement
&&
dataElement
.
id
}
<
/h4
>
<
/div
>
<
div
className
=
"card-body"
>
<
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
=
'layout_id'
>
Layout
<
/Label
>
<
Input
type
=
'select'
name
=
'layout_id'
id
=
'layout_id'
placeholder
=
'layout_id'
innerRef
=
{
register
({
required
:
true
})}
defaultValue
=
{
dataElement
&&
dataElement
.
layout_id
}
className
=
{
classnames
({
'is-invalid'
:
errors
[
'layout_id'
]
})}
onChange
=
{(
e
)
=>
handleDetailChange
(
e
.
target
.
value
,
'layout_id'
)}
>
{
!!
layoutPlaylists
?
layoutPlaylists
.
map
(
option
=>
{
return
<
option
key
=
{
option
.
id
}
selected
=
{
option
.
id
===
dataElement
.
layout_id
?
option
.
id
:
''
}
value
=
{
option
.
id
}
>
{
option
.
name
}
<
/option
>
})
:
<
option
>
Loading
<
/option>
}
<
/Input
>
<
/FormGroup
>
<
/Col
>
<
Col
md
=
'4'
sm
=
'12'
>
<
FormGroup
>
<
Label
for
=
'order'
>
order
<
/Label
>
<
Input
type
=
'text'
name
=
'order'
order
=
'order'
placeholder
=
'order'
innerRef
=
{
register
({
required
:
true
})}
defaultValue
=
{
dataElement
&&
dataElement
.
order
}
className
=
{
classnames
({
'is-invalid'
:
errors
[
'order'
]
})}
onChange
=
{(
e
)
=>
handleDetailChange
(
e
.
target
.
value
,
'order'
)}
/
>
<
/FormGroup
>
<
/Col
>
<
/Row
>
<
/div
>
<
/div
>
<
ManagePlaylist
dataElement
=
{
dataElement
&&
dataElement
.
playlists
}
/>
<
/Col>
)
}
export
default
TabLayoutPlaylist
\ No newline at end of file
src/views/playlists/projectplaylists/data.js
0 → 100644
View file @
e5549631
// ** React Imports
import
{
Link
}
from
'react-router-dom'
// import { cleanLayoutMenu } from '../store/actions'
import
{
store
}
from
'@store/storeConfig/store'
// ** Custom Components
import
Avatar
from
'@components/avatar'
// module settings
import
moduleSettings
from
'./module'
// ** Third Party Components
import
axios
from
'axios'
import
{
MoreVertical
,
Edit
,
FileText
,
Archive
,
Trash
}
from
'react-feather'
import
{
Badge
,
UncontrolledDropdown
,
DropdownToggle
,
DropdownMenu
,
DropdownItem
}
from
'reactstrap'
// ** 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
:
'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
:
'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
:
'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
:
'name'
,
sortable
:
true
,
minWidth
:
'200px'
},
{
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
:
'ID'
,
selector
:
'id'
,
sortable
:
true
,
minWidth
:
'25px'
},
{
name
:
'System name'
,
selector
:
'system_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(cleanLayoutMenu(row.id))}
>
<
span
className
=
'font-weight-bold'
>
{
row
.
system_name
}
<
/span
>
<
/Link
>
<
small
className
=
'text-truncate text-muted mb-0'
>
edit
<
/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
src/views/playlists/projectplaylists/edit/index.js
0 → 100644
View file @
e5549631
// ** 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
=
'Pages'
breadCrumbParent
=
'Pages'
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
src/views/playlists/projectplaylists/edit/main.js
0 → 100644
View file @
e5549631
import
{
useState
,
useEffect
,
Fragment
}
from
'react'
import
{
useParams
,
Link
}
from
'react-router-dom'
// ** Store & Actions
import
{
getmenupages
,
updatemenupages
}
from
'../../store/actions'
import
{
useSelector
,
useDispatch
}
from
'react-redux'
import
{
Alert
}
from
'reactstrap'
import
ElementCard
from
'../card'
// module settings
import
moduleSettings
from
'../module'
const
ElementEdit
=
()
=>
{
// ** States & Vars
const
store
=
useSelector
(
state
=>
state
.
menupages
),
[
dataElement
,
setElementData
]
=
useState
(
null
),
dispatch
=
useDispatch
(),
{
id
}
=
useParams
()
const
onSubmitHandler
=
values
=>
{
console
.
log
(
values
)
dispatch
(
updatemenupages
({
...
dataElement
,
idproject
:
values
.
idproject
,
system_name
:
values
.
system_name
,
last_seen
:
values
.
last_seen
,
layout_page_id
:
values
.
layout_page_id
,
type
:
values
.
type
,
display
:
values
.
display
,
pagetypeid
:
values
.
pagetypeid
,
order
:
values
.
order
})
)
}
// ** Function to get user on mount
useEffect
(()
=>
{
dispatch
(
getmenupages
(
id
))
},
[
dispatch
])
// ** Update user image on mount or change
useEffect
(()
=>
{
if
(
store
.
selectedMenuPage
!==
null
||
(
store
.
selectedMenuPage
!==
null
&&
dataElement
!==
null
&&
store
.
selectedMenuPage
.
id
!==
dataElement
.
id
))
{
return
setElementData
(
store
.
selectedMenuPage
)
}
},
[
store
.
selectedMenuPage
])
return
store
.
selectedMenuPage
!==
null
&&
store
.
selectedMenuPage
!==
undefined
?
(
<
ElementCard
selectedElement
=
{
store
.
selectedMenuPage
}
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
src/views/playlists/projectplaylists/index.js
0 → 100644
View file @
e5549631
// ** React Imports
import
{
Fragment
}
from
'react'
// ** Custom Components
import
Breadcrumbs
from
'@components/breadcrumbs'
// ** Third Party Components
import
{
Row
,
Col
}
from
'reactstrap'
// ** Tables
import
DataTable
from
'./table'
// ** Styles
import
'@styles/react/libs/tables/react-dataTable-component.scss'
// module settings
import
moduleSettings
from
'./module'
const
Tables
=
()
=>
{
return
(
<
Fragment
>
<
Breadcrumbs
breadCrumbTitle
=
'Screens'
breadCrumbParent
=
'Screens'
breadCrumbActive
=
{
moduleSettings
.
mainTitle
}
/
>
<
Row
>
<
Col
sm
=
'12'
>
<
DataTable
/>
<
/Col
>
<
/Row
>
<
/Fragment
>
)
}
export
default
Tables
src/views/playlists/projectplaylists/module.js
0 → 100644
View file @
e5549631
const
moduleSettings
=
{
mainTitle
:
'Playlists'
,
mainTitleSingle
:
'Playlist'
,
apiBaseURL
:
'/api/playlists'
,
baseURL
:
'/playlists/projectplaylists'
,
newElement
:
{
slug
:
0
,
type
:
0
},
elementsOption
:
{
}
}
export
default
moduleSettings
\ No newline at end of file
src/views/playlists/projectplaylists/table.js
0 → 100644
View file @
e5549631
import
{
Fragment
,
useState
,
useEffect
,
memo
}
from
'react'
// ** Table Columns
import
{
serverSideColumns
}
from
'./data'
// ** Store & Actions
import
{
getData_menupages
}
from
'../store/actions'
import
{
useSelector
,
useDispatch
}
from
'react-redux'
import
DataTableServerSide
from
'@components/datatable'
// module settings
import
moduleSettings
from
'./module'
const
DataTable
=
()
=>
{
// ** Store Vars
const
dispatch
=
useDispatch
()
const
store
=
useSelector
(
state
=>
state
.
menupages
)
return
(
<
DataTableServerSide
cardTitle
=
{
moduleSettings
.
mainTitle
}
allData
=
{
store
.
allDataMenuPages
}
getData
=
{
getData_menupages
}
serverSideColumns
=
{
serverSideColumns
}
linkAddButton
=
{
`
${
moduleSettings
.
baseURL
}
/add`
}
total
=
{
store
.
totalMenuPages
}
/
>
)
}
export
default
memo
(
DataTable
)
src/views/playlists/store/actions/index.js
0 → 100644
View file @
e5549631
export
*
from
'./playlists'
export
const
resetResults
=
id
=>
{
return
async
dispatch
=>
{
dispatch
({
type
:
'RESET_RESULTS'
,
saveSucces
:
false
,
errorMsg
:
''
})
}
}
\ No newline at end of file
src/views/playlists/store/actions/playlists.js
0 → 100644
View file @
e5549631
import
axios
from
'axios'
import
{
setSaveSatus
,
setErrorMsg
}
from
'../../../../redux/actions/api'
import
moduleSettings
from
'../../projectplaylists/module'
// ** Get table Data ///api/datatables/data
const
_getData_playlists
=
params
=>
{
return
async
dispatch
=>
{
await
axios
.
get
(
`
${
process
.
env
.
REACT_APP_API
}${
moduleSettings
.
apiBaseURL
}
`
,
{
params
}
).
then
(
response
=>
{
dispatch
({
type
:
'GET_DATA_PLAYLISTS'
,
allData
:
response
.
data
.
data
,
// datalayoumenus: response.data.invoices,
totalPages
:
response
.
data
.
recordsTotal
,
params
:
response
.
data
.
params
})
})
}
}
export
const
getData_playlists
=
params
=>
{
const
newparams
=
{
...
params
,
idproject
:
2
}
return
_getData_playlists
(
newparams
)
}
export
const
addplaylist
=
params
=>
{
return
(
dispatch
,
getState
)
=>
{
axios
.
post
(
`
${
process
.
env
.
REACT_APP_API
}${
moduleSettings
.
apiBaseURL
}
`
,
params
)
.
then
(
response
=>
{
dispatch
({
type
:
'ADD_PLAYLIST'
,
params
:
newparams
})
})
.
then
(()
=>
{
dispatch
(
setSaveSatus
(
true
))
// dispatch(getlayoumenu(layoumenu.id))
// dispatch(getData_layoumenus())
})
.
catch
(
err
=>
{
const
errosMsg
=
!
err
.
response
?
'error'
:
err
.
response
.
data
.
message
console
.
log
(
errosMsg
)
dispatch
(
setErrorMsg
(
errosMsg
))
})
}
}
export
const
getplaylist
=
id
=>
{
return
async
dispatch
=>
{
await
axios
.
get
(
`
${
process
.
env
.
REACT_APP_API
}${
moduleSettings
.
apiBaseURL
}
/
${
id
}
`
)
.
then
(
response
=>
{
// console.log('leu')
// console.log(response)
dispatch
({
type
:
'GET_PLAYLIST'
,
data
:
response
.
data
.
data
})
})
.
catch
(
err
=>
console
.
log
(
err
))
}
}
export
const
cleanplaylist
=
id
=>
{
return
async
dispatch
=>
{
dispatch
({
type
:
'GET_PLAYLISTS'
,
data
:
null
})
}
}
export
const
updateplaylist
=
params
=>
{
return
(
dispatch
,
getState
)
=>
{
axios
.
put
(
`
${
process
.
env
.
REACT_APP_API
}${
moduleSettings
.
apiBaseURL
}
/
${
params
.
id
}
`
,
params
)
.
then
(
response
=>
{
dispatch
({
type
:
'UPDATE_PLAYLISTS'
,
params
})
})
.
then
(()
=>
{
dispatch
(
setSaveSatus
(
true
))
})
.
catch
(
err
=>
{
const
errosMsg
=
!
err
.
response
?
'error'
:
err
.
response
.
data
.
message
console
.
log
(
errosMsg
)
dispatch
(
setErrorMsg
(
errosMsg
))
})
}
}
\ No newline at end of file
src/views/playlists/store/reducer/index.js
0 → 100644
View file @
e5549631
// ** Initial State
const
initialState
=
{
saveSucces
:
false
,
errorMsg
:
''
,
data
:
[],
total
:
1
,
params
:
{},
allData
:
[],
dataPlaylists
:
[],
totalPlaylists
:
1
,
paramsPlaylists
:
{},
allDataPlaylists
:
[],
selectedPlaylist
:
null
}
const
playlists
=
(
state
=
initialState
,
action
)
=>
{
switch
(
action
.
type
)
{
case
'SAVE_STATUS'
:
return
{
...
state
,
saveSucces
:
action
.
status
}
case
'SAVE_ERROR'
:
return
{
...
state
,
errorMsg
:
action
.
errorMsg
}
case
'RESET_RESULTS'
:
return
{
...
state
,
saveSucces
:
false
,
errorMsg
:
''
}
// layout menus
case
'GET_DATA_PLAYLISTS'
:
return
{
...
state
,
allDataPlaylists
:
action
.
allData
,
dataPlaylists
:
action
.
data
,
totalPlaylists
:
action
.
totalPages
,
paramsPlaylists
:
action
.
params
}
case
'ADD_PLAYLISTS'
:
return
{
...
state
}
case
'GET_PROJECT'
:
return
{
...
state
,
selectedPlaylist
:
action
.
data
}
case
'GET_MENUPLAYLIST'
:
return
{
...
state
,
selectedPlaylist
:
action
.
data
}
case
'UPDATE_MENUPLAYLIST'
:
return
{
...
state
}
case
'ADD_MENUPLAYLIST'
:
return
{
...
state
}
// default
default
:
return
state
}
}
export
default
playlists
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