diff --git a/spec/openapi.yaml b/spec/openapi.yaml index 58b1746662d6f235e27adbeecf0cd110d8cda468..56cbd1549c9dc2c72dd4d16f450c118a49c945cd 100644 --- a/spec/openapi.yaml +++ b/spec/openapi.yaml @@ -601,15 +601,18 @@ components: address: type: object properties: - street: + address_line_1: type: string description: Street address of the organization - city: + address_line_2: type: string - description: The ciy in which the organization is based - province_state: + description: Additional information about the street address of the organization + locality: type: string - description: The province/state in which the organization is based + description: The city/township in which the organization is based + administrative_area: + type: string + description: The province/state/area in which the organization is based country: type: string description: The country in which the organization is based @@ -638,15 +641,18 @@ components: address: type: object properties: - street: + address_line_1: type: string description: Street address of the organization - city: + address_line_2: + type: string + description: Additional information about the street address of the organization + locality: type: string - description: The ciy in which the organization is based - province_state: + description: The city/township in which the organization is based + administrative_area: type: string - description: The province/state in which the organization is based + description: The province/state/area in which the organization is based country: type: string description: The country in which the organization is based diff --git a/src/main/java/org/eclipsefoundation/react/bootstrap/DataLoader.java b/src/main/java/org/eclipsefoundation/react/bootstrap/DataLoader.java index 53b842fb1655a9a064b79b62d16a4e20463fe5d0..d9ccfe503ed9e4e5a88a6d1fb7c2491573a72d2f 100644 --- a/src/main/java/org/eclipsefoundation/react/bootstrap/DataLoader.java +++ b/src/main/java/org/eclipsefoundation/react/bootstrap/DataLoader.java @@ -114,11 +114,11 @@ public class DataLoader { o.setEmployeeCount(RandomStringUtils.randomNumeric(5, 10)); o.setOrganizationType(OrganizationTypes.OTHER); Address a = new Address(); - a.setCity(RandomStringUtils.randomAlphabetic(4, 10)); + a.setLocality(RandomStringUtils.randomAlphabetic(4, 10)); a.setCountry(RandomStringUtils.randomAlphabetic(4, 10)); a.setPostalCode(RandomStringUtils.randomAlphabetic(4, 10)); - a.setProvinceState(RandomStringUtils.randomAlphabetic(2)); - a.setStreet(RandomStringUtils.randomAlphabetic(4, 10)); + a.setAdministrativeArea(RandomStringUtils.randomAlphabetic(2)); + a.setAddressLine1(RandomStringUtils.randomAlphabetic(4, 10)); a.setOrganization(o); o.setAddress(a); organizations.add(o); diff --git a/src/main/java/org/eclipsefoundation/react/dto/Address.java b/src/main/java/org/eclipsefoundation/react/dto/Address.java index b7d76097b818164133387b2f7517cff6c36a67fd..f05084275ded404b5e17ad55615df4b59b020634 100644 --- a/src/main/java/org/eclipsefoundation/react/dto/Address.java +++ b/src/main/java/org/eclipsefoundation/react/dto/Address.java @@ -16,6 +16,7 @@ import java.util.Objects; import javax.inject.Inject; import javax.inject.Singleton; +import javax.json.bind.annotation.JsonbProperty; import javax.json.bind.annotation.JsonbTransient; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -56,11 +57,14 @@ public class Address extends BareNode implements TargetedClone
{ @JoinColumn(name = "organization_id", unique = true) private FormOrganization organization; - @NotBlank(message = "Street cannot be blank") - private String street; - @NotBlank(message = "City cannot be blank") - private String city; - private String provinceState; + @NotBlank(message = "First address line cannot be blank") + @JsonbProperty("address_line_1") + private String addressLine1; + @JsonbProperty("address_line_2") + private String addressLine2; + @NotBlank(message = "Locality cannot be blank") + private String locality; + private String administrativeArea; @NotBlank(message = "Country cannot be blank") private String country; private String postalCode; @@ -77,6 +81,7 @@ public class Address extends BareNode implements TargetedClone
{ } /** @return the organization */ + @JsonbTransient public FormOrganization getOrganization() { return this.organization; } @@ -86,83 +91,123 @@ public class Address extends BareNode implements TargetedClone
{ this.organization = org; } - /** @return the steet */ - public String getStreet() { - return street; + /** + * @return the addressLine1 + */ + public String getAddressLine1() { + return addressLine1; + } + + /** + * @param addressLine1 the addressLine1 to set + */ + public void setAddressLine1(String addressLine1) { + this.addressLine1 = addressLine1; + } + + /** + * @return the addressLine2 + */ + public String getAddressLine2() { + return addressLine2; } - /** @param street the street to set */ - public void setStreet(String street) { - this.street = street; + /** + * @param addressLine2 the addressLine2 to set + */ + public void setAddressLine2(String addressLine2) { + this.addressLine2 = addressLine2; } - /** @return the city */ - public String getCity() { - return city; + /** + * @return the locality + */ + public String getLocality() { + return locality; } - /** @param city the city to set */ - public void setCity(String city) { - this.city = city; + /** + * @param locality the locality to set + */ + public void setLocality(String locality) { + this.locality = locality; } - /** @return the provinceState */ - public String getProvinceState() { - return provinceState; + /** + * @return the administrativeArea + */ + public String getAdministrativeArea() { + return administrativeArea; } - /** @param provinceState the provinceState to set */ - public void setProvinceState(String provinceState) { - this.provinceState = provinceState; + /** + * @param administrativeArea the administrativeArea to set + */ + public void setAdministrativeArea(String administrativeArea) { + this.administrativeArea = administrativeArea; } - /** @return the country */ + /** + * @return the country + */ public String getCountry() { return country; } - /** @param country the country to set */ + /** + * @param country the country to set + */ public void setCountry(String country) { this.country = country; } - /** @return the postalCode */ + /** + * @return the postalCode + */ public String getPostalCode() { return postalCode; } - /** @param postalCode the postalCode to set */ + /** + * @param postalCode the postalCode to set + */ public void setPostalCode(String postalCode) { this.postalCode = postalCode; } - @Override - public Address cloneTo(Address target) { - target.setCity(getCity()); - target.setCountry(getCountry()); - target.setPostalCode(getPostalCode()); - target.setProvinceState(getProvinceState()); - target.setStreet(getStreet()); - return target; - } - @Override public int hashCode() { - return Objects.hash(city, country, id, postalCode, provinceState, street); + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + Objects.hash(addressLine1, addressLine2, administrativeArea, country, id, locality, postalCode); + return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; - if (obj == null) + if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; Address other = (Address) obj; - return Objects.equals(city, other.city) && Objects.equals(country, other.country) - && Objects.equals(id, other.id) && Objects.equals(postalCode, other.postalCode) - && Objects.equals(provinceState, other.provinceState) && Objects.equals(street, other.street); + return Objects.equals(addressLine1, other.addressLine1) && Objects.equals(addressLine2, other.addressLine2) + && Objects.equals(administrativeArea, other.administrativeArea) + && Objects.equals(country, other.country) && Objects.equals(id, other.id) + && Objects.equals(locality, other.locality) && Objects.equals(postalCode, other.postalCode); + } + + @Override + public Address cloneTo(Address target) { + target.setAddressLine1(getAddressLine1()); + target.setAddressLine2(getAddressLine2()); + target.setLocality(getLocality()); + target.setAdministrativeArea(getAdministrativeArea()); + target.setCountry(getCountry()); + target.setPostalCode(getPostalCode()); + return target; } /** @@ -200,4 +245,5 @@ public class Address extends BareNode implements TargetedClone
{ return Address.class; } } + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 158a74bcf0cae57b9acbe4f86ee4604a08fdcdc1..3c911a4cad5b3737b5f1a6637b1bd0780b196b15 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -45,6 +45,7 @@ quarkus.oidc.logout.post-logout-path=/ quarkus.oidc.logout.path=/api/logout security.csrf.enabled=true quarkus.oidc.authentication.java-script-auto-redirect=false +quarkus.oidc.authentication.cookie-force-secure=true ## Recreate DB profile (easy to trigger in remote envs) %dbfresh.quarkus.hibernate-orm.database.generation=drop-and-create diff --git a/src/main/resources/sql/ddl.sql b/src/main/resources/sql/ddl.sql index 1fc10f4278994602c15abeaa2c8bd6a5d2957479..d39950f9c0baf8ad5296c9f42e281f4f87cad75e 100644 --- a/src/main/resources/sql/ddl.sql +++ b/src/main/resources/sql/ddl.sql @@ -56,11 +56,12 @@ CREATE TABLE `FormWorkingGroup` ( CREATE TABLE `Address` ( `id` varchar(255) NOT NULL, - `city` varchar(255) DEFAULT NULL, + `locality` varchar(255) DEFAULT NULL, `country` varchar(255) DEFAULT NULL, `postalCode` varchar(255) DEFAULT NULL, - `provinceState` varchar(255) DEFAULT NULL, - `street` varchar(255) DEFAULT NULL, + `administrativeArea` varchar(255) DEFAULT NULL, + `addressLine1` varchar(255) DEFAULT NULL, + `addressLine2` varchar(255) DEFAULT NULL, `organization_id` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `UK_i4vgutrsl3ve37hc8xx7vvslf` (`organization_id`), diff --git a/src/main/resources/templates/emails/form_membership_email_template.txt b/src/main/resources/templates/emails/form_membership_email_template.txt index 14bee32016c2eb05b32f073612263715254fa9f3..73bdf35d32e3ae80bd8f57118721f821a081b0eb 100644 --- a/src/main/resources/templates/emails/form_membership_email_template.txt +++ b/src/main/resources/templates/emails/form_membership_email_template.txt @@ -1,4 +1,5 @@ Eclipse Foundation AISBL Membership Application date submitted: {now} + {#if includePreamble} Dear {name}, @@ -7,6 +8,8 @@ Meanwhile, if you have any questions, please reach out to us at membership.coord Best regards, Eclipse Foundation Membership Coordination + + {/if} New form submission by: {name} ({data.form.userID}) @@ -22,8 +25,9 @@ Employee count: {data.org.employeeCount} Organization Type: {data.org.organizationType} Address -{data.org.address.street} -{data.org.address.city}, {org.address.provinceState} +{data.org.address.addressLine1} +{data.org.address.addressLine2} +{data.org.address.locality}, {data.org.address.administrativeArea} {data.org.address.country} {data.org.address.postalCode} diff --git a/src/main/resources/templates/emails/form_membership_email_web_template.html b/src/main/resources/templates/emails/form_membership_email_web_template.html index 2f98f7259762453c2c57b5e6883f490ea58102b9..118dc6e2f1b8119f018f274512729c8605967790 100644 --- a/src/main/resources/templates/emails/form_membership_email_web_template.html +++ b/src/main/resources/templates/emails/form_membership_email_web_template.html @@ -24,7 +24,7 @@

Address

- {data.org.address.street}
{data.org.address.city}
{data.org.address.provinceState}
{data.org.address.country}
{data.org.address.postalCode} + {data.org.address.addressLine1}
{data.org.address.addressLine2}
{data.org.address.locality}
{data.org.address.administrativeArea}
{data.org.address.country}
{data.org.address.postalCode}

diff --git a/src/main/www/package.json b/src/main/www/package.json index bf49b49c08ca3b823a6ce1fed8cccc2eeac423f5..6fcd3a1f2e10dfc923267198c31570a1e7319715 100644 --- a/src/main/www/package.json +++ b/src/main/www/package.json @@ -19,6 +19,7 @@ "eclipsefdn-solstice-assets": "^0.0.162", "formik": "^2.2.6", "less-watch-compiler": "^1.15.1", + "postal-address-field-names": "^1.0.3", "react": "^17.0.0", "react-app-polyfill": "^2.0.0", "react-dom": "^17.0.0", @@ -54,9 +55,9 @@ ] }, "devDependencies": { - "@types/react-router-dom": "^5.1.7", "@openapi-contrib/openapi-schema-to-json-schema": "^3.1.1", "@stoplight/json-ref-resolver": "^3.1.2", + "@types/react-router-dom": "^5.1.7", "decamelize": "^5.0.0", "js-yaml": "^4.1.0", "react-datepicker": "^3.2.2", diff --git a/src/main/www/src/Utils/formFunctionHelpers.js b/src/main/www/src/Utils/formFunctionHelpers.js index cc3bceac7b79382b8423e652724a4952fc460e54..fdb6200c921bad1fb896edb5b8354dde1de6c384 100644 --- a/src/main/www/src/Utils/formFunctionHelpers.js +++ b/src/main/www/src/Utils/formFunctionHelpers.js @@ -79,9 +79,10 @@ export function matchCompanyFields(existingOrganizationData) { type: existingOrganizationData?.organization_type || '', address: { id: existingOrganizationData?.address?.id || '', - street: existingOrganizationData?.address?.street || '', - city: existingOrganizationData?.address?.city || '', - provinceOrState: existingOrganizationData?.address?.province_state || '', + street: existingOrganizationData?.address?.address_line_1 || '', + streetTwo: existingOrganizationData?.address?.address_line_2 || '', + city: existingOrganizationData?.address?.locality || '', + provinceOrState: existingOrganizationData?.address?.administrative_area || '', country: existingOrganizationData?.address?.country || '', 'country-label': { label: existingOrganizationData?.address?.country || '', @@ -233,11 +234,12 @@ export function matchWorkingGroupFields( export function matchCompanyFieldsToBackend(organizationData, formId) { var org = { address: { - city: organizationData.address.city, + locality: organizationData.address.city, country: organizationData.address.country, - postal_code: organizationData.address.postalCode || '', - province_state: organizationData.address.provinceOrState || '', - street: organizationData.address.street, + postal_code: organizationData.address.postalCode || '', + administrative_area: organizationData.address.provinceOrState || '', + address_line_1: organizationData.address.street, + address_line_2: organizationData.address.streetTwo, }, form_id: formId, id: organizationData.id, @@ -245,7 +247,7 @@ export function matchCompanyFieldsToBackend(organizationData, formId) { twitter: organizationData.twitterHandle || '', aggregate_revenue: organizationData.revenue, employee_count: organizationData.employeeCount, - organization_type: organizationData.type + organization_type: organizationData.type, }; if (organizationData.address.id) { diff --git a/src/main/www/src/components/Application/CompanyInformation/CompanyInformationCompany.js b/src/main/www/src/components/Application/CompanyInformation/CompanyInformationCompany.js index 8c4dc2ea638aa18386d9c460a591cce21f2fb54e..dfbc972a21c2a4feb449863ca586c52db24a6097 100644 --- a/src/main/www/src/components/Application/CompanyInformation/CompanyInformationCompany.js +++ b/src/main/www/src/components/Application/CompanyInformation/CompanyInformationCompany.js @@ -9,6 +9,8 @@ import { OPTIONS_FOR_EMPLOYEE_COUNT, HELPERTEXT_FOR_REVENUE, } from '../../../Constants/Constants'; +import countryAddressDetails from 'postal-address-field-names'; +import { useState } from 'react'; /** * Render Oraganization selector (used React-Select) @@ -21,18 +23,39 @@ import { const CompanyInformationCompany = ({ formik, useStyles }) => { const classes = useStyles(); - const { organizationName, organizationTwitter, organizationAddress, organizationRevenue, organizationType } = - formField; + const { organizationName, organizationTwitter, organizationAddress, organizationRevenue, organizationType } = formField; + const [orgAddressObj, setOrgAddressObj] = useState({ + street: 'Address 1', + streetTwo: 'Address 2', + city: 'City', + provinceOrState: 'Province', + postalCode: 'Postal Code', + }); - // get country list library and map as option pass to the React-Select - const countryList = require('country-list') - .getNames() - .map((item) => ({ label: item, value: item })); + const countryList = countryAddressDetails.map((item) => ({ label: item.name, value: item.name })); const handleFieldChange = (value, fieldName) => { formik.setFieldValue(fieldName, value); }; + const handleCountryOnChange = (ev, value) => { + // this is only for display + formik.setFieldValue(`${organizationAddress.country.name}-label`, value || null); + // this is the data will be actually used + formik.setFieldValue(organizationAddress.country.name, value?.value || null); + if (value) { + const currentAddressObj = countryAddressDetails.find((item) => item.name === value.value).fields; + console.log(currentAddressObj); + setOrgAddressObj({ + street: currentAddressObj.addressLine1, + streetTwo: currentAddressObj.addressLine2, + city: currentAddressObj.locality, + provinceOrState: currentAddressObj.administrativeArea, + postalCode: currentAddressObj.postalCode, + }); + } + }; + return ( <>

@@ -121,10 +144,10 @@ const CompanyInformationCompany = ({ formik, useStyles }) => { Address

-
+
{ helperText={formik.errors.organization?.address?.street} />
-
+
@@ -159,13 +183,7 @@ const CompanyInformationCompany = ({ formik, useStyles }) => { fullWidth={true} freeSolo={true} openOnFocus={true} - onChange={(ev, value) => { - // this is only for display - formik.setFieldValue(`${organizationAddress.country.name}-label`, value || null); - - // this is the data will be actually used - formik.setFieldValue(organizationAddress.country.name, value?.value || null); - }} + onChange={(ev, value) => handleCountryOnChange(ev, value)} value={formik.values.organization.address['country-label'] || null} renderInput={(params) => { params.inputProps = { @@ -192,11 +210,25 @@ const CompanyInformationCompany = ({ formik, useStyles }) => { />
+
+ +
+
{ />
-
+
item); +const countryList = countryAddressDetails.map((item) => item.name); const REQUIRED_MAX_YUP = yup.string().required(requiredErrorMsg).max(255, MAX_LENGTH_HELPER_TEXT); const MAX_YUP = yup.string().max(255, MAX_LENGTH_HELPER_TEXT); diff --git a/src/main/www/src/components/UIComponents/FormComponents/formFieldModel.js b/src/main/www/src/components/UIComponents/FormComponents/formFieldModel.js index 6e4a3b2b88688c2809d04bcb2d24dad2a4182244..4f531aaf70ac9d6637277fcc3bb01288c9be007a 100644 --- a/src/main/www/src/components/UIComponents/FormComponents/formFieldModel.js +++ b/src/main/www/src/components/UIComponents/FormComponents/formFieldModel.js @@ -5,7 +5,10 @@ const email = 'Email Address'; const orgName = 'Organization Name'; const twitterLabel = 'Twitter Handle'; const twitter = '@username'; -const street = 'Street'; +const street = 'Address 1'; +const streetPlaceholder = 'Street address of the organization'; +const streetTwo = 'Address 2'; +const streetTwoPlaceholder = 'Additional information about the street address'; const city = 'City'; const provinceOrState = 'Province or State'; const postalCode = 'Postal Code'; @@ -39,6 +42,7 @@ export const initialValues = { address: { id: '', street: '', + streetTwo: '', city: '', provinceOrState: '', country: '', @@ -165,7 +169,13 @@ export const formField = { street: { name: 'organization.address.street', label: street, - placeholder: street, + placeholder: streetPlaceholder, + requiredErrorMsg: requiredErrorMsg, + }, + streetTwo: { + name: 'organization.address.streetTwo', + label: streetTwo, + placeholder: streetTwoPlaceholder, requiredErrorMsg: requiredErrorMsg, }, city: { diff --git a/src/main/www/yarn.lock b/src/main/www/yarn.lock index 2a3e2b1390f7ba45aea6b1dd08b5bdf05eb09c0e..edf397e75388d3cd4ffcd5583a1db6910ed2c2c8 100644 --- a/src/main/www/yarn.lock +++ b/src/main/www/yarn.lock @@ -11632,6 +11632,11 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postal-address-field-names@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/postal-address-field-names/-/postal-address-field-names-1.0.3.tgz#2fb2695d66286c4acc08b53e61d58c90b8338a91" + integrity sha512-IuEVpLpgL44e/IVSWnH5yXQEJmKeklaMiIF6WbyElrq7e/Vwy0YeImQ2Hz10ynridXlP8drUUghDtIkRqqbQZA== + postcss-attribute-case-insensitive@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" diff --git a/src/test/java/org/eclipsefoundation/react/test/helper/DtoHelper.java b/src/test/java/org/eclipsefoundation/react/test/helper/DtoHelper.java index 3b83701fa59ad967ac702de981e3272b61ee88e6..0974968c51e24bea73c51fc14b96e62c2c6c11c4 100644 --- a/src/test/java/org/eclipsefoundation/react/test/helper/DtoHelper.java +++ b/src/test/java/org/eclipsefoundation/react/test/helper/DtoHelper.java @@ -58,11 +58,11 @@ public class DtoHelper { o.setAggregateRevenue(RandomStringUtils.randomNumeric(5, 10)); o.setEmployeeCount(RandomStringUtils.randomNumeric(5, 10)); Address a = new Address(); - a.setCity(RandomStringUtils.randomAlphabetic(4, 10)); + a.setLocality(RandomStringUtils.randomAlphabetic(4, 10)); a.setCountry(RandomStringUtils.randomAlphabetic(4, 10)); a.setPostalCode(RandomStringUtils.randomAlphabetic(4, 10)); - a.setProvinceState(RandomStringUtils.randomAlphabetic(2)); - a.setStreet(RandomStringUtils.randomAlphabetic(4, 10)); + a.setAdministrativeArea(RandomStringUtils.randomAlphabetic(2)); + a.setAddressLine1(RandomStringUtils.randomAlphabetic(4, 10)); o.setAddress(a); return o; }