Project-Timeline: Introduced timeline on projects

Limited to projects of category assets and film for now.
This commit is contained in:
Tobias Johansson 2018-11-20 16:29:01 +01:00
parent 1d909faf49
commit fc99713732
10 changed files with 94 additions and 17 deletions

View File

@ -250,7 +250,7 @@ def global_timeline():
return _global_timeline(continue_from, nbr_of_weeks, sort_direction) return _global_timeline(continue_from, nbr_of_weeks, sort_direction)
@blueprint.route('/p/<string(length=24):str_pid>', methods=['GET']) @blueprint.route('/p/<string(length=24):pid_path>', methods=['GET'])
def project_timeline(pid_path: str): def project_timeline(pid_path: str):
continue_from_str = request.args.get('from') continue_from_str = request.args.get('from')
continue_from = parse_continue_from(continue_from_str) continue_from = parse_continue_from(continue_from_str)

View File

@ -0,0 +1 @@
export { transformPlaceholder } from './utils/placeholder'

View File

@ -0,0 +1,15 @@
/**
* Fade out placeholder, then call callback.
* Note that the placeholder will not be removed, and will not be keeped hidden. The caller decides what to do with
* the placeholder.
* @param {jQueryObject} $placeholder
* @param {callback} cb
*/
export function transformPlaceholder($placeholder, cb) {
$placeholder.addClass('placeholder replaced')
.delay(250)
.queue(()=>{
$placeholder.removeClass('placeholder replaced');
cb();
})
}

View File

@ -1 +1,7 @@
export { Timeline } from './timeline/timeline'; export { Timeline } from './timeline/timeline';
// Init timelines on document ready
$(function() {
$(".timeline")
.timeline();
})

View File

@ -17,30 +17,51 @@
* continue_from: 123456.2 // python timestamp * continue_from: 123456.2 // python timestamp
* } * }
*/ */
const DEFAULT_URL = '/api/timeline';
const transformPlaceholder = pillar.utils.transformPlaceholder;
class Timeline { class Timeline {
constructor(target, params, builder) { constructor(target, builder) {
this._$targetDom = $(target) this._$targetDom = $(target);
this._url = params['url']; this._url;
this._queryParams = params['queryParams'] || {}; this._queryParams = {};
this._builder = builder; this._builder = builder;
this._init(); this._init();
} }
_init() { _init() {
this._workStart(); this._workStart();
this._setUrl();
this._setQueryParams();
this._thenLoadMore() this._thenLoadMore()
.then((it)=>{ .then((it)=>{
this._$targetDom.empty(); transformPlaceholder(this._$targetDom, () => {
this._$targetDom.append(it); this._$targetDom.empty()
if (this._hasMore()) { .append(it);
let btn = this._create$LoadMoreBtn(); if (this._hasMore()) {
this._$targetDom.append(btn); let btn = this._create$LoadMoreBtn();
} this._$targetDom.append(btn);
}
})
}) })
.always(this._workStop.bind(this)); .always(this._workStop.bind(this));
} }
_setUrl() {
let projectId = this._$targetDom.data('project-id');
this._url = DEFAULT_URL
if (projectId) {
this._url += '/p/' + projectId
}
}
_setQueryParams() {
let sortDirection = this._$targetDom.data('sort-dir');
if (sortDirection) {
this._queryParams['dir'] = sortDirection;
}
}
_loadMore(event) { _loadMore(event) {
let $spinner = $('<i>').addClass('pi-spin spinner'); let $spinner = $('<i>').addClass('pi-spin spinner');
let $loadmoreBtn = $(event.target) let $loadmoreBtn = $(event.target)
@ -122,6 +143,7 @@ class GroupBuilder {
content = content.concat(group['groups'].map(this.build$Group.bind(this, level+1))); content = content.concat(group['groups'].map(this.build$Group.bind(this, level+1)));
} }
return $('<div>') return $('<div>')
.addClass('group')
.append( .append(
$label, $label,
content content
@ -167,10 +189,9 @@ class GroupBuilder {
} }
$.fn.extend({ $.fn.extend({
timeline: function(params) { timeline: function() {
this.each(function(i, target) { this.each(function(i, target) {
new Timeline(target, new Timeline(target,
params || {},
new GroupBuilder() new GroupBuilder()
); );
}); });

View File

@ -306,6 +306,12 @@
100% 100%
transform: scale(1.0) transform: scale(1.0)
@keyframes fade-in
0%
opacity: 0
100%
opacity: 1
@keyframes grow-bounce-out @keyframes grow-bounce-out
0 0
transform: scale(1.0) transform: scale(1.0)

View File

@ -0,0 +1,6 @@
.placeholder
+pulse-75
&.replaced // added before replaced
opacity: 0
transition: 250ms

View File

@ -15,10 +15,17 @@
margin-right: -15px margin-right: -15px
margin-left: -15px margin-left: -15px
padding-right: 15px padding-right: 15px
.sticky-top
top: 2.5rem .group
opacity: 0
animation: fade-in 500ms forwards
body.homepage
.timeline
.sticky-top
top: 2.5rem
body.is-mobile body.is-mobile
.timeline .timeline
.js-asset-list .js-asset-list
@extend .card-deck-vertical @extend .card-deck-vertical

View File

@ -73,3 +73,15 @@ mixin list-asset(name, url, image, type, date)
if block if block
block block
// used together with timeline.js
mixin timeline(projectid, sortdirection)
section.timeline.placeholder(
data-project-id=projectid,
data-sort-dir=sortdirection,
)
// TODO: Make nicer reuseable placeholder
.h1.text-center
i.pi-spin.spin

View File

@ -40,6 +40,9 @@ section.px-4
| {% endif %} | {% endif %}
| {% endfor %} | {% endfor %}
| {% endif %} | {% endif %}
| {% if project.category in ['film', 'assets'] %}
+timeline("{{ project._id }}")
| {% endif %}
include _scripts include _scripts