Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
radegast
Project
Overview
Details
Activity
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
Jan Hrabal
radegast
Commits
de503827
Commit
de503827
authored
Jul 12, 2019
by
jhrabal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
radegast
parent
6a7a102c
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
215 additions
and
227 deletions
+215
-227
RatingApiController.java
...rc/main/java/com/jh/radegast/api/RatingApiController.java
+5
-3
RatingsStats.java
backend/src/main/java/com/jh/radegast/api/RatingsStats.java
+48
-0
RatingStat.java
backend/src/main/java/com/jh/radegast/model/RatingStat.java
+36
-0
RatingRepository.java
...rc/main/java/com/jh/radegast/rating/RatingRepository.java
+37
-0
RatingService.java
...d/src/main/java/com/jh/radegast/rating/RatingService.java
+34
-0
index.js
frontend/app/components/UserInfo/index.js
+2
-9
config.js
frontend/app/config.js
+0
-1
index.js
frontend/app/containers/App/index.js
+2
-2
Home.scss
frontend/app/containers/Home/Home.scss
+4
-0
index.js
frontend/app/containers/Home/index.js
+29
-125
redux.js
frontend/app/containers/Home/redux.js
+18
-87
No files found.
backend/src/main/java/com/jh/radegast/api/RatingApiController.java
View file @
de503827
package
com
.
jh
.
radegast
.
api
;
package
com
.
jh
.
radegast
.
api
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.List
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
@@ -11,6 +10,7 @@ import org.springframework.stereotype.Controller;
...
@@ -11,6 +10,7 @@ import org.springframework.stereotype.Controller;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
com.jh.common.web.list.DefaultSorting
;
import
com.jh.common.web.list.DefaultSorting
;
...
@@ -28,7 +28,6 @@ public class RatingApiController {
...
@@ -28,7 +28,6 @@ public class RatingApiController {
@Autowired
@Autowired
private
RatingService
service
;
private
RatingService
service
;
//paged endpoint
@RequestMapping
(
path
=
"ratings"
,
method
=
RequestMethod
.
GET
)
@RequestMapping
(
path
=
"ratings"
,
method
=
RequestMethod
.
GET
)
@DefaultSorting
(
field
=
"key"
,
trend
=
SortTrend
.
DESCENDING
)
@DefaultSorting
(
field
=
"key"
,
trend
=
SortTrend
.
DESCENDING
)
public
ResponseEntity
<
List
<
Rating
>>
filterRatings
(
/*Date from, Date to, */
PagingInfo
pagingInfo
)
{
public
ResponseEntity
<
List
<
Rating
>>
filterRatings
(
/*Date from, Date to, */
PagingInfo
pagingInfo
)
{
...
@@ -42,6 +41,9 @@ public class RatingApiController {
...
@@ -42,6 +41,9 @@ public class RatingApiController {
service
.
saveBulk
(
ratings
);
service
.
saveBulk
(
ratings
);
}
}
//stats endpoint
@RequestMapping
(
path
=
"ratings/stats"
,
method
=
RequestMethod
.
GET
)
public
@ResponseBody
RatingsStats
ratingsStats
(
/*Date from, Date to */
)
{
return
service
.
calculateStats
(
new
RatingsFilter
());
}
}
}
backend/src/main/java/com/jh/radegast/api/RatingsStats.java
View file @
de503827
package
com
.
jh
.
radegast
.
api
;
package
com
.
jh
.
radegast
.
api
;
import
java.math.BigDecimal
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
public
class
RatingsStats
{
public
class
RatingsStats
{
private
Long
ratings
;
private
BigDecimal
average
;
private
HashMap
<
Long
,
Long
>
values
;
public
RatingsStats
()
{
public
RatingsStats
()
{
this
.
values
=
new
LinkedHashMap
<>();
ratings
=
0L
;
}
public
RatingsStats
(
Long
ratings
,
BigDecimal
average
,
HashMap
<
Long
,
Long
>
values
)
{
super
();
this
.
ratings
=
ratings
;
this
.
values
=
values
;
this
.
average
=
average
;
}
public
Long
getRatings
()
{
return
ratings
;
}
public
void
setRatings
(
Long
ratings
)
{
this
.
ratings
=
ratings
;
}
public
HashMap
<
Long
,
Long
>
getValues
()
{
return
values
;
}
public
void
setValues
(
HashMap
<
Long
,
Long
>
values
)
{
this
.
values
=
values
;
}
public
BigDecimal
getAverage
()
{
return
average
;
}
public
void
setAverage
(
BigDecimal
average
)
{
this
.
average
=
average
;
}
}
}
}
backend/src/main/java/com/jh/radegast/model/RatingStat.java
0 → 100644
View file @
de503827
package
com
.
jh
.
radegast
.
model
;
public
class
RatingStat
{
private
Long
rating
;
private
Long
count
;
public
RatingStat
()
{
}
public
RatingStat
(
Long
rating
,
Long
count
)
{
super
();
this
.
rating
=
rating
;
this
.
count
=
count
;
}
public
Long
getRating
()
{
return
rating
;
}
public
void
setRating
(
Long
rating
)
{
this
.
rating
=
rating
;
}
public
Long
getCount
()
{
return
count
;
}
public
void
setCount
(
Long
count
)
{
this
.
count
=
count
;
}
}
backend/src/main/java/com/jh/radegast/rating/RatingRepository.java
View file @
de503827
package
com
.
jh
.
radegast
.
rating
;
package
com
.
jh
.
radegast
.
rating
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Date
;
import
java.util.Date
;
...
@@ -8,6 +9,7 @@ import java.util.Set;
...
@@ -8,6 +9,7 @@ import java.util.Set;
import
org.hibernate.Criteria
;
import
org.hibernate.Criteria
;
import
org.hibernate.criterion.Restrictions
;
import
org.hibernate.criterion.Restrictions
;
import
org.hibernate.query.NativeQuery
;
import
org.springframework.stereotype.Repository
;
import
org.springframework.stereotype.Repository
;
import
com.jh.common.jpa.AbstractHibernateRepository
;
import
com.jh.common.jpa.AbstractHibernateRepository
;
...
@@ -15,6 +17,7 @@ import com.jh.common.web.list.Page;
...
@@ -15,6 +17,7 @@ import com.jh.common.web.list.Page;
import
com.jh.common.web.list.PagingInfo
;
import
com.jh.common.web.list.PagingInfo
;
import
com.jh.radegast.api.RatingsFilter
;
import
com.jh.radegast.api.RatingsFilter
;
import
com.jh.radegast.model.Rating
;
import
com.jh.radegast.model.Rating
;
import
com.jh.radegast.model.RatingStat
;
@Repository
@Repository
...
@@ -66,5 +69,39 @@ public class RatingRepository extends AbstractHibernateRepository {
...
@@ -66,5 +69,39 @@ public class RatingRepository extends AbstractHibernateRepository {
return
c
;
return
c
;
}
}
public
List
<
RatingStat
>
stats
(
RatingsFilter
filter
)
{
StringBuilder
sql
=
new
StringBuilder
(
"select rating, count(*) from rating where 1=1"
);
if
(
filter
!=
null
)
{
if
(
filter
.
getFrom
()
!=
null
)
{
sql
.
append
(
" and key >= :from "
);
}
if
(
filter
.
getTo
()
!=
null
)
{
sql
.
append
(
" and key <= :to "
);
}
}
sql
.
append
(
" group by rating"
);
NativeQuery
query
=
getSession
().
createNativeQuery
(
sql
.
toString
());
if
(
filter
!=
null
)
{
if
(
filter
.
getFrom
()
!=
null
)
{
query
.
setParameter
(
"from"
,
String
.
valueOf
(
filter
.
getFrom
().
getTime
()));
}
if
(
filter
.
getTo
()
!=
null
)
{
query
.
setParameter
(
"to"
,
String
.
valueOf
(
filter
.
getTo
().
getTime
()));
}
}
List
<
RatingStat
>
stats
=
new
ArrayList
<>();
List
<
Object
[]>
rows
=
query
.
list
();
if
(
rows
!=
null
)
{
for
(
Object
[]
row
:
rows
)
{
stats
.
add
(
new
RatingStat
(((
Number
)
row
[
0
]).
longValue
(),
((
Number
)
row
[
1
]).
longValue
()));
}
}
return
stats
;
}
}
}
backend/src/main/java/com/jh/radegast/rating/RatingService.java
View file @
de503827
package
com
.
jh
.
radegast
.
rating
;
package
com
.
jh
.
radegast
.
rating
;
import
java.math.BigDecimal
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.StringJoiner
;
import
java.util.StringJoiner
;
...
@@ -12,10 +15,13 @@ import org.springframework.beans.factory.annotation.Autowired;
...
@@ -12,10 +15,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
com.jh.common.utils.Utils
;
import
com.jh.common.web.list.Page
;
import
com.jh.common.web.list.Page
;
import
com.jh.common.web.list.PagingInfo
;
import
com.jh.common.web.list.PagingInfo
;
import
com.jh.radegast.api.RatingsFilter
;
import
com.jh.radegast.api.RatingsFilter
;
import
com.jh.radegast.api.RatingsStats
;
import
com.jh.radegast.model.Rating
;
import
com.jh.radegast.model.Rating
;
import
com.jh.radegast.model.RatingStat
;
@Service
@Service
public
class
RatingService
{
public
class
RatingService
{
...
@@ -69,4 +75,32 @@ public class RatingService {
...
@@ -69,4 +75,32 @@ public class RatingService {
return
repo
.
filter
(
ratingsFilter
);
return
repo
.
filter
(
ratingsFilter
);
}
}
@Transactional
public
RatingsStats
calculateStats
(
RatingsFilter
filter
)
{
Long
total
=
0L
;
Long
value
=
0L
;
BigDecimal
average
=
BigDecimal
.
ZERO
;
HashMap
<
Long
,
Long
>
ratings
=
new
LinkedHashMap
<>();
for
(
int
i
=
10
;
i
>
0
;
i
--)
{
ratings
.
put
(
Long
.
valueOf
(
i
),
0L
);
}
List
<
RatingStat
>
list
=
repo
.
stats
(
filter
);
if
(
list
!=
null
)
{
for
(
RatingStat
rs
:
list
)
{
ratings
.
put
(
rs
.
getRating
(),
rs
.
getCount
());
total
+=
rs
.
getCount
();
value
+=
rs
.
getRating
()
*
rs
.
getCount
();
}
}
if
(
total
>
0
)
{
average
=
Utils
.
divide
(
new
BigDecimal
(
value
),
new
BigDecimal
(
total
),
2
);
}
return
new
RatingsStats
(
total
,
average
,
ratings
);
}
}
}
frontend/app/components/UserInfo/index.js
View file @
de503827
...
@@ -9,11 +9,8 @@ class UserInfo extends Component {
...
@@ -9,11 +9,8 @@ class UserInfo extends Component {
render
()
{
render
()
{
let
{
user
,
name
}
=
this
.
props
;
let
{
user
,
name
}
=
this
.
props
;
if
(
!
user
)
{
if
(
!
user
)
{
user
=
(
window
.
cfg
&&
window
.
cfg
.
user
)
||
{};
user
=
(
window
.
cfg
&&
window
.
cfg
.
principal
)
||
{};
}
}
if
(
!
name
)
{
name
=
window
.
cfg
&&
window
.
cfg
.
unit
&&
window
.
cfg
.
unit
.
name
;
}
let
img
=
user
.
avatar
||
require
(
"./user-placeholder.png"
);
let
img
=
user
.
avatar
||
require
(
"./user-placeholder.png"
);
...
@@ -21,11 +18,7 @@ class UserInfo extends Component {
...
@@ -21,11 +18,7 @@ class UserInfo extends Component {
<
div
className
=
"user-placeholder"
>
<
div
className
=
"user-placeholder"
>
<
img
src
=
{
img
}
/>
<
img
src
=
{
img
}
/>
<
br
/>
<
br
/>
<
span
className
=
"user-name"
>
{
name
||
(
user
.
firstName
+
" "
+
user
.
lastName
)
}
<
/span>
<
span
className
=
"user-name"
>
{
user
&&
(
user
.
firstName
+
" "
+
user
.
lastName
)
}
<
/span>
<
br
/>
<
span
>
{
user
.
email
||
""
}
<
/span>
<
br
/>
<
span
>
{
user
.
position
||
""
}
<
/span>
<
/div>
<
/div>
);
);
...
...
frontend/app/config.js
View file @
de503827
...
@@ -14,7 +14,6 @@ export default () => new Promise((resolve) => {
...
@@ -14,7 +14,6 @@ export default () => new Promise((resolve) => {
global
.
_transitions
=
true
;
//FIXME
global
.
_transitions
=
true
;
//FIXME
//set colors
//set colors
let
chartColors
=
[
"4ec3e0"
,
"1287ed"
,
"929ba3"
];
//, "678096", "5beeff"];
let
chartColors
=
[
"4ec3e0"
,
"1287ed"
,
"929ba3"
];
//, "678096", "5beeff"];
//let pal = palette(chartColors, 17);
//let pal = palette(chartColors, 17);
...
...
frontend/app/containers/App/index.js
View file @
de503827
...
@@ -22,8 +22,8 @@ export default injectIntl((props) => {
...
@@ -22,8 +22,8 @@ export default injectIntl((props) => {
let
menuItems
=
[
let
menuItems
=
[
{
{
id
:
'
home
'
,
id
:
'
stats
'
,
route
:
'/
home
'
,
route
:
'/
stats
'
,
title
:
intl
.
formatMessage
(
messages
.
homeMenu
),
title
:
intl
.
formatMessage
(
messages
.
homeMenu
),
icon
:
icons
.
reports
icon
:
icons
.
reports
},
{
},
{
...
...
frontend/app/containers/Home/Home.scss
View file @
de503827
...
@@ -127,6 +127,10 @@
...
@@ -127,6 +127,10 @@
color
:
#009A00
;
color
:
#009A00
;
}
}
.list-row-data
.main-value.neutral-amount
{
color
:
#f5ab00
;
}
.list-row-data
.main-value.minus-amount
{
.list-row-data
.main-value.minus-amount
{
color
:
#FF0000
;
color
:
#FF0000
;
}
}
...
...
frontend/app/containers/Home/index.js
View file @
de503827
...
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
...
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
import
PropTypes
from
'prop-types'
;
import
PropTypes
from
'prop-types'
;
import
{
connect
}
from
'react-redux'
;
import
{
connect
}
from
'react-redux'
;
import
{
fetchS
ummary
,
fetchCashflow
,
fetchStatuses
,
fetchDashboardRecord
sAction
,
selector
}
from
'./redux.js'
;
import
{
fetchS
tatsAction
,
fetchRating
sAction
,
selector
}
from
'./redux.js'
;
import
{
PageTitle
,
ActivityIndicator
,
Info
,
MessagePanel
,
SummaryPanel
,
ToolbarButton
,
Toolbar
,
ToolbarSection
,
ToolbarButtons
,
ToolbarRow
,
PageSwitcher
}
from
'lib/components'
;
import
{
PageTitle
,
ActivityIndicator
,
Info
,
MessagePanel
,
SummaryPanel
,
ToolbarButton
,
Toolbar
,
ToolbarSection
,
ToolbarButtons
,
ToolbarRow
,
PageSwitcher
}
from
'lib/components'
;
...
@@ -14,32 +14,24 @@ import FetchedContent, { ErrorInfo } from 'components/FetchedContent';
...
@@ -14,32 +14,24 @@ import FetchedContent, { ErrorInfo } from 'components/FetchedContent';
//localization
//localization
import
{
injectIntl
}
from
'react-intl'
;
import
{
injectIntl
}
from
'react-intl'
;
import
{
formatMoney
,
formatDate
}
from
'lib/i18n'
;
import
{
formatMoney
,
formatDate
,
formatNumber
}
from
'lib/i18n'
;
import
{
settingsSelector
}
from
'utils/settings'
;
import
{
settingsSelector
}
from
'utils/settings'
;
import
{
Doughnut
,
HorizontalBar
}
from
'react-chartjs-2'
;
import
{
Doughnut
,
HorizontalBar
}
from
'react-chartjs-2'
;
import
palette
from
'utils/palette'
;
import
palette
from
'utils/palette'
;
import
icons
from
'constants/icons'
;
import
icons
from
'constants/icons'
;
import
messages
from
'./messages.js'
;
import
messages
from
'./messages.js'
;
import
moment
from
'moment'
;
require
(
"./Home.scss"
);
require
(
"./Home.scss"
);
const
renderButtons
=
(
router
,
intl
)
=>
{
return
[
<
ToolbarButton
key
=
"invoice"
label
=
{
intl
.
formatMessage
(
messages
.
addInvoiceButton
)
}
onClick
=
{
()
=>
handleBillableClick
(
"invoice"
,
"new"
,
router
)
}
>
<
span
className
=
"icon"
>
{
icons
.
invoice
}
<
/span>
<
/ToolbarButton>
];
}
//TODO
//TODO
class
DashboardList
extends
Component
{
class
DashboardList
extends
Component
{
render
()
{
render
()
{
let
{
data
,
fresh
,
paging
,
status
,
i18n
,
unitId
,
sorting
,
from
,
to
,
dateType
,
className
,
error
,
onRefresh
,
intl
}
=
this
.
props
;
let
{
data
,
fresh
,
paging
,
status
,
i18n
,
unitId
,
sorting
,
from
,
to
,
dateType
,
className
,
error
,
onRefresh
,
intl
}
=
this
.
props
;
let
content
=
null
;
let
content
=
null
;
let
{
router
}
=
this
.
context
;
return
(
return
(
<
FetchedContent
<
FetchedContent
...
@@ -49,40 +41,36 @@ class DashboardList extends Component {
...
@@ -49,40 +41,36 @@ class DashboardList extends Component {
fresh
=
{
fresh
}
fresh
=
{
fresh
}
empty
=
{
!
data
||
!
data
.
length
}
empty
=
{
!
data
||
!
data
.
length
}
size
=
"big"
size
=
"big"
buttons
=
{
renderButtons
(
router
,
intl
)
}
onRefresh
=
{
onRefresh
}
>
onRefresh
=
{
onRefresh
}
>
{
Array
.
isArray
(
data
)
?
data
.
map
((
row
,
key
)
=>
{
{
Array
.
isArray
(
data
)
?
data
.
map
((
row
,
key
)
=>
{
let
amount
=
row
.
type
==
'income'
||
row
.
type
==
'invoice'
?
row
.
amount
:
row
.
amount
*
-
1
;
let
rating
=
row
.
rating
;
let
amountClassName
=
"right main-value p5 "
+
(
amount
<
0
?
"minus-amount"
:
"plus-amount"
);
let
amountClassName
=
"right main-value p5 "
;
if
(
rating
>
6
)
{
amountClassName
+=
"plus-amount"
;
}
else
if
(
rating
>
3
)
{
amountClassName
+=
"neutral-amount"
;
}
else
{
amountClassName
+=
"minus-amount"
;
}
let
date
=
moment
(
row
.
created
).
format
(
'DD.MM.YYYY hh:mm:ss'
);
return
(
return
(
<
div
key
=
{
key
}
className
=
"flex-list-row"
>
<
div
key
=
{
key
}
className
=
"flex-list-row"
>
<
div
className
=
"content"
>
<
div
className
=
"content"
>
<
div
className
=
"list-row-data"
>
<
div
className
=
"list-row-data"
>
<
div
className
=
"record-type"
>
<
div
className
=
"icon"
>
{
icons
[
row
.
type
]
||
icons
.
empty
}
<
div
className
=
{
`status-indicator
${
row
.
status
||
"pending"
}
`
}
/>
<
/div>
<
div
className
=
"date"
>
{
dateType
==
"BILLED_DATE"
?
formatDate
(
row
.
billedDate
)
:
formatDate
(
row
.
dueDate
)
}
<
/div>
<
/div>
<
div
className
=
"main"
>
<
div
className
=
"main"
>
<
div
className
=
"main-value"
>
<
div
className
=
"main-value"
>
{
row
.
name
}
{
date
}
<
/div>
<
div
className
=
"additional-info"
>
{
row
.
description
||
" "
}
<
/div>
<
/div>
<
/div>
<
/div>
<
div
className
=
{
amountClassName
}
>
<
div
className
=
{
amountClassName
}
>
{
formatMoney
(
amount
,
row
.
currency
,
i18n
)
}
{
rating
}
<
/div>
<
/div>
<
/div>
<
/div>
<
/div>
<
/div>
<
div
className
=
"actions"
>
<
button
className
=
"icon"
onClick
=
{
()
=>
handleBillableClick
(
row
.
type
,
row
.
objectId
,
router
)
}
>
{
icons
.
leftMenu
}
<
/button>
<
/div>
<
/div>
<
/div>
);
);
})
:
null
}
})
:
null
}
...
@@ -90,7 +78,7 @@ class DashboardList extends Component {
...
@@ -90,7 +78,7 @@ class DashboardList extends Component {
<
PageSwitcher
<
PageSwitcher
paging
=
{
paging
}
paging
=
{
paging
}
displayNoPages
displayNoPages
onPageChanged
=
{
(
paging
)
=>
this
.
props
.
fetch
DashboardRecordsAction
(
unitId
,
{
from
,
to
},
paging
,
sorting
)
}
onPageChanged
=
{
(
paging
)
=>
this
.
props
.
fetch
RatingsAction
(
{
from
,
to
},
paging
,
sorting
)
}
status
=
{
status
}
status
=
{
status
}
disabled
=
{
status
==
"pending"
}
disabled
=
{
status
==
"pending"
}
/>
/>
...
@@ -106,7 +94,7 @@ DashboardList.contextTypes = {
...
@@ -106,7 +94,7 @@ DashboardList.contextTypes = {
DashboardList
=
connect
((
state
,
props
)
=>
state
.
getIn
([
"home"
,
"list"
]).
toJS
(),
(
dispatch
,
props
)
=>
{
DashboardList
=
connect
((
state
,
props
)
=>
state
.
getIn
([
"home"
,
"list"
]).
toJS
(),
(
dispatch
,
props
)
=>
{
return
{
return
{
dispatch
,
dispatch
,
fetch
DashboardRecordsAction
:
(
unitId
,
filter
,
paging
,
sorting
)
=>
dispatch
(
fetchDashboardRecordsAction
(
filter
,
paging
,
sorting
,
{
unitId
}
))
fetch
RatingsAction
:
(
filter
,
paging
,
sorting
)
=>
dispatch
(
fetchRatingsAction
(
filter
,
paging
,
sorting
))
};
};
})(
DashboardList
);
})(
DashboardList
);
DashboardList
=
injectIntl
(
DashboardList
);
DashboardList
=
injectIntl
(
DashboardList
);
...
@@ -138,89 +126,16 @@ class DashboardSummary extends Component {
...
@@ -138,89 +126,16 @@ class DashboardSummary extends Component {
return
(
return
(
<
div
className
=
"row-flex box-margin-5"
>
<
div
className
=
"row-flex box-margin-5"
>
{
this
.
renderSummaryPanel
(
status
,
messages
.
incomeTitle
,
""
,
0
,
intl
,
"income"
)
}
{
this
.
renderSummaryPanel
(
status
,
messages
.
incomeTitle
,
""
,
data
.
ratings
||
0
,
intl
,
"income"
)
}
{
this
.
renderSummaryPanel
(
status
,
messages
.
outcomeTitle
,
""
,
0
,
intl
,
"expenses"
)
}
{
this
.
renderSummaryPanel
(
status
,
messages
.
outcomeTitle
,
""
,
formatNumber
(
data
.
average
||
0
,
i18n
,
2
)
,
intl
,
"expenses"
)
}
<
/div>
<
/div>
);
}
);
}
}
}
DashboardSummary
=
connect
(
settingsSelector
((
state
,
props
)
=>
state
.
getIn
([
"home"
,
"s
ummary
"
]).
toJS
()),
(
dispatch
)
=>
({}))(
DashboardSummary
);
DashboardSummary
=
connect
(
settingsSelector
((
state
,
props
)
=>
state
.
getIn
([
"home"
,
"s
tats
"
]).
toJS
()),
(
dispatch
)
=>
({}))(
DashboardSummary
);
DashboardSummary
=
injectIntl
(
DashboardSummary
);
DashboardSummary
=
injectIntl
(
DashboardSummary
);
class
DashboardCashflowChart
extends
Component
{
render
()
{
let
{
currency
,
currencySymbol
,
data
,
labels
,
status
,
i18n
,
intl
,
unit
,
error
}
=
this
.
props
;
return
(
<
div
className
=
"pv20"
>
<
div
className
=
"p10 hover-highlight-light"
>
<
h2
className
=
"mb20"
>
{
intl
.
formatMessage
(
messages
.
cashflowTitle
)
}
<
/h2>
<
div
className
=
"big-chart"
>
{
error
?
<
ErrorInfo
size
=
"normal"
/>
:
null
}
<
/div>
<
ActivityIndicator
show
=
{
status
===
"pending"
}
type
=
"overlay"
size
=
"big"
/>
<
/div>
<
/div>
);
}
}
DashboardCashflowChart
=
connect
((
state
,
props
)
=>
state
.
getIn
([
"home"
,
"cashflow"
]).
toJS
(),
()
=>
({})
)(
DashboardCashflowChart
);
DashboardCashflowChart
=
injectIntl
(
DashboardCashflowChart
);
class
DashboardStatusChart
extends
Component
{
render
()
{
let
{
data
,
status
,
i18n
,
intl
,
error
,
onRefresh
}
=
this
.
props
;
let
draftLabel
=
intl
.
formatMessage
(
messages
.
draft
),
activeLabel
=
intl
.
formatMessage
(
messages
.
active
),
finishedLabel
=
intl
.
formatMessage
(
messages
.
finished
),
overdueLabel
=
intl
.
formatMessage
(
messages
.
overdue
),
currency
=
this
.
props
.
currencySymbol
||
this
.
props
.
currency
;
return
(
<
div
className
=
"pv20"
>
<
div
className
=
"status-charts"
>
<
div
className
=
"relative"
>
<
h3
>
{
intl
.
formatMessage
(
messages
.
statusIncome
)
}
<
/h3>
{
error
?
<
ErrorInfo
size
=
"normal"
onRefresh
=
{
onRefresh
}
/> : <StatusChart
data
=
{
data
&&
data
.
income
}
currency
=
{
currency
}
i18n
=
{
i18n
}
draftLabel
=
{
draftLabel
}
activeLabel
=
{
activeLabel
}
finishedLabel
=
{
finishedLabel
}
overdueLabel
=
{
overdueLabel
}
/> }
<
ActivityIndicator
show
=
{
status
===
"pending"
}
type
=
"overlay"
size
=
"big"
/>
<
/div>
<
div
className
=
"relative"
>
<
h3
>
{
intl
.
formatMessage
(
messages
.
statusOutcome
)
}
<
/h3>
{
error
?
<
ErrorInfo
size
=
"normal"
onRefresh
=
{
onRefresh
}
/> : <StatusChart
data
=
{
data
&&
data
.
outcome
}
currency
=
{
currency
}
i18n
=
{
i18n
}
draftLabel
=
{
draftLabel
}
activeLabel
=
{
activeLabel
}
finishedLabel
=
{
finishedLabel
}
overdueLabel
=
{
overdueLabel
}
/> }
<
ActivityIndicator
show
=
{
status
===
"pending"
}
type
=
"overlay"
size
=
"big"
/>
<
/div>
<
/div>
<
/div>
);
}
}
DashboardStatusChart
=
connect
(
settingsSelector
((
state
,
props
)
=>
state
.
getIn
([
"home"
,
"statuses"
]).
toJS
()),
()
=>
({})
)(
DashboardStatusChart
);
DashboardStatusChart
=
injectIntl
(
DashboardStatusChart
);
class
Home
extends
Component
{
class
Home
extends
Component
{
...
@@ -257,11 +172,8 @@ class Home extends Component {
...
@@ -257,11 +172,8 @@ class Home extends Component {
let
unitId
=
this
.
props
.
unitId
;
let
unitId
=
this
.
props
.
unitId
;
let
{
from
,
to
,
dateType
}
=
periodParams
;
let
{
from
,
to
,
dateType
}
=
periodParams
;
this
.
props
.
fetchSummary
(
unitId
,
from
,
to
,
dateType
);
this
.
props
.
fetchStatsAction
(
from
,
to
,
dateType
);
this
.
props
.
fetchCashflow
(
unitId
,
from
,
to
,
dateType
);
this
.
props
.
fetchRatingsAction
({
from
,
to
},
paging
,
sorting
);
this
.
props
.
fetchStatuses
(
unitId
,
from
,
to
,
dateType
);
this
.
props
.
fetchDashboardRecordsAction
(
unitId
,
{
from
,
to
},
paging
,
sorting
);
}
}
...
@@ -280,24 +192,18 @@ class Home extends Component {
...
@@ -280,24 +192,18 @@ class Home extends Component {
<
PageTitle
title
=
{
intl
.
formatMessage
(
messages
.
pageTitle
)
}
titleIcon
=
{
icons
.
home
}
/>
<
PageTitle
title
=
{
intl
.
formatMessage
(
messages
.
pageTitle
)
}
titleIcon
=
{
icons
.
home
}
/>
<
/ToolbarSection>
<
/ToolbarSection>
<
ToolbarButtons
>
<
ToolbarButtons
>
{
renderButtons
(
router
,
intl
)
}
<
/ToolbarButtons>
<
/ToolbarButtons>
<
ToolbarRow
>
{
/*<PeriodTitle changePeriod={ this.changePeriod } />*/
}
<
/ToolbarRow>
<
/Toolbar>
<
/Toolbar>
<
/div>
<
/div>
<
/div>
<
/div>
<
div
className
=
"dashboard-row"
>
<
div
className
=
"dashboard-row"
>
<
div
className
=
"col-md-6"
>
<
div
className
=
"col-md-
4 col-sm-
6"
>
<
div
className
=
"p10 min-height-120"
>
<
div
className
=
"p10 min-height-120"
>
{
/*<DashboardList unitId={ unitId } from={ from } to={ to } dateType={ dateType } i18n={ i18n } onRefresh={ this.init } />*/
}
<
DashboardList
from
=
{
from
}
to
=
{
to
}
i18n
=
{
i18n
}
onRefresh
=
{
this
.
init
}
/>
<
/div>
<
/div>
<
/div>
<
/div>
<
div
className
=
"col-md-6 p10"
>
<
div
className
=
"col-md-
8 col-sm-
6 p10"
>
<
DashboardSummary
i18n
=
{
i18n
}
onRefresh
=
{
this
.
init
}
/>
<
DashboardSummary
i18n
=
{
i18n
}
onRefresh
=
{
this
.
init
}
/>
<
DashboardCashflowChart
i18n
=
{
i18n
}
onRefresh
=
{
this
.
init
}
/>
<
DashboardStatusChart
i18n
=
{
i18n
}
onRefresh
=
{
this
.
init
}
/>
<
/div>
<
/div>
<
/div>
<
/div>
...
@@ -316,10 +222,8 @@ Home.contextTypes = {
...
@@ -316,10 +222,8 @@ Home.contextTypes = {
function
mapDispatchToProps
(
dispatch
,
props
)
{
function
mapDispatchToProps
(
dispatch
,
props
)
{
return
{
return
{
fetchSummary
:
(
unitId
,
from
,
to
,
dateType
)
=>
dispatch
(
fetchSummary
(
unitId
,
from
,
to
,
dateType
)),
fetchStatsAction
:
(
from
,
to
,
dateType
)
=>
dispatch
(
fetchStatsAction
(
from
,
to
,
dateType
)),
fetchCashflow
:
(
unitId
,
from
,
to
,
dateType
)
=>
dispatch
(
fetchCashflow
(
unitId
,
from
,
to
,
dateType
)),
fetchRatingsAction
:
(
filter
,
paging
,
sorting
)
=>
dispatch
(
fetchRatingsAction
(
filter
,
{...
paging
,
pageSize
:
7
},
sorting
))
fetchStatuses
:
(
unitId
,
from
,
to
,
dateType
)
=>
dispatch
(
fetchStatuses
(
unitId
,
from
,
to
,
dateType
)),
fetchDashboardRecordsAction
:
(
unitId
,
filter
,
paging
,
sorting
)
=>
dispatch
(
fetchDashboardRecordsAction
(
filter
,
{...
paging
,
pageSize
:
7
},
sorting
))
};
};
}
}
...
...
frontend/app/containers/Home/redux.js
View file @
de503827
...
@@ -18,31 +18,19 @@ let initialState = {
...
@@ -18,31 +18,19 @@ let initialState = {
status
:
'pending'
,
status
:
'pending'
,
fresh
:
true
,
fresh
:
true
,
paging
:
{
paging
:
{
pageSize
:
7
pageSize
:
15
},
},
data
:
[]
data
:
[]
},
},
s
ummary
:
{
s
tats
:
{
status
:
'pending'
,
status
:
'pending'
,
},
cashflow
:
{
status
:
'pending'
,
fresh
:
true
,
data
:
{
data
:
{
empty
:
true
total
:
0
,
values
:
{
}
}
}
},
},
statuses
:
{
status
:
'pending'
,
fresh
:
true
,
data
:
{
income
:
{},
outcome
:
{},
data
:
{},
empty
:
true
}
}
};
};
let
reducer
=
createReducer
(
initialState
);
let
reducer
=
createReducer
(
initialState
);
...
@@ -55,97 +43,41 @@ let api = reduxList("home/dashboard", {
...
@@ -55,97 +43,41 @@ let api = reduxList("home/dashboard", {
});
});
//export actions
//export actions
export
const
fetch
DashboardRecord
sAction
=
api
.
actions
.
fetchList
;
export
const
fetch
Rating
sAction
=
api
.
actions
.
fetchList
;
//TODO
//TODO
export
const
selector
=
settingsSelector
((
state
,
props
)
=>
{
export
const
selector
=
settingsSelector
((
state
,
props
)
=>
{
let
home
=
safe
(
state
.
get
(
"home"
));
let
home
=
safe
(
state
.
get
(
"home"
));
let
periodParams
=
safe
(
state
.
getIn
([
"params"
,
"period"
]));
let
list
=
api
.
selector
(
state
,
props
);
let
list
=
api
.
selector
(
state
,
props
);
return
{
...
home
,
periodParams
}
;
return
home
;
});
});
export
function
fetchS
ummary
(
unitId
,
from
,
to
,
dateType
)
{
export
function
fetchS
tatsAction
(
unitId
,
from
,
to
,
dateType
)
{
return
{
return
{
type
:
'home/FETCH_S
UMMARY
'
,
type
:
'home/FETCH_S
TATS
'
,
payload
:
backendRequest
(
'/api/
'
+
unitId
+
'/home/dashboard
'
,
'GET'
,
{
params
:
{
from
,
to
}
})
payload
:
backendRequest
(
'/api/
ratings/stats
'
,
'GET'
,
{
params
:
{
from
,
to
}
})
};
};
};
};
reducer
.
handleAction
(
'home/FETCH_S
UMMARY
_PENDING'
,
(
state
,
action
)
=>
reducer
.
handleAction
(
'home/FETCH_S
TATS
_PENDING'
,
(
state
,
action
)
=>
state
.
setIn
([
"s
ummary
"
,
"status"
],
"pending"
)
state
.
setIn
([
"s
tats
"
,
"status"
],
"pending"
)
);
);
reducer
.
handleAction
(
'home/FETCH_S
UMMARY
_FULFILLED'
,
(
state
,
action
)
=>
reducer
.
handleAction
(
'home/FETCH_S
TATS
_FULFILLED'
,
(
state
,
action
)
=>
state
state
.
setIn
([
"s
ummary
"
,
"status"
],
"success"
)
.
setIn
([
"s
tats
"
,
"status"
],
"success"
)
.
setIn
([
"s
ummary
"
,
"data"
],
action
.
payload
.
body
)
.
setIn
([
"s
tats
"
,
"data"
],
action
.
payload
.
body
)
.
deleteIn
([
"s
ummary
"
,
"error"
])
.
deleteIn
([
"s
tats
"
,
"error"
])
);
);
reducer
.
handleAction
(
'home/FETCH_S
UMMARY
_REJECTED'
,
(
state
,
action
)
=>
reducer
.
handleAction
(
'home/FETCH_S
TATS
_REJECTED'
,
(
state
,
action
)
=>
state
.
setIn
([
"s
ummary"
,
"status"
],
"failed"
).
deleteIn
([
"summary"
,
"data"
]).
setIn
([
"summary
"
,
"error"
],
true
)
state
.
setIn
([
"s
tats"
,
"status"
],
"failed"
).
deleteIn
([
"stats"
,
"data"
]).
setIn
([
"stats
"
,
"error"
],
true
)
);
);
export
function
fetchCashflow
(
unitId
,
from
,
to
,
dateType
)
{
return
{
type
:
'home/FETCH_CASHFLOW'
,
payload
:
backendRequest
(
'/api/'
+
unitId
+
'/home/cashflow'
,
'GET'
,
{
params
:
{
from
,
to
,
dateType
}
})
};
};
reducer
.
handleAction
(
'home/FETCH_CASHFLOW_PENDING'
,
(
state
,
action
)
=>
state
.
setIn
([
"cashflow"
,
"status"
],
"pending"
)
);
reducer
.
handleAction
(
'home/FETCH_CASHFLOW_FULFILLED'
,
(
state
,
action
)
=>
state
.
withMutations
(
s
=>
{
let
b
=
action
.
payload
.
body
;
s
=
s
.
setIn
([
"cashflow"
,
"data"
],
b
.
data
);
s
=
s
.
setIn
([
"cashflow"
,
"labels"
],
b
.
labels
);
s
=
s
.
setIn
([
"cashflow"
,
"params"
],
b
.
params
);
s
=
s
.
setIn
([
"cashflow"
,
"currency"
],
b
.
currency
);
s
=
s
.
setIn
([
"cashflow"
,
"currencySymbol"
],
b
.
currencySymbol
);
s
=
s
.
deleteIn
([
"cashflow"
,
"error"
]);
return
s
;
})
.
setIn
([
"cashflow"
,
"status"
],
"success"
)
);
reducer
.
handleAction
(
'home/FETCH_CASHFLOW_REJECTED'
,
(
state
,
action
)
=>
state
.
setIn
([
"cashflow"
,
"status"
],
"failed"
).
setIn
([
"cashflow"
,
"error"
],
true
)
);
export
function
fetchStatuses
(
unitId
,
from
,
to
,
dateType
)
{
return
{
type
:
'home/FETCH_STATUSES'
,
payload
:
backendRequest
(
'/api/'
+
unitId
+
'/home/statuses'
,
'GET'
,
{
params
:
{
from
,
to
,
dateType
}
})
};
};
reducer
.
handleAction
(
'home/FETCH_STATUSES_PENDING'
,
(
state
,
action
)
=>
state
.
setIn
([
"statuses"
,
"status"
],
"pending"
)
);
reducer
.
handleAction
(
'home/FETCH_STATUSES_FULFILLED'
,
(
state
,
action
)
=>
state
.
withMutations
(
s
=>
{
s
=
s
.
set
(
"statuses"
,
fromJS
(
action
.
payload
.
body
));
s
=
s
.
setIn
([
"statuses"
,
"status"
],
"success"
);
s
=
s
.
deleteIn
([
"statuses"
,
"error"
]);
return
s
;
})
);
reducer
.
handleAction
(
'home/FETCH_STATUSES_REJECTED'
,
(
state
,
action
)
=>
state
.
setIn
([
"statuses"
,
"status"
],
"failed"
).
setIn
([
"statuses"
,
"error"
],
true
)
);
//export reducer
//export reducer
export
default
reducer
.
export
();
export
default
reducer
.
export
();
//TODO transform summary response
\ No newline at end of file
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