mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
Merge pull request #75 from learnhouse/swve/eng-29-fix-chapters-black-dots-css-issue
fix chapters black dots css issue
This commit is contained in:
commit
be57196fb7
10 changed files with 82 additions and 49 deletions
|
|
@ -103,6 +103,9 @@ def get_learnhouse_config() -> LearnHouseConfig:
|
||||||
'database_config', {}).get('mongodb_connection_string')
|
'database_config', {}).get('mongodb_connection_string')
|
||||||
|
|
||||||
# Sentry config
|
# Sentry config
|
||||||
|
# check if the sentry config is provided in the YAML file
|
||||||
|
sentry_config_verif = yaml_config.get('hosting_config', {}).get('sentry_config') or env_sentry_dsn or env_sentry_environment or env_sentry_release or None
|
||||||
|
|
||||||
sentry_dsn = env_sentry_dsn or yaml_config.get(
|
sentry_dsn = env_sentry_dsn or yaml_config.get(
|
||||||
'hosting_config', {}).get('sentry_config', {}).get('dsn')
|
'hosting_config', {}).get('sentry_config', {}).get('dsn')
|
||||||
sentry_environment = env_sentry_environment or yaml_config.get(
|
sentry_environment = env_sentry_environment or yaml_config.get(
|
||||||
|
|
@ -110,11 +113,16 @@ def get_learnhouse_config() -> LearnHouseConfig:
|
||||||
sentry_release = env_sentry_release or yaml_config.get(
|
sentry_release = env_sentry_release or yaml_config.get(
|
||||||
'hosting_config', {}).get('sentry_config', {}).get('release')
|
'hosting_config', {}).get('sentry_config', {}).get('release')
|
||||||
|
|
||||||
sentry_config = SentryConfig(
|
if sentry_config_verif:
|
||||||
dsn=sentry_dsn,
|
sentry_config = SentryConfig(
|
||||||
environment=sentry_environment,
|
dsn=sentry_dsn,
|
||||||
release=sentry_release
|
environment=sentry_environment,
|
||||||
)
|
release=sentry_release
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sentry_config = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Create HostingConfig and DatabaseConfig objects
|
# Create HostingConfig and DatabaseConfig objects
|
||||||
hosting_config = HostingConfig(
|
hosting_config = HostingConfig(
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,6 @@ hosting_config:
|
||||||
ssl: true
|
ssl: true
|
||||||
use_default_org: false
|
use_default_org: false
|
||||||
default_org: learnhouse
|
default_org: learnhouse
|
||||||
sentry_config:
|
|
||||||
dsn: "https://1a6aa22656224851af492aae5d4155a1@o4505007882436608.ingest.sentry.io/4505007884599296"
|
|
||||||
environment: dev
|
|
||||||
release: "0.1.0"
|
|
||||||
allowed_origins:
|
allowed_origins:
|
||||||
- http://localhost:3000
|
- http://localhost:3000
|
||||||
- http://localhost:3001
|
- http://localhost:3001
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import React from "react";
|
||||||
import { Title } from "@components/UI/Elements/Styles/Title";
|
import { Title } from "@components/UI/Elements/Styles/Title";
|
||||||
import { createCollection } from "@services/courses/collections";
|
import { createCollection } from "@services/courses/collections";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { getAPIUrl } from "@services/config/config";
|
import { getAPIUrl, getUriWithOrg } from "@services/config/config";
|
||||||
import { swrFetcher } from "@services/utils/ts/requests";
|
import { swrFetcher } from "@services/utils/ts/requests";
|
||||||
import { getOrganizationContextInfo } from "@services/organizations/orgs";
|
import { getOrganizationContextInfo } from "@services/organizations/orgs";
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ function NewCollection(params : any) {
|
||||||
org_id: org.org_id,
|
org_id: org.org_id,
|
||||||
};
|
};
|
||||||
await createCollection(collection);
|
await createCollection(collection);
|
||||||
router.push("/org/" + orgslug + "/collections");
|
router.push(getUriWithOrg(orgslug, "/collections"));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,14 @@ import React, { useMemo } from "react";
|
||||||
import { getActivity } from "@services/courses/activities";
|
import { getActivity } from "@services/courses/activities";
|
||||||
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
||||||
import Canva from "@components/Pages/Activities/DynamicCanva/DynamicCanva";
|
import Canva from "@components/Pages/Activities/DynamicCanva/DynamicCanva";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getCourse } from "@services/courses/courses";
|
import { getCourse } from "@services/courses/courses";
|
||||||
import VideoActivity from "@components/Pages/Activities/Video/Video";
|
import VideoActivity from "@components/Pages/Activities/Video/Video";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { Check } from "lucide-react";
|
import { Check } from "lucide-react";
|
||||||
import { swrFetcher } from "@services/utils/ts/requests";
|
import { swrFetcher } from "@services/utils/ts/requests";
|
||||||
import { markActivityAsComplete } from "@services/courses/activity";
|
import { markActivityAsComplete } from "@services/courses/activity";
|
||||||
|
import ToolTip from "@components/UI/Tooltip/Tooltip";
|
||||||
|
|
||||||
function ActivityPage(params: any) {
|
function ActivityPage(params: any) {
|
||||||
const activityid = params.params.activityid;
|
const activityid = params.params.activityid;
|
||||||
|
|
@ -37,7 +38,7 @@ function ActivityPage(params: any) {
|
||||||
<ActivityLayout>
|
<ActivityLayout>
|
||||||
<ActivityTopWrapper>
|
<ActivityTopWrapper>
|
||||||
<ActivityThumbnail>
|
<ActivityThumbnail>
|
||||||
<Link href={getUriWithOrg(orgslug,"") +`/course/${courseid}`}>
|
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}`}>
|
||||||
<img src={`${getBackendUrl()}content/uploads/img/${course.course.thumbnail}`} alt="" />
|
<img src={`${getBackendUrl()}content/uploads/img/${course.course.thumbnail}`} alt="" />
|
||||||
</Link>
|
</Link>
|
||||||
</ActivityThumbnail>
|
</ActivityThumbnail>
|
||||||
|
|
@ -53,11 +54,14 @@ function ActivityPage(params: any) {
|
||||||
<div style={{ display: "flex", flexDirection: "row" }} key={chapter.chapter_id}>
|
<div style={{ display: "flex", flexDirection: "row" }} key={chapter.chapter_id}>
|
||||||
{chapter.activities.map((activity: any) => {
|
{chapter.activities.map((activity: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<ToolTip sideOffset={-5} slateBlack content={activity.name} key={activity.id}>
|
||||||
<Link href={getUriWithOrg(orgslug,"") +`/course/${courseid}/activity/${activity.id.replace("activity_", "")}`}>
|
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/activity/${activity.id.replace("activity_", "")}`}>
|
||||||
<ChapterIndicator key={activity.id} />
|
<ChapterIndicator
|
||||||
</Link>{" "}
|
done={course.trail.activities_marked_complete && course.trail.activities_marked_complete.includes(activity.id) && course.trail.status == "ongoing"}
|
||||||
</>
|
active={"activity_" + activityid === activity.id ? true : false} key={activity.id}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</ToolTip>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -74,10 +78,10 @@ function ActivityPage(params: any) {
|
||||||
{activity.type == "video" && <VideoActivity course={course} activity={activity} />}
|
{activity.type == "video" && <VideoActivity course={course} activity={activity} />}
|
||||||
|
|
||||||
<ActivityMarkerWrapper>
|
<ActivityMarkerWrapper>
|
||||||
|
|
||||||
{course.trail.activities_marked_complete &&
|
{course.trail.activities_marked_complete &&
|
||||||
course.trail.activities_marked_complete.includes("activity_" + activityid) &&
|
course.trail.activities_marked_complete.includes("activity_" + activityid) &&
|
||||||
course.trail.status == "ongoing" ? (
|
course.trail.status == "ongoing" ? (
|
||||||
<button style={{ backgroundColor: "green" }}>
|
<button style={{ backgroundColor: "green" }}>
|
||||||
<i>
|
<i>
|
||||||
<Check size={20}></Check>
|
<Check size={20}></Check>
|
||||||
|
|
@ -131,28 +135,26 @@ const ChaptersWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
// row
|
// row
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-around;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
width: 1300px;
|
width: 1300px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ChapterIndicator = styled.div`
|
const ChapterIndicator = styled.div < { active?: boolean, done?: boolean } > `
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
background: #151515;
|
background: #151515;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
width: 35px;
|
width: 35px;
|
||||||
background-color: black;
|
background-color: ${props => props.done ? "green" : (props.active ? "#9d9d9d" : "black")};
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
transition: all 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
width: 50px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
background-color: #9d9d9d;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,13 @@ import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { swrFetcher } from "@services/utils/ts/requests";
|
import { swrFetcher } from "@services/utils/ts/requests";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import ToolTip from "@components/UI/Tooltip/Tooltip";
|
||||||
|
|
||||||
const CourseIdPage = (params: any) => {
|
const CourseIdPage = (params: any) => {
|
||||||
const courseid = params.params.courseid;
|
const courseid = params.params.courseid;
|
||||||
const orgslug = params.params.orgslug;
|
const orgslug = params.params.orgslug;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { data: course, error: error } = useSWR(`${getAPIUrl()}courses/meta/course_${courseid}`,
|
const { data: course, error: error } = useSWR(`${getAPIUrl()}courses/meta/course_${courseid}`,
|
||||||
(url: string, body: any) => swrFetcher(url, body, router)
|
(url: string, body: any) => swrFetcher(url, body, router)
|
||||||
);
|
);
|
||||||
|
|
@ -54,18 +55,22 @@ const CourseIdPage = (params: any) => {
|
||||||
<ChaptersWrapper>
|
<ChaptersWrapper>
|
||||||
{course.chapters.map((chapter: any) => {
|
{course.chapters.map((chapter: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<ChapterSeparator key={chapter}>
|
||||||
{chapter.activities.map((activity: any) => {
|
{chapter.activities.map((activity: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/activity/${activity.id.replace("activity_", "")}`}>
|
<ToolTip sideOffset={-18} slateBlack content={activity.name}>
|
||||||
<ChapterIndicator />
|
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/activity/${activity.id.replace("activity_", "")}`}>
|
||||||
</Link>{" "}
|
<CourseIndicator
|
||||||
|
done={course.trail.activities_marked_complete && course.trail.activities_marked_complete.includes(activity.id) && course.trail.status == "ongoing"}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</ToolTip>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
</ChapterSeparator>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ChaptersWrapper>
|
</ChaptersWrapper>
|
||||||
|
|
@ -93,12 +98,12 @@ const CourseIdPage = (params: any) => {
|
||||||
{course.chapters.map((chapter: any) => {
|
{course.chapters.map((chapter: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h3>Chapter : {chapter.name}</h3>
|
<h3>{chapter.name}</h3>
|
||||||
{chapter.activities.map((activity: any) => {
|
{chapter.activities.map((activity: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>
|
||||||
Activity {activity.name}
|
{activity.name}
|
||||||
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/activity/${activity.id.replace("activity_", "")}`} rel="noopener noreferrer">
|
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/activity/${activity.id.replace("activity_", "")}`} rel="noopener noreferrer">
|
||||||
<EyeOpenIcon />
|
<EyeOpenIcon />
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
|
|
@ -161,28 +166,33 @@ const CoursePageLayout = styled.div`
|
||||||
|
|
||||||
const ChaptersWrapper = styled.div`
|
const ChaptersWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
const ChapterIndicator = styled.div`
|
const CourseIndicator = styled.div< { active?: boolean, done?: boolean } >`
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
background: #151515;
|
background: #151515;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
width: 35px;
|
background-color: ${props => props.done ? "green" : "black"};
|
||||||
background-color: black;
|
|
||||||
|
width: 40px;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
transition: all 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
width: 50px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
background-color: #9d9d9d;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ChapterSeparator = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding-right: 7px;
|
||||||
|
`;
|
||||||
|
|
||||||
const BoxWrapper = styled.div`
|
const BoxWrapper = styled.div`
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.03);
|
box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.03);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import Youtube from "@tiptap/extension-youtube";
|
||||||
import VideoBlock from "./Extensions/Video/VideoBlock";
|
import VideoBlock from "./Extensions/Video/VideoBlock";
|
||||||
import { Save } from "lucide-react";
|
import { Save } from "lucide-react";
|
||||||
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
|
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
|
||||||
import PDFBlockComponent from "./Extensions/PDF/PDFBlockComponent";
|
|
||||||
import PDFBlock from "./Extensions/PDF/PDFBlock";
|
import PDFBlock from "./Extensions/PDF/PDFBlock";
|
||||||
import QuizBlock from "./Extensions/Quiz/QuizBlock";
|
import QuizBlock from "./Extensions/Quiz/QuizBlock";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ export const ToolbarButtons = ({ editor, props }: any) => {
|
||||||
<option value="6">Heading 6</option>
|
<option value="6">Heading 6</option>
|
||||||
</ToolSelect>
|
</ToolSelect>
|
||||||
{/* TODO: fix this : toggling only works one-way */}
|
{/* TODO: fix this : toggling only works one-way */}
|
||||||
<DividerVerticalIcon style={{margin:"auto", color : "grey"}}/>
|
<DividerVerticalIcon style={{marginTop:"auto", marginBottom:"auto", color : "grey"}}/>
|
||||||
<ToolTip content={"Info Callout"}>
|
<ToolTip content={"Info Callout"}>
|
||||||
<ToolBtn onClick={() => editor.chain().focus().toggleNode("calloutInfo").run()}>
|
<ToolBtn onClick={() => editor.chain().focus().toggleNode("calloutInfo").run()}>
|
||||||
<AlertCircle size={15} />
|
<AlertCircle size={15} />
|
||||||
|
|
|
||||||
|
|
@ -5,22 +5,24 @@ import { violet, blackA } from '@radix-ui/colors';
|
||||||
import { PlusIcon } from '@radix-ui/react-icons';
|
import { PlusIcon } from '@radix-ui/react-icons';
|
||||||
|
|
||||||
|
|
||||||
type TooltipParams = {
|
type TooltipProps = {
|
||||||
sideOffset?: number;
|
sideOffset?: number;
|
||||||
content: React.ReactNode;
|
content: React.ReactNode;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
slateBlack?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ToolTip = (params: TooltipParams) => {
|
const ToolTip = (props: TooltipProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip.Provider delayDuration={200}>
|
<Tooltip.Provider delayDuration={200}>
|
||||||
<Tooltip.Root>
|
<Tooltip.Root>
|
||||||
<Tooltip.Trigger asChild>
|
<Tooltip.Trigger asChild>
|
||||||
{params.children}
|
{props.children}
|
||||||
</Tooltip.Trigger>
|
</Tooltip.Trigger>
|
||||||
<Tooltip.Portal>
|
<Tooltip.Portal>
|
||||||
<TooltipContent side="bottom" sideOffset={params.sideOffset}>
|
<TooltipContent slateBlack={props.slateBlack} side="bottom" sideOffset={props.sideOffset}>
|
||||||
{params.content}
|
{props.content}
|
||||||
<TooltipArrow />
|
<TooltipArrow />
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip.Portal>
|
</Tooltip.Portal>
|
||||||
|
|
@ -55,6 +57,16 @@ const closeAndFade = keyframes({
|
||||||
});
|
});
|
||||||
|
|
||||||
const TooltipContent = styled(Tooltip.Content, {
|
const TooltipContent = styled(Tooltip.Content, {
|
||||||
|
|
||||||
|
variants : {
|
||||||
|
slateBlack: {
|
||||||
|
true: {
|
||||||
|
backgroundColor:" #5a5a5a",
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
padding: '5px 10px',
|
padding: '5px 10px',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ async def verify_collection_rights(request: Request,collection_id: str, current
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist")
|
||||||
|
|
||||||
hasRoleRights = await verify_user_rights_with_roles(request, action, current_user.user_id, collection_id)
|
hasRoleRights = await verify_user_rights_with_roles(request, action, current_user.user_id, collection_id, collection["org_id"])
|
||||||
|
|
||||||
if not hasRoleRights:
|
if not hasRoleRights:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,12 @@ async def get_orgs_by_user(request: Request, user_id: str, page: int = 1, limit:
|
||||||
orgs = request.app.db["organizations"]
|
orgs = request.app.db["organizations"]
|
||||||
user = request.app.db["users"]
|
user = request.app.db["users"]
|
||||||
|
|
||||||
|
if user_id is "anonymous":
|
||||||
|
|
||||||
|
# raise error
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="User not logged in")
|
||||||
|
|
||||||
# get user orgs
|
# get user orgs
|
||||||
user_orgs = await user.find_one({"user_id": user_id})
|
user_orgs = await user.find_one({"user_id": user_id})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue