diff --git a/frontend/assets/style/components/_buttons.scss b/frontend/assets/style/components/_buttons.scss index 33756591c2..0aee63e4a4 100644 --- a/frontend/assets/style/components/_buttons.scss +++ b/frontend/assets/style/components/_buttons.scss @@ -202,11 +202,12 @@ button, color: transparent; // Delay the spin for 500ms, in case load is ultra fast. // That way the user won't even see the loading - transition: color 400ms 500ms; + // [1] !important so it works even when .js-reducedMotion + transition: color 400ms 500ms !important; // [1] &::after { opacity: 1; - transition: opacity 400ms 500ms; + transition: opacity 400ms 500ms !important; // [1] animation: loadSpin 1.75s infinite linear; } } diff --git a/frontend/assets/style/components/_pills.scss b/frontend/assets/style/components/_pills.scss index 0138726566..2e825b390b 100644 --- a/frontend/assets/style/components/_pills.scss +++ b/frontend/assets/style/components/_pills.scss @@ -1,29 +1,20 @@ .pill { - font-weight: 600; - border-radius: 3px; - padding: 0.375rem $spacer-sm; + border-radius: $radius; + padding: 0.125rem 0.25rem; line-height: 1; - margin: 0 $spacer-xs; display: inline-block; white-space: nowrap; + text-transform: uppercase; + font-size: $size_5; - &.is-small { - padding: ($spacer / 8) $spacer-xs; - text-transform: uppercase; - font-size: $size_5; - font-weight: 100; - } - - &.has-background-dark { - background: $text_0; - color: $general_2; + &.is-neutral { + background-color: $general_0; } @each $name in $colors { &.is-#{$name} { - @extend .pill; - @extend .has-background-#{$name}; - @extend .has-text-#{$name}; + background-color: var(--#{$name}_2); + color: var(--#{$name}_0); } } } diff --git a/frontend/model/contracts/group.js b/frontend/model/contracts/group.js index 6bfba76499..0bffed953c 100644 --- a/frontend/model/contracts/group.js +++ b/frontend/model/contracts/group.js @@ -62,10 +62,11 @@ function initMonthlyPayments () { } } -function initGroupProfile (contractID: string) { +function initGroupProfile (contractID: string, joined: ?string) { return { contractID: contractID, - nonMonetaryContributions: [] + nonMonetaryContributions: [], + joinedDate: joined } } @@ -149,6 +150,19 @@ DefineContract({ groupMembersCount (state, getters) { return getters.groupMembersByUsername.length }, + groupMembersPending (state, getters) { + const invites = getters.currentGroupState.invites + const pendingMembers = {} + for (const inviteId in invites) { + const invite = invites[inviteId] + if (invite.status === INVITE_STATUS.VALID && invite.creator !== INVITE_INITIAL_CREATOR) { + pendingMembers[invites[inviteId].invitee] = { + invitedBy: invites[inviteId].creator + } + } + } + return pendingMembers + }, groupShouldPropose (state, getters) { return getters.groupMembersCount >= 3 }, @@ -199,7 +213,7 @@ DefineContract({ groupCreator: meta.username }, profiles: { - [meta.username]: initGroupProfile(meta.identityContractID) + [meta.username]: initGroupProfile(meta.identityContractID, meta.createdDate) }, userPaymentsByMonth: { [currentMonthTimestamp()]: initMonthlyPayments() @@ -436,7 +450,7 @@ DefineContract({ if (Object.keys(invite.responses).length === invite.quantity) { invite.status = INVITE_STATUS.USED } - Vue.set(state.profiles, meta.username, initGroupProfile(meta.identityContractID)) + Vue.set(state.profiles, meta.username, initGroupProfile(meta.identityContractID, meta.createdDate)) // If we're triggered by handleEvent in state.js (and not latestContractState) // then the asynchronous sideEffect function will get called next // and we will subscribe to this new user's identity contract diff --git a/frontend/views/components/Avatar.vue b/frontend/views/components/Avatar.vue index 9fa64cb8f4..1d78d57926 100644 --- a/frontend/views/components/Avatar.vue +++ b/frontend/views/components/Avatar.vue @@ -1,11 +1,13 @@ diff --git a/frontend/views/containers/payments/PaymentsList.vue b/frontend/views/containers/payments/PaymentsList.vue index 76fde69626..1bf7b2a24f 100644 --- a/frontend/views/containers/payments/PaymentsList.vue +++ b/frontend/views/containers/payments/PaymentsList.vue @@ -29,7 +29,7 @@ table.table.table-in-card.c-payments(:class='{"is-editing": paymentsType === "ed // TODO: replace condition to indicate whether or not the payment date is < or > than the current date using payment.paymentStatusText i18n.c-user-month( - :class='index === 0 ? "has-text-1" : "pill is-danger is-small"' + :class='index === 0 ? "has-text-1" : "pill is-danger"' :args='{date: moment(payment.date).format("MMMM DD")}' ) Due {date} td.c-payments-amount(v-if='paymentsType !== "edit"') @@ -44,7 +44,7 @@ table.table.table-in-card.c-payments(:class='{"is-editing": paymentsType === "ed :args='{partial_amount: `${currency(20)}`, partial_total: currency(payment.amount)}' ) {partial_amount} out of {partial_total} - i18n.pill.is-primary.is-small Partial + i18n.pill.is-primary Partial strong(v-else) {{currency(payment.amount)}} @@ -62,12 +62,12 @@ table.table.table-in-card.c-payments(:class='{"is-editing": paymentsType === "ed .button.is-icon-smaller.c-tip i.icon-info - i18n.pill.is-warning.is-small Not received + i18n.pill.is-warning Not received td .c-actions - .c-actions-month(:class='!(index !== 0 && paymentsType === "todo") ? "has-text-1" : "pill is-danger is-small"') {{ moment(payment.date).format('MMMM D') }} - payments-list-menu( + .c-actions-month(:class='!(index !== 0 && paymentsType === "todo") ? "has-text-1" : "pill is-danger"') {{ moment(payment.date).format('MMMM D') }} + payments-list-menu.c-actions-menu( v-if='paymentsType !== "edit"' :payment='payment' :paymentsType='paymentsType' @@ -258,6 +258,11 @@ export default { .c-actions-month { margin-left: 0; + white-space: nowrap; +} + +.c-actions-menu { + margin-left: 1rem; } .c-name { diff --git a/frontend/views/pages/DesignSystem.vue b/frontend/views/pages/DesignSystem.vue index 22d7ff5d97..85338cd480 100644 --- a/frontend/views/pages/DesignSystem.vue +++ b/frontend/views/pages/DesignSystem.vue @@ -495,9 +495,9 @@ page( th demo tr td - pre .pill.has-background-dark + pre .pill.is-neutral td - span.pill.has-background-dark Pending + span.pill.is-neutral Pending tr td @@ -523,36 +523,6 @@ page( td span.pill.is-danger Due march 08 - tr - td - pre .pill.has-background-dark.is-small - td - span.pill.has-background-dark.is-small Pending - - tr - td - pre .pill.is-success.is-small - td - span.pill.is-success.is-small Payment received - - tr - td - pre .pill.is-warning.is-small - td - span.pill.is-warning.is-small Not received - - tr - td - pre .pill.is-primary.is-small - td - span.pill.is-primary.is-small Partial - - tr - td - pre .pill.is-danger.is-small - td - span.pill.is-danger.is-small Due march 08 - article#user-feedback section.card h2.is-title-2.card-header Feedback Banners diff --git a/test/cypress/integration/group-large.spec.js b/test/cypress/integration/group-large.spec.js index 437e10d112..0e159db4f0 100644 --- a/test/cypress/integration/group-large.spec.js +++ b/test/cypress/integration/group-large.spec.js @@ -34,16 +34,13 @@ describe('Large group', () => { }) } - cy.giLogin(`user1-${userId}`) + cy.giLogin(`user1-${userId}`, { bypassUI: true }) cy.giAddRandomIncome() cy.get('.graph-bar') .should('have.length', groupLength) - cy.giLogout() }) it('A search for "user1" should display 4 members', () => { - cy.visit('/') - cy.giLogin(`user1-${userId}`) cy.getByDT('seeAllMembers').click() cy.getByDT('memberCount') .should('contain', '12 members') diff --git a/test/cypress/integration/group-proposals.spec.js b/test/cypress/integration/group-proposals.spec.js index e8d210801c..852dba84f4 100644 --- a/test/cypress/integration/group-proposals.spec.js +++ b/test/cypress/integration/group-proposals.spec.js @@ -163,6 +163,15 @@ describe('Proposals - Add members', () => { cy.getByDT('sendLink').should('not.exist') // Only visible to who created the proposal }) }) + + cy.log(`${username} is part of members list as "pending"`) + + cy.getByDT('groupMembers').find('ul').within(() => { + cy.getByDT(`${username}-${userId}`, 'li').within(() => { + cy.getByDT('username').should('contain', `${username}-${userId}`) + cy.getByDT('pillPending').should('contain', 'pending') + }) + }) } voteForAndIsAccepted(0, 'user4') @@ -239,7 +248,16 @@ describe('Proposals - Add members', () => { cy.giSignup(`user4-${userId}`, { bypassUI: true }) cy.giAcceptGroupInvite(invitationLinks.user4, { isLoggedIn: true, - groupName + groupName, + actionBeforeLogout: () => { + cy.log('"New" tag does not appear for previous members') + cy.getByDT('groupMembers').find('ul > li') + .each(([member], index) => { + cy.get(member).within(() => { + cy.getByDT('pillNew').should('not.exist') + }) + }) + } }) }) @@ -273,7 +291,7 @@ describe('Proposals - Add members', () => { cy.getByDT('welcomeHome').should('contain', 'Welcome to GroupIncome') }) - it('user1 logins and sees all 5 proposals correctly and the new member', () => { + it('user1 logins and sees all 5 proposals correctly and the new members', () => { cy.giLogin(`user1-${userId}`, { bypassUI: true }) // A quick checkup that each proposal state is correct. @@ -327,7 +345,14 @@ describe('Proposals - Add members', () => { .each(([member], index) => { cy.get(member).within(() => { const usersMap = [1, 2, 3, 4, 6] + cy.getByDT('username').should('contain', `user${usersMap[index]}-${userId}`) + + if (index === 0) { + cy.getByDT('username').should('contain', '(you)') + } else { + cy.getByDT('pillNew').should('contain', 'new') + } }) })