BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
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
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
61b71fae
Commit
61b71fae
authored
Apr 19, 2018
by
Clement Ho
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'jivl-refactor-activity-calendar' into 'master'
Refactored activity calendar See merge request gitlab-org/gitlab-ce!18469
parents
31d242d8
9451a82f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
135 additions
and
75 deletions
+135
-75
activity_calendar.js
app/assets/javascripts/pages/users/activity_calendar.js
+130
-75
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 @
61b71fae
...
...
@@ -19,7 +19,7 @@ function getSystemDate(systemUtcOffsetSeconds) {
const
date
=
new
Date
();
const
localUtcOffsetMinutes
=
0
-
date
.
getTimezoneOffset
();
const
systemUtcOffsetMinutes
=
systemUtcOffsetSeconds
/
60
;
date
.
setMinutes
(
(
date
.
getMinutes
()
-
localUtcOffsetMinutes
)
+
systemUtcOffsetMinutes
);
date
.
setMinutes
(
date
.
getMinutes
()
-
localUtcOffsetMinutes
+
systemUtcOffsetMinutes
);
return
date
;
}
...
...
@@ -35,18 +35,36 @@ function formatTooltipText({ date, count }) {
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
{
constructor
(
container
,
timestamps
,
calendarActivitiesPath
,
utcOffset
=
0
)
{
constructor
(
container
,
timestamps
,
calendarActivitiesPath
,
utcOffset
=
0
,
firstDayOfWeek
=
0
)
{
this
.
calendarActivitiesPath
=
calendarActivitiesPath
;
this
.
clickDay
=
this
.
clickDay
.
bind
(
this
);
this
.
currentSelectedDate
=
''
;
this
.
daySpace
=
1
;
this
.
daySize
=
15
;
this
.
daySizeWithSpace
=
this
.
daySize
+
(
this
.
daySpace
*
2
);
this
.
monthNames
=
[
'Jan'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
];
this
.
daySizeWithSpace
=
this
.
daySize
+
this
.
daySpace
*
2
;
this
.
monthNames
=
[
'Jan'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
,
];
this
.
months
=
[];
this
.
firstDayOfWeek
=
firstDayOfWeek
;
// 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
...
...
@@ -70,7 +88,7 @@ export default class ActivityCalendar {
// Create a new group array if this is the first day of the week
// or if is first object
if
((
day
===
0
&&
i
!==
0
)
||
i
===
0
)
{
if
((
day
===
this
.
firstDayOfWeek
&&
i
!==
0
)
||
i
===
0
)
{
this
.
timestampsTmp
.
push
([]);
group
+=
1
;
}
...
...
@@ -109,21 +127,30 @@ export default class ActivityCalendar {
}
renderSvg
(
container
,
group
)
{
const
width
=
((
group
+
1
)
*
this
.
daySizeWithSpace
)
+
this
.
getExtraWidthPadding
(
group
);
return
d3
.
select
(
container
)
const
width
=
(
group
+
1
)
*
this
.
daySizeWithSpace
+
this
.
getExtraWidthPadding
(
group
);
return
d3
.
select
(
container
)
.
append
(
'svg'
)
.
attr
(
'width'
,
width
)
.
attr
(
'height'
,
167
)
.
attr
(
'class'
,
'contrib-calendar'
);
.
attr
(
'width'
,
width
)
.
attr
(
'height'
,
167
)
.
attr
(
'class'
,
'contrib-calendar'
);
}
dayYPos
(
day
)
{
return
this
.
daySizeWithSpace
*
((
day
+
7
-
this
.
firstDayOfWeek
)
%
7
);
}
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
)
=>
{
_
.
each
(
group
,
(
stamp
,
a
)
=>
{
if
(
a
===
0
&&
stamp
.
day
===
0
)
{
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
);
if
(
lastMonth
==
null
||
...
...
@@ -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'
)
.
data
(
stamp
=>
stamp
)
.
enter
()
.
append
(
'rect'
)
.
attr
(
'x'
,
'0'
)
.
attr
(
'y'
,
stamp
=>
this
.
daySizeWithSpace
*
stamp
.
day
)
.
attr
(
'width'
,
this
.
daySize
)
.
attr
(
'height'
,
this
.
daySize
)
.
attr
(
'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
(
'data-container'
,
'body'
)
.
on
(
'click'
,
this
.
clickDay
);
.
data
(
stamp
=>
stamp
)
.
enter
()
.
append
(
'rect'
)
.
attr
(
'x'
,
'0'
)
.
attr
(
'y'
,
stamp
=>
this
.
dayYPos
(
stamp
.
day
))
.
attr
(
'width'
,
this
.
daySize
)
.
attr
(
'height'
,
this
.
daySize
)
.
attr
(
'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
(
'data-container'
,
'body'
)
.
on
(
'click'
,
this
.
clickDay
);
}
renderDayTitles
()
{
const
days
=
[
{
text
:
'M'
,
y
:
29
+
(
this
.
daySizeWithSpace
*
1
),
},
{
y
:
29
+
this
.
dayYPos
(
1
),
},
{
text
:
'W'
,
y
:
29
+
(
this
.
daySizeWithSpace
*
3
),
},
{
y
:
29
+
this
.
dayYPos
(
2
),
},
{
text
:
'F'
,
y
:
29
+
(
this
.
daySizeWithSpace
*
5
),
y
:
29
+
this
.
dayYPos
(
3
),
},
];
this
.
svg
.
append
(
'g'
)
this
.
svg
.
append
(
'g'
)
.
selectAll
(
'text'
)
.
data
(
days
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'x'
,
8
)
.
attr
(
'y'
,
day
=>
day
.
y
)
.
text
(
day
=>
day
.
text
)
.
attr
(
'class'
,
'user-contrib-text'
);
.
data
(
days
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'x'
,
8
)
.
attr
(
'y'
,
day
=>
day
.
y
)
.
text
(
day
=>
day
.
text
)
.
attr
(
'class'
,
'user-contrib-text'
);
}
renderMonths
()
{
this
.
svg
.
append
(
'g'
)
this
.
svg
.
append
(
'g'
)
.
attr
(
'direction'
,
'ltr'
)
.
selectAll
(
'text'
)
.
data
(
this
.
months
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'x'
,
date
=>
date
.
x
)
.
attr
(
'y'
,
10
)
.
attr
(
'class'
,
'user-contrib-text'
)
.
text
(
date
=>
this
.
monthNames
[
date
.
month
]);
.
data
(
this
.
months
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'x'
,
date
=>
date
.
x
)
.
attr
(
'y'
,
10
)
.
attr
(
'class'
,
'user-contrib-text'
)
.
text
(
date
=>
this
.
monthNames
[
date
.
month
]);
}
renderKey
()
{
const
keyValues
=
[
'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
)];
const
keyValues
=
[
'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'
)
.
attr
(
'transform'
,
`translate(18,
${(
this
.
daySizeWithSpace
*
8
)
+
16
}
)`
)
this
.
svg
.
append
(
'g'
)
.
attr
(
'transform'
,
`translate(18,
${
this
.
daySizeWithSpace
*
8
+
16
}
)`
)
.
selectAll
(
'rect'
)
.
data
(
keyColors
)
.
enter
()
.
append
(
'rect'
)
.
attr
(
'width'
,
this
.
daySize
)
.
attr
(
'height'
,
this
.
daySize
)
.
attr
(
'x'
,
(
color
,
i
)
=>
this
.
daySizeWithSpace
*
i
)
.
attr
(
'y'
,
0
)
.
attr
(
'fill'
,
color
=>
color
)
.
attr
(
'class'
,
'js-tooltip'
)
.
attr
(
'title'
,
(
color
,
i
)
=>
keyValues
[
i
])
.
attr
(
'data-container'
,
'body'
);
.
data
(
keyColors
)
.
enter
()
.
append
(
'rect'
)
.
attr
(
'width'
,
this
.
daySize
)
.
attr
(
'height'
,
this
.
daySize
)
.
attr
(
'x'
,
(
color
,
i
)
=>
this
.
daySizeWithSpace
*
i
)
.
attr
(
'y'
,
0
)
.
attr
(
'fill'
,
color
=>
color
)
.
attr
(
'class'
,
'js-tooltip'
)
.
attr
(
'title'
,
(
color
,
i
)
=>
keyValues
[
i
])
.
attr
(
'data-container'
,
'body'
);
}
initColor
()
{
const
colorRange
=
[
'#ededed'
,
this
.
colorKey
(
0
),
this
.
colorKey
(
1
),
this
.
colorKey
(
2
),
this
.
colorKey
(
3
)];
return
d3
.
scaleThreshold
().
domain
([
0
,
10
,
20
,
30
]).
range
(
colorRange
);
const
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
)
{
...
...
@@ -227,14 +281,15 @@ export default class ActivityCalendar {
$
(
'.user-calendar-activities'
).
html
(
LOADING_HTML
);
axios
.
get
(
this
.
calendarActivitiesPath
,
{
params
:
{
date
,
},
responseType
:
'text'
,
})
.
then
(({
data
})
=>
$
(
'.user-calendar-activities'
).
html
(
data
))
.
catch
(()
=>
flash
(
__
(
'An error occurred while retrieving calendar activity'
)));
axios
.
get
(
this
.
calendarActivitiesPath
,
{
params
:
{
date
,
},
responseType
:
'text'
,
})
.
then
(({
data
})
=>
$
(
'.user-calendar-activities'
).
html
(
data
))
.
catch
(()
=>
flash
(
__
(
'An error occurred while retrieving calendar activity'
)));
}
else
{
this
.
currentSelectedDate
=
''
;
$
(
'.user-calendar-activities'
).
html
(
''
);
...
...
changelogs/unreleased/jivl-refactor-activity-calendar.yml
0 → 100644
View file @
61b71fae
---
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