<?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: Muhammad Talha Akbar</title>
    <description>The latest articles on DEV Community by Muhammad Talha Akbar (@devtalhaakbar).</description>
    <link>https://dev.to/devtalhaakbar</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%2F38827%2F3cee5993-ab9b-4e96-8eb6-acd4fe4d1ed4.jpeg</url>
      <title>DEV Community: Muhammad Talha Akbar</title>
      <link>https://dev.to/devtalhaakbar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devtalhaakbar"/>
    <language>en</language>
    <item>
      <title>What would you do differently to build this simple form? Give your feedback!</title>
      <dc:creator>Muhammad Talha Akbar</dc:creator>
      <pubDate>Tue, 29 Aug 2023 12:32:03 +0000</pubDate>
      <link>https://dev.to/devtalhaakbar/what-would-you-do-differently-to-build-this-simple-form-give-your-feedback-3f43</link>
      <guid>https://dev.to/devtalhaakbar/what-would-you-do-differently-to-build-this-simple-form-give-your-feedback-3f43</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sXaT8_yb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tikcv9zyqw1d0x9oq86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sXaT8_yb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tikcv9zyqw1d0x9oq86.png" alt="Image description" width="692" height="793"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's been a while since I worked on a project from scratch. To check how things have since changed, I created a simple form project with React: &lt;a href="https://main--vocal-moxie-c759df.netlify.app/"&gt;https://main--vocal-moxie-c759df.netlify.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the repo: &lt;a href="https://github.com/dev-talha-akbar/react-recipe-form"&gt;https://github.com/dev-talha-akbar/react-recipe-form&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I have learned so far:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vite is fast and hassle-free. I have not had to change a single config.&lt;/li&gt;
&lt;li&gt;Bootstrap is still a great help. I could actually do way more with its well-documented and well-maintained components.&lt;/li&gt;
&lt;li&gt;It's hard to maintain state in React. It becomes frustrating to do simple operations especially on arrays.&lt;/li&gt;
&lt;li&gt;Since vanilla React easily becomes repetitive and frustrating, having React Query is a great addition to handle server logic.&lt;/li&gt;
&lt;li&gt;i18next is great but setting it up is a tricky endeavor with automatic file scans.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you had the chance to look at the source code or the demo, what would you have done differently? What would you do next?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Declarative Feedback on Vuex Actions through Vuex</title>
      <dc:creator>Muhammad Talha Akbar</dc:creator>
      <pubDate>Sun, 31 Jan 2021 16:59:08 +0000</pubDate>
      <link>https://dev.to/devtalhaakbar/declarative-feedback-on-vuex-actions-through-vuex-2me7</link>
      <guid>https://dev.to/devtalhaakbar/declarative-feedback-on-vuex-actions-through-vuex-2me7</guid>
      <description>&lt;p&gt;As a frontend developer, we come across many a times the scenario where we dispatch actions and in our components, have status "flags" that track whether that action is being processed aka. loading, succeeded or failed. And, then show an appropriate feedback to the user based on these flags. Take this Vue component with Vuex store as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;message&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Could not do something.&lt;span class="nt"&gt;&amp;lt;/message&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;message&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Did something successfully.&lt;span class="nt"&gt;&amp;lt;/message&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"doSomething()"&lt;/span&gt; &lt;span class="na"&gt;:disabled=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;spinner&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/spinner&amp;gt;&lt;/span&gt; Do Something
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;someAction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above, you can see, we have a simple, effective feedback state. However, it's repetitive and only available inside the component itself. What if we could make this tracking of action's state declarative, available globally and with almost no boilerplate? What if it was something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;action-status&lt;/span&gt; &lt;span class="na"&gt;:actionName=&lt;/span&gt;&lt;span class="s"&gt;"someAction"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;slot-scope=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ status }"&amp;gt;
      &lt;span class="nt"&gt;&amp;lt;message&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"status.error"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Could not do something.&lt;span class="nt"&gt;&amp;lt;/message&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;message&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"status.success"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Did something successfully.&lt;span class="nt"&gt;&amp;lt;/message&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"doSomething()"&lt;/span&gt; &lt;span class="na"&gt;:disabled=&lt;/span&gt;&lt;span class="s"&gt;"status.loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;spinner&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"status.loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/spinner&amp;gt;&lt;/span&gt; Do Something
      &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/action-status&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;someAction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you like the new way: a single neat component that takes the name of the Vuex action you want to observe and provides you with its status? If yes, here's how you can develop the &lt;code&gt;action-status&lt;/code&gt; component:&lt;/p&gt;

&lt;p&gt;The first step is to hook into our Vuex store and get updated about every action that is ever dispatched. To do that, you have &lt;code&gt;store.subscribeAction&lt;/code&gt; method available. It takes an object with 3 callbacks i.e. &lt;code&gt;before&lt;/code&gt;, &lt;code&gt;after&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt;. So, register all 3 callbacks with something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribeAction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second step is develop a store module named &lt;code&gt;actionStatus&lt;/code&gt; which will store the status of every action that is being dispatched. Here's how &lt;code&gt;actionStatus&lt;/code&gt; module will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;namespaced&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;statusAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;getters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;actionName&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;actionName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;NEW&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;SUCCESS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;trackNew&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NEW&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;trackSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUCCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;trackError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third step will be to dispatch &lt;code&gt;actionStatus&lt;/code&gt; actions inside our &lt;code&gt;store.subscribeAction&lt;/code&gt; hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isActionStatusAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;actionStatus) &amp;gt; -1;
}
store.subscribeAction({
  before(action) {
    if(!isActionStatusAction(action)) {
      store.dispatch(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;actionStatus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;trackNew&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, action);
    }
  },
  after(action) {
    if(!isActionStatusAction(action)) {
      store.dispatch(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;actionStatus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;trackSuccess&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, action);
    }
  },
  error(action, status, error) {
    // `error` is available too
    if(!isActionStatusAction(action)) {
      store.dispatch(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;actionStatus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;trackError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, action);
    }
  }
});
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fourth step is create the &lt;code&gt;action-status&lt;/code&gt; component that gets the status data about Vuex actions from the &lt;code&gt;actionStatus&lt;/code&gt; module and makes it available to be used in any Vue component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;actionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$scopedSlots&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;actionStatus/status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actionName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, with these 4 steps, we can now say goodbye status flags inside of our components and track any Vuex action from any Vue component. You can modify the above code to make the actual error object available in the &lt;code&gt;slot-scope&lt;/code&gt;, or modify it to accept multiple action names and report the status of each Vuex action inside your component. The possibilities are there.&lt;/p&gt;

&lt;p&gt;Finally, do you think it's something you will end up using in your project? Look forward to hear your feedback about this.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LDAP Directory &amp; SQL Database - Syncing the Unsyncable?</title>
      <dc:creator>Muhammad Talha Akbar</dc:creator>
      <pubDate>Mon, 30 Sep 2019 19:45:02 +0000</pubDate>
      <link>https://dev.to/devtalhaakbar/ldap-directory-sql-database-syncing-the-unsyncable-1c34</link>
      <guid>https://dev.to/devtalhaakbar/ldap-directory-sql-database-syncing-the-unsyncable-1c34</guid>
      <description>&lt;p&gt;While I would like to start this article by greeting you all and writing all that good stuff people put at the top but, let's just start by noting that we live in a world where nothing is perfect or at least the stuff humans come up with. One thing works great for one specific problem but, not so good for others. Like the IT guys would tell you how Directory Services are so good at managing users, computers, their access and security so, they would always like to keep that thing up and running. But, you, the developer, know how easy it is to query, sort, filter and associate data in Databases. So, how can we have the best of both? Of course, you could make something along the lines of DirectoryBase (something I totally made up just now) and for that I already wish you good luck. Or, we, the humble ones can continue along with syncing common data between the two services i.e. Directory Service and Database Service.&lt;/p&gt;

&lt;p&gt;You can think of syncing as keeping up with the changes i.e. when one thing changes, the other must too OR vice versa. Let's just discuss a case where you are developing an application that manages feedback about employees in your company. Your company already has every employee registered in their Directory Service and want to keep feedback items for each of their employees and the employee who gave that feedback. One way to architecture this simple application would be get access to the Directory Service and save feedback items as that employee's attributes but, this would not give you freedom of querying, sorting and filtering like you would have in a database. So, a better alternative would be to somehow bring the basic data about employees in a database table and create another table of feedbacks that keeps the feedback items.&lt;/p&gt;

&lt;p&gt;But, we're so humbly saying that we will fetch employee records from Directory Service and put them into our Database. What if some existing employee leaves, a new employee comes in or worst, some employee got his name or email changed? That's where we need to sync data b/w Directory Service and Database. Notice, we're considering Directory as source while Database as our destination. In some other scenario, you might want to have Database as source and Directory as destination. In very extreme cases, both Directory can act as source and destination. But, let's be humble and tackle our employee-feedback application with Directory as source and Database as destination.&lt;/p&gt;

&lt;p&gt;Where to start, you ask? I would suggest asking your very best internet friend Google. Just type your problem and let Google bring you solutions from the world of internet which is unless you want to reinvent several broken wheels yourself. However, since, I am writing this, I have already googled "syncing ldap and sql". The most popular result was this open source LDAP Synchronization Connector thingy aka. LSC.&lt;/p&gt;

&lt;p&gt;Now, before I go very specific about how LSC can help you avoid reinventing the wheel, I just want to clear a few things. Directory Service is a general concept and there are a lot of implementations of this concept on different platforms. For Windows, we have Active Directory Directory Services (yes, it's that long); for Linux, we have OpenLDAP. But, what unites all these implementations is this Lightweight Directory Access Protocol aka. LDAP. You can grab a LDAP implementation and talk to any platform-specific directory service. Hurray! And, that's what LSC builds upon. It syncs to any directory service using this LDAP protocol we just discussed. Ain't this world a beautiful place all of a sudden? Also, I would like to point out that specific implementations of these Directory Services might already give you tools to sync changes with some other application like Active Directory on Windows does. Active Directory allows you to poll for changes or subscribe to changes, implementation of which must be done by you, the developer. Active Directory recommends polling for changes is insanity: Checking again and again and expecting a lot of shit to change.&lt;/p&gt;

&lt;p&gt;LSC boasts itself to have already fixed some very strange bugs you would run into if you decide to implement your own DirectorySync Ninja - Ultimate Version (perhaps, something more catchy whatever). So, that's one reason to stick to LSC and the second reason would be that I have already gotten my hands dirty while fiddling around with it and would totally recommend it (mainly because it gets the job done).&lt;/p&gt;

&lt;p&gt;Before we can carry out this exciting experiment, you would need to setup following things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;LSC&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Directory Service&lt;/li&gt;
&lt;li&gt;SQL Database&lt;/li&gt;
&lt;li&gt;LSC Config&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Notes about LSC
&lt;/h2&gt;

&lt;p&gt;To install LSC on Ubuntu or Debian based Linux distro, you can do by following &lt;a href="https://lsc-project.org/documentation/latest/installation#apt_repository"&gt;this guide on LSC website&lt;/a&gt;. If you're using some other Operating System, you can check out the &lt;a href="https://lsc-project.org/download"&gt;Download page on LSC website&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes about Java - LSC dependency
&lt;/h2&gt;

&lt;p&gt;Since, LSC depends on Java, do setup Java on your machine. LSC documentation wants you to grab Java 6 but, I tried it with Java 8 and everything &lt;em&gt;almost&lt;/em&gt; works. Java 9 or above will not probably work as the code is bit old, I believe. It definitely didn't work on Java 11. Continuing your Java setup, make sure JAVA_HOME is in your PATH variable and if it's not, please do add it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes about Directory Service
&lt;/h2&gt;

&lt;p&gt;For directory service, you can use any implementation of it. However, if you don't have something up and running, you can always use &lt;a href="https://www.zflexsoftware.com/index.php/pages/free-online-ldap"&gt;this online LDAP server&lt;/a&gt;. If you don't have a shiny LDAP client, you can always use &lt;a href="https://direx.azurewebsites.net/home/connect"&gt;the one here&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Notes about Database Service
&lt;/h2&gt;

&lt;p&gt;For database, you can use any SQL implementation. I used MySQL. You can install and set it up honestly using any guide on the internet. If you're reading this, you probably already have it installed. &lt;strong&gt;Note:&lt;/strong&gt; Whatever implementation you choose, you must also install a JDBC Driver. For MySQL, you can find out &lt;a href="https://dev.mysql.com/downloads/connector/j/"&gt;how to install it here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  LSC Config
&lt;/h2&gt;

&lt;p&gt;Now, you're all done with installing stuff. LSC works by requiring you to edit a config file that is located at &lt;code&gt;/etc/lsc/lsc.xml&lt;/code&gt; if you're on Linux. This config file would tell LSC what services to connect to, what services to use as Source and Destination and the rules that may specify how the syncing process is carried out.&lt;/p&gt;

&lt;p&gt;Here's a sample config file that will work just fine to start out for our employee feedback application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" ?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;lsc&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://lsc-project.org/XSD/lsc-core-2.1.xsd"&lt;/span&gt; &lt;span class="na"&gt;revision=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;connections&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ldapConnection&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;ldap-src-conn&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;ldap://www.zflexldap.com:389/dc=zflexsoftware,dc=com&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;username&amp;gt;&lt;/span&gt;cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com&lt;span class="nt"&gt;&amp;lt;/username&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;password&amp;gt;&lt;/span&gt;zflexpass&lt;span class="nt"&gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;authentication&amp;gt;&lt;/span&gt;SIMPLE&lt;span class="nt"&gt;&amp;lt;/authentication&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;referral&amp;gt;&lt;/span&gt;IGNORE&lt;span class="nt"&gt;&amp;lt;/referral&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;derefAliases&amp;gt;&lt;/span&gt;NEVER&lt;span class="nt"&gt;&amp;lt;/derefAliases&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;VERSION_3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;pageSize&amp;gt;&lt;/span&gt;-1&lt;span class="nt"&gt;&amp;lt;/pageSize&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;factory&amp;gt;&lt;/span&gt;com.sun.jndi.ldap.LdapCtxFactory&lt;span class="nt"&gt;&amp;lt;/factory&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tlsActivated&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/tlsActivated&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ldapConnection&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;databaseConnection&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;jdbc-dst-conn&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;jdbc:mysql://127.0.0.1:3306/lsc&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;username&amp;gt;&lt;/span&gt;root&lt;span class="nt"&gt;&amp;lt;/username&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;password&amp;gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;driver&amp;gt;&lt;/span&gt;java.sql.DriverManager&lt;span class="nt"&gt;&amp;lt;/driver&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/databaseConnection&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/connections&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tasks&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;task&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Employees&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;bean&amp;gt;&lt;/span&gt;org.lsc.beans.SimpleBean&lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ldapSourceService&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;openldap-source-service-employee&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&lt;/span&gt; &lt;span class="na"&gt;reference=&lt;/span&gt;&lt;span class="s"&gt;"ldap-src-conn"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;baseDn&amp;gt;&lt;/span&gt;ou=users,ou=developers,dc=zflexsoftware,dc=com&lt;span class="nt"&gt;&amp;lt;/baseDn&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;pivotAttributes&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;uid&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/pivotAttributes&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;fetchedAttributes&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;cn&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;uid&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/fetchedAttributes&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;getAllFilter&amp;gt;&lt;/span&gt;(&lt;span class="ni"&gt;&amp;amp;amp;&lt;/span&gt;(objectClass=person)(uid=*))&lt;span class="nt"&gt;&amp;lt;/getAllFilter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;getOneFilter&amp;gt;&lt;/span&gt;(&lt;span class="ni"&gt;&amp;amp;amp;&lt;/span&gt;(objectClass=person)(uid={uid}))&lt;span class="nt"&gt;&amp;lt;/getOneFilter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;cleanFilter&amp;gt;&lt;/span&gt;(&lt;span class="ni"&gt;&amp;amp;amp;&lt;/span&gt;(objectClass=person)(uid={uid}))&lt;span class="nt"&gt;&amp;lt;/cleanFilter&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ldapSourceService&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;databaseDestinationService&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;mysql-src-service-client&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&lt;/span&gt; &lt;span class="na"&gt;reference=&lt;/span&gt;&lt;span class="s"&gt;"jdbc-dst-conn"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestNameForList&amp;gt;&lt;/span&gt;getEmployeeList&lt;span class="nt"&gt;&amp;lt;/requestNameForList&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestNameForObject&amp;gt;&lt;/span&gt;getEmployee&lt;span class="nt"&gt;&amp;lt;/requestNameForObject&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestsNameForInsert&amp;gt;&amp;lt;string&amp;gt;&lt;/span&gt;insertEmployee&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&amp;lt;/requestsNameForInsert&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestsNameForUpdate&amp;gt;&amp;lt;string&amp;gt;&lt;/span&gt;updateEmployee&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&amp;lt;/requestsNameForUpdate&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestsNameForDelete&amp;gt;&amp;lt;string&amp;gt;&lt;/span&gt;deleteEmployee&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&amp;lt;/requestsNameForDelete&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/databaseDestinationService&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;propertiesBasedSyncOptions&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mainIdentifier&amp;gt;&lt;/span&gt;srcBean.getMainIdentifier()&lt;span class="nt"&gt;&amp;lt;/mainIdentifier&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;defaultDelimiter&amp;gt;&lt;/span&gt;;&lt;span class="nt"&gt;&amp;lt;/defaultDelimiter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;defaultPolicy&amp;gt;&lt;/span&gt;FORCE&lt;span class="nt"&gt;&amp;lt;/defaultPolicy&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;conditions&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;create&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/create&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;update&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/update&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;delete&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/delete&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;changeId&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/changeId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/conditions&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/propertiesBasedSyncOptions&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/task&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tasks&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/lsc&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;del&gt;&lt;em&gt;If you've reached this far and are clueless, don't be. I will soon be updating this article. Just that my brain has now just jammed for the day plus, I just want to see whether people are actually interested in more of this.&lt;/em&gt;&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;Now, in the config file, you will see the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;ldapConnection&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;ldap-src-conn&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;ldap://www.zflexldap.com:389/dc=zflexsoftware,dc=com&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;username&amp;gt;&lt;/span&gt;cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com&lt;span class="nt"&gt;&amp;lt;/username&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;password&amp;gt;&lt;/span&gt;zflexpass&lt;span class="nt"&gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;authentication&amp;gt;&lt;/span&gt;SIMPLE&lt;span class="nt"&gt;&amp;lt;/authentication&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;referral&amp;gt;&lt;/span&gt;IGNORE&lt;span class="nt"&gt;&amp;lt;/referral&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;derefAliases&amp;gt;&lt;/span&gt;NEVER&lt;span class="nt"&gt;&amp;lt;/derefAliases&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;VERSION_3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;pageSize&amp;gt;&lt;/span&gt;-1&lt;span class="nt"&gt;&amp;lt;/pageSize&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;factory&amp;gt;&lt;/span&gt;com.sun.jndi.ldap.LdapCtxFactory&lt;span class="nt"&gt;&amp;lt;/factory&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tlsActivated&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/tlsActivated&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ldapConnection&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that piece of code, we're telling LSC how to connect to our LDAP server. For now, I've put in credentials of an online LDAP server which you can use, too. But, you can always put in your own LDAP server's credentials.&lt;/p&gt;

&lt;p&gt;Similarly, we define another connection but, this time, it's a database connection using the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;databaseConnection&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;jdbc-dst-conn&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;jdbc:mysql://127.0.0.1:3306/lsc&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;username&amp;gt;&lt;/span&gt;root&lt;span class="nt"&gt;&amp;lt;/username&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;password&amp;gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;driver&amp;gt;&lt;/span&gt;java.sql.DriverManager&lt;span class="nt"&gt;&amp;lt;/driver&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/databaseConnection&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've put in default MySQL configuration. If you know your credentials specifically, do edit as you please.&lt;/p&gt;

&lt;p&gt;Now, that we have let LSC know how to connect to our services, it's time to define what data should LSC take from LDAP and make it available to be put into the Database, we do so by defining a task of syncing employees from the LDAP server to our Database as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;task&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Employees&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;bean&amp;gt;&lt;/span&gt;org.lsc.beans.SimpleBean&lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ldapSourceService&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;openldap-source-service-employee&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&lt;/span&gt; &lt;span class="na"&gt;reference=&lt;/span&gt;&lt;span class="s"&gt;"ldap-src-conn"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;baseDn&amp;gt;&lt;/span&gt;ou=users,ou=developers,dc=zflexsoftware,dc=com&lt;span class="nt"&gt;&amp;lt;/baseDn&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;pivotAttributes&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;uid&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/pivotAttributes&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;fetchedAttributes&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;cn&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;uid&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/fetchedAttributes&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;getAllFilter&amp;gt;&lt;/span&gt;(&lt;span class="ni"&gt;&amp;amp;amp;&lt;/span&gt;(objectClass=person)(uid=*))&lt;span class="nt"&gt;&amp;lt;/getAllFilter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;getOneFilter&amp;gt;&lt;/span&gt;(&lt;span class="ni"&gt;&amp;amp;amp;&lt;/span&gt;(objectClass=person)(uid={uid}))&lt;span class="nt"&gt;&amp;lt;/getOneFilter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;cleanFilter&amp;gt;&lt;/span&gt;(&lt;span class="ni"&gt;&amp;amp;amp;&lt;/span&gt;(objectClass=person)(uid={uid}))&lt;span class="nt"&gt;&amp;lt;/cleanFilter&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ldapSourceService&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;databaseDestinationService&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;mysql-src-service-client&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&lt;/span&gt; &lt;span class="na"&gt;reference=&lt;/span&gt;&lt;span class="s"&gt;"jdbc-dst-conn"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestNameForList&amp;gt;&lt;/span&gt;getEmployeeList&lt;span class="nt"&gt;&amp;lt;/requestNameForList&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestNameForObject&amp;gt;&lt;/span&gt;getEmployee&lt;span class="nt"&gt;&amp;lt;/requestNameForObject&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestsNameForInsert&amp;gt;&amp;lt;string&amp;gt;&lt;/span&gt;insertEmployee&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&amp;lt;/requestsNameForInsert&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestsNameForUpdate&amp;gt;&amp;lt;string&amp;gt;&lt;/span&gt;updateEmployee&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&amp;lt;/requestsNameForUpdate&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;requestsNameForDelete&amp;gt;&amp;lt;string&amp;gt;&lt;/span&gt;deleteEmployee&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&amp;lt;/requestsNameForDelete&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/databaseDestinationService&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;propertiesBasedSyncOptions&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mainIdentifier&amp;gt;&lt;/span&gt;srcBean.getMainIdentifier()&lt;span class="nt"&gt;&amp;lt;/mainIdentifier&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;defaultDelimiter&amp;gt;&lt;/span&gt;;&lt;span class="nt"&gt;&amp;lt;/defaultDelimiter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;defaultPolicy&amp;gt;&lt;/span&gt;FORCE&lt;span class="nt"&gt;&amp;lt;/defaultPolicy&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;conditions&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;create&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/create&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;update&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/update&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;delete&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/delete&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;changeId&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/changeId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/conditions&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/propertiesBasedSyncOptions&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/task&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are some important parts from our &lt;code&gt;Employees&lt;/code&gt; task:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;baseDN&lt;/li&gt;
&lt;li&gt;pivotAttributes&lt;/li&gt;
&lt;li&gt;fetchedAttributes&lt;/li&gt;
&lt;li&gt;getAllFilter&lt;/li&gt;
&lt;li&gt;getOneFilter&lt;/li&gt;
&lt;li&gt;cleanFilter&lt;/li&gt;
&lt;li&gt;requestNameFor*&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  baseDN
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;baseDN&lt;/code&gt; defines from where should LSC start looking for LDAP objects. Since, I've used the online zflex LDAP server, I found the &lt;code&gt;users&lt;/code&gt; OU in &lt;code&gt;developers&lt;/code&gt; OU perfect for our use case. However, you can bind to any OU or DN of your choice. When we will specify our filters, LSC will search objects right under &lt;code&gt;baseDN&lt;/code&gt; value. If we were strictly following our employee feedback example, we would have &lt;code&gt;employees&lt;/code&gt; OU somewhere in our LDAP which we could bind to.&lt;/p&gt;

&lt;h3&gt;
  
  
  pivotAttributes
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;pivotAttributes&lt;/code&gt; defines the unique attribute(s) that will identify objects from LDAP. If LDAP has some object with these attributes present but, it's not in our database, that object will be enqueued for insertion. However, If LDAP does not have any object with these attributes but, such object is present in your database, it will be enqueued for deletion.&lt;/p&gt;

&lt;h3&gt;
  
  
  fetchedAttributes
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;fetchedAttributes&lt;/code&gt; includes &lt;code&gt;pivotAttributes&lt;/code&gt; and defines the attribute(s) which will be considered for syncing b/w your LDAP server and database. If any of these attributes get changed in any LDAP object, that object will be enqueued for updation.&lt;/p&gt;

&lt;h3&gt;
  
  
  getAllFilter
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;getAllFilter&lt;/code&gt; defines how to search for all candidate objects in LDAP under your &lt;code&gt;baseDN&lt;/code&gt;. Any object in LDAP that matches our &lt;code&gt;getAllFilter&lt;/code&gt; will be available for us to save it in our database.&lt;/p&gt;

&lt;h3&gt;
  
  
  getOneFilter
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;getOneFilter&lt;/code&gt; defines how to search for a specific candidate object in LDAP under your &lt;code&gt;baseDN&lt;/code&gt;. This option is just there to give you flexibility in filtering for a specific object.&lt;/p&gt;

&lt;h3&gt;
  
  
  cleanFilter
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;cleanFilter&lt;/code&gt; defines how to search for a specific in LDAP under your &lt;code&gt;baseDN&lt;/code&gt; which is a candidate for DELETION. Again, its value can just be your &lt;code&gt;getOneFilter&lt;/code&gt; but, is there for flexibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  requestsNameFor*
&lt;/h3&gt;

&lt;p&gt;All &lt;code&gt;requestsNameFor*&lt;/code&gt; tags refer to our queries that we will define and look at in a moment. LSC itself does not do the magic of syncing from LDAP to your database but, it only provides mechanism to do it. Whatever it finds in LDAP, either some object yet to inserted, deleted or updated in Database is forwarded to these requests as arguments and then these requests actually specify SQL queries that are ran to sync the LDAP objects to the database. But, I never mentioned how and where these requests should be placed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Defining Actual SQL Requests
&lt;/h4&gt;

&lt;p&gt;LSC uses iBatis ORM to make everything as easy possible for you. To configure iBatis LSC wants to write another file at &lt;code&gt;/etc/lsc/sql-map-config.xml&lt;/code&gt; which LSC will configure iBatis for basic connection details and reference to separate request definition files. Let's take a look at a sample &lt;code&gt;sql-map-config.xml&lt;/code&gt; below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE sqlMapConfig
    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--
    LDAP Synchronization Connector (LSC) - http://lsc-project.org

    This file configure iBatis to read sqlMap files.
    Settings should be generated here automatically.
    The only section you need to check is the sqlMap entries at the bottom.
--&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;sqlMapConfig&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- The settings element has a number of configuration switches and properties
       that configure the SQL Maps engine. Most are performance tweaks or resource
       management.  They are pretty self explanatory. The defaults are shown here.
       There can be only one settins element.  --&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;settings&lt;/span&gt;
    &lt;span class="na"&gt;lazyLoadingEnabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;cacheModelsEnabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;enhancementEnabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;maxRequests=&lt;/span&gt;&lt;span class="s"&gt;"512"&lt;/span&gt;
    &lt;span class="na"&gt;maxSessions=&lt;/span&gt;&lt;span class="s"&gt;"128"&lt;/span&gt;
    &lt;span class="na"&gt;maxTransactions=&lt;/span&gt;&lt;span class="s"&gt;"32"&lt;/span&gt; 
    &lt;span class="na"&gt;useStatementNamespaces=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;transactionManager&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"JDBC"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dataSource&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"SIMPLE"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"${driver}"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"JDBC.Driver"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"${url}"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"JDBC.ConnectionURL"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"${username}"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"JDBC.Username"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"${password}"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"JDBC.Password"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"15"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Pool.MaximumActiveConnections"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"15"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Pool.MaximumIdleConnections"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1000"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Pool.MaximumWait"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dataSource&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/transactionManager&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Finally, the SQL Maps themselves must be registred with the configuration file.
       Below are some examples of some SQL Map reference elements.  Notice that an
       SQL Map can  be located in the classpath (resource) or at a URL (e.g. file://
       or http://).  There can be any number of sqlMap elements. --&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;sqlMap&lt;/span&gt; &lt;span class="na"&gt;url=&lt;/span&gt;&lt;span class="s"&gt;"file://${lsc.config}/sql-map-config.d/Employees.xml"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/sqlMapConfig&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;&amp;lt;sqlMap url="file://${lsc.config}/sql-map-config.d/Employees.xml"/&amp;gt;&lt;/code&gt; line in the file. We're referring to the file &lt;code&gt;Employees.xml&lt;/code&gt; in &lt;code&gt;sql-map-config.d&lt;/code&gt; directory. You can go ahead and create &lt;code&gt;sql-map-config.d&lt;/code&gt; directory and &lt;code&gt;Employees.xml&lt;/code&gt; with the following contents in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;sqlMap&lt;/span&gt; &lt;span class="na"&gt;namespace=&lt;/span&gt;&lt;span class="s"&gt;"Employees"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"getEmployee"&lt;/span&gt; &lt;span class="na"&gt;resultClass=&lt;/span&gt;&lt;span class="s"&gt;"java.util.HashMap"&lt;/span&gt; &lt;span class="na"&gt;parameterClass=&lt;/span&gt;&lt;span class="s"&gt;"java.util.Map"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        SELECT
            uid,
            name AS cn,
            email AS mail
        FROM Employee
        WHERE uid = #uid#
    &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;insert&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"insertEmployee"&lt;/span&gt; &lt;span class="na"&gt;parameterClass=&lt;/span&gt;&lt;span class="s"&gt;"java.util.Map"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        INSERT INTO Employee
            (uid, name, email)
        VALUES
            (#uid#, IFNULL(#cn#, ''), IFNULL(#mail#, ''))
    &lt;span class="nt"&gt;&amp;lt;/insert&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;update&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"updateEmployee"&lt;/span&gt; &lt;span class="na"&gt;parameterClass=&lt;/span&gt;&lt;span class="s"&gt;"java.util.Map"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        UPDATE Employee
        SET name = #cn#
        WHERE uid = #uid#
    &lt;span class="nt"&gt;&amp;lt;/update&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;delete&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"deleteEmployee"&lt;/span&gt; &lt;span class="na"&gt;parameterClass=&lt;/span&gt;&lt;span class="s"&gt;"java.util.Map"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        DELETE FROM Employee
        WHERE uid = #uid#
    &lt;span class="nt"&gt;&amp;lt;/delete&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"getEmployeeList"&lt;/span&gt; &lt;span class="na"&gt;resultClass=&lt;/span&gt;&lt;span class="s"&gt;"java.util.HashMap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        SELECT uid
        FROM Employee
    &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/sqlMap&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've done that and modified &lt;code&gt;Employees.xml&lt;/code&gt; accordingly. You will be all setup to execute LSC with the task of syncing your company's employees. Just run in the command prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo lsc -s Employees
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-s&lt;/code&gt; flag tells LSC to run in Synchronization mode and run Employees task. If you've done everything correctly, you will start seeing logs from LSC what objects it found and what it is doing with them. By the end of it all, you'll have all your company Employees from LDAP synced to Database.&lt;/p&gt;

&lt;p&gt;BUT ALL IS NOT OVER YET.&lt;/p&gt;

&lt;p&gt;You need to register LSC as a CRON job to keep syncing Employees from LDAP to your Database. You can set appropriate time according to the requirements of the application. 5 minutes would do just fine for employee feedback application.&lt;/p&gt;

&lt;p&gt;In the next part, I would explain in more detail and would present a more difficult task of syncing groups of users. Stay tuned for that! Don't hesitate to put your thoughts in the comments. Did this article help you in any way? Or do you think it served no purpose? Perhaps, you have a better solution. I'm all ears.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; I did call LDAP-SQL duo unsyncable. They're definitely syncable. But, you would come across a very specific scenario of syncing groups of users which seemingly is unsyncable. Nevertheless, it was nice to have your attention with such title.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>showdev</category>
      <category>ldap</category>
      <category>sql</category>
    </item>
    <item>
      <title>Running a small static e-commerce store with less than 5$ budget per month</title>
      <dc:creator>Muhammad Talha Akbar</dc:creator>
      <pubDate>Sun, 04 Feb 2018 13:33:51 +0000</pubDate>
      <link>https://dev.to/devtalhaakbar/running-a-small-static-e-commerce-store-with-less-than-5-budget-per-month-3od2</link>
      <guid>https://dev.to/devtalhaakbar/running-a-small-static-e-commerce-store-with-less-than-5-budget-per-month-3od2</guid>
      <description>&lt;p&gt;Before you start, you can either read the short answer below, read the story or jump to conclusion at the end.&lt;/p&gt;

&lt;h1&gt;
  
  
  Short Answer
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Amazon Lambda&lt;/li&gt;
&lt;li&gt;Stripe&lt;/li&gt;
&lt;li&gt;serverless framework&lt;/li&gt;
&lt;li&gt;Some code magic on your side&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Story
&lt;/h1&gt;

&lt;p&gt;Recently, I was assigned a project on Upwork to build a single page store with Stripe. It was not made clear to me what technologies needed to be used for the project so, I quickly suggested the ones with which I was most comfortable with. But, soon, it was revealed to me that I needed to update an existing website and can't start from scratch. Whatever, that's not an issue, right?&lt;/p&gt;

&lt;p&gt;Turns out that the existing website that the client was referring to was an Amazon S3 bucket with static hosting enabled. I was being asked to make a fully-functioning store without any backend. I knew there must be a reason that the client wanted it to work that way and was not being totally irrational so, I asked. I was told that the current setup was great and costed around 2$ a month. At this point, I was a bit hesitant and the client felt it so, he asked how much would it cost to migrate it to some other hosting and not compromise the great setup he had. I replied that I understood that he didn't want to change anything and I will try to keep it that way but, will need some time to think...&lt;/p&gt;

&lt;p&gt;So began my search. I had heard of a term "server-less architecture". Just that. So, I quickly googled it. Somehow, I came across Amazon Lambda which allowed you to create simple isolated functions which could be invoked through a variety of events. And, not only that but, also 1 million such invocations in a month costed you nothing. I acted swiftly and shared this with the client who was amazed to hear about it and approved of it.&lt;/p&gt;

&lt;p&gt;But, all was not over yet. Although, Lambda was a key to completing this project but, I also had to deal with Stripe. I had done a few projects with Stripe before but, not a complete e-commerce solution backed by it. I revised Stripe concepts and was confident that I could make payments and create subscriptions. I just needed to send Stripe generated token to Lambda functions to process.&lt;/p&gt;

&lt;p&gt;Here's a quick tip: don't try to reinvent the wheel. I googled Lambda with Stripe and voila! A developer name Yos Riady not only had a github repository but, also had a &lt;a href="https://yos.io/2017/06/22/serverless-stripe/"&gt;tutorial for it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So far, I had discovered Amazon Lambda and tutorial by Yos Riady. Yos Riady suggested the use of server-less framework available on npm to interact with Lambda and save headaches of creating Lambda packages. He was right. It saved tons of working hours.&lt;/p&gt;

&lt;p&gt;After following the tutorial and inspecting his repository code thoroughly, I was ready to start the project.&lt;/p&gt;

&lt;p&gt;My initial idea was to store the products in a JSON file and fetch() them. After fetching, I will list the products and let the user add them to a cart. Once the user will finalize his/her cart, using Stripe elements, we will get their payment details. Once the details will be given, the Stripe generated token will be sent to Lambda function to process which will create a Stripe payment after validating the request. To tell which items the user ordered, my naive solution was to put those details in the description of the payment. Genius! Wasn't it?&lt;/p&gt;

&lt;p&gt;With the initial approach, there were two problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client will need to edit the JSON file each time he needs changes in the products.&lt;/li&gt;
&lt;li&gt;The order items in description of the payment!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I had these problems in my mind but, continued anyway. Just about when I was going to write logic for putting the order items in the description of the payment, I realized not only it's stupid but, also useless. I needed some other way. Search mode on!&lt;/p&gt;

&lt;p&gt;Believe me, out of nowhere, I came across Stripe Orders API. I could create Stripe Orders and pay for that order using the Stripe generated token. My initial guess was the order object would just let me add a bunch of items and store it. It was not the case! After carefully going through process of creation of Order through Stripe API, I discovered that I had to first register the store's catalog with Stripe then use the IDs generated for each one of them in the order create request. This lead to another discovery of the Products System in Stripe Dashboard. Stripe already gives you functionality of storing products and variations of those products in the form of SKUs. Guess what?! This also solved the problem #1.&lt;/p&gt;

&lt;p&gt;Solving the problem #1 was not obvious. I still needed to do a bit of thinking. As the store at that stage was relying on a JSON file that I had created.&lt;/p&gt;

&lt;p&gt;Regardless, I went to Stripe dashboard and added a few products along with SKUs. Stripe API lets you list these products. Considering it was a static website and we can't ask Stripe to list the products whenever the store was loaded, I created a node script that fetched the list of products from Stripe API and put it in the JSON file the application was relying on. I had to make some logic and code adjustments as the Stripe's object for list of products had a different structure than the JSON file I had created initially. It worked! I was more closer to signing off the project.&lt;/p&gt;

&lt;p&gt;However, there was still a bit of issue. It was great that the client could now see orders made in a delightful way through Stripe dashboard and also, could manage the inventory from there. But, whenever, there will be a change to products, the client will need to run the node script to update JSON file from his environment. But, this turned out not be a big problem for the client as he was already running commands to manage his website's setup.&lt;/p&gt;

&lt;p&gt;Still, I would like to propose a solution to the above mentioned problem. Stripe allows you to register Webhooks. The events occuring on your Stripe account can be captured and dealt with. So, utilizing this functionality, we could create a Lambda function that listened to any Product change event on Stripe and update the JSON file in the S3 bucket. I haven't done this myself yet but, I encourage you to do this an exercise if you're just starting out with Amazon S3, Stripe and Amazon Lambda.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;So, to conclude:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use Stripe Products section in dashboard to manage your inventory.&lt;/li&gt;
&lt;li&gt;Sync the stripe products with a JSON file using a script and Stripe API.&lt;/li&gt;
&lt;li&gt;Fetch the JSON file on load of your Store and render all of the products.&lt;/li&gt;
&lt;li&gt;Allow users to add those products to a cart. From programming point of view, you'll need to store the IDs of the products / SKUs that the user selected in the cart.&lt;/li&gt;
&lt;li&gt;Use Stripe Elements to collect user payment information and generate a Stripe token.&lt;/li&gt;
&lt;li&gt;Import serverless framework from npm and setup using &lt;a href="https://yos.io/2017/06/22/serverless-stripe/"&gt;Yos Riady's Tutorial&lt;/a&gt; as a guide. This will include creating Amazon Lambda function in the language of your choice and also, importing any Stripe API's implementation of that language. I used JavaScript both for the static site and the Lambda function.&lt;/li&gt;
&lt;li&gt;In your Lambda function, create Stripe order object and specify the items that the customer ordered. Then, you'll need to pay for the order you just created. The total price will be calculated by Stripe.&lt;/li&gt;
&lt;li&gt;You may also want to turn on Customer Emails from Stripe dashboard to send receipts of purchases.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using these 8 points as a guide, you can start your own ecommerce store. If I didn't mention who my client was in this project, let me do that now. It's an entertainment company in USA named &lt;a href="https://arrowtagoc.com/"&gt;ArrowTagOC&lt;/a&gt;. I thank Thomas Magsaysay supposedly, the owner of ArrowTagOC, for believing in me and helping make this challenging task possible. If you are around: Arrow Tag OC 3400 W. Warner Suite K Santa Ana, CA 92704, and want to do some fake archery, do visit them.&lt;/p&gt;

&lt;p&gt;Now, cost calculations:&lt;br&gt;
According to Amazon, static website on S3 costs as quoted below:&lt;br&gt;
Typically, it will cost $1-3/month if you are outside the AWS Free Tier limits. If you qualify for AWS Free Tier and are within the limits, hosting your static website will cost around $0.50/month.&lt;/p&gt;

&lt;p&gt;Amazon Lambda, for a small business, will cost nothing if you write your Lambda functions correctly. I believe as much as number of invocations matter so does the time taken during the execution of your code. Keep it under 100ms, as the minimum Billing time is 100ms. My node implementation did run under 100ms so, I guess yours can too.&lt;/p&gt;

&lt;p&gt;We used serverless framework to setup Lambda package which utilizes some additional Amazon services like Amazon Cloudwatch, Amazon CloudFormation, Amazon S3 and Amazon CloudFront e.t.c. So, keep an eye over pricing of these services as I am not sure. So far, I don't see any billing of these services. And, considering you're about to run a small store, I don't think you'll hit billing limits.&lt;/p&gt;

&lt;p&gt;So, in most cases, you'll only pay S3 static hosting costs to keep running your small static e-commerce store. In worst case, you pay more but, not more than 5$ if you stay smart.&lt;/p&gt;

&lt;p&gt;Apart from above costs, Stripe will also take its cut which you can view at &lt;a href="https://stripe.com/ie/pricing"&gt;Stripe Pricing Page&lt;/a&gt;. But, it's totally worth it considering the number of problems that could be solved by their services.&lt;/p&gt;

&lt;p&gt;If you read this far, don't forget to share. I would encourage you to suggest improvements and share your opinions. Thanks.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>ReactJS and Laravel - Running through a basic setup - Part 2</title>
      <dc:creator>Muhammad Talha Akbar</dc:creator>
      <pubDate>Fri, 27 Oct 2017 11:04:57 +0000</pubDate>
      <link>https://dev.to/devtalhaakbar/reactjs-and-laravel---running-through-a-basic-setup---part-2-20p</link>
      <guid>https://dev.to/devtalhaakbar/reactjs-and-laravel---running-through-a-basic-setup---part-2-20p</guid>
      <description>&lt;p&gt;In this big article, we will use Laravel and ReactJS to setup authentication system. We'll use Auth scaffolding that comes with Laravel 5.5. Anyways, before we start running through the code, it'll be a good idea to divide our goal, the authentication system, into smaller parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Landing Page&lt;/li&gt;
&lt;li&gt;Sign In Page&lt;/li&gt;
&lt;li&gt;Create Account Page&lt;/li&gt;
&lt;li&gt;Dashboard Page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the idea above, we can be sure that we'll have four components: &lt;code&gt;SignInPage&lt;/code&gt;, &lt;code&gt;CreateAccountPage&lt;/code&gt;, &lt;code&gt;LandingPage&lt;/code&gt;, &lt;code&gt;DashboardPage&lt;/code&gt;. And let's say these components will be shown on &lt;code&gt;/signin&lt;/code&gt;, &lt;code&gt;/account/create&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt; and &lt;code&gt;/dashboard&lt;/code&gt; URLs respectively. Considering this, we can quickly predict how our router components will look like:&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;BrowserRouter&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;Route exact path="/" component={LandingPage} /&amp;gt;
        &amp;lt;Route path="/signin" component={SignInPage} /&amp;gt;
        &amp;lt;Route path="/account/create" component={CreateAccountPage} /&amp;gt;
        &amp;lt;Route path="/dashboard" component={DashboardPage} /&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/BrowserRouter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you ask, the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; becomes necessary because &lt;code&gt;&amp;lt;BrowserRouter&amp;gt;&lt;/code&gt; accepts only one child. Continuing, let's make the components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const LandingPage = (props) =&amp;gt; {
    return &amp;lt;div&amp;gt;Landing Page&amp;lt;/div&amp;gt;;
};
const SignInPage = (props) =&amp;gt; {
    return &amp;lt;div&amp;gt;Sign In Page&amp;lt;/div&amp;gt;;
};
const CreateAccountPage = (props) =&amp;gt; {
    return &amp;lt;div&amp;gt;Create Account Page&amp;lt;/div&amp;gt;;
};
const DashboardPage = (props) =&amp;gt; {
    return &amp;lt;div&amp;gt;Dashboard Page&amp;lt;/div&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've kept them simple; so far. Also, notice all of the four components are stateless. It's my little thing that I always start off with stateless components and then if needed make them stateful. Unless, ofcourse, you know already that your component will have state. Anyways, we move on.&lt;/p&gt;

&lt;p&gt;If you haven't guessed it so far, all of the code above will go into our &lt;code&gt;/resources/assets/js/components/App.js&lt;/code&gt; file with a few adjustments, ofcourse. Let's see how &lt;code&gt;App.js&lt;/code&gt; should look like so far:&lt;br&gt;
&lt;/p&gt;

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

import {
    BrowserRouter,
    Route
} from 'react-router-dom';

let LandingPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Landing Page&amp;lt;/h1&amp;gt;;
};
let SignInPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Sign In Page&amp;lt;/h1&amp;gt;;
};
let CreateAccountPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Create Account Page&amp;lt;/h1&amp;gt;;
};
let DashboardPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Dashboard Page&amp;lt;/h1&amp;gt;;
};

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        &amp;lt;BrowserRouter&amp;gt;
            &amp;lt;div&amp;gt;
                &amp;lt;Route exact path="/" component={LandingPage} /&amp;gt;
                &amp;lt;Route path="/signin" component={SignInPage} /&amp;gt;
                &amp;lt;Route path="/account/create" component={CreateAccountPage} /&amp;gt;
                &amp;lt;Route path="/dashboard" component={DashboardPage} /&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/BrowserRouter&amp;gt;
        );
    }
};

ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('app'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And yes, by principle, &lt;code&gt;LandingPage&lt;/code&gt;, &lt;code&gt;SignInPage&lt;/code&gt;, &lt;code&gt;CreateAccountPage&lt;/code&gt;, &lt;code&gt;DashboardPage&lt;/code&gt; should be in their own file and should be imported into &lt;code&gt;App.js&lt;/code&gt; but, for simplicity, we keep it as is. Next, we can make a &lt;code&gt;Header&lt;/code&gt; component that contains &lt;code&gt;Link&lt;/code&gt; components. So, let's import &lt;code&gt;Link&lt;/code&gt; from &lt;code&gt;react-router-dom&lt;/code&gt; and declare &lt;code&gt;Header&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let Header = (props) =&amp;gt; {
    return (
        &amp;lt;nav className="navbar navbar-expand-lg navbar-light bg-light"&amp;gt;
            &amp;lt;div className="container px-2 px-sm-3"&amp;gt;
                &amp;lt;Link className="navbar-brand" to="/"&amp;gt;DEV.TO&amp;lt;/Link&amp;gt;
                &amp;lt;button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"&amp;gt;
                    &amp;lt;span className="navbar-toggler-icon"&amp;gt;&amp;lt;/span&amp;gt;
                &amp;lt;/button&amp;gt;

                &amp;lt;div className="collapse navbar-collapse" id="navbarSupportedContent"&amp;gt;
                    &amp;lt;ul className="navbar-nav ml-auto"&amp;gt;
                        &amp;lt;li className="nav-item"&amp;gt;
                            &amp;lt;Link className="nav-link" to="/signin"&amp;gt;Sign In&amp;lt;/Link&amp;gt;
                        &amp;lt;/li&amp;gt;
                        &amp;lt;li className="nav-item"&amp;gt;
                            &amp;lt;Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/account/create"&amp;gt;Create Account&amp;lt;/Link&amp;gt;
                        &amp;lt;/li&amp;gt;
                    &amp;lt;/ul&amp;gt;
                    &amp;lt;ul className="navbar-nav ml-auto"&amp;gt;
                        &amp;lt;li className="nav-item"&amp;gt;
                            &amp;lt;Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/dashboard"&amp;gt;Dashboard&amp;lt;/Link&amp;gt;
                        &amp;lt;/li&amp;gt;
                    &amp;lt;/ul&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/nav&amp;gt;
    );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have kept the Dashboard link in a separate &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; because soon we will introduce a conditional &lt;code&gt;if/else&lt;/code&gt; in the form of ternary operator in our Header. But, let's keep running!&lt;/p&gt;

&lt;p&gt;I desperately want to skip to &lt;code&gt;SignInPage&lt;/code&gt; component but, let's look at the &lt;code&gt;App.js&lt;/code&gt; file so far:&lt;br&gt;
&lt;/p&gt;

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

import {
    BrowserRouter,
    Link,
    Route
} from 'react-router-dom';

let LandingPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Landing Page&amp;lt;/h1&amp;gt;;
};
let SignInPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Sign In Page&amp;lt;/h1&amp;gt;;
};
let CreateAccountPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Create Account Page&amp;lt;/h1&amp;gt;;
};
let DashboardPage = (props) =&amp;gt; {
    return &amp;lt;h1 className="mt-5"&amp;gt;Dashboard Page&amp;lt;/h1&amp;gt;;
};
let Header = (props) =&amp;gt; {
    return (
        &amp;lt;nav className="navbar navbar-expand-lg navbar-light bg-light"&amp;gt;
            &amp;lt;div className="container px-2 px-sm-3"&amp;gt;
                &amp;lt;Link className="navbar-brand" to="/"&amp;gt;DEV.TO&amp;lt;/Link&amp;gt;
                &amp;lt;button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"&amp;gt;
                    &amp;lt;span className="navbar-toggler-icon"&amp;gt;&amp;lt;/span&amp;gt;
                &amp;lt;/button&amp;gt;

                &amp;lt;div className="collapse navbar-collapse" id="navbarSupportedContent"&amp;gt;
                    &amp;lt;ul className="navbar-nav ml-auto"&amp;gt;
                        &amp;lt;li className="nav-item"&amp;gt;
                            &amp;lt;Link className="nav-link" to="/signin"&amp;gt;Sign In&amp;lt;/Link&amp;gt;
                        &amp;lt;/li&amp;gt;
                        &amp;lt;li className="nav-item"&amp;gt;
                            &amp;lt;Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/account/create"&amp;gt;Create Account&amp;lt;/Link&amp;gt;
                        &amp;lt;/li&amp;gt;
                    &amp;lt;/ul&amp;gt;
                    &amp;lt;ul className="navbar-nav ml-auto"&amp;gt;
                        &amp;lt;li className="nav-item"&amp;gt;
                            &amp;lt;Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/dashboard"&amp;gt;Dashboard&amp;lt;/Link&amp;gt;
                        &amp;lt;/li&amp;gt;
                    &amp;lt;/ul&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/nav&amp;gt;
    );
};

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        &amp;lt;BrowserRouter&amp;gt;
            &amp;lt;div&amp;gt;
                &amp;lt;Header /&amp;gt;
                &amp;lt;Route exact path="/" component={LandingPage} /&amp;gt;
                &amp;lt;Route path="/signin" component={SignInPage} /&amp;gt;
                &amp;lt;Route path="/account/create" component={CreateAccountPage} /&amp;gt;
                &amp;lt;Route path="/dashboard" component={DashboardPage} /&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/BrowserRouter&amp;gt;
        );
    }
};

ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('app'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;SignInPage&lt;/code&gt; is going to contain a form mainly. And, for the form management, we have included &lt;code&gt;redux-form&lt;/code&gt; which depends on &lt;code&gt;redux&lt;/code&gt;. Let's quickly setup both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

import { createStore, combineReducers } from 'redux'
import { reducer as formReducer } from 'redux-form'

...

const rootReducer = combineReducers({
  form: formReducer,
  // my other reducers come here
});


const store = createStore(rootReducer);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we have a Redux store but to actually use this store with React components, we'll need to use &lt;code&gt;Provider&lt;/code&gt; component that comes with &lt;code&gt;react-redux&lt;/code&gt; package. It's quite simple (we just need to wrap our &lt;code&gt;BrowserRouter&lt;/code&gt; with &lt;code&gt;Provider&lt;/code&gt; and pass the &lt;code&gt;store&lt;/code&gt; as a prop) so, let's just look at our &lt;code&gt;App.js&lt;/code&gt; so far:&lt;br&gt;
&lt;/p&gt;

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

import {
    BrowserRouter,
    Link,
    Route
} from 'react-router-dom';

import { createStore, combineReducers } from 'redux'
import { reducer as formReducer } from 'redux-form'

import { Provider} from 'react-redux'

// Other components are here collapsed

const rootReducer = combineReducers({
  form: formReducer,
  // my other reducers come here
});

const store = createStore(rootReducer);

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        &amp;lt;Provider store={store}&amp;gt;
            &amp;lt;BrowserRouter&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;Header /&amp;gt;
                    &amp;lt;Route exact path="/" component={LandingPage} /&amp;gt;
                    &amp;lt;Route path="/signin" component={SignInPage} /&amp;gt;
                    &amp;lt;Route path="/account/create" component={CreateAccountPage} /&amp;gt;
                    &amp;lt;Route path="/dashboard" component={DashboardPage} /&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/BrowserRouter&amp;gt;
        &amp;lt;/Provider&amp;gt;
        );
    }
};

ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('app'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's modify the &lt;code&gt;SignInPage&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SignInPage extends Component {
    constructor(props) {
        super(props);

        this.processSubmit = this.processSubmit.bind(this);
    }

    componentWillMount() {
        // do something like setting default state
    }

    processSubmit(values) {
        // do something with the values
    }

    render() {
        const { handleSubmit, submitting } = this.props;

        return (
            &amp;lt;div className="container mt-5"&amp;gt;
                &amp;lt;div className="row justify-content-center"&amp;gt;
                    &amp;lt;div className="col-6"&amp;gt;
                        &amp;lt;div className="card"&amp;gt;
                            &amp;lt;div className="card-body"&amp;gt;
                            &amp;lt;h2 className="text-center font-weight-light mb-4"&amp;gt;Sign into your account&amp;lt;/h2&amp;gt;
                                &amp;lt;form onSubmit={handleSubmit(this.processSubmit)}&amp;gt;
                                    &amp;lt;Field
                                        label="Email Address"
                                        name="email"
                                        component={FormField}
                                        id="email"
                                        type="text"
                                        className="form-control"
                                    /&amp;gt;
                                    &amp;lt;Field label="Password" name="password" component={FormField} id="password" type="password" className="form-control" /&amp;gt;
                                    &amp;lt;div className="form-check"&amp;gt;
                                        &amp;lt;label className="form-check-label"&amp;gt;
                                            &amp;lt;Field name="remember" component="input" type="checkbox" className="form-check-input mt-2" value="1" /&amp;gt;
                                            Remember me
                                        &amp;lt;/label&amp;gt;
                                    &amp;lt;/div&amp;gt;
                                    &amp;lt;div className="form-group mt-4"&amp;gt;
                                        &amp;lt;button type="submit" className="btn btn-secondary" disabled={submitting}&amp;gt;Continue&amp;lt;/button&amp;gt;
                                    &amp;lt;/div&amp;gt;
                                &amp;lt;/form&amp;gt;
                            &amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        );
    }
};

SignInPage = reduxForm({
    form: 'signin',
    validate
})(SignInPage);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There a few things here to digest before we move on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SignInPage&lt;/code&gt; component is no longer a pathetic dumb component that just renders  the other components and pass &lt;code&gt;props&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;reduxForm&lt;/code&gt; decorator and &lt;code&gt;Field&lt;/code&gt; component has been imported from &lt;code&gt;redux-form&lt;/code&gt; package so, our import declaration for &lt;code&gt;redux-form&lt;/code&gt; now looks like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
    reducer as formReducer,
    reduxForm,
    Field
} from 'redux-form'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Notice the &lt;code&gt;Field&lt;/code&gt; takes a &lt;code&gt;component&lt;/code&gt; as a prop. Any component that you specify will be rendered inside &lt;code&gt;Field&lt;/code&gt;. The inner component that we specify gets some nice props that can be used to make the inputs interactive. Here's how I have written a basic &lt;code&gt;FormField&lt;/code&gt; component:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const FormField = ({
        label,
        input,
        type,
        name,
        className,
        meta: { touched, error, warning }
}) =&amp;gt; (
    &amp;lt;div className="form-group"&amp;gt;
        {
            label &amp;amp;&amp;amp;
            &amp;lt;label htmlFor={name}&amp;gt;{label}&amp;lt;/label&amp;gt;
        }
        &amp;lt;input {...input } name={name} type={type} className={
            `${className} ${
                touched &amp;amp;&amp;amp; (
                    (error &amp;amp;&amp;amp; 'is-invalid')
                )
            }`
        } /&amp;gt;
        {
            touched &amp;amp;&amp;amp;
                (error &amp;amp;&amp;amp; &amp;lt;span className="invalid-feedback"&amp;gt;{error}&amp;lt;/span&amp;gt;)
        }
    &amp;lt;/div&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Look at this line carefully in the new &lt;code&gt;SignInPage&lt;/code&gt; component:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { handleSubmit, submitting } = this.props;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;handleSubmit&lt;/code&gt; and &lt;code&gt;submitting&lt;/code&gt; props come from the decorated SignInPage component . &lt;code&gt;handleSubmit&lt;/code&gt; takes a callback with &lt;code&gt;values&lt;/code&gt; being passed as its first parameter. &lt;code&gt;submitting&lt;/code&gt; is just a boolean that tells if the form is in submitting state which is helpful in disabling the submit button to prevent multiple requests when the one is being processed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also, notice &lt;code&gt;validate&lt;/code&gt; property in the following lines:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SignInPage = reduxForm({
    form: 'signin',
    validate: validatorSignInForm,
})(SignInPage);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;validate&lt;/code&gt; property must hold a function that returns error messages for fields. I'll be using a simple JavaScript based validation library &lt;code&gt;validate.js&lt;/code&gt; to implement &lt;code&gt;validatorSignInForm&lt;/code&gt; which you can install with &lt;code&gt;npm install --save validate.js&lt;/code&gt;. The validator function looks like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const validatorSignInForm = (values) =&amp;gt; {
    const result = validate(values, {
        email: {
            presence: {
                message: '^Please enter your email address.'
            },
            email: {
                message: '^Please enter a valid email address.'
            }
        },
        password: {
            presence: {
                message: '^Please enter your password.'
            }
        }
    });

    return result;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should know that &lt;code&gt;validate()&lt;/code&gt; comes from &lt;code&gt;validate.js&lt;/code&gt; library so, for now you just need to know that it takes &lt;code&gt;values&lt;/code&gt; as its first argument and rules for each value in nicely formed object as its second argument.&lt;/p&gt;

&lt;p&gt;Now, that's a lot of code that we have looked over so far but, you'll see that once you have gone through and understood  it, you'll encounter no problem creating interactive forms for your application.&lt;/p&gt;

&lt;p&gt;Now, let's put the updated &lt;code&gt;SignInPage&lt;/code&gt; component along with the code we've written in &lt;code&gt;App.js&lt;/code&gt; so far and see how it looks like now:&lt;br&gt;
&lt;/p&gt;

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

import {
    BrowserRouter,
    Link,
    Route
} from 'react-router-dom';

import { createStore, combineReducers } from 'redux'
import {
    reducer as formReducer,
    reduxForm,
    Field
} from 'redux-form'

import { Provider} from 'react-redux'

// Other components are here collapsed

const validatorSignInForm = (values) =&amp;gt; {
    const result = validate(values, {
        email: {
            presence: {
                message: '^Please enter your email address.'
            },
            email: {
                message: '^Please enter a valid email address.'
            }
        },
        password: {
            presence: {
                message: '^Please enter your password.'
            }
        }
    });

    return result;
};

class SignInPage extends Component {
    constructor(props) {
        super(props);

        this.processSubmit = this.processSubmit.bind(this);
    }

    componentWillMount() {
        // do something like setting default state
    }

    processSubmit(values) {
        // do something with the values
    }

    render() {
        const { handleSubmit, submitting } = this.props;

        return (
            &amp;lt;div className="container mt-5"&amp;gt;
                &amp;lt;div className="row justify-content-center"&amp;gt;
                    &amp;lt;div className="col-6"&amp;gt;
                        &amp;lt;div className="card"&amp;gt;
                            &amp;lt;div className="card-body"&amp;gt;
                            &amp;lt;h2 className="text-center font-weight-light mb-4"&amp;gt;Sign into your account&amp;lt;/h2&amp;gt;
                                &amp;lt;form onSubmit={handleSubmit(this.processSubmit)}&amp;gt;
                                    &amp;lt;Field
                                        label="Email Address"
                                        name="email"
                                        component={FormField}
                                        id="email"
                                        type="text"
                                        className="form-control"
                                    /&amp;gt;
                                    &amp;lt;Field label="Password" name="password" component={FormField} id="password" type="password" className="form-control" /&amp;gt;
                                    &amp;lt;div className="form-check"&amp;gt;
                                        &amp;lt;label className="form-check-label"&amp;gt;
                                            &amp;lt;Field name="remember" component="input" type="checkbox" className="form-check-input mt-2" value="1" /&amp;gt;
                                            Remember me
                                        &amp;lt;/label&amp;gt;
                                    &amp;lt;/div&amp;gt;
                                    &amp;lt;div className="form-group mt-4"&amp;gt;
                                        &amp;lt;button type="submit" className="btn btn-secondary" disabled={submitting}&amp;gt;Continue&amp;lt;/button&amp;gt;
                                    &amp;lt;/div&amp;gt;
                                &amp;lt;/form&amp;gt;
                            &amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        );
    }
};

SignInPage = reduxForm({
    form: 'signin',
    validate: validatorSignInForm
})(SignInPage);

const rootReducer = combineReducers({
  form: formReducer,
  // my other reducers come here
});

const store = createStore(rootReducer);

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        &amp;lt;Provider store={store}&amp;gt;
            &amp;lt;BrowserRouter&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;Header /&amp;gt;
                    &amp;lt;Route exact path="/" component={LandingPage} /&amp;gt;
                    &amp;lt;Route path="/signin" component={SignInPage} /&amp;gt;
                    &amp;lt;Route path="/account/create" component={CreateAccountPage} /&amp;gt;
                    &amp;lt;Route path="/dashboard" component={DashboardPage} /&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/BrowserRouter&amp;gt;
        &amp;lt;/Provider&amp;gt;
        );
    }
};

ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('app'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Break - Breath a little
&lt;/h1&gt;

&lt;p&gt;So far, we have looked at a lot of code. You must be overwhelmed. Take a break. Inhale air. And be back where we start looking at processing the sign in form.&lt;/p&gt;

&lt;p&gt;So, have you noticed that I had left processSubmit method of &lt;code&gt;SignInPage&lt;/code&gt; component empty? Our goal will now be to look at how we will implement it. A break-down of its implementation will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send an AJAX request to the login route with the values&lt;/li&gt;
&lt;li&gt;Wait for the response&lt;/li&gt;
&lt;li&gt;Do something upon the request results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, for sending AJAX requests, we will use &lt;code&gt;axios&lt;/code&gt; - a promise based AJAX library. Don't worry, it's already installed. You can start using it like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;processSubmit(values) {
    axios
    .post('/ajax/login', values)
    .then( (response) =&amp;gt; {
        console.log(response.data);
    })
    .error( (err) =&amp;gt; {
        console.log(err);
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things to setup before you can see the request completing successfully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to put &lt;code&gt;Auth::routes();&lt;/code&gt; in &lt;code&gt;ajax&lt;/code&gt; Route group that we created in Part 1 in &lt;code&gt;/routes/web.php&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You need to make sure that you have &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag in your &lt;code&gt;web.blade.php&lt;/code&gt; that contains the CSRF token otherwise, Laravel will throw TokenMismatchException instead of processing the login request. So make sure something like below is there:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta name="csrf-token" content="{{ csrf_token() }}"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;By default, &lt;code&gt;AuthenticatesUsers&lt;/code&gt; trait in &lt;code&gt;LoginController&lt;/code&gt; has a method &lt;code&gt;sendLoginResponse&lt;/code&gt; that is implemented to redirect. The problem is that we don't want to redirect instead, we want to return user details. So, copy the following lines of code and paste them as methods of &lt;code&gt;LoginController&lt;/code&gt; which resides in &lt;code&gt;/app/Http/Controllers/Auth/LoginController.php&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * Send the response after the user was authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
protected function sendLoginResponse(Request $request)
{
    $request-&amp;gt;session()-&amp;gt;regenerate();

    $this-&amp;gt;clearLoginAttempts($request);

    $user = $this-&amp;gt;guard()-&amp;gt;user();

    if($this-&amp;gt;authenticated($request, $user)) {
        return response()-&amp;gt;json([
            'success' =&amp;gt; true,
            'user' =&amp;gt; $user
        ], 200);
    }
}

/**
 * The user has been authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  mixed  $user
 * @return mixed
 */
protected function authenticated(Request $request, $user)
{
    return true;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Similarly, the &lt;code&gt;AuthenticatesUsers&lt;/code&gt; trait has &lt;code&gt;sendFailedLoginResponse&lt;/code&gt; which also needs to be overridden. So, copy the below lines into &lt;code&gt;LoginController&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * Get the failed login response instance.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function sendFailedLoginResponse(Request $request)
{
    return response()-&amp;gt;json([
        'success' =&amp;gt; false,
        'message' =&amp;gt; trans('auth.failed')
    ], 422);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you test by submitting the form, you'll be able to receive the JSON responses. Or it doesn't? Let me know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;To be continued in Part 3. In Part 3, will continue with &lt;code&gt;processSubmit&lt;/code&gt; for the &lt;code&gt;SignInPage&lt;/code&gt; component. And, we will also look at how we can manage the user details using redux, prevent routes from being accessed in guest mode and much more.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The reason I have to split this into part 3 is because the dev.to post editor has become slow due to large amount of content in it and it's annoying!&lt;/p&gt;

</description>
      <category>starter</category>
      <category>react</category>
      <category>laravel</category>
    </item>
    <item>
      <title>ReactJS and Laravel - Running through a basic setup - Part 1</title>
      <dc:creator>Muhammad Talha Akbar</dc:creator>
      <pubDate>Thu, 26 Oct 2017 17:13:00 +0000</pubDate>
      <link>https://dev.to/devtalhaakbar/reactjs-and-laravel---running-through-a-basic-setup---part-1-ei8</link>
      <guid>https://dev.to/devtalhaakbar/reactjs-and-laravel---running-through-a-basic-setup---part-1-ei8</guid>
      <description>&lt;p&gt;Type the following command in your newly created Laravel 5.5 project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan preset react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done with it? See your &lt;code&gt;package.json&lt;/code&gt; updated? Great, don't close it! We have some work to do there. In your &lt;code&gt;devDependencies&lt;/code&gt;; add 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;"bootstrap": "^4.0.0-beta",
"popper.js": "^1.12.6",
"react-redux": "^5.0.6",
"react-router-dom": "^4.2.2",
"reactstrap": "^5.0.0-alpha.3",
"redux": "^3.7.2",
"redux-form": "^7.1.1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you're done with the above, notice I have added Bootstrap 4 Beta package there? Yup, keep it. With that said, remove the &lt;code&gt;bootstrap-sass&lt;/code&gt; and &lt;code&gt;jquery&lt;/code&gt; declaration from &lt;code&gt;devDependencies&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"bootstrap-sass": "^3.3.7",
...
"jquery": "^3.1.1",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, once you have done the above. Quickly fire up your terminal and issue 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;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope you don't have network issues. If you were lucky enough to get the packages installed, move to &lt;code&gt;/resources/assets/sass&lt;/code&gt; directory. Open &lt;code&gt;variables.scss&lt;/code&gt; file in an editor of your choice and get rid of all the content in it. Next, open &lt;code&gt;app.scss&lt;/code&gt; from the same &lt;code&gt;sass&lt;/code&gt; directory and change it to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Variables
@import "variables";

// Bootstrap
@import "~bootstrap/scss/bootstrap";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you have everything setup for Bootstrap 4 at the CSS side.&lt;/p&gt;

&lt;p&gt;Move to &lt;code&gt;/resources/assets/js/&lt;/code&gt; directory and open &lt;code&gt;bootstrap.js&lt;/code&gt; for editing. Once you have that file opened, rush to remove the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * We'll load jQuery and the Bootstrap jQuery plugin which provides support
 * for JavaScript based Bootstrap features such as modals and tabs. This
 * code may be modified to fit the specific needs of your application.
 */

try {
    window.$ = window.jQuery = require('jquery');

    require('bootstrap-sass');
} catch (e) {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, open &lt;code&gt;app.js&lt;/code&gt; file (next to &lt;code&gt;bootstrap.js&lt;/code&gt;) which actually, is configured to be the entry point for your JS code. Once you have it opened, see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require('./components/Example');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this line, just replace &lt;code&gt;/Example&lt;/code&gt; with &lt;code&gt;/App&lt;/code&gt;. That's better. Don't worry; just follow the next steps and you will know why I did it (or, you are clever enough to already guess it.)&lt;/p&gt;

&lt;p&gt;Laravel comes with Example components which are useful to check quickly if everything is setup correctly according to your chosen preset. Look into components directory, you'll see 2 files: &lt;code&gt;ExampleComponent.vue&lt;/code&gt; and &lt;code&gt;Example.js&lt;/code&gt;. Delete &lt;code&gt;ExampleComponent.vue&lt;/code&gt; file because we don't need it. Then rename &lt;code&gt;Example.js&lt;/code&gt; to &lt;code&gt;App.js&lt;/code&gt; and keep yourself ready to type some ES6 along with JSX. If you notice, we replaced &lt;code&gt;/Example&lt;/code&gt; with &lt;code&gt;/App&lt;/code&gt; in &lt;code&gt;app.js&lt;/code&gt; because we were about to rename &lt;code&gt;Example.js&lt;/code&gt; to &lt;code&gt;App.js&lt;/code&gt; in the &lt;code&gt;components&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;At this point, you can wipe everything off from &lt;code&gt;App.js&lt;/code&gt; in your components directory or keep the example code. If you decide to do the latter, I would suggest a few basic changes.&lt;/p&gt;

&lt;p&gt;Rename the component class name from &lt;code&gt;Example&lt;/code&gt; to &lt;code&gt;App&lt;/code&gt; and change the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (document.getElementById('example')) {
    ReactDOM.render(&amp;lt;Example /&amp;gt;, document.getElementById('example'));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with the lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (document.getElementById('app')) {
    ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('app'));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moving on; quickly open &lt;code&gt;web.php&lt;/code&gt; file which resides in &lt;code&gt;/routes&lt;/code&gt; directory relative to your Laravel project. Remove the only route you see and replace it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::group(['prefix' =&amp;gt; 'ajax'], function() {
    // all routes that don't need to go to react-router
});

Route::get('/{path?}', function () {
    return view('web');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we have a special route group that matches only those routes that have a prefix &lt;code&gt;ajax/&lt;/code&gt; to their URL. This route group will help us have such a &lt;code&gt;react-router&lt;/code&gt; setup that can render appropriate components without using &lt;code&gt;#&lt;/code&gt;-based URLs. However, the route declaration outside of AJAX route group matches every URL no matter what it is and return &lt;code&gt;web&lt;/code&gt; view in response.&lt;/p&gt;

&lt;p&gt;Next, move to &lt;code&gt;/resources/views&lt;/code&gt; directory and rename &lt;code&gt;welcome.blade.php&lt;/code&gt; and change it to &lt;code&gt;web.blade.php&lt;/code&gt; or whatever you prefer. Just make sure the view name matches with the one we specified in the &lt;code&gt;routes/web.php&lt;/code&gt;. (I'll assume you renamed it to &lt;code&gt;web.blade.php&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;web.blade.php&lt;/code&gt; and replace its contents with something like Bootstrap 4 HTML Starter Content. Whatever you do, make sure of the following three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag referring to &lt;code&gt;/app.css&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;There is a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag with its src set to &lt;code&gt;/app.js&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;There is a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; in the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag with an id &lt;code&gt;app&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, if you run 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;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And wait for its completion. Then, run the PHP's little server through the following artisan command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan serve --port=80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll now be able to navigate to &lt;code&gt;http://127.0.0.1&lt;/code&gt; and see everything in action. (I'm assuming you didn't touch the example code in the &lt;code&gt;Example&lt;/code&gt; component).&lt;/p&gt;

&lt;p&gt;After all of the fuss, you will be able to write React components with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React Router&lt;/li&gt;
&lt;li&gt;Redux&lt;/li&gt;
&lt;li&gt;Redux Forms&lt;/li&gt;
&lt;li&gt;Reactstrap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This concludes Part 1 of our &lt;strong&gt;ReactJS and Laravel - Running through a basic setup&lt;/strong&gt;. Considering the response on the part 1, I'll be making a part 2 in which I will be setting up Authentication System with the same setup in Laravel and React.&lt;/p&gt;

&lt;p&gt;Do notice the npm packages above were chosen after significant time spending so, keep them and check out their getting started guides to prevent yourself from headaches.&lt;/p&gt;

</description>
      <category>react</category>
      <category>laravel</category>
      <category>starter</category>
    </item>
  </channel>
</rss>
