├── Dockerfile
├── KubernetesDeployment
├── deployment.yaml
└── services.yaml
├── README.md
├── icons
├── dark.svg
└── light.svg
├── index.html
├── script.js
└── style.css
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Creating server with nginx image from dockerhub
2 | FROM nginx:alpine
3 |
4 | # Copy all info on html container server
5 | COPY . /usr/share/nginx/html
6 |
7 | # Expose on port 80
8 | EXPOSE 80
9 | # NGINX INCLUDES CMD TO RUN .html not necesary
10 | #This dockerfile is created to test env
11 |
--------------------------------------------------------------------------------
/KubernetesDeployment/deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: my-nginx-deployment
5 | spec:
6 | replicas: 3 # Number of replicas
7 | selector:
8 | matchLabels:
9 | app: my-nginx
10 | template:
11 | metadata:
12 | labels:
13 | app: my-nginx
14 | spec:
15 | containers:
16 | - name: my-nginx-container
17 | image: pamblo/nginx:osiristape # Image we tested on Dockerfile
18 | ports:
19 | - containerPort: 80 # Port open from container
20 | ---
21 | apiVersion: autoscaling/v2
22 | kind: HorizontalPodAutoscaler
23 | metadata:
24 | name: my-nginx-hpa
25 | spec:
26 | scaleTargetRef:
27 | apiVersion: apps/v1
28 | kind: Deployment
29 | name: my-nginx-deployment
30 | minReplicas: 3
31 | maxReplicas: 10
32 | metrics:
33 | - type: Resource
34 | resource:
35 | name: cpu
36 | target:
37 | type: Utilization
38 | averageUtilization: 50 # Scale on 50% of cpu consumed resources... Max 10 conteiners.
39 |
--------------------------------------------------------------------------------
/KubernetesDeployment/services.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: my-nginx-service
5 | spec:
6 | selector:
7 | app: my-nginx
8 | type: NodePort # Expose port on local.
9 | ports:
10 | - protocol: TCP
11 | port: 80 # External Port
12 | targetPort: 80 # Port from container
13 | nodePort: 30080 #External Port to localhost acces
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Notes Application
2 |
3 | This is a simple notes application that allows users to create, edit, and delete notes. The application is built using basic web technologies such as HTML, CSS, and JavaScript, and is deployed as a dynamic website.
4 |
5 | > This application also provides theme toggling
6 |
7 | #### Link: https://8ORUZ7.github.io/notes-application/
8 |
9 | ## Features
10 |
11 | - **Create Notes**: Add new notes easily.
12 | - **Edit Notes**: Modify existing notes.
13 | - **Delete Notes**: Remove notes that are no longer needed.
14 | - **Responsive Design**: Works well on both desktop and mobile devices.
15 | - **Docker&Kubernetes**: You can deploy your app on a minikube cluster to practice deployment
16 |
17 | ## Installation
18 |
19 | ### 1. Clone the Repository
20 |
21 | First, clone the repository to your local machine using Git:
22 |
23 | ```
24 | git clone https://github.com/8ORUZ7/notes-application.git
25 | ```
26 |
27 | ### 2. Navigate to the Project Directory
28 |
29 | ```
30 | cd notes-application
31 | ```
32 |
33 | ### 3. Open in Browser
34 |
35 | Since this is a static website, you can simply open the index.html file in your browser:
36 |
37 | ```
38 | open index.html
39 | ```
40 |
41 | ### 4. Optional deployment
42 |
43 | You can apply a kubectl deployment and services and test in localhost:80
44 |
45 | ``
46 | cd /KubernetesDeployment
47 | kubectl apply -f deployment.yaml
48 | kubectl apply -f services.yaml
49 | minikube services my-nginx-service
50 | ``
51 |
--------------------------------------------------------------------------------
/icons/dark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/icons/light.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Notes
7 |
8 |
9 |
10 |
11 |
12 | notes.
13 | double click on a note to remove it.
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | const btnEl = document.getElementById("btn");
2 | const appEl = document.getElementById("App");
3 | // added theme toggling functionality using addEventListener
4 | const themeBtn = document.querySelector(".theme");
5 | if (!localStorage.getItem("theme")) {
6 | localStorage.setItem("theme", "dark");
7 | }
8 | if (localStorage.getItem("theme") === "dark") {
9 | console.log(localStorage.getItem("theme"));
10 | setIcon("dark");
11 | document.body.style.backgroundColor = "black";
12 | document.body.style.filter = "invert(0)";
13 | } else {
14 | setIcon("light");
15 | document.body.style.backgroundColor = "white";
16 | document.body.style.filter = "invert(1)";
17 | }
18 | themeBtn.addEventListener("click", (e) =>{
19 | if (localStorage.getItem("theme") === "light") {
20 | setIcon("dark");
21 | localStorage.setItem("theme", "dark");
22 | document.body.style.backgroundColor = "black";
23 | document.body.style.filter = "invert(0)";
24 | } else if (localStorage.getItem("theme") === "dark") {
25 | setIcon("light");
26 | localStorage.setItem("theme", "light");
27 | document.body.style.backgroundColor = "white";
28 | document.body.style.filter = "invert(1)";
29 | }
30 | })
31 | function setIcon(theme) {
32 | themeBtn.src = `icons/${theme}.svg`;
33 | }
34 | // contribution ended
35 | getNotes().forEach((note)=>{
36 | const noteEl = createNoteEl(note.id,note.content);
37 | appEl.insertBefore(noteEl,btnEl);
38 | });
39 | function createNoteEl(id,content){
40 |
41 | const element = document.createElement("textarea");
42 | element.classList.add("note");
43 | element.placeholder = "Empty Note";
44 | element.value = content;
45 |
46 | element.addEventListener("dblclick",()=>{
47 | const warning = confirm("Do you want to delete this note?");
48 | if(warning){
49 | deleteNote(id,element)
50 | }
51 | });
52 |
53 | element.addEventListener("input",()=>{
54 | updateNote(id,element.value);
55 | });
56 |
57 |
58 | return element;
59 |
60 | }
61 |
62 | function deleteNote(id,element){
63 |
64 | notes = getNotes().filter((note)=> note.id!=id);
65 | saveNote(notes);
66 | appEl.removeChild(element);
67 |
68 | }
69 |
70 | function updateNote(id,content){
71 | const notes = getNotes();
72 | const target = notes.filter((note)=> note.id==id)[0];
73 | target.content = content;
74 | saveNote(notes);
75 | }
76 |
77 |
78 |
79 | function addNote(){
80 | // id , content
81 |
82 | const notes = getNotes();
83 |
84 | const noteObj = {
85 | id: Math.floor(Math.random() * 10000),
86 | content: ""
87 | };
88 |
89 | const noteEl = createNoteEl(noteObj.id,noteObj.content);
90 | appEl.insertBefore(noteEl,btnEl);
91 |
92 | notes.push(noteObj);
93 |
94 | saveNote(notes)
95 | }
96 |
97 | function saveNote(notes){
98 | localStorage.setItem("note-app",JSON.stringify(notes));
99 | }
100 |
101 | function getNotes(){
102 | return JSON.parse(localStorage.getItem("note-app") || "[]");
103 | }
104 |
105 | btnEl.addEventListener("click", addNote);
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | *{
2 | padding: 0;
3 | margin: 0;
4 | }
5 | body{
6 | margin: 0;
7 | background-color: #000000;
8 | font-family: cursive;
9 | }
10 |
11 | .heading{
12 | color: #ffffff;
13 | text-align: center;
14 | padding-top: 10px;
15 | font-size: 35px;
16 | }
17 |
18 | .info-text{
19 | text-align: center;
20 | color: #ffffff;
21 | font-size: 18px;
22 | }
23 |
24 | .app{
25 | display: grid;
26 | grid-template-columns: repeat(auto-fill,300px);
27 | gap: 40px;
28 | justify-content: center;
29 | padding: 50px;
30 | }
31 |
32 | .note{
33 | padding: 17px;
34 | border-radius: 5px;
35 | resize: none;
36 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
37 | font-size: 18px;
38 | height: 300px;
39 | color: #000000;
40 | border: none;
41 | outline: none;
42 | background: rgba(255,255,255,0.7);
43 | box-sizing: border-box;
44 | transition: all 0.3s ease;
45 | }
46 |
47 | .note::placeholder{
48 | color: rgb(75, 74, 74);
49 | opacity: 0.5;
50 | }
51 |
52 | .note:hover,
53 | .note:focus{
54 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
55 | background: rgba(255,255,255,0.9);
56 | }
57 |
58 | .btn{
59 | height: 300px;
60 | border: none;
61 | border-radius: 5px;
62 | font-size: 70px;
63 | font-weight: 700;
64 | color: #000000;
65 | cursor: pointer;
66 | background-color: #ffffff;
67 | transition: all 0.3s ease;
68 | }
69 |
70 | .btn:hover{
71 | transform: scale(1.1);
72 | background-color: #818181;
73 | color: #ffffff;
74 | }
75 | /* added theme class for theme btn */
76 | .theme {
77 | cursor: pointer;
78 | color: white;
79 | position: fixed;
80 | top: 1rem;
81 | right: 1rem;
82 | }
--------------------------------------------------------------------------------