Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 174073fc42 | |||
| 733e5e3683 | |||
| 090d1d0856 | |||
| e047cc45ba | |||
| c64a503546 | |||
| 13021d665d | |||
| b5dbb2449d | |||
| 302c3315a3 | |||
| bac4c1c425 | |||
| c54d754c89 | |||
| 63dd5430bc | |||
| eb2c613ac9 | |||
| bf6d9dbc31 | |||
| c491f10ec3 | |||
| d4b546bfcd | |||
| 69141a31c4 | |||
| e7c9620bbe | |||
| 832de3c06f | |||
| 50e1fc728c | |||
| 871731110b | |||
| f996c89dfe | |||
| 1d8e9ddf5d | |||
| 352c9fe3ab | |||
| e2a944ed5b |
@@ -14,10 +14,6 @@ notifications:
|
|||||||
addons:
|
addons:
|
||||||
chrome: stable
|
chrome: stable
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.npm
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
# See https://git.io/vdao3 for details.
|
# See https://git.io/vdao3 for details.
|
||||||
|
|||||||
@@ -15,11 +15,14 @@
|
|||||||
<p>
|
<p>
|
||||||
<select required onchange={{action (mut this.kind) value="target.value"}}>
|
<select required onchange={{action (mut this.kind) value="target.value"}}>
|
||||||
<option value="" selected disabled hidden></option>
|
<option value="" selected disabled hidden></option>
|
||||||
|
<option value="bureaucracy" selected={{eq this.kind "bureaucracy"}}>Bureaucracy</option>
|
||||||
<option value="community" selected={{eq this.kind "community"}}>Community</option>
|
<option value="community" selected={{eq this.kind "community"}}>Community</option>
|
||||||
<option value="design" selected={{eq this.kind "design"}}>Design</option>
|
<option value="design" selected={{eq this.kind "design"}}>Design</option>
|
||||||
<option value="dev" selected={{eq this.kind "dev"}}>Development</option>
|
<option value="dev" selected={{eq this.kind "dev"}}>Development</option>
|
||||||
<option value="docs" selected={{eq this.kind "docs"}}>Documentation</option>
|
<option value="docs" selected={{eq this.kind "docs"}}>Documentation</option>
|
||||||
<option value="ops" selected={{eq this.kind "ops"}}>IT Operations</option>
|
<option value="ops" selected={{eq this.kind "ops"}}>IT Operations</option>
|
||||||
|
<option value="outreach" selected={{eq this.kind "outreach"}}>Outreach</option>
|
||||||
|
<option value="qa" selected={{eq this.kind "qa"}}>Quality Assurance</option>
|
||||||
<option value="special" selected={{eq this.kind "special"}}>Special</option>
|
<option value="special" selected={{eq this.kind "special"}}>Special</option>
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<ul class="contribution-list">
|
<ul class="contribution-list {{if @loading 'loading'}}">
|
||||||
{{#each this.contributionsFiltered as |contribution|}}
|
{{#each this.contributionsFiltered as |contribution|}}
|
||||||
<li role="button" data-contribution-id={{contribution.id}}
|
<li role="button" data-contribution-id={{contribution.id}}
|
||||||
{{action "openContributionDetails" contribution}}
|
{{action "openContributionDetails" contribution}}
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ import Component from '@ember/component';
|
|||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
|
||||||
router: service(),
|
router: service(),
|
||||||
|
|
||||||
tagName: 'table',
|
|
||||||
classNames: 'contributor-list',
|
|
||||||
|
|
||||||
selectedContributorId: null,
|
selectedContributorId: null,
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
@@ -17,5 +15,4 @@ export default Component.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
<table class="contributor-list {{if @loading 'loading'}}">
|
||||||
|
<thead>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{#each @contributorList as |c|}}
|
{{#each @contributorList as |c|}}
|
||||||
<tr role="button"
|
<tr role="button"
|
||||||
@@ -19,3 +22,4 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import EmberObject, { computed } from '@ember/object';
|
import EmberObject, { computed } from '@ember/object';
|
||||||
import { isEmpty, isPresent } from '@ember/utils';
|
import { isEmpty, isPresent } from '@ember/utils';
|
||||||
import bignumber from 'kredits-web/utils/cps/bignumber';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
export default EmberObject.extend({
|
export default EmberObject.extend({
|
||||||
@@ -9,11 +8,15 @@ export default EmberObject.extend({
|
|||||||
id: null,
|
id: null,
|
||||||
contributorId: null,
|
contributorId: null,
|
||||||
amount: null,
|
amount: null,
|
||||||
confirmedAt: bignumber('confirmedAtBlock', 'toNumber'),
|
confirmedAt: null,
|
||||||
vetoed: null,
|
vetoed: null,
|
||||||
ipfsHash: null,
|
ipfsHash: null,
|
||||||
|
|
||||||
creatorAccount: null,
|
// contributor model instance
|
||||||
|
contributor: null,
|
||||||
|
|
||||||
|
// TODO contributor who submitted the contribution
|
||||||
|
// submittedBy: null,
|
||||||
|
|
||||||
// IPFS
|
// IPFS
|
||||||
kind: null,
|
kind: null,
|
||||||
@@ -22,7 +25,6 @@ export default EmberObject.extend({
|
|||||||
url: null,
|
url: null,
|
||||||
date: null,
|
date: null,
|
||||||
time: null,
|
time: null,
|
||||||
ipfsData: '',
|
|
||||||
|
|
||||||
pendingTx: null,
|
pendingTx: null,
|
||||||
|
|
||||||
@@ -41,6 +43,10 @@ export default EmberObject.extend({
|
|||||||
|
|
||||||
hasPendingChanges: computed('pendingTx', function() {
|
hasPendingChanges: computed('pendingTx', function() {
|
||||||
return isPresent(this.pendingTx);
|
return isPresent(this.pendingTx);
|
||||||
})
|
}),
|
||||||
|
|
||||||
|
serialize () {
|
||||||
|
return JSON.stringify(this);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import EmberObject from '@ember/object';
|
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({
|
export default EmberObject.extend({
|
||||||
// Contract
|
// Contract
|
||||||
id: bignumber('idRaw', 'toString'),
|
id: null,
|
||||||
account: null,
|
account: null,
|
||||||
balance: kreditsValue('balanceRaw'),
|
balance: 0,
|
||||||
totalKreditsEarned: bignumber('totalKreditsEarnedRaw', 'toNumber'),
|
totalKreditsEarned: 0,
|
||||||
contributionsCount: bignumber('contributionsCountRaw', 'toNumber'),
|
contributionsCount: 0,
|
||||||
isCore: false,
|
isCore: false,
|
||||||
ipfsHash: null,
|
ipfsHash: null,
|
||||||
|
|
||||||
@@ -20,6 +18,9 @@ export default EmberObject.extend({
|
|||||||
github_uid: null,
|
github_uid: null,
|
||||||
wiki_username: null,
|
wiki_username: null,
|
||||||
zoom_display_name: null,
|
zoom_display_name: null,
|
||||||
ipfsData: ''
|
|
||||||
|
serialize () {
|
||||||
|
return JSON.stringify(this);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
|
import { schedule } from '@ember/runloop';
|
||||||
|
|
||||||
export default Route.extend({
|
export default Route.extend({
|
||||||
kredits: service(),
|
kredits: service(),
|
||||||
@@ -21,6 +22,18 @@ export default Route.extend({
|
|||||||
return this.kredits.loadInitialData()
|
return this.kredits.loadInitialData()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.kredits.addContractEventHandlers();
|
this.kredits.addContractEventHandlers();
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
if (this.kredits.contributorsNeedSync) {
|
||||||
|
schedule('afterRender', this.kredits.syncContributors,
|
||||||
|
this.kredits.syncContributors.perform);
|
||||||
|
}
|
||||||
|
if (this.kredits.contributionsNeedSync) {
|
||||||
|
schedule('afterRender', this.kredits.syncContributions,
|
||||||
|
this.kredits.syncContributions.perform);
|
||||||
|
}
|
||||||
|
schedule('afterRender', this.kredits.fetchMissingContributions,
|
||||||
|
this.kredits.fetchMissingContributions.perform);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import Service from '@ember/service';
|
||||||
|
import * as localforage from 'localforage';
|
||||||
|
import config from 'kredits-web/config/environment';
|
||||||
|
|
||||||
|
function createStore(name) {
|
||||||
|
const networkName = config.web3RequiredNetwork || 'custom';
|
||||||
|
return localforage.createInstance({ name: `kredits:${networkName}:${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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+172
-17
@@ -1,14 +1,18 @@
|
|||||||
import ethers from 'ethers';
|
import ethers from 'ethers';
|
||||||
import Kredits from 'kredits-contracts';
|
import Kredits from 'kredits-contracts';
|
||||||
import RSVP from 'rsvp';
|
|
||||||
|
|
||||||
import Service from '@ember/service';
|
import Service from '@ember/service';
|
||||||
import EmberObject from '@ember/object';
|
import EmberObject from '@ember/object';
|
||||||
import { computed } from '@ember/object';
|
import { computed } from '@ember/object';
|
||||||
import { alias, notEmpty } from '@ember/object/computed';
|
import { alias, notEmpty } from '@ember/object/computed';
|
||||||
import { isEmpty, isPresent } from '@ember/utils';
|
import { isEmpty, isPresent } from '@ember/utils';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
|
import { task, taskGroup } from 'ember-concurrency';
|
||||||
|
|
||||||
import groupBy from 'kredits-web/utils/group-by';
|
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 formatKredits from 'kredits-web/utils/format-kredits';
|
||||||
|
|
||||||
import config from 'kredits-web/config/environment';
|
import config from 'kredits-web/config/environment';
|
||||||
@@ -17,6 +21,8 @@ import Contribution from 'kredits-web/models/contribution'
|
|||||||
|
|
||||||
export default Service.extend({
|
export default Service.extend({
|
||||||
|
|
||||||
|
browserCache: service(),
|
||||||
|
|
||||||
currentBlock: null,
|
currentBlock: null,
|
||||||
currentUserAccounts: null, // default to not having an account. this is the wen web3 is loaded.
|
currentUserAccounts: null, // default to not having an account. this is the wen web3 is loaded.
|
||||||
currentUser: null,
|
currentUser: null,
|
||||||
@@ -28,6 +34,10 @@ export default Service.extend({
|
|||||||
currentUserIsCore: alias('currentUser.isCore'),
|
currentUserIsCore: alias('currentUser.isCore'),
|
||||||
hasAccounts: notEmpty('currentUserAccounts'),
|
hasAccounts: notEmpty('currentUserAccounts'),
|
||||||
|
|
||||||
|
// When data was loaded from cache, we need to fetch updates from the network
|
||||||
|
contributorsNeedSync: false,
|
||||||
|
contributionsNeedSync: false,
|
||||||
|
|
||||||
contributionsUnconfirmed: computed('contributions.[]', 'currentBlock', function() {
|
contributionsUnconfirmed: computed('contributions.[]', 'currentBlock', function() {
|
||||||
return this.contributions.filter(contribution => {
|
return this.contributions.filter(contribution => {
|
||||||
return contribution.confirmedAt > this.currentBlock;
|
return contribution.confirmedAt > this.currentBlock;
|
||||||
@@ -84,7 +94,7 @@ export default Service.extend({
|
|||||||
getEthProvider () {
|
getEthProvider () {
|
||||||
let ethProvider;
|
let ethProvider;
|
||||||
|
|
||||||
return new RSVP.Promise(async (resolve) => {
|
return new Promise(resolve => {
|
||||||
function instantiateWithoutAccount () {
|
function instantiateWithoutAccount () {
|
||||||
console.debug('[kredits] Creating new instance from npm module class');
|
console.debug('[kredits] Creating new instance from npm module class');
|
||||||
console.debug(`[kredits] providerURL: ${config.web3ProviderUrl}`);
|
console.debug(`[kredits] providerURL: ${config.web3ProviderUrl}`);
|
||||||
@@ -169,12 +179,24 @@ export default Service.extend({
|
|||||||
.then(total => total.toNumber());
|
.then(total => total.toNumber());
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
async loadInitialData () {
|
||||||
|
const numCachedContributors = await this.browserCache.contributors.length();
|
||||||
|
if (numCachedContributors > 0) {
|
||||||
|
await this.loadContributorsFromCache();
|
||||||
|
this.set('contributorsNeedSync', true);
|
||||||
|
} else {
|
||||||
|
await this.fetchContributors();
|
||||||
|
}
|
||||||
|
|
||||||
loadInitialData () {
|
const numCachedContributions = await this.browserCache.contributions.length();
|
||||||
return this.getContributors()
|
if (numCachedContributions > 0) {
|
||||||
.then(contributors => this.contributors.pushObjects(contributors))
|
await this.loadContributionsFromCache();
|
||||||
.then(() => this.getContributions())
|
this.set('contributionsNeedSync', true);
|
||||||
.then(contributions => this.contributions.pushObjects(contributions))
|
} else {
|
||||||
|
await this.fetchContributions({ page: { size: 30 } });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
addContributor (attributes) {
|
addContributor (attributes) {
|
||||||
@@ -205,15 +227,48 @@ export default Service.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getContributors () {
|
fetchContributors () {
|
||||||
|
console.debug(`[kredits] Fetching all contributors from the network`);
|
||||||
return this.kredits.Contributor.all()
|
return this.kredits.Contributor.all()
|
||||||
.then(contributors => {
|
.then(contributors => {
|
||||||
return contributors.map(contributor => {
|
return contributors.forEach(data => {
|
||||||
return Contributor.create(contributor);
|
this.loadContributorFromData(data);
|
||||||
|
return;
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return this.cacheLoadedContributors();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadContributorFromData(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;
|
||||||
|
},
|
||||||
|
|
||||||
|
async cacheLoadedContributors () {
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
|
||||||
|
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`);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
syncContributors: task(function * () {
|
||||||
|
yield this.fetchContributors();
|
||||||
|
}),
|
||||||
|
|
||||||
addContribution (attributes) {
|
addContribution (attributes) {
|
||||||
console.debug('[kredits] add contribution', attributes);
|
console.debug('[kredits] add contribution', attributes);
|
||||||
|
|
||||||
@@ -229,16 +284,116 @@ export default Service.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getContributions () {
|
fetchContributions (options = { page: { size: 200 } }) {
|
||||||
return this.kredits.Contribution.all({page: {size: 200}})
|
console.debug(`[kredits] Fetching contributions from the network`);
|
||||||
|
return this.kredits.Contribution.all(options)
|
||||||
.then(contributions => {
|
.then(contributions => {
|
||||||
return contributions.map(contribution => {
|
return contributions.map(data => {
|
||||||
contribution.contributor = this.contributors.findBy('id', contribution.contributorId.toString());
|
const contribution = this.loadContributionFromData(data);
|
||||||
return Contribution.create(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`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadContributionFromData(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;
|
||||||
|
},
|
||||||
|
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
|
||||||
|
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`);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
contributionTasks: taskGroup().enqueue(),
|
||||||
|
|
||||||
|
syncContributions: task(function * () {
|
||||||
|
yield this.fetchNewContributions.perform();
|
||||||
|
yield this.syncUnconfirmedContributions.perform();
|
||||||
|
}).group('contributionTasks'),
|
||||||
|
|
||||||
|
fetchNewContributions: task(function * () {
|
||||||
|
const count = yield this.kredits.Contribution.functions.contributionsCount();
|
||||||
|
const lastKnownContributionId = Math.max.apply(null, this.contributions.mapBy('id'));
|
||||||
|
const toFetch = count - lastKnownContributionId;
|
||||||
|
|
||||||
|
if (toFetch > 0) {
|
||||||
|
console.debug(`[kredits] Fetching ${toFetch} new contributions`);
|
||||||
|
for (let id = lastKnownContributionId; id <= count; id++) {
|
||||||
|
const data = yield this.kredits.Contribution.getById(id);
|
||||||
|
const c = this.loadContributionFromData(data);
|
||||||
|
yield this.browserCache.contributions.setItem(c.id.toString(), c.serialize());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.debug(`[kredits] No new contributions to fetch`);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
fetchMissingContributions: task(function * () {
|
||||||
|
const count = yield this.kredits.Contribution.functions.contributionsCount();
|
||||||
|
const allIds = [...Array(count+1).keys()];
|
||||||
|
allIds.shift(); // remove first item, which is 0
|
||||||
|
const loadedContributions = new Set(this.contributions.mapBy('id'));
|
||||||
|
const toFetch = allIds.filter(id => !loadedContributions.has(id));
|
||||||
|
if (toFetch.length === 0) {
|
||||||
|
console.debug(`[kredits] No contributions left to fetch`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.debug(`[kredits] Fetching ${toFetch.length} past contributions`);
|
||||||
|
let countFetched = 0;
|
||||||
|
|
||||||
|
for (let id = count; id > 0; id--) {
|
||||||
|
if (loadedContributions.has(id)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
const data = yield this.kredits.Contribution.getById(id);
|
||||||
|
const c = this.loadContributionFromData(data);
|
||||||
|
yield this.browserCache.contributions.setItem(c.id.toString(), c.serialize());
|
||||||
|
countFetched++;
|
||||||
|
if (countFetched % 20 === 0) {
|
||||||
|
console.debug(`[kredits] Fetched ${countFetched} more contributions`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.debug(`[kredits] Cached ${countFetched} past contributions`);
|
||||||
|
}).group('contributionTasks'),
|
||||||
|
|
||||||
|
syncUnconfirmedContributions: task(function * () {
|
||||||
|
if (this.contributionsUnconfirmed.length > 0) {
|
||||||
|
console.debug(`[kredits] Syncing unconfirmed contributions`);
|
||||||
|
for (const c of this.contributionsUnconfirmed) {
|
||||||
|
const data = yield this.kredits.Contribution.getById(c.id);
|
||||||
|
const contribution = this.loadContributionFromData(data);
|
||||||
|
yield this.browserCache.contributions.setItem(c.id.toString(), contribution.serialize());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.debug(`[kredits] No unconfirmed contributions to sync`);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
veto (contributionId) {
|
veto (contributionId) {
|
||||||
console.debug('[kredits] veto against', contributionId);
|
console.debug('[kredits] veto against', contributionId);
|
||||||
const contribution = this.contributions.findBy('id', contributionId);
|
const contribution = this.contributions.findBy('id', contributionId);
|
||||||
@@ -253,14 +408,14 @@ export default Service.extend({
|
|||||||
|
|
||||||
getCurrentUser: computed('kredits.provider', 'currentUserAccounts.[]', function() {
|
getCurrentUser: computed('kredits.provider', 'currentUserAccounts.[]', function() {
|
||||||
if (isEmpty(this.currentUserAccounts)) {
|
if (isEmpty(this.currentUserAccounts)) {
|
||||||
return RSVP.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return this.kredits.Contributor
|
return this.kredits.Contributor
|
||||||
.functions.getContributorIdByAddress(this.currentUserAccounts.firstObject)
|
.functions.getContributorIdByAddress(this.currentUserAccounts.firstObject)
|
||||||
.then((id) => {
|
.then((id) => {
|
||||||
// check if the user is a contributor or not
|
// check if the user is a contributor or not
|
||||||
if (id === 0) {
|
if (id === 0) {
|
||||||
return RSVP.resolve();
|
return Promise.resolve();
|
||||||
} else {
|
} else {
|
||||||
return this.kredits.Contributor.getById(id);
|
return this.kredits.Contributor.getById(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
@mixin loading-border-top {
|
||||||
|
&::before {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 40%, #68d7fb 60%, rgba(255, 255, 255, 0.2));
|
||||||
|
background-size: 200% 200%;
|
||||||
|
animation: kitt 2.5s linear infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes kitt {
|
||||||
|
0%{ background-position: 0% 0%}
|
||||||
|
50%{ background-position: 100% 0%}
|
||||||
|
100%{ background-position: 0% 0%}
|
||||||
|
}
|
||||||
@@ -88,6 +88,7 @@ section {
|
|||||||
|
|
||||||
@import "buttons";
|
@import "buttons";
|
||||||
@import "forms";
|
@import "forms";
|
||||||
|
@import "sugar";
|
||||||
|
|
||||||
@import "components/contribution-list";
|
@import "components/contribution-list";
|
||||||
@import "components/contribution-details";
|
@import "components/contribution-details";
|
||||||
|
|||||||
@@ -114,4 +114,13 @@ ul.contribution-list {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
@include loading-border-top;
|
||||||
|
|
||||||
|
li {
|
||||||
|
&:first-of-type {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
table.contributor-list {
|
table.contributor-list {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
@@ -48,4 +49,11 @@ table.contributor-list {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
@include loading-border-top;
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<ContributorList @contributorList={{this.kreditsToplist}}
|
<ContributorList @contributorList={{this.kreditsToplist}}
|
||||||
@showUnconfirmedKredits={{this.showUnconfirmedKredits}}
|
@showUnconfirmedKredits={{this.showUnconfirmedKredits}}
|
||||||
@selectedContributorId={{this.selectedContributorId}} />
|
@selectedContributorId={{this.selectedContributorId}}
|
||||||
|
@loading={{this.kredits.syncContributors.isRunning}} />
|
||||||
|
|
||||||
<p class="stats">
|
<p class="stats">
|
||||||
<span class="number">{{await this.kredits.totalKreditsEarned}}</span> kredits confirmed and issued to
|
<span class="number">{{await this.kredits.totalKreditsEarned}}</span> kredits confirmed and issued to
|
||||||
@@ -58,7 +59,9 @@
|
|||||||
{{#if this.contributionsUnconfirmed}}
|
{{#if this.contributionsUnconfirmed}}
|
||||||
<section id="contributions-unconfirmed">
|
<section id="contributions-unconfirmed">
|
||||||
<header class="with-nav">
|
<header class="with-nav">
|
||||||
<h2>Latest Contributions</h2>
|
<h2>
|
||||||
|
Latest Contributions
|
||||||
|
</h2>
|
||||||
<nav>
|
<nav>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
onclick={{action "toggleQuickFilterUnconfirmed"}}
|
onclick={{action "toggleQuickFilterUnconfirmed"}}
|
||||||
@@ -78,7 +81,8 @@
|
|||||||
@vetoContribution={{action "vetoContribution"}}
|
@vetoContribution={{action "vetoContribution"}}
|
||||||
@contractInteractionEnabled={{this.kredits.hasAccounts}}
|
@contractInteractionEnabled={{this.kredits.hasAccounts}}
|
||||||
@selectedContributionId={{this.selectedContributionId}}
|
@selectedContributionId={{this.selectedContributionId}}
|
||||||
@showQuickFilter={{this.showQuickFilterUnconfirmed}} />
|
@showQuickFilter={{this.showQuickFilterUnconfirmed}}
|
||||||
|
@loading={{this.kredits.syncContributions.isRunning}}/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -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]();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
Generated
+2984
-1440
File diff suppressed because it is too large
Load Diff
+13
-11
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "kredits-web",
|
"name": "kredits-web",
|
||||||
"version": "1.16.0",
|
"version": "1.17.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Contribution dashboard of the Kosmos project",
|
"description": "Contribution dashboard of the Kosmos project",
|
||||||
"repository": "https://github.com/67P/kredits-web",
|
"repository": "https://github.com/67P/kredits-web",
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
"@ember/optional-features": "^1.3.0",
|
"@ember/optional-features": "^1.3.0",
|
||||||
"@glimmer/component": "^1.0.0",
|
"@glimmer/component": "^1.0.0",
|
||||||
"@glimmer/tracking": "^1.0.0",
|
"@glimmer/tracking": "^1.0.0",
|
||||||
|
"@kosmos/schemas": "^2.2.1",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-preset-es2015": "^6.22.0",
|
"babel-preset-es2015": "^6.22.0",
|
||||||
"babelify": "^7.3.0",
|
"babelify": "^7.3.0",
|
||||||
@@ -38,42 +39,43 @@
|
|||||||
"ember-awesome-macros": "0.41.0",
|
"ember-awesome-macros": "0.41.0",
|
||||||
"ember-cli": "~3.18.0",
|
"ember-cli": "~3.18.0",
|
||||||
"ember-cli-app-version": "^3.2.0",
|
"ember-cli-app-version": "^3.2.0",
|
||||||
"ember-cli-babel": "^7.19.0",
|
"ember-cli-babel": "^7.20.4",
|
||||||
"ember-cli-chart": "^3.6.0",
|
"ember-cli-chart": "^3.6.0",
|
||||||
"ember-cli-dependency-checker": "^3.2.0",
|
"ember-cli-dependency-checker": "^3.2.0",
|
||||||
"ember-cli-htmlbars": "^4.3.1",
|
"ember-cli-htmlbars": "^5.1.2",
|
||||||
"ember-cli-inject-live-reload": "^2.0.2",
|
"ember-cli-inject-live-reload": "^2.0.2",
|
||||||
"ember-cli-moment-shim": "^3.7.1",
|
"ember-cli-moment-shim": "^3.8.0",
|
||||||
"ember-cli-sass": "^10.0.1",
|
"ember-cli-sass": "^10.0.1",
|
||||||
"ember-cli-sri": "^2.1.1",
|
"ember-cli-sri": "^2.1.1",
|
||||||
"ember-cli-uglify": "^3.0.0",
|
"ember-cli-uglify": "^3.0.0",
|
||||||
|
"ember-concurrency": "^1.1.7",
|
||||||
"ember-export-application-global": "^2.0.1",
|
"ember-export-application-global": "^2.0.1",
|
||||||
"ember-fetch": "^8.0.1",
|
"ember-fetch": "^8.0.1",
|
||||||
"ember-flatpickr": "^2.16.2",
|
"ember-flatpickr": "^2.16.2",
|
||||||
"ember-load-initializers": "^2.1.1",
|
"ember-load-initializers": "^2.1.1",
|
||||||
"ember-macro-helpers": "0.17.0",
|
"ember-macro-helpers": "0.17.0",
|
||||||
"ember-maybe-import-regenerator": "^0.1.6",
|
"ember-maybe-import-regenerator": "^0.1.6",
|
||||||
"ember-moment": "^7.8.1",
|
"ember-moment": "^8.0.0",
|
||||||
"ember-promise-helpers": "^1.0.9",
|
"ember-promise-helpers": "^1.0.9",
|
||||||
"ember-qunit": "^4.6.0",
|
"ember-qunit": "^4.6.0",
|
||||||
"ember-resolver": "^8.0.0",
|
"ember-resolver": "^8.0.0",
|
||||||
"ember-source": "~3.18.0",
|
"ember-source": "~3.18.0",
|
||||||
"ember-template-lint": "^2.6.0",
|
"ember-template-lint": "^2.8.0",
|
||||||
"ember-truth-helpers": "github:jmurphyau/ember-truth-helpers#31a14373a31f1f82c77537720549b47a95c28e5f",
|
"ember-truth-helpers": "github:jmurphyau/ember-truth-helpers#31a14373a31f1f82c77537720549b47a95c28e5f",
|
||||||
"eslint": "^7.0.0",
|
"eslint": "^7.1.0",
|
||||||
"eslint-plugin-ember": "^8.4.0",
|
"eslint-plugin-ember": "^8.5.2",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"ethers": "^4.0.47",
|
"ethers": "^4.0.47",
|
||||||
"kosmos-schemas": "^2.1.0",
|
|
||||||
"kredits-contracts": "^5.5.0",
|
"kredits-contracts": "^5.5.0",
|
||||||
"loader.js": "^4.7.0",
|
"loader.js": "^4.7.0",
|
||||||
|
"localforage": "^1.7.3",
|
||||||
"ndjson": "github:hugomrdias/ndjson#feat/readable-stream3",
|
"ndjson": "github:hugomrdias/ndjson#feat/readable-stream3",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"qunit-dom": "^1.2.0",
|
"qunit-dom": "^1.2.0",
|
||||||
"sass": "^1.26.5",
|
"sass": "^1.26.7",
|
||||||
"transform-loader": "^0.2.4",
|
"transform-loader": "^0.2.4",
|
||||||
"tv4": "^1.3.0",
|
"tv4": "^1.3.0",
|
||||||
"web3-utils": "^1.2.7"
|
"web3-utils": "^1.2.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "10.* || >= 12"
|
"node": "10.* || >= 12"
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+176
-65
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2445
-1873
File diff suppressed because one or more lines are too long
+4
-4
@@ -8,10 +8,10 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
|
|
||||||
|
|
||||||
<meta name="kredits-web/config/environment" content="%7B%22modulePrefix%22%3A%22kredits-web%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22auto%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_DEFAULT_ASYNC_OBSERVERS%22%3Atrue%2C%22_JQUERY_INTEGRATION%22%3Afalse%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22name%22%3A%22kredits-web%22%2C%22version%22%3A%221.16.0%2B41cc37d3%22%7D%2C%22browserify%22%3A%7B%22tests%22%3Atrue%2C%22transform%22%3A%5B%5B%22babelify%22%2C%7B%22presets%22%3A%5B%22es2015%22%5D%2C%22global%22%3Atrue%7D%5D%5D%7D%2C%22web3ProviderUrl%22%3A%22https%3A%2F%2Frinkeby.infura.io%2Fv3%2Fd4f788b7a6584f7db2fc3c268d4d09e9%22%2C%22web3RequiredNetwork%22%3A%22rinkeby%22%2C%22githubConnectUrl%22%3A%22https%3A%2F%2Fhal8000.chat.kosmos.org%2Fkredits%2Fsignup%2Fconnect%2Fgithub%22%2C%22githubSignupUrl%22%3A%22https%3A%2F%2Fhal8000.chat.kosmos.org%2Fkredits%2Fsignup%2Fgithub%22%2C%22ipfs%22%3A%7B%22host%22%3A%22ipfs.kosmos.org%22%2C%22port%22%3A%225444%22%2C%22protocol%22%3A%22https%22%2C%22gatewayUrl%22%3A%22https%3A%2F%2Fipfs.kosmos.org%2Fipfs%22%7D%2C%22exportApplicationGlobal%22%3Afalse%7D" />
|
<meta name="kredits-web/config/environment" content="%7B%22modulePrefix%22%3A%22kredits-web%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%22%2C%22locationType%22%3A%22auto%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_DEFAULT_ASYNC_OBSERVERS%22%3Atrue%2C%22_JQUERY_INTEGRATION%22%3Afalse%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22name%22%3A%22kredits-web%22%2C%22version%22%3A%221.17.0%2B733e5e36%22%7D%2C%22browserify%22%3A%7B%22tests%22%3Atrue%2C%22transform%22%3A%5B%5B%22babelify%22%2C%7B%22presets%22%3A%5B%22es2015%22%5D%2C%22global%22%3Atrue%7D%5D%5D%7D%2C%22web3ProviderUrl%22%3A%22https%3A%2F%2Frinkeby.infura.io%2Fv3%2Fd4f788b7a6584f7db2fc3c268d4d09e9%22%2C%22web3RequiredNetwork%22%3A%22rinkeby%22%2C%22githubConnectUrl%22%3A%22https%3A%2F%2Fhal8000.chat.kosmos.org%2Fkredits%2Fsignup%2Fconnect%2Fgithub%22%2C%22githubSignupUrl%22%3A%22https%3A%2F%2Fhal8000.chat.kosmos.org%2Fkredits%2Fsignup%2Fgithub%22%2C%22ipfs%22%3A%7B%22host%22%3A%22ipfs.kosmos.org%22%2C%22port%22%3A%225444%22%2C%22protocol%22%3A%22https%22%2C%22gatewayUrl%22%3A%22https%3A%2F%2Fipfs.kosmos.org%2Fipfs%22%7D%2C%22exportApplicationGlobal%22%3Afalse%7D" />
|
||||||
|
|
||||||
<link integrity="" rel="stylesheet" href="/assets/vendor-ca96b2e19fc9f356e3dbad90c9f3f323.css">
|
<link integrity="" rel="stylesheet" href="/assets/vendor-ca96b2e19fc9f356e3dbad90c9f3f323.css">
|
||||||
<link integrity="" rel="stylesheet" href="/assets/kredits-web-8440190dda6de1748075524fe140b4ee.css">
|
<link integrity="" rel="stylesheet" href="/assets/kredits-web-f225d49328a14feac0888a2126087423.css">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|
||||||
<script src="/assets/vendor-5ebca0a713676bf484d729ec58e9d74b.js" integrity="sha256-K9BPrQzg0Nv83HSPUwk2n1hU8IOaceDf03EaU5LgblQ= sha512-stOJYOdJfiuzleqChwK9pNLCVMQwg9sZXUSboTsvtIixnRoQ285yS080rRX/GfcRd/eI0TEpPI0XKqvN56kzLA==" ></script>
|
<script src="/assets/vendor-c96bc8b15817400d8cb58a32671bab0c.js" integrity="sha256-vRS2UvkDzerqXqzdCMPtGtxCDFflTcDv9xfi/8NLKJw= sha512-GWfVwFu8LhNRJyijvRuow7f38ARQGGCU0uKzB7HwiX+pQF6Vw5zSfZHtlfZiucFImmb2uyxSexiXkh16ulShEw==" ></script>
|
||||||
<script src="/assets/kredits-web-d376614e43d3edec456b90f7efdfedf4.js" integrity="sha256-ZUj9gy+521ioE0n+gKl53UrRqVALwY7YTOonD2SjZfg= sha512-0G4MUqxkZ+yazboR03+jfA9BRKoyKh2/IgG9iAVttTfVZRyMTHqiFnGlG00KY72H0y2jVamQtgY6UpLgAohGLg==" ></script>
|
<script src="/assets/kredits-web-b7d7786c26ec2d9d78fc58c35d4e9c59.js" integrity="sha256-IUbTJl1JYq98BlScoUafRjtznFRb4LOaGC0weMP0ycU= sha512-kzcGqMHh8+3DLnSeTwK3Mw6Nr+JZw0EEjfMGx+c/D1OkAVvuKXYmUKq1b5XgFw+lQ7cDkGLiAb4ud6O4DpT3Jg==" ></script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Vendored
+391
File diff suppressed because one or more lines are too long
Vendored
+13
-11
@@ -1,23 +1,25 @@
|
|||||||
import Model from 'kredits-web/models/contribution';
|
import Model from 'kredits-web/models/contribution';
|
||||||
import contributors from '../../tests/fixtures/contributors';
|
import contributors from '../../tests/fixtures/contributors';
|
||||||
|
import processContributionData from 'kredits-web/utils/process-contribution-data';
|
||||||
|
|
||||||
const items = [];
|
const items = [];
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{ id: 1, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'dev' },
|
{ id: 1, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'dev' },
|
||||||
{ id: 2, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'ops' },
|
{ id: 2, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'ops' },
|
||||||
{ id: 3, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'ops' },
|
{ id: 3, contributorId: 2, confirmedAt: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'ops' },
|
||||||
{ id: 4, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'docs' },
|
{ id: 4, contributorId: 2, confirmedAt: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'docs' },
|
||||||
{ id: 5, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'design' },
|
{ id: 5, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'design' },
|
||||||
{ id: 6, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: true, amount: 500, kind: 'dev' },
|
{ id: 6, contributorId: 1, confirmedAt: 1000, claimed: false, vetoed: true, amount: 500, kind: 'dev' },
|
||||||
{ id: 7, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 5000, kind: 'dev' },
|
{ id: 7, contributorId: 3, confirmedAt: 2000, claimed: false, vetoed: false, amount: 5000, kind: 'dev' },
|
||||||
{ id: 8, contributorId: 1, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 1500, kind: 'community' },
|
{ id: 8, contributorId: 1, confirmedAt: 2000, claimed: false, vetoed: false, amount: 1500, kind: 'community' },
|
||||||
{ id: 9, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: true, amount: 1500, kind: 'docs' },
|
{ id: 9, contributorId: 3, confirmedAt: 2000, claimed: false, vetoed: true, amount: 1500, kind: 'docs' },
|
||||||
];
|
];
|
||||||
|
|
||||||
data.forEach(attrs => {
|
data.forEach(attrs => {
|
||||||
attrs.contributor = contributors.findBy('id', attrs.contributorId.toString());
|
const c = Model.create(processContributionData(attrs));
|
||||||
items.push(Model.create(attrs))
|
c.set('contributor', contributors.findBy('id', attrs.contributorId.toString()));
|
||||||
|
items.push(c);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default items;
|
export default items;
|
||||||
|
|||||||
Vendored
+64
@@ -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}"
|
||||||
|
}
|
||||||
Vendored
+8
-4
@@ -1,13 +1,17 @@
|
|||||||
import Contributor from 'kredits-web/models/contributor';
|
import Contributor from 'kredits-web/models/contributor';
|
||||||
|
import processContributorData from 'kredits-web/utils/process-contributor-data';
|
||||||
|
|
||||||
const contributors = [];
|
const contributors = [];
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{ id: 1, name: 'Bumi', totalKreditsEarned: 11500, github_uid: 318 },
|
{ id: '1', name: 'Bumi', totalKreditsEarned: 11500, github_uid: 318 },
|
||||||
{ id: 2, name: 'Râu Cao', totalKreditsEarned: 3000, github_uid: 842 },
|
{ id: '2', name: 'Râu Cao', totalKreditsEarned: 3000, github_uid: 842 },
|
||||||
{ id: 3, name: 'Manuel', totalKreditsEarned: 0, github_uid: 54812 }
|
{ 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;
|
export default contributors;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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:rinkeby:contributors");
|
||||||
|
assert.equal(cache.contributions._config.name, "kredits:rinkeby:contributions");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user