Merge pull request #266 from learnhouse/feat/enable-umami

Enable umami
This commit is contained in:
Badr B 2024-06-10 10:23:46 +01:00 committed by GitHub
commit d13468b17f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 42 additions and 28 deletions

View file

@ -1,5 +1,5 @@
# Base image # Base image
FROM python:3.12-slim-bookworm as base FROM python:3.12.3-slim-bookworm as base
# Install Nginx, curl, and build-essential # Install Nginx, curl, and build-essential
RUN apt update && apt install -y nginx curl build-essential \ RUN apt update && apt install -y nginx curl build-essential \

View file

@ -1,5 +1,5 @@
# #
FROM python:3.12 FROM python:3.12.3
# poetry # poetry
RUN pip install poetry RUN pip install poetry

View file

@ -9,7 +9,7 @@ import { getResponseMetadata } from '@services/utils/ts/requests'
import CredentialsProvider from 'next-auth/providers/credentials' import CredentialsProvider from 'next-auth/providers/credentials'
import GoogleProvider from 'next-auth/providers/google' import GoogleProvider from 'next-auth/providers/google'
const isDevEnv = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? true : false export const isDevEnv = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? true : false
export const nextAuthOptions = { export const nextAuthOptions = {
debug: true, debug: true,

View file

@ -4,6 +4,8 @@ import StyledComponentsRegistry from '../components/Utils/libs/styled-registry'
import { motion } from 'framer-motion' import { motion } from 'framer-motion'
import { SessionProvider } from 'next-auth/react' import { SessionProvider } from 'next-auth/react'
import LHSessionProvider from '@components/Contexts/LHSessionContext' import LHSessionProvider from '@components/Contexts/LHSessionContext'
import { isDevEnv } from './auth/options'
import Script from 'next/script'
export default function RootLayout({ export default function RootLayout({
children, children,
@ -19,6 +21,7 @@ export default function RootLayout({
<html className="" lang="en"> <html className="" lang="en">
<head /> <head />
<body> <body>
{isDevEnv ? '' : <Script data-website-id="a1af6d7a-9286-4a1f-8385-ddad2a29fcbb" src="/umami/script.js" />}
<SessionProvider> <SessionProvider>
<LHSessionProvider> <LHSessionProvider>
<StyledComponentsRegistry> <StyledComponentsRegistry>

View file

@ -13,7 +13,7 @@ import useSWR from 'swr'
function Trail(params: any) { function Trail(params: any) {
let orgslug = params.orgslug let orgslug = params.orgslug
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const org = useOrg() as any const org = useOrg() as any
const orgID = org?.id const orgID = org?.id
const { data: trail, error: error } = useSWR( const { data: trail, error: error } = useSWR(

View file

@ -12,8 +12,7 @@ export function CourseProvider({ children, courseuuid }: any) {
const session = useLHSession() as any; const session = useLHSession() as any;
const access_token = session?.data?.tokens?.access_token; const access_token = session?.data?.tokens?.access_token;
const { data: courseStructureData, error } = useSWR( const { data: courseStructureData, error } = useSWR(`${getAPIUrl()}courses/${courseuuid}/meta`,
access_token ? `${getAPIUrl()}courses/${courseuuid}/meta` : null,
url => swrFetcher(url, access_token) url => swrFetcher(url, access_token)
); );

View file

@ -15,7 +15,7 @@ import { updateUserAvatar } from '@services/users/users'
function UserEditGeneral() { function UserEditGeneral() {
const session = useLHSession() as any; const session = useLHSession() as any;
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [localAvatar, setLocalAvatar] = React.useState(null) as any const [localAvatar, setLocalAvatar] = React.useState(null) as any
const [isLoading, setIsLoading] = React.useState(false) as any const [isLoading, setIsLoading] = React.useState(false) as any
const [error, setError] = React.useState() as any const [error, setError] = React.useState() as any

View file

@ -5,7 +5,7 @@ import React, { useEffect } from 'react'
function UserEditPassword() { function UserEditPassword() {
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const updatePasswordUI = async (values: any) => { const updatePasswordUI = async (values: any) => {
let user_id = session.data.user.id let user_id = session.data.user.id

View file

@ -21,7 +21,7 @@ import { useLHSession } from '@components/Contexts/LHSessionContext'
function OrgAccess() { function OrgAccess() {
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const { data: invites } = useSWR( const { data: invites } = useSWR(
org ? `${getAPIUrl()}orgs/${org?.id}/invites` : null, org ? `${getAPIUrl()}orgs/${org?.id}/invites` : null,
(url) => swrFetcher(url, access_token) (url) => swrFetcher(url, access_token)

View file

@ -16,7 +16,7 @@ import useSWR, { mutate } from 'swr'
function OrgUserGroups() { function OrgUserGroups() {
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [userGroupManagementModal, setUserGroupManagementModal] = React.useState(false) const [userGroupManagementModal, setUserGroupManagementModal] = React.useState(false)
const [createUserGroupModal, setCreateUserGroupModal] = React.useState(false) const [createUserGroupModal, setCreateUserGroupModal] = React.useState(false)
const [selectedUserGroup, setSelectedUserGroup] = React.useState(null) as any const [selectedUserGroup, setSelectedUserGroup] = React.useState(null) as any

View file

@ -16,7 +16,7 @@ import useSWR, { mutate } from 'swr'
function OrgUsers() { function OrgUsers() {
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const { data: orgUsers } = useSWR( const { data: orgUsers } = useSWR(
org ? `${getAPIUrl()}orgs/${org?.id}/users` : null, org ? `${getAPIUrl()}orgs/${org?.id}/users` : null,
(url) => swrFetcher(url, access_token) (url) => swrFetcher(url, access_token)

View file

@ -14,7 +14,7 @@ import useSWR, { mutate } from 'swr'
function OrgUsersAdd() { function OrgUsersAdd() {
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [isLoading, setIsLoading] = React.useState(false) const [isLoading, setIsLoading] = React.useState(false)
const [invitedUsers, setInvitedUsers] = React.useState(''); const [invitedUsers, setInvitedUsers] = React.useState('');
const [selectedInviteCode, setSelectedInviteCode] = React.useState(''); const [selectedInviteCode, setSelectedInviteCode] = React.useState('');

View file

@ -75,7 +75,7 @@ type ActivityChatMessageBoxProps = {
function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) { function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
const dispatchAIChatBot = useAIChatBotDispatch() as any const dispatchAIChatBot = useAIChatBotDispatch() as any

View file

@ -94,7 +94,7 @@ function AIActionButton(props: {
activity: any activity: any
}) { }) {
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const dispatchAIChatBot = useAIChatBotDispatch() as any const dispatchAIChatBot = useAIChatBotDispatch() as any
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes const aiChatBotState = useAIChatBot() as AIChatBotStateTypes

View file

@ -143,7 +143,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => {
const dispatchAIEditor = useAIEditorDispatch() as any const dispatchAIEditor = useAIEditorDispatch() as any
const aiEditorState = useAIEditor() as AIEditorStateTypes const aiEditorState = useAIEditor() as AIEditorStateTypes
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => { const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
await dispatchAIEditor({ await dispatchAIEditor({

View file

@ -25,7 +25,7 @@ interface EditorWrapperProps {
function EditorWrapper(props: EditorWrapperProps): JSX.Element { function EditorWrapper(props: EditorWrapperProps): JSX.Element {
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
// Define provider in the state // Define provider in the state
const [provider, setProvider] = React.useState<HocuspocusProvider | null>(null); const [provider, setProvider] = React.useState<HocuspocusProvider | null>(null);
const [thisPageColor, setThisPageColor] = useState(randomColor({ luminosity: 'light' }) as string) const [thisPageColor, setThisPageColor] = useState(randomColor({ luminosity: 'light' }) as string)

View file

@ -16,7 +16,7 @@ function ImageBlockComponent(props: any) {
const course = useCourse() as any const course = useCourse() as any
const editorState = useEditorProvider() as any const editorState = useEditorProvider() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const isEditable = editorState.isEditable const isEditable = editorState.isEditable
const [image, setImage] = React.useState(null) const [image, setImage] = React.useState(null)

View file

@ -14,7 +14,7 @@ function PDFBlockComponent(props: any) {
const org = useOrg() as any const org = useOrg() as any
const course = useCourse() as any const course = useCourse() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [pdf, setPDF] = React.useState(null) const [pdf, setPDF] = React.useState(null)
const [isLoading, setIsLoading] = React.useState(false) const [isLoading, setIsLoading] = React.useState(false)
const [blockObject, setblockObject] = React.useState( const [blockObject, setblockObject] = React.useState(

View file

@ -17,7 +17,7 @@ function VideoBlockComponents(props: any) {
const isEditable = editorState.isEditable const isEditable = editorState.isEditable
const [video, setVideo] = React.useState(null) const [video, setVideo] = React.useState(null)
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [isLoading, setIsLoading] = React.useState(false) const [isLoading, setIsLoading] = React.useState(false)
const [blockObject, setblockObject] = React.useState( const [blockObject, setblockObject] = React.useState(
props.node.attrs.blockObject props.node.attrs.blockObject

View file

@ -19,7 +19,7 @@ function LinkToUserGroup(props: LinkToUserGroupProps) {
const course = useCourse() as any const course = useCourse() as any
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const courseStructure = course.courseStructure const courseStructure = course.courseStructure
const { data: usergroups } = useSWR( const { data: usergroups } = useSWR(

View file

@ -15,7 +15,7 @@ type OrgInviteCodeGenerateProps = {
function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) { function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [usergroup_id, setUsergroup_id] = React.useState(0); const [usergroup_id, setUsergroup_id] = React.useState(0);
const { data: usergroups } = useSWR( const { data: usergroups } = useSWR(
org ? `${getAPIUrl()}usergroups/org/${org.id}` : null, org ? `${getAPIUrl()}usergroups/org/${org.id}` : null,

View file

@ -23,7 +23,7 @@ type AddUserGroupProps = {
function AddUserGroup(props: AddUserGroupProps) { function AddUserGroup(props: AddUserGroupProps) {
const org = useOrg() as any; const org = useOrg() as any;
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [userGroupName, setUserGroupName] = React.useState('') const [userGroupName, setUserGroupName] = React.useState('')
const [userGroupDescription, setUserGroupDescription] = React.useState('') const [userGroupDescription, setUserGroupDescription] = React.useState('')
const [isSubmitting, setIsSubmitting] = React.useState(false) const [isSubmitting, setIsSubmitting] = React.useState(false)

View file

@ -16,7 +16,7 @@ type ManageUsersProps = {
function ManageUsers(props: ManageUsersProps) { function ManageUsers(props: ManageUsersProps) {
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const { data: OrgUsers } = useSWR( const { data: OrgUsers } = useSWR(
org ? `${getAPIUrl()}orgs/${org.id}/users` : null, org ? `${getAPIUrl()}orgs/${org.id}/users` : null,
swrFetcher swrFetcher

View file

@ -24,7 +24,7 @@ interface Props {
function RolesUpdate(props: Props) { function RolesUpdate(props: Props) {
const org = useOrg() as any const org = useOrg() as any
const session = useLHSession() as any const session = useLHSession() as any
const access_token = session.data.tokens.access_token; const access_token = session?.data?.tokens?.access_token;
const [isSubmitting, setIsSubmitting] = React.useState(false) const [isSubmitting, setIsSubmitting] = React.useState(false)
const [assignedRole, setAssignedRole] = React.useState( const [assignedRole, setAssignedRole] = React.useState(
props.alreadyAssignedRole props.alreadyAssignedRole

View file

@ -16,10 +16,11 @@ export const config = {
* 1. /api routes * 1. /api routes
* 2. /_next (Next.js internals) * 2. /_next (Next.js internals)
* 3. /fonts (inside /public) * 3. /fonts (inside /public)
* 4. Umami Analytics
* 4. /examples (inside /public) * 4. /examples (inside /public)
* 5. all root files inside /public (e.g. /favicon.ico) * 5. all root files inside /public (e.g. /favicon.ico)
*/ */
'/((?!api|_next|fonts|examples|[\\w-]+\\.\\w+).*)', '/((?!api|_next|fonts|umami|examples|[\\w-]+\\.\\w+).*)',
], ],
} }

View file

@ -1,8 +1,19 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
async rewrites() {
return [
{
source: '/umami/script.js',
destination: `https://eu.umami.is/script.js`,
},
{
source: '/umami/api/send',
destination: `https://eu.umami.is/api/send`,
},
]
},
reactStrictMode: false, reactStrictMode: false,
output: 'standalone', output: 'standalone',
} }
module.exports = nextConfig module.exports = nextConfig