Hello and welcome Everyone,
I am pleased to introduce to you today the Polynotes application, which was developed as part of a WOA (Web Oriented Architecture) school project.
Polynotes is a web application aimed at facilitating the management of notes, tasks, and databases by providing increased flexibility and customization. This application will be implemented in two iterations: the first iteration is presented here, while the second iteration will be carried out in a team.
We hope that this first iteration of Polynotes will be useful to you and we invite you to explore the features of this application.
In this first iteration of Polynotes, the main features are as follows:
-
Notes and Wikis: Allows you to create and organize notes, documentation, and wikis in a flexible and customizable format.
-
Task and Project Management: Allows you to create and manage tasks, task lists, and projects in a way that best suits your needs.
-
Databases: Allows you to create and manage databases to store and organize information such as contacts, products, or expenses.
-
Document Sharing: Allows you to manage access to your documents, so that your professional or personal network can help you edit them.
Main Library
UI Libraries Components
State & HTTP REQUEST management
Routing
GET /authentification
Components | Description |
---|---|
🧩 Login | Login VIEW |
🧩 Register | Register VIEW |
GET /home
Components | Description |
---|---|
🧩 File Explorer | File Explorer |
🧩 Recents Files | Recents Files |
🧩 User Card | User Card |
GET /document/{id}
Components | Description |
---|---|
🧩 Sous Page Block | File Sub Page |
🧩 DataBase Block | DataBase Block |
🧩 Trello Block | Trello Block |
🧩 Image Block | Image Block |
🧩 Text Editor Block | Text Editor Block |
🧩 Bubble Menu | Bubble Menu |
🧩 DropDown Menu | DropDown Menu |
This code uses the React Router library to manage routes in a React application.
The component defines a group of routes. In this example, there are two groups of routes: a private group and a public group. Private routes are only accessible to authenticated users, while public routes are accessible to all users.
// Pour créer une nouvelle route importer un composant dans les balises "Public" ou "Privé"
<Routes>
<Route element={<PrivateRoutes isAuthenticated={isAuthenticated} />}>
<Route path="/any/page" element={<Page />} />
</Route>
<Route element={<PublicRoutes isAuthenticated={isAuthenticated} />}>
<Route element={<Page />} path="/any" />
</Route>
</Routes>
Framework
Database et ORM
Check out the full swagger documentation here
GET /api/users/{id}
Parameter | Type | Description |
---|---|---|
token |
string |
Required. Your API key |
id |
string |
Required. Id of item to fetch |
POST /api/auth/login
Parameter | Type | Description |
---|---|---|
email |
string |
Required. User email |
password |
string |
Required. User password |
POST /api/auth/signup
Parameter | Type | Description |
---|---|---|
username |
string |
Required. Username |
email |
string |
Required. User email |
password |
string |
Required. User password |
POST /api/auth/logout
Parameter | Type | Description |
---|---|---|
token |
string |
Required. Your API key |
POST /api/auth/email-verification/{token}
Parameter | Type | Description |
---|---|---|
token |
string |
Required. Your Token as URI param |
POST /api/page/add
Parameter | Type | Description |
---|---|---|
pageId |
ObjectId |
Required. Page ID as Mongoose Object ID |
title |
string |
Required. Document title |
userId |
string |
Required. UserId as string |
content |
Array |
Required. Content as Array Block |
GET /api/page/user/{id}
Parameter | Type | Description |
---|---|---|
token |
string |
Optional. Optional if shared document |
id |
string |
Required. Id of item to fetch |
PATCH /api/page/{id}
Parameter | Type | Description |
---|---|---|
content |
Array |
Required. Content as Array Block |
id |
string |
Required. Id of item to fetch |
PATCH /api/page/title/{id}
Parameter | Type | Description |
---|---|---|
title |
Array |
Required. Content as Array Block |
id |
string |
Required. Id of item to fetch |
token |
string |
Required. Token cookie |
PATCH /api/page/privacy/{id}
Parameter | Type | Description |
---|---|---|
token |
string |
Required. Token cookie |
isPublic |
Boolean |
Optional/Required. To share your document to any one |
isEditable |
Boolean |
Optional/Required. To let people edit your document |
POST /api/file-system/tree/create-or-update
Parameter | Type | Description |
---|---|---|
token |
string |
Required. Token cookie |
userId |
string |
Required. User ID |
key |
string |
Required. key generate by uuid() |
children |
NodeFileNavigator |
Required. Children file system |
interface NodeFileNavigator {
title: string;
key: string;
// si undefined alors c'est un fichier
children: NodeFileNavigator[] | undefined;
}
GET /api/file-system/tree/{id}
Parameter | Type | Description |
---|---|---|
token |
string |
Required. Token cookie |
id |
string |
Required. User ID as URI param |
export class User {
// required: true
username: string;
// required: true, unique : true
email: string;
// required: true, default : false
email_verified: boolean;
// required: true
password: string;
}
export class Page {
// required: true
title: string;
// required: true
userId: ObjectId;
// required: true, default : false
isPublic: boolean;
// required: true, default : false
isEditable: boolean;
// required: true
content: [];
}
export class FileSystemTree {
// required: true, unique: true
userId: string;
// required: true
title: string;
// required: true, unique: true
key: string;
// required: true
children: NodeFileNavigator[];
}
Docker CLI & Docker compose
Prenez soin de renseigner vos propres identifiants afin de bénéficier de la fonctionnalité
// make sur to have your .env init in your project
MONGODB_URL=mongodb://mongo:27017/polynotes
MONGODB_DATABASE=polynotes
MAILER_PASSWORD= ## use your own mailer password
MAILER_PORT= ## use your own mailer port
MAILER_HOST= ## use your own host mailer
MAILER_USER= ## use your own account mailer
JWT_SECRET= ## use your own jwt secret mailer
BASE_URL_API=http://localhost:3000/api
docker compose up --build
Note You can check out my github actions configuration file HERE.You can clone it and feel free to customize it by adding new jobs. Don't forget to be register on Docker Hub and adding your own credentials as bellow
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
Warning Before apply your Terraform configuration make sur to have you Kubernetes distribution installed and ArgoCD set on it. If not check the documentation above before starting it.
- From Terraform folder setup your Provider as bellow
provider.tf
:
provider "argocd" {
server_addr = var.server_addr
username = var.username
password = var.password
kubernetes {
host = var.host
client_certificate = var.client_certificate
client_key = var.client_key
cluster_ca_certificate = var.cluster_ca_certificate
}
}
- Then connect your Github repository to ARGOCD as bellow
main.tf
:
resource "argocd_repository" "<your-argocd-app-name>" {
repo = ## your own repository
type = "git"
username = ## your own username
password = ## your own password
}
- Create all variables needed as bellow
variables.tf
, check Terraform documentation to get more informations about variables management :
## ArgoCD
variable "server_addr" {
description = "ArgoCD server address with port."
type = string
}
## K8s
variable "host" {
description = "The hostname (in form of URI) of the Kubernetes API."
type = string
}
Note Before apply your terraform configuration make sur to init all changes your
terraform.tfstate
by running
terraform init
Then you can apply your configuration
terraform apply
- From Terraform folder setup your Provider as bellow
provider.tf
:
provider "kubernetes" {
host = var.host
client_certificate = base64decode(var.client_certificate)
client_key = base64decode(var.client_key)
cluster_ca_certificate = base64decode(var.cluster_ca_certificate)
}
- Then give all the secrets resources that kubernetes need in
main.tf
:
resource "kubernetes_secret" "<your-argocd-app-name>" {
metadata {
name = "<your-secret-kube-object-name>"
namespace = "<your-namespace>"
labels = {
managed-by = "terraform"
}
}
data = {
"mongodb-root-password" = ## your own password
"mongodb-passwords" = ## your own password
"jwt_secret" = ## your own JWT secret
"mailer-password" = ## your own mail password
"mongodb-url" = ## your own string connexion
}
type = "Opaque"
}
Note Before apply your terraform configuration make sur to init all changes your
terraform.tfstate
by running
terraform init
Then you can apply your configuration
terraform apply
Advantages: React JS is really popual with ⭐205k on github repository, so reactjs has a large community and large online documentation and many third-party libraries available.
ReactJS is easy to learn and more permissive than other frameworks like Angular, allowing for greater flexibility in how components are structured and allowing developers to choose their own preferred libraries for state management, routing, and other functionalities.
I also found interesting the way to manage state when reactjs is using with Redux Toolkit.
Disadvantages: In contrast to VueJS, ReactJS can be more challenging to learn and use effectively, particularly when managing reactivity. VueJS offers a more straightforward approach with two-way data binding and computed properties, while ReactJS requires managing state changes manually using lifecycle methods and component state.
Advantages: Redux Toolkit is most popular state manager of react. Comprehensive state management library, easy to use and configure, with a wide variety of features available.
Disadvantages: The Redux data flow model can seem a bit verbose for some use cases. Specially when developper want to make async method (createAsyncThunk) inside reducer.
Advantages: Ant design is really popular with ⭐85k on github repository. The UI component library is well-documented and easy to use, with a wide variety of features available.
Disadvantages: UI may seem uninspired, as it is very standardized.
Advantages: TipTap is popular with ⭐18.7k on github repository.TipTap is Lightweight library for creating rich text editors, with a nice user interface and easy integration with React.
Disadvantages: Despite the popularity of the library, the documentation for TipTap can be difficult to navigate and is not always comprehensive or up-to-date.
Advantages: Routing library for React that is easy to use and configure, with a wide variety of features available.
Advantages: NestJS is a framework that offers a wide range of built-in modules, including Express or authentication management for JWT or Error management standardized. This makes it easy for developers to build complex server-side applications and to maintain it in team.
NestJS also has a well-documented API that is easy to understand and use, making it an ideal choice for novice developper. Additionally, NestJS has a large and active community, with many third-party modules and plugins available to extend its functionality even further.
Disadvantages: Despite its many advantages, NestJS can be challenging to learn for developers who are new to the framework. While it offers a lot of functionality out of the box, this can make it overwhelming for beginners to get all of the concepts and best practices.
Additionally, unlike the more flexible approach of Express, NestJS is a strongly opinionated framework that enforces certain conventions and patterns. This can make it difficult for developers who prefer more flexibility and control over their code.
Advantages: MongoDB is a popular NoSQL document database that offers a high degree of flexibility and scalability, with support for features like sharding, replication. It has a simple and intuitive query language, and allows for dynamic schema design that can accommodate changing data requirements over time.
Disadvantages: While MongoDB's flexibility can be an advantage, it can also introduce potential complexity and require more careful management to ensure data consistency and integrity. Additionally, because MongoDB does not enforce a schema by default, developers may need to invest more time and effort into designing and managing their data models effectively.