diff --git a/pillar/api/timeline.py b/pillar/api/timeline.py index 6735ec08..602275e5 100644 --- a/pillar/api/timeline.py +++ b/pillar/api/timeline.py @@ -250,7 +250,7 @@ def global_timeline(): return _global_timeline(continue_from, nbr_of_weeks, sort_direction) -@blueprint.route('/p/', methods=['GET']) +@blueprint.route('/p/', methods=['GET']) def project_timeline(pid_path: str): continue_from_str = request.args.get('from') continue_from = parse_continue_from(continue_from_str) diff --git a/src/scripts/js/es6/common/utils.js b/src/scripts/js/es6/common/utils.js new file mode 100644 index 00000000..15c2a56f --- /dev/null +++ b/src/scripts/js/es6/common/utils.js @@ -0,0 +1 @@ +export { transformPlaceholder } from './utils/placeholder' \ No newline at end of file diff --git a/src/scripts/js/es6/common/utils/placeholder.js b/src/scripts/js/es6/common/utils/placeholder.js new file mode 100644 index 00000000..b2bb162a --- /dev/null +++ b/src/scripts/js/es6/common/utils/placeholder.js @@ -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(); + }) +} \ No newline at end of file diff --git a/src/scripts/js/es6/individual/timeline.js b/src/scripts/js/es6/individual/timeline.js index b5788a9f..22142634 100644 --- a/src/scripts/js/es6/individual/timeline.js +++ b/src/scripts/js/es6/individual/timeline.js @@ -1 +1,7 @@ -export { Timeline } from './timeline/timeline'; \ No newline at end of file +export { Timeline } from './timeline/timeline'; + +// Init timelines on document ready +$(function() { + $(".timeline") + .timeline(); +}) \ No newline at end of file diff --git a/src/scripts/js/es6/individual/timeline/timeline.js b/src/scripts/js/es6/individual/timeline/timeline.js index 00c50aea..b91b1964 100644 --- a/src/scripts/js/es6/individual/timeline/timeline.js +++ b/src/scripts/js/es6/individual/timeline/timeline.js @@ -17,30 +17,51 @@ * continue_from: 123456.2 // python timestamp * } */ +const DEFAULT_URL = '/api/timeline'; +const transformPlaceholder = pillar.utils.transformPlaceholder; class Timeline { - constructor(target, params, builder) { - this._$targetDom = $(target) - this._url = params['url']; - this._queryParams = params['queryParams'] || {}; + constructor(target, builder) { + this._$targetDom = $(target); + this._url; + this._queryParams = {}; this._builder = builder; this._init(); } _init() { this._workStart(); + this._setUrl(); + this._setQueryParams(); this._thenLoadMore() .then((it)=>{ - this._$targetDom.empty(); - this._$targetDom.append(it); - if (this._hasMore()) { - let btn = this._create$LoadMoreBtn(); - this._$targetDom.append(btn); - } + transformPlaceholder(this._$targetDom, () => { + this._$targetDom.empty() + .append(it); + if (this._hasMore()) { + let btn = this._create$LoadMoreBtn(); + this._$targetDom.append(btn); + } + }) }) .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) { let $spinner = $('').addClass('pi-spin spinner'); let $loadmoreBtn = $(event.target) @@ -122,6 +143,7 @@ class GroupBuilder { content = content.concat(group['groups'].map(this.build$Group.bind(this, level+1))); } return $('
') + .addClass('group') .append( $label, content @@ -167,10 +189,9 @@ class GroupBuilder { } $.fn.extend({ - timeline: function(params) { + timeline: function() { this.each(function(i, target) { new Timeline(target, - params || {}, new GroupBuilder() ); }); diff --git a/src/styles/_utils.sass b/src/styles/_utils.sass index 8781a85d..c2da6d83 100644 --- a/src/styles/_utils.sass +++ b/src/styles/_utils.sass @@ -306,6 +306,12 @@ 100% transform: scale(1.0) +@keyframes fade-in + 0% + opacity: 0 + 100% + opacity: 1 + @keyframes grow-bounce-out 0 transform: scale(1.0) diff --git a/src/styles/components/_placeholder.sass b/src/styles/components/_placeholder.sass new file mode 100644 index 00000000..98464775 --- /dev/null +++ b/src/styles/components/_placeholder.sass @@ -0,0 +1,6 @@ +.placeholder + +pulse-75 + + &.replaced // added before replaced + opacity: 0 + transition: 250ms \ No newline at end of file diff --git a/src/styles/components/_timeline.sass b/src/styles/components/_timeline.sass index 1c56d5ae..1bb18c7e 100644 --- a/src/styles/components/_timeline.sass +++ b/src/styles/components/_timeline.sass @@ -15,10 +15,17 @@ margin-right: -15px margin-left: -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 .timeline .js-asset-list - @extend .card-deck-vertical \ No newline at end of file + @extend .card-deck-vertical diff --git a/src/templates/mixins/components.pug b/src/templates/mixins/components.pug index ba9195f0..7145937b 100644 --- a/src/templates/mixins/components.pug +++ b/src/templates/mixins/components.pug @@ -73,3 +73,15 @@ mixin list-asset(name, url, image, type, date) if 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 + + + diff --git a/src/templates/projects/view_embed.pug b/src/templates/projects/view_embed.pug index 9b164cfc..d9384780 100644 --- a/src/templates/projects/view_embed.pug +++ b/src/templates/projects/view_embed.pug @@ -40,6 +40,9 @@ section.px-4 | {% endif %} | {% endfor %} | {% endif %} + | {% if project.category in ['film', 'assets'] %} + +timeline("{{ project._id }}") + | {% endif %} include _scripts