From f996c89dfe159b1132f5b4e353992730f59da8d1 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Wed, 27 May 2020 12:59:37 +0200 Subject: [PATCH 1/8] Add localforage, basic cache service --- app/services/browser-cache.js | 25 +++++++++++++++++++++++ app/services/kredits.js | 2 +- package-lock.json | 24 ++++++++++++++++++++++ package.json | 1 + tests/unit/services/browser-cache-test.js | 18 ++++++++++++++++ 5 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 app/services/browser-cache.js create mode 100644 tests/unit/services/browser-cache-test.js diff --git a/app/services/browser-cache.js b/app/services/browser-cache.js new file mode 100644 index 0000000..12506ed --- /dev/null +++ b/app/services/browser-cache.js @@ -0,0 +1,25 @@ +import Service from '@ember/service'; +import * as localforage from 'localforage'; + +function createStore(name) { + return localforage.createInstance({ name: `kredits:${name}` }); +} + +export default class BrowserCacheService extends Service { + + constructor() { + super(...arguments); + this.stores = { + contributors: createStore('contributors'), + contributions: createStore('contributions') + } + } + + get contributors() { + return this.stores.contributors; + } + + get contributions() { + return this.stores.contributions; + } +} diff --git a/app/services/kredits.js b/app/services/kredits.js index bd1b0f5..5ed3942 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -230,7 +230,7 @@ export default Service.extend({ }, getContributions () { - return this.kredits.Contribution.all({page: {size: 200}}) + return this.kredits.Contribution.all({page: {size: 30}}) .then(contributions => { return contributions.map(contribution => { contribution.contributor = this.contributors.findBy('id', contribution.contributorId.toString()); diff --git a/package-lock.json b/package-lock.json index 8c36079..aaac05a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15545,6 +15545,12 @@ "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, "import-fresh": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", @@ -16768,6 +16774,15 @@ } } }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "linkify-it": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", @@ -16849,6 +16864,15 @@ "integrity": "sha512-9M2KvGT6duzGMgkOcTkWb+PR/Q2Oe54df/tLgHGVmFpAmtqJ553xJh6N63iFYI2yjo2PeJXbS5skHi/QpJq4vA==", "dev": true }, + "localforage": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.7.3.tgz", + "integrity": "sha512-1TulyYfc4udS7ECSBT2vwJksWbkwwTX8BzeUIiq8Y07Riy7bDAAnxDaPU/tWyOVmQAcWJIEIFP9lPfBGqVoPgQ==", + "dev": true, + "requires": { + "lie": "3.1.1" + } + }, "locate-character": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-2.0.5.tgz", diff --git a/package.json b/package.json index e87aa72..3ec4ec6 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "kosmos-schemas": "^2.1.0", "kredits-contracts": "^5.5.0", "loader.js": "^4.7.0", + "localforage": "^1.7.3", "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", "npm-run-all": "^4.1.5", "qunit-dom": "^1.2.0", diff --git a/tests/unit/services/browser-cache-test.js b/tests/unit/services/browser-cache-test.js new file mode 100644 index 0000000..6cdd09e --- /dev/null +++ b/tests/unit/services/browser-cache-test.js @@ -0,0 +1,18 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Service | browser-cache', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let service = this.owner.lookup('service:browser-cache'); + assert.ok(service); + }); + + test('creates kredits data stores', function(assert) { + let cache = this.owner.lookup('service:browser-cache'); + assert.equal(cache.contributors._config.name, "kredits:contributors"); + assert.equal(cache.contributions._config.name, "kredits:contributions"); + }); + +}); From 871731110b6aa42a2698e294911259b9bdd352e0 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Wed, 27 May 2020 16:27:08 +0200 Subject: [PATCH 2/8] Process contributor data Add util function for processing contributor data, and remove bignums, etc. --- app/models/contributor.js | 11 ++-- app/services/kredits.js | 5 +- app/utils/process-contributor-data.js | 19 ++++++ tests/fixtures/contributor-data.js | 64 +++++++++++++++++++ tests/fixtures/contributors.js | 6 +- .../utils/process-contributor-data-test.js | 31 +++++++++ 6 files changed, 124 insertions(+), 12 deletions(-) create mode 100644 app/utils/process-contributor-data.js create mode 100644 tests/fixtures/contributor-data.js create mode 100644 tests/unit/utils/process-contributor-data-test.js diff --git a/app/models/contributor.js b/app/models/contributor.js index 76baf08..8e9f39e 100644 --- a/app/models/contributor.js +++ b/app/models/contributor.js @@ -1,14 +1,12 @@ import EmberObject from '@ember/object'; -import bignumber from 'kredits-web/utils/cps/bignumber'; -import kreditsValue from 'kredits-web/utils/cps/kredits'; export default EmberObject.extend({ // Contract - id: bignumber('idRaw', 'toString'), + id: null, account: null, - balance: kreditsValue('balanceRaw'), - totalKreditsEarned: bignumber('totalKreditsEarnedRaw', 'toNumber'), - contributionsCount: bignumber('contributionsCountRaw', 'toNumber'), + balance: 0, + totalKreditsEarned: 0, + contributionsCount: 0, isCore: false, ipfsHash: null, @@ -20,6 +18,5 @@ export default EmberObject.extend({ github_uid: null, wiki_username: null, zoom_display_name: null, - ipfsData: '' }); diff --git a/app/services/kredits.js b/app/services/kredits.js index 5ed3942..06d8d3f 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -9,6 +9,7 @@ import { alias, notEmpty } from '@ember/object/computed'; import { isEmpty, isPresent } from '@ember/utils'; import groupBy from 'kredits-web/utils/group-by'; +import processContributorData from 'kredits-web/utils/process-contributor-data'; import formatKredits from 'kredits-web/utils/format-kredits'; import config from 'kredits-web/config/environment'; @@ -208,8 +209,8 @@ export default Service.extend({ getContributors () { return this.kredits.Contributor.all() .then(contributors => { - return contributors.map(contributor => { - return Contributor.create(contributor); + return contributors.map(data => { + return Contributor.create(processContributorData(data)); }); }); }, diff --git a/app/utils/process-contributor-data.js b/app/utils/process-contributor-data.js new file mode 100644 index 0000000..7066f93 --- /dev/null +++ b/app/utils/process-contributor-data.js @@ -0,0 +1,19 @@ +export default function processContributorData(data) { + const processed = { + id: data.id.toString(), + balance: data.balanceInt, + totalKreditsEarned: data.totalKreditsEarned, + contributionsCount: data.contributionsCount.toNumber() + } + + const otherProperties = [ + 'account', 'accounts', 'ipfsHash', 'isCore', 'kind', 'name', 'url', + 'github_username', 'github_uid', 'wiki_username', 'zoom_display_name' + ]; + + otherProperties.forEach(prop => { + processed[prop] = data[prop]; + }); + + return processed; +} diff --git a/tests/fixtures/contributor-data.js b/tests/fixtures/contributor-data.js new file mode 100644 index 0000000..5d7477c --- /dev/null +++ b/tests/fixtures/contributor-data.js @@ -0,0 +1,64 @@ +export default { + "0": 1, + "1": "0x7E8f313C56F809188313aa274Fa67EE58c31515d", + "2": "0x99b8afd7b266e19990924a8be9099e81054b70c36b20937228a77a5cf75723b8", + "3": 18, + "4": 32, + "5": true, + "6": { + "_hex": "0x09979c0838e8fc880000" + }, + "7": 53500, + "8": { + "_hex": "0x49" + }, + "9": true, + "id": 1, + "account": "0x7E8f313C56F809188313aa274Fa67EE58c31515d", + "hashDigest": "0x99b8afd7b266e19990924a8be9099e81054b70c36b20937228a77a5cf75723b8", + "hashFunction": 18, + "hashSize": 32, + "isCore": true, + "balance": { + "_hex": "0x09979c0838e8fc880000" + }, + "totalKreditsEarned": 53500, + "contributionsCount": { + "_hex": "0x49", + "toNumber": function() { return 73; } + }, + "exists": true, + "balanceInt": 45298, + "ipfsHash": "QmYgiRd1FZ7JjDGBwkmLQNF6XQuyF8AWoFDRvUWhhmxiEj", + "name": "Bumi", + "kind": "person", + "url": "https://michaelbumann.com", + "accounts": [ + { + "site": "github.com", + "uid": 318, + "username": "bumi", + "url": "https://github.com/bumi" + }, + { + "site": "gitea.kosmos.org", + "username": "bumi", + "url": "https://gitea.kosmos.org/bumi" + }, + { + "site": "wiki.kosmos.org", + "username": "Bumi", + "url": "https://wiki.kosmos.org/User:Bumi" + }, + { + "site": "zoom.us", + "username": "bumi" + } + ], + "github_uid": 318, + "github_username": "bumi", + "gitea_username": "bumi", + "wiki_username": "Bumi", + "zoom_display_name": "bumi", + "ipfsData": "{\n \"@context\": \"https://schema.kosmos.org\",\n \"@type\": \"Contributor\",\n \"kind\": \"person\",\n \"name\": \"Bumi\",\n \"accounts\": [\n {\n \"site\": \"github.com\",\n \"uid\": 318,\n \"username\": \"bumi\",\n \"url\": \"https://github.com/bumi\"\n },\n {\n \"site\": \"gitea.kosmos.org\",\n \"username\": \"bumi\",\n \"url\": \"https://gitea.kosmos.org/bumi\"\n },\n {\n \"site\": \"wiki.kosmos.org\",\n \"username\": \"Bumi\",\n \"url\": \"https://wiki.kosmos.org/User:Bumi\"\n },\n {\n \"site\": \"zoom.us\",\n \"username\": \"bumi\"\n }\n ],\n \"url\": \"https://michaelbumann.com\"\n}" +} diff --git a/tests/fixtures/contributors.js b/tests/fixtures/contributors.js index 97c0fac..8c8f0ea 100644 --- a/tests/fixtures/contributors.js +++ b/tests/fixtures/contributors.js @@ -3,9 +3,9 @@ import Contributor from 'kredits-web/models/contributor'; const contributors = []; const data = [ - { id: 1, name: 'Bumi', totalKreditsEarned: 11500, github_uid: 318 }, - { id: 2, name: 'Râu Cao', totalKreditsEarned: 3000, github_uid: 842 }, - { id: 3, name: 'Manuel', totalKreditsEarned: 0, github_uid: 54812 } + { id: '1', name: 'Bumi', totalKreditsEarned: 11500, github_uid: 318 }, + { id: '2', name: 'Râu Cao', totalKreditsEarned: 3000, github_uid: 842 }, + { id: '3', name: 'Manuel', totalKreditsEarned: 0, github_uid: 54812 } ]; data.forEach(attrs => contributors.push(Contributor.create(attrs))); diff --git a/tests/unit/utils/process-contributor-data-test.js b/tests/unit/utils/process-contributor-data-test.js new file mode 100644 index 0000000..1d223fb --- /dev/null +++ b/tests/unit/utils/process-contributor-data-test.js @@ -0,0 +1,31 @@ +import { module, test } from 'qunit'; +import processContributorData from 'kredits-web/utils/process-contributor-data'; +import testData from '../../fixtures/contributor-data'; + +module('Unit | Utility | process-contributor-data', function() { + + let result = processContributorData(testData); + + test('formats the data correctly', function(assert) { + // TODO use integers everywhere for IDs + assert.ok(typeof result.id == 'string'); + assert.ok(typeof result.balance == 'number'); + assert.ok(typeof result.totalKreditsEarned == 'number'); + assert.ok(typeof result.contributionsCount == 'number'); + }); + + test('copies other properties', function(assert) { + [ + 'account', 'accounts', 'ipfsHash', 'isCore', 'kind', 'name', 'url', + 'github_username', 'github_uid', 'wiki_username', 'zoom_display_name' + ].forEach(p => { + assert.ok(Object.prototype.hasOwnProperty.call(result, p), `copies property ${p}`); + }) + }); + + test('does not copy unnecessary properties', function(assert) { + ['exists', '5'].forEach(p => { + assert.notOk(Object.prototype.hasOwnProperty.call(result, p)); + }) + }); +}); From 50e1fc728cce709f5b84c34d360f7399878f2707 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Wed, 27 May 2020 17:33:36 +0200 Subject: [PATCH 3/8] Cache contributors in IndexedDB --- app/models/contributor.js | 3 +++ app/services/kredits.js | 22 ++++++++++++++++++---- tests/unit/services/browser-cache-test.js | 1 - 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/models/contributor.js b/app/models/contributor.js index 8e9f39e..67cfa30 100644 --- a/app/models/contributor.js +++ b/app/models/contributor.js @@ -19,4 +19,7 @@ export default EmberObject.extend({ wiki_username: null, zoom_display_name: null, + serialize() { + return JSON.stringify(this); + } }); diff --git a/app/services/kredits.js b/app/services/kredits.js index 06d8d3f..73c4062 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -7,6 +7,7 @@ import EmberObject from '@ember/object'; import { computed } from '@ember/object'; import { alias, notEmpty } from '@ember/object/computed'; import { isEmpty, isPresent } from '@ember/utils'; +import { inject as service } from '@ember/service'; import groupBy from 'kredits-web/utils/group-by'; import processContributorData from 'kredits-web/utils/process-contributor-data'; @@ -18,6 +19,8 @@ import Contribution from 'kredits-web/models/contribution' export default Service.extend({ + browserCache: service(), + currentBlock: null, currentUserAccounts: null, // default to not having an account. this is the wen web3 is loaded. currentUser: null, @@ -172,8 +175,9 @@ export default Service.extend({ loadInitialData () { - return this.getContributors() - .then(contributors => this.contributors.pushObjects(contributors)) + return this.fetchContributors() + // .then(contributors => this.contributors.pushObjects(contributors)) + .then(() => this.cacheContributors()) .then(() => this.getContributions()) .then(contributions => this.contributions.pushObjects(contributions)) }, @@ -206,15 +210,25 @@ export default Service.extend({ }); }, - getContributors () { + fetchContributors () { return this.kredits.Contributor.all() .then(contributors => { return contributors.map(data => { - return Contributor.create(processContributorData(data)); + const contributor = Contributor.create(processContributorData(data)); + this.contributors.pushObject(contributor); + return contributor; }); }); }, + async cacheContributors () { + for (const c of this.contributors) { + await this.browserCache.contributors.setItem(c.id, c.serialize()); + } + console.debug(`[kredits] Cached ${this.contributors.length} contributors in browser storage`); + return Promise.resolve(); + }, + addContribution (attributes) { console.debug('[kredits] add contribution', attributes); diff --git a/tests/unit/services/browser-cache-test.js b/tests/unit/services/browser-cache-test.js index 6cdd09e..7c77937 100644 --- a/tests/unit/services/browser-cache-test.js +++ b/tests/unit/services/browser-cache-test.js @@ -14,5 +14,4 @@ module('Unit | Service | browser-cache', function(hooks) { assert.equal(cache.contributors._config.name, "kredits:contributors"); assert.equal(cache.contributions._config.name, "kredits:contributions"); }); - }); From 832de3c06fafd0340c44edb11d3171e2e59357b1 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 28 May 2020 10:54:38 +0200 Subject: [PATCH 4/8] Load contributors from cache if present And then update from network later --- app/models/contributor.js | 2 +- app/routes/application.js | 6 +++++ app/services/kredits.js | 54 +++++++++++++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/app/models/contributor.js b/app/models/contributor.js index 67cfa30..40f6448 100644 --- a/app/models/contributor.js +++ b/app/models/contributor.js @@ -19,7 +19,7 @@ export default EmberObject.extend({ wiki_username: null, zoom_display_name: null, - serialize() { + serialize () { return JSON.stringify(this); } }); diff --git a/app/routes/application.js b/app/routes/application.js index 85eabe9..eae822b 100644 --- a/app/routes/application.js +++ b/app/routes/application.js @@ -1,5 +1,6 @@ import { inject as service } from '@ember/service'; import Route from '@ember/routing/route'; +import { schedule } from '@ember/runloop'; export default Route.extend({ kredits: service(), @@ -21,6 +22,11 @@ export default Route.extend({ return this.kredits.loadInitialData() .then(() => { this.kredits.addContractEventHandlers(); + }) + .then(() => { + if (this.kredits.contributorsNeedFetch) { + schedule('afterRender', this.kredits, this.kredits.fetchContributors); + } }); } }); diff --git a/app/services/kredits.js b/app/services/kredits.js index 73c4062..2242dc0 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -20,6 +20,8 @@ import Contribution from 'kredits-web/models/contribution' export default Service.extend({ browserCache: service(), + contributorsNeedFetch: false, + contributionsNeedFetch: false, currentBlock: null, currentUserAccounts: null, // default to not having an account. this is the wen web3 is loaded. @@ -173,13 +175,23 @@ export default Service.extend({ .then(total => total.toNumber()); }), + async loadInitialData () { + const numCachedContributors = await this.browserCache.contributors.length(); + if (numCachedContributors > 0) { + await this.loadContributorsFromCache(); + this.set('contributorsNeedFetch', true); + } else { + await this.fetchContributors(); + } - loadInitialData () { - return this.fetchContributors() - // .then(contributors => this.contributors.pushObjects(contributors)) - .then(() => this.cacheContributors()) - .then(() => this.getContributions()) - .then(contributions => this.contributions.pushObjects(contributions)) + const numCachedContributions = await this.browserCache.contributions.length(); + if (numCachedContributions > 0) { + // TODO promises.push(this.loadContributionsFromCache); + } else { + await this.fetchContributions({ page: { size: 30 } }); + } + + return Promise.resolve(); }, addContributor (attributes) { @@ -211,13 +223,19 @@ export default Service.extend({ }, fetchContributors () { + console.debug(`[kredits] Fetching all contributors from the network`); return this.kredits.Contributor.all() .then(contributors => { return contributors.map(data => { const contributor = Contributor.create(processContributorData(data)); + const loadedContributor = this.contributors.findBy('id', contributor.id); + if (loadedContributor) { this.contributors.removeObject(loadedContributor); } this.contributors.pushObject(contributor); return contributor; }); + }) + .then(() => { + return this.cacheContributors(); }); }, @@ -229,6 +247,14 @@ export default Service.extend({ return Promise.resolve(); }, + async loadContributorsFromCache () { + return this.browserCache.contributors.iterate((value, key/* , iterationNumber */) => { + this.contributors.pushObject(Contributor.create(JSON.parse(value))); + }).then(result => { + console.debug(`[kredits] Loaded ${this.contributors.length} contributors from cache`); + }); + }, + addContribution (attributes) { console.debug('[kredits] add contribution', attributes); @@ -244,14 +270,20 @@ export default Service.extend({ }); }, - getContributions () { - return this.kredits.Contribution.all({page: {size: 30}}) + fetchContributions (options = { page: { size: 200 } }) { + console.debug(`[kredits] Fetching contributions from the network`); + return this.kredits.Contribution.all(options) .then(contributions => { - return contributions.map(contribution => { - contribution.contributor = this.contributors.findBy('id', contribution.contributorId.toString()); - return Contribution.create(contribution); + return contributions.map(data => { + data.contributor = this.contributors.findBy('id', data.contributorId.toString()); + const contribution = Contribution.create(data); + this.contributions.pushObject(contribution); + return contribution; }); }); + // TODO .then(() => { + // this.cacheContributions() + // }); }, veto (contributionId) { From e7c9620bbe2a4ea37c7c37feecb78095d2a8a92a Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 28 May 2020 11:53:19 +0200 Subject: [PATCH 5/8] Add network namespace for browser cache We want to be able to cache data from multiple networks side-by-side, without them interfering with each other. --- app/services/browser-cache.js | 4 +++- tests/unit/services/browser-cache-test.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/services/browser-cache.js b/app/services/browser-cache.js index 12506ed..29232dd 100644 --- a/app/services/browser-cache.js +++ b/app/services/browser-cache.js @@ -1,8 +1,10 @@ import Service from '@ember/service'; import * as localforage from 'localforage'; +import config from 'kredits-web/config/environment'; function createStore(name) { - return localforage.createInstance({ name: `kredits:${name}` }); + const networkName = config.web3RequiredNetwork || 'custom'; + return localforage.createInstance({ name: `kredits:${networkName}:${name}` }); } export default class BrowserCacheService extends Service { diff --git a/tests/unit/services/browser-cache-test.js b/tests/unit/services/browser-cache-test.js index 7c77937..a7d6459 100644 --- a/tests/unit/services/browser-cache-test.js +++ b/tests/unit/services/browser-cache-test.js @@ -11,7 +11,7 @@ module('Unit | Service | browser-cache', function(hooks) { test('creates kredits data stores', function(assert) { let cache = this.owner.lookup('service:browser-cache'); - assert.equal(cache.contributors._config.name, "kredits:contributors"); - assert.equal(cache.contributions._config.name, "kredits:contributions"); + assert.equal(cache.contributors._config.name, "kredits:rinkeby:contributors"); + assert.equal(cache.contributions._config.name, "kredits:rinkeby:contributions"); }); }); From 69141a31c44eac9be54d01f63fc2430bf16660c4 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 28 May 2020 13:44:32 +0200 Subject: [PATCH 6/8] Process contribution data before loading models --- app/models/contribution.js | 16 +- app/models/contributor.js | 1 + app/services/kredits.js | 38 +- app/utils/process-contribution-data.js | 21 + app/utils/process-contributor-data.js | 2 +- tests/fixtures/contribution-data.js | 391 ++++++++++++++++++ tests/fixtures/contributions.js | 24 +- tests/fixtures/contributors.js | 6 +- .../utils/process-contribution-data-test.js | 28 ++ .../utils/process-contributor-data-test.js | 8 +- 10 files changed, 501 insertions(+), 34 deletions(-) create mode 100644 app/utils/process-contribution-data.js create mode 100644 tests/fixtures/contribution-data.js create mode 100644 tests/unit/utils/process-contribution-data-test.js diff --git a/app/models/contribution.js b/app/models/contribution.js index 1b89125..3fde117 100644 --- a/app/models/contribution.js +++ b/app/models/contribution.js @@ -1,6 +1,5 @@ import EmberObject, { computed } from '@ember/object'; import { isEmpty, isPresent } from '@ember/utils'; -import bignumber from 'kredits-web/utils/cps/bignumber'; import moment from 'moment'; export default EmberObject.extend({ @@ -9,11 +8,15 @@ export default EmberObject.extend({ id: null, contributorId: null, amount: null, - confirmedAt: bignumber('confirmedAtBlock', 'toNumber'), + confirmedAt: null, vetoed: null, ipfsHash: null, - creatorAccount: null, + // contributor model instance + contributor: null, + + // TODO contributor who submitted the contribution + // submittedBy: null, // IPFS kind: null, @@ -22,7 +25,6 @@ export default EmberObject.extend({ url: null, date: null, time: null, - ipfsData: '', pendingTx: null, @@ -41,6 +43,10 @@ export default EmberObject.extend({ hasPendingChanges: computed('pendingTx', function() { return isPresent(this.pendingTx); - }) + }), + + serialize () { + return JSON.stringify(this); + } }); diff --git a/app/models/contributor.js b/app/models/contributor.js index 40f6448..9485d0f 100644 --- a/app/models/contributor.js +++ b/app/models/contributor.js @@ -22,4 +22,5 @@ export default EmberObject.extend({ serialize () { return JSON.stringify(this); } + }); diff --git a/app/services/kredits.js b/app/services/kredits.js index 2242dc0..313d504 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -11,6 +11,7 @@ import { inject as service } from '@ember/service'; import groupBy from 'kredits-web/utils/group-by'; import processContributorData from 'kredits-web/utils/process-contributor-data'; +import processContributionData from 'kredits-web/utils/process-contribution-data'; import formatKredits from 'kredits-web/utils/format-kredits'; import config from 'kredits-web/config/environment'; @@ -185,11 +186,11 @@ export default Service.extend({ } const numCachedContributions = await this.browserCache.contributions.length(); - if (numCachedContributions > 0) { + // if (numCachedContributions > 0) { // TODO promises.push(this.loadContributionsFromCache); - } else { + // } else { await this.fetchContributions({ page: { size: 30 } }); - } + // } return Promise.resolve(); }, @@ -235,11 +236,11 @@ export default Service.extend({ }); }) .then(() => { - return this.cacheContributors(); + return this.cacheLoadedContributors(); }); }, - async cacheContributors () { + async cacheLoadedContributors () { for (const c of this.contributors) { await this.browserCache.contributors.setItem(c.id, c.serialize()); } @@ -248,9 +249,9 @@ export default Service.extend({ }, async loadContributorsFromCache () { - return this.browserCache.contributors.iterate((value, key/* , iterationNumber */) => { + return this.browserCache.contributors.iterate((value/*, key , iterationNumber */) => { this.contributors.pushObject(Contributor.create(JSON.parse(value))); - }).then(result => { + }).then((/* result */) => { console.debug(`[kredits] Loaded ${this.contributors.length} contributors from cache`); }); }, @@ -275,15 +276,28 @@ export default Service.extend({ return this.kredits.Contribution.all(options) .then(contributions => { return contributions.map(data => { - data.contributor = this.contributors.findBy('id', data.contributorId.toString()); - const contribution = Contribution.create(data); + const contribution = Contribution.create(processContributionData(data)); + contribution.set('contributor', this.contributors.findBy('id', data.contributorId.toString())); this.contributions.pushObject(contribution); return contribution; }); + }) + .then(contributions => { + const cacheWrites = contributions.map(c => { + return this.browserCache.contributions.setItem(c.id.toString(), c.serialize()); + }); + return Promise.all(cacheWrites).then(() => { + console.debug(`[kredits] Cached ${contributions.length} contributions in browser storage`); + }); }); - // TODO .then(() => { - // this.cacheContributions() - // }); + }, + + async cacheLoadedContributions () { + for (const c of this.contributions) { + await this.browserCache.contributions.setItem(c.id, c.serialize()); + } + console.debug(`[kredits] Cached ${this.contributions.length} contributions in browser storage`); + return Promise.resolve(); }, veto (contributionId) { diff --git a/app/utils/process-contribution-data.js b/app/utils/process-contribution-data.js new file mode 100644 index 0000000..0a3f18d --- /dev/null +++ b/app/utils/process-contribution-data.js @@ -0,0 +1,21 @@ +export default function processContributionData(data) { + const processed = {} + + if (data.confirmedAtBlock && (typeof data.confirmedAtBlock.toNumber === 'function')) { + processed.confirmedAt = data.confirmedAtBlock.toNumber(); + } else if (data.confirmedAt !== 'undefined') { + processed.confirmedAt = data.confirmedAt; + } + + const otherProperties = [ + 'id', 'contributorId', 'amount', 'vetoed', + 'ipfsHash', 'kind', 'description', 'details', + 'url', 'date', 'time', 'pendingTx' + ]; + + otherProperties.forEach(prop => { + processed[prop] = data[prop]; + }); + + return processed; +} diff --git a/app/utils/process-contributor-data.js b/app/utils/process-contributor-data.js index 7066f93..48074fb 100644 --- a/app/utils/process-contributor-data.js +++ b/app/utils/process-contributor-data.js @@ -3,7 +3,7 @@ export default function processContributorData(data) { id: data.id.toString(), balance: data.balanceInt, totalKreditsEarned: data.totalKreditsEarned, - contributionsCount: data.contributionsCount.toNumber() + contributionsCount: data.contributionsCount?.toNumber() } const otherProperties = [ diff --git a/tests/fixtures/contribution-data.js b/tests/fixtures/contribution-data.js new file mode 100644 index 0000000..38aa602 --- /dev/null +++ b/tests/fixtures/contribution-data.js @@ -0,0 +1,391 @@ +export default { + "0": 511, + "1": 1, + "2": 500, + "3": false, + "4": "0x4e918f5b0199311fffa2c930cd6ec8e82de65d4caa5a84e6e850c9c956a92ed7", + "5": 18, + "6": 32, + "7": { + "_hex": "0x64bf54" + }, + "8": true, + "9": false, + "id": 511, + "contributorId": 1, + "amount": 500, + "claimed": false, + "hashDigest": "0x4e918f5b0199311fffa2c930cd6ec8e82de65d4caa5a84e6e850c9c956a92ed7", + "hashFunction": 18, + "hashSize": 32, + "confirmedAtBlock": { + "_hex": "0x64bf54", + "toNumber": function() { return 6602580; } + }, + "exists": true, + "vetoed": false, + "ipfsHash": "QmTdMF6u8TBNp2riP43m8p49VxMasS73Qbdj3fSo2V8SJ2", + "date": "2020-05-27", + "time": "14:22:41Z", + "kind": "dev", + "description": "67P/kredits-contracts: Chore/dependency updates", + "details": { + "url": "https://api.github.com/repos/67P/kredits-contracts/pulls/196", + "id": 423708597, + "node_id": "MDExOlB1bGxSZXF1ZXN0NDIzNzA4NTk3", + "html_url": "https://github.com/67P/kredits-contracts/pull/196", + "diff_url": "https://github.com/67P/kredits-contracts/pull/196.diff", + "patch_url": "https://github.com/67P/kredits-contracts/pull/196.patch", + "issue_url": "https://api.github.com/repos/67P/kredits-contracts/issues/196", + "number": 196, + "state": "closed", + "locked": false, + "title": "Chore/dependency updates", + "user": { + "login": "bumi", + "id": 318, + "node_id": "MDQ6VXNlcjMxOA==", + "avatar_url": "https://avatars1.githubusercontent.com/u/318?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/bumi", + "html_url": "https://github.com/bumi", + "followers_url": "https://api.github.com/users/bumi/followers", + "following_url": "https://api.github.com/users/bumi/following{/other_user}", + "gists_url": "https://api.github.com/users/bumi/gists{/gist_id}", + "starred_url": "https://api.github.com/users/bumi/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/bumi/subscriptions", + "organizations_url": "https://api.github.com/users/bumi/orgs", + "repos_url": "https://api.github.com/users/bumi/repos", + "events_url": "https://api.github.com/users/bumi/events{/privacy}", + "received_events_url": "https://api.github.com/users/bumi/received_events", + "type": "User", + "site_admin": false + }, + "body": "Updated the npm dependencies to the latest versions\r\n\r\nmissing: \r\n- [ ] ipfs-http-client - which has some breaking changes. I think it is not a problem for us but needs to be tested\r\n- [ ] solhint - wich also has a breaking change and now needs pretier for codestyle linting. I did not want that additional dependency now. Also we probably needs to improve the linting of the solidity files\r\n", + "created_at": "2020-05-27T08:57:43Z", + "updated_at": "2020-05-27T14:22:41Z", + "closed_at": "2020-05-27T14:22:41Z", + "merged_at": "2020-05-27T14:22:41Z", + "merge_commit_sha": "2b99593699999756f0f49549873f2cfb679d3f4c", + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "requested_teams": [], + "labels": [ + { + "id": 923540870, + "node_id": "MDU6TGFiZWw5MjM1NDA4NzA=", + "url": "https://api.github.com/repos/67P/kredits-contracts/labels/kredits-1", + "name": "kredits-1", + "color": "008080", + "default": false, + "description": "" + } + ], + "milestone": null, + "draft": false, + "commits_url": "https://api.github.com/repos/67P/kredits-contracts/pulls/196/commits", + "review_comments_url": "https://api.github.com/repos/67P/kredits-contracts/pulls/196/comments", + "review_comment_url": "https://api.github.com/repos/67P/kredits-contracts/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/67P/kredits-contracts/issues/196/comments", + "statuses_url": "https://api.github.com/repos/67P/kredits-contracts/statuses/606350eb5e173a38a8c5f1b3faf30aa03224065c", + "head": { + "label": "67P:chore/dependency-updates", + "ref": "chore/dependency-updates", + "sha": "606350eb5e173a38a8c5f1b3faf30aa03224065c", + "user": { + "login": "67P", + "id": 9769503, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=", + "avatar_url": "https://avatars1.githubusercontent.com/u/9769503?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/67P", + "html_url": "https://github.com/67P", + "followers_url": "https://api.github.com/users/67P/followers", + "following_url": "https://api.github.com/users/67P/following{/other_user}", + "gists_url": "https://api.github.com/users/67P/gists{/gist_id}", + "starred_url": "https://api.github.com/users/67P/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/67P/subscriptions", + "organizations_url": "https://api.github.com/users/67P/orgs", + "repos_url": "https://api.github.com/users/67P/repos", + "events_url": "https://api.github.com/users/67P/events{/privacy}", + "received_events_url": "https://api.github.com/users/67P/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 124804465, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjQ4MDQ0NjU=", + "name": "kredits-contracts", + "full_name": "67P/kredits-contracts", + "private": false, + "owner": { + "login": "67P", + "id": 9769503, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=", + "avatar_url": "https://avatars1.githubusercontent.com/u/9769503?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/67P", + "html_url": "https://github.com/67P", + "followers_url": "https://api.github.com/users/67P/followers", + "following_url": "https://api.github.com/users/67P/following{/other_user}", + "gists_url": "https://api.github.com/users/67P/gists{/gist_id}", + "starred_url": "https://api.github.com/users/67P/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/67P/subscriptions", + "organizations_url": "https://api.github.com/users/67P/orgs", + "repos_url": "https://api.github.com/users/67P/repos", + "events_url": "https://api.github.com/users/67P/events{/privacy}", + "received_events_url": "https://api.github.com/users/67P/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/67P/kredits-contracts", + "description": "Smart contracts and JS API for Kosmos Kredits", + "fork": false, + "url": "https://api.github.com/repos/67P/kredits-contracts", + "forks_url": "https://api.github.com/repos/67P/kredits-contracts/forks", + "keys_url": "https://api.github.com/repos/67P/kredits-contracts/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/67P/kredits-contracts/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/67P/kredits-contracts/teams", + "hooks_url": "https://api.github.com/repos/67P/kredits-contracts/hooks", + "issue_events_url": "https://api.github.com/repos/67P/kredits-contracts/issues/events{/number}", + "events_url": "https://api.github.com/repos/67P/kredits-contracts/events", + "assignees_url": "https://api.github.com/repos/67P/kredits-contracts/assignees{/user}", + "branches_url": "https://api.github.com/repos/67P/kredits-contracts/branches{/branch}", + "tags_url": "https://api.github.com/repos/67P/kredits-contracts/tags", + "blobs_url": "https://api.github.com/repos/67P/kredits-contracts/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/67P/kredits-contracts/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/67P/kredits-contracts/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/67P/kredits-contracts/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/67P/kredits-contracts/statuses/{sha}", + "languages_url": "https://api.github.com/repos/67P/kredits-contracts/languages", + "stargazers_url": "https://api.github.com/repos/67P/kredits-contracts/stargazers", + "contributors_url": "https://api.github.com/repos/67P/kredits-contracts/contributors", + "subscribers_url": "https://api.github.com/repos/67P/kredits-contracts/subscribers", + "subscription_url": "https://api.github.com/repos/67P/kredits-contracts/subscription", + "commits_url": "https://api.github.com/repos/67P/kredits-contracts/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/67P/kredits-contracts/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/67P/kredits-contracts/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/67P/kredits-contracts/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/67P/kredits-contracts/contents/{+path}", + "compare_url": "https://api.github.com/repos/67P/kredits-contracts/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/67P/kredits-contracts/merges", + "archive_url": "https://api.github.com/repos/67P/kredits-contracts/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/67P/kredits-contracts/downloads", + "issues_url": "https://api.github.com/repos/67P/kredits-contracts/issues{/number}", + "pulls_url": "https://api.github.com/repos/67P/kredits-contracts/pulls{/number}", + "milestones_url": "https://api.github.com/repos/67P/kredits-contracts/milestones{/number}", + "notifications_url": "https://api.github.com/repos/67P/kredits-contracts/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/67P/kredits-contracts/labels{/name}", + "releases_url": "https://api.github.com/repos/67P/kredits-contracts/releases{/id}", + "deployments_url": "https://api.github.com/repos/67P/kredits-contracts/deployments", + "created_at": "2018-03-11T22:11:45Z", + "updated_at": "2020-05-07T08:08:30Z", + "pushed_at": "2020-05-27T14:22:41Z", + "git_url": "git://github.com/67P/kredits-contracts.git", + "ssh_url": "git@github.com:67P/kredits-contracts.git", + "clone_url": "https://github.com/67P/kredits-contracts.git", + "svn_url": "https://github.com/67P/kredits-contracts", + "homepage": "https://wiki.kosmos.org/Kredits", + "size": 2289, + "stargazers_count": 3, + "watchers_count": 3, + "language": "JavaScript", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 3, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 35, + "license": null, + "forks": 3, + "open_issues": 35, + "watchers": 3, + "default_branch": "master" + } + }, + "base": { + "label": "67P:master", + "ref": "master", + "sha": "31c29ab6d0bf0d4fc4c27dbc1ecbb3d27659cf7e", + "user": { + "login": "67P", + "id": 9769503, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=", + "avatar_url": "https://avatars1.githubusercontent.com/u/9769503?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/67P", + "html_url": "https://github.com/67P", + "followers_url": "https://api.github.com/users/67P/followers", + "following_url": "https://api.github.com/users/67P/following{/other_user}", + "gists_url": "https://api.github.com/users/67P/gists{/gist_id}", + "starred_url": "https://api.github.com/users/67P/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/67P/subscriptions", + "organizations_url": "https://api.github.com/users/67P/orgs", + "repos_url": "https://api.github.com/users/67P/repos", + "events_url": "https://api.github.com/users/67P/events{/privacy}", + "received_events_url": "https://api.github.com/users/67P/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 124804465, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjQ4MDQ0NjU=", + "name": "kredits-contracts", + "full_name": "67P/kredits-contracts", + "private": false, + "owner": { + "login": "67P", + "id": 9769503, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=", + "avatar_url": "https://avatars1.githubusercontent.com/u/9769503?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/67P", + "html_url": "https://github.com/67P", + "followers_url": "https://api.github.com/users/67P/followers", + "following_url": "https://api.github.com/users/67P/following{/other_user}", + "gists_url": "https://api.github.com/users/67P/gists{/gist_id}", + "starred_url": "https://api.github.com/users/67P/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/67P/subscriptions", + "organizations_url": "https://api.github.com/users/67P/orgs", + "repos_url": "https://api.github.com/users/67P/repos", + "events_url": "https://api.github.com/users/67P/events{/privacy}", + "received_events_url": "https://api.github.com/users/67P/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/67P/kredits-contracts", + "description": "Smart contracts and JS API for Kosmos Kredits", + "fork": false, + "url": "https://api.github.com/repos/67P/kredits-contracts", + "forks_url": "https://api.github.com/repos/67P/kredits-contracts/forks", + "keys_url": "https://api.github.com/repos/67P/kredits-contracts/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/67P/kredits-contracts/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/67P/kredits-contracts/teams", + "hooks_url": "https://api.github.com/repos/67P/kredits-contracts/hooks", + "issue_events_url": "https://api.github.com/repos/67P/kredits-contracts/issues/events{/number}", + "events_url": "https://api.github.com/repos/67P/kredits-contracts/events", + "assignees_url": "https://api.github.com/repos/67P/kredits-contracts/assignees{/user}", + "branches_url": "https://api.github.com/repos/67P/kredits-contracts/branches{/branch}", + "tags_url": "https://api.github.com/repos/67P/kredits-contracts/tags", + "blobs_url": "https://api.github.com/repos/67P/kredits-contracts/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/67P/kredits-contracts/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/67P/kredits-contracts/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/67P/kredits-contracts/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/67P/kredits-contracts/statuses/{sha}", + "languages_url": "https://api.github.com/repos/67P/kredits-contracts/languages", + "stargazers_url": "https://api.github.com/repos/67P/kredits-contracts/stargazers", + "contributors_url": "https://api.github.com/repos/67P/kredits-contracts/contributors", + "subscribers_url": "https://api.github.com/repos/67P/kredits-contracts/subscribers", + "subscription_url": "https://api.github.com/repos/67P/kredits-contracts/subscription", + "commits_url": "https://api.github.com/repos/67P/kredits-contracts/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/67P/kredits-contracts/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/67P/kredits-contracts/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/67P/kredits-contracts/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/67P/kredits-contracts/contents/{+path}", + "compare_url": "https://api.github.com/repos/67P/kredits-contracts/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/67P/kredits-contracts/merges", + "archive_url": "https://api.github.com/repos/67P/kredits-contracts/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/67P/kredits-contracts/downloads", + "issues_url": "https://api.github.com/repos/67P/kredits-contracts/issues{/number}", + "pulls_url": "https://api.github.com/repos/67P/kredits-contracts/pulls{/number}", + "milestones_url": "https://api.github.com/repos/67P/kredits-contracts/milestones{/number}", + "notifications_url": "https://api.github.com/repos/67P/kredits-contracts/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/67P/kredits-contracts/labels{/name}", + "releases_url": "https://api.github.com/repos/67P/kredits-contracts/releases{/id}", + "deployments_url": "https://api.github.com/repos/67P/kredits-contracts/deployments", + "created_at": "2018-03-11T22:11:45Z", + "updated_at": "2020-05-07T08:08:30Z", + "pushed_at": "2020-05-27T14:22:41Z", + "git_url": "git://github.com/67P/kredits-contracts.git", + "ssh_url": "git@github.com:67P/kredits-contracts.git", + "clone_url": "https://github.com/67P/kredits-contracts.git", + "svn_url": "https://github.com/67P/kredits-contracts", + "homepage": "https://wiki.kosmos.org/Kredits", + "size": 2289, + "stargazers_count": 3, + "watchers_count": 3, + "language": "JavaScript", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 3, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 35, + "license": null, + "forks": 3, + "open_issues": 35, + "watchers": 3, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/67P/kredits-contracts/pulls/196" + }, + "html": { + "href": "https://github.com/67P/kredits-contracts/pull/196" + }, + "issue": { + "href": "https://api.github.com/repos/67P/kredits-contracts/issues/196" + }, + "comments": { + "href": "https://api.github.com/repos/67P/kredits-contracts/issues/196/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/67P/kredits-contracts/pulls/196/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/67P/kredits-contracts/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/67P/kredits-contracts/pulls/196/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/67P/kredits-contracts/statuses/606350eb5e173a38a8c5f1b3faf30aa03224065c" + } + }, + "author_association": "CONTRIBUTOR", + "merged": true, + "mergeable": null, + "rebaseable": null, + "mergeable_state": "unknown", + "merged_by": { + "login": "bumi", + "id": 318, + "node_id": "MDQ6VXNlcjMxOA==", + "avatar_url": "https://avatars1.githubusercontent.com/u/318?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/bumi", + "html_url": "https://github.com/bumi", + "followers_url": "https://api.github.com/users/bumi/followers", + "following_url": "https://api.github.com/users/bumi/following{/other_user}", + "gists_url": "https://api.github.com/users/bumi/gists{/gist_id}", + "starred_url": "https://api.github.com/users/bumi/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/bumi/subscriptions", + "organizations_url": "https://api.github.com/users/bumi/orgs", + "repos_url": "https://api.github.com/users/bumi/repos", + "events_url": "https://api.github.com/users/bumi/events{/privacy}", + "received_events_url": "https://api.github.com/users/bumi/received_events", + "type": "User", + "site_admin": false + }, + "comments": 3, + "review_comments": 0, + "maintainer_can_modify": false, + "commits": 4, + "additions": 16649, + "deletions": 4256, + "changed_files": 10 + }, + "url": "https://github.com/67P/kredits-contracts/pull/196", + "ipfsData": "{\n \"@context\": \"https://schema.kosmos.org\",\n \"@type\": \"Contribution\",\n \"contributor\": {\n \"ipfs\": \"QmYgiRd1FZ7JjDGBwkmLQNF6XQuyF8AWoFDRvUWhhmxiEj\"\n },\n \"date\": \"2020-05-27\",\n \"time\": \"14:22:41Z\",\n \"kind\": \"dev\",\n \"description\": \"67P/kredits-contracts: Chore/dependency updates\",\n \"details\": {\n \"url\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/196\",\n \"id\": 423708597,\n \"node_id\": \"MDExOlB1bGxSZXF1ZXN0NDIzNzA4NTk3\",\n \"html_url\": \"https://github.com/67P/kredits-contracts/pull/196\",\n \"diff_url\": \"https://github.com/67P/kredits-contracts/pull/196.diff\",\n \"patch_url\": \"https://github.com/67P/kredits-contracts/pull/196.patch\",\n \"issue_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues/196\",\n \"number\": 196,\n \"state\": \"closed\",\n \"locked\": false,\n \"title\": \"Chore/dependency updates\",\n \"user\": {\n \"login\": \"bumi\",\n \"id\": 318,\n \"node_id\": \"MDQ6VXNlcjMxOA==\",\n \"avatar_url\": \"https://avatars1.githubusercontent.com/u/318?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/bumi\",\n \"html_url\": \"https://github.com/bumi\",\n \"followers_url\": \"https://api.github.com/users/bumi/followers\",\n \"following_url\": \"https://api.github.com/users/bumi/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/bumi/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/bumi/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/bumi/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/bumi/orgs\",\n \"repos_url\": \"https://api.github.com/users/bumi/repos\",\n \"events_url\": \"https://api.github.com/users/bumi/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/bumi/received_events\",\n \"type\": \"User\",\n \"site_admin\": false\n },\n \"body\": \"Updated the npm dependencies to the latest versions\\r\\n\\r\\nmissing: \\r\\n- [ ] ipfs-http-client - which has some breaking changes. I think it is not a problem for us but needs to be tested\\r\\n- [ ] solhint - wich also has a breaking change and now needs pretier for codestyle linting. I did not want that additional dependency now. Also we probably needs to improve the linting of the solidity files\\r\\n\",\n \"created_at\": \"2020-05-27T08:57:43Z\",\n \"updated_at\": \"2020-05-27T14:22:41Z\",\n \"closed_at\": \"2020-05-27T14:22:41Z\",\n \"merged_at\": \"2020-05-27T14:22:41Z\",\n \"merge_commit_sha\": \"2b99593699999756f0f49549873f2cfb679d3f4c\",\n \"assignee\": null,\n \"assignees\": [],\n \"requested_reviewers\": [],\n \"requested_teams\": [],\n \"labels\": [\n {\n \"id\": 923540870,\n \"node_id\": \"MDU6TGFiZWw5MjM1NDA4NzA=\",\n \"url\": \"https://api.github.com/repos/67P/kredits-contracts/labels/kredits-1\",\n \"name\": \"kredits-1\",\n \"color\": \"008080\",\n \"default\": false,\n \"description\": \"\"\n }\n ],\n \"milestone\": null,\n \"draft\": false,\n \"commits_url\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/196/commits\",\n \"review_comments_url\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/196/comments\",\n \"review_comment_url\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/comments{/number}\",\n \"comments_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues/196/comments\",\n \"statuses_url\": \"https://api.github.com/repos/67P/kredits-contracts/statuses/606350eb5e173a38a8c5f1b3faf30aa03224065c\",\n \"head\": {\n \"label\": \"67P:chore/dependency-updates\",\n \"ref\": \"chore/dependency-updates\",\n \"sha\": \"606350eb5e173a38a8c5f1b3faf30aa03224065c\",\n \"user\": {\n \"login\": \"67P\",\n \"id\": 9769503,\n \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=\",\n \"avatar_url\": \"https://avatars1.githubusercontent.com/u/9769503?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/67P\",\n \"html_url\": \"https://github.com/67P\",\n \"followers_url\": \"https://api.github.com/users/67P/followers\",\n \"following_url\": \"https://api.github.com/users/67P/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/67P/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/67P/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/67P/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/67P/orgs\",\n \"repos_url\": \"https://api.github.com/users/67P/repos\",\n \"events_url\": \"https://api.github.com/users/67P/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/67P/received_events\",\n \"type\": \"Organization\",\n \"site_admin\": false\n },\n \"repo\": {\n \"id\": 124804465,\n \"node_id\": \"MDEwOlJlcG9zaXRvcnkxMjQ4MDQ0NjU=\",\n \"name\": \"kredits-contracts\",\n \"full_name\": \"67P/kredits-contracts\",\n \"private\": false,\n \"owner\": {\n \"login\": \"67P\",\n \"id\": 9769503,\n \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=\",\n \"avatar_url\": \"https://avatars1.githubusercontent.com/u/9769503?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/67P\",\n \"html_url\": \"https://github.com/67P\",\n \"followers_url\": \"https://api.github.com/users/67P/followers\",\n \"following_url\": \"https://api.github.com/users/67P/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/67P/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/67P/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/67P/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/67P/orgs\",\n \"repos_url\": \"https://api.github.com/users/67P/repos\",\n \"events_url\": \"https://api.github.com/users/67P/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/67P/received_events\",\n \"type\": \"Organization\",\n \"site_admin\": false\n },\n \"html_url\": \"https://github.com/67P/kredits-contracts\",\n \"description\": \"Smart contracts and JS API for Kosmos Kredits\",\n \"fork\": false,\n \"url\": \"https://api.github.com/repos/67P/kredits-contracts\",\n \"forks_url\": \"https://api.github.com/repos/67P/kredits-contracts/forks\",\n \"keys_url\": \"https://api.github.com/repos/67P/kredits-contracts/keys{/key_id}\",\n \"collaborators_url\": \"https://api.github.com/repos/67P/kredits-contracts/collaborators{/collaborator}\",\n \"teams_url\": \"https://api.github.com/repos/67P/kredits-contracts/teams\",\n \"hooks_url\": \"https://api.github.com/repos/67P/kredits-contracts/hooks\",\n \"issue_events_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues/events{/number}\",\n \"events_url\": \"https://api.github.com/repos/67P/kredits-contracts/events\",\n \"assignees_url\": \"https://api.github.com/repos/67P/kredits-contracts/assignees{/user}\",\n \"branches_url\": \"https://api.github.com/repos/67P/kredits-contracts/branches{/branch}\",\n \"tags_url\": \"https://api.github.com/repos/67P/kredits-contracts/tags\",\n \"blobs_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/blobs{/sha}\",\n \"git_tags_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/tags{/sha}\",\n \"git_refs_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/refs{/sha}\",\n \"trees_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/trees{/sha}\",\n \"statuses_url\": \"https://api.github.com/repos/67P/kredits-contracts/statuses/{sha}\",\n \"languages_url\": \"https://api.github.com/repos/67P/kredits-contracts/languages\",\n \"stargazers_url\": \"https://api.github.com/repos/67P/kredits-contracts/stargazers\",\n \"contributors_url\": \"https://api.github.com/repos/67P/kredits-contracts/contributors\",\n \"subscribers_url\": \"https://api.github.com/repos/67P/kredits-contracts/subscribers\",\n \"subscription_url\": \"https://api.github.com/repos/67P/kredits-contracts/subscription\",\n \"commits_url\": \"https://api.github.com/repos/67P/kredits-contracts/commits{/sha}\",\n \"git_commits_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/commits{/sha}\",\n \"comments_url\": \"https://api.github.com/repos/67P/kredits-contracts/comments{/number}\",\n \"issue_comment_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues/comments{/number}\",\n \"contents_url\": \"https://api.github.com/repos/67P/kredits-contracts/contents/{+path}\",\n \"compare_url\": \"https://api.github.com/repos/67P/kredits-contracts/compare/{base}...{head}\",\n \"merges_url\": \"https://api.github.com/repos/67P/kredits-contracts/merges\",\n \"archive_url\": \"https://api.github.com/repos/67P/kredits-contracts/{archive_format}{/ref}\",\n \"downloads_url\": \"https://api.github.com/repos/67P/kredits-contracts/downloads\",\n \"issues_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues{/number}\",\n \"pulls_url\": \"https://api.github.com/repos/67P/kredits-contracts/pulls{/number}\",\n \"milestones_url\": \"https://api.github.com/repos/67P/kredits-contracts/milestones{/number}\",\n \"notifications_url\": \"https://api.github.com/repos/67P/kredits-contracts/notifications{?since,all,participating}\",\n \"labels_url\": \"https://api.github.com/repos/67P/kredits-contracts/labels{/name}\",\n \"releases_url\": \"https://api.github.com/repos/67P/kredits-contracts/releases{/id}\",\n \"deployments_url\": \"https://api.github.com/repos/67P/kredits-contracts/deployments\",\n \"created_at\": \"2018-03-11T22:11:45Z\",\n \"updated_at\": \"2020-05-07T08:08:30Z\",\n \"pushed_at\": \"2020-05-27T14:22:41Z\",\n \"git_url\": \"git://github.com/67P/kredits-contracts.git\",\n \"ssh_url\": \"git@github.com:67P/kredits-contracts.git\",\n \"clone_url\": \"https://github.com/67P/kredits-contracts.git\",\n \"svn_url\": \"https://github.com/67P/kredits-contracts\",\n \"homepage\": \"https://wiki.kosmos.org/Kredits\",\n \"size\": 2289,\n \"stargazers_count\": 3,\n \"watchers_count\": 3,\n \"language\": \"JavaScript\",\n \"has_issues\": true,\n \"has_projects\": false,\n \"has_downloads\": true,\n \"has_wiki\": false,\n \"has_pages\": false,\n \"forks_count\": 3,\n \"mirror_url\": null,\n \"archived\": false,\n \"disabled\": false,\n \"open_issues_count\": 35,\n \"license\": null,\n \"forks\": 3,\n \"open_issues\": 35,\n \"watchers\": 3,\n \"default_branch\": \"master\"\n }\n },\n \"base\": {\n \"label\": \"67P:master\",\n \"ref\": \"master\",\n \"sha\": \"31c29ab6d0bf0d4fc4c27dbc1ecbb3d27659cf7e\",\n \"user\": {\n \"login\": \"67P\",\n \"id\": 9769503,\n \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=\",\n \"avatar_url\": \"https://avatars1.githubusercontent.com/u/9769503?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/67P\",\n \"html_url\": \"https://github.com/67P\",\n \"followers_url\": \"https://api.github.com/users/67P/followers\",\n \"following_url\": \"https://api.github.com/users/67P/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/67P/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/67P/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/67P/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/67P/orgs\",\n \"repos_url\": \"https://api.github.com/users/67P/repos\",\n \"events_url\": \"https://api.github.com/users/67P/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/67P/received_events\",\n \"type\": \"Organization\",\n \"site_admin\": false\n },\n \"repo\": {\n \"id\": 124804465,\n \"node_id\": \"MDEwOlJlcG9zaXRvcnkxMjQ4MDQ0NjU=\",\n \"name\": \"kredits-contracts\",\n \"full_name\": \"67P/kredits-contracts\",\n \"private\": false,\n \"owner\": {\n \"login\": \"67P\",\n \"id\": 9769503,\n \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjk3Njk1MDM=\",\n \"avatar_url\": \"https://avatars1.githubusercontent.com/u/9769503?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/67P\",\n \"html_url\": \"https://github.com/67P\",\n \"followers_url\": \"https://api.github.com/users/67P/followers\",\n \"following_url\": \"https://api.github.com/users/67P/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/67P/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/67P/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/67P/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/67P/orgs\",\n \"repos_url\": \"https://api.github.com/users/67P/repos\",\n \"events_url\": \"https://api.github.com/users/67P/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/67P/received_events\",\n \"type\": \"Organization\",\n \"site_admin\": false\n },\n \"html_url\": \"https://github.com/67P/kredits-contracts\",\n \"description\": \"Smart contracts and JS API for Kosmos Kredits\",\n \"fork\": false,\n \"url\": \"https://api.github.com/repos/67P/kredits-contracts\",\n \"forks_url\": \"https://api.github.com/repos/67P/kredits-contracts/forks\",\n \"keys_url\": \"https://api.github.com/repos/67P/kredits-contracts/keys{/key_id}\",\n \"collaborators_url\": \"https://api.github.com/repos/67P/kredits-contracts/collaborators{/collaborator}\",\n \"teams_url\": \"https://api.github.com/repos/67P/kredits-contracts/teams\",\n \"hooks_url\": \"https://api.github.com/repos/67P/kredits-contracts/hooks\",\n \"issue_events_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues/events{/number}\",\n \"events_url\": \"https://api.github.com/repos/67P/kredits-contracts/events\",\n \"assignees_url\": \"https://api.github.com/repos/67P/kredits-contracts/assignees{/user}\",\n \"branches_url\": \"https://api.github.com/repos/67P/kredits-contracts/branches{/branch}\",\n \"tags_url\": \"https://api.github.com/repos/67P/kredits-contracts/tags\",\n \"blobs_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/blobs{/sha}\",\n \"git_tags_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/tags{/sha}\",\n \"git_refs_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/refs{/sha}\",\n \"trees_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/trees{/sha}\",\n \"statuses_url\": \"https://api.github.com/repos/67P/kredits-contracts/statuses/{sha}\",\n \"languages_url\": \"https://api.github.com/repos/67P/kredits-contracts/languages\",\n \"stargazers_url\": \"https://api.github.com/repos/67P/kredits-contracts/stargazers\",\n \"contributors_url\": \"https://api.github.com/repos/67P/kredits-contracts/contributors\",\n \"subscribers_url\": \"https://api.github.com/repos/67P/kredits-contracts/subscribers\",\n \"subscription_url\": \"https://api.github.com/repos/67P/kredits-contracts/subscription\",\n \"commits_url\": \"https://api.github.com/repos/67P/kredits-contracts/commits{/sha}\",\n \"git_commits_url\": \"https://api.github.com/repos/67P/kredits-contracts/git/commits{/sha}\",\n \"comments_url\": \"https://api.github.com/repos/67P/kredits-contracts/comments{/number}\",\n \"issue_comment_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues/comments{/number}\",\n \"contents_url\": \"https://api.github.com/repos/67P/kredits-contracts/contents/{+path}\",\n \"compare_url\": \"https://api.github.com/repos/67P/kredits-contracts/compare/{base}...{head}\",\n \"merges_url\": \"https://api.github.com/repos/67P/kredits-contracts/merges\",\n \"archive_url\": \"https://api.github.com/repos/67P/kredits-contracts/{archive_format}{/ref}\",\n \"downloads_url\": \"https://api.github.com/repos/67P/kredits-contracts/downloads\",\n \"issues_url\": \"https://api.github.com/repos/67P/kredits-contracts/issues{/number}\",\n \"pulls_url\": \"https://api.github.com/repos/67P/kredits-contracts/pulls{/number}\",\n \"milestones_url\": \"https://api.github.com/repos/67P/kredits-contracts/milestones{/number}\",\n \"notifications_url\": \"https://api.github.com/repos/67P/kredits-contracts/notifications{?since,all,participating}\",\n \"labels_url\": \"https://api.github.com/repos/67P/kredits-contracts/labels{/name}\",\n \"releases_url\": \"https://api.github.com/repos/67P/kredits-contracts/releases{/id}\",\n \"deployments_url\": \"https://api.github.com/repos/67P/kredits-contracts/deployments\",\n \"created_at\": \"2018-03-11T22:11:45Z\",\n \"updated_at\": \"2020-05-07T08:08:30Z\",\n \"pushed_at\": \"2020-05-27T14:22:41Z\",\n \"git_url\": \"git://github.com/67P/kredits-contracts.git\",\n \"ssh_url\": \"git@github.com:67P/kredits-contracts.git\",\n \"clone_url\": \"https://github.com/67P/kredits-contracts.git\",\n \"svn_url\": \"https://github.com/67P/kredits-contracts\",\n \"homepage\": \"https://wiki.kosmos.org/Kredits\",\n \"size\": 2289,\n \"stargazers_count\": 3,\n \"watchers_count\": 3,\n \"language\": \"JavaScript\",\n \"has_issues\": true,\n \"has_projects\": false,\n \"has_downloads\": true,\n \"has_wiki\": false,\n \"has_pages\": false,\n \"forks_count\": 3,\n \"mirror_url\": null,\n \"archived\": false,\n \"disabled\": false,\n \"open_issues_count\": 35,\n \"license\": null,\n \"forks\": 3,\n \"open_issues\": 35,\n \"watchers\": 3,\n \"default_branch\": \"master\"\n }\n },\n \"_links\": {\n \"self\": {\n \"href\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/196\"\n },\n \"html\": {\n \"href\": \"https://github.com/67P/kredits-contracts/pull/196\"\n },\n \"issue\": {\n \"href\": \"https://api.github.com/repos/67P/kredits-contracts/issues/196\"\n },\n \"comments\": {\n \"href\": \"https://api.github.com/repos/67P/kredits-contracts/issues/196/comments\"\n },\n \"review_comments\": {\n \"href\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/196/comments\"\n },\n \"review_comment\": {\n \"href\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/comments{/number}\"\n },\n \"commits\": {\n \"href\": \"https://api.github.com/repos/67P/kredits-contracts/pulls/196/commits\"\n },\n \"statuses\": {\n \"href\": \"https://api.github.com/repos/67P/kredits-contracts/statuses/606350eb5e173a38a8c5f1b3faf30aa03224065c\"\n }\n },\n \"author_association\": \"CONTRIBUTOR\",\n \"merged\": true,\n \"mergeable\": null,\n \"rebaseable\": null,\n \"mergeable_state\": \"unknown\",\n \"merged_by\": {\n \"login\": \"bumi\",\n \"id\": 318,\n \"node_id\": \"MDQ6VXNlcjMxOA==\",\n \"avatar_url\": \"https://avatars1.githubusercontent.com/u/318?v=4\",\n \"gravatar_id\": \"\",\n \"url\": \"https://api.github.com/users/bumi\",\n \"html_url\": \"https://github.com/bumi\",\n \"followers_url\": \"https://api.github.com/users/bumi/followers\",\n \"following_url\": \"https://api.github.com/users/bumi/following{/other_user}\",\n \"gists_url\": \"https://api.github.com/users/bumi/gists{/gist_id}\",\n \"starred_url\": \"https://api.github.com/users/bumi/starred{/owner}{/repo}\",\n \"subscriptions_url\": \"https://api.github.com/users/bumi/subscriptions\",\n \"organizations_url\": \"https://api.github.com/users/bumi/orgs\",\n \"repos_url\": \"https://api.github.com/users/bumi/repos\",\n \"events_url\": \"https://api.github.com/users/bumi/events{/privacy}\",\n \"received_events_url\": \"https://api.github.com/users/bumi/received_events\",\n \"type\": \"User\",\n \"site_admin\": false\n },\n \"comments\": 3,\n \"review_comments\": 0,\n \"maintainer_can_modify\": false,\n \"commits\": 4,\n \"additions\": 16649,\n \"deletions\": 4256,\n \"changed_files\": 10\n },\n \"url\": \"https://github.com/67P/kredits-contracts/pull/196\"\n}" +} diff --git a/tests/fixtures/contributions.js b/tests/fixtures/contributions.js index f675937..75a1270 100644 --- a/tests/fixtures/contributions.js +++ b/tests/fixtures/contributions.js @@ -1,23 +1,25 @@ import Model from 'kredits-web/models/contribution'; import contributors from '../../tests/fixtures/contributors'; +import processContributionData from 'kredits-web/utils/process-contribution-data'; const items = []; const data = [ - { id: 1, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'dev' }, - { id: 2, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'ops' }, - { id: 3, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'ops' }, - { id: 4, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'docs' }, - { id: 5, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'design' }, - { id: 6, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: true, amount: 500, kind: 'dev' }, - { id: 7, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 5000, kind: 'dev' }, - { id: 8, contributorId: 1, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 1500, kind: 'community' }, - { id: 9, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: true, amount: 1500, kind: 'docs' }, + { id: 1, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'dev' }, + { id: 2, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'ops' }, + { id: 3, contributorId: 2, confirmedAt: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'ops' }, + { id: 4, contributorId: 2, confirmedAt: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'docs' }, + { id: 5, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'design' }, + { id: 6, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: true, amount: 500, kind: 'dev' }, + { id: 7, contributorId: 3, confirmedAt: 2000, claimed: false, vetoed: false, amount: 5000, kind: 'dev' }, + { id: 8, contributorId: 1, confirmedAt: 2000, claimed: false, vetoed: false, amount: 1500, kind: 'community' }, + { id: 9, contributorId: 3, confirmedAt: 2000, claimed: false, vetoed: true, amount: 1500, kind: 'docs' }, ]; data.forEach(attrs => { - attrs.contributor = contributors.findBy('id', attrs.contributorId.toString()); - items.push(Model.create(attrs)) + const c = Model.create(processContributionData(attrs)); + c.set('contributor', contributors.findBy('id', attrs.contributorId.toString())); + items.push(c); }); export default items; diff --git a/tests/fixtures/contributors.js b/tests/fixtures/contributors.js index 8c8f0ea..ebe261e 100644 --- a/tests/fixtures/contributors.js +++ b/tests/fixtures/contributors.js @@ -1,4 +1,5 @@ import Contributor from 'kredits-web/models/contributor'; +import processContributorData from 'kredits-web/utils/process-contributor-data'; const contributors = []; @@ -8,6 +9,9 @@ const data = [ { id: '3', name: 'Manuel', totalKreditsEarned: 0, github_uid: 54812 } ]; -data.forEach(attrs => contributors.push(Contributor.create(attrs))); +data.forEach(attrs => { + const c = Contributor.create(processContributorData(attrs)); + contributors.push(c); +}); export default contributors; diff --git a/tests/unit/utils/process-contribution-data-test.js b/tests/unit/utils/process-contribution-data-test.js new file mode 100644 index 0000000..9c93c02 --- /dev/null +++ b/tests/unit/utils/process-contribution-data-test.js @@ -0,0 +1,28 @@ +import { module, test } from 'qunit'; +import processContributionData from 'kredits-web/utils/process-contribution-data'; +import testData from '../../fixtures/contribution-data'; + +module('Unit | Utility | process-contribution-data', function() { + + let result = processContributionData(testData); + + test('formats the data correctly', function(assert) { + assert.ok(typeof result.confirmedAt === 'number'); + }); + + test('copies other properties', function(assert) { + [ + 'id', 'contributorId', 'amount', 'vetoed', + 'ipfsHash', 'kind', 'description', 'details', + 'url', 'date', 'time', 'pendingTx' + ].forEach(p => { + assert.ok(Object.prototype.hasOwnProperty.call(result, p), `copies property ${p}`); + }) + }); + + test('does not copy unnecessary properties', function(assert) { + ['exists', '5'].forEach(p => { + assert.notOk(Object.prototype.hasOwnProperty.call(result, p)); + }) + }); +}); diff --git a/tests/unit/utils/process-contributor-data-test.js b/tests/unit/utils/process-contributor-data-test.js index 1d223fb..f81a58d 100644 --- a/tests/unit/utils/process-contributor-data-test.js +++ b/tests/unit/utils/process-contributor-data-test.js @@ -8,10 +8,10 @@ module('Unit | Utility | process-contributor-data', function() { test('formats the data correctly', function(assert) { // TODO use integers everywhere for IDs - assert.ok(typeof result.id == 'string'); - assert.ok(typeof result.balance == 'number'); - assert.ok(typeof result.totalKreditsEarned == 'number'); - assert.ok(typeof result.contributionsCount == 'number'); + assert.ok(typeof result.id === 'string'); + assert.ok(typeof result.balance === 'number'); + assert.ok(typeof result.totalKreditsEarned === 'number'); + assert.ok(typeof result.contributionsCount === 'number'); }); test('copies other properties', function(assert) { From d4b546bfcd9cf74057e0eb7cd8b49d585fef90d0 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 28 May 2020 13:59:10 +0200 Subject: [PATCH 7/8] Load contributions from cache if present And then fetch more from network. Also, only load 30 from network before first render (with nothing cached), then load more after the page has rendered. --- app/routes/application.js | 1 + app/services/kredits.js | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/routes/application.js b/app/routes/application.js index eae822b..b5fdfc9 100644 --- a/app/routes/application.js +++ b/app/routes/application.js @@ -27,6 +27,7 @@ export default Route.extend({ if (this.kredits.contributorsNeedFetch) { schedule('afterRender', this.kredits, this.kredits.fetchContributors); } + schedule('afterRender', this.kredits, this.kredits.fetchContributions); }); } }); diff --git a/app/services/kredits.js b/app/services/kredits.js index 313d504..c33b347 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -22,7 +22,6 @@ export default Service.extend({ browserCache: service(), contributorsNeedFetch: false, - contributionsNeedFetch: false, currentBlock: null, currentUserAccounts: null, // default to not having an account. this is the wen web3 is loaded. @@ -186,11 +185,11 @@ export default Service.extend({ } const numCachedContributions = await this.browserCache.contributions.length(); - // if (numCachedContributions > 0) { - // TODO promises.push(this.loadContributionsFromCache); - // } else { + if (numCachedContributions > 0) { + await this.loadContributionsFromCache(); + } else { await this.fetchContributions({ page: { size: 30 } }); - // } + } return Promise.resolve(); }, @@ -278,6 +277,8 @@ export default Service.extend({ return contributions.map(data => { const contribution = Contribution.create(processContributionData(data)); contribution.set('contributor', this.contributors.findBy('id', data.contributorId.toString())); + const loadedContribution = this.contributions.findBy('id', contribution.id); + if (loadedContribution) { this.contributions.removeObject(loadedContribution); } this.contributions.pushObject(contribution); return contribution; }); @@ -300,6 +301,14 @@ export default Service.extend({ return Promise.resolve(); }, + async loadContributionsFromCache () { + return this.browserCache.contributions.iterate((value/*, key , iterationNumber */) => { + this.contributions.pushObject(Contribution.create(JSON.parse(value))); + }).then((/* result */) => { + console.debug(`[kredits] Loaded ${this.contributions.length} contributions from cache`); + }); + }, + veto (contributionId) { console.debug('[kredits] veto against', contributionId); const contribution = this.contributions.findBy('id', contributionId); From c491f10ec3b7a7d8d9184997e8ec097b8a483e99 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 28 May 2020 14:18:30 +0200 Subject: [PATCH 8/8] Remove obsolete utils --- app/utils/cps/bignumber.js | 20 -------------------- app/utils/cps/kredits.js | 17 ----------------- 2 files changed, 37 deletions(-) delete mode 100644 app/utils/cps/bignumber.js delete mode 100644 app/utils/cps/kredits.js diff --git a/app/utils/cps/bignumber.js b/app/utils/cps/bignumber.js deleted file mode 100644 index 5646820..0000000 --- a/app/utils/cps/bignumber.js +++ /dev/null @@ -1,20 +0,0 @@ -import { computed } from '@ember/object'; -import ethers from 'ethers'; - -export default function(dependentKey, converterMethod) { - return computed(dependentKey, { - get () { - let value = this.get(dependentKey); - if (value && ethers.utils.BigNumber.isBigNumber(value)) { - return value[converterMethod](); - } else { - return value; - } - }, - set (key, value) { - const bnValue = ethers.utils.bigNumberify(value); - this.set(dependentKey, bnValue); - return bnValue[converterMethod](); - } - }); -} diff --git a/app/utils/cps/kredits.js b/app/utils/cps/kredits.js deleted file mode 100644 index 8f6eb3e..0000000 --- a/app/utils/cps/kredits.js +++ /dev/null @@ -1,17 +0,0 @@ -import { computed } from '@ember/object'; -import ethers from 'ethers'; -import formatKredits from 'kredits-web/utils/format-kredits'; - -export default function(dependentKey, options = {}) { - return computed(dependentKey, { - get () { - const value = this.get(dependentKey); - return formatKredits(value, options); - }, - set (key, value) { - const bnValue = ethers.utils.bigNumberify(value); - this.set(dependentKey, bnValue); - return formatKredits(bnValue, options); - } - }); -}