<?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>DEV Community: David Akim</title>
    <description>The latest articles on DEV Community by David Akim (@david001).</description>
    <link>https://dev.to/david001</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%2F1085899%2Fbf4de66c-d65e-4cb2-b587-b258475f3bed.png</url>
      <title>DEV Community: David Akim</title>
      <link>https://dev.to/david001</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/david001"/>
    <language>en</language>
    <item>
      <title>Deploying Taipy app in Render</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Sun, 05 Jan 2025 18:03:45 +0000</pubDate>
      <link>https://dev.to/david001/deploying-taipy-app-in-render-56pf</link>
      <guid>https://dev.to/david001/deploying-taipy-app-in-render-56pf</guid>
      <description>&lt;p&gt;In this lesson we will go the steps of deploying a Taipy app in Render. &lt;a href="https://taipy.io/" rel="noopener noreferrer"&gt;Taipy&lt;/a&gt; is an open-source Python library that supports both front-end and back-end development, streamlining the process from creating prototypes to deploying production-ready applications. &lt;a href="https://render.com/" rel="noopener noreferrer"&gt;Render&lt;/a&gt; is a service that allows you to build, deploy, and scale your apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Must be familiar with Python and Github&lt;/li&gt;
&lt;li&gt;Have a Github account. Create one &lt;a href="https://github.com/signup?ref_cta=Sign+up&amp;amp;ref_loc=header+logged+out&amp;amp;ref_page=%2F&amp;amp;source=header-home" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Have a Render account. Create one &lt;a href="https://dashboard.render.com/register" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Have a Taipy app&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Procedure&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new Github repository.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a requirements.txt file for your Taipy app.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set your Taipy app host to 0.0.0.0 and port to 10000.&lt;br&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%2Ftpd65btj922ua1e0f5zg.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%2Ftpd65btj922ua1e0f5zg.png" alt="Image description" width="484" height="41"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push your Taipy app to your Github repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Login to your Render account and select &lt;strong&gt;Web Service&lt;/strong&gt;.&lt;br&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%2Fscrbsjhrbia1lls576bf.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%2Fscrbsjhrbia1lls576bf.png" alt="Image description" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select your Github repository that contains the Taipy app.&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%2Fne9nia2raf77v34girg4.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%2Fne9nia2raf77v34girg4.png" alt="Image description" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give your web service a name, select &lt;strong&gt;Python 3&lt;/strong&gt; for &lt;strong&gt;Language&lt;/strong&gt; and select the Github branch that you want to deploy.  &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%2F7dwrj6ox460ui2vk3mp5.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%2F7dwrj6ox460ui2vk3mp5.png" alt="Image description" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter the root directory (if any) and the &lt;strong&gt;Start Command&lt;/strong&gt; (the command you use to run the app locally). &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%2Fcs1sq2ohbwn4ne36ngx0.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%2Fcs1sq2ohbwn4ne36ngx0.png" alt="Image description" width="800" height="234"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select your instance. (There is a free tier)&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%2Fca7h87sg3lsko0sntzau.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%2Fca7h87sg3lsko0sntzau.png" alt="Image description" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter any &lt;strong&gt;Environment Variables&lt;/strong&gt; and then click &lt;strong&gt;Deploy Web Service&lt;/strong&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%2Fn4raath6kgmfupwzyf0t.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%2Fn4raath6kgmfupwzyf0t.png" alt="Image description" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The URL for your app is generated. The status of your app is shown. In this case, it is &lt;strong&gt;Live&lt;/strong&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%2Fkmhm2b1r4v5aqiyn3io2.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%2Fkmhm2b1r4v5aqiyn3io2.png" alt="Image description" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to the URL to see your app. &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%2Fzjmbn05ocnhr4qrq0l6j.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%2Fzjmbn05ocnhr4qrq0l6j.png" alt="Image description" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your app fails, you can fix your app, push it to Github and Render will automatically re-deploy it. If it doesn't, you can click &lt;strong&gt;Manual Deploy&lt;/strong&gt;. This concludes our lesson. &lt;/p&gt;

</description>
      <category>taipy</category>
      <category>python</category>
    </item>
    <item>
      <title>Sophisticated Speech-to-Text Application</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Mon, 25 Nov 2024 00:54:01 +0000</pubDate>
      <link>https://dev.to/david001/sophisticated-speech-to-text-47jm</link>
      <guid>https://dev.to/david001/sophisticated-speech-to-text-47jm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/assemblyai"&gt;AssemblyAI Challenge &lt;/a&gt;: Sophisticated Speech-to-Text.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I developed a Speech-to-Text application in &lt;a href="https://taipy.io/" rel="noopener noreferrer"&gt;Taipy&lt;/a&gt; using AssemblyAI's Universal-2 Speech-to-Text model. The application's features are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Transcribe spoken words into written text.&lt;/li&gt;
&lt;li&gt;Detect multiple speakers in an audio file and what each speaker said.&lt;/li&gt;
&lt;li&gt;Summarize your audio data with key takeaways&lt;/li&gt;
&lt;li&gt;Download transcriptions to a text file.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/david-001/assemblyai_challenge" rel="noopener noreferrer"&gt;Link to Github repository&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&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%2Fu214mg2wdbchq0qazk10.jpg" 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%2Fu214mg2wdbchq0qazk10.jpg" alt="Transcription" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&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%2Fxpeojrouhi2tr2ltikzk.jpg" 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%2Fxpeojrouhi2tr2ltikzk.jpg" alt="Summarization" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&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%2Fuvt2n5mgkiy26llknhcn.jpg" 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%2Fuvt2n5mgkiy26llknhcn.jpg" alt="Diarization" width="800" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;The application was developed using Taipy, a Python-based framework, which made integrating with AssemblyAI’s Speech-to-Text Model seamless, as both use Python. AssemblyAI's comprehensive documentation simplified the implementation of the transcription and diarization features. Taipy was utilized for the user interface, while AssemblyAI handled all the Speech-to-Text processing.&lt;br&gt;
This submission also meets the criteria for the &lt;strong&gt;No More Monkey Business Challenge Prompt&lt;/strong&gt;. The summarization feature was implemented using LeMUR, where a custom prompt was sent to the LLM to generate a concise summary of the transcript.&lt;br&gt;
This is a &lt;strong&gt;solo submission&lt;/strong&gt;, with all the work on Taipy and AssemblyAI completed by myself. It was an enjoyable learning experience. AssemblyAI has made building Speech-to-Text applications incredibly easy, and I will certainly use it again in the future.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>assemblyaichallenge</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>2024 Hacktoberfest Writing challenge: Contributor Experience</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Fri, 01 Nov 2024 00:48:15 +0000</pubDate>
      <link>https://dev.to/david001/hacktoberfest-2024-my-contributor-experience-3i77</link>
      <guid>https://dev.to/david001/hacktoberfest-2024-my-contributor-experience-3i77</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest"&gt;2024 Hacktoberfest Writing challenge&lt;/a&gt;: Contributor Experience&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I’ve been programming for a few years, but my experience has been limited to solo projects. I hadn’t contributed to a team project until I discovered Hacktoberfest, thanks to the amazing members at &lt;a href="https://virtualcoffee.io/" rel="noopener noreferrer"&gt;Virtual Coffee&lt;/a&gt; who introduced me to the event.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I started contributing?
&lt;/h2&gt;

&lt;p&gt;I felt a bit intimidated at first because I wasn’t sure where to begin. I also worried that if I took on an issue, I might not be able to solve it and that I should let someone else handle it. Fortunately, the members at Virtual Coffee offered tutorials and resources that were incredibly helpful, including beginner-friendly repositories.&lt;/p&gt;

&lt;h2&gt;
  
  
  How was my experience?
&lt;/h2&gt;

&lt;p&gt;I learned the steps for making a contribution, and it turned out to be easier and less intimidating than I expected, though resolving merge conflicts was a bit frustrating. I successfully completed four pull requests and even received a badge just for registering!&lt;/p&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%2F9h2o0bed4h661yhqfan4.jpg" 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%2F9h2o0bed4h661yhqfan4.jpg" alt=" " width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Frontend Challenge: Space Edition (Rocket Emoji CSS)</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Mon, 09 Sep 2024 00:17:51 +0000</pubDate>
      <link>https://dev.to/david001/rocket-emoji-1pbb</link>
      <guid>https://dev.to/david001/rocket-emoji-1pbb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2024-09-04"&gt;Frontend Challenge v24.09.04&lt;/a&gt;, CSS Art: Space.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;This submission was inspired by celebrating people's success on a chat. One space related emoji used to acknowledge their wins is the rocket emoji.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/david-001/embed/vYqvQwP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;This challenge provided an excellent learning experience. The task was to create a rocket emoji using CSS and HTML, which involved crafting shapes that are not typically seen on websites.&lt;br&gt;
I started by breaking the image into 8 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Body&lt;/li&gt;
&lt;li&gt;Nose Cone&lt;/li&gt;
&lt;li&gt;Window&lt;/li&gt;
&lt;li&gt;Left Fin&lt;/li&gt;
&lt;li&gt;Middle Fin&lt;/li&gt;
&lt;li&gt;Right Fin&lt;/li&gt;
&lt;li&gt;Nozzle&lt;/li&gt;
&lt;li&gt;Flame&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;b&gt;Body&lt;/b&gt; is a div element that is rotated 45 degrees with a border radius added to each corner to give it a rounded appearance. This element contains the &lt;b&gt;Nose Cone&lt;/b&gt; and the &lt;b&gt;Window&lt;/b&gt;. The &lt;b&gt;Nose Cone&lt;/b&gt; is a div element with a border radius of 50% which makes it a circle. It is positioned at the top of the &lt;b&gt;Body&lt;/b&gt;. The &lt;b&gt;Window&lt;/b&gt; is similar to the The &lt;b&gt;Nose Cone&lt;/b&gt; but it has a border to give it a window frame and it is positioned near the center of the &lt;b&gt;Body&lt;/b&gt;. The &lt;b&gt;Left Fin&lt;/b&gt; is a div element with a clip-path attribute. Using this attribute I can define a polygon, which allows me to draw the fin. The &lt;b&gt;Middle Fin&lt;/b&gt; is a div element with rounded corners. The &lt;b&gt;Right Fin&lt;/b&gt; similar to the &lt;b&gt;Left Fin&lt;/b&gt; but it is inverted. The &lt;b&gt;Nozzle&lt;/b&gt; is a rectangular div element with rounded corners. The &lt;b&gt;Flame&lt;/b&gt; is a square div element with varying border radius for each corner. A border with a deeper color was added to &lt;b&gt;Flame&lt;/b&gt; to give it more of a flame appearance. Animation was added to &lt;b&gt;Flame&lt;/b&gt; which simply changes the size and opacity every 2 seconds indefinitely. The background is a series of radial-gradient attributes used to create random white circles of varying sizes at different locations.&lt;/p&gt;

&lt;p&gt;I learned some new CSS techniques, including how to create animations and polygons. In the future, I hope to add even more animations to the rocket.&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
    </item>
    <item>
      <title>One Byte Explainer: Recursion</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Wed, 19 Jun 2024 03:53:17 +0000</pubDate>
      <link>https://dev.to/david001/one-byte-explainer-recursion-240o</link>
      <guid>https://dev.to/david001/one-byte-explainer-recursion-240o</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/cs"&gt;DEV Computer Science Challenge v24.06.12: One Byte Explainer&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explainer
&lt;/h2&gt;

&lt;p&gt;Recursion is a technique where a function calls itself, allowing large complicated problems to be broken down into smaller, simpler problems. Since a recursive function can run indefinitely, a base case is used to terminate it.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cschallenge</category>
      <category>computerscience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Frontend Challenge: Cat CSS</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Fri, 07 Jun 2024 12:04:49 +0000</pubDate>
      <link>https://dev.to/david001/frontend-challenge-evil-cat-css-1f0b</link>
      <guid>https://dev.to/david001/frontend-challenge-evil-cat-css-1f0b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2024-05-29"&gt;Frontend Challenge v24.04.17&lt;/a&gt;, CSS Art: June.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;This submission was inspired by Frontend Friday Folks Fighting CSSBattle.dev hosted by &lt;a href="https://virtualcoffee.io/" rel="noopener noreferrer"&gt;Virtual Coffee&lt;/a&gt;. It is an activity where you take on a challenge at &lt;a href="https://cssbattle.dev" rel="noopener noreferrer"&gt;CSS Battle&lt;/a&gt;. I completed the &lt;a href="https://cssbattle.dev/play/175" rel="noopener noreferrer"&gt;CSS Battle #175. Evil Cat&lt;/a&gt; challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/david-001/embed/RwmZbbo?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;This challenge provided an excellent learning experience. The task was to create a cat using CSS and HTML, which involved crafting shapes that are not typically seen on websites.&lt;/p&gt;

&lt;p&gt;I started by breaking the image into 8 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Face&lt;/li&gt;
&lt;li&gt;Left ear&lt;/li&gt;
&lt;li&gt;Right ear&lt;/li&gt;
&lt;li&gt;Left eye&lt;/li&gt;
&lt;li&gt;Left pupil&lt;/li&gt;
&lt;li&gt;Right eye&lt;/li&gt;
&lt;li&gt;Right pupil&lt;/li&gt;
&lt;li&gt;Nose&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I created a container that housed all the individual parts and positioned it at the center of the screen. The face was a simple rectangle with rounded corners achieved by applying a border radius. The ears were a bit more challenging. I solved this by creating a rectangle with only three borders—left, right, and bottom. The side borders were made transparent, and I adjusted the border widths until the desired triangle shape was formed, then rotated them to align correctly. The eyes are rectangles with two rounded corners on opposite sides and rotated for correct alignment. The pupils are rectangles with rounded corners. The nose was created using the same method as the ears.&lt;/p&gt;

&lt;p&gt;I learned some new CSS techniques, including how to center an item on the screen, create a triangle, apply rotation, and round corners. I am proud to have achieved a 100% match for this challenge. In the future, I hope to add animation to make the pupils move from side to side. &lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
    </item>
    <item>
      <title>Installing Odoo from source code</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Tue, 19 Dec 2023 15:45:08 +0000</pubDate>
      <link>https://dev.to/david001/installing-odoo-from-source-code-be7</link>
      <guid>https://dev.to/david001/installing-odoo-from-source-code-be7</guid>
      <description>&lt;p&gt;In this lesson, we will go through the steps of running &lt;a href="https://www.odoo.com/" rel="noopener noreferrer"&gt;Odoo&lt;/a&gt; (Community version) in Windows from the source code. Odoo is an open-source business management software suite that includes a range of business applications for various purposes such as accounting, inventory management, and customer relationship management (CRM). We will be using the PyCharm IDE. To run Odoo in other operating systems, please check the documentation &lt;a href="https://www.odoo.com/documentation/master/administration/install/source.html#" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Must have &lt;a href="https://www.python.org/downloads/" rel="noopener noreferrer"&gt;Python&lt;/a&gt; (version 3.10 or later) installed&lt;/li&gt;
&lt;li&gt;Must have &lt;a href="https://www.jetbrains.com/pycharm/download/?section=windows" rel="noopener noreferrer"&gt;PyCharm Community Edition&lt;/a&gt; installed&lt;/li&gt;
&lt;li&gt;Must have &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;Git&lt;/a&gt; installed&lt;/li&gt;
&lt;li&gt;Must have &lt;a href="https://www.postgresql.org/download/windows" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; (version 12.0 or later) installed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Add PostgreSQL’s bin directory to the Environment variables&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Launch Control Panel&lt;/li&gt;
&lt;li&gt;Click System and Security&lt;/li&gt;
&lt;li&gt;Click System&lt;/li&gt;
&lt;li&gt;Click Advance System Settings&lt;/li&gt;
&lt;li&gt;Click Environment Variables...&lt;/li&gt;
&lt;li&gt;If you want to make this path available to you alone, click &lt;strong&gt;New...&lt;/strong&gt; under &lt;strong&gt;User variables&lt;/strong&gt;. If you want to make this path available to everyone, click &lt;strong&gt;New...&lt;/strong&gt; under &lt;strong&gt;System variables&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variable name&lt;/strong&gt; is &lt;strong&gt;Path&lt;/strong&gt; and &lt;strong&gt;Variable value&lt;/strong&gt; is the PostgreSQL’s bin directory (by default: &lt;em&gt;C:\Program Files\PostgreSQL&amp;lt;version&amp;gt;\bin&lt;/em&gt;)
(&lt;strong&gt;Note&lt;/strong&gt;: If this variable already exists, click &lt;strong&gt;Edit...&lt;/strong&gt; instead of &lt;strong&gt;New...&lt;/strong&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Create a new PostgreSQL user&lt;/strong&gt;&lt;br&gt;
Open the pg admin gui (pgAdmin 4). Enter master password or click Reset Master Password if you forgot the password.&lt;/p&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%2Fjc95iguiulfqcmqq3gab.jpg" 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%2Fjc95iguiulfqcmqq3gab.jpg" alt="Image description" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter password for postgres user. This is usually password.&lt;/p&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%2Fx9gl598im9dy667a2tk9.jpg" 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%2Fx9gl598im9dy667a2tk9.jpg" alt="Image description" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Login/Group Roles&lt;/strong&gt;. Right click and select Create-&amp;gt;Login/Group Role.&lt;/p&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%2F7hsn783nb93i6p2lcuy9.jpg" 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%2F7hsn783nb93i6p2lcuy9.jpg" alt="Image description" width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;General&lt;/strong&gt; tab, give the role a &lt;strong&gt;Name&lt;/strong&gt;. In this example &lt;strong&gt;Name&lt;/strong&gt; is &lt;strong&gt;odoo_user&lt;/strong&gt;. (Remember this)&lt;/p&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%2F9152jkcsdzyz00w0jrte.jpg" 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%2F9152jkcsdzyz00w0jrte.jpg" alt="Image description" width="706" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Definition&lt;/strong&gt; tab, fill out the &lt;strong&gt;Password&lt;/strong&gt; field. (Remember this)&lt;/p&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%2F3vionvactmb39zbatgcq.jpg" 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%2F3vionvactmb39zbatgcq.jpg" alt="Image description" width="704" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Privileges&lt;/strong&gt; tab, enable &lt;strong&gt;Can login?&lt;/strong&gt; and &lt;strong&gt;Create databases?&lt;/strong&gt;. Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&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%2F1a335f7nkvvyrelzixqp.jpg" 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%2F1a335f7nkvvyrelzixqp.jpg" alt="Image description" width="709" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up project folder&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a folder called &lt;strong&gt;Odoo Project&lt;/strong&gt; (you can give this folder any name)&lt;/p&gt;

&lt;p&gt;Inside this folder create a folder called &lt;strong&gt;config&lt;/strong&gt; and another folder called &lt;strong&gt;custom_addons&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;config&lt;/strong&gt; folder, create a file called &lt;strong&gt;odoo.conf&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Open a command terminal and navigate to &lt;strong&gt;Odoo Project&lt;/strong&gt; folder.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Odoo Project&lt;/strong&gt; directory, clone the Odoo source code Git repository with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/odoo/odoo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, your folder structure should look 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;Odoo Project/
├─ config/
│  ├─ odoo.conf
├─ custom_addons/
├─ odoo/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the &lt;strong&gt;requirements.txt&lt;/strong&gt; in &lt;strong&gt;odoo&lt;/strong&gt; folder and paste in the &lt;strong&gt;Odoo Project&lt;/strong&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up Pycharm&lt;/strong&gt;&lt;br&gt;
Open &lt;strong&gt;PyCharm&lt;/strong&gt; and click &lt;strong&gt;New Project&lt;/strong&gt;.&lt;/p&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%2Fg9j6z6u0ep3gid8ee79e.jpg" 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%2Fg9j6z6u0ep3gid8ee79e.jpg" alt="Image description" width="787" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the location of your project. Check the option &lt;strong&gt;New environment using Virtualenv&lt;/strong&gt;. You can leave the location of the environment as it is. Select the location of python.exe for the &lt;strong&gt;Base interpreter&lt;/strong&gt;. Click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/p&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%2Ffncy9i4unpt0njgoj91r.jpg" 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%2Ffncy9i4unpt0njgoj91r.jpg" alt="Image description" width="787" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to give Odoo our database information: user, password, host and port. The &lt;strong&gt;db_user&lt;/strong&gt; and &lt;strong&gt;db_password&lt;/strong&gt; created earlier (&lt;strong&gt;Create a new PostgreSQL user&lt;/strong&gt; section). We also need to give Odoo the location of our &lt;strong&gt;custom_addons&lt;/strong&gt; folder (&lt;strong&gt;addons_path&lt;/strong&gt;).&lt;br&gt;
On the Project Panel, open the &lt;strong&gt;odoo.conf&lt;/strong&gt; file and copy the contents below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[options]
addons_path = G:\Projects\Odoo\Odoo Project\custom_addons
db_user = odoo_user
db_password = odoo_user
db_host = localhost
db_port = 5432
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click File-&amp;gt;Run-&amp;gt;Edit Configurations. &lt;/p&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%2Fxu3ck1fjf71x1vjsyr7j.jpg" 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%2Fxu3ck1fjf71x1vjsyr7j.jpg" alt="Image description" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Add new run configuration...&lt;/strong&gt;&lt;/p&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%2F48befv2g6b4ltiraqi0n.jpg" 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%2F48befv2g6b4ltiraqi0n.jpg" alt="Image description" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Python&lt;/strong&gt;&lt;/p&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%2F1pmomm121fjfgy0quwc5.jpg" 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%2F1pmomm121fjfgy0quwc5.jpg" alt="Image description" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set the &lt;strong&gt;Name&lt;/strong&gt; to Odoo. Set &lt;strong&gt;Script Path&lt;/strong&gt; to the &lt;strong&gt;odoo-bin&lt;/strong&gt; file. This is located inside the &lt;strong&gt;odoo&lt;/strong&gt; folder which is inside the &lt;strong&gt;Odoo Project&lt;/strong&gt; folder. Set &lt;strong&gt;Parameters&lt;/strong&gt; to &lt;em&gt;-c config/odoo.conf&lt;/em&gt;. Set &lt;strong&gt;Working Directory&lt;/strong&gt; to the &lt;strong&gt;Odoo Project&lt;/strong&gt; folder. Click &lt;strong&gt;Apply&lt;/strong&gt; and &lt;strong&gt;OK&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Click Terminal at the bottom left.&lt;/p&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%2Foa3tnok8koz8isqtyb92.jpg" 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%2Foa3tnok8koz8isqtyb92.jpg" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install the dependencies using the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install setuptools wheel
pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click the &lt;strong&gt;Run Odoo&lt;/strong&gt; button at the top.&lt;/p&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%2F14l31lx3uvdtq2bej81m.jpg" 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%2F14l31lx3uvdtq2bej81m.jpg" alt="Image description" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a browser go to &lt;a href="http://localhost:8069" rel="noopener noreferrer"&gt;http://localhost:8069&lt;/a&gt;. Enter &lt;strong&gt;Database Name&lt;/strong&gt;, &lt;strong&gt;Email&lt;/strong&gt; and &lt;strong&gt;Password&lt;/strong&gt;.&lt;/p&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%2Fubmp1smtmffvpulcdaqm.jpg" 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%2Fubmp1smtmffvpulcdaqm.jpg" alt="Image description" width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Log in using your credentials.&lt;/p&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%2F2yef6ctq049eflr0a09w.jpg" 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%2F2yef6ctq049eflr0a09w.jpg" alt="Image description" width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will now be logged in. Here you can activate your required applications.&lt;/p&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%2F2kjcfhsysu7919uaqprz.jpg" 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%2F2kjcfhsysu7919uaqprz.jpg" alt="Image description" width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This concludes our lesson. For more information, check the documentation &lt;a href="https://www.odoo.com/documentation/master/administration/install/source.html#" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>odoo</category>
      <category>python</category>
    </item>
    <item>
      <title>Create an Agebot in Slack using Python</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Thu, 30 Nov 2023 01:41:06 +0000</pubDate>
      <link>https://dev.to/david001/create-an-agebot-in-slack-41j5</link>
      <guid>https://dev.to/david001/create-an-agebot-in-slack-41j5</guid>
      <description>&lt;p&gt;In this lesson, we will go through the steps of creating a bot in the Slack messaging app which automatically determines the user's age based on the user's input. We will be implementing this app in Python and deploying it locally.&lt;/p&gt;

&lt;p&gt;Prerequisites&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be familiar with Python&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a Slack Workspace for AgeBot Project
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://slack.com/" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; and &lt;strong&gt;Sign in&lt;/strong&gt; or &lt;strong&gt;Sign up with Email&lt;/strong&gt; if you don't have an account. &lt;br&gt;
After signing in, click &lt;strong&gt;Create Another Workspace&lt;/strong&gt; or &lt;strong&gt;Create a Workspace&lt;/strong&gt;. Fill out the required information. You can invite team members or create channels for specific topics.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the Slack Workspace for AgeBot Project
&lt;/h2&gt;

&lt;p&gt;Create an app by going to &lt;a href="https://api.slack.com/apps" rel="noopener noreferrer"&gt;Slack API apps&lt;/a&gt;. Click &lt;strong&gt;Create an App&lt;/strong&gt;. If you have create apps before in Slack, this page will look different. In that case, there will be a &lt;strong&gt;Create New App&lt;/strong&gt; button.&lt;/p&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%2Fotr6moosbhi33osdlln0.jpg" 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%2Fotr6moosbhi33osdlln0.jpg" alt="Image description" width="692" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click create &lt;strong&gt;From scratch&lt;/strong&gt;&lt;/p&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%2F88uhsx0xluxx65erfndd.jpg" 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%2F88uhsx0xluxx65erfndd.jpg" alt="Image description" width="526" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give your app a name and choose a workspace to develop your app in. In this example, we will be using a workspace we have already created called Cyber Coder. Please use one of the workspaces you created. Click &lt;strong&gt;Create App&lt;/strong&gt;.&lt;/p&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%2F5fjibq3qcggvrl9glq5g.jpg" 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%2F5fjibq3qcggvrl9glq5g.jpg" alt="Image description" width="527" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to &lt;strong&gt;Display Section&lt;/strong&gt;. Give your app a &lt;strong&gt;Short description&lt;/strong&gt; and &lt;strong&gt;Long description&lt;/strong&gt;. Then click &lt;strong&gt;Save Changes&lt;/strong&gt;.&lt;/p&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%2F7panxpksdakr9cupspj1.jpg" 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%2F7panxpksdakr9cupspj1.jpg" alt="Image description" width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll up and click &lt;strong&gt;Bots&lt;/strong&gt;. &lt;/p&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%2F8jhsqn0xtdwtv0w6y3z5.jpg" 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%2F8jhsqn0xtdwtv0w6y3z5.jpg" alt="Image description" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Review Scopes to Add&lt;/strong&gt;.&lt;/p&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%2Fw49tavy4t1komrd56uox.jpg" 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%2Fw49tavy4t1komrd56uox.jpg" alt="Image description" width="693" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to the &lt;strong&gt;Scopes&lt;/strong&gt; Section. Under &lt;strong&gt;Bot Token Scopes&lt;/strong&gt;, click &lt;strong&gt;Add an OAuth Scope&lt;/strong&gt;.&lt;/p&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%2Fbtgtfawovkn0j139xmg3.jpg" 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%2Fbtgtfawovkn0j139xmg3.jpg" alt="Image description" width="693" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Search for the following and add them. &lt;strong&gt;app_mentions:read&lt;/strong&gt; views messages that directly mention @AgeBot in conversations that the app is in. &lt;strong&gt;chat:write&lt;/strong&gt; sends messages as @AgeBot. &lt;strong&gt;im:history&lt;/strong&gt; views messages and other content in direct messages that AgeBot has been added to.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;app_mentions:read&lt;/li&gt;
&lt;li&gt;chat:write&lt;/li&gt;
&lt;li&gt;im:history&lt;/li&gt;
&lt;/ul&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%2Fa5zpvsr8hx5dyaiz4o8b.jpg" 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%2Fa5zpvsr8hx5dyaiz4o8b.jpg" alt="Image description" width="694" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll up to the &lt;strong&gt;OAuth Tokens for Your Workspace&lt;/strong&gt; Section. Click &lt;strong&gt;Install to Workspace&lt;/strong&gt;.&lt;/p&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%2Frn11krza7skofja3vs7p.jpg" 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%2Frn11krza7skofja3vs7p.jpg" alt="Image description" width="695" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Allow&lt;/strong&gt;.&lt;/p&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%2F6cd7pf2bshl7en046kjw.jpg" 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%2F6cd7pf2bshl7en046kjw.jpg" alt="Image description" width="612" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Socket Mode&lt;/strong&gt; under &lt;strong&gt;Settings&lt;/strong&gt; and turn on &lt;strong&gt;Enable Socket Mode&lt;/strong&gt;. Turning on Socket Mode will route your app’s interactions and events over a WebSockets connection instead sending these payloads to Request URLs. Since we will be running this app locally, we need to enable this feature.&lt;/p&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%2Fd91gjn6moegfq86f9go5.jpg" 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%2Fd91gjn6moegfq86f9go5.jpg" alt="Image description" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Basic Information&lt;/strong&gt; under &lt;strong&gt;Settings&lt;/strong&gt;. &lt;/p&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%2Fpb13snzx06tl9fkpjp2k.jpg" 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%2Fpb13snzx06tl9fkpjp2k.jpg" alt="Image description" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to the &lt;strong&gt;App-Level Tokens&lt;/strong&gt; Section. Click &lt;strong&gt;Generate Token and Scopes&lt;/strong&gt;.&lt;/p&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%2F3qikhimnnpe1kmmhfrhx.jpg" 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%2F3qikhimnnpe1kmmhfrhx.jpg" alt="Image description" width="698" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give your App level token a name. Then click &lt;strong&gt;Add Scope&lt;/strong&gt;. Select &lt;strong&gt;connections:write&lt;/strong&gt; and click &lt;strong&gt;Generate&lt;/strong&gt;. This setting will route your app's interactions and event payloads over WebSockets.&lt;/p&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%2F404o7t3fjkrxl03wqwde.jpg" 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%2F404o7t3fjkrxl03wqwde.jpg" alt="Image description" width="521" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy this token in a notepad. Store this token in a variable call &lt;strong&gt;SLACK_APP_TOKEN&lt;/strong&gt;. Click &lt;strong&gt;Done&lt;/strong&gt;.&lt;/p&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%2Fb291l25ld85mcdfy57wy.jpg" 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%2Fb291l25ld85mcdfy57wy.jpg" alt="Image description" width="518" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll back up to the &lt;strong&gt;Building Apps for Slack&lt;/strong&gt; Section. Click &lt;strong&gt;Add features and functionality&lt;/strong&gt; Section. Then click &lt;strong&gt;Event Subscriptions&lt;/strong&gt;. Turn on &lt;strong&gt;Enable Events&lt;/strong&gt;. &lt;/p&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%2Faxdfq3v8cjgqmw6s4ajw.jpg" 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%2Faxdfq3v8cjgqmw6s4ajw.jpg" alt="Image description" width="713" height="740"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the &lt;strong&gt;Subscribe to bot events&lt;/strong&gt; Section, click &lt;strong&gt;Add Bot User Event&lt;/strong&gt;. Select the following events. &lt;strong&gt;app_mention&lt;/strong&gt; subscribes to only the message events that mention your app or bot. &lt;strong&gt;message.im&lt;/strong&gt; checks if a message was posted in a direct message channel. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;app_mention&lt;/li&gt;
&lt;li&gt;message.im&lt;/li&gt;
&lt;/ul&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%2Fzl344hvv6re1h9d3yat9.jpg" 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%2Fzl344hvv6re1h9d3yat9.jpg" alt="Image description" width="703" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;OAuth &amp;amp; Permissions&lt;/strong&gt; under &lt;strong&gt;Features&lt;/strong&gt;. Under &lt;strong&gt;OAuth Tokens for Your Workspace&lt;/strong&gt; copy the &lt;strong&gt;Bot User OAuth Token&lt;/strong&gt; into a notepad. Store this token in a variable call &lt;strong&gt;SLACK_BOT_TOKEN&lt;/strong&gt;. &lt;/p&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%2Fj9bztj3hoei6lq3gx1rn.jpg" 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%2Fj9bztj3hoei6lq3gx1rn.jpg" alt="Image description" width="800" height="540"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Writing the Python code
&lt;/h2&gt;

&lt;p&gt;This app will automatically calculate the user's age based on the user's input. To trigger this function, go on Slack and in the chat type &lt;strong&gt;@AgeBot&lt;/strong&gt; [day-month-year]. For example, &lt;strong&gt;@AgeBot&lt;/strong&gt; 25-12-2012. Given that the date of writing this blog is 30-11-2023 the response from &lt;strong&gt;AgeBot&lt;/strong&gt; is 10. &lt;/p&gt;

&lt;p&gt;Create a folder called &lt;strong&gt;agebot&lt;/strong&gt;. Navigate into this folder by typing the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd agebot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a virtual environment by entering the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;virtualenv venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate the virtual environment using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;venv\Scripts\activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the required libraries: &lt;strong&gt;slack-bolt&lt;/strong&gt; and &lt;strong&gt;python-dotenv&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;pip install slack-bolt
pip install python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;strong&gt;.env&lt;/strong&gt; file and copy and paste your tokens here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SLACK_APP_TOKEN = "YOUR APP TOKEN"
SLACK_BOT_TOKEN = "YOUR BOT TOKEN"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import the required libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from slack_sdk import WebClient
from datetime import datetime, date
import re

from dotenv import load_dotenv
load_dotenv()
import os
SLACK_APP_TOKEN = os.environ.get("SLACK_APP_TOKEN")
SLACK_BOT_TOKEN = os.environ.get("SLACK_BOT_TOKEN")

app = App(token=SLACK_APP_TOKEN)
client = WebClient(token=SLACK_BOT_TOKEN)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a function to calculate the user's age. First we need to extract the date from the user input. Then we define the date format. The date string is converted to a &lt;strong&gt;datetime&lt;/strong&gt; object. We call the function &lt;strong&gt;date.today()&lt;/strong&gt; to get today's date. The difference between today's date and the user's input date is calculated. This result is then divided by 365 to get the number of years. Finally, return the result as a chat message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_age_request(channel, text):
    # Example string containing a date
    date_string = re.sub('&amp;lt;.*?&amp;gt;', '', text)
    date_string = re.sub(r"\s+", "", date_string)

    # Define the date format
    date_format = "%d-%m-%Y"

    # Convert the string to a datetime object
    date_object = datetime.strptime(date_string, date_format)
    dob = date_object.date()

    today = date.today()

    # Calculate the difference between the two dates
    delta = today - dob

    # Calculate the number of years
    years = delta.days // 365


    client.chat_postMessage(channel=channel, text=str(years))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a function to handle &lt;strong&gt;app_mention&lt;/strong&gt;. This function is called whenever a message mentions the app or bot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.event("app_mention")
def handle_mention(event, say):
    channel = event.get('channel')
    text = event.get('text')
    handle_age_request(channel, text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the &lt;strong&gt;Socket&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;print("Start your bot")
handler = SocketModeHandler(app, app_token=SLACK_APP_TOKEN)
handler.start()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire script should look 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 os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from slack_sdk import WebClient
from datetime import datetime, date
import re

from dotenv import load_dotenv
load_dotenv()
import os
SLACK_APP_TOKEN = os.environ.get("SLACK_APP_TOKEN")
SLACK_BOT_TOKEN = os.environ.get("SLACK_BOT_TOKEN")

app = App(token=SLACK_APP_TOKEN)
client = WebClient(token=SLACK_BOT_TOKEN)

def handle_age_request(channel, text):
    # Example string containing a date
    date_string = re.sub('&amp;lt;.*?&amp;gt;', '', text)
    date_string = re.sub(r"\s+", "", date_string)

    # Define the date format
    date_format = "%d-%m-%Y"

    # Convert the string to a datetime object
    date_object = datetime.strptime(date_string, date_format)
    dob = date_object.date()

    today = date.today()

    # Calculate the difference between the two dates
    delta = today - dob

    # Calculate the number of years
    years = delta.days // 365


    client.chat_postMessage(channel=channel, text=str(years))


@app.event("app_mention")
def handle_mention(event, say):
    channel = event.get('channel')
    text = event.get('text')
    handle_age_request(channel, text)


print("Start your bot")
handler = SocketModeHandler(app, app_token=SLACK_APP_TOKEN)
handler.start()

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

&lt;/div&gt;



&lt;p&gt;Now go to your workspace in Slack. In any of your channels, start a conversation with &lt;strong&gt;@AgeBot&lt;/strong&gt;. You may get this message "&lt;em&gt;You mentioned @AgeBot, but they’re not in this channel&lt;/em&gt;". Click &lt;strong&gt;Invite Them&lt;/strong&gt;. You can now message &lt;strong&gt;@AgeBot&lt;/strong&gt;. Type &lt;strong&gt;@AgeBot&lt;/strong&gt; 25-12-2000. Given that the date of writing this blog is 30-11-2023 &lt;strong&gt;AgeBot&lt;/strong&gt; will respond with 22. This concludes our lesson. &lt;/p&gt;

</description>
      <category>python</category>
      <category>slackbot</category>
    </item>
    <item>
      <title>Creating a movie finder app with Streamlit and OMDb API</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Mon, 27 Nov 2023 17:13:09 +0000</pubDate>
      <link>https://dev.to/david001/creating-a-movie-finder-app-with-streamlit-and-omdb-api-2fak</link>
      <guid>https://dev.to/david001/creating-a-movie-finder-app-with-streamlit-and-omdb-api-2fak</guid>
      <description>&lt;p&gt;In this lesson, we will go through the steps of creating a movie finder app using Streamlit and the OMDb API. Streamlit is an open-source Python library that makes it easy to create custom web apps. You can easily integrate popular data visualization libraries into your Streamlit app. The OMDb API is a RESTful web service for retrieving movie information. Our movie finder app will have a feature to filter the movie results by type either movie or series, by year of release and by IMDB rating. It will also have a feature to plot the ratings and votes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Must be familiar with Python&lt;/li&gt;
&lt;li&gt;Must have &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fwww.python.org%2Fdownloads%2F" rel="noopener noreferrer"&gt;Python&lt;/a&gt; (at least version 3.8)  installed&lt;/li&gt;
&lt;li&gt;Sign up for &lt;a href="https://share.streamlit.io/signup" rel="noopener noreferrer"&gt;Streamlit account&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sign up for &lt;a href="https://www.omdbapi.com/apikey.aspx?__EVENTTARGET=freeAcct&amp;amp;__EVENTARGUMENT=&amp;amp;__LASTFOCUS=&amp;amp;__VIEWSTATE=%2FwEPDwUKLTIwNDY4MTIzNQ9kFgYCAQ9kFgICBw8WAh4HVmlzaWJsZWhkAgIPFgIfAGhkAgMPFgIfAGhkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYDBQtwYXRyZW9uQWNjdAUIZnJlZUFjY3QFCGZyZWVBY2N0oCxKYG7xaZwy2ktIrVmWGdWzxj%2FDhHQaAqqFYTiRTDE%3D&amp;amp;__VIEWSTATEGENERATOR=5E550F58&amp;amp;__EVENTVALIDATION=%2FwEdAAU%2BO86JjTqdg0yhuGR2tBukmSzhXfnlWWVdWIamVouVTzfZJuQDpLVS6HZFWq5fYpioiDjxFjSdCQfbG0SWduXFd8BcWGH1ot0k0SO7CfuulHLL4j%2B3qCcW3ReXhfb4KKsSs3zlQ%2B48KY6Qzm7wzZbR&amp;amp;at=freeAcct&amp;amp;Email=" rel="noopener noreferrer"&gt;OMDb API Key&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Procedure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a folder called &lt;strong&gt;streamlit-movie-info&lt;/strong&gt;.&lt;br&gt;
Navigate into this folder by typing the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd streamlit-movie-info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a virtual environment by entering the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;virtualenv venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate the virtual environment using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;venv\Scripts\activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install streamlit using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install streamlit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will also be plotting the ratings and votes, so we need to install &lt;strong&gt;plotly-express&lt;/strong&gt; with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install plotly-express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a folder called &lt;strong&gt;.streamlit&lt;/strong&gt;. Make sure it is called &lt;strong&gt;.streamlit&lt;/strong&gt; and not streamlit.&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;.streamlit&lt;/strong&gt; folder, create a file called &lt;strong&gt;secrets.toml&lt;/strong&gt;. Put your OMDb API here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omdb_api = "YOUR OMDb API"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a custom poster image for movies that don't have a poster. You can create this image using any software. Call this image &lt;strong&gt;film-solid.png&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Create a python script called &lt;strong&gt;streamlit_app.py&lt;/strong&gt;. Now we are going to write code. First we need to import the required libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import streamlit as st
import requests
import pandas as pd
import plotly.express as px
from datetime import datetime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the title for the app. This code will display the text in title formatting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Streamlit app title
st.title("Movie Finder App")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an input element for user to enter movie title. This code will display a single-line text input widget. This is the movie search field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# User input for movie title
movie_title = st.text_input("Enter Movie Title", "")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The year filter will have a range from 1900 to the current year. The current year is obtained using the following code snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Current Year
current_year = datetime.now().year
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need a variable to store the movie search results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Dataframe for storing all movie data
movies_df = pd.DataFrame()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the filter options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Filter options
type_filter = st.selectbox("Filter by Type", ["movie", "series"])
year_filter = st.slider("Filter by Release Year", min_value=1900, max_value=current_year, step=1, value=(1900, current_year))
rating_filter = st.slider("Filter by IMDb Rating", min_value=0.0, max_value=10.0, step=0.1, value=(0.0, 10.0))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are 2 slider widgets and 1 select widget. The type filter is the select widget with 2 options: movie and series. The year of release filter is the slider widget which has a range from 1900 to the current year. The IMDB rating filter is also a slider widget which has a range from 0.0 to 10.0 with increments of 0.1.&lt;br&gt;
Get the results of query using the following code snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Search for the movie using the OMDB API
if movie_title:
  omdb_api_url = "http://www.omdbapi.com/"    
  api_key = st.secrets["omdb_api"] # OMDb API key (you need to sign up for a free API key)

  params = {
    "apikey": api_key,
    "s": movie_title,
    "type": type_filter,
    "y": f"{year_filter[0]}-{year_filter[1]}",    
    "r": "json"
  }

  with st.spinner('Processing...'):    

    response = requests.get(omdb_api_url, params=params)
    data = response.json()

    # Filter and display movie details
    if "Search" in data:      
      for movie in data["Search"]:
        # Additional request to get detailed information for each movie
        detailed_params = {"apikey": api_key, "i": movie["imdbID"], "plot":"full", "r": "json"}
        detailed_response = requests.get(omdb_api_url, params=detailed_params)
        detailed_data = detailed_response.json()


        detailed_data["Year"] = detailed_data["Year"].rstrip("–")  
        # Apply additional filters
        if (
            (
              type_filter == 'movie' and            
              year_filter[0] &amp;lt;= int(detailed_data["Year"]) &amp;lt;= year_filter[1] and    
              detailed_data["imdbRating"] != "N/A" and
              rating_filter[0] &amp;lt;= float(detailed_data["imdbRating"]) &amp;lt;= rating_filter[1]
            ) or  
            (
              type_filter == 'series' and                        
              detailed_data["imdbRating"] != "N/A" and
              rating_filter[0] &amp;lt;= float(detailed_data["imdbRating"]) &amp;lt;= rating_filter[1]
            )    
        ):     

          # Temporarily store movie detail in this dataframe.                                         
          new_row_df = pd.DataFrame({'Poster':[detailed_data['Poster']],
                                    'Title':[f"{detailed_data['Title']} ({detailed_data['Year']})"],
                                    'Year':[detailed_data['Year']],
                                    'Rated':[detailed_data['Rated']],
                                    'Runtime':[detailed_data['Runtime']],
                                    'Released':[detailed_data['Released']],
                                    'Genre':[detailed_data['Genre']],
                                    'Director':[detailed_data['Director']],
                                    'Writer':[detailed_data['Writer']],
                                    'Actors':[detailed_data['Actors']],
                                    'Language':[detailed_data['Language']],
                                    'Country':[detailed_data['Country']],
                                    'Awards':[detailed_data['Awards']],
                                    'Plot': [detailed_data['Plot']],
                                    'IMDB Rating': [detailed_data['imdbRating']],
                                    'IMDB Votes': [detailed_data['imdbVotes']],                                    
                                    })

          # Add movie detail dataframe to the main dataframe containing all movies
          movies_df = pd.concat([movies_df, new_row_df], ignore_index=True)                                             
    else:
      st.warning("No movies found for the specified criteria.")
else:
  st.warning("Please enter a movie title.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Breakdown&lt;/strong&gt;&lt;br&gt;
First we check if the movie search is not empty. If it is, we throw a warning using &lt;strong&gt;st.warning&lt;/strong&gt;. Then we set the OMDb API url and API key. The API key is stored in the &lt;strong&gt;secrets.toml&lt;/strong&gt; file and is called &lt;strong&gt;omdb_api&lt;/strong&gt;. We can access this key using &lt;strong&gt;st.secrets&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;omdb_api_url = "http://www.omdbapi.com/"    
api_key = st.secrets["omdb_api"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the other parameters. The "&lt;strong&gt;s&lt;/strong&gt;" field sets the movie title to search for. The "&lt;strong&gt;type&lt;/strong&gt;" field sets the type of result to return. In this case, it is either movie or series. The "&lt;strong&gt;y&lt;/strong&gt;" field sets the year of release. In this case, it is between 1900 and the current year. The "&lt;strong&gt;r&lt;/strong&gt;" field sets the data type to return.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;params = {
    "apikey": api_key,
    "s": movie_title,
    "type": type_filter,
    "y": f"{year_filter[0]}-{year_filter[1]}",    
    "r": "json"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will be using a spinner to indicate that searching is in progress. This widget temporarily shows a message while a code block is being executed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;with st.spinner('Processing...')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the response from the query and load JSON data into a Python object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;response = requests.get(omdb_api_url, params=params)
data = response.json()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if there are any results. If there are no results throw a warning using &lt;strong&gt;st.warning&lt;/strong&gt;. If there are results, iterate through each item in the search results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for movie in data["Search"]:
  # Additional request to get detailed information for each movie
  detailed_params = {"apikey": api_key, "i": movie["imdbID"], "plot":"full", "r": "json"}
  detailed_response = requests.get(omdb_api_url, params=detailed_params)
  detailed_data = detailed_response.json()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like before, set the parameters. The "&lt;strong&gt;i&lt;/strong&gt;" field sets the IMDb ID. The "plot" field determines if to use the short or full plot. &lt;/p&gt;

&lt;p&gt;Sometimes the "&lt;strong&gt;year&lt;/strong&gt;" parameter in the search results may contain an invalid number. Remove the additional character.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;detailed_data["Year"] = detailed_data["Year"].rstrip("–")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the filters. &lt;strong&gt;Note&lt;/strong&gt;: For there is no year of release for &lt;strong&gt;type: series&lt;/strong&gt;. Therefore, the year filter does not affect this type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (
  (
    type_filter == 'movie' and            
    year_filter[0] &amp;lt;= int(detailed_data["Year"]) &amp;lt;= year_filter[1] and    
    detailed_data["imdbRating"] != "N/A" and
    rating_filter[0] &amp;lt;= float(detailed_data["imdbRating"]) &amp;lt;= rating_filter[1]
  ) or  
  (
    type_filter == 'series' and                        
    detailed_data["imdbRating"] != "N/A" and
    rating_filter[0] &amp;lt;= float(detailed_data["imdbRating"]) &amp;lt;= rating_filter[1]
  )    
):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temporarily store the result in a variable called &lt;strong&gt;new_row_df&lt;/strong&gt;. This variable will be concatenated with the main variable containing all results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Temporarily store movie detail in this dataframe.                                         
new_row_df = pd.DataFrame({'Poster':[detailed_data['Poster']],
                          'Title':[f"{detailed_data['Title']} ({detailed_data['Year']})"],
                          'Year':[detailed_data['Year']],
                          'Rated':[detailed_data['Rated']],
                          'Runtime':[detailed_data['Runtime']],
                          'Released':[detailed_data['Released']],
                          'Genre':[detailed_data['Genre']],
                          'Director':[detailed_data['Director']],
                          'Writer':[detailed_data['Writer']],
                          'Actors':[detailed_data['Actors']],
                          'Language':[detailed_data['Language']],
                          'Country':[detailed_data['Country']],
                          'Awards':[detailed_data['Awards']],
                          'Plot': [detailed_data['Plot']],
                          'IMDB Rating': [detailed_data['imdbRating']],
                          'IMDB Votes': [detailed_data['imdbVotes']],                                    
                          })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Concatenate the temporary variable with the main variable called &lt;strong&gt;movies_df&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;# Add movie detail dataframe to the main dataframe containing all movies
movies_df = pd.concat([movies_df, new_row_df], ignore_index=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have to create the visualize the data. Create two tabs. The first tab contains the search results with the movie details. The second tab contains the plots of the Ratings and Reviews.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Setup tabs
tab1, tab2 = st.tabs(["Search Results", "Ratings and Votes"])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first tab print out all the movie details such as poster, title, rating, rated, runtime, released, genre, director, writer, actors, plot, language, country and awards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;with tab1:
  if(len(movies_df)&amp;gt;0):
    st.header("Search Results")          
    for i in range(len(movies_df)):
      col1, col2 = st.columns([1,2])
      with col1:
        # Display movie poster              
        if(movies_df['Poster'][i]!="N/A"):
          st.image(movies_df['Poster'][i], caption=movies_df['Title'][i], use_column_width=True)
        else:
        # If there is no movie poster, use custom movie poster  
          st.image("film-solid.png")               

      with col2:  
        # Display movie details
        st.subheader(movies_df['Title'][i])              

        col1, col2, col3 = st.columns(3)          
        col1.write(f"IMDb Rating: {movies_df['IMDB Rating'][i]}")    
        col2.write(f"Rated: {movies_df['Rated'][i]}")          
        col3.write(f"Runtime: {movies_df['Runtime'][i]}")

        st.write(f"Released: {movies_df['Released'][i]}")          
        st.write(f"Genre: {movies_df['Genre'][i]}")
        st.write(f"Director: {movies_df['Director'][i]}")
        st.write(f"Writer: {movies_df['Writer'][i]}")
        st.write(f"Actors: {movies_df['Actors'][i]}")
        st.write(f"Plot: {movies_df['Plot'][i]}")        
        st.write(f"Language: {movies_df['Language'][i]}")
        st.write(f"Country: {movies_df['Country'][i]}")
        st.write(f"Awards: {movies_df['Awards'][i]}")

      st.divider()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All text content is printed using &lt;strong&gt;st.write&lt;/strong&gt;. Images are displayed using &lt;strong&gt;st.image&lt;/strong&gt;. &lt;strong&gt;st.header&lt;/strong&gt; and &lt;strong&gt;st.subheader&lt;/strong&gt; display the text in header and sub-header formats. st.columns creates columns. In this case, there are 3 columns: IMDb Rating, Rated and Runtime. &lt;strong&gt;st.divider&lt;/strong&gt; displays a horizontal rule.&lt;/p&gt;

&lt;p&gt;In the second tab plot the ratings and votes for the movies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Plots of Ratings and Votes
with tab2:
  if(len(movies_df)&amp;gt;0):
    fig = px.bar(movies_df, x='Title', y='IMDB Rating')  
    st.header("IMDB Ratings")
    st.plotly_chart(fig, theme="streamlit", use_container_width=True) 

    fig = px.bar(movies_df, x='Title', y='IMDB Votes')  
    st.header("IMDB Votes")
    st.plotly_chart(fig, theme="streamlit", use_container_width=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plot type is a bar chart. The x axis contains the title of the movies and y axis contains IMDB Ratings or Votes. &lt;strong&gt;st.plotly_chart&lt;/strong&gt; plots the chart. The theme is set to streamlit. The width of the chart is set to container width. To find out more information about &lt;strong&gt;st.plotly_chart&lt;/strong&gt; click &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fdocs.streamlit.io%2Flibrary%2Fapi-reference%2Fcharts%2Fst.plotly_chart" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The entire script should look 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 streamlit as st
import requests
import pandas as pd
import plotly.express as px
from datetime import datetime 

# Streamlit app title
st.title("Movie Finder App")

# User input for movie title
movie_title = st.text_input("Enter Movie Title", "")

# Current Year
current_year = datetime.now().year

# Dataframe for storing all movie data
movies_df = pd.DataFrame()

# Filter options
type_filter = st.selectbox("Filter by Type", ["movie", "series"])
year_filter = st.slider("Filter by Release Year", min_value=1900, max_value=current_year, step=1, value=(1900, current_year))
rating_filter = st.slider("Filter by IMDb Rating", min_value=0.0, max_value=10.0, step=0.1, value=(0.0, 10.0))

# Search for the movie using the OMDB API
if movie_title:
  omdb_api_url = "http://www.omdbapi.com/"    
  api_key = st.secrets["omdb_api"] # OMDb API key (you need to sign up for a free API key)

  params = {
    "apikey": api_key,
    "s": movie_title,
    "type": type_filter,
    "y": f"{year_filter[0]}-{year_filter[1]}",    
    "r": "json"
  }

  with st.spinner('Processing...'):    

    response = requests.get(omdb_api_url, params=params)
    data = response.json()

    # Filter and display movie details
    if "Search" in data:      
      for movie in data["Search"]:
        # Additional request to get detailed information for each movie
        detailed_params = {"apikey": api_key, "i": movie["imdbID"], "plot":"full", "r": "json"}
        detailed_response = requests.get(omdb_api_url, params=detailed_params)
        detailed_data = detailed_response.json()


        detailed_data["Year"] = detailed_data["Year"].rstrip("–")  
        # Apply additional filters
        if (
            (
              type_filter == 'movie' and            
              year_filter[0] &amp;lt;= int(detailed_data["Year"]) &amp;lt;= year_filter[1] and    
              detailed_data["imdbRating"] != "N/A" and
              rating_filter[0] &amp;lt;= float(detailed_data["imdbRating"]) &amp;lt;= rating_filter[1]
            ) or  
            (
              type_filter == 'series' and                        
              detailed_data["imdbRating"] != "N/A" and
              rating_filter[0] &amp;lt;= float(detailed_data["imdbRating"]) &amp;lt;= rating_filter[1]
            )    
        ):     

          # Temporarily store movie detail in this dataframe.                                         
          new_row_df = pd.DataFrame({'Poster':[detailed_data['Poster']],
                                    'Title':[f"{detailed_data['Title']} ({detailed_data['Year']})"],
                                    'Year':[detailed_data['Year']],
                                    'Rated':[detailed_data['Rated']],
                                    'Runtime':[detailed_data['Runtime']],
                                    'Released':[detailed_data['Released']],
                                    'Genre':[detailed_data['Genre']],
                                    'Director':[detailed_data['Director']],
                                    'Writer':[detailed_data['Writer']],
                                    'Actors':[detailed_data['Actors']],
                                    'Language':[detailed_data['Language']],
                                    'Country':[detailed_data['Country']],
                                    'Awards':[detailed_data['Awards']],
                                    'Plot': [detailed_data['Plot']],
                                    'IMDB Rating': [detailed_data['imdbRating']],
                                    'IMDB Votes': [detailed_data['imdbVotes']],                                    
                                    })

          # Add movie detail dataframe to the main dataframe containing all movies
          movies_df = pd.concat([movies_df, new_row_df], ignore_index=True)                                             
    else:
      st.warning("No movies found for the specified criteria.")
else:
  st.warning("Please enter a movie title.")

# Setup tabs
tab1, tab2 = st.tabs(["Search Results", "Ratings and Votes"])

# Search Results: List of movie details
with tab1:
  if(len(movies_df)&amp;gt;0):
    st.header("Search Results")          
    for i in range(len(movies_df)):
      col1, col2 = st.columns([1,2])
      with col1:
        # Display movie poster              
        if(movies_df['Poster'][i]!="N/A"):
          st.image(movies_df['Poster'][i], caption=movies_df['Title'][i], use_column_width=True)
        else:
        # If there is no movie poster, use custom movie poster  
          st.image("film-solid.png")               

      with col2:  
        # Display movie details
        st.subheader(movies_df['Title'][i])              

        col1, col2, col3 = st.columns(3)          
        col1.write(f"IMDb Rating: {movies_df['IMDB Rating'][i]}")    
        col2.write(f"Rated: {movies_df['Rated'][i]}")          
        col3.write(f"Runtime: {movies_df['Runtime'][i]}")

        st.write(f"Released: {movies_df['Released'][i]}")          
        st.write(f"Genre: {movies_df['Genre'][i]}")
        st.write(f"Director: {movies_df['Director'][i]}")
        st.write(f"Writer: {movies_df['Writer'][i]}")
        st.write(f"Actors: {movies_df['Actors'][i]}")
        st.write(f"Plot: {movies_df['Plot'][i]}")        
        st.write(f"Language: {movies_df['Language'][i]}")
        st.write(f"Country: {movies_df['Country'][i]}")
        st.write(f"Awards: {movies_df['Awards'][i]}")

      st.divider()     

# Plots of Ratings and Votes
with tab2:
  if(len(movies_df)&amp;gt;0):
    fig = px.bar(movies_df, x='Title', y='IMDB Rating')  
    st.header("IMDB Ratings")
    st.plotly_chart(fig, theme="streamlit", use_container_width=True) 

    fig = px.bar(movies_df, x='Title', y='IMDB Votes')  
    st.header("IMDB Votes")
    st.plotly_chart(fig, theme="streamlit", use_container_width=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the application by typing the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;streamlit run streamlit_app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;streamlit_app.py&lt;/strong&gt; is the name of the file we need to run.&lt;/p&gt;

&lt;p&gt;On the browser go to &lt;a href="http://localhost:8501/" rel="noopener noreferrer"&gt;http://localhost:8501/&lt;/a&gt;. You will see the following screen.&lt;/p&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%2Ft27io0o3qef4mpa78v69.jpg" 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%2Ft27io0o3qef4mpa78v69.jpg" alt="Image description" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, search for the dark knight. There are multiple results. This is only one of them.&lt;/p&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%2Fpbo6l4pirgr8qdo119m1.jpg" 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%2Fpbo6l4pirgr8qdo119m1.jpg" alt="Image description" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;View the plots.&lt;/p&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%2F3m37rghcbnxfwnsjn3dp.jpg" 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%2F3m37rghcbnxfwnsjn3dp.jpg" alt="Image description" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&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%2Fjge5m042pa6tpgwcbhxe.jpg" 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%2Fjge5m042pa6tpgwcbhxe.jpg" alt="Image description" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This concludes our lesson. For more information on Streamlit, check the documentation &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fdocs.streamlit.io%2Flibrary%2Fget-started" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>streamlit</category>
      <category>python</category>
    </item>
    <item>
      <title>Using Plotly.js with React</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Fri, 17 Nov 2023 15:17:21 +0000</pubDate>
      <link>https://dev.to/david001/using-plotlyjs-with-react-el8</link>
      <guid>https://dev.to/david001/using-plotlyjs-with-react-el8</guid>
      <description>&lt;p&gt;In this lesson, we will go through the steps of using &lt;a href="https://plotly.com/javascript/" rel="noopener noreferrer"&gt;Plotly.js&lt;/a&gt; in &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt;. Plotly.js is an Open Source Graphing Library. At the end of this lesson, you should be able to do a simple plot with Plotly.js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be familiar with JavaScript&lt;/li&gt;
&lt;li&gt;Must be familiar with installing NPM packages&lt;/li&gt;
&lt;li&gt;Must have React installed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Procedure&lt;/strong&gt;&lt;br&gt;
Create a new react project called &lt;strong&gt;react-plotly&lt;/strong&gt; by typing the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app react-plotly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate into the &lt;strong&gt;react-plotly&lt;/strong&gt; project folder by typing the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd react-plotly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Plotly.js for React by typing the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-plotly.js plotly.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider a fictional scenario, where a doctor or nurse needs to see the growth rate of boys. In this example we will be plotting this data. The x-axis contains the age and the y-axis contains the height.&lt;/p&gt;

&lt;p&gt;Clear the styling of the React app by opening the &lt;strong&gt;App.css&lt;/strong&gt; file and deleting all the contents.&lt;/p&gt;

&lt;p&gt;Replace the contents in the &lt;strong&gt;App.js&lt;/strong&gt; file with the code below. (&lt;strong&gt;Note&lt;/strong&gt;: The values are fictional).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "./App.css";
import Plot from "react-plotly.js";

function App() {
  return (
    &amp;lt;div
      className="App"
      style={{
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        height: "100vh",
      }}
    &amp;gt;
      &amp;lt;Plot
        data={[
          {
            x: [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18],
            y: [32, 37, 40.5, 43, 49, 54, 59, 63.5, 69.5, 73, 74],
            mode: "markers",
            type: "scatter",
          },
        ]}
        layout={{
          title: "Growth Rate in Boys",
          xaxis: {
            title: "Age (years)",
          },
          yaxis: {
            title: "Height (inches)",
          },
        }}
      /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;Run the React app typing the following in the command terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the browser go to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;. You will see the following graph in the middle of the screen.&lt;/p&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%2Fwqx0zxr8kqp58a3mg5xn.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%2Fwqx0zxr8kqp58a3mg5xn.png" alt="Image description" width="700" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;data&lt;/strong&gt; property contains the &lt;strong&gt;x&lt;/strong&gt; data, &lt;strong&gt;y&lt;/strong&gt; data, the &lt;strong&gt;mode&lt;/strong&gt; and the &lt;strong&gt;type&lt;/strong&gt;. In this example, the &lt;strong&gt;x&lt;/strong&gt; array contains the ages and the &lt;strong&gt;y&lt;/strong&gt; array contains the heights. The mode is set to &lt;strong&gt;markers&lt;/strong&gt;. Some other modes are &lt;strong&gt;lines&lt;/strong&gt;, &lt;strong&gt;lines+markers&lt;/strong&gt;, &lt;strong&gt;markers+text&lt;/strong&gt; and &lt;strong&gt;none&lt;/strong&gt;. The type is set to &lt;strong&gt;scatter&lt;/strong&gt;. Some other types are &lt;strong&gt;bar&lt;/strong&gt;, &lt;strong&gt;pie&lt;/strong&gt; and &lt;strong&gt;sunburst&lt;/strong&gt;. The &lt;strong&gt;layout&lt;/strong&gt; property sets the title of the plot, x-axis label and y-axis label. For example, the x-label is set using the following code snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xaxis: {
  title: "Age (years)",
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are other types of charts which can be found &lt;a href="https://plotly.com/javascript/basic-charts/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Multiple plots can be displayed on the same graph. In this example, we will include the growth rate of girls.&lt;/p&gt;

&lt;p&gt;In order to distinguish the two plots add the &lt;strong&gt;name&lt;/strong&gt; property under &lt;strong&gt;type&lt;/strong&gt; as shown below. This will be shown in the legend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  x: [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18],
  y: [32, 37, 40.5, 43, 49, 54, 59, 63.5, 69.5, 73, 74],
  mode: "markers",
  type: "scatter",
  name: "Boys",
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following snippet of code in the &lt;strong&gt;data&lt;/strong&gt; property as shown below. The age and height data for the girls are added. (&lt;strong&gt;Note&lt;/strong&gt;: The values are fictional). Plotly.js automatically assigns different colors for each plot. The color for the plot can be changed. In this example, the color for the girls’ data was changed to red.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  x: [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18],
  y: [32, 37, 40.5, 43, 49, 54, 59, 63.5, 69.5, 73, 74],
  mode: "markers",
  type: "scatter",
  name: "Boys",
},
{
  x: [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18],
  y: [30, 36, 39, 42, 48, 53, 58, 62, 67.5, 68, 68.5],
  mode: "lines+markers",
  type: "scatter",
  name: "Girls",
  marker: { color: "red" },
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The size of the plot can be changed. Edit the &lt;strong&gt;width&lt;/strong&gt; and &lt;strong&gt;height&lt;/strong&gt; as seen below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;layout={{
  title: "Growth Rate in Boys",
  xaxis: {
    title: "Age (years)",
  },
  yaxis: {
    title: "Height (inches)",
  },
  width: 600,
  height: 500,
}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire should look like this. The title was changed to &lt;strong&gt;Growth Rate in Children&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 "./App.css";
import Plot from "react-plotly.js";

function App() {
  return (
    &amp;lt;div
      className="App"
      style={{
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        height: "100vh",
      }}
    &amp;gt;
      &amp;lt;Plot
        data={[
          {
            x: [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18],
            y: [32, 37, 40.5, 43, 49, 54, 59, 63.5, 69.5, 73, 74],
            mode: "markers",
            type: "scatter",
            name: "Boys",
          },
          {
            x: [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18],
            y: [30, 36, 39, 42, 48, 53, 58, 62, 67.5, 68, 68.5],
            mode: "lines+markers",
            type: "scatter",
            name: "Girls",
            marker: { color: "red" },
          },
        ]}
        layout={{
          title: "Growth Rate in Children",
          xaxis: {
            title: "Age (years)",
          },
          yaxis: {
            title: "Height (inches)",
          },
          width: 600,
          height: 500,
        }}
      /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;On the browser go to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;. You will see the following graph in the middle of the screen.&lt;/p&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%2Fl6k61rn2k69t0h1lcat9.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%2Fl6k61rn2k69t0h1lcat9.png" alt="Image description" width="600" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you hover over the plot, there are some controls at the top as shown below.&lt;/p&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%2Fsg3swn6dt9u9ewh911kw.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%2Fsg3swn6dt9u9ewh911kw.png" alt="Image description" width="271" height="34"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These allow you to download the plot as a png, zoom, pan, select, zoom in, zoom out, auto-scale and reset axes. You can also hover the points to see their values.&lt;/p&gt;

&lt;p&gt;This concludes our lesson. For more information on Plotly.js, check the documentation &lt;a href="https://plotly.com/javascript/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>plotly</category>
      <category>react</category>
    </item>
    <item>
      <title>Using CesiumJS with Angular</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Thu, 08 Jun 2023 14:55:27 +0000</pubDate>
      <link>https://dev.to/david001/using-cesiumjs-with-angular-4kh1</link>
      <guid>https://dev.to/david001/using-cesiumjs-with-angular-4kh1</guid>
      <description>&lt;p&gt;In this lesson, we will go through the steps of integrating CesiumJS with Angular. CesiumJS is an open source JavaScript library for creating 3D globes and maps. At the end of the lesson you should be able to do a simple plot with CesiumJS.&lt;/p&gt;

&lt;p&gt;Prerequisite&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be familiar with Angular&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a new angular project called &lt;strong&gt;angular-plotly&lt;/strong&gt;. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng new angular-cesium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted “&lt;em&gt;Would you like to add Angular routing? (y/N)&lt;/em&gt;”, you can type either y or N and hit Enter on the keyboard. When prompted “&lt;em&gt;Which stylesheet format would you like to use?&lt;/em&gt;”, you can select CSS.&lt;/p&gt;

&lt;p&gt;Navigate into the &lt;strong&gt;angular-cesium&lt;/strong&gt; directory. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd angular-cesium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new component called &lt;strong&gt;cesium-component&lt;/strong&gt;. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate component cesium-component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;strong&gt;app.component.html&lt;/strong&gt; ,delete all the contents and add the following line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;app-cesium-component&amp;gt;&amp;lt;/app-cesium-component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to &lt;a href="https://cesium.com/downloads/" rel="noopener noreferrer"&gt;CesiumJS&lt;/a&gt;. There will be 2 options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install from NPM&lt;/li&gt;
&lt;li&gt;Download CesiumJS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this demonstration, download CesiumJS and unzip the file.&lt;/p&gt;

&lt;p&gt;Copy the &lt;strong&gt;Cesium&lt;/strong&gt; folder (from the unzipped folder) in &lt;strong&gt;Cesium-1.96/Build to angular-cesium/src/assets&lt;/strong&gt; (your angular project).&lt;/p&gt;

&lt;p&gt;Open the &lt;strong&gt;angular.json&lt;/strong&gt; file and modify the styles and scripts as seen below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"styles": [
  "src/styles.css",
  "src/assets/Cesium/Widgets/widgets.css"
],
"scripts": [
  "src/assets/Cesium/Cesium.js"
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are having difficulty finding the specific lines to modify, simply search for the keyword &lt;strong&gt;scripts&lt;/strong&gt;. This is the complete code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "angular-cesium": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:application": {
          "strict": true
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/angular-cesium",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css",
              "src/assets/Cesium/Widgets/widgets.css"
            ],
            "scripts": [
              "src/assets/Cesium/Cesium.js"
            ]
          },
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "500kb",
                  "maximumError": "1mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "2kb",
                  "maximumError": "4kb"
                }
              ],
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "outputHashing": "all"
            },
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true
            }
          },
          "defaultConfiguration": "production"
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "configurations": {
            "production": {
              "browserTarget": "angular-cesium:build:production"
            },
            "development": {
              "browserTarget": "angular-cesium:build:development"
            }
          },
          "defaultConfiguration": "development"
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "angular-cesium:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css",
              "src/assets/Cesium/Widgets/widgets.css"
            ],
            "scripts": [
              "src/assets/Cesium/Cesium.js"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "angular-cesium"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new service called &lt;strong&gt;cesium&lt;/strong&gt;. This service will contain the plot functions. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate service cesium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to create an account in Cesium &lt;a href="https://ion.cesium.com/signin?" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;Access Tokens&lt;/strong&gt; and click &lt;strong&gt;Create token&lt;/strong&gt;. Give it a name and click &lt;strong&gt;Create&lt;/strong&gt;. In this demonstration the name is &lt;strong&gt;cesiumtest&lt;/strong&gt;.&lt;/p&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%2F9h946m9ytpzj8ovnq5dz.jpg" 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%2F9h946m9ytpzj8ovnq5dz.jpg" alt="Image description" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the token you just created and copy the the token.&lt;/p&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%2Fpqpnyq4pdi0yifagyvp3.jpg" 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%2Fpqpnyq4pdi0yifagyvp3.jpg" alt="Image description" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open &lt;strong&gt;cesium.service.ts&lt;/strong&gt; and make the following changes as seen below. For &lt;strong&gt;Cesium.Ion.defaultAccessToken&lt;/strong&gt;, paste your token. Here we created a function called &lt;strong&gt;plotPoints&lt;/strong&gt; which takes an argument &lt;strong&gt;div&lt;/strong&gt;. This is the id of the div tag used for displaying the plot. Three points will be plotted at the following coordinates&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latitude: 40.03883, Longitude: -75.59777, Color: Red&lt;/li&gt;
&lt;li&gt;Latitude: 35.14, Longitude: -80.5, Color: Blue&lt;/li&gt;
&lt;li&gt;Latitude: 25.46, Longitude: -80.12, Color: Yellow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the points have a pixel size of 16. For more information the &lt;strong&gt;Cesium.Cartesian3.fromDegrees&lt;/strong&gt; method on visit this &lt;a href="https://cesium.com/learn/cesiumjs/ref-doc/Cartesian3.html" rel="noopener noreferrer"&gt;link&lt;/a&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 { Injectable } from '@angular/core';
declare let Cesium: any;
// import * as Cesium from '../assets/js/Cesium.js';
Cesium.Ion.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2MWZlOTZjMy1iYjhiLTRkYjktOWEyYS0xYjllYWM4NmQ3YjYiLCJpZCI6ODM1MzksImlhdCI6MTY2MTU0NTg0MX0.PBHIiiQPO0_kfthCfRxp4VVGlhFZp4BMKIeILBwYuqk";@Injectable({
  providedIn: 'root'
})
export class CesiumService {constructor() { }
  private viewer: any;plotPoints(div:string){
    this.viewer = new Cesium.Viewer(div);
    this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
      point: {
        color: Cesium.Color.RED,
        pixelSize: 16,
      },
    });
    this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-80.5, 35.14),
      point: {
        color: Cesium.Color.BLUE,
        pixelSize: 16,
      },
    });
    this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(-80.12, 25.46),
      point: {
        color: Cesium.Color.YELLOW,
        pixelSize: 16,
      },
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;strong&gt;cesium-component.component.ts&lt;/strong&gt; and make the following changes as seen below. When the page loads, 3 points will be plotted on a 3D globe. The id of the div displaying the plot is “cesium”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, OnInit } from '@angular/core';
import { CesiumService } from '../cesium.service';@Component({
  selector: 'app-cesium-component',
  templateUrl: './cesium-component.component.html',
  styleUrls: ['./cesium-component.component.css']
})
export class CesiumComponentComponent implements OnInit {constructor(private cesium: CesiumService) { }ngOnInit(): void {
    this.cesium.plotPoints("cesium");
  }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;strong&gt;cesium-component.component.html&lt;/strong&gt; and make the following changes. Here the div with the id &lt;strong&gt;cesium&lt;/strong&gt; is created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="cesium"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;strong&gt;index.html&lt;/strong&gt; from &lt;strong&gt;angular-cesium/src&lt;/strong&gt; and make the following changes as seen below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;title&amp;gt;AngularCesium&amp;lt;/title&amp;gt;
  &amp;lt;base href="/"&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1"&amp;gt;
  &amp;lt;link rel="icon" type="image/x-icon" href="favicon.ico"&amp;gt;
  &amp;lt;script&amp;gt;
    window.CESIUM_BASE_URL = 'http://localhost:4200/assets/Cesium/';
  &amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;app-root&amp;gt;&amp;lt;/app-root&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On your browser go to &lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt;. You should see the plot.&lt;/p&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%2Fgpn6p29bzpunaqkjddyi.jpg" 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%2Fgpn6p29bzpunaqkjddyi.jpg" alt="Image description" width="596" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the end of the lesson. For more examples on CesiumJS, check the documentation &lt;a href="https://sandcastle.cesium.com/?src=Points.html&amp;amp;label=Beginner" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cesium</category>
      <category>angular</category>
      <category>plotly</category>
    </item>
    <item>
      <title>Using Plotly.js with Angular</title>
      <dc:creator>David Akim</dc:creator>
      <pubDate>Thu, 08 Jun 2023 14:17:25 +0000</pubDate>
      <link>https://dev.to/david001/using-plotlyjs-with-angular-31jd</link>
      <guid>https://dev.to/david001/using-plotlyjs-with-angular-31jd</guid>
      <description>&lt;p&gt;In this lesson, we will go through the steps of integrating Plotly.js with Angular. Plotly.js is an Open Source Graphing Library. At the end of the lesson you should be able to do a simple plot with Plotly.js.&lt;/p&gt;

&lt;p&gt;Prerequisite&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be familiar with Angular&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a new angular project called &lt;strong&gt;angular-plotly&lt;/strong&gt;. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng new angular-plotly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted “&lt;em&gt;Would you like to add Angular routing? (y/N)&lt;/em&gt;”, you can type either y or N and hit Enter on the keyboard. When prompted “&lt;em&gt;Which stylesheet format would you like to use?&lt;/em&gt;”, you can select CSS.&lt;/p&gt;

&lt;p&gt;Navigate into the &lt;strong&gt;angular-plotly&lt;/strong&gt; directory. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd angular-plotly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new component called plotly-component. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate component plotly-component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open app.component.html ,delete all the contents and add the following line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;app-plotly-component&amp;gt;&amp;lt;/app-plotly-component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to &lt;a href="https://plotly.com/javascript/getting-started/" rel="noopener noreferrer"&gt;Plotly.js&lt;/a&gt;. There will be 3 options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install from NPM&lt;/li&gt;
&lt;li&gt;Use CDN link&lt;/li&gt;
&lt;li&gt;Download Plotly.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this demonstration, download Plotly.js.&lt;/p&gt;

&lt;p&gt;Copy the downloaded file into the assets folder of your angular project, which is located at &lt;strong&gt;angular-plotly/src/assets&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Open the &lt;strong&gt;angular.json&lt;/strong&gt; file and modify lines 35 and 104 as seen below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": ["src/assets/plotly-2.14.0.min.js"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are having difficulty finding the specific lines to modify, simply search for the keyword scripts. Please note at the time of writing this article the name of the script is &lt;strong&gt;plotly-2.14.0.min.js&lt;/strong&gt;. The name of your script may vary. This is the complete code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "cli": {
    "analytics": false
  },
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "angular-plotly": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:application": {
          "strict": true
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/angular-plotly",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": [
              "src/assets/plotly-2.14.0.min.js"
            ]
          },
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "500kb",
                  "maximumError": "1mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "2kb",
                  "maximumError": "4kb"
                }
              ],
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "outputHashing": "all"
            },
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true
            }
          },
          "defaultConfiguration": "production"
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "configurations": {
            "production": {
              "browserTarget": "angular-plotly:build:production"
            },
            "development": {
              "browserTarget": "angular-plotly:build:development"
            }
          },
          "defaultConfiguration": "development"
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "angular-plotly:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": [
              "src/assets/plotly-2.14.0.min.js"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "angular-plotly"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new service called &lt;strong&gt;plotly&lt;/strong&gt;. This service will contain the plot functions. In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate service plotly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;strong&gt;plotly.service.ts&lt;/strong&gt; and make the following changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@angular/core';declare let Plotly: any;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;plotly.service.ts&lt;/strong&gt; create a new function called &lt;strong&gt;plotLine&lt;/strong&gt;. This function accepts 4 arguments. The &lt;strong&gt;&lt;em&gt;title&lt;/em&gt;&lt;/strong&gt; argument is the title of the plot and &lt;strong&gt;&lt;em&gt;plotDiv&lt;/em&gt;&lt;/strong&gt; is the id of the div tag used for displaying the plot. The x and y arrays contain the plot data. This is the complete code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@angular/core';
declare let Plotly: any;@Injectable({
  providedIn: 'root'
})
export class PlotlyService {constructor() { }plotLine(title: string, plotDiv: string, x:number[], y:number[]){           
    let trace = {
      x: x,    
      y: y,   
      type: 'scatter'   
    };

    let layout = {
      title:title
    };

    Plotly.newPlot(plotDiv, [trace], layout);     
  }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;strong&gt;plotly-component.component.ts&lt;/strong&gt; and make the following changes. When the page loads, a straight line will be plotted. Here the title of the plot is “Line Plot”. The id of the div displaying the plot is “plot”. The x and y values are 1,2,3,4,5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, OnInit } from '@angular/core';
import { PlotlyService } from '../plotly.service';@Component({
  selector: 'app-plotly-component',
  templateUrl: './plotly-component.component.html',
  styleUrls: ['./plotly-component.component.css']
})
export class PlotlyComponentComponent implements OnInit {constructor(private plot:PlotlyService) { }ngOnInit(): void {
    let x:number[] = [1,2,3,4,5];
    let y:number[] = [1,2,3,4,5];
    this.plot.plotLine("Line Plot","plot",x,y);
  }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;em&gt;plotly-component.component.html&lt;/em&gt; and make the following changes. Here the div with the id &lt;strong&gt;plot&lt;/strong&gt; is created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="plot"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the command terminal type the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On your browser go to &lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt;. You should see the plot.&lt;/p&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%2Fki8k1k0zfc2qyme6wd16.jpg" 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%2Fki8k1k0zfc2qyme6wd16.jpg" alt="Image description" width="596" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the end of the lesson. For more information on Plotly.js, check the documentation &lt;a href="https://plotly.com/javascript/" rel="noopener noreferrer"&gt;Plotly&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>plotly</category>
      <category>angular</category>
    </item>
  </channel>
</rss>
