Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add backend config to Gateway service #197

Merged
merged 13 commits into from
Oct 27, 2023
Merged
2 changes: 1 addition & 1 deletion deployment/gke-prod-manifests/frontend-ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ metadata:
spec:
defaultBackend:
service:
name: frontend-service
name: frontend
port:
number: 3000
13 changes: 13 additions & 0 deletions deployment/gke-prod-manifests/gateway-backend-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: gateway-backend-config
spec:
healthCheck:
timeoutSec: 3
type: HTTP
requestPath: /healthz
port: 8080
customRequestHeaders:
headers:
- "Access-Control-Allow-Origin: https://www.codeparty.org"
4 changes: 4 additions & 0 deletions deployment/gke-prod-manifests/gateway-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ spec:
- containerPort: 4003
hostPort: 4003
protocol: TCP
# Needed for health check
- containerPort: 8080
hostPort: 8080
protocol: TCP
resources:
# You must specify requests for CPU to autoscale
# based on CPU utilization
Expand Down
2 changes: 1 addition & 1 deletion deployment/gke-prod-manifests/gateway-http-ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ metadata:
spec:
defaultBackend:
service:
name: frontend-service
name: gateway
port:
number: 4000
6 changes: 6 additions & 0 deletions deployment/gke-prod-manifests/gateway-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ metadata:
io.kompose.service: gateway
name: gateway
namespace: default
annotations:
cloud.google.com/backend-config: '{"default": "gateway-backend-config"}'
spec:
ports:
- name: "4000"
Expand All @@ -16,6 +18,10 @@ spec:
- name: "4003"
port: 4003
targetPort: 4003
# Needed for health check
- name: "8080"
port: 8080
targetPort: 8080
selector:
io.kompose.service: gateway
status:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ metadata:
spec:
defaultBackend:
service:
name: gateway-service
name: gateway
port:
number: 4003
2 changes: 1 addition & 1 deletion deployment/gke-prod-manifests/gateway-wsmatch-ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ metadata:
spec:
defaultBackend:
service:
name: gateway-service
name: gateway
port:
number: 4002
1 change: 0 additions & 1 deletion deployment/gke-prod-manifests/gke-managed-cert.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ metadata:
name: gke-managed-cert
spec:
domains:
- codeparty.org
- www.codeparty.org
- api.codeparty.org
- wsmatch.codeparty.org
Expand Down
89 changes: 78 additions & 11 deletions frontend/src/components/questions/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function DataTable<TData, TValue>({
columns,
isEditable = false,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = useState<SortingState>([]);
const [sorting, setSorting] = useState<SortingState>([{"id": "title", "desc": false}]);
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
const { user: currentUser, authIsReady } = useContext(AuthContext);
Expand All @@ -60,19 +60,37 @@ export function DataTable<TData, TValue>({

const [{pageIndex, pageSize}, setPagination] = useState<PaginationState>({ pageIndex: 0, pageSize: 10 });

const [searchTitle, setSearchTitle] = useState("");
const [filteredDifficulty, setFilteredDifficulty] = useState({"easy": true, "medium": true, "hard": true});
const [localFilteredDifficulty, setLocalFilteredDifficulty] = useState({"easy": true, "medium": true, "hard": true});

const fetchDataOptions = {
pageIndex,
pageSize,
searchTitle,
filteredDifficulty,
sorting,
uid: currentUser?.uid ?? null,
};

const dataQuery = useQuery({
queryKey: ["questions", fetchDataOptions],
queryFn: async ({queryKey}) => {
const {uid, pageIndex, pageSize} = queryKey[1] as {uid: string | null, pageIndex: number, pageSize: number};
const {uid, pageIndex, pageSize, searchTitle, filteredDifficulty, sorting} = queryKey[1] as typeof fetchDataOptions;
if (!uid) throw new Error("Unauthenticated user");
setLoading(true);
const response = await fetchQuestions(currentUser, pageIndex, pageSize, (isEditable ? {"author": uid}: {}));
let conditions: any = {"difficulty": Object.keys(filteredDifficulty).filter((key) => (filteredDifficulty as any)[key])};
if (isEditable) {
conditions = {...conditions, "author": uid};
}
if (searchTitle) {
conditions = {...conditions, "searchTitle": searchTitle};
}
if (sorting.length > 0) {
const sortObj = sorting.map(sortState => ({[sortState.id]: sortState.desc ? -1 : 1})).reduce((acc, curr) => ({...acc, ...curr}), {});
conditions = {...conditions, "sort": sortObj};
}
const response = await fetchQuestions(currentUser, pageIndex, pageSize, conditions);
setLoading(false)
if (pageIndex > maxPage.current.maxFetchedPage) {
maxPage.current.maxFetchedPage = pageIndex;
Expand Down Expand Up @@ -110,22 +128,71 @@ export function DataTable<TData, TValue>({
columnVisibility,
pagination
},
manualSorting: true,
manualPagination: true,
onPaginationChange: setPagination,
pageCount: maxPage.current.isMax ? maxPage.current.maxFetchedPage + 1 : -1,
});



return (
<div>
<div className="flex items-center py-4">
<Input
placeholder="Search questions..."
value={(table.getColumn("title")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn("title")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
<div className="flex items-left w-full space-x-2">
<Input
placeholder="Search questions..."
defaultValue={searchTitle}
onKeyDown={e => {
if (e.key === 'Enter') {
setSearchTitle((e.target as EventTarget & HTMLInputElement).value);
// reset pagination
setPagination({pageIndex: 0, pageSize: 10});
maxPage.current = {maxFetchedPage: -1, isMax: false};
}
}}
className="max-w-sm"
/>
<DropdownMenu onOpenChange={open => {
if (!open) {
if (JSON.stringify(localFilteredDifficulty) !== JSON.stringify(filteredDifficulty)) {
setFilteredDifficulty(localFilteredDifficulty);
// reset pagination
setPagination({pageIndex: 0, pageSize: 10});
maxPage.current = {maxFetchedPage: -1, isMax: false};
}
}
}}>
<DropdownMenuTrigger asChild>
<Button variant="secondary" size="sm" className="ml-auto">
Filter by difficulty
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{["easy", "medium", "hard"]
.map((difficulty) => {
return (
<DropdownMenuCheckboxItem
key={difficulty}
className="capitalize"
checked={(localFilteredDifficulty as any)[difficulty]}
onCheckedChange={(value) =>
setLocalFilteredDifficulty(prevValue => {
const newValue = {...prevValue};
(newValue as any)[difficulty] = !!value;
return newValue;
})
}
onSelect={e => e.preventDefault()}
>
{difficulty}
</DropdownMenuCheckboxItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
</div>

<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="secondary" size="sm" className="ml-auto">
Expand Down