Skip to content

Commit e7cf57f

Browse files
authored
Merge pull request #1916 from codeforboston/main
Deploy to PROD 8/17/25
2 parents 9d600ad + 8a51f70 commit e7cf57f

File tree

70 files changed

+2667
-2106
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2667
-2106
lines changed

.all-contributorsrc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,24 @@
722722
"contributions": [
723723
"code"
724724
]
725+
},
726+
{
727+
"login": "yasminekarni",
728+
"name": "yasminekarni",
729+
"avatar_url": "https://avatars.githubusercontent.com/u/47721405?v=4",
730+
"profile": "https://github.com/yasminekarni",
731+
"contributions": [
732+
"code"
733+
]
734+
},
735+
{
736+
"login": "chaoyi09",
737+
"name": "Chaoyi Jiang",
738+
"avatar_url": "https://avatars.githubusercontent.com/u/117859839?v=4",
739+
"profile": "http://chaoyijiang.com",
740+
"contributions": [
741+
"code"
742+
]
725743
}
726744
],
727745
"commitType": "docs"

.github/actions/setup-repo/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ inputs:
44
node-version:
55
description: "Version used by actions/setup-node"
66
required: true
7-
default: "18"
7+
default: "20"
88
yarn-version:
99
description: "Version of Yarn used to install dependencies"
1010
required: true

.github/workflows/deploy-backend-dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: Setup Build Environment
2323
uses: ./.github/actions/setup-repo
2424
- name: Build and Deploy to Firebase
25-
uses: w9jds/firebase-action@v13.0.2
25+
uses: w9jds/firebase-action@v13.18.0
2626
with:
2727
args: deploy --force --only firestore,functions:maple,storage
2828
env:

.github/workflows/deploy-prod.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup Build Environment
1717
uses: ./.github/actions/setup-repo
1818
- name: Build and Deploy to Firebase
19-
uses: w9jds/firebase-action@v13.0.2
19+
uses: w9jds/firebase-action@v13.18.0
2020
with:
2121
args: deploy --force --only firestore,functions:maple,storage
2222
env:

README.md

Lines changed: 12 additions & 8 deletions
Large diffs are not rendered by default.

components/CommentModal/Attachment.tsx

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ChangeEventHandler, useCallback, useEffect, useState } from "react"
44
import { Button, Col, Form, InputGroup, Row, Spinner } from "../bootstrap"
55
import { AttachmentInfo, UseDraftTestimonyAttachment } from "../db"
66
import { External } from "../links"
7+
import { useTranslation } from "next-i18next"
78

89
export function Attachment({
910
attachment,
@@ -65,11 +66,10 @@ const Label = ({
6566
}: {
6667
attachment: UseDraftTestimonyAttachment
6768
}) => {
69+
const { t } = useTranslation("attachment")
6870
return (
6971
<Form.Label>
70-
<span className="me-1">
71-
(Optional) Provide your testimony as a file attachment
72-
</span>
72+
<span className="me-1">{t("provide_testimony_as_file")}</span>
7373
{status === "loading" && <Spinner animation="border" size="sm" />}
7474
{status === "error" && (
7575
<FontAwesomeIcon icon={faExclamationTriangle} className="text-danger" />
@@ -85,13 +85,10 @@ export const AttachmentLink = ({
8585
attachment: AttachmentInfo
8686
className?: string
8787
}) => {
88-
const linkLabel = [
89-
"Attached",
90-
name ?? "Testimony",
91-
size ? formatSize(size) : null
92-
]
93-
.filter(Boolean)
94-
.join(" - ")
88+
const { t } = useTranslation("attachment")
89+
const linkLabelParts = [t("attached"), name ?? t("testimony")]
90+
if (size) linkLabelParts.push(formatSize(size))
91+
const linkLabel = linkLabelParts.join(" - ")
9592
return (
9693
<External className={className} href={url}>
9794
{linkLabel}
@@ -106,13 +103,10 @@ const Attached = ({
106103
attachment: UseDraftTestimonyAttachment
107104
confirmRemove: boolean
108105
}) => {
106+
const { t } = useTranslation("attachment")
109107
const { url, name, size, id, remove, status } = attachment
110108
const onClick = () => {
111-
if (
112-
!confirmRemove ||
113-
confirm("Are you sure you want to remove your attachment?")
114-
)
115-
remove()
109+
if (!confirmRemove || confirm(t("confirm_remove"))) remove()
116110
}
117111
return (
118112
<Row className="align-items-center">
@@ -128,7 +122,7 @@ const Attached = ({
128122
onClick={onClick}
129123
disabled={status === "loading"}
130124
>
131-
Remove
125+
{t("remove")}
132126
</Button>
133127
</Col>
134128
</Row>
@@ -140,19 +134,18 @@ const StatusMessage = ({
140134
}: {
141135
attachment: UseDraftTestimonyAttachment
142136
}) => {
137+
const { t } = useTranslation("attachment")
143138
if (status === "error") {
144139
let message: string
145140
if (error?.code === "storage/unauthorized") {
146-
message = "Invalid file. Please upload PDF's less than 10 MB"
141+
message = t("error.storage_unauthorized")
147142
} else {
148-
message = "Something went wrong. Please try again."
143+
message = t("error.generic")
149144
}
150145

151146
return <Form.Text className="text-danger">{message}</Form.Text>
152147
} else if (status === "ok" && !id) {
153-
return (
154-
<Form.Text>Files must be PDF documents and less than 10 MB.</Form.Text>
155-
)
148+
return <Form.Text>{t("file_requirements")}</Form.Text>
156149
} else {
157150
return null
158151
}

components/EditProfilePage/EditProfilePage.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
} from "./StyledEditProfileComponents"
2626
import { TestimoniesTab } from "./TestimoniesTab"
2727
import { useFlags } from "components/featureFlags"
28-
import LoginPage from "components/Login/login"
28+
import LoginPage from "components/Login/Login"
2929
import { PendingUpgradeBanner } from "components/PendingUpgradeBanner"
3030

3131
const tabTitle = ["about-you", "testimonies", "following"] as const
@@ -137,7 +137,9 @@ export function EditProfileForm({
137137
content: (
138138
<TestimoniesTab
139139
publishedTestimonies={publishedTestimonies.items.result ?? []}
140-
draftTestimonies={draftTestimonies.result ?? []}
140+
publishedTestimoniesPagination={publishedTestimonies.pagination}
141+
draftTestimonies={draftTestimonies.items.result ?? []}
142+
draftTestimoniesPagination={draftTestimonies.pagination}
141143
/>
142144
)
143145
},

components/EditProfilePage/FollowingTab.tsx

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { collection, getDocs, query, where } from "firebase/firestore"
2-
import { getFunctions } from "firebase/functions"
32
import { useTranslation } from "next-i18next"
43
import { useCallback, useEffect, useMemo, useState } from "react"
54
import { useAuth } from "../auth"
@@ -10,6 +9,7 @@ import UnfollowItem, { UnfollowModalConfig } from "./UnfollowModal"
109
import { FollowedItem } from "./FollowingTabComponents"
1110
import { BillElement, UserElement } from "./FollowingTabComponents"
1211
import { deleteItem } from "components/shared/FollowingQueries"
12+
import { PaginationButtons } from "../table"
1313

1414
export function FollowingTab({ className }: { className?: string }) {
1515
const { user } = useAuth()
@@ -29,6 +29,10 @@ export function FollowingTab({ className }: { className?: string }) {
2929
const [billsFollowing, setBillsFollowing] = useState<BillElement[]>([])
3030
const [usersFollowing, setUsersFollowing] = useState<UserElement[]>([])
3131

32+
const [currentBillsPage, setCurrentBillsPage] = useState(1)
33+
const [currentUsersPage, setCurrentUsersPage] = useState(1)
34+
const itemsPerPage = 10
35+
3236
const billsFollowingQuery = useCallback(async () => {
3337
if (!subscriptionRef) return // handle the case where subscriptionRef is null
3438
const billList: BillElement[] = []
@@ -44,12 +48,12 @@ export function FollowingTab({ className }: { className?: string }) {
4448
})
4549
if (billsFollowing.length === 0 && billList.length != 0) {
4650
setBillsFollowing(billList)
47-
}
51+
} // this limits the code from falling into an infinite loop
4852
}, [subscriptionRef, uid, billsFollowing])
4953

5054
useEffect(() => {
5155
uid ? billsFollowingQuery() : null
52-
})
56+
}, [uid, billsFollowingQuery])
5357

5458
const orgsFollowingQuery = useCallback(async () => {
5559
if (!subscriptionRef) return // handle the case where subscriptionRef is null
@@ -67,7 +71,7 @@ export function FollowingTab({ className }: { className?: string }) {
6771

6872
if (usersFollowing.length === 0 && usersList.length != 0) {
6973
setUsersFollowing(usersList)
70-
}
74+
} // this limits the code from falling into an infinite loop
7175
}, [subscriptionRef, uid, usersFollowing])
7276

7377
const fetchFollowedItems = useCallback(async () => {
@@ -104,6 +108,21 @@ export function FollowingTab({ className }: { className?: string }) {
104108
setUnfollow(null)
105109
}
106110

111+
const getPaginatedBills = () => {
112+
const startIndex = (currentBillsPage - 1) * itemsPerPage
113+
const endIndex = startIndex + itemsPerPage
114+
return billsFollowing.slice(startIndex, endIndex)
115+
}
116+
117+
const getPaginatedUsers = () => {
118+
const startIndex = (currentUsersPage - 1) * itemsPerPage
119+
const endIndex = startIndex + itemsPerPage
120+
return usersFollowing.slice(startIndex, endIndex)
121+
}
122+
123+
const totalBillsPages = Math.ceil(billsFollowing.length / itemsPerPage)
124+
const totalUsersPages = Math.ceil(usersFollowing.length / itemsPerPage)
125+
107126
const { t } = useTranslation("editProfile")
108127

109128
return (
@@ -112,7 +131,7 @@ export function FollowingTab({ className }: { className?: string }) {
112131
<div className={`mx-4 mt-3 d-flex flex-column gap-3`}>
113132
<Stack>
114133
<h2>{t("follow.bills")}</h2>
115-
{billsFollowing.map((element: BillElement, index: number) => (
134+
{getPaginatedBills().map((element: BillElement, index: number) => (
116135
<FollowedItem
117136
key={index}
118137
index={index}
@@ -121,14 +140,26 @@ export function FollowingTab({ className }: { className?: string }) {
121140
type={"bill"}
122141
/>
123142
))}
143+
{billsFollowing.length > 0 && (
144+
<PaginationButtons
145+
pagination={{
146+
currentPage: currentBillsPage,
147+
hasNextPage: currentBillsPage < totalBillsPages,
148+
hasPreviousPage: currentBillsPage > 1,
149+
nextPage: () => setCurrentBillsPage(prev => prev + 1),
150+
previousPage: () => setCurrentBillsPage(prev => prev - 1),
151+
itemsPerPage
152+
}}
153+
/>
154+
)}
124155
</Stack>
125156
</div>
126157
</TitledSectionCard>
127158
<TitledSectionCard className={`${className}`}>
128159
<div className={`mx-4 mt-3 d-flex flex-column gap-3`}>
129160
<Stack>
130161
<h2 className="pb-3">{t("follow.orgs")}</h2>
131-
{usersFollowing.map((element: UserElement, index: number) => (
162+
{getPaginatedUsers().map((element: UserElement, index: number) => (
132163
<FollowedItem
133164
key={index}
134165
index={index}
@@ -137,6 +168,18 @@ export function FollowingTab({ className }: { className?: string }) {
137168
type={"org"}
138169
/>
139170
))}
171+
{usersFollowing.length > 0 && (
172+
<PaginationButtons
173+
pagination={{
174+
currentPage: currentUsersPage,
175+
hasNextPage: currentUsersPage < totalUsersPages,
176+
hasPreviousPage: currentUsersPage > 1,
177+
nextPage: () => setCurrentUsersPage(prev => prev + 1),
178+
previousPage: () => setCurrentUsersPage(prev => prev - 1),
179+
itemsPerPage
180+
}}
181+
/>
182+
)}
140183
</Stack>
141184
</div>
142185
</TitledSectionCard>

components/EditProfilePage/TestimoniesTab.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,21 @@ import { TitledSectionCard } from "../shared"
44
import { TestimonyItem } from "components/TestimonyCard/TestimonyItem"
55
import { SortTestimonyDropDown } from "components/TestimonyCard/SortTestimonyDropDown"
66
import { TestimonyFAQ } from "./TestimonyFAQ"
7-
import { Testimony } from "../db"
7+
import { Testimony, DraftTestimony, Pagination } from "../db"
88
import { useTranslation } from "next-i18next"
9+
import { PaginationButtons } from "../table"
910

1011
export const TestimoniesTab = ({
1112
publishedTestimonies,
13+
publishedTestimoniesPagination,
1214
draftTestimonies,
15+
draftTestimoniesPagination,
1316
className
1417
}: {
1518
publishedTestimonies: Testimony[]
16-
draftTestimonies: Testimony[]
19+
publishedTestimoniesPagination?: Pagination
20+
draftTestimonies: DraftTestimony[]
21+
draftTestimoniesPagination?: Pagination
1722
className?: string
1823
}) => {
1924
const [orderBy, setOrderBy] = useState<string>()
@@ -58,17 +63,23 @@ export const TestimoniesTab = ({
5863
onProfilePage={true}
5964
/>
6065
))}
66+
{publishedTestimoniesPagination && (
67+
<PaginationButtons pagination={publishedTestimoniesPagination} />
68+
)}
6169
</TitledSectionCard>
6270
<TitledSectionCard className="mt-3 mb-4">
6371
<h2>{t("testimonies.draft")}</h2>
6472
{draftTestimonies.map(t => (
6573
<TestimonyItem
66-
key={t.authorUid + t.billId + t.publishedAt}
67-
testimony={t}
74+
key={t.billId + t.court + t.position}
75+
testimony={t as any}
6876
isUser={true}
6977
onProfilePage={true}
7078
/>
7179
))}
80+
{draftTestimoniesPagination && (
81+
<PaginationButtons pagination={draftTestimoniesPagination} />
82+
)}
7283
</TitledSectionCard>
7384
</Col>
7485
<Col>

components/HotBillCard/HotBillCard.tsx

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)