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:
Badr B 2023-04-24 23:02:20 +02:00 committed by GitHub
commit be57196fb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 82 additions and 49 deletions

View file

@ -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(

View file

@ -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

View file

@ -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"));
}; };

View file

@ -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;
} }
`; `;

View file

@ -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>
</> </>
); );
})} })}
&nbsp;&nbsp;&nbsp;&nbsp; </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);

View file

@ -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";

View file

@ -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} />

View file

@ -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,

View file

@ -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(

View file

@ -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})