diff --git a/apps/api/migrations/versions/eb10d15465b3_org_scripts.py b/apps/api/migrations/versions/eb10d15465b3_org_scripts.py new file mode 100644 index 00000000..ab222cd6 --- /dev/null +++ b/apps/api/migrations/versions/eb10d15465b3_org_scripts.py @@ -0,0 +1,31 @@ +"""Org Scripts + +Revision ID: eb10d15465b3 +Revises: a5afa69dd917 +Create Date: 2025-06-08 18:12:18.853988 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa # noqa: F401 +import sqlmodel # noqa: F401 + + +# revision identifiers, used by Alembic. +revision: str = 'eb10d15465b3' +down_revision: Union[str, None] = 'a5afa69dd917' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('organization', sa.Column('scripts', sa.JSON(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('organization', 'scripts') + # ### end Alembic commands ### diff --git a/apps/api/src/db/organizations.py b/apps/api/src/db/organizations.py index 81dbfea8..f8fd9ec9 100644 --- a/apps/api/src/db/organizations.py +++ b/apps/api/src/db/organizations.py @@ -12,6 +12,7 @@ class OrganizationBase(SQLModel): about: Optional[str] socials: Optional[dict] = Field(default={}, sa_column=Column(JSON)) links: Optional[dict] = Field(default={}, sa_column=Column(JSON)) + scripts: Optional[dict] = Field(default={}, sa_column=Column(JSON)) logo_image: Optional[str] thumbnail_image: Optional[str] previews: Optional[dict] = Field(default={}, sa_column=Column(JSON)) @@ -38,6 +39,7 @@ class OrganizationUpdate(SQLModel): about: Optional[str] = None socials: Optional[dict] = None links: Optional[dict] = None + scripts: Optional[dict] = None logo_image: Optional[str] = None thumbnail_image: Optional[str] = None previews: Optional[dict] = None diff --git a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx index 6ac8785e..85030599 100644 --- a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx +++ b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx @@ -24,7 +24,7 @@ export async function generateMetadata(props: MetadataProps): Promise // Get Org context information const course_meta = await getCourseMetadata( params.courseid, - { revalidate: 30, tags: ['courses'] }, + { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null ) @@ -41,7 +41,7 @@ const EditActivity = async (params: any) => { const courseid = (await params.params).courseid const courseInfo = await getCourseMetadata( courseid, - { revalidate: 30, tags: ['courses'] }, + { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null ) const activity = await getActivityWithAuthHeader( diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx index 9418630d..5e5b459c 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx @@ -21,7 +21,7 @@ type Session = { async function fetchCourseMetadata(courseuuid: string, access_token: string | null | undefined) { return await getCourseMetadata( courseuuid, - { revalidate: 30, tags: ['courses'] }, + { revalidate: 0, tags: ['courses'] }, access_token || null ) } diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx index e5d06129..df4fbccd 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx @@ -24,7 +24,7 @@ export async function generateMetadata(props: MetadataProps): Promise }) const course_meta = await getCourseMetadata( params.courseuuid, - { revalidate: 30, tags: ['courses'] }, + { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null ) @@ -72,7 +72,7 @@ const CoursePage = async (params: any) => { // Fetch course metadata once const course_meta = await getCourseMetadata( params.params.courseuuid, - { revalidate: 30, tags: ['courses'] }, + { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null ) diff --git a/apps/web/app/orgs/[orgslug]/dash/org/settings/[subpage]/page.tsx b/apps/web/app/orgs/[orgslug]/dash/org/settings/[subpage]/page.tsx index fc83647c..bf5fde69 100644 --- a/apps/web/app/orgs/[orgslug]/dash/org/settings/[subpage]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/dash/org/settings/[subpage]/page.tsx @@ -1,7 +1,7 @@ 'use client' import BreadCrumbs from '@components/Dashboard/Misc/BreadCrumbs' import { getUriWithOrg } from '@services/config/config' -import { ImageIcon, Info, LockIcon, SearchIcon, TextIcon, LucideIcon, Share2Icon, LayoutDashboardIcon } from 'lucide-react' +import { ImageIcon, Info, LockIcon, SearchIcon, TextIcon, LucideIcon, Share2Icon, LayoutDashboardIcon, CodeIcon } from 'lucide-react' import Link from 'next/link' import React, { useEffect, use } from 'react'; import { motion } from 'framer-motion' @@ -9,6 +9,7 @@ import OrgEditGeneral from '@components/Dashboard/Pages/Org/OrgEditGeneral/OrgEd import OrgEditImages from '@components/Dashboard/Pages/Org/OrgEditImages/OrgEditImages' import OrgEditSocials from '@components/Dashboard/Pages/Org/OrgEditSocials/OrgEditSocials' import OrgEditLanding from '@components/Dashboard/Pages/Org/OrgEditLanding/OrgEditLanding' +import OrgEditOther from '@components/Dashboard/Pages/Org/OrgEditOther/OrgEditOther' export type OrgParams = { subpage: string @@ -26,6 +27,7 @@ const SETTING_TABS: TabItem[] = [ { id: 'landing', label: 'Landing Page', icon: LayoutDashboardIcon }, { id: 'previews', label: 'Images & Previews', icon: ImageIcon }, { id: 'socials', label: 'Socials', icon: Share2Icon }, + { id: 'other', label: 'Other', icon: CodeIcon }, ] function TabLink({ tab, isActive, orgslug }: { @@ -67,6 +69,9 @@ function OrgPage(props: { params: Promise }) { } else if (params.subpage == 'landing') { setH1Label('Landing Page') setH2Label('Customize your organization landing page') + } else if (params.subpage == 'other') { + setH1Label('Other') + setH2Label('Manage additional organization settings') } } @@ -111,6 +116,7 @@ function OrgPage(props: { params: Promise }) { {params.subpage == 'previews' ? : ''} {params.subpage == 'socials' ? : ''} {params.subpage == 'landing' ? : ''} + {params.subpage == 'other' ? : ''} ) diff --git a/apps/web/app/orgs/[orgslug]/layout.tsx b/apps/web/app/orgs/[orgslug]/layout.tsx index 2a6e4014..1c1c4cf6 100644 --- a/apps/web/app/orgs/[orgslug]/layout.tsx +++ b/apps/web/app/orgs/[orgslug]/layout.tsx @@ -5,6 +5,7 @@ import NextTopLoader from 'nextjs-toploader'; import Toast from '@components/Objects/StyledElements/Toast/Toast' import '@styles/globals.css' import Onboarding from '@components/Objects/Onboarding/Onboarding'; +import Footer from "@components/Footer/Footer"; export default function RootLayout( props: { @@ -25,6 +26,7 @@ export default function RootLayout( {children} +