{ "version": 3, "sources": ["../../../../../../internal/esbuild/entrypoints/legacy/stats.js", "../../src/legacy/stats.es6.js", "../../src/legacy/highcharts/themes/hcgroupedcolumns.es6.js", "../../src/legacy/react/stats/utils/poller.es6.js", "../../src/legacy/react/stats/utils/odo.es6.js", "../../src/legacy/react/stats/components/stats.js", "../../src/legacy/react/stats/components/LinearTableView.js", "../../src/legacy/react/stats/components/HeaderView.js", "../../src/legacy/react/stats/components/RowView.js", "../../src/legacy/react/stats/components/ItemView.js", "../../src/legacy/react/stats/components/ComparisonTableView.js", "../../src/legacy/react/stats/components/LabelView.js", "../../src/legacy/react/stats/components/ColumnView.js", "../../src/legacy/react/stats/components/DataView.js"], "sourcesContent": ["import 'lib:../../../../src/ulule/static/site/public/libs/moment.min.cjs'\nimport 'lib:../../../../src/ulule/static/site/public/libs/moment-with-langs.min.cjs'\nimport 'lib:../../../../src/ulule/static/site/public/libs/highcharts.cjs'\nimport 'lib:../../../../src/ulule/static/site/public/libs/highcharts-grouped-categories.cjs'\nimport '../../../../src/ulule/static/site/src/legacy/stats.es6.js'\nimport '../../../../src/ulule/static/site/src/legacy/react/stats/utils/odo.es6.js'\nimport 'lib:../../../../src/ulule/static/site/public/libs/bootstrap-dropdown.js'\nimport 'lib:../../../../src/ulule/static/site/public/libs/odometer.min.js'\nimport '../../../../src/ulule/static/site/src/legacy/react/stats/components/stats.js'\n", "'use strict';\n\nimport accounting from 'accounting'\nimport HCBaseTheme from './highcharts/hcbasetheme.es6.js';\nimport HCAreaSpline from './highcharts/themes/hcareaspline.es6.js';\nimport HCSplineColumn from './highcharts/themes/hcsplinecolumn.es6.js';\nimport HCGroupedColumns from './highcharts/themes/hcgroupedcolumns.es6.js';\nimport Poller from './react/stats/utils/poller.es6.js';\nimport Odo from './react/stats/utils/odo.es6.js';\n\nwindow.accounting = accounting\nwindow.Swipe = Swipe\n\n/*global Odometer, Poller, window */\nclass Stats {\n constructor(options) {\n if (!options.url) {\n console.log('[Stats] Cannot init, no URL');\n return null;\n }\n\n this.url = options.url;\n this.dataset = options.data;\n this.currentLang = options.langCode;\n this.translations = options.translations || {};\n this.showLastMonth = options.showLastMonth || false;\n\n this.datum = [];\n this.graphs = {};\n this.odometers = {};\n\n this.currency = options.currentCurrency;\n\n this.hcwrapper = new HCBaseTheme();\n\n this._initPoller();\n this._initOdometers();\n this._drawCharts()\n this._updateTextData();\n\n Stats.reloadSprites();\n\n this._handleCurrencyChange();\n }\n\n static pluralize(singular, plural, count) {\n return (count === 1) ? singular : plural;\n }\n\n static reloadSprites() {\n let sprites = document.querySelectorAll('main i');\n\n [].forEach.call(sprites, (sprite, index) => {\n if (window.innerWidth <= 320) {\n sprite.className = 'sprite-stats-' + sprite.className;\n } else {\n sprite.className = 'sprite-stats-big-' + sprite.className;\n }\n });\n }\n\n static sortObject(source) {\n let keys = [];\n let result = {};\n\n for (let key in source) {\n if (source.hasOwnProperty(key)) {\n keys.push(key);\n }\n }\n\n keys.sort();\n\n $.each(keys, (i, key) => {\n result[key] = source[key];\n });\n\n return result;\n }\n\n static selectPeriod(endDate, period, datum) {\n let selection = [];\n\n const startDate = moment(endDate).subtract('months', period).toDate();\n const years = Stats.sortObject(Stats.parseSelection(startDate, endDate, datum));\n\n for (const year in years) {\n selection.push({key: year, value: years[year]})\n }\n\n return selection;\n }\n\n static parseSelection(first, current, datum) {\n const firstYear = first.getFullYear();\n const firstMonth = first.getMonth() + 1;\n const currentYear = current.getFullYear();\n const currentMonth = current.getMonth() + 1;\n\n let months = [];\n let years = {};\n\n var entry = {};\n\n let selectMonths = function(range) {\n if (entry.year === currentYear) {\n if (range.month <= currentMonth) {\n return range;\n }\n }\n else if (entry.year === firstYear) {\n if (range.month >= firstMonth) {\n return range;\n }\n }\n else {\n return range;\n }\n };\n\n for (let i = 0; i < datum.length; ++i) {\n entry = datum[i];\n\n if (entry.year >= firstYear && entry.year <= currentYear) {\n months = entry.months.filter(selectMonths);\n years[entry.year] = months;\n } else {\n continue;\n }\n }\n\n return years;\n }\n\n static flatten(array, callback) {\n let result = [];\n\n for (let i = 0; i < array.length; ++i) {\n const year = array[i];\n for (let j = 0; j < year.value.length; ++j) {\n const month = year.value[j];\n callback(result, year, month);\n }\n }\n\n return result;\n }\n\n static combine(date, value) {\n let res = [];\n\n for (let i = 0, len = value.length; i < len; ++i) {\n const obj = {\n 'date': date[i],\n 'value': value[i]\n };\n res.push(obj);\n }\n\n return res;\n }\n\n _handleCurrencyChange() {\n let currenciesSelectors = $('.currency-selector span');\n\n currenciesSelectors.on('click', ((e) => {\n let selector = $(e.target);\n let selectedCurrency = selector.attr(\"data-currency\");\n\n if (selectedCurrency === this.currency) return;\n\n this.currency = selectedCurrency;\n $('.currency-selector span').removeClass('active');\n selector.addClass('active');\n\n accounting.settings.currency.symbol = selector.text();\n\n this.cumulCollectedFundsChartUpdate();\n\n this._updateTextData();\n this.odometers.collectedFunds.update(this.dataset.amount_raised[this.currency]);\n\n document.querySelector('#graph-cumul-collected-funds header span').textContent = accounting.formatMoney(this.dataset.amount_raised[this.currency]);\n }).bind(this))\n }\n\n _setFlatten(selection, callback) {\n return Stats.combine(\n Stats.flatten(selection, ((result, year, month) => {\n let date = new Date(parseInt(year.key, 10), parseInt(month.month, 10) - 1, 1);\n date.label = month.languages_abbrv[this.currentLang];\n date.legend = month.languages[this.currentLang];\n\n result.push(date);\n }).bind(this)),\n Stats.flatten(selection, (result, year, month) => {\n result.push(callback(month));\n })\n );\n }\n\n cumulCollectedFundsChart(selection) {\n const data = this._setFlatten(selection, (m) => {\n return [m.amount_raised_cumulated[this.currency], m.amount_raised[this.currency]];\n });\n\n let chart = new HCAreaSpline($('#graph-cumul-collected-funds > .graph-container.chart'));\n\n chart.setAdditionalOptions({\n chart: {\n height: 320\n },\n xAxis: {\n labels: {\n style: {\n color: 'transparent',\n fontSize: '3px'\n }\n },\n categories: selection.map((entry, index) => {\n return {\n name: entry.key,\n categories: entry.value.map((entry, index) => {\n return entry.languages[this.currentLang];\n })\n }\n })\n },\n yAxis: {\n labels: {\n formatter() {\n return accounting.formatMoney(this.value);\n }\n }\n },\n tooltip: {\n formatter() {\n const cumul = accounting.formatMoney(this.y);\n const diff = accounting.formatMoney(data[this.point.index].value[1]);\n return `
${this.x}
\n${cumul}
\n${diff}
`\n }\n },\n series: [{\n data: data.map((entry, index) => {\n return entry.value[0];\n })\n }]\n })\n .drawChart();\n\n this.graphs.cumulCollectedFundsChart = chart;\n }\n\n cumulCollectedFundsChartUpdate() {\n const selection = Stats.selectPeriod(moment().toDate(), 36, this.datum);\n\n const data = this._setFlatten(selection, (m) => {\n return [m.amount_raised_cumulated[this.currency], m.amount_raised[this.currency]];\n });\n\n this.graphs.cumulCollectedFundsChart.chart.series[0].setData(data.map((entry, index) => {\n return entry.value[0]\n }));\n }\n\n collectedFundsChart(selection, showLastMonth) {\n const data = this._setFlatten(selection, (m) => {\n return m.amount_raised[this.currency];\n });\n\n let chart = new HCSplineColumn($('#graph-collected-funds > .graph-container.chart'));\n\n chart.setAdditionalOptions({\n xAxis: {\n labels: {\n style: {\n color: 'transparent',\n fontSize: '3px'\n }\n },\n categories: selection.map((entry, index) => {\n return {\n name: entry.key,\n categories: entry.value.map((entry, index) => {\n return entry.languages[this.currentLang];\n })\n }\n })\n },\n yAxis: [{\n labels: {\n formatter() {\n return accounting.formatMoney(this.value);\n }\n }\n }, {}],\n tooltip: {\n formatter() {\n const value = accounting.formatMoney(this.y);\n return `${this.x}
\n${value}
`;\n }\n },\n series: [{\n data: data.map((entry, index) => {\n return entry.value;\n })\n }, {\n data: data.map((entry, index) => {\n return entry.value;\n })\n }]\n })\n .drawChart();\n\n this.graphs.collectedFundsChart = chart;\n }\n\n presalesChart(selection) {\n const data = this._setFlatten(selection, (m) => {\n return m.contributions_count;\n });\n\n let chart = new HCAreaSpline($('#graph-presales > .graph-container.chart'));\n\n chart.setAdditionalOptions({\n xAxis: {\n categories: data.map((entry, index) => {\n return entry.date.label;\n })\n },\n yAxis: {\n labels: {\n formatter() {\n return accounting.formatNumber(this.value);\n }\n }\n },\n tooltip: {\n formatter: HCBaseTheme.simpleFormattedNumberTooltip\n },\n series: [{\n data: data.map((entry, index) => {\n return entry.value;\n })\n }]\n })\n .drawChart();\n }\n\n projectsCountChart(selection) {\n const data = this._setFlatten(selection, (m) => {\n return [m.projects_started_count, m.projects_success_count, m.projects_success_percent];\n });\n\n let chart = new HCGroupedColumns($('#graph-projects > .graph-container.chart'));\n\n chart.setAdditionalOptions({\n xAxis: {\n categories: data.map((entry, index) => {\n return entry.date.label;\n })\n },\n tooltip: {\n formatter: HCBaseTheme.groupedColumnsTooltip\n },\n series: [{\n translations: this.translations.started,\n data: data.map((entry, index) => {\n return entry.value[0];\n })\n }, {\n translations: this.translations.funded,\n data: data.map((entry, index) => {\n return entry.value[1];\n })\n }]\n })\n .drawChart();\n }\n\n proposalsCountChart(selection) {\n const data = this._setFlatten(selection, (m) => {\n return [m.proposals_started_count, m.proposals_accepted_count, m.proposals_accepted_percent];\n });\n\n let chart = new HCGroupedColumns($('#graph-proposals > .graph-container.chart'));\n\n chart.setAdditionalOptions({\n xAxis: {\n categories: data.map((entry, index) => {\n return entry.date.label;\n })\n },\n tooltip: {\n formatter: HCBaseTheme.groupedColumnsTooltip\n },\n series: [{\n translations: this.translations.started,\n data: data.map((entry, index) => {\n return entry.value[0];\n })\n }, {\n translations: this.translations.accepted,\n data: data.map((entry, index) => {\n return entry.value[1];\n })\n }]\n })\n .drawChart();\n }\n\n _initPoller() {\n let plr = new Poller({\n url: this.url,\n onSuccess: ((s) => {\n this.odometers.collectedFunds.update(s.amount_raised[this.currency]);\n this.odometers.projectsFunded.update(s.projects_success_count);\n this.odometers.projectsFunding.update(s.projects_started_count);\n this.odometers.totalMembers.update(s.users_count);\n }).bind(this),\n maxRetries: 3,\n pollTime: 30000\n });\n }\n\n _drawCharts() {\n this.datum = this.dataset.years.slice().reverse();\n const endDate = moment().toDate();\n\n if (document.querySelector('#graph-cumul-collected-funds') !== null) {\n const selection = Stats.selectPeriod(endDate, 36, this.datum);\n this.cumulCollectedFundsChart(selection);\n document.querySelector('#graph-cumul-collected-funds header span').textContent = accounting.formatMoney(this.dataset.amount_raised[this.currency]);\n }\n\n if (document.querySelector('#graph-presales') !== null) {\n const selection = Stats.selectPeriod(endDate, 12, this.datum);\n this.presalesChart(selection);\n document.querySelector('#graph-presales header span').textContent = accounting.formatNumber(this.dataset.contributions_count);\n }\n\n if (document.querySelector('#graph-projects') !== null) {\n const selection = Stats.selectPeriod(endDate, 12, this.datum);\n this.projectsCountChart(selection);\n document.querySelector('#graph-projects .graph-selector .started span').textContent = accounting.formatNumber(this.dataset.projects_started_count);\n document.querySelector('#graph-projects .graph-selector .funded span').textContent = accounting.formatNumber(this.dataset.projects_success_count);\n }\n\n if (document.querySelector('#graph-proposals') !== null) {\n const selection = Stats.selectPeriod(endDate, 12, this.datum);\n this.proposalsCountChart(selection);\n document.querySelector('#graph-proposals .graph-selector .accepted span').textContent = accounting.formatNumber(this.dataset.proposals_accepted_count);\n document.querySelector('#graph-proposals .graph-selector .started span').textContent = accounting.formatNumber(this.dataset.proposals_started_count);\n }\n }\n\n _initOdometers() {\n this.odometers.collectedFunds = new Odo('#counter-collected-funds .stats-counter', {\n duration: 1600,\n format: '( ddd),dd',\n value: this.dataset.amount_raised[this.currency]\n });\n\n this.odometers.successRate = new Odo('#counter-success-rate .stats-counter', {\n duration: 1400,\n format: '',\n value: Math.round(this.dataset.years[(this.dataset.years.length - 1)].projects_success_percent)\n });\n\n this.odometers.projectsFunded = new Odo('#counter-projects-funded .stats-counter', {\n duration: 1800,\n format: '( ddd),dd',\n value: this.dataset.projects_success_count\n });\n\n this.odometers.projectsFunding = new Odo('#counter-projects-funding .stats-counter', {\n duration: 2400,\n format: '( ddd),dd',\n value: this.dataset.projects_started_count\n });\n\n this.odometers.totalMembers = new Odo('#counter-total-members .stats-counter', {\n duration: 2200,\n format: '( ddd),dd',\n value: this.dataset.users_count\n });\n }\n\n _updateTextData() {\n document.querySelector('#contrib-moy').textContent = accounting.formatMoney(this.dataset.amount_avg[this.currency]);\n document.querySelector('#current_year').textContent = this.dataset.years[(this.dataset.years.length - 1)].year;\n document.querySelector('#total-members').textContent = accounting.formatNumber(this.dataset.users_count);\n\n const currency = this.dataset.currencies.find(currency => currency.value === this.currency);\n if (currency) {\n document.querySelector('#counter-collected-funds .currency-value').textContent = currency.label;\n }\n }\n}\n\nexport default Stats;\n\nwindow.Stats = Stats;\n", "'use strict';\n\nimport HCBaseTheme from '../hcbasetheme.es6.js';\n\nclass HCGroupedColumns extends HCBaseTheme {\n constructor(container) {\n super();\n\n this.container = container;\n\n this.options = {\n chart: {\n type: 'column'\n },\n plotOptions: {\n series: {\n point: {\n events: {\n mouseOver() {\n HCGroupedColumns._changeColumnColor($(container), '#18A5D6', '#0071A4', this);\n },\n mouseOut() {\n HCGroupedColumns._changeColumnColor($(container), '#F0F0F0', '#D5D5D5', this);\n }\n }\n },\n states: {\n hover: {\n enabled: false\n }\n }\n }\n },\n series: [{\n color: '#F0F0F0',\n stack: 'left'\n }, {\n color: '#D5D5D5',\n stack: 'right'\n }]\n };\n }\n\n drawChart() {\n super.drawChart(this.container, this.options);\n return this;\n }\n\n static _changeColumnColor(container, firstColor, secondColor, self) {\n let chart = container.highcharts();\n chart.series[0].data[self.x].graphic.attr({ fill: firstColor });\n chart.series[1].data[self.x].graphic.attr({ fill: secondColor });\n }\n}\n\nexport default HCGroupedColumns;\n", "'use strict';\n/**\n * @desc (Object) Options object\n * @TODO Add XHR support :)\n*/\nclass Poller {\n constructor(options) {\n if (!options || !options.url) {\n console.log('[Poller] Missing options or URL.');\n return null;\n }\n\n this.url = options.url;\n\n this.maxRetries = options.maxRetries === undefined ? 3 : options.maxRetries;\n this.retryInterval = options.retryInterval || 1000;\n this.pollTime = options.pollTime || 10000;\n this.onSuccess = options.onSuccess || null;\n this.onError = options.onError || null;\n this.onPoll = options.onPoll || null;\n this.onFail = options.onFail || null;\n\n // Inner state\n this.failed = false;\n this.polling = false;\n this.failCount = 0;\n this.pollTimer = null;\n\n // Save options if we need em someday, dunno, bbq dawg\n this.options = options;\n\n this.create();\n }\n\n create(interval) {\n interval = interval || 0;\n\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n }\n\n this.pollTimer = setTimeout(() => {\n this.doPoll(this);\n }, this.pollTime + interval);\n }\n\n doPoll(self) {\n this.polling = true;\n\n if (this.onPoll !== null) {\n this.onPoll();\n }\n\n $.getJSON(self.url, (data) => {\n self.doSuccess(data);\n }).fail((data) => {\n self.doRetry(data);\n });\n }\n\n doRetry(e) {\n this.polling = false;\n\n if (this.failCount === this.maxRetries) {\n console.log(`[Poller] URL exceeded maxRetries (${this.maxRetries}), stopping.`);\n this.doFail(e);\n } else {\n console.log(`[Poller] URL failed, retrying (${this.failCount}/${this.maxRetries})`);\n this.create(this.retryInterval);\n }\n\n if (this.onError) {\n this.onError(e);\n }\n\n this.failCount++;\n }\n\n doFail(e) {\n this.failed = true;\n this.polling = false;\n this.remove();\n\n if (this.onFail !== null) {\n this.onFail(e);\n }\n }\n\n doSuccess(s) {\n this.failCount = 0;\n this.polling = false;\n this.create(this.retryInterval);\n\n if (this.onSuccess !== null) {\n this.onSuccess(s);\n }\n }\n\n remove() {\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n }\n}\n\nexport default Poller;\n\nwindow.Poller = Poller;\n", "'use strict';\n/**\n * @desc (String) String for the Odo element\n * @desc (Object) Options object\n * @desc (Function) Overload setup function (Odometer)\n */\nclass Odo {\n constructor(elm, options) {\n if (!elm || !options) {\n return null;\n }\n\n this.elm = document.querySelector(elm);\n this.options = options;\n this.setup();\n }\n\n setup() {\n this.odometer = new Odometer({\n el: this.elm,\n value: 0,\n theme: 'default',\n format: this.options.format || '',\n duration: this.options.duration || '1000'\n });\n\n this.update();\n }\n\n update(v) {\n if (v) {\n this.odometer.update(v);\n } else {\n this.odometer.update(this.options.value);\n }\n }\n}\n\nexport default Odo;\n", "'use strict'\n\nimport * as React from 'react'\nimport * as ReactDOM from 'react-dom/client'\nimport LinearTableView from './LinearTableView.js'\nimport ComparisonTableView from './ComparisonTableView.js'\n\nclass ReactStats extends React.Component {\n constructor(dataset, objects, language, yearLimit) {\n super()\n\n this.dataset = dataset\n this.objects = objects\n this.language = language\n this.sortedCategories = this.dataset.categories.slice().sort((a, b) => b.amount_raised.EUR - a.amount_raised.EUR)\n }\n\n renderYearsTable(container, legend, yearLimit = 5) {\n let years = { ...this.dataset.years }\n\n years = Object.assign([], years).reverse()\n years = Object.values(years).slice(0, yearLimit)\n\n let headers = Object.values(years).map((year) => {\n return year.year\n })\n headers.unshift(legend)\n\n let totals = Object.values(this.objects).map(\n ((object) => {\n return {\n label: object.label,\n data: Object.values(years).map((year) => object.data(year)),\n total: object.total,\n }\n }).bind(this)\n )\n\n for (let i = 0; i < totals.length; ++i) {\n let total = totals[i]\n total.data.unshift(total.total)\n }\n\n const root = ReactDOM.createRoot(container)\n root.render(