diff --git a/.env b/.env
index 7a551280e..f3b43d191 100644
--- a/.env
+++ b/.env
@@ -32,9 +32,14 @@ TWILIO_AUTH_TOKEN=TWILIO_SECRET_KEY
# **We always run in single-campaign mode now so this is mandatory!**
# Use campaign seeder file for local dev campaigns.
VUE_APP_CAMPAIGN_MODE=single
-VUE_APP_FEATURED_CAMPAIGN=1
+VUE_APP_FEATURED_CAMPAIGN=3
+
+VUE_APP_EMPTY_TRANSACTIONS=off
+VUE_APP_SHOW_EXT_DONATION=false
+VUE_APP_EXT_DONATION_URL=
+VUE_APP_NO_COST_MAIL=false
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_PORT=5432
-POSTGRES_HOST=amplify_db
+POSTGRES_HOST=amplify_db
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 7c97a281e..e00b40279 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ package-lock.json
.env.test
.env.local
.env.*.local
+.env.test
# Log files
npm-debug.log*
diff --git a/package-lock.json b/package-lock.json
index d0230b0eb..54c5e331c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,8 @@
"@fortawesome/free-regular-svg-icons": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/vue-fontawesome": "^2.0.8",
+ "@sendgrid/client": "^8.1.3",
+ "@sendgrid/mail": "^8.1.3",
"@stripe/stripe-js": "^1.35.0",
"@vue-stripe/vue-stripe": "^4.4.4",
"axios": "^0.27.2",
@@ -28,6 +30,7 @@
"express": "^4.18.1",
"express-jwt": "^8.4.0",
"express-rate-limit": "^6.6.0",
+ "handlebars": "^4.7.8",
"jwks-rsa": "^2.1.4",
"knex": "^2.4.2",
"lob": "^6.6.3",
@@ -2657,6 +2660,51 @@
"node": ">=10.13.0"
}
},
+ "node_modules/@sendgrid/client": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.3.tgz",
+ "integrity": "sha512-mRwTticRZIdUTsnyzvlK6dMu3jni9ci9J+dW/6fMMFpGRAJdCJlivFVYQvqk8kRS3RnFzS7sf6BSmhLl1ldDhA==",
+ "dependencies": {
+ "@sendgrid/helpers": "^8.0.0",
+ "axios": "^1.6.8"
+ },
+ "engines": {
+ "node": ">=12.*"
+ }
+ },
+ "node_modules/@sendgrid/client/node_modules/axios": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/@sendgrid/helpers": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz",
+ "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==",
+ "dependencies": {
+ "deepmerge": "^4.2.2"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/@sendgrid/mail": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.3.tgz",
+ "integrity": "sha512-Wg5iKSUOER83/cfY6rbPa+o3ChnYzWwv1OcsR8gCV8SKi+sUPIMroildimlnb72DBkQxcbylxng1W7f0RIX7MQ==",
+ "dependencies": {
+ "@sendgrid/client": "^8.1.3",
+ "@sendgrid/helpers": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=12.*"
+ }
+ },
"node_modules/@sideway/address": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
@@ -7469,7 +7517,6 @@
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -9310,9 +9357,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"node_modules/follow-redirects": {
- "version": "1.15.3",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
- "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"funding": [
{
"type": "individual",
@@ -9738,6 +9785,26 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/handlebars": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
+ "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
"node_modules/har-schema": {
"version": "2.0.0",
"license": "ISC",
@@ -12865,8 +12932,7 @@
"node_modules/minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
- "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
- "dev": true
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"node_modules/minipass": {
"version": "3.1.6",
@@ -13094,7 +13160,6 @@
},
"node_modules/neo-async": {
"version": "2.6.2",
- "dev": true,
"license": "MIT"
},
"node_modules/nice-try": {
@@ -16296,7 +16361,6 @@
},
"node_modules/source-map": {
"version": "0.6.1",
- "dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -17723,7 +17787,7 @@
},
"node_modules/uglify-js": {
"version": "3.4.10",
- "dev": true,
+ "devOptional": true,
"license": "BSD-2-Clause",
"dependencies": {
"commander": "~2.19.0",
@@ -17738,7 +17802,7 @@
},
"node_modules/uglify-js/node_modules/commander": {
"version": "2.19.0",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/unbox-primitive": {
@@ -19767,6 +19831,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
+ },
"node_modules/workbox-background-sync": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz",
@@ -21936,6 +22005,44 @@
"@panva/asn1.js": {
"version": "1.0.0"
},
+ "@sendgrid/client": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.3.tgz",
+ "integrity": "sha512-mRwTticRZIdUTsnyzvlK6dMu3jni9ci9J+dW/6fMMFpGRAJdCJlivFVYQvqk8kRS3RnFzS7sf6BSmhLl1ldDhA==",
+ "requires": {
+ "@sendgrid/helpers": "^8.0.0",
+ "axios": "^1.6.8"
+ },
+ "dependencies": {
+ "axios": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "requires": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ }
+ }
+ },
+ "@sendgrid/helpers": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz",
+ "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==",
+ "requires": {
+ "deepmerge": "^4.2.2"
+ }
+ },
+ "@sendgrid/mail": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.3.tgz",
+ "integrity": "sha512-Wg5iKSUOER83/cfY6rbPa+o3ChnYzWwv1OcsR8gCV8SKi+sUPIMroildimlnb72DBkQxcbylxng1W7f0RIX7MQ==",
+ "requires": {
+ "@sendgrid/client": "^8.1.3",
+ "@sendgrid/helpers": "^8.0.0"
+ }
+ },
"@sideway/address": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
@@ -25568,8 +25675,7 @@
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
- "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
- "dev": true
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
},
"default-gateway": {
"version": "5.0.5",
@@ -26916,9 +27022,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"follow-redirects": {
- "version": "1.15.3",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
- "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q=="
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
},
"for-in": {
"version": "1.0.2",
@@ -27218,6 +27324,18 @@
"version": "2.0.1",
"dev": true
},
+ "handlebars": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
+ "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
+ "requires": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "uglify-js": "^3.1.4",
+ "wordwrap": "^1.0.0"
+ }
+ },
"har-schema": {
"version": "2.0.0"
},
@@ -29405,8 +29523,7 @@
"minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
- "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
- "dev": true
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"minipass": {
"version": "3.1.6",
@@ -29585,8 +29702,7 @@
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
},
"neo-async": {
- "version": "2.6.2",
- "dev": true
+ "version": "2.6.2"
},
"nice-try": {
"version": "1.0.5",
@@ -31888,8 +32004,7 @@
"dev": true
},
"source-map": {
- "version": "0.6.1",
- "dev": true
+ "version": "0.6.1"
},
"source-map-js": {
"version": "1.0.2",
@@ -32938,7 +33053,7 @@
},
"uglify-js": {
"version": "3.4.10",
- "dev": true,
+ "devOptional": true,
"requires": {
"commander": "~2.19.0",
"source-map": "~0.6.1"
@@ -32946,7 +33061,7 @@
"dependencies": {
"commander": {
"version": "2.19.0",
- "dev": true
+ "devOptional": true
}
}
},
@@ -34412,6 +34527,11 @@
"version": "1.2.3",
"dev": true
},
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
+ },
"workbox-background-sync": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz",
diff --git a/package.json b/package.json
index 3266929c5..93dce1b94 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,8 @@
"@fortawesome/free-regular-svg-icons": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/vue-fontawesome": "^2.0.8",
+ "@sendgrid/client": "^8.1.3",
+ "@sendgrid/mail": "^8.1.3",
"@stripe/stripe-js": "^1.35.0",
"@vue-stripe/vue-stripe": "^4.4.4",
"axios": "^0.27.2",
@@ -60,6 +62,7 @@
"express": "^4.18.1",
"express-jwt": "^8.4.0",
"express-rate-limit": "^6.6.0",
+ "handlebars": "^4.7.8",
"jwks-rsa": "^2.1.4",
"knex": "^2.4.2",
"lob": "^6.6.3",
diff --git a/script/send-letters.js b/script/send-letters.js
new file mode 100644
index 000000000..cf0a22b36
--- /dev/null
+++ b/script/send-letters.js
@@ -0,0 +1,26 @@
+const axios = require('axios')
+const letterData = require('./catchup.js')
+
+;(async () => {
+ const data = JSON.parse(letterData)
+
+ for (const transaction of data) {
+ try {
+ const response = await axios.post(
+ 'https://amplify-hooks-0194518485a8.herokuapp.com/api/checkout/process-transaction',
+ {
+ data: {
+ object: {
+ id: transaction.stripe_id
+ }
+ },
+ type: 'payment_intent.succeeded'
+ }
+ )
+
+ if (response.statusCode == 201) console.log(transaction.stripe_id)
+ } catch (error) {
+ console.error(error)
+ }
+ }
+})()
diff --git a/script/stringify.js b/script/stringify.js
index 2c36f5fb5..35102da8d 100644
--- a/script/stringify.js
+++ b/script/stringify.js
@@ -1,328 +1,32 @@
+/*
const reps = JSON.stringify([
{
- name: 'Dr. Buu Nygren',
- title: 'President of the Navajo Nation',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/photo_P_Nygren.jpg?resize=1080%2C1080&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: 'alray.nelson@navajo-nsn.gov'
- },
- {
- name: 'Jasmine Blackwater-Nygren',
- title: 'First Lady of the Navajo Nation',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/photo_FL_Nygren-Blackwater.jpg?resize=1080%2C1080&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: 'alray.nelson@navajo-nsn.gov'
- },
- {
- name:"Richelle Montoya",
- title:"Vice President of the Navajo Nation",
- photoUrl:"https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/photo_VP_Montoya.jpg?resize=1080%2C1080&ssl=1",
- address_line1:"PO Box 7440",
- address_line2:"",
- address_city:"Window Rock",
- address_state:"AZ",
- address_zip:"86515",
- address_country:"US",
- email:"josie.bowman@navajo-nsn.gov"
- },
- {
- name: 'Ethel Branch',
- title: 'Department of Justice, Attorney General',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/attorney_general_Branch.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Sean McCabe',
- title: 'Office of the Controller, Controller',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/controller_McCabe.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Justin Ahasteen',
- title: 'Navajo Nation Washington Office, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Ahasteen.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Heather Clah',
- title: 'Department of Justice, Deputy Attorney General',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/dag_Clah.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Thomas Cody',
- title: 'Division of Social Services, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Cody.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Sherylene Yazzie',
- title: 'Department of Health, Acting Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/Seal_gray_gradient.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Roy Tracy',
- title: 'Department of Diné Education, Interim Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Tracy.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Tony Skrelunas',
- title: 'Division of Economic Development, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Skrelunas.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Bobbie Ann Baldwin',
- title: 'Navajo Nation Veterans Administration, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Baldwin.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Shawnevan Dale',
- title: 'Executive Director, Division of General Services',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Dale.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Tom Platero',
- title: 'Division of Transportation, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Platero.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Effie Edsitty',
- title: 'Office of the Navajo Tax Commission, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Edsitty.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Arbin Mitchell',
- title: 'Division of Community Development, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Mitchell.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Sarah Slim',
- title: 'Navajo-Hopi Land Commission Office, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Slim_2.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'W. Mike Halona',
- title: 'Division of Natural Resources, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Halona.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Byron C. Shorty',
- title: 'Telecommunications Regulatory Commission Office, Acting Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/09/director_Shorty.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Michael Anderson',
- title: 'Division of Public Safety, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Anderson-1.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Stephen Etsitty',
- title: 'Navajo Nation Environmental Protection Agency, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Etsitty.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Dominic Beyal',
- title: 'Office of Management & Budget, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Beyal.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Lisa Jymm',
- title: 'Navajo Nation Fiscal Recovery Fund Office, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/03/director.Jymm_.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Reycita Toddy',
- title: 'Division of Human Resources, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/Seal_gray_gradient.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
+ name: 'Stephen Hoffman',
+ title: 'LANL SWEIS Document Manager, DOE/NNSA ',
+ photoUrl: 'https://imgs.search.brave.com/G46oqr3VnummnoFmkqT_NqalvvWvKQxpoX-EJITKqGQ/rs:fit:860:0:0:0/g:ce/aHR0cHM6Ly9uYXRp/b25hbG1hZ2xhYi5v/cmcvaW1hZ2VzL2xh/eW91dC9sb3MtYWxh/bW9zLWxvZ28uanBn/P2Q9MjAyMzAyMDc',
+ address_line1: '3747 West Jemez Road ',
address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
+ address_city: 'Los Alamos',
+ address_state: 'NM',
+ address_zip: '87544',
address_country: 'US',
- email: ''
- }
+ email: 'lanlsweis@nnsa.doe.gov'
+ }
])
+ */
-
-/*
const assets = JSON.stringify({
- campaign_logo: 'https://i.imgur.com/o3lxGJD.png',
- campaign_background: 'https://i.imgur.com/qGOHdiP.jpeg',
- 'campaign-img-1': 'https://i.imgur.com/h88GBNC.jpeg',
- 'campaign-img-2': 'https://i.imgur.com/lcQWK6p.jpeg',
- 'campaign-img-3': 'https://i.imgur.com/bnPQVOR.jpeg',
- 'infographic': 'https://i.imgur.com/BJCPDCR.jpeg'
+ campaign_logo: 'https://i.imgur.com/0I80XGh.png',
+ campaign_background:
+ 'https://media.assettype.com/freepressjournal/2024-09-04/i722yxsy/lg_NR15OldQueensGate0889_edit.jpg?rect=0%2C0%2C3900%2C2194&w=1200&auto=format%2Ccompress&ogImage=true',
+ infographic: 'https://i.imgur.com/I7E3J5Q.png',
+ 'campaign-img-1':
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-yngrxizvU5kAZ3CP9-iQnn1OD14eXkpeXUYo96KOL6sg19Icwoes_JYlm_a61pzAcRE&usqp=CAU',
+ 'campaign-img-2':
+ 'https://images-prod.gothamist.com/images/GettyImages-1481222828.width-1000.jpg',
+ 'campaign-img-3':
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2X0OYEKhzrxmyMymuEaqDUIq0jDakYX4i4jaqRI3AUs0svGfcNDbpdatY4WUD6LMPRqg&usqp=CAU'
})
- */
-console.log(reps)
-//console.log(assets)
+//console.log(reps)
+console.log(assets)
diff --git a/server/db/migrations/20240817143934_create_letter_templates_table.js b/server/db/migrations/20240817143934_create_letter_templates_table.js
new file mode 100644
index 000000000..f28f55008
--- /dev/null
+++ b/server/db/migrations/20240817143934_create_letter_templates_table.js
@@ -0,0 +1,39 @@
+module.exports = {
+ async up(knex) {
+ await knex.schema.createTable('letter_templates', (table) => {
+ table.increments()
+ table.timestamps(false, true, false)
+ table.string('name').notNullable()
+ table.string('subject').notNullable()
+ table.text('html').notNullable()
+ table.jsonb('merge_variables').notNullable()
+ })
+
+ await knex.schema.alterTable('letters', (table) => {
+ table.integer('letter_template_id').unsigned()
+ table.foreign('letter_template_id').references('letter_templates.id')
+ table.enu('delivery_method', ['email', 'snail_mail'], {
+ useNative: true,
+ enumName: 'delivery_methods'
+ })
+ table.string('email')
+ })
+
+ await knex.schema.alterTable('campaigns', (table) => {
+ table.integer('letter_template_id').unsigned()
+ table.foreign('letter_template_id').references('letter_templates.id')
+ })
+ },
+
+ async down(knex) {
+ await knex.schema.dropTable('letter_templates')
+
+ await knex.schema.alterTable('letters', (table) => {
+ table.dropColumn('letter_template_id')
+ })
+
+ await knex.schema.alterTable('campaigns', (table) => {
+ table.dropColumn('letter_template_id')
+ })
+ }
+}
diff --git a/server/db/models/campaign.js b/server/db/models/campaign.js
index 1b1ccd244..cf75fe676 100644
--- a/server/db/models/campaign.js
+++ b/server/db/models/campaign.js
@@ -25,7 +25,8 @@ class Campaign extends BaseModel {
page_url: { type: 'string', minLength: 1 },
campaign_tagline: { type: 'string' },
campaign_text: { type: 'string' },
- supplemental_text: { type: 'string' }
+ supplemental_text: { type: 'string' },
+ letter_template_id: { type: 'integer' }
}
}
}
diff --git a/server/db/models/letter-template.js b/server/db/models/letter-template.js
new file mode 100644
index 000000000..4c1b32128
--- /dev/null
+++ b/server/db/models/letter-template.js
@@ -0,0 +1,22 @@
+const BaseModel = require('./_base')
+
+class LetterTemplate extends BaseModel {
+ static get tableName() {
+ return 'letter_templates'
+ }
+
+ static get jsonSchema() {
+ return {
+ type: 'object',
+ required: ['lob_template_id', 'sendgrid_template_id', 'merge_variables'],
+
+ properties: {
+ subject: { type: 'string', minLength: 1, maxLength: 255 },
+ name: { type: 'string', minLength: 1, maxLength: 255 },
+ merge_variables: { type: 'object' }
+ }
+ }
+ }
+}
+
+module.exports = LetterTemplate
diff --git a/server/db/models/letter.js b/server/db/models/letter.js
index 648e4872c..4f13121e9 100644
--- a/server/db/models/letter.js
+++ b/server/db/models/letter.js
@@ -12,22 +12,27 @@ class Letter extends BaseModel {
'constituentId',
'transactionId',
'letterTemplate',
- 'letterVersion',
'addressee',
'addressLine_1',
'city',
'state',
- 'zip'
+ 'zip',
+ 'deliveryMethod'
],
properties: {
- letter_template: { type: 'string', minLength: 1, maxLength: 255 },
+ letter_template: { type: 'string', minLength: 1, maxLength: 255 }, // Don't use this field now. Saving it just for compatibility
+ lob_template_id: { type: 'string', maxLength: 255 },
+ sendgrid_template_id: { type: 'string', maxLength: 255 },
letter_version: { type: 'string', minLength: 1, maxLength: 255 },
addressee: { type: 'string', minLength: 1, maxLength: 255 },
address_line_1: { type: 'string', minLength: 1, maxLength: 255 },
address_line_2: { type: 'string', minLength: 1, maxLength: 255 },
city: { type: 'string', minLength: 1, maxLength: 255 },
state: { type: 'string', minLength: 1, maxLength: 255 },
- zip: { type: 'string', minLength: 1, maxLength: 255 }
+ zip: { type: 'string', minLength: 1, maxLength: 255 },
+ email: { type: 'string', minLength: 1, maxLength: 255 },
+ deliveryMethod: { type: 'string', minLength: 1, maxLength: 255 },
+ trackingNumber: { type: 'string', minLength: 1, maxLength: 255 }
}
}
}
diff --git a/server/db/seeds/development/01-seed-letter_templates-table.js b/server/db/seeds/development/01-seed-letter_templates-table.js
new file mode 100644
index 000000000..920670724
--- /dev/null
+++ b/server/db/seeds/development/01-seed-letter_templates-table.js
@@ -0,0 +1,66 @@
+module.exports = {
+ async seed(knex) {
+ await knex('letter_templates').del()
+
+ await knex('letter_templates').insert([
+ {
+ id: 1,
+ name: 'test_template',
+ subject: 'To Whom it May Concern',
+ merge_variables: {
+ representativeName: {
+ choices: [],
+ label: '',
+ display: false
+ },
+ communityImpact: {
+ choices: [
+ 'my family is affected by the damming of this river',
+ 'too many children are being forced to work at beaver malls for substandard wages'
+ ],
+ label: 'How this legislation impacts you',
+ display: true
+ },
+ personalImpact: {
+ choices: [
+ 'I am allergic to the hardwoods used in beaver dam construction',
+ 'local children are being kidnapped by beavers and indoctrinated into new age beaver spirituality',
+ 'local children are being kidnapped by beavers and indoctrinated into late stage beaver capitalism'
+ ],
+ label: 'How this legislation impacts your community',
+ display: true
+ }
+ },
+ html: '
This is a test template!
Dear {{representativeName}},
This campaign is important because {{communityImpact}}.
It affects me personally because {{personalImpact}}.
'
+ },
+ {
+ id: 2,
+ name: 'rutgers caste equity petition',
+ subject: 'To the Administration of Rutgers University',
+ merge_variables: {},
+ html: 'Dear Rutgers Administration,
I write today to urge Rutgers University to take bold action by adopting all four recommendations from the University Task Force on Caste Discrimination, including adding caste as a protected category within the institution’s anti-discrimination policies. This essential step would reaffirm Rutgers’ commitment to fostering an inclusive and equitable campus for all students, faculty, and staff.
Caste discrimination is a grave and pervasive form of oppression that transcends borders and affects marginalized communities globally. At Rutgers, caste-oppressed students and staff deserve the same protections afforded to others against bias and harm. Recognizing caste explicitly in Rutgers’ policies will ensure that those impacted have the institutional support needed to seek accountability and justice.
The inclusion of caste protections is not about targeting any particular group; it is about creating an environment where equity is non-negotiable. Opponents of this policy often use misinformation to sideline the voices of caste-oppressed communities. Rutgers must not allow such narratives to delay progress. Instead, it should set a powerful example by prioritizing the voices of those most impacted and centering their lived experiences in its decision-making.
As a university that prides itself on diversity, equity, and inclusion, Rutgers has an opportunity to demonstrate what those values look like in practice. By taking immediate steps to implement the Task Force’s recommendations, Rutgers can establish itself as a leader in addressing caste oppression in higher education.
This is a pivotal moment for Rutgers to be on the right side of history. I urge you to act now and adopt caste protections, ensuring that all members of your community can thrive with dignity, safety, and equality.
In solidarity,
{{ firstName }} {{ lastName }}
'
+ },
+ {
+ id: 3,
+ name: 'Pueblo Action Alliance Los Alamos Campaign',
+ subject:
+ 'Halt Los Alamos National Lab’s Flanged Tritium Waste Container (FTWC) Venting in Pueblo Communities',
+ merge_variables: {},
+ html: 'Dear Mr. Hoffman,
\
+
\
+ I\'m submitting a public comment to express my concern regarding the NNSA/LANL\'s draft Site-Wide Environmental Impact Statement. (EPCU) project outline still poses adverse threats to the Caja del Rio\'s sensitive ecosystem, cultural resources utilized by surrounding Pueblos, and land-based learning opportunities for Pueblo youth and other community members.
\
+ • The NNSA and DOE need to engage in Free, Prior and Informed Consent practices that ensure meaningful consultation with tribal leadership.
\
+ Increasing plutonium pit production to grow the nuclear weapons arsenal is in direct contradiction to the wishes of concerned Pueblo community members to stop plutonium pit production altogether.
\
+ • There must be comprehensive cleanup efforts of existing radioactive nuclear waste which continues to threaten groundwater sources and soil health.
\
+ • LANL\'s permit to vent tritium as another means to expand and continue operations has already faced heavy opposition due to the radioactive exposure to the surrounding landscapes and community. This is also in violation of the Clean Water Act.
\
+ Modifying and expanding LAN\'s facilities would put an additional strain on the region\'s water supply issues. Our water must be protected and preserved sustainably for our future generations.
\
+ Addressing the concerns outlined in this email/letter will allow impacted Pueblo communities to voice opposition on the Los Alamos National Lab\'s expanded nuclear weapons programs and the violent legacy of environmental degradation to the land, air, and water.
\
+ Sincerely,
\
+
\
+ {{ firstName }} {{ lastName }}
\
+
\
+
'
+ }
+ ])
+ }
+}
diff --git a/server/db/seeds/development/02-seed-campaigns-table.js b/server/db/seeds/development/02-seed-campaigns-table.js
new file mode 100644
index 000000000..b03b08850
--- /dev/null
+++ b/server/db/seeds/development/02-seed-campaigns-table.js
@@ -0,0 +1,206 @@
+module.exports = {
+ async seed(knex) {
+ // Deletes ALL existing entries
+ await knex('campaigns').del()
+
+ // Inserts seed entries
+ await knex('campaigns').insert([
+ {
+ id: 1,
+ organization: 'BeaverHalters',
+ name: 'Stopping PNW Beavers',
+ cause: 'Civic Rights',
+ type: 'Grant',
+ page_url: 'https://example.com',
+ letter_template_id: 1,
+ campaign_tagline:
+ 'Protecting our Woodlands and Rivers from the Big Beaver Menace',
+ campaign_text:
+ 'For years, Beavers in the Pacific Northwest have been getting more aggressive about damming rivers and gentrifying our beautiful rivers.
In recent years, they have started erecting large beaver shopping centers and abducting human children to use as low wage labor in their beaver malls!
With your help, we can stop the further encroachment of beavers into human habitats.
',
+ supplemental_text:
+ 'Did you know that PNW beavers are also all communists? Only with your help can we turn the tide and live in freedom and prosperity.
',
+ representatives: JSON.stringify([
+ {
+ name: 'Velma Dinkley',
+ title: 'District 1 Supervisor',
+ photoUrl: 'https://placehold.co/250',
+ address_line1: '123 Fake St.',
+ address_line2: 'Suite 8B',
+ address_city: 'Portland',
+ address_state: 'OR',
+ address_zip: '12345',
+ address_country: 'US',
+ email: 'noreply@example.com'
+ },
+ {
+ name: 'Jar Jar Binks',
+ title: 'District 2 Supervisor',
+ photoUrl: 'https://placehold.co/250',
+ address_line1: '123 Fake St.',
+ address_line2: 'Suite 9B',
+ address_city: 'Portland',
+ address_state: 'OR',
+ address_zip: '12345',
+ address_country: 'US',
+ email: 'noreply@example.com'
+ },
+ {
+ name: 'Fei Fong Wong',
+ title: 'District 3 Supervisor',
+ photoUrl: 'https://placehold.co/250',
+ address_line1: '123 Fake St.',
+ address_line2: 'Suite 8B',
+ address_city: 'Portland',
+ address_state: 'OR',
+ address_zip: '12345',
+ address_country: 'US',
+ email: 'noreply@example.com'
+ },
+ {
+ name: 'Buccee Beaver',
+ title: 'District 1 Supervisor',
+ photoUrl: 'https://placehold.co/250',
+ address_line1: '123 Fake St.',
+ address_line2: 'Suite 7F',
+ address_city: 'Portland',
+ address_state: 'OR',
+ address_zip: '12345',
+ address_country: 'US',
+ email: 'noreply@example.com'
+ },
+ {
+ name: 'Hatsune Miku',
+ title: 'District 1 Supervisor',
+ photoUrl:
+ 'https://preview.redd.it/bucsune-miku-v0-niqz9xavfz3d1.png?auto=webp&s=c7291ff1aa26b98cac36f9a759de823f1d294bc3',
+ address_line1: '123 Fake St.',
+ address_line2: 'Suite 8B',
+ address_city: 'Portland',
+ address_state: 'OR',
+ address_zip: '12345',
+ address_country: 'US',
+ email: 'noreply@example.com'
+ }
+ ]),
+ assets: JSON.stringify({
+ campaign_logo: 'https://placehold.co/600x400',
+ campaign_background: 'https://placehold.co/1500x600',
+ 'campaign-img-1': 'https://placehold.co/600x400',
+ 'campaign-img-2': 'https://placehold.co/600x400',
+ 'campaign-img-3': 'https://placehold.co/600x400'
+ })
+ },
+ {
+ id: 2,
+ organization: 'Equality Labs',
+ name: 'Protect Caste Equity at Rutgers University',
+ cause: 'Civic Rights',
+ type: 'Grant',
+ page_url:
+ 'https://rutgersaaup.org/wp-content/uploads/2024/08/Rutgers-Caste-Report-August-2024.pdf',
+ letter_template_id: 2,
+ campaign_tagline: 'URGE RUTGERS TO PRIORITIZE CASTE EQUITY',
+ campaign_text:
+ 'We applaud Rutgers University for taking a crucial step toward addressing caste inequity through the recent University Task Force Report on Caste Discrimination in Higher Education and at Rutgers Global caste systems enforce discrimination through inherited social status. They are a systemic injustice that has long been overlooked in the United States, despite its prevalence in many American institutions including higher education. That is why the findings of this report are so crucial. By recommending to add caste as a protected category, Rutgers has an opportunity to lead the way in creating equitable spaces for all, especially for caste-oppressed faculty, students, and workers who experience this bias.
The testimonies presented in Rutgers’ task force report are a powerful reminder of the urgent need to address caste-based exclusion, harassment, and inequities in higher education. Caste is not an abstract concept; it is a harsh reality for millions. Caste discrimination spans across industries and includes bullying, harassment, bias, wage theft, sexual harassment, and even trafficking. Caste-oppressed individuals have also been denied rental housing upon the discovery of their caste identity. This issue has gained significant attention in New Jersey following human trafficking allegations against the BAPS temples, where caste-oppressed workers were held against their will and paid just a dollar an hour under inhumane conditions
In New Jersey there are many communities who suffer caste discrimination in their communities from Africa, South Asia, Asia, and Indigenous residents of the state. Students, faculty and staff from these backgrounds must be able to access the campus as a place of learning and as a workplace free from discrimination and harm.
From workplace discrimination to campus bullying, the insidious impacts of caste privilege have been well-documented by marginalized communities, In our own 2016 report Caste in the United States we have found caste oppressed people face alarming discrimination and harassment with 1 in 4 facing physical and verbal assault, 1 in 3 education discrimination and 2 out 3 workplace discrimination.
As a U.S.-based civil rights group we urge Rutgers’ administration **to fully adopt the task force’s recommendations and implement robust enforcement mechanisms.** This includes education on caste equity for students, staff, and faculty and meaningful support for those who come forward with experiences of caste-based harm.
As Rutgers advances this work, we caution against narratives that dismiss caste protections as “anti-Hindu” or as targeting specific communities. Such arguments weaponize bad faith arguments and privilege to silence Dalit voices and maintain systems of oppression. Caste is found across multiple geographies and faiths and it must be addressed as its own system of exclusion. We believe in fostering dialogue that centers the experiences of the most vulnerable while rejecting extremist rhetoric that masquerades falsely as a defense of cultural identity.
Rutgers’ initiative is part of a broader, necessary movement to confront caste oppression in the United States. We look forward to standing alongside other universities and institutions in their journey toward caste equity. Together, we can build communities where everyone can thrive with dignity and equal opportunity.
In solidarity,
Equality Labs
',
+ supplemental_text:
+ 'Caste-oppressed students and staff deserve protection—yet Rutgers University continues to delay adopting crucial caste protections in its anti-discrimination policy. This hesitation comes after pressure from far-right nationalist groups that aim to erase the realities of caste-based harm.
In August 2024, the Rutgers Task Force on Caste Discrimination recommended adding caste as a protected category after collecting powerful testimony from affected community members. These recommendations are a critical step toward equity but remain stalled.
It’s time to demand action! Let’s ensure Rutgers doesn’t back down in the face of opposition. Flood the administration’s inboxes today and call for the immediate adoption of caste protections. Together, we can build a campus where no one has to endure caste discrimination.
',
+ representatives: JSON.stringify([
+ {
+ name: 'President Jonathan Holloway',
+ title: 'President, Rutgers University',
+ photoUrl:
+ 'https://www.rutgers.edu/sites/default/files/styles/3x4_one_third_full_1024_1x/public/2020-07/pro_NR20HollowayJonathan1819.jpg?h=ef631461&itok=uRWXEI4G',
+ address_line1: '7 College Avenue',
+ address_line2: '2nd Floor',
+ address_city: 'New Brunswick',
+ address_state: 'NJ',
+ address_zip: '08901',
+ address_country: 'US',
+ email: 'president@rutgers.edu'
+ },
+ {
+ name: 'Anna (Enobong) Branch',
+ title: 'Senior Vice President for University Equity and Inclusion',
+ photoUrl:
+ 'https://www.rutgers.edu/sites/default/files/styles/3x4_one_third_full_1024_1x/public/2020-09/pro_Ann_Branch.jpg?h=3dfac914&itok=rA6GxwC_',
+ address_line1: '106 Sommerset Street',
+ address_line2: '7th Floor',
+ address_city: 'New Brunswick',
+ address_state: 'NJ',
+ address_zip: '08901',
+ address_country: 'US',
+ email: 'enobong.branch@rutgers.edu'
+ },
+ {
+ name: 'Prabhas Moghe',
+ title: 'Executive Vice President for Academic Affairs at Rutgers',
+ photoUrl:
+ 'https://www.rutgers.edu/sites/default/files/styles/max_width_embed_default_2x/public/2020-09/pro_Prabhas_Moghe.jpg?itok=dLd3TLhW',
+ address_line1: '7 College Avenue',
+ address_line2: '2nd Floor',
+ address_city: 'New Brunswick',
+ address_state: 'NJ',
+ address_zip: '08901',
+ address_country: 'US',
+ email: 'nbprovost@rutgers.edu.'
+ }
+ ]),
+ assets: JSON.stringify({
+ campaign_logo: 'https://i.imgur.com/0I80XGh.png',
+ campaign_background:
+ 'https://media.assettype.com/freepressjournal/2024-09-04/i722yxsy/lg_NR15OldQueensGate0889_edit.jpg?rect=0%2C0%2C3900%2C2194&w=1200&auto=format%2Ccompress&ogImage=true',
+ infographic: 'https://i.imgur.com/I7E3J5Q.png',
+ 'campaign-img-1':
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-yngrxizvU5kAZ3CP9-iQnn1OD14eXkpeXUYo96KOL6sg19Icwoes_JYlm_a61pzAcRE&usqp=CAU',
+ 'campaign-img-2':
+ 'https://images-prod.gothamist.com/images/GettyImages-1481222828.width-1000.jpg',
+ 'campaign-img-3':
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2X0OYEKhzrxmyMymuEaqDUIq0jDakYX4i4jaqRI3AUs0svGfcNDbpdatY4WUD6LMPRqg&usqp=CAU'
+ })
+ },
+ {
+ id: 3,
+ organization: 'Pueblo Action Alliance',
+ name: 'Pueblo Action Alliance',
+ cause: 'Civic Rights',
+ type: 'Grant',
+ page_url:
+ 'https://rutgersaaup.org/wp-content/uploads/2024/08/Rutgers-Caste-Report-August-2024.pdf',
+ letter_template_id: 3,
+ campaign_tagline:
+ 'Halt Los Alamos National Lab’s Flanged Tritium Waste Container (FTWC) Venting in Pueblo Communities',
+ campaign_text:
+ 'Los Alamos National Labs (LANL) has proposed the Flanged Tritium Waste Container venting, four containers, near LANL and neighboring Pueblos. [Tewa Women United](https://tewawomenunited.org/) (TWU) took a position alongside many other concerned citizens and organizations opposing the FTWC venting and started a petition on Change.org called [“Protect Vulnerable New Mexico Communities: Halt Radioactive Tritium Release from LANL,”](https://www.change.org/p/protect-vulnerable-nm-communities-halt-radioactive-tritium-release-from-lanl) that accumulated 3,112 signatures that helped postpone the proposed venting on April 1st 2020. The All Pueblo Council of Governors also released a press release on March, 30th in opposition that alluded to the lack of tribal consultation as well as the lack of capacity in tribal governments due to COVID19.
The All Pueblo Council of Governers is set to give public comment to the NM Hazardous Waste Committee Meeting on September, 9th. It’s been stated that the New Mexico Environmental Department (NMED) and NM Hazardous Waste Board (NM HWB) do not oversee radiological contamination from LANL and that all radiological contamination remediation and radiological release approvals are under the regulatory authority of the Department of Energy (DOE). Even though it is the responsibility of NMED to ensure safety regulations for New Mexico citizens. In 2009 DOE enacted a policy, [Order 144.1](https://www.energy.gov/sites/prod/files/DOE%20O%20144.1.pdf), to ensure responsible interactions and consultation with sovereign tribal nations that we believe aren\'t being upheld.
',
+ supplemental_text:
+ 'Caste-oppressed students and staff deserve protection—yet Rutgers University continues to delay adopting crucial caste protections in its anti-discrimination policy. This hesitation comes after pressure from far-right nationalist groups that aim to erase the realities of caste-based harm.
In August 2024, the Rutgers Task Force on Caste Discrimination recommended adding caste as a protected category after collecting powerful testimony from affected community members. These recommendations are a critical step toward equity but remain stalled.
It’s time to demand action! Let’s ensure Rutgers doesn’t back down in the face of opposition. Flood the administration’s inboxes today and call for the immediate adoption of caste protections. Together, we can build a campus where no one has to endure caste discrimination.
',
+ representatives: JSON.stringify([
+ {
+ name: 'Stephen Hoffman',
+ title: 'LANL SWEIS Document Manager, DOE/NNSA ',
+ photoUrl:
+ 'https://imgs.search.brave.com/G46oqr3VnummnoFmkqT_NqalvvWvKQxpoX-EJITKqGQ/rs:fit:860:0:0:0/g:ce/aHR0cHM6Ly9uYXRp/b25hbG1hZ2xhYi5v/cmcvaW1hZ2VzL2xh/eW91dC9sb3MtYWxh/bW9zLWxvZ28uanBn/P2Q9MjAyMzAyMDc',
+ address_line1: '3747 West Jemez Road ',
+ address_line2: '',
+ address_city: 'Los Alamos',
+ address_state: 'NM',
+ address_zip: '87544',
+ address_country: 'US',
+ email: 'lanlsweis@nnsa.doe.gov'
+ }
+ ]),
+ assets: JSON.stringify({
+ campaign_logo: 'https://i.imgur.com/0I80XGh.png',
+ campaign_background:
+ 'https://media.assettype.com/freepressjournal/2024-09-04/i722yxsy/lg_NR15OldQueensGate0889_edit.jpg?rect=0%2C0%2C3900%2C2194&w=1200&auto=format%2Ccompress&ogImage=true',
+ infographic: 'https://i.imgur.com/I7E3J5Q.png',
+ 'campaign-img-1':
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-yngrxizvU5kAZ3CP9-iQnn1OD14eXkpeXUYo96KOL6sg19Icwoes_JYlm_a61pzAcRE&usqp=CAU',
+ 'campaign-img-2':
+ 'https://images-prod.gothamist.com/images/GettyImages-1481222828.width-1000.jpg',
+ 'campaign-img-3':
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2X0OYEKhzrxmyMymuEaqDUIq0jDakYX4i4jaqRI3AUs0svGfcNDbpdatY4WUD6LMPRqg&usqp=CAU'
+ })
+ }
+ ])
+ }
+}
diff --git a/server/db/seeds/development/seed-admins-table.js b/server/db/seeds/development/03-seed-admins-table.js
similarity index 100%
rename from server/db/seeds/development/seed-admins-table.js
rename to server/db/seeds/development/03-seed-admins-table.js
diff --git a/server/db/seeds/development/seed-constituents-table.js b/server/db/seeds/development/04-seed-constituents-table.js
similarity index 100%
rename from server/db/seeds/development/seed-constituents-table.js
rename to server/db/seeds/development/04-seed-constituents-table.js
diff --git a/server/db/seeds/development/seed-transactions-table.js b/server/db/seeds/development/05-seed-transactions-table.js
similarity index 100%
rename from server/db/seeds/development/seed-transactions-table.js
rename to server/db/seeds/development/05-seed-transactions-table.js
diff --git a/server/db/seeds/development/seed-campaigns-table.js b/server/db/seeds/development/seed-campaigns-table.js
deleted file mode 100644
index 7c0732b87..000000000
--- a/server/db/seeds/development/seed-campaigns-table.js
+++ /dev/null
@@ -1,425 +0,0 @@
-module.exports = {
- async seed(knex) {
- // Deletes ALL existing entries
- await knex('campaigns').del()
-
- // Inserts seed entries
- await knex('campaigns').insert([
- {
- id: 1,
- organization: 'White Mesa Ute Community',
- name: 'White Mesa Concerned Community',
- cause: 'Civic Rights',
- type: 'Grant',
- page_url: 'https://protectwhitemesa.org/',
- campaign_tagline: 'Protecting the Ute Tribal Lands and Peoples from Radioactive Waste',
- campaign_text: 'White Mesa Concerned Community is a grassroots group of concerned tribal members of the Ute Mountain Ute Tribe. We work to inform our fellow tribal members and the public about our struggle to protect our community, health, water, air, land, culture, and sacred sites from toxic and radioactive contamination from the uranium mill. We demand that the uranium mill be closed and cleaned up.
Here are some of the species that continue to be impacted by the uranium mining:
Mexican Spotted Owl (Strix occidentalis lucida): This owl is found in forested canyons and riparian zones. The tribe works to protect its habitat by managing forest resources and reducing threats such as wildfires and logging.
Southwestern Willow Flycatcher (Empidonax traillii extimus): Found in riparian areas, this bird\'s protection includes restoring native vegetation, managing water resources, and preventing habitat degradation from livestock grazing and invasive species.
Gunnison Sage-Grouse (Centrocercus minimus): The tribe participates in habitat restoration and conservation efforts for this species, including managing land use and mitigating threats like overgrazing, invasive plants, and human encroachment.
Yellow-Billed Cuckoo (Coccyzus americanus): The tribe works to conserve riparian habitats crucial for this bird by managing water flow and restoring native plant communities that provide nesting and foraging opportunities.
Colorado Pikeminnow (Ptychocheilus lucius): The tribe collaborates with state and federal agencies to protect this endangered fish by managing water quality and flow in river systems, reducing the impact of non-native species, and restoring critical habitat areas.
Bonytail Chub (Gila elegans) and Humpback Chub (Gila cypha): Both fish species benefit from the tribe\'s efforts to maintain clean and healthy river systems, which include monitoring water quality, controlling non-native species, and advocating for water management practices that support native fish populations.
',
- supplemental_text: 'The White Mesa Ute Community of the Ute Mountain Ute Tribe is located between Blanding and Bluff in San Juan County in southern Utah. It is near Cedar Mesa, the Bears Ears National Monument, Valley of the Gods, the San Juan River, national parks, and many other beautiful and sacred areas.
White Mesa, however, is adjacent to the Energy Fuels’ uranium mill, the last such facility in the United States, where uranium tailings and other radioactive materials are sent for “processing” and dumping. Not only was the mill built right next to our community, but it was built right on top of hundreds of our culturally significant sites.
',
- representatives: JSON.stringify([
- {
- name: 'Spencer Cox',
- title: 'Governor of Utah',
- photoUrl:
- 'https://www.nga.org/wp-content/uploads/2021/01/Governor_Cox_official_square-scaled.jpg',
- address_line1: '350 N STATE ST',
- address_line2: 'STE 200',
- address_city: 'SALT LAKE CITY',
- address_state: 'UT',
- address_zip: '84114',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Phil Lyman',
- title: 'State Representative for District 69',
- photoUrl:
- 'https://le.utah.gov/images/legislator/house/LYMANP.jpg',
- address_line1: '333 S MAIN ST',
- address_line2: '',
- address_city: 'BLANDING',
- address_state: 'UT',
- address_zip: '84511',
- address_country: 'US',
- email: ''
- },
- ]),
- assets: JSON.stringify({
- campaign_logo: 'https://i.imgur.com/Lc9fG1y.png',
- campaign_background: 'https://i.imgur.com/WcFdL78.jpeg',
- 'campaign-img-1': 'https://i.imgur.com/gpGQxZQ.jpeg',
- 'campaign-img-2': 'https://i.imgur.com/5pSUR0q.jpeg',
- 'campaign-img-3': 'https://i.imgur.com/0EctJWf.png'
- })
- },
- {
- id: 2,
- organization: 'Hualapai Nation',
- name: 'Protect Hakamwe',
- cause: 'Civic Rights',
- type: 'Grant',
- page_url: 'http://instagram.com/protecthakamwe',
- campaign_tagline: 'Protect Ha’kamwe’ - No Lithium Mine',
- campaign_text: 'What is Ha’Kamwe’?
Ha’Kamwe’ means warm spring in the language of the Hualapai people.
Ha’Kamwe’ is fed by water naturally stored underground in volcanic rocks that seal it off from the land surface above (aka a confined volcanic aquifer). Under pressure, water flows underground along a geologic fault and emerges from the spring.
This sacred spring is a place for healing. In the words of a Hualapai elder: this is holy ground.
Where is Ha’Kamwe’?
Ha’Kamwe’ is part of Cholla Canyon Ranch in Wikieup, Arizona, where the Mojave and Sonoran deserts meet within the Big Sandy River basin. The ranch is managed by the Hualapai Tribe, while the ancestral homelands of the Hualapai people surrounding the site are currently managed by the Bureau of Land Management (BLM).
',
- supplemental_text: 'Hualapai tribal members, local community members, and allies are working to prevent further exploration drilling for the Big Sandy Lithium Project that would desecrate Ha’Kamwe’ and the ancestral homelands of the Hualapai people.
',
- representatives: JSON.stringify([
- {
- name: 'Dr. Buu Nygren',
- title: 'President of the Navajo Nation',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/photo_P_Nygren.jpg?resize=1080%2C1080&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: 'alray.nelson@navajo-nsn.gov'
- },
- {
- name: 'Jasmine Blackwater-Nygren',
- title: 'First Lady of the Navajo Nation',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/photo_FL_Nygren-Blackwater.jpg?resize=1080%2C1080&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: 'alray.nelson@navajo-nsn.gov'
- },
- {
- name:"Richelle Montoya",
- title:"Vice President of the Navajo Nation",
- photoUrl:"https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/photo_VP_Montoya.jpg?resize=1080%2C1080&ssl=1",
- address_line1:"PO Box 7440",
- address_line2:"",
- address_city:"Window Rock",
- address_state:"AZ",
- address_zip:"86515",
- address_country:"US",
- email:"josie.bowman@navajo-nsn.gov"
- },
- {
- name: 'Ethel Branch',
- title: 'Department of Justice, Attorney General',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/attorney_general_Branch.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Sean McCabe',
- title: 'Office of the Controller, Controller',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/controller_McCabe.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Justin Ahasteen',
- title: 'Navajo Nation Washington Office, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Ahasteen.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Heather Clah',
- title: 'Department of Justice, Deputy Attorney General',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/dag_Clah.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Thomas Cody',
- title: 'Division of Social Services, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Cody.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Sherylene Yazzie',
- title: 'Department of Health, Acting Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/Seal_gray_gradient.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Roy Tracy',
- title: 'Department of Diné Education, Interim Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Tracy.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Tony Skrelunas',
- title: 'Division of Economic Development, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Skrelunas.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Bobbie Ann Baldwin',
- title: 'Navajo Nation Veterans Administration, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Baldwin.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Shawnevan Dale',
- title: 'Executive Director, Division of General Services',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Dale.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Tom Platero',
- title: 'Division of Transportation, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Platero.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Effie Edsitty',
- title: 'Office of the Navajo Tax Commission, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Edsitty.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Arbin Mitchell',
- title: 'Division of Community Development, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Mitchell.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Sarah Slim',
- title: 'Navajo-Hopi Land Commission Office, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Slim_2.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'W. Mike Halona',
- title: 'Division of Natural Resources, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Halona.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Byron C. Shorty',
- title: 'Telecommunications Regulatory Commission Office, Acting Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/09/director_Shorty.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Michael Anderson',
- title: 'Division of Public Safety, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Anderson-1.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Stephen Etsitty',
- title: 'Navajo Nation Environmental Protection Agency, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/director_Etsitty.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Dominic Beyal',
- title: 'Office of Management & Budget, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/04/director_Beyal.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Lisa Jymm',
- title: 'Navajo Nation Fiscal Recovery Fund Office, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2024/03/director.Jymm_.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- },
- {
- name: 'Reycita Toddy',
- title: 'Division of Human Resources, Executive Director',
- photoUrl:
- 'https://i0.wp.com/opvp.navajo-nsn.gov/wp-content/uploads/2023/12/Seal_gray_gradient.jpg?resize=1080%2C1440&ssl=1',
- address_line1: 'PO Box 7440',
- address_line2: '',
- address_city: 'Window Rock',
- address_state: 'AZ',
- address_zip: '86515',
- address_country: 'US',
- email: ''
- }
- ]),
- assets: JSON.stringify({
- campaign_logo: 'https://i.imgur.com/o3lxGJD.png',
- campaign_background: 'https://i.imgur.com/qGOHdiP.jpeg',
- 'campaign-img-1': 'https://i.imgur.com/h88GBNC.jpeg',
- 'campaign-img-2': 'https://i.imgur.com/lcQWK6p.jpeg',
- 'campaign-img-3': 'https://i.imgur.com/bnPQVOR.jpeg',
- 'infographic': 'https://i.imgur.com/BJCPDCR.jpeg'
- })
- },
- {
- id: 3,
- organization: 'Save California Salmon',
- name: 'Save California Salmon',
- cause: 'Civic Rights',
- type: 'Grant',
- page_url: 'https://www.californiasalmon.org/',
- campaign_tagline:
- 'Restoring and Protecting California Salmon and Rivers for Future Generations',
- campaign_text:
- '#UNDAMTHEKLAMATH
Save California Salmon (SCS) is dedicated to policy change and community advocacy for Northern California’s salmon and fish dependent people. We support the fisheries and water protection work of the local communities, and advocate effective policy change for clean water, restored fisheries and vibrant communities. We aim to help to support Tribes and the general public in engaging with public comments related to water pollution, fisheries, and beneficial use issues.
Restoration of the Klamath River does not stop with dam removal. Salmon populations are continuing to plummet throughout California, leaving Tribal communities without salmon for subsistence, and ocean fishermen without a season. Restoration of the Klamath’s tributaries, which are often dewatered for animal agriculture, is also critical. We continued to support Tribal efforts to establish both permanent and temporary emergency flows in the Scott and Shasta Rivers through the California Water Resources Control Board. In December, the board passed emergency irrigation curtailments for both rivers, and we are still pushing for permanent instream flow requirements.
We also continued to fight for Trinity River flows, which are critical to the river, and to stop fish kills in the Klamath River. The Trinity is the Klamath’s largest tributary, but it is also an artificial Sacramento River tributary that feeds the Central Valley Water Project. The federal government is working on a new Biological Opinion for Endangered Species (water operations plan) for the Central Valley and State Water Projects. We are calling for a separate, protective Biological Opinion for the Trinity River, and for flows in the Bay Delta watersheds.
We are deeply dedicated to dam removal and flow restoration in all the North State’s watersheds. We want salmon back for all Northern California Tribes, which is why we are hopeful about Pacific Gas & Electric’s (PGE) December proposal to fully decommission the Eel River Dams.
',
- supplemental_text:
- 'At the end of 2020 California, Oregon and Berkshire Hathaway entered a new agreement to undam the Klamath River. This decision came after almost twenty years of organizing, testifying, actions and planning from the native peoples of the Klamath basin, coastal fishermen and their allies. This year we continue our advocacy to make sure these dams come down.
',
- representatives: JSON.stringify([
- {
- name: 'Bureau of Reclamation',
- title: '',
- photoUrl:
- 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/USBR_logo_oct_2019.jpg/220px-USBR_logo_oct_2019.jpg',
- address_line1: '2800 Cottage Way',
- address_line2: 'Room W-2820',
- address_city: 'Sacramento',
- address_state: 'CA',
- address_zip: '95825',
- address_country: 'US',
- email: ''
- }
- ]),
- assets: JSON.stringify({
- campaign_logo:
- 'https://static.wixstatic.com/media/d97ff6_b61eff2e17cc4511b92752e6af420835~mv2.png/v1/fill/w_96,h_97,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/White%20circle%2C%20Black%20background%20SCS%20Logo.png',
- campaign_background: 'https://i.imgur.com/4OsValj.png',
- 'campaign-img-1': 'https://i.imgur.com/fGMy8Wz.png',
- 'campaign-img-2': 'https://i.imgur.com/toMnnE0.png',
- 'campaign-img-3': 'https://i.imgur.com/wXRXDCd.png'
- })
- }
- ])
- }
-}
diff --git a/server/lib/handlebars.js b/server/lib/handlebars.js
new file mode 100644
index 000000000..6fd3ea5d4
--- /dev/null
+++ b/server/lib/handlebars.js
@@ -0,0 +1,23 @@
+// Wrapper for Handlebars template engine
+const handlebars = require('handlebars')
+
+class HandlebarsError extends Error {
+ constructor(message) {
+ super(message)
+ this.name = 'HandlebarsError'
+ }
+}
+
+class Handlebars {
+ static render(mergeVariables, html) {
+ try {
+ const template = handlebars.compile(html)
+
+ return template(mergeVariables)
+ } catch (err) {
+ throw new HandlebarsError(err.message)
+ }
+ }
+}
+
+module.exports = Handlebars
diff --git a/server/lib/lob.js b/server/lib/lob.js
new file mode 100644
index 000000000..4114b8d77
--- /dev/null
+++ b/server/lib/lob.js
@@ -0,0 +1,126 @@
+// Wrapper for the Lob API
+// We have the SDK in this project but it has incomplete functionality
+// so we will use endpoints directly.
+require('dotenv').config()
+const axios = require('axios')
+
+class LobError extends Error {
+ constructor(message) {
+ super(message)
+ this.name = 'LobError'
+ }
+}
+
+class Lob {
+ constructor() {
+ this.apiKey = process.env.LOB_API_KEY
+ this.lobUrl = process.env.LOB_BASE_URL
+ this.env = process.env.NODE_ENV
+ }
+
+ // auth headers
+ authHeaders() {
+ const encodedKey = btoa(`${this.apiKey}:`)
+ console.log(encodedKey)
+
+ return {
+ Authorization: `Basic ${encodedKey}`
+ }
+ }
+
+ // Merges all headers
+ headers() {
+ return { ...this.authHeaders() }
+ }
+
+ async template(id) {
+ try {
+ const letters = await axios.get(`${this.lobUrl}/templates/${id}`, {
+ headers: this.headers()
+ })
+
+ return letters.data.published_version
+ } catch (err) {
+ throw new LobError(err.message)
+ }
+ }
+
+ async send(payload) {
+ const data = {
+ to: payload.to,
+ from: payload.from,
+ file: payload.templateId,
+ merge_variables: payload.mergeVariables,
+ use_type: 'operational',
+ color: false
+ }
+
+ try {
+ if (this.env != 'production') {
+ return { response: 200, payload }
+ }
+
+ const response = await axios.post({
+ url: `${this.lobUrl}/letters}`,
+ headers: this.headers(),
+ 'Idempotency-key': payload.uuid,
+ data
+ })
+
+ return response.data
+ } catch (err) {
+ throw new LobError(err.message)
+ }
+ }
+
+ async verifyAddress(address) {
+ const payload = {
+ recipient: address.name,
+ primary_line: address.line1,
+ secondary_line: address.line2,
+ city: address.city,
+ state: address.state,
+ zip_code: address.zip
+ }
+
+ try {
+ const addr = axios.post({
+ url: `${this.lobUrl}/us_verifications`,
+ headers: this.headers(),
+ data: payload
+ })
+
+ return addr.data
+ } catch (err) {
+ throw new LobError(err.message)
+ }
+ }
+
+ // Args should be the payload returned by verifyAddress()
+ // See https://docs.lob.com/#tag/US-Verifications/operation/us_verification
+ // For some reason, the parameter names are different b/w endpoints --_--
+ async returnAddress(verifiedAddress) {
+ const payload = {
+ name: verifiedAddress.name,
+ address_line1: verifiedAddress.primary_line,
+ address_line2: verifiedAddress.secondary_line,
+ address_city: verifiedAddress.components.city,
+ address_state: verifiedAddress.components.state,
+ address_zip: verifiedAddress.components.zip_code
+ }
+
+ try {
+ const addr = axios.post({
+ url: `${this.lobUrl}/addresses`,
+ headers: this.headers(),
+ data: payload
+ })
+
+ return addr.data
+ } catch (err) {
+ throw new LobError(err.message)
+ }
+ }
+}
+
+module.exports = { Lob, LobError }
diff --git a/server/lib/sendgrid.js b/server/lib/sendgrid.js
new file mode 100644
index 000000000..f1ffd4e2f
--- /dev/null
+++ b/server/lib/sendgrid.js
@@ -0,0 +1,45 @@
+// Wrapper for Sendgrid API
+
+require('dotenv').config()
+const sgMail = require('@sendgrid/mail') // For sending email
+const sgClient = require('@sendgrid/client') // For other api endpoints
+
+class SendgridError extends Error {
+ constructor(message) {
+ super(message)
+ this.name = 'SendgridError'
+ }
+}
+
+class Sendgrid {
+ constructor() {
+ this.apiKey = process.env.SENDGRID_API_KEY
+ this.env = process.env.NODE_ENV
+
+ this.sgMail = sgMail
+ this.sgClient = sgClient
+ this.sgMail.setApiKey(this.apiKey)
+ this.sgClient.setApiKey(this.apiKey)
+ }
+
+ async template(id) {
+ const params = { method: 'GET', url: `/v3/templates/${id}` }
+
+ try {
+ const response = await this.sgClient.request(params)
+
+ console.log(response)
+ return response
+ } catch (err) {
+ throw new SendgridError(err.message)
+ }
+ }
+
+ async send(payload) {
+ if (this.env != 'production') {
+ return { response: 200, payload }
+ }
+ }
+}
+
+module.exports = { Sendgrid, SendgridError }
diff --git a/server/routes/api/checkout.js b/server/routes/api/checkout.js
index d0b91aaf3..4dd6c0276 100644
--- a/server/routes/api/checkout.js
+++ b/server/routes/api/checkout.js
@@ -6,9 +6,11 @@ const {
PaymentPresenter,
PaymentPresenterError
} = require('../../../shared/presenters/payment-presenter')
+const Handlebars = require('../../lib/handlebars')
const Constituent = require('../../db/models/constituent')
const Transaction = require('../../db/models/transaction')
const Letter = require('../../db/models/letter')
+const LetterTemplate = require('../../db/models/letter-template')
const router = express.Router()
@@ -20,11 +22,11 @@ class CheckoutError extends Error {
}
router.post('/create-checkout-session', async (req, res) => {
- const { donation, user, letter } = req.body
+ let { donation, user, letter, deliveryMethods } = req.body
+ console.dir(user)
+ console.dir(letter)
const origin = req.get('origin')
- console.log(`origin: ${origin}`)
-
try {
const presenter = new PaymentPresenter()
@@ -53,11 +55,31 @@ router.post('/create-checkout-session', async (req, res) => {
})
// Using a temporary mapping here also
- await Letter.query().insert({
- transactionId: transaction.id,
- constituentId: constituent.id,
- ...letter
- })
+ // Re-render the letter html, merging user data to be saved in case that's in the template.
+ letter.merge_variables = {
+ ...letter.merge_variables,
+ firstName: user.firstName,
+ lastName: user.lastName
+ }
+ const template = await LetterTemplate.query().findById(
+ letter.letter_template_id
+ )
+ const html = Handlebars.render(letter.merge_variables, template.html)
+
+ // Using a temporary mapping here also
+ for (const method of deliveryMethods) {
+ // Generate a uuid so letters are idempotent
+ letter.trackingNumber = uuidv4()
+ console.log(letter.trackingNumber)
+
+ await Letter.query().insert({
+ transactionId: transaction.id,
+ constituentId: constituent.id,
+ letterTemplate: html,
+ deliveryMethod: method,
+ ...letter
+ })
+ }
return res
.status(200)
@@ -97,12 +119,32 @@ router.post('/create-checkout-session', async (req, res) => {
paymentMethod: 'credit_card'
})
+ // Re-render the letter html, merging user data to be saved in case that's in the template.
+ letter.merge_variables = {
+ ...letter.merge_variables,
+ firstName: user.firstName,
+ lastName: user.lastName
+ }
+ const template = await LetterTemplate.query().findById(
+ letter.letter_template_id
+ )
+ const html = Handlebars.render(letter.merge_variables, template.html)
+
+
// Using a temporary mapping here also
- await Letter.query().insert({
- transactionId: transaction.id,
- constituentId: constituent.id,
- ...letter
- })
+ for (const method of deliveryMethods) {
+ // Generate a uuid so letters are idempotent
+ letter.trackingNumber = uuidv4()
+ console.log(letter.trackingNumber)
+
+ await Letter.query().insert({
+ transactionId: transaction.id,
+ constituentId: constituent.id,
+ letterTemplate: html,
+ deliveryMethod: method,
+ ...letter
+ })
+ }
return res
.status(200)
@@ -159,19 +201,23 @@ router.post('/process-transaction', async (req, res) => {
)
}
- const transaction = await Transaction.query().findOne({ stripe_transaction_id: paymentIntent })
+ const transaction = await Transaction.query().findOne({
+ stripe_transaction_id: paymentIntent
+ })
await transaction.$query().patch({ status: eventOutcome })
- const letter = await Letter.query().where({ transaction_id: transaction.id }).first()
+ const letter = await Letter.query()
+ .where({ transaction_id: transaction.id })
+ .first()
letter.trackingNumber = uuidv4()
const letterTemplate = JSON.parse(letter.letterTemplate)
-
+
const lobApiKey = process.env.LOB_API_KEY
const lobCredentials = btoa(`${lobApiKey}:`)
console.log(letter.mergeVariables)
const lobResponse = await axios.post(
- 'https://api.lob.com/v1/letters',
+ 'https://api.lob.com/v1/letters',
{
to: {
name: letter.addressee,
@@ -197,7 +243,7 @@ router.post('/process-transaction', async (req, res) => {
if (!lobResponse.statusCode === 200) throw new CheckoutError(lobResponse)
- await letter.$query().patch({ sent: true})
+ await letter.$query().patch({ sent: true })
return res.status(201).end()
} catch (error) {
diff --git a/server/routes/api/v1/letter-templates/index.js b/server/routes/api/v1/letter-templates/index.js
new file mode 100644
index 000000000..a41786ba3
--- /dev/null
+++ b/server/routes/api/v1/letter-templates/index.js
@@ -0,0 +1,54 @@
+// Routes for getting letter templates
+const express = require('express')
+const LetterTemplate = require('../../../../db/models/letter-template')
+const Handlebars = require('../../../../lib/handlebars')
+
+const router = express.Router()
+
+/**
+ * Retrieves a letterTemplate, given its as a query param id
+ */
+router.get('/:id', async (req, res) => {
+ const id = req.params.id
+
+ if (!id) return res.status(404).end()
+
+ try {
+ const letterTemplate = await LetterTemplate.query().findById(id)
+
+ if (!letterTemplate) {
+ return res.status(404).end()
+ }
+
+ return res.status(200).json({ letterTemplate }).end()
+ } catch (err) {
+ console.error(err)
+ return res.status(500).end()
+ }
+})
+
+/**
+ * @params mergeVariables - object
+ * @params id - number, string
+ * Renders a template
+ */
+router.post('/render', async (req, res) => {
+ const { mergeVariables, templateId } = req.body
+
+ try {
+ const template = await LetterTemplate.query().findById(templateId)
+
+ if (!template) {
+ return res.status(404).json({ error: 'Template id does not exist' })
+ }
+
+ const letter = Handlebars.render(mergeVariables, template.html)
+
+ return res.status(200).json({ letter })
+ } catch (err) {
+ console.error(err.message)
+ return res.status(500).end()
+ }
+})
+
+module.exports = router
diff --git a/server/routes/api/v1/v1.js b/server/routes/api/v1/v1.js
index a084330ab..7da5c6822 100644
--- a/server/routes/api/v1/v1.js
+++ b/server/routes/api/v1/v1.js
@@ -1,9 +1,11 @@
const express = require('express')
const campaigns = require('./campaigns') // If the routes file is named index.js, we can omit it when we do the import instead of writing './campaigns/index'.
+const letterTemplates = require('./letter-templates')
const v1Router = express.Router()
// Create the final piece of the url /campaigns
v1Router.use('/campaigns', campaigns)
+v1Router.use('/letter_templates', letterTemplates)
module.exports = v1Router
diff --git a/src/components/CampaignBlurb.vue b/src/components/CampaignBlurb.vue
index 71acad4b7..9e643c400 100644
--- a/src/components/CampaignBlurb.vue
+++ b/src/components/CampaignBlurb.vue
@@ -2,22 +2,25 @@
-
+
- Donate to the cause.
-
+ Select your delivery method
+ Please select the type of letter you want to send
+
+
+ {{ item.label }}
+
+
+
+ Donate to the cause.
Your voice is super important!
@@ -16,85 +36,75 @@
Your donation makes it possible to change our relationship with
representatives, from the comfort of your home or on the go.
+
+
+ 2
+
-
-
-
-
- If you'd like to make a donation, please do so
- here.
-
-
Donors should add a note saying its for {{ campaign.name }}.
-
-
-
+ 20
+
+
+
+ 50
+
+
+
+ 0
+
+
+
+ Custom Amount
+
+
+
+
+
-
- 2
-
-
-
- 20
-
-
-
- 50
-
-
-
- 0
-
-
-
- Custom Amount
-
-
-
-
-
- mdi-currency-usd
- {{ styledCustomDonation }}
-
-
+ mdi-currency-usd
+ {{ styledCustomDonation }}
+
- Send Letter
+
+ Send Letter
+
@@ -103,6 +113,8 @@
import axios from 'axios'
import { PaymentPresenter } from '../../shared/presenters/payment-presenter'
+const LETTER_DELIVERY_METHODS = [{ label: 'Email', type: 'email' }, {label: 'Physical Mail', type: 'snail_mail'}]
+
export default {
name: 'DonateMoney',
props: [],
@@ -111,12 +123,16 @@ export default {
donationAmount: 0,
customAmountSelected: false,
customDonationAmount: null,
+ deliveryMethods: [],
}
},
computed: {
// These are temporary structures until we can reorganize the frontend.
+ letterDeliveryMethods() {
+ return LETTER_DELIVERY_METHODS
+ },
noCostMailEnabled() {
- return Boolean(process.env.VUE_APP_NO_COST_MAIL)
+ return process.env.VUE_APP_NO_COST_MAIL == 'true'
},
campaign() {
return this.$store.state.campaign
@@ -148,11 +164,12 @@ export default {
}
},
letter() {
- const rep = this.$store.state.selectedRep
- const letterId = this.$store.state.letterId
- const letterVersion = this.$store.state.letterVersion
- const returnAddressId = this.$store.state.lobReturnAddressId
- const mergeVariables = this.$store.state.mergeVariables
+ const rep = this.$store.state.selectedRep
+ const letterId = this.$store.state.letterId
+ const letterVersion = this.$store.state.letterVersion
+ const returnAddressId = this.$store.state.lobReturnAddressId
+ const mergeVariables = this.$store.state.mergeVariables
+ const letterTemplateId = this.$store.state.campaign.letterTemplateId
return {
letterTemplate: letterId,
@@ -163,8 +180,10 @@ export default {
state: rep.address_state,
city: rep.address_city,
zip: rep.address_zip,
+ email: rep.email,
returnAddress: returnAddressId,
- merge_variables: mergeVariables
+ merge_variables: mergeVariables,
+ letter_template_id: letterTemplateId,
}
},
styledCustomDonation() {
@@ -175,6 +194,16 @@ export default {
}
},
methods: {
+ setDeliveryMethods(method) {
+ console.log('logging delivery methods', method)
+ // If item in array, delete on button click, else add to array.
+ const idx = this.deliveryMethods.indexOf(method)
+ if (idx > -1 ) {
+ return this.deliveryMethods.splice(idx, 1)
+ }
+
+ this.deliveryMethods.push(method)
+ },
unsetCustomAmountSelection() {
this.customAmountSelected = false
},
@@ -187,19 +216,26 @@ export default {
donation = presenter.formatPaymentAmount(donation)
- this.createCheckoutSession(donation, this.user, this.letter)
+ if (this.deliveryMethods.length == 0) {
+ alert('Please pick at least one delivery method!')
+ }
+
+ if (donation === 0 && !this.noCostMailEnabled) {
+ alert('Please pick a donation amount greater than $0.')
+ }
+
+ this.createCheckoutSession(donation, this.user, this.letter, this.deliveryMethods)
},
- createCheckoutSession(donation, user, letter) {
- console.log(donation, user, letter)
- axios.post('/api/checkout/create-checkout-session', { donation, user, letter })
- // TODO: Investigate whether we need to dump user state still. With the new stripe webhook it may not be necessary.
+ createCheckoutSession(donation, user, letter, deliveryMethods) {
+ console.log(donation, user, letter, deliveryMethods)
+ axios.post('/api/checkout/create-checkout-session', { donation, user, letter, deliveryMethods })
.then((response) => {
- // Dump state to local storage before redirect
+ // Redirect to Stripe
this.$store.dispatch(
'dumpStateToLocalStorage',
response.data.sessionId
)
- // Redirect to Stripe
+
location.href = response.data.url
})
.catch((error) => {
diff --git a/src/components/HakamweLetterLoad.vue b/src/components/HakamweLetterLoad.vue
index 33cad6b94..a204ea50f 100644
--- a/src/components/HakamweLetterLoad.vue
+++ b/src/components/HakamweLetterLoad.vue
@@ -12,7 +12,7 @@
{{ selectedRep.address_city }}, {{ selectedRep.address_state }},
{{ selectedRep.address_zip }}
-
+
{{ user.name }}
{{ user.line1 }}
@@ -29,27 +29,90 @@
Hello,
- am an Arizona constituent writing in to discuss my grave concerns regarding the ongoing drilling activities in Sandy Valley, northern Arizona.
- 1. Threats to Hualapai Cultural Heritage and Religious Freedoms
- The mining exploration, authorized by the Bureau of Land Management (BLM), directly impacts Ha’Kamwe’ (Cofer Hot Spring), a sacred site that holds profound spiritual significance for the Hualapai Tribe and other Indigenous communities.
+
+ am an Arizona constituent writing in to discuss my grave concerns
+ regarding the ongoing drilling activities in Sandy Valley, northern
+ Arizona.
+
+
+ 1. Threats to Hualapai Cultural Heritage and Religious
+ Freedoms
+
+
+ The mining exploration, authorized by the Bureau of Land Management
+ (BLM), directly impacts Ha’Kamwe’ (Cofer Hot Spring), a sacred site
+ that holds profound spiritual significance for the Hualapai Tribe
+ and other Indigenous communities.
+
- - Religious Freedom Restoration Act (42 U.S.C. § 2000bb et seq.): The ongoing drilling undermines how the Hualapai and other tribes have used the spring for centuries for healing, prayer, and rites of passage, including childbirth and coming-of-age ceremonies for young women. Ha’Kamwe’ is integral to the spiritual practices of the Hualapai people.
- - National Historic Preservation Act (54 U.S.C. § 300101 et seq.): Ha’Kamwe’ is part of the ancient Salt Song Trail and features prominently in tribal songs and stories about the Hualapai people’s history and connection to their land. BLM’s approval of exploratory drilling without fully considering the cultural importance of Ha’Kamwe’ disregards this statute and disrespects the rights of the Hualapai Tribe.
+ -
+ Religious Freedom Restoration Act (42 U.S.C. § 2000bb et
+ seq.):
+ The ongoing drilling undermines how the Hualapai and other tribes
+ have used the spring for centuries for healing, prayer, and rites
+ of passage, including childbirth and coming-of-age ceremonies for
+ young women. Ha’Kamwe’ is integral to the spiritual practices of
+ the Hualapai people.
+
+ -
+ National Historic Preservation Act (54 U.S.C. § 300101 et
+ seq.):
+ Ha’Kamwe’ is part of the ancient Salt Song Trail and features
+ prominently in tribal songs and stories about the Hualapai
+ people’s history and connection to their land. BLM’s approval of
+ exploratory drilling without fully considering the cultural
+ importance of Ha’Kamwe’ disregards this statute and disrespects
+ the rights of the Hualapai Tribe.
+
-
- 2. Environmental Violations and the Rights of Nature
- The drilling project threatens to cause irreversible damage to the local ecosystem, including the depletion of water sources that sustain Ha’Kamwe’. The proposed 131 exploration holes, reaching depths of up to 360 feet, could alter the temperature and flow of the aquifer feeding the spring, endangering the surrounding plants and wildlife.
+
+
+ 2. Environmental Violations and the Rights of Nature
+
+
+ The drilling project threatens to cause irreversible damage to the
+ local ecosystem, including the depletion of water sources that
+ sustain Ha’Kamwe’. The proposed 131 exploration holes, reaching
+ depths of up to 360 feet, could alter the temperature and flow of
+ the aquifer feeding the spring, endangering the surrounding plants
+ and wildlife.
+
- - Clean Water Act (33 U.S.C. § 1251 et seq.) The drilling activities risk contaminating the aquifer, which could lead to ecological degradation, violating federal regulations designed to protect water quality.
- - Rights of Nature Doctrine: The concept of the Rights of Nature recognizes natural entities, such as springs, as rights-bearing entities with the right to exist, thrive, and regenerate. The drilling endangers Ha’Kamwe’, infringing on its right to exist and maintain its natural state.
+ -
+ Clean Water Act (33 U.S.C. § 1251 et seq.) The
+ drilling activities risk contaminating the aquifer, which could
+ lead to ecological degradation, violating federal regulations
+ designed to protect water quality.
+
+ -
+ Rights of Nature Doctrine: The concept of the
+ Rights of Nature recognizes natural entities, such as springs, as
+ rights-bearing entities with the right to exist, thrive, and
+ regenerate. The drilling endangers Ha’Kamwe’, infringing on its
+ right to exist and maintain its natural state.
+
-
+
Call for Collaboration and Respect:
- We request a precautionary pause as an injunction on all drilling activities in Sandy Valley until a thorough assessment of the environmental and cultural impacts can be conducted, and meaningful consultation with the Hualapai Nation can take place.
- We await your prompt response and look forward to scheduling a meeting at your earliest convenience.
- Sincerely,
+ We request a precautionary pause as an injunction on all drilling
+ activities in Sandy Valley until a thorough assessment of the
+ environmental and cultural impacts can be conducted, and meaningful
+ consultation with the Hualapai Nation can take place.
+
+
+ We await your prompt response and look forward to scheduling a
+ meeting at your earliest convenience.
+ Sincerely,
{{ user.name }}
diff --git a/src/components/LetterLoad.vue b/src/components/LetterLoad.vue
index 1ee80de63..fcc4c6733 100644
--- a/src/components/LetterLoad.vue
+++ b/src/components/LetterLoad.vue
@@ -2,6 +2,17 @@
+
+
+
+
+
{{ currentDate }}
@@ -13,45 +24,10 @@
{{ selectedRep.address_zip }}
- {{ user.name }}
-
- {{ user.line1 }}
-
- {{ user.line2 }}
-
- {{ formattedCityState }}
+
-
- Dear {{ selectedRep.name }},
-
-
-
-
-
-
-
-
-
-
-
{{ user.name }}
clicked
@@ -74,6 +50,11 @@
diff --git a/src/components/SearchReps.vue b/src/components/SearchReps.vue
index c463d0a85..4c778a3ed 100644
--- a/src/components/SearchReps.vue
+++ b/src/components/SearchReps.vue
@@ -162,11 +162,15 @@
-
+
+
+
![infographic for campaign]()
+
![Vue logo]()
{
+ this.$store.dispatch('loadLetterTemplate')
+ })
this.$store.commit('setGenericValue', {
key: 'letterId',
@@ -252,15 +260,7 @@ export default {
clearSelectedRep() {
this.$store.commit('setGenericValue', { key: 'selectedRep', value: {} })
},
- async loadLetterWorkflow() {
- const letter = await axios.get(`/api/lob/templates/${this.letterId}`)
-
- const latest = letter.data.versions[letter.data.versions.length - 1]
-
- this.$store.commit('setGenericValue', { key: 'letterId', value: latest })
-
- this.letterBody = latest.html
-
+ loadLetterWorkflow() {
this.listVisible = true
},
CheckInputContent: function () {
@@ -325,4 +325,8 @@ export default {
.search-reps-button {
margin: 5px 10px;
}
+
+.infographic-img {
+ max-width: 100%;
+}
diff --git a/src/components/SignName.vue b/src/components/SignName.vue
index 56266ca6c..f9dc32b39 100644
--- a/src/components/SignName.vue
+++ b/src/components/SignName.vue
@@ -196,6 +196,8 @@ export default {
key: 'userData',
data: this.form
})
+
+ this.$emit('address-validated', true)
})
.catch(function (error) {
console.log(error)
diff --git a/src/components/TakeAction.vue b/src/components/TakeAction.vue
index a2f89952e..172bfc7cc 100644
--- a/src/components/TakeAction.vue
+++ b/src/components/TakeAction.vue
@@ -28,35 +28,14 @@
-
-
-
-
-
-
+
Next
@@ -99,11 +78,12 @@
-
+