diff --git a/components/CreateEventForm.js b/components/CreateEventForm.js
index c2380a0963e..7ea4723ca92 100644
--- a/components/CreateEventForm.js
+++ b/components/CreateEventForm.js
@@ -148,10 +148,9 @@ class CreateEventForm extends React.Component {
return
;
}
- const isNew = !(event && event.id);
+ const isNew = !event.id;
const submitBtnLabel = loading ? 'loading' : isNew ? 'Create Event' : 'Save';
-
- this.fields = [
+ const fields = [
{
name: 'name',
maxLength: 255,
@@ -192,9 +191,7 @@ class CreateEventForm extends React.Component {
type: 'textarea',
maxLength: 10000,
},
- ];
-
- this.fields = this.fields.map(field => {
+ ].map(field => {
if (this.messages[`${field.name}.label`]) {
field.label = intl.formatMessage(this.messages[`${field.name}.label`]);
}
@@ -208,7 +205,7 @@ class CreateEventForm extends React.Component {
- {this.fields.map(field =>
+ {fields.map(field =>
field.name === 'timezone' ? (
{
type="url"
placeholder="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
value={url || ''}
- onChange={e => onChange(e.target.value)}
+ onChange={e => onChange(e.target.value || null)}
width={1}
autoFocus
/>
diff --git a/components/dashboard/sections/AccountSettings.js b/components/dashboard/sections/AccountSettings.js
index fa5d8ecf5d9..9f16bd62c3d 100644
--- a/components/dashboard/sections/AccountSettings.js
+++ b/components/dashboard/sections/AccountSettings.js
@@ -86,28 +86,6 @@ const AccountSettings = ({ account, section }) => {
}
const CollectiveInputType = pick(collective, collectiveFields);
- if (isArray(collective.tiers)) {
- CollectiveInputType.tiers = collective.tiers.map(tier =>
- pick(tier, [
- 'id',
- 'type',
- 'name',
- 'description',
- 'longDescription',
- 'useStandalonePage',
- 'amount',
- 'amountType',
- 'interval',
- 'maxQuantity',
- 'presets',
- 'minimumAmount',
- 'goal',
- 'button',
- 'invoiceTemplate',
- 'singleTicket',
- ]),
- );
- }
if (isArray(collective.socialLinks)) {
CollectiveInputType.socialLinks = collective.socialLinks.map(sl => omit(sl, '__typename'));
diff --git a/components/edit-collective/Form.js b/components/edit-collective/Form.js
index e11e1b8a705..1bbf9e0855a 100644
--- a/components/edit-collective/Form.js
+++ b/components/edit-collective/Form.js
@@ -4,13 +4,12 @@ import { getApplicableTaxesForCountry, TaxType } from '@opencollective/taxes';
import { InfoCircle } from '@styled-icons/boxicons-regular/InfoCircle';
import { ArrowBack } from '@styled-icons/material/ArrowBack';
import dayjs from 'dayjs';
-import { cloneDeep, find, get, isNil, set } from 'lodash';
+import { cloneDeep, get, isNil, set } from 'lodash';
import { withRouter } from 'next/router';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { AccountTypesWithHost, CollectiveType, defaultBackgroundImage } from '../../lib/constants/collectives';
import { Currency } from '../../lib/constants/currency';
-import { TierTypes } from '../../lib/constants/tiers-types';
import { VAT_OPTIONS } from '../../lib/constants/vat';
import { convertDateFromApiUtc, convertDateToApiUtc } from '../../lib/date-utils';
import { isValidUrl } from '../../lib/utils';
@@ -282,15 +281,9 @@ class EditCollectiveForm extends React.Component {
collective.slug = collective.slug ? collective.slug.replace(/.*\//, '') : '';
collective.tos = get(collective, 'settings.tos');
- // TODO Remove this once tier legacy is removed
- const tiers = collective.tiers && collective.tiers.filter(tier => tier.type !== TierTypes.TICKET);
- const tickets = collective.tiers && collective.tiers.filter(tier => tier.type === TierTypes.TICKET);
-
return {
modified: false,
collective,
- tiers: tiers.length === 0 ? [] : tiers,
- tickets: tickets.length === 0 ? [] : tickets,
validStartDate: true,
validEndDate: true,
isValidSocialLinks: true,
@@ -352,15 +345,6 @@ class EditCollectiveForm extends React.Component {
async handleSubmit() {
const collective = { ...this.state.collective };
- // Add Tiers and Tickets
- collective.tiers = [];
- if (find(this.state.tiers, 'name')) {
- collective.tiers = [...this.state.tiers];
- }
- if (find(this.state.tickets, 'name')) {
- collective.tiers = [...collective.tiers, ...this.state.tickets];
- }
-
// Add a confirm if slug changed
if (collective.slug !== this.props.collective.slug) {
if (
diff --git a/components/tier-page/TierLongDescription.js b/components/tier-page/TierLongDescription.js
index 3caa9ae5779..9d858e88336 100644
--- a/components/tier-page/TierLongDescription.js
+++ b/components/tier-page/TierLongDescription.js
@@ -12,9 +12,9 @@ import StyledButton from '../StyledButton';
* Displays the tier long description on the page, with an optional form to edit it
* if user is allowed to do so.
*/
-const TierLongDescription = ({ tier, editMutation, canEdit }) => {
+const TierLongDescription = ({ tier, editMutation, canEdit, ...inlineEditFieldProps }) => {
return (
-
+
{({ isEditing, value, setValue, enableEditor, setUploading }) => {
if (isEditing) {
return (
diff --git a/components/tier-page/TierVideo.js b/components/tier-page/TierVideo.js
index dc3143995a0..034d41d64d1 100644
--- a/components/tier-page/TierVideo.js
+++ b/components/tier-page/TierVideo.js
@@ -12,15 +12,15 @@ const VideoLinkerBox = dynamic(() => import(/* webpackChunkName: 'VideoLinkerBox
* Displays the video on the page, with an optional form to edit it
* if user is allowed to do so.
*/
-const TierVideo = ({ tier, editMutation, canEdit }) => {
+const TierVideo = ({ tier, editMutation, canEdit, ...inlineEditFieldProps }) => {
return (
{({ isEditing, value, setValue, enableEditor, disableEditor }) => {
if (isEditing || (!value && canEdit)) {
diff --git a/components/tier-page/graphql/queries.js b/components/tier-page/graphql/queries.js
index 9f63f29df0b..194c2b01437 100644
--- a/components/tier-page/graphql/queries.js
+++ b/components/tier-page/graphql/queries.js
@@ -6,6 +6,7 @@ export const tierPageQuery = gqlV1/* GraphQL */ `
query TierPage($tierId: Int!) {
Tier(id: $tierId) {
id
+ idV2
name
slug
description
diff --git a/components/tier-page/index.js b/components/tier-page/index.js
index 3ad5700cabf..fe0eff1b896 100644
--- a/components/tier-page/index.js
+++ b/components/tier-page/index.js
@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
+import { gql } from '@apollo/client';
import { themeGet } from '@styled-system/theme-get';
import { withRouter } from 'next/router';
import { FormattedMessage } from 'react-intl';
@@ -7,7 +8,7 @@ import styled from 'styled-components';
// Open Collective Frontend imports
import INTERVALS from '../../lib/constants/intervals';
-import { gqlV1 } from '../../lib/graphql/helpers';
+import { API_V2_CONTEXT } from '../../lib/graphql/helpers';
import { isTierExpired } from '../../lib/tier-utils';
import { getCollectivePageRoute } from '../../lib/url-helpers';
import { getWebsiteUrl } from '../../lib/utils';
@@ -80,8 +81,14 @@ const ProgressInfoContainer = styled.div`
`;
/** A mutation with all the info that user is allowed to edit on this page */
-const editTierMutation = gqlV1/* GraphQL */ `
- mutation UpdateTier($id: Int!, $name: String, $description: String, $longDescription: String, $videoUrl: String) {
+const editTierMutation = gql`
+ mutation EditTierPage(
+ $id: String!
+ $name: NonEmptyString
+ $description: String
+ $longDescription: String
+ $videoUrl: URL
+ ) {
editTier(
tier: { id: $id, description: $description, name: $name, longDescription: $longDescription, videoUrl: $videoUrl }
) {
@@ -115,6 +122,7 @@ class TierPage extends Component {
/** The actual tier */
tier: PropTypes.shape({
id: PropTypes.number.isRequired,
+ idV2: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
slug: PropTypes.string.isRequired,
@@ -164,6 +172,26 @@ class TierPage extends Component {
);
}
+ /**
+ * Helper to plug the `InlineEditField` with the GraphQL V2 API. Fields take a GraphQLV1 tier as input,
+ * use the GraphQLV2 API to update the tier, and update the cache for GraphQLV1 with the result.
+ */
+ getGraphQLV2Bindings(graphqlV1FieldName, graphqlV2FieldName = graphqlV1FieldName) {
+ const graphQLV1Tier = this.props.tier;
+ return {
+ prepareVariables: (tier, newValue) => ({ id: tier.idV2, [graphqlV2FieldName]: newValue }),
+ mutationOptions: {
+ context: API_V2_CONTEXT,
+ update: (cache, { data: { editTier } }) => {
+ cache.modify({
+ id: cache.identify(graphQLV1Tier),
+ fields: { [graphqlV1FieldName]: () => editTier[graphqlV2FieldName] },
+ });
+ },
+ },
+ };
+ }
+
render() {
const { collective, tier, contributors, contributorsStats, redirect, LoggedInUser } = this.props;
const canEdit = LoggedInUser && LoggedInUser.isAdminOfCollective(collective);
@@ -212,6 +240,7 @@ class TierPage extends Component {
maxLength={255}
placeholder={}
required
+ {...this.getGraphQLV2Bindings('name')}
/>
}
+ {...this.getGraphQLV2Bindings('description')}
/>
-
+
-
+
@@ -374,7 +416,13 @@ class TierPage extends Component {
{/** Video */}
-
+
{/** Share buttons (desktop only) */}
{shareBlock}
diff --git a/lib/graphql/schema.graphql b/lib/graphql/schema.graphql
index ffddc61f576..7fae39262a2 100644
--- a/lib/graphql/schema.graphql
+++ b/lib/graphql/schema.graphql
@@ -424,6 +424,7 @@ This represents an Tier
"""
type Tier {
id: Int
+ idV2: String!
slug: String
type: String
name: String
diff --git a/lib/graphql/schemaV2.graphql b/lib/graphql/schemaV2.graphql
index c4bd8bbfc4f..643fac04700 100644
--- a/lib/graphql/schemaV2.graphql
+++ b/lib/graphql/schemaV2.graphql
@@ -21016,6 +21016,8 @@ input TierUpdateInput {
amount: AmountInput
name: NonEmptyString
description: String
+ longDescription: String
+ videoUrl: URL
button: String
goal: AmountInput
type: TierType
diff --git a/lib/graphql/types/v2/graphql.ts b/lib/graphql/types/v2/graphql.ts
index f155e7ab049..28f14f52c65 100644
--- a/lib/graphql/types/v2/graphql.ts
+++ b/lib/graphql/types/v2/graphql.ts
@@ -10341,6 +10341,7 @@ export type TierUpdateInput = {
/** The public id identifying the tier (ie: dgm9bnk8-0437xqry-ejpvzeol-jdayw5re) */
id: Scalars['String']['input'];
invoiceTemplate?: InputMaybe;
+ longDescription?: InputMaybe;
maxQuantity?: InputMaybe;
minimumAmount?: InputMaybe;
name?: InputMaybe;
@@ -10348,6 +10349,7 @@ export type TierUpdateInput = {
singleTicket?: InputMaybe;
type?: InputMaybe;
useStandalonePage?: InputMaybe;
+ videoUrl?: InputMaybe;
};
export type TimeSeries = {
diff --git a/lib/graphql/v1/mutations.js b/lib/graphql/v1/mutations.js
index 2117997208a..8bf749c4258 100644
--- a/lib/graphql/v1/mutations.js
+++ b/lib/graphql/v1/mutations.js
@@ -146,9 +146,6 @@ export const addCreateCollectiveMutation = graphql(createCollectiveMutation, {
'isIncognito',
'settings',
]);
- CollectiveInputType.tiers = (collective.tiers || []).map(tier =>
- pick(tier, ['type', 'name', 'description', 'amount', 'maxQuantity']),
- );
CollectiveInputType.location = pick(collective.location, [
'name',
'address',
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index 0c884a19a5b..f024fe324ed 100644
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -151,7 +151,7 @@ Cypress.Commands.add('createCollective', ({ type = 'ORGANIZATION', email = defau
}
}
`,
- variables: { collective: { location: {}, name: 'TestOrg', slug: '', tiers: [], type, ...params } },
+ variables: { collective: { location: {}, name: 'TestOrg', slug: '', type, ...params } },
}).then(({ body }) => {
return body.data.createCollective;
});