<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Deepak Jaiswal </title>
    <description>The latest articles on Forem by Deepak Jaiswal  (@deepakjaiswal).</description>
    <link>https://forem.com/deepakjaiswal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F776540%2F01a8f7fe-5855-4635-ab5b-79181a54a33a.png</url>
      <title>Forem: Deepak Jaiswal </title>
      <link>https://forem.com/deepakjaiswal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/deepakjaiswal"/>
    <language>en</language>
    <item>
      <title>Add localization in nextjs project</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sun, 09 Mar 2025 17:45:05 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/add-localization-in-nextjs-project-3g5k</link>
      <guid>https://forem.com/deepakjaiswal/add-localization-in-nextjs-project-3g5k</guid>
      <description>&lt;p&gt;When i am integrating localization in nextjs getting many issues. so can create post for it. I have implement in client side.&lt;br&gt;
First you need to create file for language which you want to include.&lt;/p&gt;

&lt;p&gt;like &lt;br&gt;
public/locales/&lt;br&gt;
en.json , ar.json, de.json&lt;/p&gt;

&lt;h1&gt;
  
  
  en.json
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "HEADING":"My First Page"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  de.json
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "HEADING":"Meine erste Seite"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;like this you can add language keys.&lt;/p&gt;

&lt;h1&gt;
  
  
  package.json
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
"name": "translation-project",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"aos": "^2.3.4",
"bootstrap": "^5.3.3",
"i18next": "^24.2.2",
"i18next-browser-languagedetector": "^8.0.4",
"i18next-http-backend": "^3.0.2",
"next": "15.1.6",
"react": "^19.0.0",
"react-bootstrap": "^2.10.8",
"react-dom": "^19.0.0",
"react-i18next": "^15.4.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@types/node": "22.12.0",
"eslint": "^9",
"eslint-config-next": "15.1.6",
"sass": "^1.85.1",
"sass-loader": "^16.0.5",
"typescript": "5.7.3"
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Base.tsx
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react'
import Footer from '../footer/page';
import { I18nextProvider, useTranslation } from "react-i18next";
import i18n from "../../../utils/i18n";
const Base = ({children}) =&amp;gt; {
const { i18n: i18nInstance } = useTranslation();
const [loading, setLoading] = useState(true);
useEffect(() =&amp;gt; {
if (i18nInstance.isInitialized) {
   setLoading(false);
}
}, [i18nInstance.isInitialized]);

if (loading) {
return (
&amp;lt;div className="global-loading"&amp;gt;
&amp;lt;/div&amp;gt;
);
}
return (
&amp;lt;I18nextProvider i18n={i18n}&amp;gt;
{children}
&amp;lt;Footer /&amp;gt;
&amp;lt;/I18nextProvider&amp;gt;
)
}
export default Base;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  i18n.ts
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client"; 
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import HttpApi from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
if (typeof window !== "undefined") {
i18n
.use(HttpApi) // Load translations dynamically
.use(LanguageDetector)
.use(initReactI18next)
.init({
supportedLngs: ["en", "ar"],
fallbackLng: "en",
debug: false, // Set false in production
detection: {
  order: ["localStorage", "cookie", "navigator"],
  caches: ["localStorage"]
},
backend: {
   loadPath: "/locales/{{lng}}.json"
},
interpolation: {
    escapeValue: false
}
});
}
export default i18n;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this file i have show that how you can change language &amp;amp; use it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Footer.tsx
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";
import React, { useEffect } from 'react';
import Link from 'next/link';
import './style.scss';
import { PolicyMenu, SocialMenu } from "../../../constant/const";
import { useTranslation } from 'react-i18next';
export default function Footer() {
const { t, i18n } = useTranslation();
const change = (lang) =&amp;gt; {
if (i18n?.language == lang) return;
i18n?.changeLanguage(lang);
}
return (
&amp;lt;div className='footer-wrapper'&amp;gt;
&amp;lt;div className='container'&amp;gt;
&amp;lt;div className='row align-items-center justify-content-center gap-8'&amp;gt;
&amp;lt;div className='col-md-3'&amp;gt;
&amp;lt;p className='mb-0 text-white'&amp;gt;{t("SITE_BY")}&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div className='col-md-6'&amp;gt;
&amp;lt;ul className='social-menu d-flex gap-8 justify-content-center flex-wrap'&amp;gt;
{SocialMenu.map((item, index) =&amp;gt; (
&amp;lt;li key={index}&amp;gt;&amp;lt;Link target="_blank" href={item.url}&amp;gt;{item.icon}&amp;lt;/Link&amp;gt;&amp;lt;/li&amp;gt;
))}
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div className='col-md-3'&amp;gt;
&amp;lt;ul className='footer-links d-flex flex-wrap'&amp;gt;
{PolicyMenu.map((value, index) =&amp;gt; (
&amp;lt;li key={index}&amp;gt;&amp;lt;Link className='text-white'
href={value.url}&amp;gt;{t(value.name)}&amp;lt;/Link&amp;gt;&amp;lt;/li&amp;gt;
))
}
&amp;lt;div className='d-flex gap-2 text-white lang-active'&amp;gt;
&amp;lt;span className={ 'cursor-pointer ' +(i18n?.language=='en' &amp;amp;&amp;amp; "active")}
onClick={() =&amp;gt; change('en')}&amp;gt;EN&amp;lt;/span&amp;gt;
&amp;lt;span className={ 'cursor-pointer ' +(i18n?.language=='ar' &amp;amp;&amp;amp; "active")}
onClick={() =&amp;gt; change('ar')}&amp;gt;AR&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Create slug using title in React</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Thu, 06 Feb 2025 18:25:50 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/create-slug-using-title-14nf</link>
      <guid>https://forem.com/deepakjaiswal/create-slug-using-title-14nf</guid>
      <description>&lt;p&gt;I have seen some time we are using _id in routing. and we get the data based on _id but it shows our original data id that i have leak. and based on SEO the id is not best way to add in url.&lt;/p&gt;

&lt;p&gt;Like i'm creating a blog detail page based on id it looks bad but when i am using slug based on title. it looks good.&lt;/p&gt;

&lt;p&gt;And the user understand by the url.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getSafeRegexpString(input) {
  return input
    .split("")
    .map((char) =&amp;gt; `\\${char}`)
    .join("");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am using the package &lt;strong&gt;diacritics&lt;/strong&gt; which is remove unnecessary text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { remove as stripAccents} from 'diacritics';
function format(
  input,
  delimiter,
  ignoreInvalid = false
) {
  const harmonized = stripAccents(input).trim().toLowerCase();
  const safeDelimiter = getSafeRegexpString(delimiter);

  if (ignoreInvalid) {
    return harmonized.replace(/\s+/g, delimiter);
  }

  return harmonized
    .replace(new RegExp(`[^a-z0-9\\u0900-\\u097F${safeDelimiter}]+`, "g"), delimiter) // Replace all non-valid caracters by delimiter
    .replace(new RegExp(`${safeDelimiter}+`, "g"), delimiter) // Remove multiple delimiters repetition
    .replace(new RegExp(`^${safeDelimiter}`, "g"), "") // remove delimiter at the beginning
    .replace(new RegExp(`${safeDelimiter}$`, "g"), ""); // remove delimiter at the end
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also put your regex for custom change. I have put [^a-z0-9\u0900-\u097F${safeDelimiter}] for &lt;strong&gt;hindi&lt;/strong&gt; words.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function slugify(
  node,
  options = { delimiter: "-", prefix: "" }
) {
  if (!options.delimiter) options.delimiter = "-";
  if (!options.prefix) options.prefix = "";

  if (!node || typeof node === "boolean") {
    return "";
  }

  const { delimiter, prefix } = options;

  // boolean
  if (typeof node === "boolean") {
    return ""; // not much we can do here
  }

  // string, number
  if (typeof node === "string" || typeof node === "number") {
    const harmonizedPrefix = format(prefix, delimiter, true);
    const harmonizedNode = format(String(node), delimiter);

    if (harmonizedPrefix) {
      return `${harmonizedPrefix}${delimiter}${harmonizedNode}`;
    }

    return harmonizedNode;
  }

  // ReactPortal
  if ("children" in node) {
    return slugify(node.children);
  }

  // ReactElement
  if ("type" in node) return slugify(node.props.children, options);

  // ReactFragment (including array of nodes)
  if (Symbol.iterator in node) {
    return slugify(
      Array.from(node)
        .map((subNode) =&amp;gt; slugify(subNode, { delimiter }))
        .join(delimiter),
      options
    );
  }

  // unhandled case
  return "";
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Astro: Best for business, portfolio and bloging sites</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sun, 19 Jan 2025 19:16:23 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/astro-best-for-business-portfolio-and-bloging-sites-4idc</link>
      <guid>https://forem.com/deepakjaiswal/astro-best-for-business-portfolio-and-bloging-sites-4idc</guid>
      <description>&lt;p&gt;I am writing this post because I see their performance and seo friendly nature.and I'm surprised when see their ratio from others framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Astro powers the world's fastest marketing sites, blogs, e-commerce websites, and more
&lt;/h2&gt;

&lt;p&gt;Astro is a JavaScript web framework optimized for building fast, content-driven websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server-First
&lt;/h2&gt;

&lt;p&gt;Astro improves website performance by rendering components on the server, sending lightweight HTML to the browser with zero unnecessary JavaScript overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content-Driven
&lt;/h2&gt;

&lt;p&gt;Astro was designed to work with your content, no matter where it lives. Load data from your file system, external API, or your favorite CMS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizable
&lt;/h2&gt;

&lt;p&gt;Extend Astro with your favorite tools. Bring your own JavaScript UI components, CSS libraries, themes, integrations, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Core Web Vitals
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Astro Core Web Vitals Passing&lt;/strong&gt;&lt;br&gt;
65%&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gatsby Core Web Vitals Passing&lt;/strong&gt;&lt;br&gt;
44%&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WordPress Core Web Vitals Passing&lt;/strong&gt;&lt;br&gt;
43%&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next.js Core Web Vitals Passing&lt;/strong&gt;&lt;br&gt;
28%&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nuxt Core Web Vitals Passing&lt;/strong&gt;&lt;br&gt;
26%&lt;/p&gt;

&lt;p&gt;Many brands currently using you can on their website &lt;a href="https://astro.build/" rel="noopener noreferrer"&gt;https://astro.build/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>wordpress</category>
      <category>nextjs</category>
      <category>gatsby</category>
    </item>
    <item>
      <title>Create Custom Block in Quill like Video, Link, Banner.</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Mon, 14 Aug 2023 18:09:01 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/create-custom-block-in-quill-like-video-link-banner-1k13</link>
      <guid>https://forem.com/deepakjaiswal/create-custom-block-in-quill-like-video-link-banner-1k13</guid>
      <description>&lt;p&gt;i am creating this post as my experience. sometime we need to create custom block in quill to create block for our need. i create some block.&lt;/p&gt;

&lt;h2&gt;
  
  
  index.html
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="" id="editor-wrapper" (keyup)="keyup($event)" (click)="keyup($event)"&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;button (click)="download()"&amp;gt;Download&amp;lt;/button&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;button (click)="insert()"&amp;gt;Insert Hr&amp;lt;/button&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id="customDropdown" style="display: none;"&amp;gt;
  &amp;lt;!-- Add your dropdown options here --&amp;gt;
  &amp;lt;button&amp;gt;Option 1&amp;lt;/button&amp;gt;
  &amp;lt;button&amp;gt;Option 2&amp;lt;/button&amp;gt;
  &amp;lt;button&amp;gt;Option 3&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  editor.ts
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;declare const Quill: any;
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
declare const quillBetterTable: any;
declare const htmlToPdfmake: any;
declare const pdfMake: any;
import jsPDF from 'jspdf';

Quill.register({
  'modules/better-table': quillBetterTable
}, true);
const Link = Quill.import("formats/link");

const BlockEmbed = Quill.import("blots/block/embed");

class VideoBlot extends BlockEmbed {
  static create(obj:any) {
    console.log(obj)
    let node = super.create(obj?.url?obj?.url:obj);
    let iframe = document.createElement('iframe');
    let con = document.createElement('span');
    con.setAttribute('style', 'display:flex;');
    con.setAttribute('class', 'resize-container');
    con.innerHTML=`
        &amp;lt;button data-size="1" class="re-1"&amp;gt;1x&amp;lt;/button&amp;gt;
        &amp;lt;button data-size="2" class="re-2"&amp;gt;2x&amp;lt;/button&amp;gt;
        &amp;lt;button data-size="3" class="re-3"&amp;gt;3x&amp;lt;/button&amp;gt;
        &amp;lt;button data-size="4" class="re-4"&amp;gt;4x&amp;lt;/button&amp;gt;
    `
    // con.addEventListener('click',(e:any)=&amp;gt;{
    //   node.setAttribute('data-width', 'embed-responsive-'+e.target.dataset.size);
    //   console.log("first",e.target.dataset.size)
    // })

    node.setAttribute('data-width', obj?.size?obj?.size:'embed-responsive-'+3);
    // Set styles for wrapper
    node.setAttribute('class', 'embed-responsive embed-responsive-16by9');
    node.appendChild(con)
    // Set styles for iframe
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('allowfullscreen', 'true');
    iframe.setAttribute('src', obj?.url?obj?.url:obj);
    // Append iframe as child to wrapper
    node.appendChild(iframe);
    return node;
  }

  static value(domNode:any) {
    const url=domNode.getElementsByTagName('iframe')[0].getAttribute('src');
    const size=domNode.getAttribute('data-width');
    return {url,size}
  }

  // format(name:any, value:any) {
  //   // Override the format method to handle your custom attribute
  //   if (name === 'custom-attribute') {
  //     const previousValue = this['domNode'].getAttribute('data-custom-attribute');
  //     if (value) {
  //       this['domNode'].setAttribute('data-custom-attribute', value);
  //     } else {
  //       this['domNode'].removeAttribute('data-custom-attribute');
  //     }
  //     // Use the previousValue as needed
  //   } else {
  //     super.format(name, value);
  //   }
  //   console.log('Previous value:', name,value);
  // }
}
VideoBlot['blotName'] = 'video';
VideoBlot['tagName'] = 'div';

Quill.register(VideoBlot, true);

var CustomLink = Quill.import('formats/link');
CustomLink.sanitize = function(url:any) {
  return url; // Customize the URL sanitization if needed
};

class CustomLinkFormat extends CustomLink {
  static create(value:any) {
    const node = super.create(value.url);
    console.log(value);
    node.setAttribute('data-custom-attribute', value.customAttribute); // Set the custom attribute
    return node;
  }

  static formats(node:any) {
    const format = super.formats(node);
    console.log(node)
    format.customAttribute = node.getAttribute('data-custom-attribute')||'1'; // Get the custom attribute
    return format;
  }
}
Quill.register(CustomLinkFormat, true);

var Inline = Quill.import('blots/inline');

// Define the custom format class
class CustomFormat extends Inline {
  static create(v:any) {
    const node = super.create();
    const d=document.createElement('sup');
    d.classList.add('custom-format');
    d.appendChild(node)
    return d;
  }
}

// Assign a CSS class name to the custom format
CustomFormat['blotName'] = 'highlight';
CustomFormat['tagName'] = 'span';

// Register the custom format with Quill
Quill.register(CustomFormat);


// Extend ListContainer module
// const Block = Quill.import('blots/block');

// class CustomListContainer extends Block {
//   static create(value:any) {
//     const node = super.create(value);
//     node.classList.add('custom-list-container');
//     return node;
//   }
// }

// CustomListContainer['tagName'] = 'div';
// CustomListContainer['allowedChildren'] = [Block, CustomListContainer];
// CustomListContainer['scope'] = Block.scope;
// CustomListContainer['defaultChild'] = 'block';


// // Override the default ListItem module to use the custom list container
// const ListItem = Quill.import('formats/list');

// class CustomListItem extends ListItem {   
//   format(name:any, value:any) {
//     if (name === 'list' &amp;amp;&amp;amp; value) {
//       const isOrdered = value === 'ordered';
//       const CustomContainer:any = isOrdered ? 'OL' : 'UL';
//       const container:any = this['parent'];
//       if (!(container instanceof CustomContainer)) {
//         const newContainer = this['scroll'].create(CustomContainer);
//         container.replaceWith(newContainer);
//         newContainer.appendChild(this['domNode']);
//       }
//     }
//     super.format(name, value);
//   }
// }


import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-rich-editor',
  templateUrl: './rich-editor.component.html',
  styleUrls: ['./rich-editor.component.css']
})
export class RichEditorComponent implements OnInit{
  data:any=`&amp;lt;p&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;`
  quill:any;
  constructor(public sanitizer: DomSanitizer){

  }
  ngOnInit(): void {
    setTimeout(()=&amp;gt;{
      this.initEditor()
    },1000)
    // document.querySelector('.re-1')?.addEventListener('click',()=&amp;gt;{
    //   console.log('sadasa')
    // })

  }

  initEditor(){
    this.quill = new Quill('#editor-wrapper', {
      theme: 'snow',
      modules: {
        toolbar:{
          container:[
          'video',
          'image',
          'link',
          'align',
          'customLink',
          { 'script': 'sub'}, { 'script': 'super' },
          {'list':'ordered'},{'list':'bullet'}
        ],
        handlers:{
          'customLink':(v:any)=&amp;gt;{
            console.log(v)
            this.quill.format('link', {
              url: 'https://example.com',
              customAttribute: 'custom value'
            });
          },
          },

      },
        table: false,  // disable table module
        'better-table': {
          operationMenu: {
            items: {
              unmergeCells: {
                text: 'Another unmerge cells name'
              }
            }
          }
        },
        keyboard: {
          bindings: quillBetterTable.keyboardBindings
        },
      },
    })

    var customDropdown:any = document.getElementById('customDropdown');
    var dropdownOpen = false;

    this.quill.on('text-change', (delta:any, oldDelta:any, source:any)=&amp;gt; {
      console.log(delta,oldDelta,source)
      var range = this.quill.getSelection();
      if (range &amp;amp;&amp;amp; range.length === 0) {
        var cursorPosition = range.index;
        var lineText = this.quill.getText(0, cursorPosition);

        // Define the trigger text or condition to open the dropdown
        var triggerText = '/'; // Example: Open the dropdown when the user types '@dropdown'

        if (lineText.endsWith(triggerText)) {
          if (!dropdownOpen) {
            // Get the bounds of the current cursor position
            var bounds = this.quill.getBounds(range.index);

            // Get the offset position of the Quill editor
            var editorBounds:any = document.getElementById('editor-wrapper')?.getBoundingClientRect();
            var editorOffsetTop = editorBounds.top + window.pageYOffset;
            var editorOffsetLeft = editorBounds.left + window.pageXOffset;

            // Position the dropdown below the cursor, considering the editor offset
            customDropdown.style.left = (bounds.left - editorOffsetLeft) + 'px';
            customDropdown.style.top = (bounds.top - editorOffsetTop + bounds.height) + 'px';
            customDropdown.style.display = 'block';
            dropdownOpen = true;
          }
        } else {
          if (dropdownOpen) {
            // Close the dropdown
            customDropdown.style.display = 'none';
            dropdownOpen = false;
          }
        }
      }
    });

    document.addEventListener('click', function(event) {
      // Close the dropdown if a click event occurs outside the dropdown
      if (!customDropdown.contains(event.target)) {
        customDropdown.style.display = 'none';
        dropdownOpen = false;
      }
    });

  }
  click(x:any){
    console.log(x)
  }

  download(){
   let x=this.quill.root.innerHTML;
  const htmlString = '&amp;lt;ol&amp;gt;&amp;lt;li class="child"&amp;gt;Item 1&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Item 2&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;ol&amp;gt;&amp;lt;li class="chi"&amp;gt;Item 1&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Item 2&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;';

// Replace &amp;lt;ol&amp;gt; tags with &amp;lt;ul&amp;gt; tags for child elements with the class "child"
x= x.replaceAll(/&amp;lt;ol\b([^&amp;gt;]*)&amp;gt;(.*?&amp;lt;li\s+data-list="bullet"&amp;gt;.*?&amp;lt;\/li&amp;gt;.*?)&amp;lt;\/ol&amp;gt;/gi, '&amp;lt;ul $1&amp;gt;$2&amp;lt;/ul&amp;gt;')



    var html = htmlToPdfmake(x);
  // console.log(html)
  var docDefinition = {
    content: [
      html
    ],
    styles:{

    }
  };

  var pdfDocGenerator = pdfMake.createPdf(docDefinition);
  pdfDocGenerator.download()

  // var doc:any = new jsPDF();
  // doc.html(this.quill.root.innerHTML, {
  //   callback: function (docs:any) {
  //     docs.save('quill_content.pdf');
  //   }
  // });

  }

  insert(){
    const range=this.quill.getSelection();
    const is=this.quill.getFormat(range.index,range.length)
    console.log(is)
    if(is.highlight)
    this.quill.format('highlight', false);
    else this.quill.format('highlight', true);
  }

  keyup(event:any){
    console.log(event)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  style.css
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-toggle {
  padding: 10px 15px;
  background-color: #f5f5f5;
  border: 1px solid #ccc;
  border-radius: 4px;
  cursor: pointer;
}

.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  display: none;
  min-width: 160px;
  padding: 5px 0;
  background-color: #fff;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
  z-index: 1;
}

.dropdown-menu.show {
  display: block;
}

.dropdown-item {
  display: block;
  padding: 5px 10px;
  color: #333;
  text-decoration: none;
  transition: background-color 0.3s;
}

.dropdown-item:hover {
  background-color: #f5f5f5;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>react</category>
      <category>angular</category>
      <category>webdev</category>
      <category>html</category>
    </item>
    <item>
      <title>Watchlist application using ReactJS, NodeJS</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sat, 08 Apr 2023 07:08:53 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/watchlist-application-using-reactjs-nodejs-47b8</link>
      <guid>https://forem.com/deepakjaiswal/watchlist-application-using-reactjs-nodejs-47b8</guid>
      <description>&lt;p&gt;today we create watchlist application using &lt;strong&gt;reactjs&lt;/strong&gt;, &lt;strong&gt;nodejs&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;config.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "DB_URL": "mongodb+srv://user:password@cluster0.wb0iyao.mongodb.net/?retryWrites=true&amp;amp;w=majority"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;default.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports.defaultSymbols=[
    {
        symbol:"SYY",
        bid:"sp",
        ask:"sp",
        bidSize:3,
        askSize:4,
        volume:5,
        description:"Fixed wrong interpolated variables with node-sass/Hugo"
    },
    {
        symbol:"KJJ",
        bid:"d",
        ask:"d",
        bidSize:3,
        askSize:4,
        volume:5,
        description:"Fixed wrong interpolated variables with node-sass/Hugo"
    },
    {
        symbol:"LLL",
        bid:"ru",
        ask:"ru",
        bidSize:3,
        askSize:4,
        volume:5,
        description:"Fixed wrong interpolated variables with node-sass/Hugo"
    },
    {
        symbol:"NHD",
        bid:"nd",
        ask:"nd",
        bidSize:2,
        askSize:6,
        volume:0,
        description:"Fixed wrong interpolated variables with node-sass/Hugo"
    },
    {
        symbol:"QWA",
        bid:"ts",
        ask:"ts",
        bidSize:7,
        askSize:4,
        volume:1,
        description:"Fixed wrong interpolated variables with node-sass/Hugo"
    }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;watchlist.controller.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const WatchListModel = require("../models/WatchList")

module.exports.getWatchLists=async(req,res,next)=&amp;gt;{
    try {
        const watchLists=await WatchListModel.find({});
        res.status(200).send(watchLists);
    } catch (error) {
        next(error)
    }
}

module.exports.addSymbol=async(req,res,next)=&amp;gt;{
    try {
        const {symbol,bid,ask,bidSize,askSize,volume}=req.body;
        const symbolObj={
            symbol,
            bid,
            ask,
            bidSize,
            askSize,
            volume
        }
        const watchList=await WatchListModel.findOneAndUpdate({
            _id: req.params.id
        },{
          $push:{
            symbols:symbolObj
          }
        },{new:true})
        res.status(200).send(watchList);
    } catch (error) {
        next(error)
    }
}

module.exports.updateSymbol=async(req,res,next)=&amp;gt;{
    try {
        const {symbolId,symbol,bid,ask,bidSize,askSize,volume,description}=req.body;
        const symbolObj={
            symbol,
            bid,
            ask,
            bidSize,
            askSize,
            volume,description
        }
        let watchList=await WatchListModel.findOne({
            _id: req.params.id
        })
        const index=watchList?.symbols.findIndex((symbol)=&amp;gt;symbol?._id?.toString()==symbolId);
        watchList.symbols[index]=symbolObj;
        watchList=await WatchListModel.findOneAndUpdate({_id: req.params.id},{$set:{
            symbols:watchList?.symbols
        }},{new:true})
        res.status(200).send(watchList);
    } catch (error) {
        next(error)
    }
}

module.exports.removeSymbol=async(req,res,next)=&amp;gt;{
    try {
        const {symbolId}=req.body
        let watchList=await WatchListModel.findOne({
            _id: req.params.id
        })
        const updatedSymbols=watchList?.symbols.filter((symbol)=&amp;gt;symbol?._id?.toString()!==symbolId);
        watchList=await WatchListModel.findOneAndUpdate({_id: req.params.id},{$set:{
            symbols:updatedSymbols
        }},{new:true})
        res.status(200).send(watchList);
    } catch (error) {
        next(error)
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;createDefaultwatchlist.middleware.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const WatchListModel = require("../models/WatchList")
const symbols=require('../constants/defaults')

module.exports.createDefaultWatchList=async(req,res,next)=&amp;gt;{
    try {
        let watchList=await WatchListModel.findOne({});
        console.log(watchList)
        if(!watchList){
            watchList=new WatchListModel({symbols:symbols.defaultSymbols});
            watchList=await watchList.save();
            next(watchList)
        }
    } catch (error) {
        next(error)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;error.middleware.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
module.exports=async(err,req,res)=&amp;gt;{
    try {
        if(err){
            return res.status(500).send({status:500,message:err})
        }
    } catch (error) {
        console.log(error.body);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;validateObjectId.middleware.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose= require("mongoose")

module.exports.validateObjectId=(req,res,next)=&amp;gt;{
    try {
        if(!mongoose.Types.ObjectId.isValid(req.params.id))
            return res.status(400).send({message:"Invalid Id",status:400});
        next(); 
    } catch (error) {
        next(error)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;watchlist.model.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose=require('mongoose');

const {Schema,model}=mongoose;

const watchlistSchema=new Schema({
    symbols:[
        {
            symbol:{
                type:String,
                required: true,
                index:true
            },
            bid:{
                type:String,
                default:''
            },
            ask:{
                type:String,
                default:''
            },
            bidSize:{
                type:Number,
                default:null
            },
            askSize:{
                type:Number,
                default:null
            },
            volume:{
                type:Number,
                default:null
            },
            description:{
                type:String,
                default: ""
            }
        }
    ]
})

const WatchListModel=model('watchlist',watchlistSchema);

module.exports=WatchListModel;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;watchlist.route.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express=require('express');
const { createDefaultWatchList } = require("../middlewares/createDefaultWatchList.middleware");
const WatchListModel = require("../models/WatchList.model");
const router=express.Router();
const symbols=require('../constants/defaults');
const { addSymbol, getWatchLists, removeSymbol, updateSymbol } = require("../controllers/watchlist.controller");
const { validateObjectId } = require('../middlewares/validateObjectId.middleware');

router.get('',getWatchLists);

router.post('/create-default',createDefaultWatchList);

router.post('/add-symbol/:id',validateObjectId,addSymbol);

router.patch('/update-symbol/:id',validateObjectId,updateSymbol);

router.patch('/remove-symbol/:id',validateObjectId,removeSymbol);

module.exports=router;


(async ()=&amp;gt;{
    let watchList=await WatchListModel.findOne({});
    if(!watchList){
        watchList=new WatchListModel({symbols:symbols.defaultSymbols});
        watchList=await watchList.save();
        console.log('default watch list created')
    }
})()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;connection.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose=require('mongoose');
const config=require('config');

const DB_URL=config.get('DB_URL');

module.exports=mongoose.connect(DB_URL).then((conn)=&amp;gt;{
    console.log(`Database connected on mongo server ${DB_URL}`);   
}).catch((err)=&amp;gt;{
    console.log(`Database Error -&amp;gt;:  ${err}`);  
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;app.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express=require('express');
const cors=require('cors');

require('./services/connection');
const errorMiddleware=require('./middlewares/error.middleware');
const watchListRouter=require('./routes/watchlist.route')

const app=express();
const PORT=process.env.PORT|| 8000;
//middlewares
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use(cors());
//routes of app
app.use('/api/v1/watchlist',watchListRouter);
//global error middleware 

app.use(errorMiddleware)

app.listen(PORT,()=&amp;gt;{
    console.log(`server is running on the port ${PORT}`)
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;package.json&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1",
    "start": "node app.js",
    "dev": "nodemon app.js"
  },
  "keywords": [],
  "author": "Sandeep Jaiswal",
  "license": "MIT",
  "dependencies": {
    "config": "^3.3.9",
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "mongoose": "^7.0.3"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Header.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'

const Header = () =&amp;gt; {
    return (
        &amp;lt;div className="container-fluid bg-primary"&amp;gt;
            &amp;lt;nav className="navbar navbar-expand-lg bg-body-tertiary"&amp;gt;
                &amp;lt;div className="container-fluid"&amp;gt;
                    &amp;lt;a className="navbar-brand text-white fw-bold" href="#"&amp;gt;Watchlist&amp;lt;/a&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/nav&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}

export default Header
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;UpdateWatch.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react'

const UpdateWatch = ({ data, updateSymbol }) =&amp;gt; {
  const [form, setForm] = useState({
    symbolId: '', symbol: '', bid: '', ask: '', bidSize: null, askSize: null, volume: null, description: ''
  })
  useEffect(() =&amp;gt; {
    setForm({ symbolId: data?._id, symbol: data?.symbol,
       bid: data?.bid, ask: data?.ask, bidSize: data?.bidSize||0,
        askSize: data?.askSize||0 ,volume:data?.volume||0,description:data?.description});
  }, [data?._id])

  const change = (event) =&amp;gt; {
    const { name, value } = event.target;
    setForm({ ...form, [name]: value })
  }

  const submit = () =&amp;gt; {
    updateSymbol(form);
    setForm({
      symbolId: '', symbol: '', bid: '', ask: '', bidSize: 0, askSize: 0, volume: 0, description: ''
    })
  }
  return (
    &amp;lt;div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"&amp;gt;
      &amp;lt;div class="modal-dialog"&amp;gt;
        &amp;lt;div class="modal-content"&amp;gt;
          &amp;lt;div class="modal-header"&amp;gt;
            &amp;lt;h1 class="modal-title fs-5" id="exampleModalLabel"&amp;gt;Update Symbol&amp;lt;/h1&amp;gt;
            &amp;lt;button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"&amp;gt;&amp;lt;/button&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div class="modal-body"&amp;gt;
            &amp;lt;form&amp;gt;
              &amp;lt;div class="mb-3"&amp;gt;
                &amp;lt;label for="recipient-name" class="col-form-label"&amp;gt;Symbol:&amp;lt;/label&amp;gt;
                &amp;lt;input type="text" name="symbol" value={form.symbol} onChange={(e) =&amp;gt; change(e)} class="form-control" id="recipient-name" /&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div class="mb-3"&amp;gt;
                &amp;lt;label for="recipient-name" class="col-form-label"&amp;gt;Bid:&amp;lt;/label&amp;gt;
                &amp;lt;input type="text" name="bid" value={form.bid} onChange={(e) =&amp;gt; change(e)} class="form-control" id="recipient-name" /&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div class="mb-3"&amp;gt;
                &amp;lt;label for="recipient-name" class="col-form-label"&amp;gt;ask:&amp;lt;/label&amp;gt;
                &amp;lt;input type="text" name="ask" value={form.ask} onChange={(e) =&amp;gt; change(e)} class="form-control" id="recipient-name" /&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div class="mb-3"&amp;gt;
                &amp;lt;label for="recipient-name" class="col-form-label"&amp;gt;Bid Size:&amp;lt;/label&amp;gt;
                &amp;lt;input type="number" name="bidSize" value={form.bidSize} onChange={(e) =&amp;gt; change(e)} class="form-control" id="recipient-name" /&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div class="mb-3"&amp;gt;
                &amp;lt;label for="recipient-name" class="col-form-label"&amp;gt;Ask Size:&amp;lt;/label&amp;gt;
                &amp;lt;input type="number" name="askSize" value={form.askSize} onChange={(e) =&amp;gt; change(e)} class="form-control" id="recipient-name" /&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div class="mb-3"&amp;gt;
                &amp;lt;label for="recipient-name" class="col-form-label"&amp;gt;Volume:&amp;lt;/label&amp;gt;
                &amp;lt;input type="number" name="volume" value={form.volume} onChange={(e) =&amp;gt; change(e)} class="form-control" id="recipient-name" /&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div class="mb-3"&amp;gt;
                &amp;lt;label for="recipient-name" class="col-form-label"&amp;gt;Description:&amp;lt;/label&amp;gt;
                &amp;lt;input type="text" name="description" value={form.description} onChange={(e) =&amp;gt; change(e)} class="form-control" id="recipient-name" /&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/form&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div class="modal-footer"&amp;gt;
            &amp;lt;button type="button" class="btn btn-secondary" data-bs-dismiss="modal"&amp;gt;Close&amp;lt;/button&amp;gt;
            &amp;lt;button type="button" class="btn btn-primary" data-bs-dismiss="modal" onClick={() =&amp;gt; submit()}&amp;gt; Update&amp;lt;/button&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}

export default UpdateWatch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;watchlist.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useContext, useState } from 'react'
import WatchListContext from "../contexts/WatchListContext";
import { addSymbols, removeSymbols, updateSymbols } from "../services/watchList.service";
import UpdateWatch from "./common/UpdateWatch";

const WatchList = () =&amp;gt; {
    const [watchlist, setWatchlist] = useContext(WatchListContext);
    const [updateObject,setUpdateObject]=useState({});
    const [selectedSymbol,setSelectedSymbol]=useState([])
    const addSymbol = async (event) =&amp;gt; {
        if (event.keyCode === 13) {
            const res = await addSymbols(watchlist?._id, { symbol: event.target.value });
            setWatchlist(res.data);
            event.target.value = '';
        }
    }

    const removeSymbol = async (symbolId) =&amp;gt; {
            const res = await removeSymbols(watchlist?._id, { symbolId });
            setWatchlist(res.data);
    }

    const updateSymbol = async (data) =&amp;gt; {
        const res = await updateSymbols(watchlist?._id, data)
        setWatchlist(res.data);
    }
    const toggleSelect=(symbol)=&amp;gt;{
        const check=selectedSymbol.find(s=&amp;gt;s?._id===symbol?._id)
        if(check){
            let s=selectedSymbol.filter(sym=&amp;gt;sym?._id!==symbol?._id)
            setSelectedSymbol(s);
        }else{
            let s=[...selectedSymbol,symbol]
            setSelectedSymbol(s);
        }
    }
    return (
        &amp;lt;div&amp;gt;
            &amp;lt;div className="p-4"&amp;gt;
                &amp;lt;div className="row"&amp;gt;
                    &amp;lt;div className="col-3 fs-2"&amp;gt;
                        Quote Details
                    &amp;lt;/div&amp;gt;
                    &amp;lt;div className="col-9"&amp;gt;
                        {selectedSymbol?.length ? 
                            selectedSymbol?.map((s)=&amp;gt;(
                                &amp;lt;div key={s?._id}&amp;gt;
                                    &amp;lt;h5&amp;gt;{s?.symbol}&amp;lt;/h5&amp;gt;
                                    &amp;lt;p&amp;gt;{s?.description}&amp;lt;/p&amp;gt;
                                &amp;lt;/div&amp;gt;
                            )
                        ):"No Any row selected"}
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="border"&amp;gt;
                    &amp;lt;div className="bg-light p-2 fw-bold"&amp;gt;My Watchlist&amp;lt;/div&amp;gt;
                    &amp;lt;table className="table table-bordered"&amp;gt;
                        &amp;lt;thead&amp;gt;
                            &amp;lt;tr&amp;gt;
                                &amp;lt;th scope="col"&amp;gt;&amp;lt;/th&amp;gt;
                                &amp;lt;th scope="col"&amp;gt;Bid&amp;lt;/th&amp;gt;
                                &amp;lt;th scope="col"&amp;gt;Ask&amp;lt;/th&amp;gt;
                                &amp;lt;th scope="col"&amp;gt;Bid Size&amp;lt;/th&amp;gt;
                                &amp;lt;th scope="col"&amp;gt;Ask Size&amp;lt;/th&amp;gt;
                                &amp;lt;th scope="col"&amp;gt;Volume&amp;lt;/th&amp;gt;
                                &amp;lt;th scope="col"&amp;gt;Action&amp;lt;/th&amp;gt;
                            &amp;lt;/tr&amp;gt;
                        &amp;lt;/thead&amp;gt;
                        &amp;lt;tbody&amp;gt;
                        {watchlist?.symbols.map((symbol) =&amp;gt; (
                        &amp;lt;tr key={symbol?._id} onClick={()=&amp;gt;toggleSelect(symbol)} className={selectedSymbol?.find(s=&amp;gt;s?._id===symbol?._id)?'table-success':''}&amp;gt;
                        &amp;lt;th scope="row"&amp;gt;{symbol?.symbol}&amp;lt;/th&amp;gt;
                        &amp;lt;td&amp;gt;{symbol?.bid}&amp;lt;/td&amp;gt;
                        &amp;lt;td&amp;gt;{symbol?.ask}&amp;lt;/td&amp;gt;
                        &amp;lt;td&amp;gt;{symbol?.bidSize}&amp;lt;/td&amp;gt;
                        &amp;lt;td&amp;gt;{symbol?.askSize}&amp;lt;/td&amp;gt;
                        &amp;lt;td&amp;gt;{symbol?.volume}&amp;lt;/td&amp;gt;
                        &amp;lt;td&amp;gt;
                            &amp;lt;div className="d-flex justify-content-around"&amp;gt;
                            &amp;lt;button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo" onClick={()=&amp;gt;setUpdateObject(symbol)}&amp;gt;Edit&amp;lt;/button&amp;gt;
                            &amp;lt;button className="btn btn-danger" onClick={()=&amp;gt;removeSymbol(symbol?._id)}&amp;gt;Delete&amp;lt;/button&amp;gt;
                            &amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;
                    &amp;lt;/tr&amp;gt;    
                    ))}

                        &amp;lt;/tbody&amp;gt;
                    &amp;lt;/table&amp;gt;
                    &amp;lt;div className="bg-light p-1 w-100" style={{ height: 40 }}&amp;gt;
                        Add Symbol &amp;lt;input className="ms-2 rounded" placeholder="" onKeyUp={(e) =&amp;gt; addSymbol(e)} /&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;UpdateWatch data={updateObject} updateSymbol={updateSymbol}/&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}

export default WatchList
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;watchlist.service.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { toast } from "react-toastify";

const { http, URL } = require("./http.service")


export const getWatchList = async () =&amp;gt; {
    try {
        const res = await http.get(URL + '/watchlist');
        return res;
    } catch (error) {
        handleError(error);
    }
}

export const addSymbols = async (watchListId,payload) =&amp;gt; {
    try {
        const res = await http.post(URL + '/watchlist/add-symbol/'+watchListId, payload);
        return res;
    } catch (error) {
        handleError(error);
    }
}

export const removeSymbols = async (watchListId, payload) =&amp;gt; {
    try {
        const res = await http.patch(URL +'/watchlist/remove-symbol/' + watchListId, payload);
        return res;
    } catch (error) {
        handleError(error);
    }
}

export const updateSymbols = async (watchListId, payload) =&amp;gt; {
    try {
        const res = await http.patch(URL +'/watchlist/update-symbol/' + watchListId, payload);
        return res;
    } catch (error) {
        handleError(error);
    }
}

export const isLogged = () =&amp;gt; {
    const token = localStorage.getItem('token');
    return token ? true : false;
}

export const logoutUser = () =&amp;gt; {
    localStorage.removeItem('token');
}

export const getToken = () =&amp;gt; {
    return localStorage.getItem('token');
}

export const handleError = (error) =&amp;gt; {
    toast.error(error?.message)
}

export const setCredentials=(token)=&amp;gt;{
    http.defaults.headers.common['x-auth-token'] = token;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;App.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from "react";
import './App.css';
import WatchList from "./components/WatchList";
import WatchListContext from "./contexts/WatchListContext";
import { getWatchList } from "./services/watchList.service";
import Header from "./components/common/Header";
import Loader from "./components/common/Loader";

function App() {
  const [watchlist,setWatchlist]=useState();
  const [isLoading,setIsLoading]=useState(false);

  useEffect(()=&amp;gt;{
    getWatchListData()
  },[]);

  const getWatchListData=async ()=&amp;gt;{
    setIsLoading(true)
    const result=await getWatchList();
    if(result.status ===200 ){
      setWatchlist(result?.data?.[0])
      setIsLoading(false)
    }else{
      setIsLoading(false)
    }
  }

  return (
    &amp;lt;WatchListContext.Provider value={[watchlist,setWatchlist]}&amp;gt;
         &amp;lt;Header /&amp;gt;
         {isLoading?&amp;lt;Loader /&amp;gt;:&amp;lt;WatchList /&amp;gt;}
    &amp;lt;/WatchListContext.Provider&amp;gt;
  );
}

export default App;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this is not of the complete code if you have any doubt regarding this comment in this post. I give the answer as soon as possible. thank you for reading my post.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TINYMCE Editor with angular</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sat, 18 Mar 2023 06:14:59 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/tinymce-editor-with-angular-1cd3</link>
      <guid>https://forem.com/deepakjaiswal/tinymce-editor-with-angular-1cd3</guid>
      <description>&lt;p&gt;&lt;strong&gt;tinymce&lt;/strong&gt; editor is paid editor to use in our application. tinymce has many toolbar, plugins, and events to use in our application. today we add in our angular app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup and installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NgModule } from '@angular/core';

import 'tinymce';
import 'tinymce/themes/modern';
import 'tinymce/plugins/table';
import 'tinymce/plugins/link';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { EditorModule } from '@tinymce/tinymce-angular';


import { TinyEditorComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule, EditorModule ],
  declarations: [ TinyEditorComponent ],
  providers: [],
  bootstrap:    [ TinyEditorComponent ]
})
export class AppModule { }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup editor configuration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  Component,
  AfterViewInit,
  EventEmitter,
  OnDestroy,
  Input,
  Output,
} from '@angular/core';

declare var tinymce: any;

@Component({
  selector: 'tinymce-editor',
  template: `&amp;lt;textarea id="editor"&amp;gt;&amp;lt;/textarea&amp;gt;`,
})
export class TinyEditorComponent implements AfterViewInit, OnDestroy {
  @Output() onEditorContentChange = new EventEmitter();

  editor;

  ngAfterViewInit() {
    tinymce.init({
      selector: '#editor',
      plugins: ['link', 'table'],
      skin_url: 'assets/skins/lightgray',
      setup: (editor) =&amp;gt; {
        this.editor = editor;
        editor.on('keyup change', () =&amp;gt; {
          const content = editor.getContent();
          this.onEditorContentChange.emit(content);
        });
      },
    });
  }

  ngOnDestroy() {
    tinymce.remove(this.editor);
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add editor event
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ngAfterViewInit() {
    tinymce.init({
      selector: '#local-upload',
      plugins: 'image code',
      toolbar: 'undo redo | image code',

      /* we override default upload handler to simulate successful upload*/
      images_upload_handler: function (blobInfo, success, failure) {
        setTimeout(function () {
          /* no matter what you upload, we will turn it into TinyMCE logo :)*/
          success('http://moxiecode.cachefly.net/tinymce/v9/images/logo.png');
        }, 2000);
      },
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hide toolabr &amp;amp; menubar
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Add domain in tinymce cloud
&lt;/h2&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Use axios as better practice in ReactJS</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Tue, 14 Feb 2023 03:40:56 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/use-axios-as-better-practice-in-reactjs-2m6b</link>
      <guid>https://forem.com/deepakjaiswal/use-axios-as-better-practice-in-reactjs-2m6b</guid>
      <description>&lt;p&gt;in this post i explain use axios as in &lt;strong&gt;ReactJS&lt;/strong&gt; as better practice.you all kown very well axios handle http request in single promise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use axios as http
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from 'axios';

export let URL="http://localhost:5000/api/v1";
export let URL_PROFILE="http://localhost:5000/uploads/avatar/";
export let URL_POST="http://localhost:5000/uploads/posts/";
export let AUTH_TOKEN=localStorage.getItem('token')||'';

axios.defaults.baseURL = URL;
axios.defaults.headers.common['x-auth-token'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';


export const http=axios;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and use http in your services like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { http, URL } from "./http.service";
import { errorHandler } from "./error.service";

export const getAllTags=async ()=&amp;gt;{
    try {
        let resp=await http.get(URL+'/tag/all/tags')
        return resp;
    } catch (error) {
        errorHandler(error)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it is better practice to use axios in your application&lt;br&gt;
and when you change your default token like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { http} from "./http.service";
export const setToken=(token)=&amp;gt;{
  axios.defaults.headers.common['x-auth-token'] = token;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  use error handler
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { toast } from "react-toastify"

export const errorHandler=(error)=&amp;gt;{
   if(error.message==="Network Error" &amp;amp;&amp;amp; error.status===500){
        toast.error(error.message)
   }
   toast.error(error?.response?.data?.message)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think you better understanding of axios better practice to use. thank you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Convert Canvas To Image | Use with react-image-crop</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Fri, 20 Jan 2023 19:47:29 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/convert-canvas-to-image-4l1j</link>
      <guid>https://forem.com/deepakjaiswal/convert-canvas-to-image-4l1j</guid>
      <description>&lt;p&gt;sometime we can show data source of image show in canvas do activity like graphics design or like crop image then we need to convert canvas to image. in this example we crop a image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const TO_RADIANS = Math.PI / 180;
export function getCroppedImg(image, crop, fileName) {
    const canvas = document.createElement("canvas");
    let scale = 1;
    let rotate = 0;
    const ctx = canvas.getContext('2d')

    if (!ctx) {
      throw new Error('No 2d context')
    }

    const scaleX = image.naturalWidth / image.width
    const scaleY = image.naturalHeight / image.height
    const pixelRatio = window.devicePixelRatio
    canvas.width = Math.floor(crop.width * scaleX * pixelRatio)
    canvas.height = Math.floor(crop.height * scaleY * pixelRatio)
    ctx.scale(pixelRatio, pixelRatio)
    ctx.imageSmoothingQuality = 'high'
    const cropX = crop.x * scaleX
    const cropY = crop.y * scaleY

    const rotateRads = rotate * TO_RADIANS
    const centerX = image.naturalWidth / 2
    const centerY = image.naturalHeight / 2
    ctx.save()
    ctx.translate(-cropX, -cropY)
    ctx.translate(centerX, centerY)
    ctx.rotate(rotateRads)
    ctx.scale(scale, scale)
    ctx.translate(-centerX, -centerY)
    ctx.drawImage(
      image,
      0,
      0,
      image.naturalWidth,
      image.naturalHeight,
      0,
      0,
      image.naturalWidth,
      image.naturalHeight,
    )
    return new Promise((resolve, reject) =&amp;gt; {
      canvas.toBlob(blob =&amp;gt; {
        blob.name = fileName;
        resolve(blob);
      }, 'image/jpeg', 1);
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this is main function to get image file from image ref&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const save = async () =&amp;gt; {
    setIsLoading(true)
    let image = document.getElementById('crop-image')
    let file = await getCroppedImg(image, crop, filename);
    await changeAvatar(file);
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the crop has some object&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  {
    unit: "%",
    width: 30,
    height: 30,
    aspect: 1 / 1
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when we use any crop library like &lt;strong&gt;react-image-crop&lt;/strong&gt; it gives crop values of object then need to how to get cropped image then it helps to find exact image as your need.&lt;/p&gt;

&lt;p&gt;In this example we sure to understand how we convert canvas as in image. and use it. thank you.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>angular</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Extract All Exif Data from media files in ReactJS and Nodejs Using Exiftool library</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sat, 23 Jul 2022 10:40:00 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/extract-all-exif-data-from-media-files-in-reactjs-and-nodejs-4980</link>
      <guid>https://forem.com/deepakjaiswal/extract-all-exif-data-from-media-files-in-reactjs-and-nodejs-4980</guid>
      <description>&lt;p&gt;I am making this post to capture all meta data from file using exiftools in nodejs.&lt;/p&gt;

&lt;h2&gt;
  
  
  what is exif data
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Exchangeable image file data format is a standard that specifies formats for images file, sound, and ancillary tags used by digital cameras, scanners and other systems handling image and sound files recorded by digital cameras.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  backend
&lt;/h2&gt;

&lt;p&gt;these library use and install&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;express&lt;/li&gt;
&lt;li&gt;mongoose&lt;/li&gt;
&lt;li&gt;cors&lt;/li&gt;
&lt;li&gt;node-exiftool&lt;/li&gt;
&lt;li&gt;dist-exiftool&lt;/li&gt;
&lt;li&gt;multer&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  package.json
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "metadata-extractor",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "dist-exiftool": "^10.53.0",
    "express": "^4.18.1",
    "mongoose": "^6.4.6",
    "multer": "^1.4.5-lts.1",
    "node-exiftool": "^2.3.0"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  server.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express=require('express');
const cors=require('cors');

const metaDataRoute=require('./routes/metadata.route')
require('./services/connection');
const app=express();
const PORT=process.env.PORT|5000;

app.use(express.json());
app.use(cors());
app.use(express.static(__dirname+"./public"));

app.use('/api',metaDataRoute);

app.listen(PORT,()=&amp;gt;{
    console.log(`server is listening on port ${PORT}`)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  metadata.controller.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const exiftoolBin = require('dist-exiftool');
const exiftool =  require('node-exiftool');
const fs = require('fs');
const path = require('path');
const MetaDataModel=require("../models/meta.models");

module.exports.createMetaData=(req,res,next)=&amp;gt;{
    try {
        if(!req.file){
            return res.status(404).send({message:"File Not Found",status:404})
        }
    const PHOTO_PATH = path.join(__dirname, '../public/upload/'+req.file.filename)
    const rs = fs.createReadStream(PHOTO_PATH)
    const ep = new exiftool.ExiftoolProcess(exiftoolBin)
    ep.open()
      .then(() =&amp;gt; ep.readMetadata(rs, ['-File:all']))
      .then(async (result) =&amp;gt; {
          let metadata=new MetaDataModel({
              fileName:req.file.filename,
              originalName:req.file.originalname,
              size:req.file.size,
              information:result.data[0]
              });
          metadata=await metadata.save();
          return res.send(metadata);
    })
    .then(() =&amp;gt; ep.close(), () =&amp;gt; ep.close())
    .catch(console.error);

    } catch (error) {
        next(error);
    }
}

module.exports.getAllMetaData=async (req,res,next)=&amp;gt;{
    try {
        let allData=await MetaDataModel.find({}).sort({createdAt:-1});
        res.send(allData)
    } catch (error) {
        next(error)
    }
}

module.exports.deleteMetaData=async (req,res,next)=&amp;gt;{
    try {
        let metadata=await MetaDataModel.findOneAndDelete({_id:req.params.id});
        if(!metadata){
            return res.status(400).send({message:"Metadata not exist"})
        }
        const PHOTO_PATH = path.join(__dirname, '../public/upload/'+metadata.fileName)
        fs.unlink(PHOTO_PATH,(err,data)=&amp;gt;{
            if(err){

            }
        })
        res.send({message:"Deleted Successfully",status:200});
    } catch (error) {
        next(error)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  middlewares/uploadFile.middleware.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const multer=require('multer');
const path=require('path');

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, path.join(__dirname,'../public/upload/'))
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
    cb(null, file.fieldname + '-'+uniqueSuffix+'-' +file.originalname)
  }
})

const upload = multer({ storage: storage }).single('file');

module.exports.uploadFile=(req,res,next)=&amp;gt;{
try {
      upload(req, res, function (err) {
    if (err instanceof multer.MulterError) {
        return res.status(400).send({message:"Error: "+err,status:400})
    } else if (err) {
       return res.status(400).send({message:"Error: "+err,status:400})
    }
    next()
  })
} catch (error) {
    next(error);
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  middlewres/validateObjectId.middleware.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose=require('mongoose');

module.exports.validateObjectId=(req,res,next)=&amp;gt;{
    try {
        if(!mongoose.Types.ObjectId.isValid(req.params.id)){
            return res.status(400).send({message:"Invalid Id"});
        }
        next()
    } catch (error) {
        next(error)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  metadata.model.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose=require('mongoose');

const {Schema,model}=mongoose;

const metaDataSchema=new Schema({
    fileName:{
        type:String,
        required:true,
        index:true
    },
    originalName:{
        type:String
    },
    size:{
        type:Number
    },
    information:{
        type:Object
    }
},{timestamps:true});

const MetaDataModel=model('metadata',metaDataSchema);

module.exports=MetaDataModel;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  metadata.route.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express=require('express');

const router=express.Router();

const metaDataController=require("../controllers/metadata.controller");
const {uploadFile}=require("../middlewares/uploadFile.middleware");
const {validateObjectId}=require('../middlewares/validateObjectId.middleware')

router.post('/metadata',uploadFile, metaDataController.createMetaData);

router.get('/metadata',metaDataController.getAllMetaData);

router.delete('/metadata/:id',validateObjectId,metaDataController.deleteMetaData);

module.exports=router
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  services/connection.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose=require('mongoose')

module.exports=mongoose.connect('mongodb://localhost:27017/metadata').then((conn)=&amp;gt;{
    console.log('Database Connected');
}).catch((err)=&amp;gt;{
    console.log("Database not connected");
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;h2&gt;
  
  
  App.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {useState,useEffect} from 'react';
import './App.css';
import Accordian from './Accordian'
import axios from 'axios';

function App() {
  const [file,setFile]= useState();
  const [metaData,setMetadata]=useState([]);
  const BASE_URL='http://localhost:5000/api';
  useEffect(() =&amp;gt; {
    getAllData();
  }, [])

  const getAllData=async()=&amp;gt;{
    let data=await axios.get(BASE_URL+'/metadata');
    setMetadata(data?.data);
    console.log(data.data)
  }

  const handleSubmit=async(event)=&amp;gt;{
    event.preventDefault();
    let formData=new FormData();
    formData.append("file",file);
    let uploadMetaData=await axios.post(BASE_URL+'/metadata',formData);
    if(uploadMetaData){
      let metadata=[uploadMetaData.data,...metaData];
      setMetadata(metadata);
      setFile()
    }
  }

  const deleteMetaData=async(id)=&amp;gt;{
    let doc=await axios.delete(BASE_URL+'/metadata/'+id);
    if(doc){
      let metadata=metaData.filter(m=&amp;gt;m._id!==id);
      setMetadata(metadata);
    }
  }
  return (
    &amp;lt;&amp;gt;
    &amp;lt;div className="page-header mt-5"&amp;gt;
       &amp;lt;h1&amp;gt;Extract File Upload Control &amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;


&amp;lt;div className="container mt-5"&amp;gt;
    &amp;lt;div className=""&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div className="col-md-6 mx-auto mt-4"&amp;gt;
        &amp;lt;form onSubmit={handleSubmit} method="post" encType="multipart/form-data"&amp;gt;
            &amp;lt;input type="file" id="files" onChange={(e)=&amp;gt;setFile(e.target.files[0])} className="form-control" name="files" /&amp;gt;
            &amp;lt;p className="mt-4"&amp;gt;
                &amp;lt;input type="submit" value="Upload File" disabled={!file} className="btn btn-primary" /&amp;gt;
            &amp;lt;/p&amp;gt;
        &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div className="col-md-4"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;div className="col-md-6 mx-auto"&amp;gt;
&amp;lt;div className="accordion" id="accordionExample"&amp;gt;
      {
        metaData.length&amp;gt;0 &amp;amp;&amp;amp; metaData.map((data,index)=&amp;gt;(
      &amp;lt;div key={index}&amp;gt;    
     &amp;lt;Accordian data={data} deleteMetaData={deleteMetaData}&amp;gt;&amp;lt;/Accordian&amp;gt;
&amp;lt;/div&amp;gt;

        ))
      }
     &amp;lt;/div&amp;gt; 
&amp;lt;/div&amp;gt;
&amp;lt;/&amp;gt;
  );
}

export default App;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Accordian.jsx
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React,{useState} from 'react'

const Accordian = ({data,deleteMetaData}) =&amp;gt; {
    const [show,setShow]=useState(false);

    const deleteMeta=(id)=&amp;gt;{
      setShow(false);
      deleteMetaData(id);
    }

  return (
    &amp;lt;div className="accordion-item"&amp;gt;
    &amp;lt;h2 className="accordion-header" id={'#heading'+data.fileName}&amp;gt;
      &amp;lt;button className="accordion-button" onClick={()=&amp;gt;setShow(!show)} type="button"&amp;gt;
        {data?.originalName}
      &amp;lt;/button&amp;gt;
    &amp;lt;/h2&amp;gt;
    {show &amp;amp;&amp;amp;&amp;lt;div  className="accordion-collapse"  &amp;gt;
      &amp;lt;div className="accordion-body"&amp;gt;
        &amp;lt;pre style={{overflowWrap:'break-word'}}&amp;gt;
           {JSON.stringify(data.information,null,2)}
        &amp;lt;/pre&amp;gt;
        &amp;lt;div className="text-end"&amp;gt;
        &amp;lt;button className="btn btn-danger btn-sm " onClick={()=&amp;gt;deleteMeta(data?._id)}&amp;gt;Delete&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;}
  &amp;lt;/div&amp;gt;
  )
}

export default Accordian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  App.css
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h1{
  text-align: center;
}    
p{
text-align: center; margin-top: 20px; 
}       

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  response
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "SourceFile": "C:/Users/DELL/AppData/Local/Temp/wrote-93199.data",
  "ExifToolVersion": 10.53,
  "Model": "Redmi 5A",
  "ModifyDate": "2019:10:01 16:12:33",
  "YCbCrPositioning": "Centered",
  "ISO": 100,
  "ExposureProgram": "Not Defined",
  "FNumber": 2,
  "ExposureTime": "1/117",
  "SensingMethod": "One-chip color area",
  "SubSecTimeDigitized": "033060",
  "SubSecTimeOriginal": "033060",
  "SubSecTime": "033060",
  "FocalLength": "2.6 mm",
  "Flash": "Off, Did not fire",
  "MeteringMode": "Center-weighted average",
  "SceneCaptureType": "Standard",
  "InteropIndex": "R98 - DCF basic file (sRGB)",
  "InteropVersion": "0100",
  "FocalLengthIn35mmFormat": "3 mm",
  "CreateDate": "2019:10:01 16:12:33",
  "ExifImageHeight": 2592,
  "WhiteBalance": "Auto",
  "DateTimeOriginal": "2019:10:01 16:12:33",
  "BrightnessValue": 3.92,
  "ExifImageWidth": 1944,
  "ExposureMode": "Auto",
  "ApertureValue": 2,
  "ComponentsConfiguration": "Y, Cb, Cr, -",
  "ColorSpace": "sRGB",
  "SceneType": "Directly photographed",
  "ShutterSpeedValue": "1/117",
  "ExifVersion": "0220",
  "FlashpixVersion": "0100",
  "ResolutionUnit": "inches",
  "GPSLatitudeRef": "North",
  "GPSLongitudeRef": "East",
  "GPSAltitudeRef": "Unknown (2)",
  "GPSTimeStamp": "10:42:24",
  "GPSProcessingMethod": "ASCII",
  "GPSDateStamp": "2019:10:01",
  "XResolution": 72,
  "YResolution": 72,
  "Make": "Xiaomi",
  "ThumbnailOffset": 1040,
  "ThumbnailLength": 15180,
  "Compression": "JPEG (old-style)",
  "Aperture": 2,
  "GPSAltitude": "0 m Above Sea Level",
  "GPSDateTime": "2019:10:01 10:42:24Z",
  "GPSLatitude": "25 deg 42' 21.34\" N",
  "GPSLongitude": "81 deg 46' 35.33\" E",
  "GPSPosition": "25 deg 42' 21.34\" N, 81 deg 46' 35.33\" E",
  "ImageSize": "1944x2592",
  "Megapixels": 5,
  "ScaleFactor35efl": 1.1,
  "ShutterSpeed": "1/117",
  "SubSecCreateDate": "2019:10:01 16:12:33.033060",
  "SubSecDateTimeOriginal": "2019:10:01 16:12:33.033060",
  "SubSecModifyDate": "2019:10:01 16:12:33.033060",
  "ThumbnailImage": "(Binary data 15180 bytes, use -b option to extract)",
  "CircleOfConfusion": "0.026 mm",
  "FOV": "161.1 deg",
  "FocalLength35efl": "2.6 mm (35 mm equivalent: 3.0 mm)",
  "HyperfocalDistance": "0.13 m",
  "LightValue": 8.9
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4yg72m3c08d4ua7rv22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4yg72m3c08d4ua7rv22.png" alt=" " width="748" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this tool to extract media files inner data that not see in file.&lt;/p&gt;

</description>
      <category>react</category>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Create A Forget password link for one time and expire in 10 minutes in nodeJS</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sun, 03 Jul 2022 07:50:14 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/create-a-forget-password-link-for-one-time-and-expire-in-10-minutes-in-nodejs-2le6</link>
      <guid>https://forem.com/deepakjaiswal/create-a-forget-password-link-for-one-time-and-expire-in-10-minutes-in-nodejs-2le6</guid>
      <description>&lt;p&gt;here create forget password link with json web token (jwt) to create expire token in 10 minutes.&lt;/p&gt;

&lt;p&gt;but in token not make it for one time so store in database after successfully OTP verify i have remove from database.&lt;/p&gt;

&lt;p&gt;in mongoose model i add a field name otp has number and expire field in 10 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  user.model.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require("mongoose")

const userSchema = new mongoose.Schema({
    name:{
        type:String,
        required:true,
        trim:true
    },
        email:{
                type:String,
                required:true
        },
    otp:{
        type:Number,
        expires:'10m',
                index:true
    },
    imageUrl:{
        type:String,
        default:'avatar.png'
    }
})

module.exports = mongoose.model('User',userSchema)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  user.controller.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports.forgetPassword =async (req,res,next)=&amp;gt;{
     try{

    const {email} = req.body

        User.findOne({email}).exec(function(err,user){
                if(err) throw err;
                if(!user){
                    res.json({"error":"User not 
                                      found"})
                }
                else{
                let otp=Math.random().toString(5);
                              user=await User.findOneAndUpdate({
                                   _id:user._id},
                               {$set :{otp}},{new:true});    
     const  {_id,email} = user;
     let  token=jwt.sign({_id,email,tokenId:uuidv4()},"SECRET_TOKEN",{expiresIn: '10m' });
     let url=HOST_URL+token;
     await sendMail(email,"forget password link",url,`your otp is ${user.otp}`);                 
     res.status(200).send({message:"send link to your mail"});


        }
    }
   }catch(err){
    next(err)
  }
}

module.exports.verifyOtp =async (req,res,next)=&amp;gt;{

   try{
        //email get from token
         const {email,otp}=req.body;
        User.findOne({email,otp}).exec(function(err,user){
                if(err) throw err
                if(!user){
                    res.json({"error":"Link is Expired"})
                }
                else{
await User.updateOne({_id:user._id},{$set:{otp:null}});
                            const token=jwt.sign({_id:user._id,tokenId:uuidv4()},"SECRET_TOKEN")
                            res.header("token",token).json({message:"otp verification success"})

        }
    }
    }catch(err){
    next(err)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;check on client side if token is expired then message token is expired.&lt;/p&gt;

</description>
      <category>node</category>
      <category>angular</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Get MongoDB data 10x smaller &amp; faster using lean function in NodeJs</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sat, 02 Jul 2022 04:36:21 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/get-mongodb-data-10x-faster-using-lean-function-5a7n</link>
      <guid>https://forem.com/deepakjaiswal/get-mongodb-data-10x-faster-using-lean-function-5a7n</guid>
      <description>&lt;p&gt;sometimes, i am finding data in mongoose collection it give mongoose document but when we use lean function in find collection it gives response 10x smaller and faster as compare to simple finding collection. mongoose also say this its gives 10x smaller response.&lt;/p&gt;

&lt;h2&gt;
  
  
  product.model.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require("mongoose")

const ProductSchema = new mongoose.Schema({
    name:{
        type:String,
        required:true,
                index:true,
        trim:true
    },
        createdBy:{
                type:mongoose.Types.Schema.ObjectId,
                ref:'user',
                required:true
        },
    color:{
        type:String,
        required:true,
        trim:true
    },
    ram:{
        type:String,
        required:true
    },
    rom:{
        type:String,
        required:true
    },
    price:{
        type:String,
        required:true
    },
    qty:{
        type:String,
        required:true,
        default:1
    },
    displaySize:{
        type:String,
        required:true
    },
    frontCamera:{
        type:String,
        required:true
    },
    rearCamera:{
        type:String,
        required:true
    },
    battery:{
        type:String,
        required:true
    },
    processor:{
        type:String,
        required:true
    },
    imageUrl:{
        type:String,
        required:true
    },
    modelNumber:{
        type:String,
        required:true
    },
    modelName:{
        type:String,
        required:true
    },
    operatingSystem:{
        type:String,
        required:true
    },
    warrenty:{
        type:String,
                default:"6 months"
    },
    addDate:{
        type:Date,
                default:Date.now
    }
})

module.exports = mongoose.model('Product',ProductSchema)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  product.controller.js
&lt;/h2&gt;

&lt;p&gt;without lean function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports.listAllProducts =async (req,res,next)=&amp;gt;{
  try{
    let products=await Product.find()
                .populate("createdBy").sort({addDate:-1})
        res.send(products);
  }catch(err){
    next(err)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with lean function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports.listAllProducts =async (req,res,next)=&amp;gt;{
  try{
    let products=await Product.find().populate("createdBy")
               .lean().sort({addDate:-1})
        res.send(products);
  }catch(err){
    next(err)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when we use lean function we cannot modify document value and save it.&lt;/p&gt;

</description>
      <category>node</category>
      <category>angular</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Edit Image in NodeJS Using Sharp</title>
      <dc:creator>Deepak Jaiswal </dc:creator>
      <pubDate>Sat, 25 Jun 2022 18:07:21 +0000</pubDate>
      <link>https://forem.com/deepakjaiswal/edit-image-in-nodejs-using-sharp-3fe7</link>
      <guid>https://forem.com/deepakjaiswal/edit-image-in-nodejs-using-sharp-3fe7</guid>
      <description>&lt;p&gt;sometimes need to edit image properties and filter in nodejs. when their is no any image editor in frontend side then we use backend as image editor library &lt;strong&gt;sharp&lt;/strong&gt;. sharp is best package in npm to edit image.&lt;/p&gt;

&lt;h2&gt;
  
  
  install package
&lt;/h2&gt;

&lt;p&gt;npm i sharp&lt;/p&gt;

&lt;h2&gt;
  
  
  server.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const app = express()
const multer  = require('multer');
const path= require('path');
const sharp = require('sharp');
const UserModel=require('./user.model');

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, '/uploads')
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
    cb(null, file.fieldname + '-' + uniqueSuffix)
  }
})

const upload = multer(
{ storage: storage ,
    fileFilter: function (req, file, callback) {
        var ext = path.extname(file.originalname);
        if(ext !== '.png' &amp;amp;&amp;amp; ext !== '.jpg' &amp;amp;&amp;amp; ext !== '.gif' &amp;amp;&amp;amp; ext !== '.jpeg') {
            return callback(new Error('Only images are allowed'))
        }
        callback(null, true)
    },
    limits:{
        fileSize: 1024 * 1024
    }
})

app.post('/profile', upload.single('profile'),async function (req, res, next) {
  // req.file contains the file fields

  try {
    await sharp("./uploads/"+req.file.filename)
      .resize({
        width: 150,
        height: 97
      })
      .toFile("./resize-uploads/"+req.file.filename);
    let user=await UserModel({name:req.body.name,avatar:req.file.filename}).save();

res.send(user);
  } catch (error) {
    console.log(error);
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here first upload file in original directory image then resize image and save resize image into another directory. &lt;br&gt;
also we add many functionality in sharp package to use like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//filter image to grayscale
await sharp("./uploads/"+req.file.filename)
      .extract({ width: 400, height: 320, left: 120, top: 70 })
      .grayscale()
      .toFile("./resize-uploads/"+req.file.filename);

//rotate image 
await sharp("./uploads/"+req.file.filename)
      .rotate(40, { background: { r: 0, g: 0, b: 0, alpha: 0 } })
      .toFile("./resize-uploads/"+req.file.filename);

//blur image

    await sharp("./uploads/"+req.file.filename)
      .rotate(40, { background: { r: 0, g: 0, b: 0, alpha: 0 } })
      .blur(4)
      .toFile("./resize-uploads/"+req.file.filename);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  index.html
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;form action="/profile" enctype="multipart/form-data" method="post"&amp;gt;
  &amp;lt;div class="form-group"&amp;gt;
    &amp;lt;input type="file" class="form-control-file" name="profile" accept="/image"&amp;gt;
    &amp;lt;input type="text" class="form-control" placeholder="Enter Name" name="name"&amp;gt;
    &amp;lt;input type="submit" value="Get me the stats!" class="btn btn-default"&amp;gt;            
  &amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that is enough for this explore on sharp package to add many filter. thank you everyone.&lt;/p&gt;

</description>
      <category>node</category>
      <category>express</category>
      <category>react</category>
      <category>angular</category>
    </item>
  </channel>
</rss>
