diff --git a/apps/web/package.json b/apps/web/package.json index c55c95e5d..d0a57f33a 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,96 +1,96 @@ { - "name": "@courselit/web", - "version": "0.57.12", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint", - "prettier": "prettier --write **/*.ts" - }, - "dependencies": { - "@courselit/common-logic": "workspace:^", - "@courselit/common-models": "workspace:^", - "@courselit/common-widgets": "workspace:^", - "@courselit/components-library": "workspace:^", - "@courselit/icons": "workspace:^", - "@courselit/state-management": "workspace:^", - "@courselit/utils": "workspace:^", - "@hookform/resolvers": "^3.9.1", - "@radix-ui/react-alert-dialog": "^1.1.2", - "@radix-ui/react-avatar": "^1.1.3", - "@radix-ui/react-checkbox": "^1.1.4", - "@radix-ui/react-collapsible": "^1.1.3", - "@radix-ui/react-compose-refs": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-dropdown-menu": "^2.1.6", - "@radix-ui/react-label": "^2.1.2", - "@radix-ui/react-popover": "^1.1.6", - "@radix-ui/react-radio-group": "^1.2.3", - "@radix-ui/react-scroll-area": "^1.2.3", - "@radix-ui/react-select": "^2.1.6", - "@radix-ui/react-separator": "^1.1.2", - "@radix-ui/react-slot": "^1.1.2", - "@radix-ui/react-switch": "^1.1.3", - "@radix-ui/react-tabs": "^1.1.3", - "@radix-ui/react-toast": "^1.2.6", - "@radix-ui/react-tooltip": "^1.1.8", - "@radix-ui/react-visually-hidden": "^1.1.0", - "@stripe/stripe-js": "^5.4.0", - "@types/base-64": "^1.0.0", - "archiver": "^5.3.1", - "aws4": "^1.13.2", - "base-64": "^1.0.0", - "chart.js": "^4.4.7", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "cookie": "^0.4.2", - "date-fns": "^4.1.0", - "graphql": "^16.10.0", - "graphql-type-json": "^0.3.2", - "lodash.debounce": "^4.0.8", - "lucide-react": "^0.475.0", - "mongodb": "^6.15.0", - "mongoose": "^8.13.1", - "next": "^14.2.4", - "next-auth": "5.0.0-beta.19", - "nodemailer": "^6.7.2", - "pug": "^3.0.2", - "razorpay": "^2.9.4", - "react": "^18.2.0", - "react-chartjs-2": "^5.3.0", - "react-csv": "^2.2.2", - "react-dom": "^18.2.0", - "react-hook-form": "^7.54.1", - "react-redux": "^8.1.2", - "recharts": "^2.15.1", - "remirror": "^3.0.1", - "sharp": "^0.33.2", - "slugify": "^1.6.5", - "stripe": "^17.5.0", - "tailwind-merge": "^2.5.4", - "tailwindcss-animate": "^1.0.7", - "zod": "^3.24.1" - }, - "devDependencies": { - "@types/bcryptjs": "^2.4.2", - "@types/cookie": "^0.4.1", - "@types/mongodb": "^4.0.7", - "@types/node": "17.0.21", - "@types/nodemailer": "^6.4.4", - "@types/pug": "^2.0.6", - "@types/react": "18.2.31", - "@types/react-redux": "^7.1.23", - "@types/redux-thunk": "^2.1.0", - "eslint": "8.48.0", - "eslint-config-next": "^14.0.4", - "eslint-config-prettier": "^9.0.0", - "postcss": "^8.4.27", - "prettier": "^3.0.2", - "tailwind-config": "workspace:^", - "tailwindcss": "^3.4.1", - "tsconfig": "workspace:^", - "typescript": "^5.6.2" - } + "name": "@courselit/web", + "version": "0.57.12", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "prettier": "prettier --write **/*.ts" + }, + "dependencies": { + "@courselit/common-logic": "workspace:^", + "@courselit/common-models": "workspace:^", + "@courselit/common-widgets": "workspace:^", + "@courselit/components-library": "workspace:^", + "@courselit/icons": "workspace:^", + "@courselit/state-management": "workspace:^", + "@courselit/utils": "workspace:^", + "@hookform/resolvers": "^3.9.1", + "@radix-ui/react-alert-dialog": "^1.1.2", + "@radix-ui/react-avatar": "^1.1.3", + "@radix-ui/react-checkbox": "^1.1.4", + "@radix-ui/react-collapsible": "^1.1.3", + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-radio-group": "^1.2.3", + "@radix-ui/react-scroll-area": "^1.2.3", + "@radix-ui/react-select": "^2.1.6", + "@radix-ui/react-separator": "^1.1.2", + "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-switch": "^1.1.3", + "@radix-ui/react-tabs": "^1.1.3", + "@radix-ui/react-toast": "^1.2.6", + "@radix-ui/react-tooltip": "^1.1.8", + "@radix-ui/react-visually-hidden": "^1.1.0", + "@stripe/stripe-js": "^5.4.0", + "@types/base-64": "^1.0.0", + "archiver": "^5.3.1", + "aws4": "^1.13.2", + "base-64": "^1.0.0", + "chart.js": "^4.4.7", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "cookie": "^0.4.2", + "date-fns": "^4.1.0", + "graphql": "^16.10.0", + "graphql-type-json": "^0.3.2", + "lodash.debounce": "^4.0.8", + "lucide-react": "^0.475.0", + "mongodb": "^6.15.0", + "mongoose": "^8.13.1", + "next": "^14.2.4", + "next-auth": "5.0.0-beta.19", + "nodemailer": "^6.7.2", + "pug": "^3.0.2", + "razorpay": "^2.9.4", + "react": "^18.2.0", + "react-chartjs-2": "^5.3.0", + "react-csv": "^2.2.2", + "react-dom": "^18.2.0", + "react-hook-form": "^7.54.1", + "react-redux": "^8.1.2", + "recharts": "^2.15.1", + "remirror": "^3.0.1", + "sharp": "^0.33.2", + "slugify": "^1.6.5", + "stripe": "^17.5.0", + "tailwind-merge": "^2.5.4", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.24.1" + }, + "devDependencies": { + "@types/bcryptjs": "^2.4.2", + "@types/cookie": "^0.4.1", + "@types/mongodb": "^4.0.7", + "@types/node": "17.0.21", + "@types/nodemailer": "^6.4.4", + "@types/pug": "^2.0.6", + "@types/react": "18.2.31", + "@types/react-redux": "^7.1.23", + "@types/redux-thunk": "^2.1.0", + "eslint": "8.48.0", + "eslint-config-next": "^14.0.4", + "eslint-config-prettier": "^9.0.0", + "postcss": "^8.4.27", + "prettier": "^3.0.2", + "tailwind-config": "workspace:^", + "tailwindcss": "^3.4.1", + "tsconfig": "workspace:^", + "typescript": "^5.6.2" + } } diff --git a/apps/web/ui-config/widgets.tsx b/apps/web/ui-config/widgets.tsx index 7ee4e32cb..5151ab4fb 100644 --- a/apps/web/ui-config/widgets.tsx +++ b/apps/web/ui-config/widgets.tsx @@ -12,6 +12,8 @@ import { FAQ, Pricing, Media, + Embed, + Marquee, } from "@courselit/common-widgets"; function loadWidgets(): Record { @@ -27,6 +29,8 @@ function loadWidgets(): Record { widgets[FAQ.metadata.name] = FAQ; widgets[Pricing.metadata.name] = Pricing; widgets[Media.metadata.name] = Media; + widgets[Embed.metadata.name] = Embed; + widgets[Marquee.metadata.name] = Marquee; widgets[Footer.metadata.name] = Object.assign({}, Footer, { shared: true }); widgets[Header.metadata.name] = Object.assign({}, Header, { shared: true }); widgets[EmailForm.metadata.name] = Object.assign({}, EmailForm, { diff --git a/packages/common-widgets/src/embed/admin-widget.tsx b/packages/common-widgets/src/embed/admin-widget.tsx new file mode 100644 index 000000000..6416cdcdc --- /dev/null +++ b/packages/common-widgets/src/embed/admin-widget.tsx @@ -0,0 +1,161 @@ +import React, { ChangeEvent, useEffect, useState } from "react"; +import Settings from "./settings"; +import { + horizontalPadding as defaultHorizontalPadding, + verticalPadding as defaultVerticalPadding, + height as defaultHeight, +} from "./defaults"; +import { + CssIdField, + AdminWidgetPanel, + ColorSelector, + ContentPaddingSelector, + Form, + FormField, + Select, + Textarea, + AlertTitle, + AlertDescription, + Alert, +} from "@courselit/components-library"; +import { AlertCircle, Lightbulb } from "lucide-react"; + +export default function AdminWidget({ + settings, + onChange, +}: { + settings: Settings; + onChange: (...args: any[]) => void; +}) { + const [backgroundColor, setBackgroundColor] = useState( + settings.backgroundColor, + ); + const [url, setUrl] = useState(settings.url); + const [script, setScript] = useState(settings.script); + const [aspectRatio, setAspectRatio] = useState(settings.aspectRatio); + const [height, setHeight] = useState(settings.height || defaultHeight); + const [horizontalPadding, setHorizontalPadding] = useState( + settings.horizontalPadding || defaultHorizontalPadding, + ); + const [verticalPadding, setVerticalPadding] = useState( + settings.verticalPadding || defaultVerticalPadding, + ); + const [cssId, setCssId] = useState(settings.cssId); + + useEffect(() => { + onChange({ + backgroundColor, + url, + script, + aspectRatio, + height, + horizontalPadding, + verticalPadding, + cssId, + }); + }, [ + backgroundColor, + url, + script, + aspectRatio, + height, + horizontalPadding, + verticalPadding, + cssId, + ]); + + return ( +
+ + + + Beware + + + + Embedding external content may have security implications. + Only embed content from trusted sources. + + + +
+ ) => + setUrl(e.target.value) + } + /> +
+
+ + OR + +
+
+
+ +