From cc6cc52ba5fc88e4688747f270683fbf579b6b12 Mon Sep 17 00:00:00 2001 From: swve Date: Fri, 19 May 2023 09:33:54 +0000 Subject: [PATCH] feat: use Next.js on demand revalidation --- front/app/api/revalidate/route.ts | 19 +++++++++++++++++++ .../[orgslug]/(withmenu)/courses/courses.tsx | 6 ++++-- .../[orgslug]/(withmenu)/courses/page.tsx | 4 ++-- front/app/orgs/[orgslug]/(withmenu)/page.tsx | 4 ++-- .../Modals/Course/Create/CreateCourse.tsx | 7 ++++--- front/services/config/config.ts | 2 +- front/services/utils/ts/requests.ts | 7 +++++++ 7 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 front/app/api/revalidate/route.ts diff --git a/front/app/api/revalidate/route.ts b/front/app/api/revalidate/route.ts new file mode 100644 index 00000000..c3d0aa71 --- /dev/null +++ b/front/app/api/revalidate/route.ts @@ -0,0 +1,19 @@ +import { NextRequest, NextResponse } from "next/server"; +import { revalidateTag } from "next/cache"; + +export async function GET(request: NextRequest) { + const tag: any = request.nextUrl.searchParams.get("tag"); + revalidateTag(tag); + + return NextResponse.json( + { revalidated: true, now: Date.now() }, + { + status: 200, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type, Authorization", + }, + } + ); +} diff --git a/front/app/orgs/[orgslug]/(withmenu)/courses/courses.tsx b/front/app/orgs/[orgslug]/(withmenu)/courses/courses.tsx index a37f2010..079cc54a 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/courses/courses.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/courses/courses.tsx @@ -10,6 +10,7 @@ import Link from 'next/link'; import React from 'react' import Image from 'next/image'; import { AuthContext } from '@components/Security/AuthProvider'; +import { revalidateTags } from '@services/utils/ts/requests'; interface CourseProps { orgslug: string; @@ -28,13 +29,14 @@ function Courses(props: CourseProps) { async function deleteCourses(course_id: any) { await deleteCourseFromBackend(course_id); + revalidateTags(['courses']); } async function closeNewCourseModal() { setNewCourseModal(false); } - + return ( @@ -103,7 +105,7 @@ const AdminEditsArea = (props: any) => { // this is amazingly terrible code, but gotta release that MVP // TODO: fix this - + function isAuthorized() { const org_id = props.course.org_id; const org_roles = auth.userInfo.user_object.orgs; diff --git a/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx b/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx index d0099bba..aa66b09a 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx @@ -11,11 +11,11 @@ export const metadata: Metadata = { const CoursesPage = async (params: any) => { const orgslug = params.params.orgslug; - const courses = await getOrgCourses(orgslug, { revalidate: 360 }); + const courses = await getOrgCourses(orgslug, { revalidate: 360, tags: ['courses'] }); return (
- +
); }; diff --git a/front/app/orgs/[orgslug]/(withmenu)/page.tsx b/front/app/orgs/[orgslug]/(withmenu)/page.tsx index 23c6ac4d..ee1d2d7f 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/page.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/page.tsx @@ -22,7 +22,7 @@ export async function generateMetadata( ): Promise { // Get Org context information - const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800 }); + const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] }); return { title: org.name + " — Home", description: org.description, @@ -31,7 +31,7 @@ export async function generateMetadata( const OrgHomePage = async (params: any) => { const orgslug = params.params.orgslug; - const courses = await getOrgCourses(orgslug, { revalidate: 360 }); + const courses = await getOrgCourses(orgslug, { revalidate: 360 , tags: ['courses'] }); const collections = await getOrgCollections(); // function to remove "course_" from the course_id diff --git a/front/components/Modals/Course/Create/CreateCourse.tsx b/front/components/Modals/Course/Create/CreateCourse.tsx index f182bb38..96a7456e 100644 --- a/front/components/Modals/Course/Create/CreateCourse.tsx +++ b/front/components/Modals/Course/Create/CreateCourse.tsx @@ -1,4 +1,4 @@ -import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, Input, Textarea } from '@components/UI/Form/Form' +import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, Input, Textarea } from '@components/UI/Form/Form' import * as Form from '@radix-ui/react-form' import { getAPIUrl, getUriWithOrg } from '@services/config/config'; import { FormMessage } from "@radix-ui/react-form"; @@ -7,6 +7,7 @@ import { getOrganizationContextInfo } from '@services/organizations/orgs'; import React, { useState } from 'react' import { BarLoader } from 'react-spinners' import { mutate } from 'swr'; +import { revalidateTags } from '@services/utils/ts/requests'; function CreateCourseModal({ closeModal, orgslug }: any) { const [isSubmitting, setIsSubmitting] = useState(false); @@ -19,7 +20,7 @@ function CreateCourseModal({ closeModal, orgslug }: any) { const getOrgMetadata = async () => { - const org = await getOrganizationContextInfo(orgslug); + const org = await getOrganizationContextInfo(orgslug, { revalidate: 360, tags: ['organizations'] }); setOrgId(org.org_id); } @@ -40,7 +41,7 @@ function CreateCourseModal({ closeModal, orgslug }: any) { e.preventDefault(); setIsSubmitting(true); let status = await createNewCourse(orgId, { name, description }, thumbnail); - mutate(`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`); + revalidateTags(['courses']); setIsSubmitting(false); if (status.org_id == orgId) { diff --git a/front/services/config/config.ts b/front/services/config/config.ts index fd674bf0..4fca83ce 100644 --- a/front/services/config/config.ts +++ b/front/services/config/config.ts @@ -1,4 +1,4 @@ -const LEARNHOUSE_HTTP_PROTOCOL = process.env.NEXT_PUBLIC_LEARNHOUSE_HTTPS === "true" ? "https://" : "http://"; +export const LEARNHOUSE_HTTP_PROTOCOL = process.env.NEXT_PUBLIC_LEARNHOUSE_HTTPS === "true" ? "https://" : "http://"; const LEARNHOUSE_API_URL = `${process.env.NEXT_PUBLIC_LEARNHOUSE_API_URL}`; const LEARNHOUSE_BACKEND_URL = `${process.env.NEXT_PUBLIC_LEARNHOUSE_BACKEND_URL}`; export const LEARNHOUSE_DOMAIN = process.env.NEXT_PUBLIC_LEARNHOUSE_DOMAIN; diff --git a/front/services/utils/ts/requests.ts b/front/services/utils/ts/requests.ts index 2d636be4..07ba1142 100644 --- a/front/services/utils/ts/requests.ts +++ b/front/services/utils/ts/requests.ts @@ -1,5 +1,6 @@ import { AppRouterInstance } from "next/dist/shared/lib/app-router-context"; import { denyAccessToUser } from "../react/middlewares/views"; +import { LEARNHOUSE_DOMAIN, LEARNHOUSE_HTTP_PROTOCOL } from "@services/config/config"; export const RequestBody = (method: string, data: any, next: any) => { let HeadersConfig = new Headers({ "Content-Type": "application/json" }); @@ -69,3 +70,9 @@ export const errorHandling = (res: any) => { } return res.json(); }; + +export const revalidateTags = (tags: string[]) => { + tags.forEach((tag) => { + fetch(`${LEARNHOUSE_HTTP_PROTOCOL}${LEARNHOUSE_DOMAIN}/api/revalidate?tag=${tag}`); + }); +};