Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
9451a82f
Commit
9451a82f
authored
Apr 18, 2018
by
Jose
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored activity calendar
parent
fb46dfb2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
135 additions
and
75 deletions
+135
-75
app/assets/javascripts/pages/users/activity_calendar.js
app/assets/javascripts/pages/users/activity_calendar.js
+130
-75
changelogs/unreleased/jivl-refactor-activity-calendar.yml
changelogs/unreleased/jivl-refactor-activity-calendar.yml
+5
-0
No files found.
app/assets/javascripts/pages/users/activity_calendar.js
View file @
9451a82f
...
@@ -19,7 +19,7 @@ function getSystemDate(systemUtcOffsetSeconds) {
...
@@ -19,7 +19,7 @@ function getSystemDate(systemUtcOffsetSeconds) {
const
date
=
new
Date
();
const
date
=
new
Date
();
const
localUtcOffsetMinutes
=
0
-
date
.
getTimezoneOffset
();
const
localUtcOffsetMinutes
=
0
-
date
.
getTimezoneOffset
();
const
systemUtcOffsetMinutes
=
systemUtcOffsetSeconds
/
60
;
const
systemUtcOffsetMinutes
=
systemUtcOffsetSeconds
/
60
;
date
.
setMinutes
(
(
date
.
getMinutes
()
-
localUtcOffsetMinutes
)
+
systemUtcOffsetMinutes
);
date
.
setMinutes
(
date
.
getMinutes
()
-
localUtcOffsetMinutes
+
systemUtcOffsetMinutes
);
return
date
;
return
date
;
}
}
...
@@ -35,18 +35,36 @@ function formatTooltipText({ date, count }) {
...
@@ -35,18 +35,36 @@ function formatTooltipText({ date, count }) {
return
`
${
contribText
}
<br />
${
dateDayName
}
${
dateText
}
`
;
return
`
${
contribText
}
<br />
${
dateDayName
}
${
dateText
}
`
;
}
}
const
initColorKey
=
()
=>
d3
.
scaleLinear
().
range
([
'
#acd5f2
'
,
'
#254e77
'
]).
domain
([
0
,
3
]);
const
initColorKey
=
()
=>
d3
.
scaleLinear
()
.
range
([
'
#acd5f2
'
,
'
#254e77
'
])
.
domain
([
0
,
3
]);
export
default
class
ActivityCalendar
{
export
default
class
ActivityCalendar
{
constructor
(
container
,
timestamps
,
calendarActivitiesPath
,
utcOffset
=
0
)
{
constructor
(
container
,
timestamps
,
calendarActivitiesPath
,
utcOffset
=
0
,
firstDayOfWeek
=
0
)
{
this
.
calendarActivitiesPath
=
calendarActivitiesPath
;
this
.
calendarActivitiesPath
=
calendarActivitiesPath
;
this
.
clickDay
=
this
.
clickDay
.
bind
(
this
);
this
.
clickDay
=
this
.
clickDay
.
bind
(
this
);
this
.
currentSelectedDate
=
''
;
this
.
currentSelectedDate
=
''
;
this
.
daySpace
=
1
;
this
.
daySpace
=
1
;
this
.
daySize
=
15
;
this
.
daySize
=
15
;
this
.
daySizeWithSpace
=
this
.
daySize
+
(
this
.
daySpace
*
2
);
this
.
daySizeWithSpace
=
this
.
daySize
+
this
.
daySpace
*
2
;
this
.
monthNames
=
[
'
Jan
'
,
'
Feb
'
,
'
Mar
'
,
'
Apr
'
,
'
May
'
,
'
Jun
'
,
'
Jul
'
,
'
Aug
'
,
'
Sep
'
,
'
Oct
'
,
'
Nov
'
,
'
Dec
'
];
this
.
monthNames
=
[
'
Jan
'
,
'
Feb
'
,
'
Mar
'
,
'
Apr
'
,
'
May
'
,
'
Jun
'
,
'
Jul
'
,
'
Aug
'
,
'
Sep
'
,
'
Oct
'
,
'
Nov
'
,
'
Dec
'
,
];
this
.
months
=
[];
this
.
months
=
[];
this
.
firstDayOfWeek
=
firstDayOfWeek
;
// Loop through the timestamps to create a group of objects
// Loop through the timestamps to create a group of objects
// The group of objects will be grouped based on the day of the week they are
// The group of objects will be grouped based on the day of the week they are
...
@@ -70,7 +88,7 @@ export default class ActivityCalendar {
...
@@ -70,7 +88,7 @@ export default class ActivityCalendar {
// Create a new group array if this is the first day of the week
// Create a new group array if this is the first day of the week
// or if is first object
// or if is first object
if
((
day
===
0
&&
i
!==
0
)
||
i
===
0
)
{
if
((
day
===
this
.
firstDayOfWeek
&&
i
!==
0
)
||
i
===
0
)
{
this
.
timestampsTmp
.
push
([]);
this
.
timestampsTmp
.
push
([]);
group
+=
1
;
group
+=
1
;
}
}
...
@@ -109,21 +127,30 @@ export default class ActivityCalendar {
...
@@ -109,21 +127,30 @@ export default class ActivityCalendar {
}
}
renderSvg
(
container
,
group
)
{
renderSvg
(
container
,
group
)
{
const
width
=
((
group
+
1
)
*
this
.
daySizeWithSpace
)
+
this
.
getExtraWidthPadding
(
group
);
const
width
=
(
group
+
1
)
*
this
.
daySizeWithSpace
+
this
.
getExtraWidthPadding
(
group
);
return
d3
.
select
(
container
)
return
d3
.
select
(
container
)
.
append
(
'
svg
'
)
.
append
(
'
svg
'
)
.
attr
(
'
width
'
,
width
)
.
attr
(
'
width
'
,
width
)
.
attr
(
'
height
'
,
167
)
.
attr
(
'
height
'
,
167
)
.
attr
(
'
class
'
,
'
contrib-calendar
'
);
.
attr
(
'
class
'
,
'
contrib-calendar
'
);
}
dayYPos
(
day
)
{
return
this
.
daySizeWithSpace
*
((
day
+
7
-
this
.
firstDayOfWeek
)
%
7
);
}
}
renderDays
()
{
renderDays
()
{
this
.
svg
.
selectAll
(
'
g
'
).
data
(
this
.
timestampsTmp
).
enter
().
append
(
'
g
'
)
this
.
svg
.
selectAll
(
'
g
'
)
.
data
(
this
.
timestampsTmp
)
.
enter
()
.
append
(
'
g
'
)
.
attr
(
'
transform
'
,
(
group
,
i
)
=>
{
.
attr
(
'
transform
'
,
(
group
,
i
)
=>
{
_
.
each
(
group
,
(
stamp
,
a
)
=>
{
_
.
each
(
group
,
(
stamp
,
a
)
=>
{
if
(
a
===
0
&&
stamp
.
day
===
0
)
{
if
(
a
===
0
&&
stamp
.
day
===
0
)
{
const
month
=
stamp
.
date
.
getMonth
();
const
month
=
stamp
.
date
.
getMonth
();
const
x
=
(
this
.
daySizeWithSpace
*
i
)
+
1
+
this
.
daySizeWithSpace
;
const
x
=
this
.
daySizeWithSpace
*
i
+
1
+
this
.
daySizeWithSpace
;
const
lastMonth
=
_
.
last
(
this
.
months
);
const
lastMonth
=
_
.
last
(
this
.
months
);
if
(
if
(
lastMonth
==
null
||
lastMonth
==
null
||
...
@@ -133,86 +160,113 @@ export default class ActivityCalendar {
...
@@ -133,86 +160,113 @@ export default class ActivityCalendar {
}
}
}
}
});
});
return
`translate(
${
(
this
.
daySizeWithSpace
*
i
)
+
1
+
this
.
daySizeWithSpace
}
, 18)`
;
return
`translate(
${
this
.
daySizeWithSpace
*
i
+
1
+
this
.
daySizeWithSpace
}
, 18)`
;
})
})
.
selectAll
(
'
rect
'
)
.
selectAll
(
'
rect
'
)
.
data
(
stamp
=>
stamp
)
.
data
(
stamp
=>
stamp
)
.
enter
()
.
enter
()
.
append
(
'
rect
'
)
.
append
(
'
rect
'
)
.
attr
(
'
x
'
,
'
0
'
)
.
attr
(
'
x
'
,
'
0
'
)
.
attr
(
'
y
'
,
stamp
=>
this
.
daySizeWithSpace
*
stamp
.
day
)
.
attr
(
'
y
'
,
stamp
=>
this
.
dayYPos
(
stamp
.
day
))
.
attr
(
'
width
'
,
this
.
daySize
)
.
attr
(
'
width
'
,
this
.
daySize
)
.
attr
(
'
height
'
,
this
.
daySize
)
.
attr
(
'
height
'
,
this
.
daySize
)
.
attr
(
'
fill
'
,
stamp
=>
(
.
attr
(
stamp
.
count
!==
0
?
this
.
color
(
Math
.
min
(
stamp
.
count
,
40
))
:
'
#ededed
'
'
fill
'
,
))
stamp
=>
(
stamp
.
count
!==
0
?
this
.
color
(
Math
.
min
(
stamp
.
count
,
40
))
:
'
#ededed
'
),
.
attr
(
'
title
'
,
stamp
=>
formatTooltipText
(
stamp
))
)
.
attr
(
'
class
'
,
'
user-contrib-cell js-tooltip
'
)
.
attr
(
'
title
'
,
stamp
=>
formatTooltipText
(
stamp
))
.
attr
(
'
data-container
'
,
'
body
'
)
.
attr
(
'
class
'
,
'
user-contrib-cell js-tooltip
'
)
.
on
(
'
click
'
,
this
.
clickDay
);
.
attr
(
'
data-container
'
,
'
body
'
)
.
on
(
'
click
'
,
this
.
clickDay
);
}
}
renderDayTitles
()
{
renderDayTitles
()
{
const
days
=
[
const
days
=
[
{
{
text
:
'
M
'
,
text
:
'
M
'
,
y
:
29
+
(
this
.
daySizeWithSpace
*
1
),
y
:
29
+
this
.
dayYPos
(
1
),
},
{
},
{
text
:
'
W
'
,
text
:
'
W
'
,
y
:
29
+
(
this
.
daySizeWithSpace
*
3
),
y
:
29
+
this
.
dayYPos
(
2
),
},
{
},
{
text
:
'
F
'
,
text
:
'
F
'
,
y
:
29
+
(
this
.
daySizeWithSpace
*
5
),
y
:
29
+
this
.
dayYPos
(
3
),
},
},
];
];
this
.
svg
.
append
(
'
g
'
)
this
.
svg
.
append
(
'
g
'
)
.
selectAll
(
'
text
'
)
.
selectAll
(
'
text
'
)
.
data
(
days
)
.
data
(
days
)
.
enter
()
.
enter
()
.
append
(
'
text
'
)
.
append
(
'
text
'
)
.
attr
(
'
text-anchor
'
,
'
middle
'
)
.
attr
(
'
text-anchor
'
,
'
middle
'
)
.
attr
(
'
x
'
,
8
)
.
attr
(
'
x
'
,
8
)
.
attr
(
'
y
'
,
day
=>
day
.
y
)
.
attr
(
'
y
'
,
day
=>
day
.
y
)
.
text
(
day
=>
day
.
text
)
.
text
(
day
=>
day
.
text
)
.
attr
(
'
class
'
,
'
user-contrib-text
'
);
.
attr
(
'
class
'
,
'
user-contrib-text
'
);
}
}
renderMonths
()
{
renderMonths
()
{
this
.
svg
.
append
(
'
g
'
)
this
.
svg
.
append
(
'
g
'
)
.
attr
(
'
direction
'
,
'
ltr
'
)
.
attr
(
'
direction
'
,
'
ltr
'
)
.
selectAll
(
'
text
'
)
.
selectAll
(
'
text
'
)
.
data
(
this
.
months
)
.
data
(
this
.
months
)
.
enter
()
.
enter
()
.
append
(
'
text
'
)
.
append
(
'
text
'
)
.
attr
(
'
x
'
,
date
=>
date
.
x
)
.
attr
(
'
x
'
,
date
=>
date
.
x
)
.
attr
(
'
y
'
,
10
)
.
attr
(
'
y
'
,
10
)
.
attr
(
'
class
'
,
'
user-contrib-text
'
)
.
attr
(
'
class
'
,
'
user-contrib-text
'
)
.
text
(
date
=>
this
.
monthNames
[
date
.
month
]);
.
text
(
date
=>
this
.
monthNames
[
date
.
month
]);
}
}
renderKey
()
{
renderKey
()
{
const
keyValues
=
[
'
no contributions
'
,
'
1-9 contributions
'
,
'
10-19 contributions
'
,
'
20-29 contributions
'
,
'
30+ contributions
'
];
const
keyValues
=
[
const
keyColors
=
[
'
#ededed
'
,
this
.
colorKey
(
0
),
this
.
colorKey
(
1
),
this
.
colorKey
(
2
),
this
.
colorKey
(
3
)];
'
no contributions
'
,
'
1-9 contributions
'
,
'
10-19 contributions
'
,
'
20-29 contributions
'
,
'
30+ contributions
'
,
];
const
keyColors
=
[
'
#ededed
'
,
this
.
colorKey
(
0
),
this
.
colorKey
(
1
),
this
.
colorKey
(
2
),
this
.
colorKey
(
3
),
];
this
.
svg
.
append
(
'
g
'
)
this
.
svg
.
attr
(
'
transform
'
,
`translate(18,
${(
this
.
daySizeWithSpace
*
8
)
+
16
}
)`
)
.
append
(
'
g
'
)
.
attr
(
'
transform
'
,
`translate(18,
${
this
.
daySizeWithSpace
*
8
+
16
}
)`
)
.
selectAll
(
'
rect
'
)
.
selectAll
(
'
rect
'
)
.
data
(
keyColors
)
.
data
(
keyColors
)
.
enter
()
.
enter
()
.
append
(
'
rect
'
)
.
append
(
'
rect
'
)
.
attr
(
'
width
'
,
this
.
daySize
)
.
attr
(
'
width
'
,
this
.
daySize
)
.
attr
(
'
height
'
,
this
.
daySize
)
.
attr
(
'
height
'
,
this
.
daySize
)
.
attr
(
'
x
'
,
(
color
,
i
)
=>
this
.
daySizeWithSpace
*
i
)
.
attr
(
'
x
'
,
(
color
,
i
)
=>
this
.
daySizeWithSpace
*
i
)
.
attr
(
'
y
'
,
0
)
.
attr
(
'
y
'
,
0
)
.
attr
(
'
fill
'
,
color
=>
color
)
.
attr
(
'
fill
'
,
color
=>
color
)
.
attr
(
'
class
'
,
'
js-tooltip
'
)
.
attr
(
'
class
'
,
'
js-tooltip
'
)
.
attr
(
'
title
'
,
(
color
,
i
)
=>
keyValues
[
i
])
.
attr
(
'
title
'
,
(
color
,
i
)
=>
keyValues
[
i
])
.
attr
(
'
data-container
'
,
'
body
'
);
.
attr
(
'
data-container
'
,
'
body
'
);
}
}
initColor
()
{
initColor
()
{
const
colorRange
=
[
'
#ededed
'
,
this
.
colorKey
(
0
),
this
.
colorKey
(
1
),
this
.
colorKey
(
2
),
this
.
colorKey
(
3
)];
const
colorRange
=
[
return
d3
.
scaleThreshold
().
domain
([
0
,
10
,
20
,
30
]).
range
(
colorRange
);
'
#ededed
'
,
this
.
colorKey
(
0
),
this
.
colorKey
(
1
),
this
.
colorKey
(
2
),
this
.
colorKey
(
3
),
];
return
d3
.
scaleThreshold
()
.
domain
([
0
,
10
,
20
,
30
])
.
range
(
colorRange
);
}
}
clickDay
(
stamp
)
{
clickDay
(
stamp
)
{
...
@@ -227,14 +281,15 @@ export default class ActivityCalendar {
...
@@ -227,14 +281,15 @@ export default class ActivityCalendar {
$
(
'
.user-calendar-activities
'
).
html
(
LOADING_HTML
);
$
(
'
.user-calendar-activities
'
).
html
(
LOADING_HTML
);
axios
.
get
(
this
.
calendarActivitiesPath
,
{
axios
params
:
{
.
get
(
this
.
calendarActivitiesPath
,
{
date
,
params
:
{
},
date
,
responseType
:
'
text
'
,
},
})
responseType
:
'
text
'
,
.
then
(({
data
})
=>
$
(
'
.user-calendar-activities
'
).
html
(
data
))
})
.
catch
(()
=>
flash
(
__
(
'
An error occurred while retrieving calendar activity
'
)));
.
then
(({
data
})
=>
$
(
'
.user-calendar-activities
'
).
html
(
data
))
.
catch
(()
=>
flash
(
__
(
'
An error occurred while retrieving calendar activity
'
)));
}
else
{
}
else
{
this
.
currentSelectedDate
=
''
;
this
.
currentSelectedDate
=
''
;
$
(
'
.user-calendar-activities
'
).
html
(
''
);
$
(
'
.user-calendar-activities
'
).
html
(
''
);
...
...
changelogs/unreleased/jivl-refactor-activity-calendar.yml
0 → 100644
View file @
9451a82f
---
title
:
Refactored activity calendar
merge_request
:
18469
author
:
Enrico Scholz
type
:
changed
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