Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d35cab0a67 | |||
| b4a094bc89 | |||
| e43706e2a6 | |||
| 2befc91d90 | |||
| 7a35f5177c | |||
| 6efc3ea790 | |||
| ef0f3ffbfb | |||
| 1e14cc695e | |||
| c074ccf460 | |||
| 5436469128 | |||
| 32714efeb9 | |||
| cf777571dc | |||
| 44b4340a91 | |||
| 24e3171311 |
@@ -0,0 +1,59 @@
|
|||||||
|
import Component from '@ember/component';
|
||||||
|
import { computed } from '@ember/object';
|
||||||
|
|
||||||
|
let categoryColors = {
|
||||||
|
community: "#fb6868",
|
||||||
|
design: "#fbe468",
|
||||||
|
dev: "#e068fb",
|
||||||
|
docs: "#97fb68",
|
||||||
|
ops: "#8f68fb",
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
|
||||||
|
contributions: null,
|
||||||
|
|
||||||
|
chartData: computed('contributions', function() {
|
||||||
|
let kredits = this.get('contributions')
|
||||||
|
.map(c => {
|
||||||
|
return { kind: c.kind, amount: c.amount }
|
||||||
|
}).reduce(function (kinds, c) {
|
||||||
|
kinds[c.kind] = (kinds[c.kind] || 0) + c.amount;
|
||||||
|
return kinds;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return {
|
||||||
|
datasets: [{
|
||||||
|
data: [
|
||||||
|
kredits['community'],
|
||||||
|
kredits['design'],
|
||||||
|
kredits['dev'],
|
||||||
|
kredits['ops'],
|
||||||
|
kredits['docs'],
|
||||||
|
],
|
||||||
|
borderColor: [
|
||||||
|
categoryColors.community,
|
||||||
|
categoryColors.design,
|
||||||
|
categoryColors.dev,
|
||||||
|
categoryColors.ops,
|
||||||
|
categoryColors.docs,
|
||||||
|
],
|
||||||
|
borderWidth: 1
|
||||||
|
}],
|
||||||
|
labels: [
|
||||||
|
'Community',
|
||||||
|
'Design',
|
||||||
|
'Development',
|
||||||
|
'Operations & Infrastructure',
|
||||||
|
'Documentation'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
chartOptions: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<div class="chart">
|
||||||
|
{{ember-chart type='doughnut'
|
||||||
|
data=chartData
|
||||||
|
options=chartOptions
|
||||||
|
width=200
|
||||||
|
height=200}}
|
||||||
|
</div>
|
||||||
@@ -1,30 +1,20 @@
|
|||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import { inject } from '@ember/service';
|
|
||||||
import { empty } from '@ember/object/computed';
|
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
kredits: inject(),
|
|
||||||
|
|
||||||
tagName: 'ul',
|
tagName: 'ul',
|
||||||
classNames: ['proposal-list'],
|
classNames: ['proposal-list'],
|
||||||
|
|
||||||
selectedProposals: [],
|
|
||||||
submitButtonDisabled: empty('selectedProposals'),
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
confirm() {
|
|
||||||
this.confirmProposals(this.selectedProposals)
|
|
||||||
.then(() => {
|
|
||||||
this.selectedProposals = [];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleSelect(proposalId, selected) {
|
confirm(proposalId) {
|
||||||
if (selected) {
|
if (this.contractInteractionEnabled) {
|
||||||
this.selectedProposals.removeObject(proposalId);
|
this.confirmProposal(proposalId);
|
||||||
} else {
|
} else {
|
||||||
this.selectedProposals.addObject(proposalId);
|
window.alert('Only members can vote on proposals. Please ask someone to set you up.');
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
import Component from '@ember/component';
|
|
||||||
import tag from 'ember-awesome-macros/tag';
|
|
||||||
import { computed } from '@ember/object';
|
|
||||||
import { reads } from '@ember/object/computed';
|
|
||||||
import { inject } from '@ember/service';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
kredits: inject(),
|
|
||||||
|
|
||||||
tagName: 'li',
|
|
||||||
classNames: ['proposal-list-item'],
|
|
||||||
|
|
||||||
attributeBindings: ['data-proposal-id', 'title'],
|
|
||||||
|
|
||||||
title: tag`(${'proposal.kind'}) ${'proposal.description'}`,
|
|
||||||
'data-proposal-id': reads('proposal.id'),
|
|
||||||
|
|
||||||
canBeVoted: computed('voterIds.[]', 'kredits.currentUser', function() {
|
|
||||||
let { isExecuted, voterIds } = this.proposal;
|
|
||||||
let { currentUser } = this.kredits;
|
|
||||||
voterIds = voterIds.map((id) => id.toString());
|
|
||||||
|
|
||||||
return currentUser.isCore && !isExecuted && !voterIds.includes(currentUser.id);
|
|
||||||
}),
|
|
||||||
|
|
||||||
selected: computed('selectedProposals.[]', function() {
|
|
||||||
return this.selectedProposals.includes(this.proposal.id);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<span class="category {{proposal.kind}}">♥</span>
|
|
||||||
<span class="amount">{{proposal.amount}}</span><span class="symbol">₭S</span>
|
|
||||||
for <span class="recipient">{{proposal.contributor.name}}</span>
|
|
||||||
<span class="votes">({{proposal.votesCount}}/{{proposal.votesNeeded}} votes)</span>
|
|
||||||
|
|
||||||
{{#if canBeVoted}}
|
|
||||||
<button {{action toggleSelect proposal.id selected}} class="{{if selected 'selected' ''}}">+1</button>
|
|
||||||
{{/if}}
|
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
{{#each proposals as |proposal|}}
|
{{#each proposals as |proposal|}}
|
||||||
{{proposal-list/item
|
<li data-proposal-id={{proposal.id}} class={{if proposal.isExecuted "confirmed" "unconfirmed"}}>
|
||||||
proposal=proposal
|
<p class="meta">
|
||||||
selectedProposals=selectedProposals
|
<span class="category {{proposal.kind}}">♥ ({{proposal.kind}})</span>
|
||||||
toggleSelect=(action 'toggleSelect')
|
<span class="recipient">{{proposal.contributor.name}}:</span>
|
||||||
}}
|
|
||||||
{{/each}}
|
|
||||||
|
|
||||||
{{#if confirmProposals}}
|
|
||||||
<p class="actions">
|
|
||||||
<input type="submit" disabled={{submitButtonDisabled}}
|
|
||||||
value="Confirm selected" {{action 'confirm'}}>
|
|
||||||
</p>
|
</p>
|
||||||
{{/if}}
|
<p class="kredits-amount">
|
||||||
|
<span class="amount">{{proposal.amount}}</span><span class="symbol">₭S</span>
|
||||||
|
</p>
|
||||||
|
<p class="description">
|
||||||
|
<span class="description">{{proposal.description}}</span>
|
||||||
|
</p>
|
||||||
|
<p class="voting">
|
||||||
|
{{#unless proposal.isExecuted}}
|
||||||
|
<span class="votes">({{proposal.votesCount}}/{{proposal.votesNeeded}} votes)</span>
|
||||||
|
<button {{action "confirm" proposal.id}}>+1</button>
|
||||||
|
{{/unless}}
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import Controller from '@ember/controller';
|
import Controller from '@ember/controller';
|
||||||
|
import { inject as injectService } from '@ember/service';
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
|
kredits: injectService(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import Controller from '@ember/controller';
|
import Controller from '@ember/controller';
|
||||||
import { alias, filter, filterBy, sort } from '@ember/object/computed';
|
import { alias, filter, filterBy, sort } from '@ember/object/computed';
|
||||||
import { inject as injectService } from '@ember/service';
|
import { inject as injectService } from '@ember/service';
|
||||||
import RSVP from 'rsvp';
|
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
kredits: injectService(),
|
kredits: injectService(),
|
||||||
@@ -21,17 +20,10 @@ export default Controller.extend({
|
|||||||
proposalsOpenSorted: sort('proposalsOpen', 'proposalsSorting'),
|
proposalsOpenSorted: sort('proposalsOpen', 'proposalsSorting'),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
confirmProposals(proposalIds) {
|
confirmProposal(proposalId) {
|
||||||
if (this.kredits.currentUser.isCore) {
|
this.kredits.vote(proposalId).then(transaction => {
|
||||||
return this.kredits.batchVote(proposalIds)
|
|
||||||
.then((transaction) => {
|
|
||||||
window.confirm('Vote submitted to Ethereum blockhain: '+transaction.hash);
|
window.confirm('Vote submitted to Ethereum blockhain: '+transaction.hash);
|
||||||
return transaction;
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
window.alert('Only members can vote on proposals. Please ask someone to set you up.');
|
|
||||||
return RSVP.reject();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
save(contributor) {
|
save(contributor) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import RSVP from 'rsvp';
|
|||||||
|
|
||||||
import Service from '@ember/service';
|
import Service from '@ember/service';
|
||||||
import { computed } from '@ember/object';
|
import { computed } from '@ember/object';
|
||||||
import { notEmpty } from '@ember/object/computed';
|
import { alias, notEmpty } from '@ember/object/computed';
|
||||||
import { isEmpty } from '@ember/utils';
|
import { isEmpty } from '@ember/utils';
|
||||||
|
|
||||||
import config from 'kredits-web/config/environment';
|
import config from 'kredits-web/config/environment';
|
||||||
@@ -16,6 +16,8 @@ export default Service.extend({
|
|||||||
|
|
||||||
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,
|
||||||
|
currentUserIsContributor: notEmpty('currentUser'),
|
||||||
|
currentUserIsCore: alias('currentUser.isCore'),
|
||||||
hasAccounts: notEmpty('currentUserAccounts'),
|
hasAccounts: notEmpty('currentUserAccounts'),
|
||||||
accountNeedsUnlock: computed('currentUserAccounts', function() {
|
accountNeedsUnlock: computed('currentUserAccounts', function() {
|
||||||
return this.currentUserAccounts && isEmpty(this.currentUserAccounts);
|
return this.currentUserAccounts && isEmpty(this.currentUserAccounts);
|
||||||
@@ -70,7 +72,7 @@ export default Service.extend({
|
|||||||
this.set('kredits', kredits);
|
this.set('kredits', kredits);
|
||||||
if (this.currentUserAccounts && this.currentUserAccounts.length > 0) {
|
if (this.currentUserAccounts && this.currentUserAccounts.length > 0) {
|
||||||
this.getCurrentUser.then((contributorData) => {
|
this.getCurrentUser.then((contributorData) => {
|
||||||
this.set('currentUser', Contributor.create(contributorData));
|
this.set('currentUser', contributorData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return kredits;
|
return kredits;
|
||||||
@@ -132,11 +134,10 @@ export default Service.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
batchVote(proposalIds) {
|
vote(proposalId) {
|
||||||
proposalIds = proposalIds.map((id) => parseInt(id))
|
console.debug('[kredits] vote for', proposalId);
|
||||||
console.debug('[kredits] vote for', proposalIds);
|
|
||||||
|
|
||||||
return this.kredits.Operator.functions.batchVote(proposalIds)
|
return this.kredits.Operator.functions.vote(proposalId)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.debug('[kredits] vote response', data);
|
console.debug('[kredits] vote response', data);
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
+14
-1
@@ -5,4 +5,17 @@ $green: #97fb68;
|
|||||||
$yellow: #fbe468;
|
$yellow: #fbe468;
|
||||||
$red: #fb6868;
|
$red: #fb6868;
|
||||||
|
|
||||||
$primaryColor: $blue;
|
$primary-color: $blue;
|
||||||
|
|
||||||
|
$body-text-color: #fff;
|
||||||
|
|
||||||
|
@mixin body-background {
|
||||||
|
background-image: linear-gradient(to bottom, rgba(22, 21, 40, .4), rgba(0, 0, 0, .75)), url('/img/bg.jpg');
|
||||||
|
background-repeat: none;
|
||||||
|
background-attachment: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#topbar {
|
||||||
|
background-color: rgba(255, 0, 255, .2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
button, input[type=submit] {
|
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid rgba(22, 21, 40, 1);
|
|
||||||
background-color: rgba(22, 21, 40, 0.6);
|
|
||||||
color: $primaryColor;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-weight: 500;
|
|
||||||
text-transform: uppercase;
|
|
||||||
cursor: pointer;
|
|
||||||
letter-spacing: 0.1em;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(22, 21, 40, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=submit] {
|
|
||||||
padding: 0.6rem 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=text], select {
|
|
||||||
width: 100%;
|
|
||||||
padding: 1rem;
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
|
||||||
background-color: rgba(22, 21, 40, 0.3);
|
|
||||||
color: #fff;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
&:focus, &.valid {
|
|
||||||
background-color: rgba(22, 21, 40, 0.6);
|
|
||||||
}
|
|
||||||
@include placeholder {
|
|
||||||
color: rgba(238, 238, 238, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: rgba(22, 21, 40, 0.6);
|
|
||||||
background-image:
|
|
||||||
linear-gradient(45deg, transparent 50%, gray 50%),
|
|
||||||
linear-gradient(135deg, gray 50%, transparent 50%);
|
|
||||||
background-position:
|
|
||||||
calc(100% - 1.5rem) calc(1rem + 0.5rem),
|
|
||||||
calc(100% - 1rem) calc(1rem + 0.5rem);
|
|
||||||
background-size:
|
|
||||||
0.5rem 0.5rem,
|
|
||||||
0.5rem 0.5rem;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
|
|
||||||
&:invalid {
|
|
||||||
color: rgba(238, 238, 238, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=checkbox] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
label.checkbox {
|
|
||||||
line-height: 3.2rem;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
&::before {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 0.8rem;
|
|
||||||
height: 3.2rem;
|
|
||||||
width: 3.2rem;
|
|
||||||
font-size: 2rem;
|
|
||||||
background-color: rgba(22, 21, 40, 0.3);
|
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
|
||||||
text-align: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
content: '✓';
|
|
||||||
color: rgba(255,255,255,0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=checkbox]:checked + label.checkbox {
|
|
||||||
&::before {
|
|
||||||
background-color: rgba(22, 21, 40, 0.6);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+36
-14
@@ -1,31 +1,53 @@
|
|||||||
section {
|
#topbar {
|
||||||
@include outer-container;
|
height: 3rem;
|
||||||
margin-bottom: 8rem;
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
&#index {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-row-gap: 2rem;
|
||||||
|
grid-template-areas:
|
||||||
|
"stats"
|
||||||
|
"contributions";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 550px) {
|
||||||
|
main {
|
||||||
|
&#index {
|
||||||
|
grid-column-gap: 4rem;
|
||||||
|
grid-row-gap: 2rem;
|
||||||
|
grid-template-columns: 2fr 4fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"stats contributions";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main section {
|
||||||
|
margin-bottom: 5rem;
|
||||||
|
|
||||||
&:first-of-type {
|
&:first-of-type {
|
||||||
margin-top: 6rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media($mobile) {
|
@include media($mobile) {
|
||||||
margin-bottom: 5rem;
|
margin-bottom: 5rem;
|
||||||
&:first-of-type {
|
|
||||||
margin-top: 2rem;
|
&#proposals-open, &#proposals-closed {
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
@include span-columns(12);
|
|
||||||
padding-bottom: 3rem;
|
padding-bottom: 3rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
// background-color: purple;
|
|
||||||
|
|
||||||
@include media($mobile) {
|
@include media($mobile) {
|
||||||
@include span-columns(10);
|
|
||||||
@include shift(1);
|
|
||||||
padding-bottom: 2rem;
|
padding-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.content {
|
|
||||||
@include span-columns(12);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-14
@@ -2,6 +2,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
*:hover, *:active, *:focus {
|
*:hover, *:active, *:focus {
|
||||||
@@ -20,13 +21,10 @@
|
|||||||
$font-family-sans: 'Open Sans', sans-serif;
|
$font-family-sans: 'Open Sans', sans-serif;
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-image: url('/img/bg.jpg');
|
@include body-background;
|
||||||
background-repeat: none;
|
|
||||||
background-attachment: fixed;
|
|
||||||
font-family: $font-family-sans;
|
font-family: $font-family-sans;
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
color: #fff;
|
color: $body-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 900px) {
|
@media screen and (min-width: 900px) {
|
||||||
@@ -43,14 +41,11 @@ h1, h2, h3, h4, h5, input, button {
|
|||||||
|
|
||||||
section {
|
section {
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 2.8rem;
|
font-size: 1.4rem;
|
||||||
color: $primaryColor;
|
color: $primary-color;
|
||||||
@include media($mobile) {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&#contributors {
|
&#people {
|
||||||
.content {
|
.content {
|
||||||
p.stats {
|
p.stats {
|
||||||
padding-top: 3rem;
|
padding-top: 3rem;
|
||||||
@@ -67,25 +62,60 @@ section {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&#contributions-by-type {
|
||||||
|
.chart {
|
||||||
|
width: 50%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media($mobile) {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&#proposals-open, &#proposals-closed {
|
&#proposals-open, &#proposals-closed {
|
||||||
.actions {
|
.actions {
|
||||||
padding-top: 3rem;
|
padding-top: 3rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: $primaryColor;
|
color: $primary-color;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@include media($mobile) {
|
@include media($mobile) {
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $primaryColor;
|
color: $primary-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "forms";
|
button, input[type=submit] {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid rgba(22, 21, 40, 1);
|
||||||
|
background-color: rgba(22, 21, 40, 0.6);
|
||||||
|
color: $primary-color;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(22, 21, 40, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 550px) {
|
||||||
|
section {
|
||||||
|
h2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@import "components/topbar";
|
||||||
@import "components/loading-spinner";
|
@import "components/loading-spinner";
|
||||||
@import "components/contributor-list";
|
@import "components/contributor-list";
|
||||||
@import "components/add-contributor";
|
@import "components/add-contributor";
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
section#add-contributor, section#add-proposal {
|
section#add-contributor, section#add-proposal {
|
||||||
|
|
||||||
form {
|
form {
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
@@ -8,11 +9,86 @@ section#add-contributor, section#add-proposal {
|
|||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
a {
|
a {
|
||||||
color: $primaryColor;
|
color: $primary-color;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type=text], select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||||
|
background-color: rgba(22, 21, 40, 0.3);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
&:focus, &.valid {
|
||||||
|
background-color: rgba(22, 21, 40, 0.6);
|
||||||
|
}
|
||||||
|
@include placeholder {
|
||||||
|
color: rgba(238, 238, 238, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border-radius: 0;
|
||||||
|
background-color: rgba(22, 21, 40, 0.6);
|
||||||
|
background-image:
|
||||||
|
linear-gradient(45deg, transparent 50%, gray 50%),
|
||||||
|
linear-gradient(135deg, gray 50%, transparent 50%);
|
||||||
|
background-position:
|
||||||
|
calc(100% - 1.5rem) calc(1rem + 0.5rem),
|
||||||
|
calc(100% - 1rem) calc(1rem + 0.5rem);
|
||||||
|
background-size:
|
||||||
|
0.5rem 0.5rem,
|
||||||
|
0.5rem 0.5rem;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
|
||||||
|
&:invalid {
|
||||||
|
color: rgba(238, 238, 238, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=submit] {
|
||||||
|
padding: 0.6rem 2rem;
|
||||||
|
&:disabled {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=checkbox] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.checkbox {
|
||||||
|
line-height: 3.2rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
&::before {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 0.8rem;
|
||||||
|
height: 3.2rem;
|
||||||
|
width: 3.2rem;
|
||||||
|
font-size: 2rem;
|
||||||
|
background-color: rgba(22, 21, 40, 0.3);
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
content: '✓';
|
||||||
|
color: rgba(255,255,255,0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=checkbox]:checked + label.checkbox {
|
||||||
|
&::before {
|
||||||
|
background-color: rgba(22, 21, 40, 0.6);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ table.contributor-list {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $primaryColor;
|
color: $primary-color;
|
||||||
&:hover, &:active {
|
&:hover, &:active {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
margin-top: 12rem;
|
margin-top: 12rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
color: $primaryColor;
|
color: $primary-color;
|
||||||
|
|
||||||
@include media($mobile) {
|
@include media($mobile) {
|
||||||
margin-top: 6rem;
|
margin-top: 6rem;
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
#path-comet {
|
#path-comet {
|
||||||
fill: $primaryColor;
|
fill: $primary-color;
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
|
|
||||||
animation-name: pulse;
|
animation-name: pulse;
|
||||||
|
|||||||
@@ -4,16 +4,46 @@ ul.proposal-list {
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
// display: block;
|
display: grid;
|
||||||
padding: 0 1.2rem;
|
grid-template-columns: auto 5rem;
|
||||||
line-height: 4.2rem;
|
grid-row-gap: 0.5rem;
|
||||||
|
padding: 1rem 1.2rem;
|
||||||
background-color: rgba(255,255,255,0.1);
|
background-color: rgba(255,255,255,0.1);
|
||||||
font-size: 1.4rem;
|
font-size: 1.2rem;
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||||
|
|
||||||
&:first-of-type {
|
&:first-of-type {
|
||||||
border-top: 1px solid rgba(255,255,255,0.2);
|
border-top: 1px solid rgba(255,255,255,0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
align-self: center;
|
||||||
|
margin: 0;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: 2rem;
|
||||||
|
|
||||||
|
&.kredits-amount, &.voting {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.description {
|
||||||
|
grid-column-start: span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.voting {
|
||||||
|
grid-column-start: span 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
line-height: 1.4em;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.category {
|
.category {
|
||||||
color: $blue;
|
color: $blue;
|
||||||
padding-right: 0.2rem;
|
padding-right: 0.2rem;
|
||||||
@@ -23,34 +53,68 @@ ul.proposal-list {
|
|||||||
&.docs { color: $green; }
|
&.docs { color: $green; }
|
||||||
&.ops { color: $purple; }
|
&.ops { color: $purple; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.amount {
|
.amount {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.symbol {
|
.symbol {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding-left: 0.2rem;
|
padding-left: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipient {
|
.recipient {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.votes {
|
.votes {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: $primaryColor;
|
color: $primary-color;
|
||||||
padding-left: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
float: right;
|
|
||||||
margin-top: 1.1rem;
|
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
padding: 0 0.6rem;
|
padding: 0 0.6rem;
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: rgba(224,104,251, 0.6);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 550px) {
|
||||||
|
ul.proposal-list {
|
||||||
|
li {
|
||||||
|
grid-template-columns: auto 10rem;
|
||||||
|
grid-row-gap: 0.5rem;
|
||||||
|
|
||||||
|
p {
|
||||||
|
&.kredits-amount, &.voting {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.unconfirmed {
|
||||||
|
p {
|
||||||
|
&.kredits-amount, &.voting {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.description {
|
||||||
|
grid-column-start: span 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.voting {
|
||||||
|
grid-column-start: span 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#topbar {
|
||||||
|
padding: 0 1rem;
|
||||||
|
line-height: 3rem;
|
||||||
|
background-color: rgba(0,0,0,.3);
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
display: inline-block;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#user-account {
|
||||||
|
display: inline-block;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,4 +2,4 @@
|
|||||||
// $visual-grid-color: red;
|
// $visual-grid-color: red;
|
||||||
// $visual-grid-index: front;
|
// $visual-grid-index: front;
|
||||||
// $visual-grid-opacity: 0.5;
|
// $visual-grid-opacity: 0.5;
|
||||||
$max-width: em(500, 12);
|
$max-width: em(1200, 12);
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
<main>
|
<header id="topbar">
|
||||||
|
<h1>Kosmos Kredits</h1>
|
||||||
|
|
||||||
|
<section id="user-account">
|
||||||
|
{{#if kredits.hasAccounts }}
|
||||||
|
{{#if kredits.currentUser}}
|
||||||
|
{{kredits.currentUser.name}}
|
||||||
|
{{#if kredits.currentUserIsCore}}(core){{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
Anonymous
|
||||||
|
{{/if}}
|
||||||
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
</main>
|
|
||||||
|
|||||||
+27
-25
@@ -1,18 +1,9 @@
|
|||||||
{{#if kredits.hasAccounts }}
|
<main id="index">
|
||||||
<section id="user-account">
|
|
||||||
{{#if kredits.currentUser }}
|
|
||||||
{{ kredits.currentUser.name }}
|
|
||||||
{{#if kredits.currentUser.isCore }}
|
|
||||||
(core)
|
|
||||||
{{/if}}
|
|
||||||
Account: {{kredits.currentUser.account}}
|
|
||||||
{{/if}}
|
|
||||||
</section>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<section id="contributors">
|
<div id="stats">
|
||||||
|
<section id="people">
|
||||||
<header>
|
<header>
|
||||||
<h2>Kosmos Contributors</h2>
|
<h2>Contributors</h2>
|
||||||
</header>
|
</header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{{contributor-list contributors=contributorsSorted}}
|
{{contributor-list contributors=contributorsSorted}}
|
||||||
@@ -24,32 +15,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="contributions-by-type">
|
||||||
|
<header>
|
||||||
|
<h2>Contributions by type</h2>
|
||||||
|
</header>
|
||||||
|
<div class="content">
|
||||||
|
{{chart-contributions-by-type contributions=proposals}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="contributions">
|
||||||
{{#if proposalsOpen}}
|
{{#if proposalsOpen}}
|
||||||
<section id="proposals-open">
|
<section id="proposals-open">
|
||||||
<header>
|
<header>
|
||||||
<h2>Open Proposals</h2>
|
<h2>Unconfirmed Contributions</h2>
|
||||||
</header>
|
</header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{{!-- TODO: We need a better naming for kredits.hasAccounts --}}
|
{{!-- TODO: We need a better naming for kredits.hasAccounts --}}
|
||||||
{{proposal-list proposals=proposalsOpenSorted
|
{{proposal-list proposals=proposalsOpenSorted
|
||||||
confirmProposals=(action 'confirmProposals')}}
|
confirmProposal=(action "confirmProposal")
|
||||||
|
contractInteractionEnabled=kredits.hasAccounts}}
|
||||||
{{!-- TODO: We need a better naming --}}
|
|
||||||
{{#if kredits.hasAccounts}}
|
|
||||||
<p class="actions">
|
|
||||||
{{#link-to 'proposals.new'}}Create new proposal{{/link-to}}
|
|
||||||
</p>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<section id="proposals-closed">
|
<section id="proposals-closed">
|
||||||
<header>
|
<header>
|
||||||
<h2>Closed Proposals</h2>
|
<h2>Confirmed Contributions</h2>
|
||||||
</header>
|
</header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{{proposal-list proposals=proposalsClosedSorted}}
|
{{proposal-list proposals=proposalsClosedSorted
|
||||||
|
confirmProposal=(action "confirmProposal")}}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{!-- TODO: We need a better naming --}}
|
{{!-- TODO: We need a better naming --}}
|
||||||
{{#if kredits.hasAccounts}}
|
{{#if kredits.hasAccounts}}
|
||||||
@@ -57,9 +55,10 @@
|
|||||||
{{#link-to 'proposals.new'}}Create new proposal{{/link-to}}
|
{{#link-to 'proposals.new'}}Create new proposal{{/link-to}}
|
||||||
</p>
|
</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if kredits.hasAccounts}}
|
||||||
<section id="add-contributor">
|
<section id="add-contributor">
|
||||||
<header>
|
<header>
|
||||||
<h2>Add Contributor</h2>
|
<h2>Add Contributor</h2>
|
||||||
@@ -73,3 +72,6 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|||||||
Generated
+1441
-704
File diff suppressed because it is too large
Load Diff
+4
-3
@@ -27,9 +27,10 @@
|
|||||||
"ember-ajax": "^3.0.0",
|
"ember-ajax": "^3.0.0",
|
||||||
"ember-awesome-macros": "0.41.0",
|
"ember-awesome-macros": "0.41.0",
|
||||||
"ember-browserify": "^1.1.13",
|
"ember-browserify": "^1.1.13",
|
||||||
"ember-cli": "^3.1.4",
|
"ember-cli": "~3.1.2",
|
||||||
"ember-cli-app-version": "^3.0.0",
|
"ember-cli-app-version": "^3.0.0",
|
||||||
"ember-cli-babel": "^6.6.0",
|
"ember-cli-babel": "^6.6.0",
|
||||||
|
"ember-cli-chart": "^3.4.0",
|
||||||
"ember-cli-dependency-checker": "^2.0.0",
|
"ember-cli-dependency-checker": "^2.0.0",
|
||||||
"ember-cli-eslint": "^4.2.1",
|
"ember-cli-eslint": "^4.2.1",
|
||||||
"ember-cli-htmlbars": "^2.0.1",
|
"ember-cli-htmlbars": "^2.0.1",
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
"ember-cli-sass": "^7.2.0",
|
"ember-cli-sass": "^7.2.0",
|
||||||
"ember-cli-sri": "^2.1.0",
|
"ember-cli-sri": "^2.1.0",
|
||||||
"ember-cli-uglify": "^2.0.0",
|
"ember-cli-uglify": "^2.0.0",
|
||||||
"ember-cli-update": "^0.21.4",
|
"ember-cli-update": "^0.21.2",
|
||||||
"ember-export-application-global": "^2.0.0",
|
"ember-export-application-global": "^2.0.0",
|
||||||
"ember-load-initializers": "^1.0.0",
|
"ember-load-initializers": "^1.0.0",
|
||||||
"ember-macro-helpers": "0.17.0",
|
"ember-macro-helpers": "0.17.0",
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
"eslint-plugin-ember": "^5.0.0",
|
"eslint-plugin-ember": "^5.0.0",
|
||||||
"ethers": "3.0.15",
|
"ethers": "3.0.15",
|
||||||
"kosmos-schemas": "^1.1.2",
|
"kosmos-schemas": "^1.1.2",
|
||||||
"kredits-contracts": "^3.0.2",
|
"kredits-contracts": "^3.x",
|
||||||
"loader.js": "^4.2.3",
|
"loader.js": "^4.2.3",
|
||||||
"tv4": "^1.3.0"
|
"tv4": "^1.3.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { module, test } from 'qunit';
|
||||||
|
import { setupRenderingTest } from 'ember-qunit';
|
||||||
|
import { render } from '@ember/test-helpers';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
|
||||||
|
module('Integration | Component | chart-contributions-by-type', function(hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
|
let proposals = [
|
||||||
|
{ kind: 'dev', amount: 500 },
|
||||||
|
{ kind: 'dev', amount: 1500 },
|
||||||
|
{ kind: 'ops', amount: 1500 },
|
||||||
|
{ kind: 'design', amount: 5000 },
|
||||||
|
{ kind: 'ops', amount: 1500 },
|
||||||
|
{ kind: 'dev', amount: 5000 },
|
||||||
|
{ kind: 'community', amount: 5000 },
|
||||||
|
{ kind: 'docs', amount: 500 },
|
||||||
|
{ kind: 'docs', amount: 500 },
|
||||||
|
{ kind: 'docs', amount: 500 },
|
||||||
|
];
|
||||||
|
|
||||||
|
test('it renders', async function(assert) {
|
||||||
|
this.set('proposals', proposals);
|
||||||
|
|
||||||
|
await render(hbs`{{chart-contributions-by-type contributions=proposals}}`);
|
||||||
|
|
||||||
|
assert.equal(this.element.textContent.trim(), '');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { module, test } from 'qunit';
|
||||||
|
import { setupTest } from 'ember-qunit';
|
||||||
|
|
||||||
|
module('Unit | Component | chart-contributions-by-type', function(hooks) {
|
||||||
|
setupTest(hooks);
|
||||||
|
|
||||||
|
let proposals = [
|
||||||
|
{ kind: 'dev', amount: 500 },
|
||||||
|
{ kind: 'dev', amount: 1500 },
|
||||||
|
{ kind: 'ops', amount: 1500 },
|
||||||
|
{ kind: 'design', amount: 5000 },
|
||||||
|
{ kind: 'ops', amount: 1500 },
|
||||||
|
{ kind: 'dev', amount: 5000 },
|
||||||
|
{ kind: 'community', amount: 5000 },
|
||||||
|
{ kind: 'docs', amount: 500 },
|
||||||
|
{ kind: 'docs', amount: 500 },
|
||||||
|
{ kind: 'docs', amount: 500 },
|
||||||
|
];
|
||||||
|
|
||||||
|
test('#chartData', function(assert) {
|
||||||
|
let component = this.owner.factoryFor('component:chart-contributions-by-type').create();
|
||||||
|
component.set('contributions', proposals);
|
||||||
|
|
||||||
|
let data = component.get('chartData');
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
data.labels,
|
||||||
|
['Community', 'Design', 'Development', 'Operations & Infrastructure', 'Documentation'],
|
||||||
|
'returns the correct labels'
|
||||||
|
);
|
||||||
|
assert.deepEqual(
|
||||||
|
data.datasets[0].data,
|
||||||
|
[5000, 5000, 7000, 3000, 1500],
|
||||||
|
'returns the correct kredit sums'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user