├── 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 | 2 | 4 | -------------------------------------------------------------------------------- /icons/light.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /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 | } --------------------------------------------------------------------------------