Compare commits

...

77 Commits

Author SHA1 Message Date
Kamran Ahmed
1c0adf22b6 Add devops beginner roadmap 2023-06-10 04:01:41 +01:00
Kamran Ahmed
6a4481a3d0 Rewrite devops roadmap 2023-06-07 23:08:32 +01:00
Kamran Ahmed
557c426078 Update apollo workshop image 2023-06-07 11:19:42 +01:00
Kamran Ahmed
d61a83a0a3 chore: add resource under flutter:design-principles:solid-principles 2023-06-06 14:19:46 +01:00
Kamran Ahmed
7500c6c1cb chore: add resource under backend:internet:what-is-http 2023-06-06 14:19:16 +01:00
Kamran Ahmed
b51076dd0a chore: add resource under cpp:introduction 2023-06-06 14:18:56 +01:00
Kamran Ahmed
8010bfc832 Add kodecloud link 2023-06-06 14:17:21 +01:00
Kamran Ahmed
0f80f26d17 Update link-groups 2023-06-06 11:02:08 +01:00
thesmallrock
40d25c43f4 Fixing "new and delete operators" titles. (#3994) 2023-06-06 09:32:02 +01:00
Kamran Ahmed
686a7382ab chore: add resource under cyber-security:basic-it-skills:basics-of-computer-networking 2023-06-06 09:11:42 +01:00
Kamran Ahmed
88401bd7b1 chore: add resource under mongodb:datatypes:date 2023-06-06 09:11:12 +01:00
Kamran Ahmed
1d97467c05 chore: add resource under software-design-architecture:architectural-styles 2023-06-06 09:10:43 +01:00
Kamran Ahmed
2388fa148b Update apollo workshop 2023-06-05 23:40:10 +01:00
Kamran Ahmed
d574fccbc8 Add apollo asset 2023-06-05 23:21:04 +01:00
Kamran Ahmed
89cc55a1eb chore: add resource under flutter:state-management:change-notifier 2023-06-05 21:18:29 +01:00
Kamran Ahmed
8c75354235 chore: add resource under flutter:state-management:value-notifier 2023-06-05 21:18:22 +01:00
Kamran Ahmed
9eb9dc8cd8 chore: add resource under nodejs:nodejs-command-line-apps:taking-input 2023-06-05 21:18:07 +01:00
Kamran Ahmed
afa28bddd3 chore: add resource under python:python-advanced-topics:lambdas 2023-06-05 21:17:32 +01:00
Kamran Ahmed
5cf0e76765 chore: add resource under react:components:props-vs-state 2023-06-05 21:16:59 +01:00
Kamran Ahmed
16b3f8ff49 chore: add resource under system-design:application-layer:microservices 2023-06-05 21:16:12 +01:00
Kamran Ahmed
d2055e0f6d chore: add resource under react:components:conditional-rendering 2023-06-05 21:15:43 +01:00
Kamran Ahmed
4010157baf chore: add resource under ux-design:human-decision-making:frameworks:bj-frogg-behavior-model 2023-06-05 21:15:08 +01:00
Kamran Ahmed
75c7e83264 chore: add resource under backend:os-general-knowledge:terminal-usage 2023-06-05 21:14:28 +01:00
Kamran Ahmed
8ca22e0dcc chore: add resource under python:python-testing:pytest 2023-06-05 21:13:27 +01:00
Kamran Ahmed
2b8d1f470c chore: add resource under backend:version-control-systems:git 2023-06-05 21:13:15 +01:00
Kamran Ahmed
c4d9651e95 chore: add resource under react:components 2023-06-05 21:12:13 +01:00
Kamran Ahmed
813c0ebd93 chore: add resource under backend:relational-databases:mysql 2023-06-05 21:11:38 +01:00
Kamran Ahmed
e376942c8d chore: add resource under devops:infrastructure-as-code:gitops:argo-cd 2023-06-05 21:02:21 +01:00
Kamran Ahmed
6d91c11856 chore: add resource link to ux-design >> human-decision-making:frameworks:stephen-wendell-create-action-funnel 2023-06-05 21:00:49 +01:00
Kamran Ahmed
1d47b1fb7b chore: add resource link to cpp >> introduction:what-is-cpp 2023-06-05 20:47:54 +01:00
Kamran Ahmed
54a9e586bf chore: add resource link to frontend >> progressive-web-apps:lighthouse 2023-06-05 20:46:58 +01:00
Kamran Ahmed
b58c2a1356 Fix roadmap json 2023-06-05 20:38:54 +01:00
Kamran Ahmed
dec5e58063 Refactor roadmap and best practice rendering engine 2023-06-05 19:55:58 +01:00
Kamran Ahmed
b0a4130229 Update code review pyramid 2023-06-04 23:00:35 +01:00
Kamran Ahmed
a06e992b8a Update reference link for code review pyramid 2023-06-03 21:31:37 +01:00
Kamran Ahmed
6e1072bea9 Add code review pyramid 2023-06-03 21:17:55 +01:00
Kamran Ahmed
1f9eb18bfb Add update file URL in the topic file 2023-06-02 22:45:37 +01:00
Kamran Ahmed
603bd2b107 Update contribution copy 2023-06-02 21:34:30 +01:00
Kamran Ahmed
0163d9e4f9 Update copy on contribution 2023-06-02 21:33:30 +01:00
Kamran Ahmed
910579f463 Update isNew badges 2023-06-02 21:31:27 +01:00
Kamran Ahmed
d6a28a312a Add contribution functionality 2023-06-02 21:23:26 +01:00
Kamran Ahmed
267a4a7be5 Update cpp roadmap dates 2023-06-01 17:01:39 +01:00
Kamran Ahmed
59111a1a90 Add link to C++ roadmap 2023-06-01 03:59:22 +01:00
Kamran Ahmed
9f5d1aef74 Add content to C++ roadmap 2023-06-01 03:42:42 +01:00
Kamran Ahmed
36eed57ec2 Add content to C++ roadmap 2023-06-01 03:33:27 +01:00
Kamran Ahmed
cc054bb24b Add content to C++ roadmap 2023-06-01 03:18:40 +01:00
Kamran Ahmed
056256015d Add C++ roadmap 2023-06-01 02:55:26 +01:00
Arik Chakma
dd5f3795ec fix: login link (#3985) 2023-05-31 10:00:19 +01:00
Kamran Ahmed
8c29d43bef fix: page loading message does not persist 2023-05-30 19:48:40 +01:00
Kamran Ahmed
aa32258aa1 Refactor page progress implementation 2023-05-30 18:52:41 +01:00
Kamran Ahmed
d2394aca77 Downgrade nanostores 2023-05-30 18:40:58 +01:00
Kamran Ahmed
6804535fe4 chore: update dependencies 2023-05-30 18:27:08 +01:00
github-actions[bot]
3852e7d96f chore: update dependencies to latest (#3973)
Co-authored-by: kamranahmedse <kamranahmedse@users.noreply.github.com>
2023-05-30 17:41:57 +01:00
Kamran Ahmed
eb852caee8 Update link to improve guide 2023-05-30 14:50:37 +01:00
유성현
1414693e33 fix minor typos (#3974)
* 📝 fix : typos

* Update 101-anti-corruption-layer.md

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2023-05-30 14:32:15 +01:00
Kamran Ahmed
fbdb7e77c3 Fix: active sidebar missing border 2023-05-27 03:04:35 +01:00
Kamran Ahmed
c72658938f Add icons in the mobile sidebar menu 2023-05-26 17:31:10 +01:00
Kamran Ahmed
718c582a8c Update account sidebar 2023-05-26 17:11:59 +01:00
Kamran Ahmed
12f385dffd Show the recently updated item on top 2023-05-26 15:38:04 +01:00
Kamran Ahmed
35f500d218 Show most recently tracked items on top 2023-05-26 03:43:50 +01:00
Kamran Ahmed
44949709d1 Add activity page 2023-05-26 03:16:25 +01:00
Kamran Ahmed
476557db80 Add activity dashboard 2023-05-25 16:37:33 +01:00
Kamran Ahmed
f7625a8250 Add basic UI for activity dashboard 2023-05-24 19:25:35 +01:00
Kamran Ahmed
c06c236da5 Refactor account pages 2023-05-24 15:18:29 +01:00
Kamran Ahmed
24c262282e External redirect tracking from roadmap.sh 2023-05-22 19:59:38 +01:00
Kamran Ahmed
876330522d Add devops by nana link 2023-05-22 19:59:38 +01:00
Sean Kelly
f1c771e95c Fix typo in content (#3959) 2023-05-22 18:08:55 +01:00
Kamran Ahmed
d3668b25e9 Add kbd around cmd+k 2023-05-22 11:06:26 +01:00
Kamran Ahmed
b0493c370c Add prompt engineering roadmap 2023-05-21 13:00:45 +01:00
Arik Chakma
e67caa0ffe chore: firefox input outline (#3951) 2023-05-21 12:56:34 +01:00
Arik Chakma
82a44ddfef fix: user gets logged out on browser quit (#3947) 2023-05-21 12:55:02 +01:00
Arik Chakma
205fe6cc23 fix: firefox bug (#3948) 2023-05-21 12:27:38 +01:00
Kamran Ahmed
591cac8bfa Add content for reliability 2023-05-21 03:39:19 +01:00
Kamran Ahmed
42debdeab0 Add content for real world under prompting techniques 2023-05-21 03:22:20 +01:00
Kamran Ahmed
0555452bf2 Load pages on render 2023-05-21 02:17:31 +01:00
Kamran Ahmed
cc7f9d94bb Clear text on command menu close 2023-05-20 23:47:54 +01:00
Kamran Ahmed
51d986b86f Add support for CMD + K search (#3944)
* Add command k input

* On Enter open the page

* chore: backend fix

* Refactor pages and add retrieval

* Group separation, no result handling and filtering

* Fix responsiveness of command menu

* Activate on CMD+K and focus

* Add icons to menu

* Add page filtering

* Add search icon in navigation

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2023-05-20 23:20:11 +01:00
512 changed files with 43263 additions and 9748 deletions

View File

@@ -21,25 +21,25 @@
"test:e2e": "playwright test"
},
"dependencies": {
"@astrojs/preact": "^2.2.0",
"@astrojs/sitemap": "^1.3.1",
"@astrojs/preact": "^2.2.1",
"@astrojs/sitemap": "^1.3.3",
"@astrojs/tailwind": "^3.1.3",
"@fingerprintjs/fingerprintjs": "^3.4.1",
"@nanostores/preact": "^0.4.1",
"astro": "^2.5.0",
"astro-compress": "^1.1.43",
"@nanostores/preact": "^0.5.0",
"astro": "^2.5.7",
"astro-compress": "^1.1.46",
"jose": "^4.14.4",
"js-cookie": "^3.0.5",
"nanostores": "^0.8.1",
"nanostores": "^0.9.1",
"node-html-parser": "^6.1.5",
"npm-check-updates": "^16.10.12",
"preact": "^10.14.1",
"preact": "^10.15.1",
"rehype-external-links": "^2.1.0",
"roadmap-renderer": "^1.0.6",
"tailwindcss": "^3.3.2"
},
"devDependencies": {
"@playwright/test": "^1.33.0",
"@playwright/test": "^1.34.3",
"@tailwindcss/typography": "^0.5.9",
"@types/js-cookie": "^3.0.3",
"csv-parser": "^3.0.0",
@@ -48,7 +48,7 @@
"markdown-it": "^13.0.1",
"openai": "^3.2.1",
"prettier": "^2.8.8",
"prettier-plugin-astro": "^0.9.0",
"prettier-plugin-astro": "^0.10.0",
"prettier-plugin-tailwindcss": "^0.3.0"
}
}

633
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

BIN
public/roadmaps/cpp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 KiB

View File

@@ -40,6 +40,7 @@ Here is the list of available roadmaps with more being actively worked upon.
- [Software Design and Architecture Roadmap](https://roadmap.sh/software-design-architecture)
- [JavaScript Roadmap](https://roadmap.sh/javascript)
- [TypeScript Roadmap](https://roadmap.sh/typescript)
- [C++ Roadmap](https://roadmap.sh/cpp)
- [React Roadmap](https://roadmap.sh/react)
- [Vue Roadmap](https://roadmap.sh/vue)
- [Angular Roadmap](https://roadmap.sh/angular)
@@ -61,6 +62,7 @@ Here is the list of available roadmaps with more being actively worked upon.
- [MongoDB Roadmap](https://roadmap.sh/mongodb)
- [UX Design Roadmap](https://roadmap.sh/ux-design)
- [Docker Roadmap](https://roadmap.sh/docker)
- [Prompt Engineering Roadmap](https://roadmap.sh/prompt-engineering)
We have also added a new form of visual content covering best practices:

View File

@@ -1,19 +0,0 @@
const fs = require('node:fs');
const path = require('node:path');
const jsonsDir = path.join(process.cwd(), 'public/jsons');
const childJsonDirs = fs.readdirSync(jsonsDir);
childJsonDirs.forEach((childJsonDir) => {
const fullChildJsonDirPath = path.join(jsonsDir, childJsonDir);
const jsonFiles = fs.readdirSync(fullChildJsonDirPath);
jsonFiles.forEach((jsonFileName) => {
console.log(`Compressing ${jsonFileName}...`);
const jsonFilePath = path.join(fullChildJsonDirPath, jsonFileName);
const json = require(jsonFilePath);
fs.writeFileSync(jsonFilePath, JSON.stringify(json));
});
});

View File

@@ -3,7 +3,6 @@ const path = require('path');
const OPEN_AI_API_KEY = process.env.OPEN_AI_API_KEY;
const ALL_ROADMAPS_DIR = path.join(__dirname, '../src/data/roadmaps');
const ROADMAP_JSON_DIR = path.join(__dirname, '../public/jsons/roadmaps');
const roadmapId = process.argv[2];
@@ -61,9 +60,9 @@ function writeTopicContent(currTopicUrl) {
const roadmapTitle = roadmapId.replace(/-/g, ' ');
let prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${childTopic}". Write me a brief summary for that topic. Content should be in markdown. Behave as if you are the author of the guide.`;
let prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${childTopic}". Write me with a brief summary of that. Content should be in markdown. I already know the benefits of each so do not add benefits in the output. Also include the code examples if applicable to this topic.`;
if (!childTopic) {
prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${parentTopic}". Write me a brief summary for that topic. Content should be in markdown. Behave as if you are the author of the guide.`;
prompt = `I am reading a guide about "${roadmapTitle}". I am on the topic "${parentTopic}". I want to know more about "${parentTopic}". Write me with a brief summary of that. Content should be in markdown. I already know the benefits of each so do not add benefits in the output. Also include the code examples if applicable to this topic.`;
}
console.log(`Generating '${childTopic || parentTopic}'...`);
@@ -139,7 +138,11 @@ async function writeFileForGroup(group, topicUrlToPathMapping) {
async function run() {
const topicUrlToPathMapping = getFilesInFolder(ROADMAP_CONTENT_DIR);
const roadmapJson = require(path.join(ROADMAP_JSON_DIR, `${roadmapId}.json`));
const roadmapJson = require(path.join(
ALL_ROADMAPS_DIR,
`${roadmapId}/${roadmapId}`
));
const groups = roadmapJson?.mockup?.controls?.control?.filter(
(control) =>
control.typeID === '__group__' &&

View File

@@ -84,8 +84,9 @@ function prepareDirTree(control, dirTree, dirSortOrders) {
const roadmap = require(path.join(
__dirname,
`../public/jsons/roadmaps/${roadmapId}`
`../src/data/roadmaps/${roadmapId}/${roadmapId}`
));
const controls = roadmap.mockup.controls.control;
// Prepare the dir tree that we will be creating and also calculate the sort orders

View File

@@ -0,0 +1,115 @@
---
import AstroIcon from './AstroIcon.astro';
const { activePageId, activePageTitle } = Astro.props;
export interface Props {
activePageId: string;
activePageTitle: string;
}
const sidebarLinks = [
{
href: '/account',
title: 'Activity',
id: 'activity',
icon: {
glyph: 'analytics',
classes: 'h-3 w-4',
}
},
{
href: '/account/update-profile',
title: 'Profile',
id: 'profile',
icon: {
glyph: 'user',
classes: 'h-4 w-4',
}
},
{
href: '/account/update-password',
title: 'Security',
id: 'change-password',
icon: {
glyph: 'security',
classes: 'h-4 w-4'
}
},
];
---
<div class='relative mb-5 block border-b p-4 shadow-inner md:hidden'>
<button
class='flex h-10 w-full items-center justify-between rounded-md border bg-white px-2 text-center text-gray-900 text-sm font-medium'
id='settings-menu'
>
{activePageTitle}
<AstroIcon icon='dropdown' />
</button>
<ul
id='settings-menu-dropdown'
class='absolute left-0 right-0 z-10 mt-1 hidden space-y-1.5 bg-white p-2 shadow-lg'
>
{
sidebarLinks.map((sidebarLink) => (
<li>
<a
href={sidebarLink.href}
class={`flex items-center w-full rounded px-3 py-1.5 text-slate-900 hover:bg-slate-200 text-sm ${
activePageId === sidebarLink.id ? 'bg-slate-100' : ''
}`}
>
<AstroIcon icon={sidebarLink.icon.glyph} class={`${sidebarLink.icon.classes} mr-2`} />
{sidebarLink.title}
</a>
</li>
))
}
</ul>
</div>
<div class='container flex min-h-screen items-stretch'>
<!-- Start Desktop Sidebar -->
<aside class='hidden shrink-0 w-44 border-r border-slate-200 py-10 md:block'>
<nav>
<ul class='space-y-1'>
{
sidebarLinks.map((sidebarLink) => (
<li>
<a
href={sidebarLink.href}
class={`font-regular flex w-full items-center gap-2 px-2 py-1.5 text-sm border-r-2 ${
activePageId === sidebarLink.id ? 'text-black border-r-black bg-gray-100' : 'text-gray-500 border-r-transparent hover:border-r-gray-300'
}`}
>
<AstroIcon icon={sidebarLink.icon.glyph} class={`${sidebarLink.icon.classes} mr-0`} />
{sidebarLink.title}
</a>
</li>
))
}
</ul>
</nav>
</aside>
<!-- /End Desktop Sidebar -->
<div class='grow px-0 py-0 md:px-10 md:py-10'>
<slot />
</div>
</div>
<script>
const menuButton = document.getElementById('settings-menu');
const menuDropdown = document.getElementById('settings-menu-dropdown');
menuButton?.addEventListener('click', () => {
menuDropdown?.classList.toggle('hidden');
});
document.addEventListener('click', (e) => {
if (!menuButton?.contains(e.target as Node)) {
menuDropdown?.classList.add('hidden');
}
});
</script>

View File

@@ -0,0 +1,56 @@
type ActivityCountersType = {
done: {
today: number;
total: number;
};
learning: {
today: number;
total: number;
};
streak: {
count: number;
};
};
type ActivityCounterType = {
text: string;
count: string;
};
function ActivityCounter(props: ActivityCounterType) {
const { text, count } = props;
return (
<div class="relative flex flex-1 flex-row-reverse sm:flex-col px-0 sm:px-4 py-2 sm:py-4 text-center sm:pt-10 items-center gap-2 sm:gap-0 justify-end">
<h2 class="text-base sm:text-5xl font-bold">
{count}
</h2>
<p class="mt-0 sm:mt-2 text-sm text-gray-400">{text}</p>
</div>
);
}
export function ActivityCounters(props: ActivityCountersType) {
const { done, learning, streak } = props;
return (
<div class="mx-0 -mt-5 sm:-mx-10 md:-mt-10">
<div class="flex flex-col sm:flex-row gap-0 sm:gap-2 divide-y sm:divide-y-0 divide-x-0 sm:divide-x border-b">
<ActivityCounter
text={'Topics Completed'}
count={`${done?.total || 0}`}
/>
<ActivityCounter
text={'Currently Learning'}
count={`${learning?.total || 0}`}
/>
<ActivityCounter
text={'Visit Streak'}
count={`${streak?.count || 0}d`}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,161 @@
import { useEffect, useState } from 'preact/hooks';
import { httpGet } from '../../lib/http';
import { ActivityCounters } from './ActivityCounters';
import { ResourceProgress } from './ResourceProgress';
import { pageProgressMessage } from '../../stores/page';
import { EmptyActivity } from './EmptyActivity';
type ActivityResponse = {
done: {
today: number;
total: number;
};
learning: {
today: number;
total: number;
roadmaps: {
title: string;
id: string;
learning: number;
done: number;
total: number;
skipped: number;
updatedAt: string;
}[];
bestPractices: {
title: string;
id: string;
learning: number;
done: number;
skipped: number;
total: number;
updatedAt: string;
}[];
};
streak: {
count: number;
firstVisitAt: Date | null;
lastVisitAt: Date | null;
};
activity: {
type: 'done' | 'learning' | 'pending' | 'skipped';
createdAt: Date;
metadata: {
resourceId?: string;
resourceType?: 'roadmap' | 'best-practice';
topicId?: string;
topicLabel?: string;
resourceTitle?: string;
};
}[];
};
export function ActivityPage() {
const [activity, setActivity] = useState<ActivityResponse>();
const [isLoading, setIsLoading] = useState(true);
async function loadActivity() {
const { error, response } = await httpGet<ActivityResponse>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-user-stats`
);
if (!response || error) {
console.error('Error loading activity');
console.error(error);
return;
}
setActivity(response);
}
useEffect(() => {
loadActivity().finally(() => {
pageProgressMessage.set('');
setIsLoading(false);
});
}, []);
const learningRoadmaps = activity?.learning.roadmaps || [];
const learningBestPractices = activity?.learning.bestPractices || [];
if (isLoading) {
return null;
}
return (
<>
<ActivityCounters
done={activity?.done || { today: 0, total: 0 }}
learning={activity?.learning || { today: 0, total: 0 }}
streak={activity?.streak || { count: 0 }}
/>
<div class="mx-0 px-0 py-5 md:-mx-10 md:px-8 md:py-8">
{learningRoadmaps.length === 0 &&
learningBestPractices.length === 0 && <EmptyActivity />}
{(learningRoadmaps.length > 0 || learningBestPractices.length > 0) && (
<>
<h2 class="mb-3 text-xs uppercase text-gray-400">
Continue Following
</h2>
<div class="flex flex-col gap-3">
{learningRoadmaps
.sort((a, b) => {
const updatedAtA = new Date(a.updatedAt);
const updatedAtB = new Date(b.updatedAt);
return updatedAtB.getTime() - updatedAtA.getTime();
})
.map((roadmap) => (
<ResourceProgress
doneCount={roadmap.done || 0}
learningCount={roadmap.learning || 0}
totalCount={roadmap.total || 0}
skippedCount={roadmap.skipped || 0}
resourceId={roadmap.id}
resourceType={'roadmap'}
updatedAt={roadmap.updatedAt}
title={roadmap.title}
onCleared={() => {
pageProgressMessage.set('Updating activity');
loadActivity().finally(() => {
pageProgressMessage.set('');
});
}}
/>
))}
{learningBestPractices
.sort((a, b) => {
const updatedAtA = new Date(a.updatedAt);
const updatedAtB = new Date(b.updatedAt);
return updatedAtB.getTime() - updatedAtA.getTime();
})
.map((bestPractice) => (
<ResourceProgress
doneCount={bestPractice.done || 0}
totalCount={bestPractice.total || 0}
learningCount={bestPractice.learning || 0}
resourceId={bestPractice.id}
skippedCount={bestPractice.skipped || 0}
resourceType={'best-practice'}
title={bestPractice.title}
updatedAt={bestPractice.updatedAt}
onCleared={() => {
pageProgressMessage.set('Updating activity');
loadActivity().finally(() => {
pageProgressMessage.set('');
});
}}
/>
))}
</div>
</>
)}
</div>
</>
);
}

View File

@@ -0,0 +1,27 @@
import CheckIcon from '../../icons/roadmap.svg';
export function EmptyActivity() {
return (
<div class="rounded-md">
<div class="flex flex-col items-center p-7 text-center">
<img
alt="no roadmaps"
src={CheckIcon}
class="mb-2 w-[60px] h-[60px] sm:h-[120px] sm:w-[120px] opacity-10"
/>
<h2 class="text-lg sm:text-xl font-bold">No Progress</h2>
<p className="my-1 sm:my-2 max-w-[400px] text-gray-500 text-sm sm:text-base">
Progress will appear here as you start tracking your{' '}
<a href="/roadmaps" class="mt-4 text-blue-500 hover:underline">
Roadmaps
</a>{' '}
or{' '}
<a href="/best-practices" class="mt-4 text-blue-500 hover:underline">
Best Practices
</a>{' '}
progress.
</p>
</div>
</div>
);
}

View File

@@ -0,0 +1,139 @@
import { useState } from 'preact/hooks';
import { httpPost } from '../../lib/http';
import { getRelativeTimeString } from '../../lib/date';
type ResourceProgressType = {
resourceType: 'roadmap' | 'best-practice';
resourceId: string;
title: string;
updatedAt: string;
totalCount: number;
doneCount: number;
learningCount: number;
skippedCount: number;
onCleared: () => void;
};
export function ResourceProgress(props: ResourceProgressType) {
const [isClearing, setIsClearing] = useState(false);
const [isConfirming, setIsConfirming] = useState(false);
const {
updatedAt,
resourceType,
resourceId,
title,
totalCount,
learningCount,
doneCount,
skippedCount,
onCleared,
} = props;
async function clearProgress() {
setIsClearing(true);
const { error, response } = await httpPost(
`${import.meta.env.PUBLIC_API_URL}/v1-clear-resource-progress`,
{
resourceId,
resourceType,
}
);
if (error || !response) {
alert('Error clearing progress. Please try again.');
console.error(error);
setIsClearing(false);
return;
}
localStorage.removeItem(`${resourceType}-${resourceId}-progress`);
console.log(`${resourceType}-${resourceId}-progress`);
setIsClearing(false);
setIsConfirming(false);
onCleared();
}
const url =
resourceType === 'roadmap'
? `/${resourceId}`
: `/best-practices/${resourceId}`;
const totalMarked = doneCount + skippedCount;
const progressPercentage = Math.round((totalMarked / totalCount) * 100);
return (
<div>
<a
href={url}
className="group relative flex cursor-pointer items-center rounded-t-md border p-3 text-gray-600 hover:border-gray-300 hover:text-black"
>
<span
className={`absolute left-0 top-0 block h-full cursor-pointer rounded-tl-md bg-black/5 group-hover:bg-black/10`}
style={{
width: `${progressPercentage}%`,
}}
></span>
<span className="relative flex-1 cursor-pointer truncate">
{title}
</span>
<span className="ml-1 cursor-pointer text-sm text-gray-400">
{getRelativeTimeString(updatedAt)}
</span>
</a>
<p className="sm:space-between flex flex-row items-start rounded-b-md border border-t-0 px-2 py-2 text-xs text-gray-500">
<span className="hidden flex-1 gap-1 sm:flex">
{doneCount > 0 && (
<>
<span>{doneCount} done</span> &bull;
</>
)}
{learningCount > 0 && (
<>
<span>{learningCount} in progress</span> &bull;
</>
)}
{skippedCount > 0 && (
<>
<span>{skippedCount} skipped</span> &bull;
</>
)}
<span>{totalCount} total</span>
</span>
{!isConfirming && (
<button
className="text-red-500 hover:text-red-800"
onClick={() => setIsConfirming(true)}
disabled={isClearing}
>
{!isClearing && (
<>
Clear Progress <span>&times;</span>
</>
)}
{isClearing && 'Processing...'}
</button>
)}
{isConfirming && (
<span>
Are you sure?{' '}
<button
onClick={clearProgress}
className="ml-1 mr-1 text-red-500 underline hover:text-red-800"
>
Yes
</button>{' '}
<button
onClick={() => setIsConfirming(false)}
className="text-red-500 underline hover:text-red-800"
>
No
</button>
</span>
)}
</p>
</div>
);
}

View File

@@ -26,7 +26,10 @@ const EmailLoginForm: FunctionComponent<{}> = () => {
// Log the user in and reload the page
if (response?.token) {
Cookies.set(TOKEN_COOKIE_NAME, response.token);
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
path: '/',
expires: 30,
});
window.location.reload();
return;

View File

@@ -59,7 +59,10 @@ export function GitHubButton(props: GitHubButtonProps) {
localStorage.removeItem(GITHUB_REDIRECT_AT);
localStorage.removeItem(GITHUB_LAST_PAGE);
Cookies.set(TOKEN_COOKIE_NAME, response.token);
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
path: '/',
expires: 30,
});
window.location.href = redirectUrl;
})
.catch((err) => {

View File

@@ -57,7 +57,10 @@ export function GoogleButton(props: GoogleButtonProps) {
localStorage.removeItem(GOOGLE_REDIRECT_AT);
localStorage.removeItem(GOOGLE_LAST_PAGE);
Cookies.set(TOKEN_COOKIE_NAME, response.token);
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
path: '/',
expires: 30,
});
window.location.href = redirectUrl;
})
.catch((err) => {

View File

@@ -1,7 +1,7 @@
import { useEffect, useState } from 'preact/hooks';
import { httpPost } from '../../lib/http';
import Cookies from 'js-cookie';
import {TOKEN_COOKIE_NAME} from "../../lib/jwt";
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
export default function ResetPasswordForm() {
const [code, setCode] = useState('');
@@ -53,7 +53,10 @@ export default function ResetPasswordForm() {
}
const token = response.token;
Cookies.set(TOKEN_COOKIE_NAME, token);
Cookies.set(TOKEN_COOKIE_NAME, token, {
path: '/',
expires: 30,
});
window.location.href = '/';
};

View File

@@ -27,7 +27,10 @@ export function TriggerVerifyAccount() {
return;
}
Cookies.set(TOKEN_COOKIE_NAME, response.token);
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
path: '/',
expires: 30,
});
window.location.href = '/';
})
.catch((err) => {

View File

@@ -32,8 +32,9 @@ function showHideGuestElements(hideOrShow: 'hide' | 'show' = 'hide') {
// Prepares the UI for the user who is logged in
function handleGuest() {
const authenticatedRoutes = [
'/settings/update-profile',
'/settings/update-password',
'/account/update-profile',
'/account/update-password',
'/account',
];
showHideAuthElements('hide');

View File

@@ -1,5 +0,0 @@
---
---
<div class='recaptcha-field mb-2'></div>
<input type='hidden' name='g-recaptcha-response' class='recaptcha-response' />

View File

@@ -1,36 +0,0 @@
---
---
<script src='./captcha.js'></script>
<script is:inline>
window.onCaptchaLoad = function () {
if (!window.grecaptcha) {
console.warn('window.grecaptcha is not defined');
return;
}
const recaptchaFields = document.querySelectorAll('.recaptcha-field');
// render recaptcha on fields
recaptchaFields.forEach((field) => {
// If captcha already rendered for this field
if (field.hasAttribute('data-recaptcha-id')) {
return;
}
const renderedId = window.grecaptcha.render(field, {
sitekey: '6Ldn2YsjAAAAABlUxNxukAuDAUIuZIhO0hRVxzJW',
});
field.setAttribute('data-recaptcha-id', renderedId);
});
};
</script>
<script
src='https://www.google.com/recaptcha/api.js?onload=onCaptchaLoad&render=explicit'
async
defer
></script>

View File

@@ -1,49 +0,0 @@
class Captcha {
constructor() {
this.onDOMLoaded = this.onDOMLoaded.bind(this);
this.bindValidation = this.bindValidation.bind(this);
this.validateCaptchaBeforeSubmit =
this.validateCaptchaBeforeSubmit.bind(this);
}
validateCaptchaBeforeSubmit(e) {
const target = e.target;
const captchaField = target.querySelector('.recaptcha-field');
if (captchaField) {
const captchaId = captchaField.dataset.recaptchaId;
const captchaResponse = window.grecaptcha.getResponse(captchaId);
// If valid captcha is not present, prevent form submission
if (!captchaResponse) {
e.preventDefault();
alert('Please verify that you are human first');
return false;
}
target.querySelector('.recaptcha-response').value = captchaResponse;
}
target.closest('.popup').classList.add('hidden');
return true;
}
bindValidation() {
const forms = document.querySelectorAll('[captcha-form]');
forms.forEach((form) => {
form.addEventListener('submit', this.validateCaptchaBeforeSubmit);
});
}
onDOMLoaded() {
this.bindValidation();
}
init() {
window.addEventListener('DOMContentLoaded', this.onDOMLoaded);
}
}
const captcha = new Captcha();
captcha.init();

View File

@@ -0,0 +1,204 @@
import { useEffect, useRef, useState } from 'preact/hooks';
import { useKeydown } from '../../hooks/use-keydown';
import { useOutsideClick } from '../../hooks/use-outside-click';
import BestPracticesIcon from '../../icons/best-practices.svg';
import GuideIcon from '../../icons/guide.svg';
import HomeIcon from '../../icons/home.svg';
import RoadmapIcon from '../../icons/roadmap.svg';
import UserIcon from '../../icons/user.svg';
import VideoIcon from '../../icons/video.svg';
import { httpGet } from '../../lib/http';
import { isLoggedIn } from '../../lib/jwt';
type PageType = {
url: string;
title: string;
group: string;
icon?: string;
isProtected?: boolean;
};
const defaultPages: PageType[] = [
{ url: '/', title: 'Home', group: 'Pages', icon: HomeIcon },
{
url: '/account',
title: 'Account',
group: 'Pages',
icon: UserIcon,
isProtected: true,
},
{ url: '/roadmaps', title: 'Roadmaps', group: 'Pages', icon: RoadmapIcon },
{
url: '/best-practices',
title: 'Best Practices',
group: 'Pages',
icon: BestPracticesIcon,
},
{ url: '/guides', title: 'Guides', group: 'Pages', icon: GuideIcon },
{ url: '/videos', title: 'Videos', group: 'Pages', icon: VideoIcon },
];
function shouldShowPage(page: PageType) {
const isUser = isLoggedIn();
return !page.isProtected || isUser;
}
export function CommandMenu() {
const inputRef = useRef<HTMLInputElement>(null);
const modalRef = useRef<HTMLInputElement>(null);
const [isActive, setIsActive] = useState(false);
const [allPages, setAllPages] = useState<PageType[]>([]);
const [searchResults, setSearchResults] = useState<PageType[]>(defaultPages);
const [searchedText, setSearchedText] = useState('');
const [activeCounter, setActiveCounter] = useState(0);
useKeydown('mod_k', () => {
setIsActive(true);
});
useOutsideClick(modalRef, () => {
setSearchedText('');
setIsActive(false);
});
useEffect(() => {
function handleToggleTopic(e: any) {
setIsActive(true);
}
getAllPages();
window.addEventListener(`command.k`, handleToggleTopic);
return () => {
window.removeEventListener(`command.k`, handleToggleTopic);
};
}, []);
useEffect(() => {
if (!isActive || !inputRef.current) {
return;
}
inputRef.current.focus();
}, [isActive]);
async function getAllPages() {
if (allPages.length > 0) {
return allPages;
}
const { error, response } = await httpGet<PageType[]>(`/pages.json`);
if (!response) {
return defaultPages.filter(shouldShowPage);
}
setAllPages([...defaultPages, ...response].filter(shouldShowPage));
return response;
}
useEffect(() => {
if (!searchedText) {
setSearchResults(defaultPages.filter(shouldShowPage));
return;
}
const normalizedSearchText = searchedText.trim().toLowerCase();
getAllPages().then((unfilteredPages = defaultPages) => {
const filteredPages = unfilteredPages
.filter((currPage: PageType) => {
return (
currPage.title.toLowerCase().indexOf(normalizedSearchText) !== -1
);
})
.slice(0, 10);
setActiveCounter(0);
setSearchResults(filteredPages);
});
}, [searchedText]);
if (!isActive) {
return null;
}
return (
<div className="fixed left-0 right-0 top-0 z-50 flex h-full justify-center overflow-y-auto overflow-x-hidden bg-black/50">
<div className="relative top-0 h-full w-full max-w-lg p-2 sm:top-20 md:h-auto">
<div className="relative rounded-lg bg-white shadow" ref={modalRef}>
<input
ref={inputRef}
autofocus={true}
type="text"
value={searchedText}
className="w-full rounded-t-md border-b p-4 text-sm focus:bg-gray-50 focus:outline-none"
placeholder="Search roadmaps, guides or pages .."
autocomplete="off"
onInput={(e) => {
const value = (e.target as HTMLInputElement).value.trim();
setSearchedText(value);
}}
onKeyDown={(e) => {
if (e.key === 'ArrowDown') {
const canGoNext = activeCounter < searchResults.length - 1;
setActiveCounter(canGoNext ? activeCounter + 1 : 0);
} else if (e.key === 'ArrowUp') {
const canGoPrev = activeCounter > 0;
setActiveCounter(
canGoPrev ? activeCounter - 1 : searchResults.length - 1
);
} else if (e.key === 'Tab') {
e.preventDefault();
} else if (e.key === 'Escape') {
setSearchedText('');
setIsActive(false);
} else if (e.key === 'Enter') {
const activePage = searchResults[activeCounter];
if (activePage) {
window.location.href = activePage.url;
}
}
}}
/>
<div class="px-2 py-2">
<div className="flex flex-col">
{searchResults.length === 0 && (
<div class="p-5 text-center text-sm text-gray-400">
No results found
</div>
)}
{searchResults.map((page, counter) => {
const prevPage = searchResults[counter - 1];
const groupChanged = prevPage && prevPage.group !== page.group;
return (
<>
{groupChanged && (
<div class="border-b border-gray-100"></div>
)}
<a
class={`flex w-full items-center rounded p-2 text-sm ${
counter === activeCounter ? 'bg-gray-100' : ''
}`}
onMouseOver={() => setActiveCounter(counter)}
href={page.url}
>
{!page.icon && (
<span class="mr-2 text-gray-400">{page.group}</span>
)}
{page.icon && (
<img src={page.icon} class="mr-2 h-4 w-4" />
)}
{page.title}
</a>
</>
);
})}
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -5,14 +5,13 @@ import './FrameRenderer.css';
export interface Props {
resourceType: 'roadmap' | 'best-practice';
resourceId: string;
jsonUrl: string;
dimensions?: {
width: number;
height: number;
};
}
const { resourceId, resourceType, jsonUrl, dimensions = null } = Astro.props;
const { resourceId, resourceType, dimensions = null } = Astro.props;
---
<div
@@ -22,7 +21,6 @@ const { resourceId, resourceType, jsonUrl, dimensions = null } = Astro.props;
: null}
data-resource-type={resourceType}
data-resource-id={resourceId}
data-json-url={jsonUrl}
>
<div id='resource-loader'>
<Loader />

View File

@@ -1,10 +1,10 @@
import { wireframeJSONToSVG } from 'roadmap-renderer';
import { httpPost } from '../../lib/http';
import { isLoggedIn } from '../../lib/jwt';
import {
renderResourceProgress,
ResourceType,
} from '../../lib/resource-progress';
import { isLoggedIn } from '../../lib/jwt';
import { httpPost } from '../../lib/http';
export class Renderer {
resourceId: string;
@@ -51,7 +51,6 @@ export class Renderer {
this.resourceType = dataset.resourceType!;
this.resourceId = dataset.resourceId!;
this.jsonUrl = dataset.jsonUrl!;
return true;
}
@@ -130,13 +129,19 @@ export class Renderer {
this.trackVisit();
if (roadmapType) {
this.switchRoadmap(`/jsons/roadmaps/${roadmapType}.json`);
this.switchRoadmap(`/${roadmapType}.json`);
} else {
this.jsonToSvg(this.jsonUrl);
this.jsonToSvg(
this.resourceType === 'roadmap'
? `/${this.resourceId}.json`
: `/best-practices/${this.resourceId}.json`
);
}
}
switchRoadmap(newJsonUrl: string) {
this.containerEl?.setAttribute('style', '');
const newJsonFileSlug = newJsonUrl.split('/').pop()?.replace('.json', '');
// Update the URL and attach the new roadmap type
@@ -145,25 +150,15 @@ export class Renderer {
const type = this.resourceType[0]; // r for roadmap, b for best-practices
url.searchParams.delete(type);
url.searchParams.set(type, newJsonFileSlug!);
if (newJsonFileSlug !== this.resourceId) {
url.searchParams.set(type, newJsonFileSlug!);
}
window.history.pushState(null, '', url.toString());
}
const pageType = this.resourceType.replace(/\b\w/g, (l) => l.toUpperCase());
window.fireEvent({
// RoadmapClick, BestPracticesClick, etc
category: `${pageType.replace('-', '')}Click`,
// roadmap/frontend/switch-version
action: `${this.resourceId}/switch-version`,
// roadmap/frontend/switch-version
label: `${newJsonFileSlug}`,
});
this.jsonToSvg(newJsonUrl)?.then(() => {
this.containerEl?.setAttribute('style', '');
});
this.jsonToSvg(newJsonUrl)?.then(() => {});
}
handleSvgClick(e: any) {
@@ -176,7 +171,17 @@ export class Renderer {
e.stopImmediatePropagation();
if (/^ext_link/.test(groupId)) {
window.open(`https://${groupId.replace('ext_link:', '')}`);
const externalLink = groupId.replace('ext_link:', '');
if (!externalLink.startsWith('roadmap.sh')) {
window.fireEvent({
category: 'RoadmapExternalLink',
action: `${this.resourceType} / ${this.resourceId}`,
label: externalLink,
});
}
window.open(`https://${externalLink}`);
return;
}

View File

@@ -32,7 +32,7 @@ const { author } = frontmatter;
<span class='mx-1.5'>&middot;</span>
<a
class='text-blue-400 hover:text-blue-500 hover:underline'
href={`https://github.com/kamranahmedse/roadmap.sh/tree/master/src/data/guides/${guide.id}.md`}
href={`https://github.com/kamranahmedse/developer-roadmap/tree/master/src/data/guides/${guide.id}.md`}
target='_blank'>Improve this Guide</a
>
</p>

View File

@@ -24,10 +24,10 @@ import Icon from '../AstroIcon.astro';
<ul>
<li class='px-1'>
<a
href='/settings/update-profile'
href='/account'
class='block rounded px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700'
>
Settings
Profile
</a>
</li>
<li class='px-1'>

View File

@@ -7,7 +7,6 @@ import AccountDropdown from './AccountDropdown.astro';
<nav class='container flex items-center justify-between'>
<a class='flex items-center text-lg font-medium text-white' href='/' aria-label="roadmap.sh">
<Icon icon='logo' />
<span class='ml-3 hidden md:block'>roadmap.sh</span>
</a>
<!-- Desktop navigation items -->
@@ -20,11 +19,17 @@ import AccountDropdown from './AccountDropdown.astro';
>Best Practices</a
>
</li>
<li>
<a href='/guides' class='hidden lg:inline text-gray-400 hover:text-white'>Guides</a>
<li class='hidden lg:inline'>
<a href='/guides' class='text-gray-400 hover:text-white'>Guides</a>
</li>
<li class='hidden lg:inline'>
<a href='/videos' class='text-gray-400 hover:text-white'>Videos</a>
</li>
<li>
<a href='/videos' class='hidden lg:inline text-gray-400 hover:text-white'>Videos</a>
<kbd data-command-menu class="hidden sm:flex items-center text-gray-400 border border-gray-800 rounded-md px-2.5 py-1 text-sm hover:bg-gray-800 hover:cursor-pointer">
<Icon icon='search' class='h-3 w-3 mr-2' />
<kbd class='font-sans mr-1'>⌘</kbd><kbd class='font-sans'>K</kbd>
</kbd>
</li>
</ul>
<ul class='hidden h-8 w-[172px] items-center justify-end gap-5 sm:flex'>
@@ -93,10 +98,10 @@ import AccountDropdown from './AccountDropdown.astro';
<!-- Links for logged in users -->
<li data-auth-required class='hidden'>
<a
href='/settings/update-profile'
href='/account'
class='text-xl hover:text-blue-300 md:text-lg'
>
Settings
Account
</a>
</li>
<li data-auth-required class='hidden'>
@@ -110,7 +115,7 @@ import AccountDropdown from './AccountDropdown.astro';
<li>
<a
data-guest-required
href='/signup'
href='/login'
class='hidden text-xl text-white md:text-lg'
>
Login

View File

@@ -1,6 +1,5 @@
import Cookies from 'js-cookie';
import { handleAuthRequired } from '../Authenticator/authenticator';
import {TOKEN_COOKIE_NAME} from "../../lib/jwt";
import { TOKEN_COOKIE_NAME } from "../../lib/jwt";
export function logout() {
Cookies.remove(TOKEN_COOKIE_NAME);
@@ -34,6 +33,12 @@ function bindEvents() {
.querySelector('[data-account-dropdown]')
?.classList.toggle('hidden');
});
document
.querySelector('[data-command-menu]')
?.addEventListener('click', () => {
window.dispatchEvent(new CustomEvent('command.k'));
});
}
bindEvents();

View File

@@ -1,7 +1,7 @@
import { useStore } from '@nanostores/preact';
import { useIsFirstRender } from '../hooks/use-is-first-render';
import SpinnerIcon from '../icons/spinner.svg';
import { pageLoadingMessage } from '../stores/page';
import { pageProgressMessage } from '../stores/page';
import { useEffect, useState } from 'preact/hooks';
export interface Props {
initialMessage: string;
@@ -9,14 +9,20 @@ export interface Props {
export function PageProgress(props: Props) {
const { initialMessage } = props;
const [message, setMessage] = useState(initialMessage);
const isFirstRender = useIsFirstRender();
const $pageLoadingMessage = useStore(pageLoadingMessage);
const $pageProgressMessage = useStore(pageProgressMessage);
if (!$pageLoadingMessage) {
if (!initialMessage || !isFirstRender) {
return null;
useEffect(() => {
if ($pageProgressMessage === undefined) {
return;
}
setMessage($pageProgressMessage);
}, [$pageProgressMessage]);
if (!message) {
return null;
}
return (
@@ -30,7 +36,7 @@ export function PageProgress(props: Props) {
className="h-4 w-4 animate-spin fill-blue-600 text-gray-200 sm:h-4 sm:w-4"
/>
<h1 className="ml-2">
{$pageLoadingMessage || initialMessage}
{message}
<span className="animate-pulse">...</span>
</h1>
</div>

View File

@@ -56,7 +56,7 @@ const roadmapTitle =
class='mr-0.5 rounded-sm bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900'
>New</span
>
Resources are here, try clicking nodes
Track your progress and learn by clicking roadmap items.
</p>
<a
@@ -72,9 +72,6 @@ const roadmapTitle =
<p
class='relative block rounded-md border border-yellow-500 bg-white px-2 py-1.5 text-sm text-yellow-700 sm:hidden'
>
Click roadmap items for resources or visit{' '}
<a href={`/${roadmapId}/topics`} class='text-blue-700 underline'>
resources list</a
>.
Track your progress and learn about the topics by clicking the roadmap items.
</p>
</div>

View File

@@ -1,81 +0,0 @@
---
import Icon from '../AstroIcon.astro';
const { pageUrl, name } = Astro.props;
export interface Props {
pageUrl: string;
name: string;
}
---
<div
class='container flex min-h-[calc(100vh-37px-70px)] items-stretch sm:min-h-[calc(100vh-37px-96px)]'
>
<aside class='hidden w-56 border-r border-slate-200 py-10 pr-5 md:block'>
<nav>
<ul class='space-y-1'>
<li>
<a
href='/settings/update-profile'
class=`block w-full rounded px-2 py-1.5 font-regular text-slate-900 hover:bg-slate-100 ${pageUrl === 'profile' ? 'bg-slate-100' : ''}`
>Profile</a
>
</li>
<li>
<a
href='/settings/update-password'
class=`block w-full rounded px-2 py-1.5 font-regular text-slate-900 hover:bg-slate-100 ${pageUrl === 'change-password' ? 'bg-slate-100' : ''}`
>Security</a
>
</li>
</ul>
</nav>
</aside>
<div class='grow py-10 pl-0 md:p-10 md:pr-0'>
<div class='relative mb-5 md:hidden'>
<button
class='flex h-10 w-full items-center justify-between rounded-md bg-slate-800 px-2 text-center font-medium text-slate-100'
id='settings-menu'
>
{name}
<Icon icon='dropdown' />
</button>
<ul
id='settings-menu-dropdown'
class='absolute mt-1 hidden w-full space-y-1.5 rounded-md bg-white p-2 shadow-lg'
>
<li>
<a
href='/settings/update-profile'
class=`block w-full rounded px-2 py-1.5 font-medium text-slate-900 hover:bg-slate-200 ${pageUrl === 'profile' ? 'bg-slate-100' : ''}`
>Profile</a
>
</li>
<li>
<a
href='/settings/update-password'
class=`block w-full rounded px-2 py-1.5 font-medium text-slate-900 hover:bg-slate-200 ${pageUrl === 'change-password' ? 'bg-slate-100' : ''}`
>Change password</a
>
</li>
</ul>
</div>
<slot />
</div>
</div>
<script>
const menuButton = document.getElementById('settings-menu');
const menuDropdown = document.getElementById('settings-menu-dropdown');
menuButton?.addEventListener('click', () => {
menuDropdown?.classList.toggle('hidden');
});
document.addEventListener('click', (e) => {
if (!menuButton?.contains(e.target as Node)) {
menuDropdown?.classList.add('hidden');
}
});
</script>

View File

@@ -0,0 +1,226 @@
import { useEffect, useRef, useState } from 'preact/hooks';
import { httpPost } from '../../lib/http';
type ContributionInputProps = {
id: number;
title: string;
link: string;
isLast: boolean;
totalCount: number;
onAdd: () => void;
onRemove: () => void;
onChange: (link: { id: number; title: string; link: string }) => void;
};
function ContributionInput(props: ContributionInputProps) {
const {
isLast,
totalCount,
onAdd,
onRemove,
onChange,
id,
title: defaultTitle,
link: defaultLink,
} = props;
const titleRef = useRef<HTMLInputElement>(null);
const [focused, setFocused] = useState('');
const [title, setTitle] = useState(defaultTitle);
const [link, setLink] = useState(defaultLink);
useEffect(() => {
if (!titleRef?.current) {
return;
}
titleRef.current.focus();
}, []);
useEffect(() => {
onChange({ id, title, link });
}, [title, link]);
const canAddMore = isLast && totalCount < 5;
return (
<div className="relative mb-3 rounded-md border p-3">
<p
className={`mb-1 text-xs uppercase ${
focused === 'title' ? 'text-black' : 'text-gray-400'
}`}
>
Resource Title
</p>
<input
ref={titleRef}
type="text"
required
className="block w-full rounded-md border p-2 text-sm focus:border-gray-400 focus:outline-none"
placeholder="e.g. Introduction to RESTful APIs"
onFocus={() => setFocused('title')}
onBlur={() => setFocused('')}
onChange={(e) => setTitle((e.target as any).value)}
/>
<p
className={`mb-1 mt-3 text-xs uppercase ${
focused === 'link' ? 'text-black' : 'text-gray-400'
}`}
>
Resource Link
</p>
<input
type="url"
required
className="block w-full rounded-md border p-2 text-sm focus:border-gray-400 focus:outline-none"
placeholder="e.g. https://roadmap.sh/guides/some-url"
onFocus={() => setFocused('link')}
onBlur={() => setFocused('')}
onChange={(e) => setLink((e.target as any).value)}
/>
<div className="mb-0 mt-3 flex gap-3">
{totalCount !== 1 && (
<button
onClick={(e) => {
e.preventDefault();
onRemove();
}}
className="rounded-md text-sm font-semibold text-red-500 underline underline-offset-2 hover:text-red-800"
>
- Remove Link
</button>
)}
{canAddMore && (
<button
onClick={(e) => {
e.preventDefault();
onAdd();
}}
className="rounded-md text-sm font-semibold text-gray-600 underline underline-offset-2 hover:text-black"
>
+ Add another Link
</button>
)}
</div>
</div>
);
}
type ContributionFormProps = {
resourceType: string;
resourceId: string;
topicId: string;
onClose: (message?: string) => void;
};
export function ContributionForm(props: ContributionFormProps) {
const { onClose, resourceType, resourceId, topicId } = props;
const [isSubmitting, setIsSubmitting] = useState(false);
const [links, setLinks] = useState<
{ id: number; title: string; link: string }[]
>([
{
id: new Date().getTime(),
title: '',
link: '',
},
]);
async function onSubmit(e: any) {
e.preventDefault();
setIsSubmitting(true);
const { response, error } = await httpPost(
`${import.meta.env.PUBLIC_API_URL}/v1-contribute-link`,
{
resourceType,
resourceId,
topicId,
links,
}
);
setIsSubmitting(false);
if (!response || error) {
alert(error?.message || 'Something went wrong. Please try again.');
return;
}
onClose('Thanks for your contribution! We will review it shortly.');
}
return (
<div>
<div className="mb-2 mt-2 rounded-md border bg-gray-100 p-3">
<h1 className="mb-2 text-2xl font-bold">Guidelines</h1>
<ul class="flex flex-col gap-1 text-sm text-gray-700">
<li>Content should only be in English.</li>
<li>Do not add things you have not evaluated personally.</li>
<li>It should strictly be relevant to the topic.</li>
<li>It should not be paid or behind a signup.</li>
<li>
Quality over quantity. Smaller set of quality links is preferred.
</li>
</ul>
</div>
<form onSubmit={onSubmit}>
{links.map((link, counter) => (
<ContributionInput
key={link.id}
id={link.id}
title={link.title}
link={link.link}
isLast={counter === links.length - 1}
totalCount={links.length}
onChange={(newLink) => {
setLinks(
links.map((l) => {
if (l.id === link.id) {
return newLink;
}
return l;
})
);
}}
onRemove={() => {
setLinks(links.filter((l) => l.id !== link.id));
}}
onAdd={() => {
setLinks([
...links,
{
id: new Date().getTime(),
title: '',
link: '',
},
]);
}}
/>
))}
<div className="flex gap-2">
<button
disabled={isSubmitting}
type="submit"
className="block w-full rounded-md bg-gray-800 p-2 text-sm text-white hover:bg-black disabled:cursor-not-allowed disabled:bg-gray-400"
>
{isSubmitting ? 'Please wait ...' : 'Submit'}
</button>
<button
className="block w-full rounded-md border border-red-500 p-2 text-sm text-red-600 hover:bg-red-600 hover:text-white"
onClick={(e) => {
e.preventDefault();
onClose();
}}
>
Cancel
</button>
</div>
</form>
</div>
);
}

View File

@@ -14,12 +14,15 @@ import {
ResourceType,
updateResourceProgress as updateResourceProgressApi,
} from '../../lib/resource-progress';
import { pageLoadingMessage, sponsorHidden } from '../../stores/page';
import { pageProgressMessage, sponsorHidden } from '../../stores/page';
import { TopicProgressButton } from './TopicProgressButton';
import { ContributionForm } from './ContributionForm';
export function TopicDetail() {
const [contributionAlertMessage, setContributionAlertMessage] = useState('');
const [isActive, setIsActive] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [isContributing, setIsContributing] = useState(false);
const [error, setError] = useState('');
const [topicHtml, setTopicHtml] = useState('');
@@ -45,14 +48,15 @@ export function TopicDetail() {
}
};
// Close the topic detail when user clicks outside the topic detail
useOutsideClick(topicRef, () => {
setIsActive(false);
setIsContributing(false);
});
useKeydown('Escape', () => {
setIsActive(false);
setIsContributing(false);
});
// Toggle topic is available even if the component UI is not active
@@ -64,7 +68,7 @@ export function TopicDetail() {
return;
}
pageLoadingMessage.set('Updating');
pageProgressMessage.set('Updating');
// Toggle the topic status
isTopicDone({ topicId, resourceId, resourceType })
@@ -89,7 +93,7 @@ export function TopicDetail() {
console.error(err);
})
.finally(() => {
pageLoadingMessage.set('');
pageProgressMessage.set('');
});
});
@@ -99,6 +103,7 @@ export function TopicDetail() {
setIsActive(true);
sponsorHidden.set(true);
setContributionAlertMessage('');
setTopicId(topicId);
setResourceType(resourceType);
setResourceId(resourceId);
@@ -142,10 +147,6 @@ export function TopicDetail() {
return null;
}
const contributionDir =
resourceType === 'roadmap' ? 'roadmaps' : 'best-practices';
const contributionUrl = `https://github.com/kamranahmedse/developer-roadmap/tree/master/src/data/${contributionDir}/${resourceId}/content`;
return (
<div>
<div
@@ -162,7 +163,22 @@ export function TopicDetail() {
</div>
)}
{!isLoading && !error && (
{!isLoading && isContributing && (
<ContributionForm
resourceType={resourceType}
resourceId={resourceId}
topicId={topicId}
onClose={(message?: string) => {
if (message) {
setContributionAlertMessage(message);
}
setIsContributing(false);
}}
/>
)}
{!isContributing && !isLoading && !error && (
<>
{/* Actions for the topic */}
<div className="mb-2">
@@ -173,6 +189,7 @@ export function TopicDetail() {
onShowLoginPopup={showLoginPopup}
onClose={() => {
setIsActive(false);
setIsContributing(false);
}}
/>
@@ -180,7 +197,10 @@ export function TopicDetail() {
type="button"
id="close-topic"
className="absolute right-2.5 top-2.5 inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900"
onClick={() => setIsActive(false)}
onClick={() => {
setIsActive(false);
setIsContributing(false);
}}
>
<img alt="Close" class="h-5 w-5" src={CloseIcon} />
</button>
@@ -193,20 +213,29 @@ export function TopicDetail() {
dangerouslySetInnerHTML={{ __html: topicHtml }}
></div>
<p
id="contrib-meta"
class="mt-10 border-t pt-3 text-sm leading-relaxed text-gray-400"
>
Contribute links to learning resources about this topic{' '}
<a
target="_blank"
class="text-blue-700 underline"
href={contributionUrl}
{/* Contribution */}
<div className="mt-8 flex-1 border-t">
<p class="mb-2 mt-2 text-sm leading-relaxed text-gray-400">
Help others learn by submitting links to learn more about this topic{' '}
</p>
<button
onClick={() => {
if (isGuest) {
setIsActive(false);
showLoginPopup();
return;
}
setIsContributing(true);
}}
disabled={!!contributionAlertMessage}
className="block w-full rounded-md bg-gray-800 p-2 text-sm text-white transition-colors hover:bg-black hover:text-white disabled:bg-green-200 disabled:text-black"
>
on GitHub repository.
</a>
.
</p>
{contributionAlertMessage
? contributionAlertMessage
: 'Submit a Link'}
</button>
</div>
</>
)}
</div>

View File

@@ -1,6 +1,6 @@
import { useEffect, useState } from 'preact/hooks';
import { httpGet, httpPost } from '../../lib/http';
import { pageLoadingMessage } from '../../stores/page';
import { pageProgressMessage } from '../../stores/page';
export default function UpdatePasswordForm() {
const [authProvider, setAuthProvider] = useState('');
@@ -72,15 +72,17 @@ export default function UpdatePasswordForm() {
useEffect(() => {
loadProfile().finally(() => {
pageLoadingMessage.set('');
pageProgressMessage.set('');
});
}, []);
return (
<form onSubmit={handleSubmit}>
<h2 className="text-3xl font-bold sm:text-4xl">Password</h2>
<p className="mt-2">Use the form below to update your password.</p>
<div className="mt-8 space-y-4">
<div class="hidden md:block mb-8">
<h2 className="text-3xl font-bold sm:text-4xl">Password</h2>
<p className="mt-2">Use the form below to update your password.</p>
</div>
<div className="space-y-4">
{authProvider === 'email' && (
<div className="flex w-full flex-col">
<label
@@ -132,7 +134,7 @@ export default function UpdatePasswordForm() {
for="new-password-confirmation"
className="text-sm leading-none text-slate-500"
>
New Password Confirm
Confirm New Password
</label>
<input
type="password"
@@ -141,7 +143,7 @@ export default function UpdatePasswordForm() {
className="mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
required
minLength={6}
placeholder="New password confirm"
placeholder="Confirm New Password"
value={newPasswordConfirmation}
onInput={(e) =>
setNewPasswordConfirmation((e.target as HTMLInputElement).value)

View File

@@ -1,7 +1,7 @@
import { useEffect, useState } from 'preact/hooks';
import { httpGet, httpPost } from '../../lib/http';
import { pageLoadingMessage } from '../../stores/page';
import UploadProfilePicture from '../Profile/UploadProfilePicture';
import { pageProgressMessage } from '../../stores/page';
import UploadProfilePicture from './UploadProfilePicture';
export function UpdateProfileForm() {
const [name, setName] = useState('');
@@ -75,14 +75,16 @@ export function UpdateProfileForm() {
// Make a request to the backend to fill in the form with the current values
useEffect(() => {
loadProfile().finally(() => {
pageLoadingMessage.set('');
pageProgressMessage.set('');
});
}, []);
return (
<div>
<h2 className="text-3xl font-bold sm:text-4xl">Profile</h2>
<p className="mt-2">Update your profile details below.</p>
<div className="mb-8 hidden md:block">
<h2 className="text-3xl font-bold sm:text-4xl">Profile</h2>
<p className="mt-2">Update your profile details below.</p>
</div>
<UploadProfilePicture
avatarUrl={
avatar

View File

@@ -1,7 +1,6 @@
import { useEffect, useRef, useState } from 'preact/hooks';
import Cookies from 'js-cookie';
import { useEffect, useRef, useState } from 'preact/hooks';
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
import { httpCall, httpPost } from '../../lib/http';
interface PreviewFile extends File {
preview: string;
@@ -131,7 +130,7 @@ export default function UploadProfilePicture(props: UploadProfilePictureProps) {
<form
onSubmit={handleSubmit}
encType="multipart/form-data"
className="mt-8 flex flex-col gap-2"
className="flex flex-col gap-2"
>
<label htmlFor="avatar" className="text-sm leading-none text-slate-500">
Profile Picture

View File

@@ -1,4 +1,4 @@
# Disable Entinty Parsing in XML
# Disable Entity Parsing in XML
> Disable entity parsing if you are parsing XML to avoid XXE attacks

View File

@@ -2,4 +2,4 @@
> Get your alerts to become notifications.
If you've set everyting up correctly, your health checks should automatically destroy bad instances and spawn new ones. There's usually no action to take when getting a CloudWatch alert, as everything should be automated. If you're getting alerts where manual intervention is required, do a post-mortem and figure out if there's a way you can automate the action in future. The last time I had an actionable alert from CloudWatch was about a year ago, and it's extremely awesome not to be woken up at 4am for ops alerts any more.
If you've set everything up correctly, your health checks should automatically destroy bad instances and spawn new ones. There's usually no action to take when getting a CloudWatch alert, as everything should be automated. If you're getting alerts where manual intervention is required, do a post-mortem and figure out if there's a way you can automate the action in future. The last time I had an actionable alert from CloudWatch was about a year ago, and it's extremely awesome not to be woken up at 4am for ops alerts any more.

View File

@@ -1,3 +1,3 @@
# App Changes for AWS
While a lot of applications can probably just be deployed to an EC2 instance and work well, if you're coming from a physical environment, you may need to re-architect your application in order to accomodate changes. Don't just think you can copy the files over and be done with it.
While a lot of applications can probably just be deployed to an EC2 instance and work well, if you're coming from a physical environment, you may need to re-architect your application in order to accommodate changes. Don't just think you can copy the files over and be done with it.

View File

@@ -2,4 +2,4 @@
> Don't give servers static/elastic IPs.
For a typical web application, you should put things behind a load balancer, and balance them between AZs. There are a few cases where Elastic IPs will probably need to be used, but in order to make best use of auto-scaling you'll want to use a load balancer instad of giving every instance their own unique IP.
For a typical web application, you should put things behind a load balancer, and balance them between AZs. There are a few cases where Elastic IPs will probably need to be used, but in order to make best use of auto-scaling you'll want to use a load balancer instead of giving every instance their own unique IP.

View File

@@ -2,4 +2,4 @@
> Set up granular billing alerts.
You should always have at least one billing alert set up, but that will only tell you on a monthly basis once you've exceeded your allowance. If you want to catch runaway billing early, you need a more fine grained approach. The way I do it is to set up an alert for my expected usage each week. So the first week's alert for say $1,000, the second for $2,000, third for $3,000, etc. If the week-2 alarm goes off before the 14th/15th of the month, then I know something is probably going wrong. For even more fine-grained control, you can set this up for each individual service, that way you instantly know which service is causing the problem. This could be useful if your usage on one service is quite steady month-to-month, but another is more erratic. Have the indidividual weekly alerts for the steady one, but just an overall one for the more erratic one. If everything is steady, then this is probably overkill, as looking at CloudWatch will quickly tell you which service is the one causing the problem.
You should always have at least one billing alert set up, but that will only tell you on a monthly basis once you've exceeded your allowance. If you want to catch runaway billing early, you need a more fine grained approach. The way I do it is to set up an alert for my expected usage each week. So the first week's alert for say $1,000, the second for $2,000, third for $3,000, etc. If the week-2 alarm goes off before the 14th/15th of the month, then I know something is probably going wrong. For even more fine-grained control, you can set this up for each individual service, that way you instantly know which service is causing the problem. This could be useful if your usage on one service is quite steady month-to-month, but another is more erratic. Have the individual weekly alerts for the steady one, but just an overall one for the more erratic one. If everything is steady, then this is probably overkill, as looking at CloudWatch will quickly tell you which service is the one causing the problem.

View File

@@ -2,4 +2,4 @@
> Scale down on INSUFFICIENT_DATA as well as ALARM.
For your scale-down action, make sure to trigger a scale-down event when there's no metric data, as well as when your trigger goes off. For example, if you have an app which usually has very low traffic, but experiences occasional spikes, you want to be sure that it scales down once the spike is over and the traffic stops. If there's no traffic, you'll get `INSUFFIFIENT_DATA` instead of `ALARM` for your low traffic threshold and it won't trigger a scale-down action.
For your scale-down action, make sure to trigger a scale-down event when there's no metric data, as well as when your trigger goes off. For example, if you have an app which usually has very low traffic, but experiences occasional spikes, you want to be sure that it scales down once the spike is over and the traffic stops. If there's no traffic, you'll get `INSUFFICIENT_DATA` instead of `ALARM` for your low traffic threshold and it won't trigger a scale-down action.

View File

@@ -1,5 +1,5 @@
# Use Official SDKs
> If you need to interact with AWS, use the SDK for your langauge.
> If you need to interact with AWS, use the SDK for your language.
Don't try to roll your own, I did this at first as I only needed a simple upload to S3, but then you add more services and it's just an all around bad idea. [The AWS SDKs](http://aws.amazon.com/tools/) are well written, handle authentication automatically, handle retry logic, and they're maintained and iterated on by Amazon. Also, if you use EC2 IAM roles (which you absolutely should, more on this later) then the SDK will automatically grab the correct credentials for you.

View File

@@ -1,5 +1,5 @@
# Use VPC
Setting up a VPC seems like a pain at first, but once you get stuck in and play with it, it's suprising easy to set up and get going. It provides all sorts of extra features over EC2 that are well worth the extra time it takes to set up a VPC. First, you can control traffic at the network level using ACLs, you can modify instance size, security groups, etc. without needing to terminate an instance. You can specify egress firewall rules (you cannot control outbound traffic from normal EC2). But the biggest thing is that you have your own private subnet where your instances are completely cut off from everyone else, so it adds an extra layer of protection.
Setting up a VPC seems like a pain at first, but once you get stuck in and play with it, it's surprising easy to set up and get going. It provides all sorts of extra features over EC2 that are well worth the extra time it takes to set up a VPC. First, you can control traffic at the network level using ACLs, you can modify instance size, security groups, etc. without needing to terminate an instance. You can specify egress firewall rules (you cannot control outbound traffic from normal EC2). But the biggest thing is that you have your own private subnet where your instances are completely cut off from everyone else, so it adds an extra layer of protection.
If you're interested in the internals of VPC, I highly recommend watching [A Day in the Life of Billion Packets](http://www.youtube.com/watch?v=Zd5hsL-JNY4) ([Slides](https://www.slideshare.net/AmazonWebServices/a-day-in-the-life-of-a-billion-packets-cpn401-aws-reinvent-2013)).

View File

@@ -7,6 +7,6 @@ When CSS files are minified, the content is loaded faster and less data is sent
Use tools to minify your files automatically before or during your build or your deployment.
- [cssnano: A modular minifier based on the PostCSS ecosystem. - cssnano](https://cssnano.co/)
- [CSS Minfier](https://goonlinetools.com/css-minifier/)
- [CSS Minifier](https://goonlinetools.com/css-minifier/)
- [@neutrinojs/style-minify - npm](https://www.npmjs.com/package/@neutrinojs/style-minify)
- [Online CSS Compressor](http://refresh-sf.com)

View File

@@ -8,7 +8,7 @@ author:
seo:
title: 'Consistency Patterns - roadmap.sh'
description: 'Everything you need to know about Week, Strong and Eventual Consistency'
isNew: true
isNew: false
canonicalUrl: 'https://cs.fyi/guide/consistency-patterns-week-strong-eventual/'
type: 'textual'
date: 2023-01-18
@@ -61,7 +61,7 @@ An example of strong consistency is a financial system where users can transfer
In a weakly consistent system, updates to the data may not be immediately propagated. This can lead to inconsistencies and conflicts between different versions of the data, but it also allows for **high availability and low latency**.
Another example of weak consistency is a gaming platform where users can play online multiplayer games. When a user plays a game, their actions are immediately visible to other players in the same data center, but if there was a lag or temporary connectoin loss, the actions may not be seen by some of the users and the game will continue. This can lead to inconsistencies between different versions of the game state, but it also allows for a high level of availability and low latency.
Another example of weak consistency is a gaming platform where users can play online multiplayer games. When a user plays a game, their actions are immediately visible to other players in the same data center, but if there was a lag or temporary connection loss, the actions may not be seen by some of the users and the game will continue. This can lead to inconsistencies between different versions of the game state, but it also allows for a high level of availability and low latency.
### Eventual Consistency

View File

@@ -8,7 +8,7 @@ author:
seo:
title: 'Jump Servers: What, Why and How - roadmap.sh'
description: 'Learn what is a Jump Server and how to set it up for SSH access.'
isNew: true
isNew: false
type: 'textual'
date: 2023-03-20
sitemap:

View File

@@ -8,7 +8,7 @@ author:
seo:
title: "Guide to Let's Encrypt SSL Setup - roadmap.sh"
description: "Learn how to protect your website using Let's Encrypt SSL Certificates."
isNew: true
isNew: false
type: 'textual'
date: 2023-03-13
sitemap:

View File

@@ -8,7 +8,7 @@ author:
seo:
title: 'Single Command Database Setup - roadmap.sh'
description: 'Learn how to run MySQL, PostgreSQL, or MongoDB in Docker with single Command'
isNew: true
isNew: false
type: 'textual'
date: 2023-02-27
sitemap:

View File

@@ -1,4 +1,5 @@
---
byte-byte-go: https://blog.bytebytego.com/archive
speedup-js: https://marvinh.dev/blog/speeding-up-javascript-ecosystem/
23-min-ts: https://www.youtube.com/watch?v=YmxwicpROps
bun-vs-node: https://www.youtube.com/watch?v=qCX8rw4qOSA

View File

@@ -7,4 +7,4 @@ Use pipes to transform strings, currency amounts, dates, and other data for disp
Visit the following resources to learn more:
- [Understanding BuiltIn Pipes](https://angular.io/guide/pipes)
- [BuiltIn Pipes - exampls](https://codecraft.tv/courses/angular/pipes/built-in-pipes/)
- [BuiltIn Pipes - examples](https://codecraft.tv/courses/angular/pipes/built-in-pipes/)

View File

@@ -2,7 +2,7 @@
Forms are used to handle user inputs in many applications. It enables users from entering sensitive information to performing several data entry tasks.
Angular provides two approachs to handle user inputs trough forms: reactive and template-driven forms.
Angular provides two approaches to handle user inputs trough forms: reactive and template-driven forms.
Visit the following resources to learn more:

View File

@@ -11,3 +11,4 @@ Visit the following resources to learn more:
- [HTTP/3 From A To Z: Core Concepts](https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)
- [HTTP/1 to HTTP/2 to HTTP/3](https://www.youtube.com/watch?v=a-sBfyiXysI)
- [HTTP Crash Course & Exploration](https://www.youtube.com/watch?v=iYM2zFP3Zn0)
- [SSL, TLS, HTTPS Explained](https://www.youtube.com/watch?v=j9qmmewmcfo)

View File

@@ -6,3 +6,4 @@ Visit the following resources to learn more:
- [Command line crash course](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line)
- [Basic Terminal Usage - Cheat Sheet to make the command line EASY](https://www.youtube.com/watch?v=jDINUSK7rXE)
- [50+ Linux Commands You Must Know](https://www.digitalocean.com/community/tutorials/linux-commands)

View File

@@ -7,3 +7,5 @@ Visit the following resources to learn more:
- [Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)
- [Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)
- [Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)
- [Learn Git Branching](https://learngitbranching.js.org/)
- [Git Tutorial](https://www.w3schools.com/git/)

View File

@@ -7,3 +7,4 @@ Visit the following resources to learn more:
- [MySQL website](https://www.mysql.com/)
- [W3Schools - MySQL tutorial ](https://www.w3schools.com/mySQl/default.asp)
- [MySQL tutorial for beginners](https://www.youtube.com/watch?v=7S_tz1z_5bA)
- [MySQL for Developers](https://planetscale.com/courses/mysql-for-developers/introduction/course-introduction)

View File

@@ -1,6 +1,6 @@
# Observability
In sofware development, observability is the measure of how well we can understand a system from the work it does, and how to make it better.
In software development, observability is the measure of how well we can understand a system from the work it does, and how to make it better.
So what makes a system to be "observable"? It is its ability of producing and collecting metrics, logs and traces in order for us to understand what happens under the hood and identify issues and bottlenecks faster.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,47 @@
---
jsonUrl: '/jsons/roadmaps/code-review.json'
pdfUrl: '/pdfs/roadmaps/code-review.pdf'
order: 14
briefTitle: 'Code Review'
briefDescription: 'Learn what to focus on when conducting a code review.'
title: 'Code Review Pyramid'
description: 'Learn what to focus on when conducting a code review.'
isNew: true
hasTopics: true
dimensions:
width: 968
height: 506.06
schema:
headline: 'Code Review Guide'
description: 'Learn what to review when conducting Code Reviews with this interactive guide. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
imageUrl: 'https://roadmap.sh/roadmaps/code-review.png'
datePublished: '2023-06-03'
dateModified: '2023-06-03'
seo:
title: 'Code Review - roadmap.sh'
description: 'Learn what to review when conducting code reviews. We also have questions to ask yourself under each node of the pyramid to guide you further.'
keywords:
- 'code review tutorial'
- 'code review guide'
- 'code review for beginners'
- 'code reviews'
- 'code review best practices'
- 'code review roadmap 2023'
- 'guide to learning code review'
- 'code review roadmap'
- 'code review learning path'
- 'code review learning roadmap'
- 'what is code review'
relatedRoadmaps:
- 'backend'
- 'frontend'
- 'devops'
- 'system-design'
sitemap:
priority: 1
changefreq: 'monthly'
tags:
- 'roadmap'
- 'main-sitemap'
- 'skill-roadmap'
---

View File

@@ -0,0 +1,6 @@
# Questions to Ask
- Is the project's formatting style applied?
- Does it adhere to the agreed-upon naming conventions?
- Is it DRY?
- Is the code sufficiently "readable" (method lengths, etc.)?

View File

@@ -0,0 +1,7 @@
# Questions to Ask
- Are all tests passing?
- Are new features reasonably tested?
- Are corner cases tested?
- Is it using unit tests where possible, integration tests where necessary?
- Are there tests for NFRs, e.g. performance?

View File

@@ -0,0 +1,5 @@
# Questions to Ask
- New features reasonably documented?
- Are the relevant kinds of does covered: README, API docs, user quide, reference docs, etc?
- Are docs understandable, are there no signiticant typos and grammar mistakes?

View File

@@ -0,0 +1,10 @@
# Questions to Ask
- Does it satisfy the original requirements?
- Is it logically correct?
- Is there no unnecessary complexity?
- Is it robust (no concurrency issues, proper error handling, etc.)?
- Is it performant?
- Is it secure e.g., no SQL injections, etc?
- Is it observable e.g., metrics, logging, tracing, etc.?
- Do newly added dependencies pull their weight? Is their license acceptable?

View File

@@ -0,0 +1,8 @@
# Questions to Ask
- API as small as possible, as large as needed?
- Is there one way of doing one thing, not multiple ones?
- Is it consistent, does it follow the principle of least surprise?
- Clean split of API/internals without internals leaking into the API?
- Are there no breaking changes to user-facing parts (API classes, configuration, metrics, log formats, etc)?
- Is a new API generally useful and not overly specific to a single use case?

View File

@@ -0,0 +1 @@
#

View File

View File

@@ -7,5 +7,5 @@ Visit the following resources to learn more:
- [Quick Sort Algorithm](https://www.programiz.com/dsa/quick-sort)
- [Quick Sort Algorithm - Geeks for Geeks](https://www.geeksforgeeks.org/quick-sort/)
- [Quick Sort in 4 Minutes](https://www.youtube.com/watch?v=Hoixgm4-P4M&feature=youtu.be)
- [Quick Sort Implementaiton in C](http://www.cs.yale.edu/homes/aspnes/classes/223/examples/randomization/quick.c)
- [Quick Sort Implementation in C](http://www.cs.yale.edu/homes/aspnes/classes/223/examples/randomization/quick.c)
- [Quick Sort Implementation in Python](https://github.com/jwasham/practice-python/blob/master/quick_sort/quick_sort.py)

View File

@@ -0,0 +1,48 @@
# What is C++?
C++ is a general-purpose programming language created by Bjarne Stroustrup as an extension of the C programming language. It was first introduced in 1985 and provides object-oriented features like classes and inheritance. C++ is widely used in various applications like game development, system programming, embedded systems, and high-performance computing.
C++ is a statically-typed language, meaning that the type of a variable is determined during compilation, and has an extensive library called the C++ Standard Library, which provides a rich set of functions, algorithms, and data structures for various tasks.
C++ builds upon the features of C, and thus, most C programs can be compiled and run with a C++ compiler.
## Code Example
Here's a simple example of a C++ program that demonstrates some essential features of the language:
```cpp
#include <iostream>
// A simple function to add two numbers
int add(int a, int b) {
return a + b;
}
class Calculator {
public:
// A member function to multiply two numbers
int multiply(int a, int b) {
return a * b;
}
};
int main() {
int x = 5;
int y = 3;
// Using the standalone function 'add'
int sum = add(x, y);
std::cout << "Sum: " << sum << std::endl;
// Using a class and member function
Calculator calc;
int product = calc.multiply(x, y);
std::cout << "Product: " << product << std::endl;
return 0;
}
```
In the above program, we define a simple function `add` and a class `Calculator` with a member function `multiply`. The `main` function demonstrates how to use these to perform basic arithmetic.
- [C++ Tutorial for Beginners - Full Course](https://youtu.be/vlnpwxzdw4y)

View File

@@ -0,0 +1,63 @@
# Why C++
C++ is a popular and widely used programming language for various reasons. Here are some of the reasons why you might choose to utilize C++:
## Performance
C++ is designed to provide high performance and efficiency. It offers fine-grained control over system resources, making it easier to optimize your software.
## Portability
C++ is supported on different computer architectures and operating systems, allowing you to write portable code that runs on various platforms without making major modifications.
## Object-Oriented Programming
C++ supports object-oriented programming (OOP) - a paradigm that allows you to design programs using classes and objects, leading to better code organization and reusability.
```cpp
class MyClass {
public:
void myFunction() {
// Code here
}
};
int main() {
MyClass obj;
obj.myFunction();
}
```
## Support for low-level and high-level programming
C++ allows you to write both low-level code, like memory manipulation, as well as high-level abstractions, like creating classes and using the Standard Template Library (STL).
```cpp
#include <iostream>
#include <vector>
int main() {
// Low-level programming
int number = 42;
int* ptr_number = &number;
// High-level programming
std::vector<int> myVector = {1, 2, 3};
for(const auto &i: myVector) {
std::cout << i << std::endl;
}
}
```
## Extensive Libraries
C++ offers a vast range of libraries and tools, such as the Standard Template Library (STL), Boost, and Qt, among others, that can aid in the development of your projects and make it more efficient.
## Combination with C language
C++ can be combined with C, offering the capabilities of both languages and allowing you to reuse your existing C code. By incorporating C++ features, you can enhance your code and improve its functionality.
## Active Community
C++ has been around for a long time and has a large, active community of users who contribute to the growth of the language, express new ideas, and engage in discussions that help develop the language further. This makes finding solutions to any problems you experience much easier.
In summary, C++ offers a great balance of performance, portability, and feature set, making it a versatile and powerful programming language suitable for many applications. With its extensive libraries, active community, and continuous development, C++ is an excellent choice for any software development project.

View File

@@ -0,0 +1,71 @@
# C vs C++
C and C++ are two popular programming languages with some similarities, but they also have key differences. C++ is an extension of the C programming language, with added features such as object-oriented programming, classes, and exception handling. Although both languages are used for similar tasks, they have their own syntax and semantics, which makes them distinct from each other.
## Syntax and Semantics
### C
- C is a procedural programming language.
- Focuses on functions and structured programming.
- Does not support objects or classes.
- Memory management is manual, using functions like `malloc` and `free`.
```c
#include <stdio.h>
void printHello() {
printf("Hello, World!\n");
}
int main() {
printHello();
return 0;
}
```
### C++
- C++ is both procedural and object-oriented.
- Supports both functions and classes.
- Incorporates different programming paradigms.
- Memory management can be manual (like C) or rely on constructors/destructors and smart pointers.
```cpp
#include <iostream>
class HelloWorld {
public:
void printHello() {
std::cout << "Hello, World!" << std::endl;
}
};
int main() {
HelloWorld obj;
obj.printHello();
return 0;
}
```
## Code Reusability and Modularity
### C
- Code reusability is achieved through functions and modular programming.
- High cohesion and low coupling are achieved via structured design.
- Function libraries can be created and included through headers.
### C++
- Offers better code reusability with classes, inheritance, and polymorphism.
- Code modularity is enhanced through namespaces and well-designed object-oriented hierarchy.
## Error Handling
### C
- Error handling in C is done primarily through return codes.
- Lacks support for exceptions or any built-in error handling mechanism.
### C++
- Offers exception handling, which can be used to handle errors that may occur during program execution.
- Enables catching and handling exceptions with `try`, `catch`, and `throw` keywords, providing more control over error handling.
## Conclusion
Both C and C++ are powerful languages with unique features and capabilities. While C is simpler and focuses on procedural programming, C++ offers the versatility of using different programming paradigms and improved code organization. Understanding the differences between these two languages can help you decide which one is more suitable for your specific needs and programming style.

View File

@@ -0,0 +1,132 @@
# Introduction to C++
C++ is a general-purpose, high-performance programming language. It was developed by Bjarne Stroustrup at Bell Labs starting in 1979. C++ is an extension of the C programming language, adding features such as classes, objects, and exceptions.
## Basics of C++ Programming
Here are some basic components and concepts in C++ programming:
## Including Libraries
In C++, we use the `#include` directive to include libraries or header files into our program. For example, to include the standard input/output library, we write:
```cpp
#include <iostream>
```
## Main Function
The entry point of a C++ program is the `main` function. Every C++ program must have a `main` function:
```cpp
int main() {
// Your code goes here
return 0;
}
```
## Input/Output
To perform input and output operations in C++, we can use the built-in objects `std::cin` for input and `std::cout` for output, available in the `iostream` library. Here's an example of reading an integer and printing its value:
```cpp
#include <iostream>
int main() {
int number;
std::cout << "Enter an integer: ";
std::cin >> number;
std::cout << "You entered: " << number << std::endl;
return 0;
}
```
## Variables and Data Types
C++ has several basic data types for representing integer, floating-point, and character values:
- `int`: integer values
- `float`: single-precision floating-point values
- `double`: double-precision floating-point values
- `char`: single characters
Variables must be declared with a data type before they can be used:
```cpp
int x;
float y;
double z;
char c;
```
## Control Structures
C++ provides control structures for conditional execution and iteration, such as `if`, `else`, `while`, `for`, and `switch` statements.
### If-Else Statement
```cpp
if (condition) {
// Code to execute if the condition is true
} else {
// Code to execute if the condition is false
}
```
### While Loop
```cpp
while (condition) {
// Code to execute while the condition is true
}
```
### For Loop
```cpp
for (initialization; condition; update) {
// Code to execute while the condition is true
}
```
### Switch Statement
```cpp
switch (variable) {
case value1:
// Code to execute if variable == value1
break;
case value2:
// Code to execute if variable == value2
break;
// More cases...
default:
// Code to execute if variable does not match any case value
}
```
## Functions
Functions are reusable blocks of code that can be called with arguments to perform a specific task. Functions are defined with a return type, a name, a parameter list, and a body.
```cpp
ReturnType functionName(ParameterType1 parameter1, ParameterType2 parameter2) {
// Function body
// ...
return returnValue;
}
```
For example, here's a function that adds two integers and returns the result:
```cpp
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 4);
std::cout << "3 + 4 = " << result << std::endl;
return 0;
}
```
This basic introduction to C++ should provide you with a good foundation for further learning. Explore more topics such as classes, objects, inheritance, polymorphism, templates, and the Standard Template Library (STL) to deepen your understanding of C++ and start writing more advanced programs.
- [LearnC++](https://www.learncpp.com/)

View File

@@ -0,0 +1,49 @@
# Installing C++
Before you can start programming in C++, you will need to have a compiler installed on your system. A compiler is a program that converts the C++ code you write into an executable file that your computer can run. There are several popular C++ compilers to choose from, depending on your operating system and preference.
### Windows
For Windows, one popular option is to install the [Microsoft Visual Studio IDE](https://visualstudio.microsoft.com/vs/), which includes the Microsoft Visual C++ compiler.
Alternatively, you can also install the [MinGW-w64](https://mingw-w64.org/doku.php) compiler, which is a Windows port of the GNU Compiler Collection (GCC). To install MinGW-w64, follow these steps:
- Download the installer from [here](https://sourceforge.net/projects/mingw-w64/files/).
- Run the installer and select your desired architecture, version, and install location.
- Add the `bin` folder inside the installation directory to your system's `PATH` environment variable.
### macOS
For macOS, you can install the Apple LLVM `clang` compiler which is part of the Xcode Command Line Tools. To do this, open a terminal and enter:
```
xcode-select --install
```
This will prompt a dialog to install the Command Line Tools, which includes the `clang` compiler.
### Linux
On Linux, you can install the GNU Compiler Collection (GCC) through your distribution's package manager. Here are some examples for popular Linux distributions:
- Ubuntu, Debian, and derivatives:
```
sudo apt-get install g++ build-essential
```
- Fedora, CentOS, RHEL, and derivatives:
```
sudo dnf install gcc-c++ make
```
- Arch Linux and derivatives:
```
sudo pacman -S gcc make
```
### Checking the Installation
To confirm that the compiler is installed and available on your system, open a terminal/command prompt, and enter the following command:
```
g++ --version
```
You should see output displaying the version of your installed C++ compiler.
Now you're ready to start writing and compiling your C++ code!

View File

@@ -0,0 +1,13 @@
# Code Editors
Code editors are programs specifically designed for editing, managing and writing source code. They offer a wide range of features that make the development process easier and faster. Here's a brief introduction to some of the most popular code editors for C++:
- **Visual Studio Code (VSCode)**: Visual Studio Code is a popular, free, open-source, and lightweight code editor developed by Microsoft. It has built-in support for C++, along with an extensive library of extensions and plugins.
- **Sublime Text**: Sublime Text is a cross-platform text editor that is quite popular among developers due to its speed and minimalist design. It supports C++ with the help of plugins and has a variety of themes and packages available for customization.
- **CLion**: CLion is an Integrated Development Environment (IDE) developed by JetBrains specifically for C and C++ developers. It provides advanced features like code completion, refactoring support, debugging, and more.
These are just a few examples, and there are many other code editors available, including Atom, Notepad++, and Geany. They all have their features and may suit different developers' needs. Finding the right code editor is often a matter of personal preference and workflow.
To work with C++ in your chosen code editor, you often need to install some additional tools and add-ons, such as compilers, linters, and debugger support. Make sure to follow the instructions provided by the editor's documentation to set up C++ correctly.

View File

@@ -0,0 +1,58 @@
# First Program in C++
In this section, we'll discuss the basic structure of a C++ program, walk you through your first program (the "Hello, World!" example), and provide additional explanations of its syntax.
## Hello, World!
The first program that most people learn to write in any programming language is often a simple one that displays the message "Hello, World!" on the screen. Here's the classic "Hello, World!" program in C++:
```cpp
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
```
Let's break down the different components of this program:
## Header Files & Preprocessor Directives
The first line of the program `#include <iostream>` is a [preprocessor directive](https://en.cppreference.com/w/cpp/preprocessor) that tells the compiler to include the header file `iostream`. Header files provide function and class declarations that we can use in our C++ programs.
```cpp
#include <iostream>
```
##`main()` Function
In C++, the `main()` function serves as the entry point of your program. The operating system runs your program by calling this `main()` function. It should be defined only once in your program and must return an integer.
```cpp
int main() {
// Your code goes here.
}
```
## Output to the Console
To output text to the console, we use the `std::cout` object and the insertion operator `<<`. In the "Hello, World!" example, we used the following line to print "Hello, World!" to the console:
```cpp
std::cout << "Hello, World!" << std::endl;
```
- `std::cout`: The standard "character output" stream that writes to the console
- `"Hello, World!"`: The string literal to print
- `std::endl`: The "end line" manipulator that inserts a newline character and flushes the output buffer
## Return Statement
Lastly, the `return 0;` statement informs the operating system that the program executed successfully. Returning any other integer value indicates that an error occurred:
```cpp
return 0;
```
Now that you understand the basic components of a C++ program, you can write your first program, compile it, and run it to see the "Hello, World!" message displayed on the screen.

View File

@@ -0,0 +1,57 @@
# Setting Up C++
Setting up C++ requires a few steps, including installing a compiler, configuring an Integrated Development Environment (IDE), and creating a new C++ project.
## 1. Installing a Compiler
A compiler is required to convert C++ code into machine language. Some popular C++ compilers include:
- GCC (GNU Compiler Collection) for Linux and macOS
- MinGW (Minimalist GNU for Windows) for Windows
- Microsoft Visual C++ for Windows
To install a compiler, simply follow the instructions provided by the respective websites.
## 2. Configuring an IDE
An IDE is a software application that provides facilities for programming, such as code editing, debugging, and building. Some popular C++ IDEs include:
- [Visual Studio](https://visualstudio.microsoft.com/vs/features/cplusplus/) (Windows, macOS)
- [Eclipse](https://eclipse.org) (Windows, macOS, Linux)
- [Code::Blocks](http://www.codeblocks.org) (Windows, macOS, Linux)
After downloading and installing an IDE, you might need to configure it to use the installed compiler. Check the documentation of the respective IDE for instructions on how to do this.
## 3. Creating a New C++ Project
Once you have your IDE and compiler set up, you can create a new C++ project and start writing code. In general, follow these steps to create a new C++ project:
- Open the IDE and create a new project.
- Select the project type (C++ Application or Console Application).
- Specify the project name and location.
- Let the IDE generate the main.cpp and build files (such as Makefile or CMakeLists.txt) for you.
## Example: Hello World in C++
Create a new file called `main.cpp` within your project and include this code:
```cpp
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
```
Then, follow the IDE's instructions to build and run your program. You should see "Hello, World!" displayed in the console.
## Summary
Setting up C++ involves:
- Installing a compiler (e.g. GCC, MinGW, or MSVC)
- Configuring an IDE (e.g. Visual Studio, Eclipse, or Code::Blocks)
- Creating a new C++ project and writing code
By following these steps, you'll be ready to start developing C++ applications!

View File

@@ -0,0 +1,66 @@
# Arithmetic Operators in C++
Arithmetic operators are used to perform mathematical operations with basic variables such as integers and floating-point numbers. Here is a brief summary of the different arithmetic operators in C++:
## 1. Addition Operator (`+`)
It adds two numbers together.
```cpp
int sum = a + b;
```
## 2. Subtraction Operator (`-`)
It subtracts one number from another.
```cpp
int difference = a - b;
```
## 3. Multiplication Operator (`*`)
It multiplies two numbers together.
```cpp
int product = a * b;
```
## 4. Division Operator (`/`)
It divides one number by another. Note that if both operands are integers, it will perform integer division and the result will be an integer.
```cpp
int quotient = a / b; // integer division
float quotient = float(a) / float(b); // floating-point division
```
## 5. Modulus Operator (`%`)
It calculates the remainder of an integer division.
```cpp
int remainder = a % b;
```
## 6. Increment Operator (`++`)
It increments the value of a variable by 1. There are two ways to use this operator: prefix (`++x`) and postfix (`x++`). Prefix increments the value before returning it, whereas postfix returns the value first and then increments it.
```cpp
int x = 5;
int y = ++x; // x = 6, y = 6
int z = x++; // x = 7, z = 6
```
## 7. Decrement Operator (`--`)
It decrements the value of a variable by 1. It can also be used in prefix (`--x`) and postfix (`x--`) forms.
```cpp
int x = 5;
int y = --x; // x = 4, y = 4
int z = x--; // x = 3, z = 4
```
These are the basic arithmetic operators in C++ that allow you to perform mathematical operations on your variables. Use them in combination with other control structures, such as loops and conditionals, to build more complex programs.

View File

@@ -0,0 +1,55 @@
# Logical Operators in C++
Logical operators are used to perform logical operations on the given expressions, mostly to test the relationship between different variables or values. They return a boolean value i.e., either true (1) or false (0) based on the result of the evaluation.
C++ provides the following logical operators:
- **AND Operator (&&)**
The AND operator checks if both the operands/conditions are true, then the expression is true. If any one of the conditions is false, the whole expression will be false.
```
(expression1 && expression2)
```
Example:
```cpp
int a = 5, b = 10;
if (a > 0 && b > 0) {
cout << "Both values are positive." << endl;
}
```
- **OR Operator (||)**
The OR operator checks if either of the operands/conditions are true, then the expression is true. If both the conditions are false, it will be false.
```
(expression1 || expression2)
```
Example:
```cpp
int a = 5, b = -10;
if (a > 0 || b > 0) {
cout << "At least one value is positive." << endl;
}
```
- **NOT Operator (!)**
The NOT operator reverses the result of the condition/expression it is applied on. If the condition is true, the NOT operator will make it false and vice versa.
```
!(expression)
```
Example:
```cpp
int a = 5;
if (!(a < 0)) {
cout << "The value is not negative." << endl;
}
```
Using these operators, you can create more complex logical expressions, for example:
```cpp
int a = 5, b = -10, c = 15;
if (a > 0 && (b > 0 || c > 0)) {
cout << "At least two values are positive." << endl;
}
```
This covers the essential information about logical operators in C++.

View File

@@ -0,0 +1,87 @@
# Loops in C++
Loops are an essential concept in programming that allow you to execute a block of code repeatedly until a specific condition is met. In C++, there are three main types of loops: `for`, `while`, and `do-while`.
## For Loop
A `for` loop is used when you know the number of times you want to traverse through a block of code. It consists of an initialization statement, a condition, and an increment/decrement operation.
Here's the syntax for a `for` loop:
```cpp
for (initialization; condition; increment/decrement) {
// block of code to execute
}
```
For example:
```cpp
#include <iostream>
using namespace std;
int main() {
for (int i = 0; i < 5; i++) {
cout << "Iteration: " << i << endl;
}
return 0;
}
```
## While Loop
A `while` loop runs as long as a specified condition is `true`. The loop checks for the condition before entering the body of the loop.
Here's the syntax for a `while` loop:
```cpp
while (condition) {
// block of code to execute
}
```
For example:
```cpp
#include <iostream>
using namespace std;
int main() {
int i = 0;
while (i < 5) {
cout << "Iteration: " << i << endl;
i++;
}
return 0;
}
```
## Do-While Loop
A `do-while` loop is similar to a `while` loop, with the key difference being that the loop body is executed at least once, even when the condition is `false`.
Here's the syntax for a `do-while` loop:
```cpp
do {
// block of code to execute
} while (condition);
```
For example:
```cpp
#include <iostream>
using namespace std;
int main() {
int i = 0;
do {
cout << "Iteration: " << i << endl;
i++;
} while (i < 5);
return 0;
}
```
In summary, loops are an integral part of C++ programming that allow you to execute a block of code multiple times. The three types of loops in C++ are `for`, `while`, and `do-while`. Each type has its own specific use case and can be chosen depending on the desired behavior.

View File

@@ -0,0 +1,67 @@
# Bitwise Operations
Bitwise operations are operations that directly manipulate the bits of a number. Bitwise operations are useful for various purposes, such as optimizing algorithms, performing certain calculations, and manipulating memory in lower-level programming languages like C and C++.
Here is a quick summary of common bitwise operations in C++:
## Bitwise AND (`&`)
The bitwise AND operation (`&`) is a binary operation that takes two numbers, compares them bit by bit, and returns a new number where each bit is set (1) if the corresponding bits in both input numbers are set (1); otherwise, the bit is unset (0).
Example:
```cpp
int result = 5 & 3; // result will be 1 (0000 0101 & 0000 0011 = 0000 0001)
```
## Bitwise OR (`|`)
The bitwise OR operation (`|`) is a binary operation that takes two numbers, compares them bit by bit, and returns a new number where each bit is set (1) if at least one of the corresponding bits in either input number is set (1); otherwise, the bit is unset (0).
Example:
```cpp
int result = 5 | 3; // result will be 7 (0000 0101 | 0000 0011 = 0000 0111)
```
## Bitwise XOR (`^`)
The bitwise XOR (exclusive OR) operation (`^`) is a binary operation that takes two numbers, compares them bit by bit, and returns a new number where each bit is set (1) if the corresponding bits in the input numbers are different; otherwise, the bit is unset (0).
Example:
```cpp
int result = 5 ^ 3; // result will be 6 (0000 0101 ^ 0000 0011 = 0000 0110)
```
## Bitwise NOT (`~`)
The bitwise NOT operation (`~`) is a unary operation that takes a single number, and returns a new number where each bit is inverted (1 becomes 0, and 0 becomes 1).
Example:
```cpp
int result = ~5; // result will be -6 (1111 1010)
```
## Bitwise Left Shift (`<<`)
The bitwise left shift operation (`<<`) is a binary operation that takes two numbers, a value and a shift amount, and returns a new number by shifting the bits of the value to the left by the specified shift amount. The vacated bits are filled with zeros.
Example:
```cpp
int result = 5 << 1; // result will be 10 (0000 0101 << 1 = 0000 1010)
```
## Bitwise Right Shift (`>>`)
The bitwise right shift operation (`>>`) is a binary operation that takes two numbers, a value and a shift amount, and returns a new number by shifting the bits of the value to the right by the specified shift amount. The vacated bits are filled with zeros or sign bit depending on the input value being signed or unsigned.
Example:
```cpp
int result = 5 >> 1; // result will be 2 (0000 0101 >> 1 = 0000 0010)
```
These were the most common bitwise operations in C++. Remember to use them carefully and understand their behavior when applied to specific data types and scenarios.

View File

@@ -0,0 +1,108 @@
# Basic Operations in C++
Basic operations in C++ refer to the fundamental arithmetic, relational, and logical operations that can be performed using C++ programming language, which are essential for any kind of program or calculation in a real-world scenario.
Here's a summary of the basic operations in C++
## Arithmetic Operations
These operations are used for performing calculations in C++ and include the following:
- **Addition (+)**: Adds two numbers.
```cpp
int a = 5;
int b = 6;
int sum = a + b; // sum is 11
```
- **Subtraction (-)**: Subtracts one number from the other.
```cpp
int a = 10;
int b = 6;
int diff = a - b; // diff is 4
```
- **Multiplication (*)**: Multiplies two numbers.
```cpp
int a = 3;
int b = 4;
int product = a * b; // product is 12
```
- **Division (/)**: Divides one number by another, yields quotient.
```cpp
int a = 12;
int b = 4;
int quotient = a / b; // quotient is 3
```
- **Modulus (%)**: Divides one number by another, yields remainder.
```cpp
int a = 15;
int b = 4;
int remainder = a % b; // remainder is 3
```
## Relational Operators
These operations compare two values and return a boolean value (true/false) depending on the comparison. The relational operations are:
- **Equal to (==)**: Returns true if both operands are equal.
```cpp
5 == 5 // true
3 == 4 // false
```
- **Not equal to (!=)**: Returns true if operands are not equal.
```cpp
5 != 2 // true
1 != 1 // false
```
- **Greater than (>)**: Returns true if the first operand is greater than the second.
```cpp
5 > 3 // true
2 > 3 // false
```
- **Less than (<)**: Returns true if the first operand is less than the second.
```cpp
3 < 5 // true
6 < 5 // false
```
- **Greater than or equal to (>=)**: Returns true if the first operand is greater than or equal to the second.
```cpp
5 >= 5 // true
6 >= 2 // true
3 >= 4 // false
```
- **Less than or equal to (<=)**: Returns true if the first operand is less than or equal to the second.
```cpp
4 <= 4 // true
2 <= 3 // true
5 <= 4 // false
```
## Logical Operators
Logical operators are used for combining multiple conditions or boolean values.
- **AND (&&)**: Returns true if both operands are true.
```cpp
true && true // true
true && false // false
```
- **OR (||)**: Returns true if any one of the operands is true.
```cpp
true || false // true
false || false // false
```
- **NOT (!)**: Returns true if the operand is false and vice versa.
```cpp
!true // false
!false // true
```

View File

@@ -0,0 +1,62 @@
# Lambda Functions in C++
A lambda function, or simply "lambda", is an anonymous (unnamed) function that is defined in place, within your source code, and with a concise syntax. Lambda functions were introduced in C++11 and have since become a widely used feature, especially in combination with the Standard Library algorithms.
## Syntax
Here is a basic syntax of a lambda function in C++:
```cpp
[capture-list](parameters) -> return_type {
// function body
};
```
- **capture-list**: A list of variables from the surrounding scope that the lambda function can access.
- **parameters**: The list of input parameters, just like in a regular function. Optional.
- **return_type**: The type of the value that the lambda function will return. This part is optional, and the compiler can deduce it in many cases.
- **function body**: The code that defines the operation of the lambda function.
## Usage Examples
Here are a few examples to demonstrate the use of lambda functions in C++:
- Lambda function with no capture, parameters, or return type.
```cpp
auto printHello = []() {
std::cout << "Hello, World!" << std::endl;
};
printHello(); // Output: Hello, World!
```
- Lambda function with parameters.
```cpp
auto add = [](int a, int b) {
return a + b;
};
int result = add(3, 4); // result = 7
```
- Lambda function with capture-by-value.
```cpp
int multiplier = 3;
auto times = [multiplier](int a) {
return a * multiplier;
};
int result = times(5); // result = 15
```
- Lambda function with capture-by-reference.
```cpp
int expiresInDays = 45;
auto updateDays = [&expiresInDays](int newDays) {
expiresInDays = newDays;
};
updateDays(30); // expiresInDays = 30
```
Note that, when using the capture by reference, any change made to the captured variable *inside* the lambda function will affect its value in the surrounding scope.

View File

@@ -0,0 +1,104 @@
# Operators in C++
Operators in C++ are symbols that perform various operations on data, such as arithmetic, comparison, and logical operations. They are used to manipulate and evaluate expressions and variables.
Here is a list of the commonly used operator types in C++:
- **Arithmetic Operators**: These are used for performing arithmetic operations like addition, subtraction, multiplication, and division.
- `+`: addition
```cpp
int sum = 5 + 3; // sum will be 8
```
- `-`: subtraction
```cpp
int difference = 5 - 3; // difference will be 2
```
- `*`: multiplication
```cpp
int product = 5 * 3; // product will be 15
```
- `/`: division
```cpp
int quotient = 15 / 3; // quotient will be 5
```
- `%`: modulo (remainder)
```cpp
int remainder = 7 % 3; // remainder will be 1
```
- **Comparison (Relational) Operators**: These are used to compare two values and return true or false based on the comparison.
- `==`: equal to
```cpp
bool isEqual = (5 == 3); // isEqual will be false
```
- `!=`: not equal to
```cpp
bool isNotEqual = (5 != 3); // isNotEqual will be true
```
- `<`: less than
```cpp
bool isLess = (5 < 3); // isLess will be false
```
- `>`: greater than
```cpp
bool isGreater = (5 > 3); // isGreater will be true
```
- `<=`: less than or equal to
```cpp
bool isLessOrEqual = (5 <= 3); // isLessOrEqual will be false
```
- `>=`: greater than or equal to
```cpp
bool isGreaterOrEqual = (5 >= 3); // isGreaterOrEqual will be true
```
- **Logical Operators**: These operators are used to perform logical operations such as AND (&&), OR (||), and NOT (!) on boolean values.
- `&&`: logical AND
```cpp
bool result = (true && false); // result will be false
```
- `||`: logical OR
```cpp
bool result = (true || false); // result will be true
```
- `!`: logical NOT
```cpp
bool result = !false; // result will be true
```
- **Assignment Operators**: These are used to assign values to variables.
- `=`: simple assignment
```cpp
int x = 5; // x gets the value 5
```
- `+=`: addition assignment
```cpp
int x = 5;
x += 3; // x gets the value 8 (5 + 3)
```
- `-=`: subtraction assignment
```cpp
int x = 5;
x -= 3; // x gets the value 2 (5 - 3)
```
- `*=`: multiplication assignment
```cpp
int x = 5;
x *= 3; // x gets the value 15 (5 * 3)
```
- `/=`: division assignment
```cpp
int x = 15;
x /= 3; // x gets the value 5 (15 / 3)
```
- `%=`: modulo assignment
```cpp
int x = 7;
x %= 3; // x gets the value 1 (7 % 3)
```
These are some of the main operator categories in C++. Each operator allows you to perform specific operations, making your code more efficient and concise.

Some files were not shown because too many files have changed in this diff Show More