From a68a2306e47f59865f134ef3f2bda6d54c5ee972 Mon Sep 17 00:00:00 2001 From: Constance Okoghenun Date: Thu, 15 Feb 2018 23:07:04 +0000 Subject: Remove Webpack bundle tag for users:show --- app/assets/javascripts/dispatcher.js | 5 - .../javascripts/pages/users/activity_calendar.js | 242 +++++++++++++++++++++ app/assets/javascripts/pages/users/index.js | 27 +++ app/assets/javascripts/pages/users/show/index.js | 3 - app/assets/javascripts/pages/users/user_tabs.js | 199 +++++++++++++++++ app/assets/javascripts/users/activity_calendar.js | 242 --------------------- app/assets/javascripts/users/index.js | 25 --- app/assets/javascripts/users/user_tabs.js | 199 ----------------- app/views/users/show.html.haml | 3 - config/webpack.config.js | 1 - 10 files changed, 468 insertions(+), 478 deletions(-) create mode 100644 app/assets/javascripts/pages/users/activity_calendar.js create mode 100644 app/assets/javascripts/pages/users/index.js delete mode 100644 app/assets/javascripts/pages/users/show/index.js create mode 100644 app/assets/javascripts/pages/users/user_tabs.js delete mode 100644 app/assets/javascripts/users/activity_calendar.js delete mode 100644 app/assets/javascripts/users/index.js delete mode 100644 app/assets/javascripts/users/user_tabs.js diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index e4288dc1317..8f708dde063 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -467,11 +467,6 @@ var Dispatcher; .then(callDefault) .catch(fail); break; - case 'users:show': - import('./pages/users/show') - .then(callDefault) - .catch(fail); - break; case 'admin:conversational_development_index:show': import('./pages/admin/conversational_development_index/show') .then(callDefault) diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js new file mode 100644 index 00000000000..57306322aa4 --- /dev/null +++ b/app/assets/javascripts/pages/users/activity_calendar.js @@ -0,0 +1,242 @@ +import _ from 'underscore'; +import { scaleLinear, scaleThreshold } from 'd3-scale'; +import { select } from 'd3-selection'; +import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility'; +import axios from '~/lib/utils/axios_utils'; +import flash from '~/flash'; +import { __ } from '~/locale'; + +const d3 = { select, scaleLinear, scaleThreshold }; + +const LOADING_HTML = ` +
+ +
+`; + +function getSystemDate(systemUtcOffsetSeconds) { + const date = new Date(); + const localUtcOffsetMinutes = 0 - date.getTimezoneOffset(); + const systemUtcOffsetMinutes = systemUtcOffsetSeconds / 60; + date.setMinutes((date.getMinutes() - localUtcOffsetMinutes) + systemUtcOffsetMinutes); + return date; +} + +function formatTooltipText({ date, count }) { + const dateObject = new Date(date); + const dateDayName = getDayName(dateObject); + const dateText = dateObject.format('mmm d, yyyy'); + + let contribText = 'No contributions'; + if (count > 0) { + contribText = `${count} contribution${count > 1 ? 's' : ''}`; + } + return `${contribText}
${dateDayName} ${dateText}`; +} + +const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]); + +export default class ActivityCalendar { + constructor(container, timestamps, calendarActivitiesPath, utcOffset = 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.months = []; + + // 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 + this.timestampsTmp = []; + let group = 0; + + const today = getSystemDate(utcOffset); + today.setHours(0, 0, 0, 0, 0); + + const oneYearAgo = new Date(today); + oneYearAgo.setFullYear(today.getFullYear() - 1); + + const days = getDayDifference(oneYearAgo, today); + + for (let i = 0; i <= days; i += 1) { + const date = new Date(oneYearAgo); + date.setDate(date.getDate() + i); + + const day = date.getDay(); + const count = timestamps[date.format('yyyy-mm-dd')] || 0; + + // 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) { + this.timestampsTmp.push([]); + group += 1; + } + + // Push to the inner array the values that will be used to render map + const innerArray = this.timestampsTmp[group - 1]; + innerArray.push({ count, date, day }); + } + + // Init color functions + this.colorKey = initColorKey(); + this.color = this.initColor(); + + // Init the svg element + this.svg = this.renderSvg(container, group); + this.renderDays(); + this.renderMonths(); + this.renderDayTitles(); + this.renderKey(); + + // Init tooltips + $(`${container} .js-tooltip`).tooltip({ html: true }); + } + + // Add extra padding for the last month label if it is also the last column + getExtraWidthPadding(group) { + let extraWidthPadding = 0; + const lastColMonth = this.timestampsTmp[group - 1][0].date.getMonth(); + const secondLastColMonth = this.timestampsTmp[group - 2][0].date.getMonth(); + + if (lastColMonth !== secondLastColMonth) { + extraWidthPadding = 6; + } + + return extraWidthPadding; + } + + renderSvg(container, group) { + 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'); + } + + renderDays() { + 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 lastMonth = _.last(this.months); + if ( + lastMonth == null || + (month !== lastMonth.month && x - this.daySizeWithSpace !== lastMonth.x) + ) { + this.months.push({ month, x }); + } + } + }); + 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); + } + + renderDayTitles() { + const days = [ + { + text: 'M', + y: 29 + (this.daySizeWithSpace * 1), + }, { + text: 'W', + y: 29 + (this.daySizeWithSpace * 3), + }, { + text: 'F', + y: 29 + (this.daySizeWithSpace * 5), + }, + ]; + 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'); + } + + renderMonths() { + 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]); + } + + 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)]; + + 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'); + } + + 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); + } + + clickDay(stamp) { + if (this.currentSelectedDate !== stamp.date) { + this.currentSelectedDate = stamp.date; + + const date = [ + this.currentSelectedDate.getFullYear(), + this.currentSelectedDate.getMonth() + 1, + this.currentSelectedDate.getDate(), + ].join('-'); + + $('.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'))); + } else { + this.currentSelectedDate = ''; + $('.user-calendar-activities').html(''); + } + } +} diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js new file mode 100644 index 00000000000..899dcd42e37 --- /dev/null +++ b/app/assets/javascripts/pages/users/index.js @@ -0,0 +1,27 @@ +import UserCallout from '~/user_callout'; +import Cookies from 'js-cookie'; +import UserTabs from './user_tabs'; + +function initUserProfile(action) { + // place profile avatars to top + $('.profile-groups-avatars').tooltip({ + placement: 'top', + }); + + // eslint-disable-next-line no-new + new UserTabs({ parentEl: '.user-profile', action }); + + // hide project limit message + $('.hide-project-limit-message').on('click', (e) => { + e.preventDefault(); + Cookies.set('hide_project_limit_message', 'false'); + $(this).parents('.project-limit-message').remove(); + }); +} + +document.addEventListener('DOMContentLoaded', () => { + const page = $('body').attr('data-page'); + const action = page.split(':')[1]; + initUserProfile(action); + new UserCallout(); // eslint-disable-line no-new +}); diff --git a/app/assets/javascripts/pages/users/show/index.js b/app/assets/javascripts/pages/users/show/index.js deleted file mode 100644 index f18f98b4e9a..00000000000 --- a/app/assets/javascripts/pages/users/show/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import UserCallout from '~/user_callout'; - -export default () => new UserCallout(); diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js new file mode 100644 index 00000000000..c1217623467 --- /dev/null +++ b/app/assets/javascripts/pages/users/user_tabs.js @@ -0,0 +1,199 @@ +import axios from '~/lib/utils/axios_utils'; +import Activities from '~/activities'; +import { localTimeAgo } from '~/lib/utils/datetime_utility'; +import { __ } from '~/locale'; +import flash from '~/flash'; +import ActivityCalendar from './activity_calendar'; + +/** + * UserTabs + * + * Handles persisting and restoring the current tab selection and lazily-loading + * content on the Users#show page. + * + * ### Example Markup + * + * + * + *
+ *
+ * Activity Content + *
+ *
+ * Groups Content + *
+ *
+ * Contributed projects content + *
+ *
+ * Projects content + *
+ *
+ * Snippets content + *
+ *
+ * + *
+ *
+ * Loading Animation + *
+ *
+ */ + +const CALENDAR_TEMPLATE = ` +
+
+
+ Summary of issues, merge requests, push events, and comments +
+
+`; + +export default class UserTabs { + constructor({ defaultAction, action, parentEl }) { + this.loaded = {}; + this.defaultAction = defaultAction || 'activity'; + this.action = action || this.defaultAction; + this.$parentEl = $(parentEl) || $(document); + this.windowLocation = window.location; + this.$parentEl.find('.nav-links a') + .each((i, navLink) => { + this.loaded[$(navLink).attr('data-action')] = false; + }); + this.actions = Object.keys(this.loaded); + this.bindEvents(); + + if (this.action === 'show') { + this.action = this.defaultAction; + } + + this.activateTab(this.action); + } + + bindEvents() { + this.$parentEl + .off('shown.bs.tab', '.nav-links a[data-toggle="tab"]') + .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event)) + .on('click', '.gl-pagination a', event => this.changeProjectsPage(event)); + } + + changeProjectsPage(e) { + e.preventDefault(); + + $('.tab-pane.active').empty(); + const endpoint = $(e.target).attr('href'); + this.loadTab(this.getCurrentAction(), endpoint); + } + + tabShown(event) { + const $target = $(event.target); + const action = $target.data('action'); + const source = $target.attr('href'); + const endpoint = $target.data('endpoint'); + this.setTab(action, endpoint); + return this.setCurrentAction(source); + } + + activateTab(action) { + return this.$parentEl.find(`.nav-links .js-${action}-tab a`) + .tab('show'); + } + + setTab(action, endpoint) { + if (this.loaded[action]) { + return; + } + if (action === 'activity') { + this.loadActivities(); + } + + const loadableActions = ['groups', 'contributed', 'projects', 'snippets']; + if (loadableActions.indexOf(action) > -1) { + this.loadTab(action, endpoint); + } + } + + loadTab(action, endpoint) { + this.toggleLoading(true); + + return axios.get(endpoint) + .then(({ data }) => { + const tabSelector = `div#${action}`; + this.$parentEl.find(tabSelector).html(data.html); + this.loaded[action] = true; + localTimeAgo($('.js-timeago', tabSelector)); + + this.toggleLoading(false); + }) + .catch(() => { + this.toggleLoading(false); + }); + } + + loadActivities() { + if (this.loaded.activity) { + return; + } + const $calendarWrap = this.$parentEl.find('.user-calendar'); + const calendarPath = $calendarWrap.data('calendarPath'); + const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath'); + const utcOffset = $calendarWrap.data('utcOffset'); + let utcFormatted = 'UTC'; + if (utcOffset !== 0) { + utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${(utcOffset / 3600)}`; + } + + axios.get(calendarPath) + .then(({ data }) => { + $calendarWrap.html(CALENDAR_TEMPLATE); + $calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`); + + // eslint-disable-next-line no-new + new ActivityCalendar('.js-contrib-calendar', data, calendarActivitiesPath, utcOffset); + }) + .catch(() => flash(__('There was an error loading users activity calendar.'))); + + // eslint-disable-next-line no-new + new Activities(); + this.loaded.activity = true; + } + + toggleLoading(status) { + return this.$parentEl.find('.loading-status .loading') + .toggle(status); + } + + setCurrentAction(source) { + let newState = source; + newState = newState.replace(/\/+$/, ''); + newState += this.windowLocation.search + this.windowLocation.hash; + history.replaceState({ + url: newState, + }, document.title, newState); + return newState; + } + + getCurrentAction() { + return this.$parentEl.find('.nav-links .active a').data('action'); + } +} diff --git a/app/assets/javascripts/users/activity_calendar.js b/app/assets/javascripts/users/activity_calendar.js deleted file mode 100644 index 57306322aa4..00000000000 --- a/app/assets/javascripts/users/activity_calendar.js +++ /dev/null @@ -1,242 +0,0 @@ -import _ from 'underscore'; -import { scaleLinear, scaleThreshold } from 'd3-scale'; -import { select } from 'd3-selection'; -import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility'; -import axios from '~/lib/utils/axios_utils'; -import flash from '~/flash'; -import { __ } from '~/locale'; - -const d3 = { select, scaleLinear, scaleThreshold }; - -const LOADING_HTML = ` -
- -
-`; - -function getSystemDate(systemUtcOffsetSeconds) { - const date = new Date(); - const localUtcOffsetMinutes = 0 - date.getTimezoneOffset(); - const systemUtcOffsetMinutes = systemUtcOffsetSeconds / 60; - date.setMinutes((date.getMinutes() - localUtcOffsetMinutes) + systemUtcOffsetMinutes); - return date; -} - -function formatTooltipText({ date, count }) { - const dateObject = new Date(date); - const dateDayName = getDayName(dateObject); - const dateText = dateObject.format('mmm d, yyyy'); - - let contribText = 'No contributions'; - if (count > 0) { - contribText = `${count} contribution${count > 1 ? 's' : ''}`; - } - return `${contribText}
${dateDayName} ${dateText}`; -} - -const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]); - -export default class ActivityCalendar { - constructor(container, timestamps, calendarActivitiesPath, utcOffset = 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.months = []; - - // 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 - this.timestampsTmp = []; - let group = 0; - - const today = getSystemDate(utcOffset); - today.setHours(0, 0, 0, 0, 0); - - const oneYearAgo = new Date(today); - oneYearAgo.setFullYear(today.getFullYear() - 1); - - const days = getDayDifference(oneYearAgo, today); - - for (let i = 0; i <= days; i += 1) { - const date = new Date(oneYearAgo); - date.setDate(date.getDate() + i); - - const day = date.getDay(); - const count = timestamps[date.format('yyyy-mm-dd')] || 0; - - // 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) { - this.timestampsTmp.push([]); - group += 1; - } - - // Push to the inner array the values that will be used to render map - const innerArray = this.timestampsTmp[group - 1]; - innerArray.push({ count, date, day }); - } - - // Init color functions - this.colorKey = initColorKey(); - this.color = this.initColor(); - - // Init the svg element - this.svg = this.renderSvg(container, group); - this.renderDays(); - this.renderMonths(); - this.renderDayTitles(); - this.renderKey(); - - // Init tooltips - $(`${container} .js-tooltip`).tooltip({ html: true }); - } - - // Add extra padding for the last month label if it is also the last column - getExtraWidthPadding(group) { - let extraWidthPadding = 0; - const lastColMonth = this.timestampsTmp[group - 1][0].date.getMonth(); - const secondLastColMonth = this.timestampsTmp[group - 2][0].date.getMonth(); - - if (lastColMonth !== secondLastColMonth) { - extraWidthPadding = 6; - } - - return extraWidthPadding; - } - - renderSvg(container, group) { - 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'); - } - - renderDays() { - 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 lastMonth = _.last(this.months); - if ( - lastMonth == null || - (month !== lastMonth.month && x - this.daySizeWithSpace !== lastMonth.x) - ) { - this.months.push({ month, x }); - } - } - }); - 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); - } - - renderDayTitles() { - const days = [ - { - text: 'M', - y: 29 + (this.daySizeWithSpace * 1), - }, { - text: 'W', - y: 29 + (this.daySizeWithSpace * 3), - }, { - text: 'F', - y: 29 + (this.daySizeWithSpace * 5), - }, - ]; - 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'); - } - - renderMonths() { - 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]); - } - - 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)]; - - 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'); - } - - 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); - } - - clickDay(stamp) { - if (this.currentSelectedDate !== stamp.date) { - this.currentSelectedDate = stamp.date; - - const date = [ - this.currentSelectedDate.getFullYear(), - this.currentSelectedDate.getMonth() + 1, - this.currentSelectedDate.getDate(), - ].join('-'); - - $('.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'))); - } else { - this.currentSelectedDate = ''; - $('.user-calendar-activities').html(''); - } - } -} diff --git a/app/assets/javascripts/users/index.js b/app/assets/javascripts/users/index.js deleted file mode 100644 index 9fd8452a2b6..00000000000 --- a/app/assets/javascripts/users/index.js +++ /dev/null @@ -1,25 +0,0 @@ -import Cookies from 'js-cookie'; -import UserTabs from './user_tabs'; - -function initUserProfile(action) { - // place profile avatars to top - $('.profile-groups-avatars').tooltip({ - placement: 'top', - }); - - // eslint-disable-next-line no-new - new UserTabs({ parentEl: '.user-profile', action }); - - // hide project limit message - $('.hide-project-limit-message').on('click', (e) => { - e.preventDefault(); - Cookies.set('hide_project_limit_message', 'false'); - $(this).parents('.project-limit-message').remove(); - }); -} - -document.addEventListener('DOMContentLoaded', () => { - const page = $('body').attr('data-page'); - const action = page.split(':')[1]; - initUserProfile(action); -}); diff --git a/app/assets/javascripts/users/user_tabs.js b/app/assets/javascripts/users/user_tabs.js deleted file mode 100644 index e13b9839a20..00000000000 --- a/app/assets/javascripts/users/user_tabs.js +++ /dev/null @@ -1,199 +0,0 @@ -import axios from '../lib/utils/axios_utils'; -import Activities from '../activities'; -import ActivityCalendar from './activity_calendar'; -import { localTimeAgo } from '../lib/utils/datetime_utility'; -import { __ } from '../locale'; -import flash from '../flash'; - -/** - * UserTabs - * - * Handles persisting and restoring the current tab selection and lazily-loading - * content on the Users#show page. - * - * ### Example Markup - * - * - * - *
- *
- * Activity Content - *
- *
- * Groups Content - *
- *
- * Contributed projects content - *
- *
- * Projects content - *
- *
- * Snippets content - *
- *
- * - *
- *
- * Loading Animation - *
- *
- */ - -const CALENDAR_TEMPLATE = ` -
-
-
- Summary of issues, merge requests, push events, and comments -
-
-`; - -export default class UserTabs { - constructor({ defaultAction, action, parentEl }) { - this.loaded = {}; - this.defaultAction = defaultAction || 'activity'; - this.action = action || this.defaultAction; - this.$parentEl = $(parentEl) || $(document); - this.windowLocation = window.location; - this.$parentEl.find('.nav-links a') - .each((i, navLink) => { - this.loaded[$(navLink).attr('data-action')] = false; - }); - this.actions = Object.keys(this.loaded); - this.bindEvents(); - - if (this.action === 'show') { - this.action = this.defaultAction; - } - - this.activateTab(this.action); - } - - bindEvents() { - this.$parentEl - .off('shown.bs.tab', '.nav-links a[data-toggle="tab"]') - .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event)) - .on('click', '.gl-pagination a', event => this.changeProjectsPage(event)); - } - - changeProjectsPage(e) { - e.preventDefault(); - - $('.tab-pane.active').empty(); - const endpoint = $(e.target).attr('href'); - this.loadTab(this.getCurrentAction(), endpoint); - } - - tabShown(event) { - const $target = $(event.target); - const action = $target.data('action'); - const source = $target.attr('href'); - const endpoint = $target.data('endpoint'); - this.setTab(action, endpoint); - return this.setCurrentAction(source); - } - - activateTab(action) { - return this.$parentEl.find(`.nav-links .js-${action}-tab a`) - .tab('show'); - } - - setTab(action, endpoint) { - if (this.loaded[action]) { - return; - } - if (action === 'activity') { - this.loadActivities(); - } - - const loadableActions = ['groups', 'contributed', 'projects', 'snippets']; - if (loadableActions.indexOf(action) > -1) { - this.loadTab(action, endpoint); - } - } - - loadTab(action, endpoint) { - this.toggleLoading(true); - - return axios.get(endpoint) - .then(({ data }) => { - const tabSelector = `div#${action}`; - this.$parentEl.find(tabSelector).html(data.html); - this.loaded[action] = true; - localTimeAgo($('.js-timeago', tabSelector)); - - this.toggleLoading(false); - }) - .catch(() => { - this.toggleLoading(false); - }); - } - - loadActivities() { - if (this.loaded.activity) { - return; - } - const $calendarWrap = this.$parentEl.find('.user-calendar'); - const calendarPath = $calendarWrap.data('calendarPath'); - const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath'); - const utcOffset = $calendarWrap.data('utcOffset'); - let utcFormatted = 'UTC'; - if (utcOffset !== 0) { - utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${(utcOffset / 3600)}`; - } - - axios.get(calendarPath) - .then(({ data }) => { - $calendarWrap.html(CALENDAR_TEMPLATE); - $calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`); - - // eslint-disable-next-line no-new - new ActivityCalendar('.js-contrib-calendar', data, calendarActivitiesPath, utcOffset); - }) - .catch(() => flash(__('There was an error loading users activity calendar.'))); - - // eslint-disable-next-line no-new - new Activities(); - this.loaded.activity = true; - } - - toggleLoading(status) { - return this.$parentEl.find('.loading-status .loading') - .toggle(status); - } - - setCurrentAction(source) { - let newState = source; - newState = newState.replace(/\/+$/, ''); - newState += this.windowLocation.search + this.windowLocation.hash; - history.replaceState({ - url: newState, - }, document.title, newState); - return newState; - } - - getCurrentAction() { - return this.$parentEl.find('.nav-links .active a').data('action'); - } -} diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index c9a77d668a2..a396d1007a7 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -4,9 +4,6 @@ - page_description @user.bio - header_title @user.name, user_path(@user) - @no_container = true -- content_for :page_specific_javascripts do - = webpack_bundle_tag 'common_d3' - = webpack_bundle_tag 'users' = content_for :meta_tags do = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") diff --git a/config/webpack.config.js b/config/webpack.config.js index 3fff808f166..3c581a156dd 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -99,7 +99,6 @@ var config = { vue_merge_request_widget: './vue_merge_request_widget/index.js', test: './test.js', two_factor_auth: './two_factor_auth.js', - users: './users/index.js', webpack_runtime: './webpack.js', }, -- cgit v1.2.1