Skip to content

Commit 194faab

Browse files
authored
Merge branch 'main' into mock-endpoints
2 parents ee4c053 + 1677d30 commit 194faab

8 files changed

Lines changed: 209 additions & 78 deletions

File tree

.github/workflows/action-cats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ jobs:
1111
name: A cat for your effort!
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: ruairidhwm/action-cats@1.0.1
14+
- uses: ruairidhwm/action-cats@1.0.2
1515
with:
1616
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ jobs:
3535

3636
# Initializes the CodeQL tools for scanning.
3737
- name: Initialize CodeQL
38-
uses: github/codeql-action/init@807578363a7869ca324a79039e6db9c843e0e100
38+
uses: github/codeql-action/init@b2a92eb56d8cb930006a1c6ed86b0782dd8a4297
3939
with:
4040
languages: javascript
4141

4242
- name: Perform CodeQL Analysis
43-
uses: github/codeql-action/analyze@807578363a7869ca324a79039e6db9c843e0e100
43+
uses: github/codeql-action/analyze@b2a92eb56d8cb930006a1c6ed86b0782dd8a4297

.github/workflows/scorecards-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454

5555
# Upload the results to GitHub's code scanning dashboard.
5656
- name: Upload to code-scanning
57-
uses: github/codeql-action/upload-sarif@807578363a7869ca324a79039e6db9c843e0e100
57+
uses: github/codeql-action/upload-sarif@b2a92eb56d8cb930006a1c6ed86b0782dd8a4297
5858
with:
5959
sarif_file: results.sarif
6060

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
"@fortawesome/free-solid-svg-icons": "^6.2.0",
5050
"@fortawesome/vue-fontawesome": "^2.0.8",
5151
"@stripe/stripe-js": "^1.35.0",
52-
"@vue-stripe/vue-stripe": "^4.4.2",
52+
"@vue-stripe/vue-stripe": "^4.4.4",
5353
"axios": "^0.27.2",
5454
"axios-cache-interceptor": "^0.10.7",
5555
"cli-plugin-eslint": "^0.1.0",
@@ -64,7 +64,7 @@
6464
"objection": "^3.0.1",
6565
"pg": "^8.7.3",
6666
"register-service-worker": "^1.7.1",
67-
"stripe": "^8.219.0",
67+
"stripe": "^11.1.0",
6868
"vue": "^2.6.11",
6969
"vue-router": "^3.5.4",
7070
"vuetify": "^2.6.8",
@@ -77,7 +77,7 @@
7777
"@vue/cli-plugin-vuex": "~4.5.0",
7878
"@vue/cli-service": "~4.5.0",
7979
"concurrently": "^7.3.0",
80-
"eslint": "^8.25.0",
80+
"eslint": "^8.29.0",
8181
"eslint-config-prettier": "^8.5.0",
8282
"eslint-plugin-vue": "^8.7.1",
8383
"husky": "^8.0.1",

server/routes/api/representatives.js

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,34 @@ const ALLOWED_JURISDICTION_FILTERS = Object.keys(JURISDICTION_FILTER_MAP)
5050
// Endpoints
5151

5252
// Get
53-
router.get('/:zipCode', async (req, res) => {
54-
const { zipCode } = req.params
55-
const { filter } = req.query
56-
57-
if (!zipCode.match(/^\d{5}(-\d{4})?$/)) {
53+
router.get('/:searchText', async (req, res) => {
54+
const { searchText } = req.params
55+
const filter = req.query.filter
56+
const streetAddress = req.query.streetAddress
57+
58+
/* check if valid ZIP code
59+
^\d{5} - the start of the line has 5 digits
60+
(-\d{4})?$ the end of the line has 4 digits preceded by a dash (optionally)
61+
*/
62+
let isValidZIPcode = /^\d{5}(-\d{4})?$/.test(searchText)
63+
64+
/* check if valid street address
65+
^(\d{3,})\s? the start of the line can have 3 or more digits followed by a space
66+
(\w{0,})\s the next part can have 2 or more letters followed by a space
67+
([a-zA-Z]{2,30})\s the next part must be an alphanetical string with 2-30 characters followed by a space
68+
([a-zA-Z]{2,15}).?\s? the next part must be an alphabetical string with 2-15 characters followed by a any digit (optionally) and/or space (optionally)
69+
(\w{0,5})$ the end of the line can have 0-5 letters
70+
*/
71+
let isValidAddress =
72+
/^(\d{3,})\s?(\w{0,5})\s([a-zA-Z]{2,30})\s?([a-zA-Z]{2,15}).?\s?(\w{0,5})$/.test(
73+
streetAddress
74+
)
75+
76+
if (!isValidZIPcode && !isValidAddress) {
5877
res.status(400).send({
5978
error:
60-
'Invalid zip code format, valid examples are 84054-6013 or 84054. The zipcode used was ' +
61-
zipCode
79+
'Invalid zip code or street address format, valid examples of a ZIP code are 84054-6013 or 84054. The zipcode/street address used was ' +
80+
searchText
6281
})
6382
return
6483
}
@@ -72,14 +91,22 @@ router.get('/:zipCode', async (req, res) => {
7291

7392
try {
7493
const params = {
75-
search_postal: zipCode,
76-
search_country: 'US',
7794
order: 'district_type', // https://cicero.azavea.com/docs/#order-by-district-type
7895
sort: 'asc',
7996
max: 200,
8097
format: 'json',
8198
key: CICERO_API_KEY
8299
}
100+
// add ZIP code search as parameter.
101+
// NOTE: we check it first, because, as of now, the regex use to validate ZIP codes is stricter and more accurate
102+
if (isValidZIPcode) {
103+
params.search_postal = searchText
104+
params.search_country = 'US'
105+
}
106+
// add street address search as parameter
107+
else if (isValidAddress) {
108+
params.search_address = streetAddress
109+
}
83110

84111
if (filter != null) {
85112
params.district_type = JURISDICTION_FILTER_MAP[filter]
@@ -94,6 +121,7 @@ router.get('/:zipCode', async (req, res) => {
94121
qs.stringify(params, { arrayFormat: 'repeat' }),
95122

96123
cache: {
124+
// TODO: we are disabling the cache to test results first
97125
ttl: 1000 * 60 * 60 * 24 * 7 // the time until the cached value is expired in milliseconds: set to 1 week
98126
}
99127
})

src/components/SearchReps.vue

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
<v-card-text>
1414
<v-subheader class="pa-0"> Where do you live? </v-subheader>
1515

16-
<v-form @submit.prevent="CreateRepList()" ref="form">
16+
<v-form ref="form">
1717
<v-text-field
18-
v-model="postalCode"
18+
v-model="searchText"
1919
label="Postal Code"
2020
required
2121
@keyup="CheckInputContent"
@@ -53,19 +53,6 @@
5353
State
5454
</v-btn>
5555

56-
<v-btn
57-
rounded
58-
dark
59-
class="ui button toggle search-reps-button"
60-
:style="{
61-
backgroundColor:
62-
currentFilter === 'local' && isActive ? 'blue' : 'gray'
63-
}"
64-
@click="FilterList('local')"
65-
>
66-
Local
67-
</v-btn>
68-
6956
<v-btn
7057
class="search-reps-button"
7158
rounded
@@ -81,17 +68,18 @@
8168
</v-btn>
8269

8370
<v-btn
84-
class="search-reps-button"
8571
rounded
8672
dark
87-
:class="{ active: isActive }"
73+
class="ui button toggle search-reps-button"
8874
:style="{
8975
backgroundColor:
90-
currentFilter === 'school' && isActive ? 'blue' : 'gray'
76+
currentFilter === 'municipality' && isActive
77+
? 'blue'
78+
: 'gray'
9179
}"
9280
@click="FilterList('school')"
9381
>
94-
School
82+
Local
9583
</v-btn>
9684
</v-col>
9785
</v-row>
@@ -101,7 +89,7 @@
10189
<v-btn
10290
:to="{
10391
name: 'Reps',
104-
params: { postalCode: postalCode }
92+
params: { searchText: searchText }
10593
}"
10694
clickclass="mr-4"
10795
@click="CreateRepList()"
@@ -153,6 +141,7 @@
153141
<take-action
154142
:letter-body="letterBody"
155143
:selected-rep="selectedRep"
144+
:rep-name="selectedRepName"
156145
/>
157146
</v-col>
158147
</v-row>
@@ -168,7 +157,6 @@
168157
import RepresentativeCard from '@/components/RepresentativeCard.vue'
169158
import TakeAction from '@/components/TakeAction.vue'
170159
import axios from 'axios'
171-
172160
export default {
173161
name: 'SearchReps',
174162
components: {
@@ -179,10 +167,11 @@ export default {
179167
return {
180168
letterBody: '',
181169
selectedRep: {},
170+
selectedRepName: '',
182171
congressMembers: [],
183172
currentFilter: '',
184173
hasContent: true,
185-
postalCode: this.$route.params.postalCode || '',
174+
searchText: this.$route.params.searchText || '',
186175
listVisible: false,
187176
isActive: false,
188177
myHeight: this.$vuetify.breakpoint.mobile ? false : "100vh"
@@ -192,26 +181,49 @@ export default {
192181
handleRepSelected(letterBody, selectedRep, step2) {
193182
this.letterBody = letterBody
194183
this.selectedRep = selectedRep
184+
this.selectedRepName = selectedRep.name
195185
this.step2 = step2
196186
},
197187
CheckInputContent: function () {
198-
if (this.postalCode !== '') {
199-
this.hasContent = true
200-
} else {
201-
this.hasContent = false
202-
}
188+
189+
if (this.searchText !== '') {
190+
this.hasContent = true
191+
} else {
192+
this.hasContent = false
193+
}
203194
},
204195
async CreateRepList() {
205196
try {
206-
this.$store.commit('setGenericValue', { key: 'zipcode', value: this.postalCode })
207-
const res = await axios.get(
208-
'/api/representatives/' + this.postalCode
209-
)
197+
this.$store.commit('setGenericValue', { key: 'searchText', value: this.searchText })
198+
// check postal code is valid with regex
199+
let res = ''
200+
let params = {streetAddress: this.searchText}
201+
let isPostalCodeValid = /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(this.searchText);
202+
let streetAddressValid = /^(\d{3,})\s?(\w{0,5})\s([a-zA-Z]{2,30})\s([a-zA-Z]{2,15})\.?\s?(\w{0,5})$/.test(this.searchText);
203+
204+
205+
if(isPostalCodeValid) {
206+
// console.log('valid input to get representatives with postal code')
207+
res = await axios.get(
208+
'/api/representatives/' + this.searchText
209+
)
210+
}
211+
212+
else if(streetAddressValid) {
213+
// console.log('valid input to get representatives with street address')
214+
res = await axios.get(
215+
'/api/representatives/ ', { params }
216+
)
217+
}
218+
210219
this.isActive = false
211220
this.congressMembers = res.data
212221
this.hasContent = true
213222
this.listVisible = true
214-
} catch (e) {
223+
}
224+
225+
226+
catch (e) {
215227
console.error(e)
216228
}
217229
},
@@ -222,27 +234,31 @@ export default {
222234
if (!this.isActive) {
223235
this.isActive = true
224236
const params = {}
237+
225238
if (this.currentFilter != null) {
226239
params.filter = this.currentFilter
227-
}
228240
241+
242+
params.streetAddress = this.searchText
229243
const res = await axios.get(
230-
'/api/representatives/' + this.postalCode,
244+
'/api/representatives/' + this.searchText,
231245
{
232246
params
233247
}
234248
)
235249
236250
console.log(res)
237251
this.congressMembers = res.data
252+
238253
} else {
239254
this.isActive = false;
240255
const res = await axios.get(
241-
'/api/representatives/' + this.postalCode
256+
'/api/representatives/' + this.searchText
242257
)
243258
244259
this.congressMembers = res.data
245260
}
261+
}
246262
} catch (e) {
247263
console.error(e)
248264
}

0 commit comments

Comments
 (0)