#v-select vue json
Explore tagged Tumblr posts
Text
Use v-select in Vue js
Use v-select in Vue js
In this article, we will learn about how we can use v-select in Vue js. I will show you step by step guide to implement v-select with options in Vue js. Basic Example of v-select In the below example you will learn how to implement v-select with options. <template> <div> <v-select v-model="selected" label="title" :options="multipleOption"/> </div> </template> <script> import…
View On WordPress
#multiple select#multiple select vue js#v select default value#v select dynamic options#v select multiple example#v select options#v select reduce#v select vuejs#v select vuetify example#v-select vue json#vue select
0 notes
Photo
hydralisk98′s web projects tracker:
Core principles=
Fail faster
‘Learn, Tweak, Make’ loop
This is meant to be a quick reference for tracking progress made over my various projects, organized by their “ultimate target” goal:
(START)
(Website)=
Install Firefox
Install Chrome
Install Microsoft newest browser
Install Lynx
Learn about contemporary web browsers
Install a very basic text editor
Install Notepad++
Install Nano
Install Powershell
Install Bash
Install Git
Learn HTML
Elements and attributes
Commenting (single line comment, multi-line comment)
Head (title, meta, charset, language, link, style, description, keywords, author, viewport, script, base, url-encode, )
Hyperlinks (local, external, link titles, relative filepaths, absolute filepaths)
Headings (h1-h6, horizontal rules)
Paragraphs (pre, line breaks)
Text formatting (bold, italic, deleted, inserted, subscript, superscript, marked)
Quotations (quote, blockquote, abbreviations, address, cite, bidirectional override)
Entities & symbols (&entity_name, &entity_number,  , useful HTML character entities, diacritical marks, mathematical symbols, greek letters, currency symbols, )
Id (bookmarks)
Classes (select elements, multiple classes, different tags can share same class, )
Blocks & Inlines (div, span)
Computercode (kbd, samp, code, var)
Lists (ordered, unordered, description lists, control list counting, nesting)
Tables (colspan, rowspan, caption, colgroup, thead, tbody, tfoot, th)
Images (src, alt, width, height, animated, link, map, area, usenmap, , picture, picture for format support)
old fashioned audio
old fashioned video
Iframes (URL src, name, target)
Forms (input types, action, method, GET, POST, name, fieldset, accept-charset, autocomplete, enctype, novalidate, target, form elements, input attributes)
URL encode (scheme, prefix, domain, port, path, filename, ascii-encodings)
Learn about oldest web browsers onwards
Learn early HTML versions (doctypes & permitted elements for each version)
Make a 90s-like web page compatible with as much early web formats as possible, earliest web browsers’ compatibility is best here
Learn how to teach HTML5 features to most if not all older browsers
Install Adobe XD
Register a account at Figma
Learn Adobe XD basics
Learn Figma basics
Install Microsoft’s VS Code
Install my Microsoft’s VS Code favorite extensions
Learn HTML5
Semantic elements
Layouts
Graphics (SVG, canvas)
Track
Audio
Video
Embed
APIs (geolocation, drag and drop, local storage, application cache, web workers, server-sent events, )
HTMLShiv for teaching older browsers HTML5
HTML5 style guide and coding conventions (doctype, clean tidy well-formed code, lower case element names, close all html elements, close empty html elements, quote attribute values, image attributes, space and equal signs, avoid long code lines, blank lines, indentation, keep html, keep head, keep body, meta data, viewport, comments, stylesheets, loading JS into html, accessing HTML elements with JS, use lowercase file names, file extensions, index/default)
Learn CSS
Selections
Colors
Fonts
Positioning
Box model
Grid
Flexbox
Custom properties
Transitions
Animate
Make a simple modern static site
Learn responsive design
Viewport
Media queries
Fluid widths
rem units over px
Mobile first
Learn SASS
Variables
Nesting
Conditionals
Functions
Learn about CSS frameworks
Learn Bootstrap
Learn Tailwind CSS
Learn JS
Fundamentals
Document Object Model / DOM
JavaScript Object Notation / JSON
Fetch API
Modern JS (ES6+)
Learn Git
Learn Browser Dev Tools
Learn your VS Code extensions
Learn Emmet
Learn NPM
Learn Yarn
Learn Axios
Learn Webpack
Learn Parcel
Learn basic deployment
Domain registration (Namecheap)
Managed hosting (InMotion, Hostgator, Bluehost)
Static hosting (Nertlify, Github Pages)
SSL certificate
FTP
SFTP
SSH
CLI
Make a fancy front end website about
Make a few Tumblr themes
===You are now a basic front end developer!
Learn about XML dialects
Learn XML
Learn about JS frameworks
Learn jQuery
Learn React
Contex API with Hooks
NEXT
Learn Vue.js
Vuex
NUXT
Learn Svelte
NUXT (Vue)
Learn Gatsby
Learn Gridsome
Learn Typescript
Make a epic front end website about
===You are now a front-end wizard!
Learn Node.js
Express
Nest.js
Koa
Learn Python
Django
Flask
Learn GoLang
Revel
Learn PHP
Laravel
Slim
Symfony
Learn Ruby
Ruby on Rails
Sinatra
Learn SQL
PostgreSQL
MySQL
Learn ORM
Learn ODM
Learn NoSQL
MongoDB
RethinkDB
CouchDB
Learn a cloud database
Firebase, Azure Cloud DB, AWS
Learn a lightweight & cache variant
Redis
SQLlite
NeDB
Learn GraphQL
Learn about CMSes
Learn Wordpress
Learn Drupal
Learn Keystone
Learn Enduro
Learn Contentful
Learn Sanity
Learn Jekyll
Learn about DevOps
Learn NGINX
Learn Apache
Learn Linode
Learn Heroku
Learn Azure
Learn Docker
Learn testing
Learn load balancing
===You are now a good full stack developer
Learn about mobile development
Learn Dart
Learn Flutter
Learn React Native
Learn Nativescript
Learn Ionic
Learn progressive web apps
Learn Electron
Learn JAMstack
Learn serverless architecture
Learn API-first design
Learn data science
Learn machine learning
Learn deep learning
Learn speech recognition
Learn web assembly
===You are now a epic full stack developer
Make a web browser
Make a web server
===You are now a legendary full stack developer
[...]
(Computer system)=
Learn to execute and test your code in a command line interface
Learn to use breakpoints and debuggers
Learn Bash
Learn fish
Learn Zsh
Learn Vim
Learn nano
Learn Notepad++
Learn VS Code
Learn Brackets
Learn Atom
Learn Geany
Learn Neovim
Learn Python
Learn Java?
Learn R
Learn Swift?
Learn Go-lang?
Learn Common Lisp
Learn Clojure (& ClojureScript)
Learn Scheme
Learn C++
Learn C
Learn B
Learn Mesa
Learn Brainfuck
Learn Assembly
Learn Machine Code
Learn how to manage I/O
Make a keypad
Make a keyboard
Make a mouse
Make a light pen
Make a small LCD display
Make a small LED display
Make a teleprinter terminal
Make a medium raster CRT display
Make a small vector CRT display
Make larger LED displays
Make a few CRT displays
Learn how to manage computer memory
Make datasettes
Make a datasette deck
Make floppy disks
Make a floppy drive
Learn how to control data
Learn binary base
Learn hexadecimal base
Learn octal base
Learn registers
Learn timing information
Learn assembly common mnemonics
Learn arithmetic operations
Learn logic operations (AND, OR, XOR, NOT, NAND, NOR, NXOR, IMPLY)
Learn masking
Learn assembly language basics
Learn stack construct’s operations
Learn calling conventions
Learn to use Application Binary Interface or ABI
Learn to make your own ABIs
Learn to use memory maps
Learn to make memory maps
Make a clock
Make a front panel
Make a calculator
Learn about existing instruction sets (Intel, ARM, RISC-V, PIC, AVR, SPARC, MIPS, Intersil 6120, Z80...)
Design a instruction set
Compose a assembler
Compose a disassembler
Compose a emulator
Write a B-derivative programming language (somewhat similar to C)
Write a IPL-derivative programming language (somewhat similar to Lisp and Scheme)
Write a general markup language (like GML, SGML, HTML, XML...)
Write a Turing tarpit (like Brainfuck)
Write a scripting language (like Bash)
Write a database system (like VisiCalc or SQL)
Write a CLI shell (basic operating system like Unix or CP/M)
Write a single-user GUI operating system (like Xerox Star’s Pilot)
Write a multi-user GUI operating system (like Linux)
Write various software utilities for my various OSes
Write various games for my various OSes
Write various niche applications for my various OSes
Implement a awesome model in very large scale integration, like the Commodore CBM-II
Implement a epic model in integrated circuits, like the DEC PDP-15
Implement a modest model in transistor-transistor logic, similar to the DEC PDP-12
Implement a simple model in diode-transistor logic, like the original DEC PDP-8
Implement a simpler model in later vacuum tubes, like the IBM 700 series
Implement simplest model in early vacuum tubes, like the EDSAC
[...]
(Conlang)=
Choose sounds
Choose phonotactics
[...]
(Animation ‘movie’)=
[...]
(Exploration top-down ’racing game’)=
[...]
(Video dictionary)=
[...]
(Grand strategy game)=
[...]
(Telex system)=
[...]
(Pen&paper tabletop game)=
[...]
(Search engine)=
[...]
(Microlearning system)=
[...]
(Alternate planet)=
[...]
(END)
4 notes
·
View notes
Link
Vue Composition API によって Vue.js にも React Hooks のようなロジックの再利用性の高い開発体験がもたらされようとしています。 しかし、まだ「Composition API の良さをわかっていない」という方や「Composition API をうまく利用した書き方がわからない」という方も多いかと思います。 本記事では Composition API 時代の便利ライブラリ VueUse を用いた実装例や、 VueUse 自体の実装がどのようなものか紹介します。 Composition API の良さや雰囲気もキャッチアップしていただければ幸いです。 VueUse とは? VueUse は Anthony Fu さん1が中心に開発しているライブラリで、Composition API を用いた便利系関数を数多く集めたライブラリです。 例えば、ブラウザ上のマウスポインタの座標をリアクティブに取得する useMouse(), ブラウザ API の localStorage を使って状態を保持できる useLocalStorage(), 負荷対策のために連続する関数呼び出しを防ぐ useDebounceFn() 2などといった関数が提供されています。 公式サイト: https://vueuse.js.org/ GitHub: antfu/vueuse npm: @vueuse/core 検証環境の構築 GitHub リポジトリの Description に記載通り、Vue 2系・3系のどちらでも利用可能です: 🧰 Collection of Composition API utils for Vue 2 and 3 https://vueuse.js.org/ 今回は Vue CLI で立ち上げた Vue 2.6 系のプロジェクトに @vue/composition-api をプラグインとして追加した環境で検証します。 動作確認した環境 macOS Catalina Node.js 12.18.1 npm 6.14.5 Vue CLI v4.4.4 Chrome 83 Vue CLI のインストール Vue CLI ��グローバルインストールしたくない方は、以下の手順の vue コマンド部分を npx @vue/cli に読み替えていただいても大丈夫です。 プロジェクトの作成 vue-2-vueuse-trial というプロジェクト名で環境を構築していきます: vue create vue-2-vueuse-trial 設定は以下のようにしました: Vue CLI v4.4.4 ? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, TS, Linter ? Use class-style component syntax? No ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? No ? Pick a linter / formatter config: Basic ? Pick additional lint features: Lint on save ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files ? Save this as a preset for future projects? No プラグインと VueUse の導入 プロジェクトディレクトリが出来上がったら、@vue/composition-api と VueUse を npm install します: cd vue-2-vueuse-trial npm i @vueuse/core@vue2 @vue/composition-api src/main.ts に Vue.use(VueCompositionApi) を追加します3: src/main.ts import Vue from 'vue' +import VueCompositionApi from '@vue/composition-api' import App from './App.vue' +Vue.use(VueCompositionApi) Vue.config.productionTip = false npm run serve で開発ビルドを開始してください。 VueUse の関数を使ってみる useMouse() リアクティブにマウスポインタの座標が取得できる useMouse() を使ってみます: src/App.vue <template {{ x }}, {{ y }} </template <script lang="ts" import { defineComponent } from '@vue/composition-api' import { useMouse } from '@vueuse/core' export default defineComponent({ setup() { // tracks mouse position const { x, y } = useMouse() return { x, y } } }) </script これだけでマウスポインタの座標がリアクティブに反映されていることがわかるかと思います。 useMouse() の実装を確認すると useEventListener() という関数を使っていて、 useEventListener() はコンポーネントのマウント時(Composition API の onMounted() を利用)にイベントリスナーを追加していることがわかります: https://github.com/antfu/vueuse/blob/master/packages/core/useMouse/index.ts https://github.com/antfu/vueuse/blob/master/packages/core/useEventListener/index.ts VueUse ではこのような関数がより抽象的な関数を参照しているパターンの実装が所々に見られます。 Composition API を用いた良い実装の例として知っておくと良いかと思います。 useLocalStorage() ブラウザ API の localStorage を使って状態を保持できる useLocalStorage() を使ってみます。 まずは useLocalStorage() を使わず、 VueUse がなくても利用できる reactive() 4 を使ってみましょう: src/App.vue <template name: <input v-model="state.name" color: <input v-model="state.color" {{ state }} </template <script lang="ts" import { defineComponent, reactive } from '@vue/composition-api' export default defineComponent({ setup() { const state = reactive({ name: 'Apple', color: 'red', }) return { state } } }) </script name, color を変更すると、下に表示されている JSON 形式の state ��表示も更新される画面が表示されます: 上記の実装では name を Banana, color を yellow のように変更してページをリロードすると、元の状態(name が Apple, color が red)に戻ります。 以下のように ブロックを変更し、reactive() の代わりに useLocalStorage() を利用するように変更してみます: import { defineComponent } from '@vue/composition-api' import { useLocalStorage } from '@vueuse/core' export default defineComponent({ setup() { // persist state in localStorage const state = useLocalStorage( 'my-storage', { name: 'Apple', color: 'red', }, ) return { state } } }) state が localStorage に保存されるようになったので、ページをリロードしても状態が保持されるようになりました。 サンプルアプリとしてよくある ToDo リストの状態管理に useLocalStorage() を使うようにすると、手軽にデータを保存できる ToDo リストにできて楽しいかもしれません。 公式サイトが Storybook でできている件 公式サイトが Storybook でできていて、各関数を即座に試せるリファレンスとなっています。 各関数のページ下部には関数の "Source" へのリンクがあり、ソースを見てどのような実装になっているか追っていくと Composition API を用いた良い実装の勉強となるかと思います。 所感 VueUse は多くの便利関数を提供しているので、今後お世話になる可能性が高いライブラリだと思いました。 まだ試せていない関数が多くあるので、使ってみたりコードを読んだりしてみようかと思います。
0 notes
Text
FlexJobs: Senior Ruby on Rails Developer
Headquarters: Boulder, CO URL: https://www.flexjobs.com
Responsibilities of the Job - The Opportunity
We’re looking for an exceptional Ruby on Rails developer to join our engineering team. As an engineer at FlexJobs you’ll work on challenging projects in collaboration with our Product and Quality Assurance teams to build, release, and maintain features for our user base.
Our team moves quickly and the ideal candidate will be comfortable working independently and at a fast pace, while also being adept at collaborating in a 100% remote environment.
Your Experience
5-7 years building web applications with Ruby on Rails
5-7 years building and maintaining high volume, consumer-facing, responsive websites
5-7 years working with client-side development technologies including HTML5, CSS, and various JavaScript (AJAX, JSON, JQUERY, Webpack, Vue, Angular)
5-7 years experience working with modern development tooling (Git, Github, Docker, bash, aws)
Experience with PHP and maintaining Wordpress sites is a plus
Traits Required of All Team Members, You, Included
A sense of pride in your work
A streak of perfectionism when it comes to details
Being highly organized, responsible, and ethical
Being proactive when it comes to asking questions, brainstorming, and working with colleagues
Excellent time management and organizational skills
An appreciation and enthusiasm for the ability to work remotely
Other Requirements
Interest in a long-term position with a company that you’re proud to be a part of
A fully functioning home office, including high-speed internet access, a fast computer, and phone access
A work environment that is quiet and one in which you can really focus without distractions
How to Apply
If this job description makes you feel as if it was written perfectly for you, then please apply! What we'll need:
An intro email/cover letter telling us why you want to work for FlexJobs (v. another company)
What makes you a great fit for this position
What hourly rate (based on a full-time, hourly schedule) you would be comfortable with
A completed Pairin assessment
A current resume in .doc, .docx, .pdf, .markdown, or .txt.
Applications can be sent to [email protected].
If you are selected to move forward, you may be required to do a background check.
FlexJobs is an equal opportunity employer. We celebrate and support diversity and are committed to creating an inclusive work environment for all employees. As a part of this commitment, we have pledged to be an Open to All business.
FlexJobs is also a veteran- and military spouse-friendly employer. Our positions are perfectly structured for qualified candidates who meet this criterion and we have a workplace culture that supports their work and life.
To apply: [email protected]
from We Work Remotely: Remote jobs in design, programming, marketing and more https://ift.tt/3b0EsfD from Work From Home YouTuber Job Board Blog https://ift.tt/3aXMMN8
0 notes
Text
SVG Web Page Components For IoT And Makers (Part 2)
SVG Web Page Components For IoT And Makers (Part 2)
Richard Leddy
2019-05-15T13:30:16+02:002019-05-15T15:35:00+00:00
So, we already have ways of dynamically loading a menu of SVG icons made to react by loading panels if we so desire, but the icons were not actual components. We were able to use a simple trick of bringing in the SVG for each icon and passing it into the Vue application. It was simple enough to generate a list of icons, and each icon reacted in a similar way except for small data differences. The data difference made it possible to bind the name of a panel to each icon in such a way that the handler for the icon’s button click could pass it on.
When a panel is loaded in the form of Vue component, everything about the panel and its components has to be loaded, templates, JavaScript, and more. So, the job of just managing loading the panel is bigger than what we have encountered so far in this discussion.
Let’s look at Vue’s way of providing a hook for async loading. The following snippet is from the Vue guide.
Vue.component('async-example', function (resolve, reject) { setTimeout(function () { // Pass the component definition to the resolve callback resolve({ template: '<div>I am async!</div>' }) }, 1000) })
The guide tells us that the setTimeout function is an example of how to use the synchronicity with Vue components. Notice that where before there had been an object as the second parameter to Vue.component, there is now a function, which is referred to as a factory function. Within the resolve callback is a component definition, that would have been the second parameter to Vue.component before.
So, I had to stare at this example a while before it made sense to me. Here is another example, which suits me better:
Vue.component('async-example', function (resolve, reject) { // Vue will call this function and promise itself to handle // it when it gets back with data. // this function can then call a promising object loader // here the 'loader' function is some abstract function. // Most likely the application will use 'fetch' // but it could be something else. loader('/my/resource/on/server.json'). then(function (JSON_data) { var object = transformJSONToJSObject(JSON_data); resolve(object) }).catch( (error) => { handle it } );
It seems like the right thing to do to make a more general function to go around this form.
function componentLoader(c_name,resource_url) { Vue.component(c_name, function (resolve, reject) { loader(resource_url). then(function (JSON_data) { var object = transformJSONToJSObject(JSON_data); resolve(object) }).catch( (error) => { handle it } ); }
So, in general, to load a component, we would just need a line like the following:
componentLoader('ThermoPanel','./JSON/thermo-panel.json');
So now, just what is the JSON that is being loaded? It can include everything about the component. In this case, as a panel component, it can include thermometers, machine switches, sliders, gauges, and more. While it seemed nicer to keep the components parts on the web page, it may actually work better to use the subcomponent field that is in the longer example for ‘thermo-panel’ that we made before and also for the other similarly constructed panels. The JSON will contain a complete panel structure.
However, if the reader will notice the inclusion of the function call to transformJSONToJSObject, he will understand that JSON might be coded in some way to make transport easier and to make it easier for a server to handle the definition. After all, the definition will include complete SVG templates, function definitions, and other JavaScript expressions. Also, the JSON object may contain more than just the panel definition because some information may simply aid in bookkeeping or validation. So, one can expect that there will be some treatment of the object upon receipt.
As for the encoding, the data coming in from the server may be encoded in a number of ways. Perhaps it will be simply URL encoded. Or more securely, it might be enciphered. For this discussion, we can just use URL encoding.
Some of the tools that are available for creating Vue applications no doubt take care of the JSON transformation. But, this discussion has so far avoided the use of command line tools. This omission is not that bad as we have also used Vue with the minimum of resources, using only one script tag for the referring to the CDN. However, I certainly do recommend looking into the command line tools especially for organizing projects.
When the JSON arrives at the page, given the component is completely assembled with subcomponents, no more work has to be done to fetch the parts. We can make the assumption that all components will come in fully defined for the rest of this discussion. But, assembling complete component hierarchies will require command line tools at some point.
The SVG editing process will also require some work. The SVG editing processes allow a designer to draw a panel and all the components on it. But, each subcomponent has to be identified, called out in a group, or given a place holder. Any approach to using the drawing requires some treatment of the SVG so that Vue component tags can replace the groups or graphic elements. In this way, any artist rendering can become a template. And, the drawn subcomponents will have to be disassembled into templates for Vue subcomponents.
This sort of parsimony is contrary to the workflow of most of the JavaScript frameworks. The frameworks are about assembling pages. But, editing or drawing, results in something already assembled by an artist. In practice, the result of editing does not provide a text file that corresponds directly to a framework component definition.
More about the editing process may be considered in some other discussion. There is a lot to it. But, for now, we have the tools we need in order to load hierarchal components and make them come alive.
The Lazy Application
For our IoT panel construction, we already have a selection bar that responds to searches. And, we have a way of loading components when we need them. We just need to connect up these parts. And, at last, we have to make sure that the panels appear and that they start working when they do.
The lazy loading of panels done by the async code above provides a sketch of an idea. But, thankfully, some people have experimented to find ways of making sure that all kinds of components can be loaded. There is one codepen entry that shows how to update Vue apps with new components of varying types. That is the mechanism that is needed for updating a designated part of the page with different types of panel.
With the ability to add in different kinds of panels and with a simple mechanism to load their definitions, we can, at last, have our panel searching page.
Here is the HTML that we need in our page so that the Vue app can place components in dynamically:
<template v-for="(panel, index) in panelList"> <component :is="panel" :key="panel.name"></component> </template>
The component tag is a Vue meta tag. See the reference for dynamic components. The properties, special attributes, used for the component tag in this case are is and key. The is attribute exists for dynamic components. And, the key ensures that the new children will have different identities from each other and helps Vue to decide what to draw.
“Children of the same common parent must have unique keys. Duplicate keys will cause rendering errors.”
The template tag will loop through components that are provided in the panelList data field of the application.
So, starting with the application level Vue definition for the icon app, we can make changes to include the panelList in the data elements. (Let’s now call it the panelApp).
var panelApp = new Vue({ el: '#PanelApp', data: { iconList: [ // Where is the data? Still on the server. ], panelList: [ ], queryToken : "Thermo Batches" // picked a name for demo }, methods : { goGetPanel: function (pname) { // var url = panelURL(pname); // this is custom to the site. fetch(url).then((response) => { // this is now browser native response.text().then((text) => { var newData = decodeURIComponent(text); eval(pHat); // widgdef = object def, must be assignment pHat = widgdef; var pnameHat = pname + pcount++; pHat.name = pnameHat; // this is needed for the key this.panelList.push(pHat); // now it’s there. }).catch( error => { /* handle it */ }); } } });
Besides adding in the panel, goGetPanel is now in a form required for getting a component definition from a database or other store. The server side must be careful about delivering JavaScript code in the correct format. As for what the object looks like coming from the server, we have already seen it. It is the kind of object used as a parameter to Vue.component.
Here is the complete body of the Vue app that provides a menu as a search result and a place to put panels fetched from the server when the user clicks an icon.
<div id="PanelApp"> <!-- Recognize the name from the Vue doc --> <div> <h2 itemprop="name">Request MCU Groups</h2> <p itemprop="description">These are groups satistfying this query: .</p> <button onclick="GetIcons(11)">Find All</button> <button onclick="GetIcons(5)">Find 5 Point</button> <button onclick="GetIcons(6)">Find 6 Point</button> </div> <!-- Here is a Vue loop for generating a lit --> <div class="entryart" style="padding:4px"> <button v-for="iconEntry in iconList" @click="goGetPanel(iconEntry.name)" > <div v-html="iconEntry.icon"> </div> </button> </div> <div class="entryart" style="padding:4px" > <template v-for="(panel, index) in panelList"> <component :is="panel" :key="panel.name" :ref="panel.name" ></component> </template> </div> </div>
In the last div, the component tag now has a ref parameter bound to the panel name. The ref parameter allows Vue app to identify which component to update with data and keeps components separate. The ref parameters also allow our application access to the new dynamically loaded components.
In one test version of the panel app, I have the following interval handler:
setInterval(() => { var refall = panelApp.$refs; // all named children that panels for ( var pname in refall ) { // in an object var pdata = refall[pname][0]; // off Vue translation, but it’s there. pdata.temp1 = Math.round(Math.random()*100); // make thermos jump around. pdata.temp2 = Math.round(Math.random()*100); } },2000)
The code provides a little animation, changing thermometers randomly. Each panel has two thermometers, and the app allows the user to keep adding panels. (In the final version, some panels must be thrown away.) The refs are being accessed using panelApp.$refs, a field that Vue creates given the refs information in the component tag.
So, this is what the randomly jumping thermometers look like in one snapshot:
A collection of animated panels for one type of panel (or component). (Large preview)
Connecting The Panel To The IoT Device
So, the last piece of code is a setInterval test updating thermometers with random values every two seconds. But, what we want to do is read in real data from real machines. In order to do that, we will need some form of communication.
There are a variety of ways. But, let’s use MQTT which is a pub/sub message system. Our SPWA can subscribe to messages from devices at any time. When it gets those messages the SPWA can direct each message to the appropriate data handler for the panel mapped to the device identified in the message.
So, basically what we need to do is replace the setInterval with a response handler. And, that will be for one panel. We probably want to map panels to handlers as they are loaded. And, it is up to the web server to see that the correct mapping is delivered.
Once the web server and the SPWA have the page ready for operation, the web server no longer needs to take care of messaging between the page and the device. the MQTT protocol specifies a routing server to handle pub/sub. A number of MQTT servers have been made. Some of them are open source. One very popular one is Mosquito, and there are a few developed on top of Node.js.
The process for the page is simple. The SPWA subscribes to a topic. One good version of a topic is an identifier for an MCU such as a MAC address or a serial number. Or, the SPWA could subscribe to all temperature readings. But, then the page would have to do the work of filtering the messages from all devices. Publication in MQTT is essentially a broadcast or multicast.
Let’s take a look at how the SPWA will interface with MQTT.
Initializing MQTT On The SPWA
There are several client libraries to choose from. One, for instance, is a MQTT.js. Another is eclipse paho. There are more of course. Let’s use Eclipse Paho since it has a CDN stored version. We just need to add the following line to our page:
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>
The MQTT client has to connect to a server before it can send and receive messages. So, lines setting up the connection also need to be included in the JavaScript. We can add in a function MQTTinitialize which sets up the client and the responses for connection management and message receipt.
var messagesReady = false; var mqttClient = null; function MQTTinitialize() { mqttClient = new Paho.MQTT.Client(MQTTHostname, Number(MQTTPort), "clientId"); mqttClient.onMessageArrived = onMessageArrived; // connect the client mqttClient.connect({ onSuccess: () => { messagesReady = true; } }); // set callback handlers mqttClient.onConnectionLost = (response) => { // messagesReady = false; // if (response.errorCode !== 0) { console.log("onConnectionLost:"+response.errorMessage); } setTimeout(() => { MQTTinitialize() },1000); // try again in a second }; }
Setting up Subscription
With the connection ready, the client can subscribe to message channels, send messages on them, etc. Just a few routines can do most of the work necessary to connect panels with the MQTT pathways.
For the panel SPWA, the moment of subscription can be used to establish the association between the panel and the topic, the MCU identifier.
function panelSubcription(topic,panel) { gTopicToPanel[topic] = panel; gPanelToTopic[panel] = topic; mqttClient.subscribe(topic); }
Given that an MCU is publishing on its topic, the SPWA will receive a message. Here, the Paho message is unpacked. And, then the message is passed on into the application mechanics.
function onMessageArrived(pmessage) { // var topic = pmessage.destinationName; var message = pmessage.payloadString; // var panel = gTopicToPanel[topic]; deliverToPanel(panel,message); }
So, now all we need to do is create deliverToPanel which should be somewhat like the interval handler that we had before. However, the panel is clearly identified, and only the keyed data sent in the particular message may be updated.
function deliverToPanel(panel,message) { var refall = panelApp.$refs; // all named children that panels var pdata = refall[panel][0]; // off Vue translation, but it’s there. var MCU_updates = JSON.parse(message); for ( var ky in MCU_updates ) { pdata[ky] = MCU_updates[ky] } }
This deliverToPanel function is abstract enough to allow any panel definition with any number of data points for animation.
Sending Messages
To complete the application loop between the MCU and the SPWA, we define a function to send a message.
function sendPanelMessage(panel,message) { var topic = gPanelToTopic[panel]; var pmessage = new Paho.MQTT.Message(message); pmessage.destinationName = topic; mqttClient.send(pmessage); }
The sendPanelMessage function does no more than sending the message out on the same topic pathway that the SPWA subscribes to.
As we plan to make the icon buttons responsible for bringing in some number of panels for a single cluster of MCU’s, there will be more than one panel to take care of. But, we keep in mind that each panel corresponds to a single MCU, so we have a one-one mapping, for which we may use two JavaScript maps for the map and the inverse.
So, when do we send messages? Usually, the panel application will send a message when it wants to change the state of the MCU.
Keeping The View (Vue) State In Sync With Devices
One of the great things about Vue is that it is very easy to keep the data model synchronized with the activity of the user, who may edit fields, click on buttons, use sliders, etc. One can be sure that button and field changes will be reflected immediately in the components’ data fields.
But, we want changes to fire off messages to the MCU as soon as the changes occur. So, we seek to make use of the interface events that Vue may govern. We seek to respond to such an event, but only after the Vue data model is ready with the current value.
I created another kind of panel, this one with a fairly artistic looking button (perhaps inspired by Jackson Pollock). And, I went about turning it into something whose click reports the state back to the panel that contains it. That was not so simple a process.
One thing that threw me off is that I had forgotten some of the oddities in managing SVG. I first tried to change the style string so that the display field of the CSS style would either be “None” or “something”. But, the browser never rewrote the styles string. But, as that was cumbersome, I tried changing the CSS class. That also had no effect. But, there the visibility attribute, which most of us recall from old HTML (version 1.0 perhaps), but that is very up to date in SVG. And, that works well. All, I had to do was to get the button click event to propagate.
Vue has designed properties to propagate in one direction, parent to child. So, to change data in the application, or in the panel, you have to send a change event to the parent. Then, you can change the data. The change of the data element controlling the button causes Vue to update the property affecting the visibility of the SVG element we have chosen to indicate state. Here is an example:
Finally, a collection of different types of panels each with instances assigned to separate MCU’s. (Large preview)
Each instance of the squiggly button panel is independent. So, some are ON and some are OFF.
This snippet of SVG contains the odd-looking yellow indicator:
<path :visibility="stateView" style="opacity:0.98000004;fill:#faea4a;fill-opacity:1;stroke:#eecd5c;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="sunthing" d="m -36.544616,12.266886 c 19.953088,17.062165 5.07961,-19.8251069 5.317463,8.531597 0.237853,28.356704 13.440044,-8.847959 -3.230451,10.779678 -16.670496,19.627638 14.254699,-2.017715 -11.652451,3.586456 -25.90715,5.60417 10.847826,19.889979 -8.095928,-1.546575 -18.943754,-21.436555 -1.177383,14.210702 -4.176821,-12.416207 -2.999438,-26.6269084 -17.110198,8.030902 2.14399,-8.927709 19.254188,-16.9586105 -19.075538,-8.0837048 9.448721,-5.4384245 28.52426,2.6452804 -9.707612,-11.6309807 10.245477,5.4311845 z" transform="translate(78.340803,6.1372042)" />
The visibility is populated by stateView, a computed variable that maps the state boolean to a string for SVG.
Here is the panel component definition template:
<script type="text/x-template" id="mcu-control-panel-template"> <div> <control-switch :state="bstate" v-on:changed="saveChanges" ></control-switch> <gauge :level="fluidLevel" ></gauge> </div> </script>
And, this is the JavaScript definition of the Vue panel with its children as subcomponents:
var widgdef = { data: function () { var currentPanel = { // at the top level, values controlling children bstate : true, fluidLevel : Math.round(Math.random()*100) } // return currentPanel }, template: '#mcu-control-panel-template', methods: { saveChanges: function() { // in real life, there is more specificity this.bstate = !this.bstate relayToMCU(this.name,"button",this.bstate) // to be defined } }, components: { 'control-switch' : { // the odd looking button props: [’state'], template: '#control-switch-template', // for demo it is in the page. computed: { // you saw this in the SVG above. stateView : function() { return ( this.state ) ? "visible" : "hidden" } }, methods : { // the button handler is in the SVG template at the top. stateChange : function () { // can send this.$emit('changed'); // tell the parent. See on the template instance } } }, 'gauge' : { // some other nice bit of SVG props: ['level'], template: '#gauge-template' } } }
So, now the mechanism for a single button embedded in a panel has been laid out. And, there has to be a hook for telling the MCU that something has taken place. It must be called immediately after the data state of the panel component has been updated. Let’s define it here:
function relayToMCU(panel,switchName,bstate) { var message = switchName + ':' + bstate // a on element parameter string. sendPanelMessage(panel,message) }
There is the state change on it’s way to hardware in just two lines of code.
But, this is a fairly simple case. Any switch can be viewed as a function call to a piece of hardware out in the world. So, the string might contain the switch name and several other data elements. So, the component method that registers change will have to have some custom handling in it in order that it might gather together all the pieces of data set on the panel and send them along in one command string. Even the command string is a little simple. If the MCU is quite small, the command string might have to be translated into a code. If the MCU has a great deal of capability, the command string might actually be a JSON structure or perhaps all the data that the panel hosts.
In this discussion, the buttons on the icon panel contain the name of the panel to fetch. That may also be fairly simplified as well. It seems to make sense that that parameter can stand for any panel that might be stored in an enterprises databases. But, perhaps it is some formula. Perhaps, information about the panel should be wrapped around the panel definition that we receive from the server. In any case, the basics can be easily expanded upon once certain headaches are out of the way, like making the SVG respond to clicks properly.
Conclusion
This discussion has laid out some basic steps and decisions that lead to the realization of a Single Page Web App (SPWA) that can interface with IoT devices. We now know how to get panels from a web server and turn them into MCU interface.
There is much more to this discussion with quite a few other discussions that may follow. Starting with Vue is one thing to think about. But, then there is the whole MCU story, which we have only briefly touched upon.
In particular, by selecting MQTT as a communication substrate, we assume that IoT devices on the other end can somehow be ruled by MQTT. But, that may not always be the case. Sometimes gateways are needed if MQTT is to gain access to a device with serial links or Bluetooth. Or, perhaps all one ever needs from on the web page is WebSockets. Nevertheless, we used MQTT as an example to show how Vue could both receive and send data while keeping its data state in sync with devices.
Once again we only have part of the story. This time it is for synchronization because the page should be able to deal with alerts and bother the user if something critical is happening. Sometimes messages can get lost. So, we have to have a mechanism for acknowledgments.
Finally, it is my opinion that Vue makes updating data upon receipt quite elegant. But, sending the state changes is not so straight forward. It does not seem to make the job much simpler than can be done with vanilla JavaScript. But, there is a way and it makes sense.
Perhaps a clean library can be built to make a universal set of components for all panels. The elements for making such libraries and having them stored in a database have been briefly mentioned. Tools that go beyond just making SVG pictures may have to be developed. In any case, there are likely many things that can be done for the next steps.
(dm, yk, il)
0 notes
Text
Create Vue Apps Visually with the Vue CLI User Interface Tool
Most JavaScript frameworks these days usually have some sort of Command Line Interface (CLI) that enables users quickly scaffold applications and get straight to building apps, without doing repetitive set up tasks. Some common ones are:
Sometimes these CLIs come with a lot of configurations, which may be fun to use, but also a bit complex, since some commands may take in a lot of parameters and flags.
The Vue CLI introduced a Graphical User Interface (GUI), which can save us a lot of time and give us clarity on what we are actually doing while building a Vue App generated with the CLI.
NOTE The UI Tool is till in Beta, and a lot may change.
You should have a basic to intermediate understanding of JavaScript and VueJS
You should have NodeJS installed.
You need to have Vue CLI 3 installed.
npm i -g @vue/cli
Typing in vue on your terminal should give you this.
vue Usage: vue <command> [options] Options: -V, --version output the version number -h, --help output usage information Commands: create [options] <app-name> create a new project powered by vue-cli-service add <plugin> [pluginOptions] install a plugin and invoke its generator in an already created project invoke <plugin> [pluginOptions] invoke the generator of a plugin in an already created project inspect [options] [paths...] inspect the webpack config in a project with vue-cli-service serve [options] [entry] serve a .js or .vue file in development mode with zero config build [options] [entry] build a .js or .vue file in production mode with zero config ui [options] start and open the vue-cli ui init [options] <template> <app-name> generate a project from a remote template (legacy API, requires @vue/cli-init) config [options] [value] inspect and modify the config Run vue <command> --help for detailed usage of given command.
Among the options, you can see there's a command called ui. This is what we're going to explore.
... ui [options] start and open the vue-cli ui ... `
Create a directory where you want your Vue apps to be, I'll call mine vue-ui
mkdir vue-ui
Then open the Vue UI tool with
vue ui
This opens the Vue GUI on http://localhost:8001 on your default browser.
The three sections shown are intuitive but to explain:
Projects - will list projects of the current directory, or the ones you have used this tool to generate
Create - will allow you to create a new Vue project
Import - will allow you to import a project from either a directory, or a remote github repository.
At the bottom of the screen, on the status bar, you will be shown where your current directory is, and on the far right, you can change the theme of the app.
Let's create a project. Click on the Create Tab, and click on the Create a new project here button.
A pop will show up. Let's fill it in with the the project name scotch-vue.
Select npm as the default package manager, and initialize a git repository if you want.
Press next, and you'll be taken to the presets tab. This is where we add in the configurations that are common to Vue applications. Select Manual and press next.
NOTE if you have saved presets, they will appear here, so that you can just select them instead. Below shows scotch-vue and all-settings presets I created earlier
You'll be navigated to the Features page so that you can select the Plugins and Configurations you want. I went mostly with the following configurations: Babel,Router, CSS Preprocessor, Linter/Formatter, Unit Testing, Use Config Files. Scroll down to see all the configs.
All the options have a More Info link, that opens in a new tab with the documentation on the plugins/features you are adding.
Finally, press next and you will be directed to the configurations section. Here's where you customize the configurations for the features you added in the previous section.
On the CSS pre-processors, pick SCSS/SASS
I decided to choose ESLint + Prettier, and selected lint on save.
Finally pick a unit testing solution: Mocha and Chai
Click on create project. You will be asked if you want to give the settings/preset a name. I called it scotch-vue-preset. Next time, you can just scaffold a project directly from this preset.
Clicking on Create Project will give you a loader, telling you the progress of the project creation, and the once done, take you to the projects dashboard.
You can open the application in an editor, by clicking on the app name on the top left.
The dashboard is divided into four parts:
1. Plugins
Lists your plugins and allow you to install other plugins into your current project.
You can click on the Install Plugins button on the top right to enable you search and install plugins.
2. Dependencies
Lists your npm dependencies, and allows you to add/remove dependencies.
You can click in the Install Dependencies button on the top right to enable you search and install dependencies.
3. Configurations
Allows you to modify configurable sections of your applications. Right now, you'll see two options:-
4. Tasks
Tasks allow you to perform operations on your application, that you normally do when building apps. They include the following. I've taken the descriptions directly from the UI.
Serve - Compiles and hot reloads your application
Build - Compiles and minifies for production
Lint - Lints and fixes files
Test - Run tests using Mocha
Inspect - inspect the resolved webpack config.
Note - These tasks are listed here based on our configuration. We do not have the E2E task listed for instance.
We've seen that this section compiles and hot reloads your application. The first part of the Serve section allows you to configure the serve task.
You can click on the gear icon to configure the serve task.
The more info button will open documentation regarding the vue-cli-service.
Then clicking the Run Task button will update the Dashboard Tab, and open the app in a new tab, as we specified in the serve task config. This is the tab opened, the default vue-cli app, with documentation links. The Run Task button changes to Stop Task.
The dashboard tab shows various stats about your application bundle, you can inspect it to see file sizes, and even loading speeds for your files.
This tab shows the logs for your task process.
The analyzer tab, tries to analyze your code, and create a graph showing the various dependencies of your code. In the below screenshot, we see the purple part representing the code we have written(even though it's generated), and the green section represents the code that we imported from dependencies.
The build section has the almost similar to the serve section, only that it produces a production bundle that can be used to deploy the application.
Clicking on the config for build task will also open configuration to allow you specify environments, output directories and even choose whether it's a web app, library or web component.
We won't look at the different tabs, as we explained them in the previous section, but notice that the analyzer, under your chunked app, has changed.
Lint should be straight forward. It will lint your code and give you an output.
This will allow us to run unit tests for our application. We just click on Run task, and see the output
This will produce the configuration of your webpack, in a json file.
We've seen how easy it is to scaffold a new VueJS application from scratch with the Vue UI tool. Even though still in beta, it can take you from Zero to building an App within seconds or minutes. Hope you find the tool helpful and use it more often, and watch out for new releases.
If you feel adventurous, you can inspect the Vue CLI UI source code.
And just in case you are wondering why the UI is so beautiful, the library used is the Vue UI library Happy Coding.
via Scotch https://ift.tt/2RdF9ZM
0 notes
Photo
New Post has been published on http://programmingbiters.com/vue-js%e2%80%8a-%e2%80%8asetting-up-auth0/
Vue.js — Setting up Auth0
There are many choices for handling security in applications. For me, offloading the details of username / password storage, change password workflows, new user signups, etc makes my app development less complicated. The team at Auth0 have done an incredible job of creating tools that allow you as a developer to add best in class security to your apps with ease. Building on the previous project, let’s setup Auth0 in the app and create a basic login page.
You will need to create an account with Auth0. Once you have your account, create a new client by clicking on the clients menu and then the new client button. That will give you a screen to name the client and choose a project type.
Auth0 — create new client
Once you click create it will take you to a quick start page where you can choose your framework and they will provide a setup guide. This will guide you thru adding the Auth0 to your app using the lock widget. I am going to be using the base Auth0 script and custom login page for this project. The lock widget is a great tool to get up and running quickly and the guide will be the best resource for using it. The main difference will be the login box, the guide will use the lock widget and I will provide a custom form … either one will process the request in a similar manner.
In the Auth0 client dashboard, select the settings tab. This is where you will find your domain and client id. These values will be needed later when making api calls via the Auth0 script. You will also need to set the allowed callback url. For development it will be http://localhost:8080 (if you are using the vue-cli and have not changed the port).
Be sure to click the save settings button at the bottom. You will also want to add a user for testing. Click on the users menu option on the left and then the create user button. Enter the details and click the save button.
Next, let’s add Auth0 to the app. There are several ways to install the package, I will be linking to it via the cdn. In the index.html, add the following line:
<!-- Auth0 --> <script src="https://cdn.auth0.com/w2/auth0-7.4.min.js"></script>
Setup auth.js
Create a file in the root of /src named auth.js. The auth logic for the entire app will be housed here. First, create an instance of Auth0.
/* eslint no-undef: "off" */ const auth0 = new Auth0( domain: 'YOUR DOMAIN', clientID: 'YOUR CLIENT ID', responseType: 'token', callbackURL: window.location.origin + '/' )
You will need to enter your domain and client id details from the settings tab in the Auth0 dashboard. If you used the webpack template from the vue-cli there are config files where you can set these details and point to them via process.env.variable_name, check out the documentation here.
This file will export 4 helper functions that we can use throughout our app:
login / logout / checkAuth / requireAuth
// login let login = (username, password) => auth0.login( connection: 'Username-Password-Authentication', responseType: 'token', email: username, password: password, scope: 'openid email' , function (err) if (err) alert('something went wrong: ' + err.message) )
The login function calls Auth0.login and passes it a config object. Auth0 provides multiple connections for social and enterprise logins but here I am using the username password connection. The response type is set to token indicating that we want to use a JWT (json web token) for our security strategy. The scope variable tells auth0 the details to be encoded in the jwt, depending on your backend api you might need to add additional data to identify the user on the api side.
// logout let logout = () => localStorage.removeItem('id_token') localStorage.removeItem('profile')
The logout function simply removes the id_token and profile items from local storage. These values are set when the login call is successful (more on that shortly).
// checkAuth let checkAuth = () => if (localStorage.getItem('id_token')) return true else return false
The checkAuth function simply returns true if there is value in the local store with and id of ‘id_token”. For a production app you could consider decoding the token and checking to make sure the value is a jwt token and has not expired. Auth0 offers a jwt-decode library that will aid in this. This library will not validate your token (that happens on the server side) but it can be used to help confirm the token.
// requireAuth let requireAuth = (to, from, next) => if (!checkAuth()) console.log('auth failed ...') let path = '/login' let result = auth0.parseHash(window.location.hash) if (result && result.idToken) // set token in local storage localStorage.setItem('id_token', result.idToken)
// redirect to home page path = '/'
// get user profile data auth0.getProfile(result.idToken, function (err, profile) if (err) // handle error alert(err) let user = JSON.stringify(profile) localStorage.setItem('profile', user) ) next( path: path ) else next()
This function is called from the router beforeEnter hook, it receives a to and from variable and callback variable named next. This allows you a chance to validate the route before the component is loaded. First we call the checkAuth function, if it passes we simply call the next() callback and let things continue on.
If the auth fails, we check the url for a hash and token. The Auth0 service is configured by default to use the re-direct method, so the whole app gets redirected back to the callback url in the Auth0 config. Since this beforeEnter hook is set on our home route, we can check it for the hash and token and set them to our local storage. We also grab the user profile and set that in local storage. One last thing to note in the function, I have variable named path that defaults to /login. If the url has a hash and token, I reset the path the take the user back home (you could also send the redirectUrl to Auth0 and take the user back where they were, for simplicity I am sending back them back to the home page). If the there was no hash or token and the checkAuth failed, the user will be taken to the login page.
Finally, export the functions:
export default checkAuth, login, logout, requireAuth
Create login container
Now that we have our auth logic setup, let’s create a simple login page. Under the containers folder, add a new file named Login.vue.
<template> <div id="login"> <div class="columns"> <div class="column is-one-quarter"> <form @submit.prevent="login"> <p class="control"> <input class="input" v-model="email" placeholder="email"> </p> <p class="control"> <input class="input" v-model="pass" placeholder="password" type="password"> </p> <p> <button class="button" type="submit">Login</button> </p> </form> </div> </div> </div> </template>
<script> import auth from '../auth'
export default name: 'login', data () return email: '', pass: '' , methods: login () auth.login(this.email, this.pass) </script>
Here I am using a simple form with inputs bound via v-model. When the form is submitted, the login method simply passes the inputs to the auth login function.
Adjusting the router
Let’s make some adjustments to the router instance to call the requireAuth function in the beforeEnter hook.
import Vue from 'vue' import Router from 'vue-router'
Vue.use(Router)
import login from './containers/Login' import home from './containers/Home' import dashboard from './containers/dashboard' import projects from './containers/projects' import auth from './auth'
// application routes const routes = [ path: '/login', component: login , path: '/', component: home, beforeEnter: auth.requireAuth , path: '/dashboard', component: dashboard, beforeEnter: auth.requireAuth , path: '/projects', component: projects, beforeEnter: auth.requireAuth ]
// export router instance export default new Router( mode: 'history', routes, linkActiveClass: 'is-active' )
Adjust the navbar
Next, the navbar needs to be updated wiring up the logout button and only showing if the user is logged in. In the navbar.vue component, add the following methods:
methods: logout () auth.logout() this.$router.go('/login') , isLoggedIn () return auth.checkAuth()
Make sure to import the auth file: import auth from ‘../auth��
Setup the click event on the button:
<a class="button" @click="logout()">Logout</a>
and finally add a v-if to the top level of the nav:
<nav class="nav has-shadow" v-if="isLoggedIn()">
Authorization headers in api calls
Now that our app is setup to authenticate our users, the app needs to send the token to our api when making secure calls. To make this work, I will set an authorization header on the default header object in axios.
Head back into the auth.js file, and in the section where it sets the token in local storage add the following line:
// set auth headers axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('id_token')
This adds the authorization header to every api call made with axios. In addition to setting the value when the auth token gets set, it needs to get set when the app loads (if there is a token). Add the following lines in the auth.js file, outside of the functions:
// set auth header on start up if token is present if (localStorage.getItem('id_token')) axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('id_token')
Response interceptor
The last item to add to make it secure is to create a response interceptor that will logout our user if an authorized call is returned. In the main.js file, add the following:
import auth from './auth' import axios from 'axios'
axios.interceptors.response.use((response) => return response , function (error) // Do something with response error if (error.response.status === 401) console.log('unauthorized, logging out ...') auth.logout() router.replace('/login') return Promise.reject(error) )
If the response returns and error and it’s 401, call auth.logout(). The user will then get re-directed to the login page.
Server side check
Just to ensure our auth is working, let’s create a simple express server to test it. Create folder named server and add a file named app.js. You will need to install express, express-jwt and cors. Cors is needed since we are going to run the express server on a different port.
$ yarn add express express-jwt cors --dev
OR
$ npm install express express-jwt cors --save --dev
I added the dev flag on the above statement to ensure these are development only dependencies. Add the following code to the server/app.js file:
var express = require('express') var app = express() var cors = require('cors') var jwt = require('express-jwt')
var jwtCheck = jwt( secret: 'YOUR_CLIENT_SECRECT', audience: 'YOUR_CLIENT_ID' )
app.use(cors())
// check security for anything under the secured route app.use('/secured', jwtCheck)
// open call app.get('/ping', function(req, res) res.send("All good. You don't need to be authenticated to call this"); )
// secured call app.get('/secured/ping', function(req, res) res.status(200).send("All good. You only get this message if you're authenticated"); )
app.listen(3000, function () console.log('Example app listening on port 3000!') )
Here I created a simple express server that has 2 routes. The /ping route is un-secured and can be called by anyone. Any path under /secured will get processed thru the jwtCheck function and a valid token must be sent in the header of the request. So if I call /secured/ping I will need to provide a valid token to get a response.
You will need to supply the jwtCheck function 2 variables: secret and audience. The audience is your client id from your client dashboard in Auth0 and the secret is the client secret from the same screen. For a more complete server backend example, check out the Auth0 express example repo here.
Back in the client side of our app, let’s make the final adjustments to test our app. In the main.js file, add the following line to set the baseUrl for axios.
axios.defaults.baseURL = 'http://localhost:3000'
Then in home.vue add a button to call the secured api:
<button type="button" class="button" v-on:click="testSecured()">Test API - Secured</button>
methods: testSecured: function () console.log('sending secured test call to api ...') axios.get('/secured/ping').then((response) => console.log(response) , (response) => console.log(response) )
Run the app and start the node server [ node server/app.js ], login and test to make sure you can make authenticated calls. The button will log the response to the console:
example secured api call
Conclusion
Now that we have secured we can take the next steps to building out the rest of our screens and functionality. In my next post I will cover setting up vuex and using it to store the user profile data. I will also use to manage the state of our projects page.
0 notes
Link
Calendars are an important part of our lives. In today’s world, people mostly use the web or mobile calendars. They can be found everywhere, including various software: booking apps, travel software, project management, admin panels, etc. Users may need calendars on websites for several reasons. The user may need to pick a date from the calendar to fill up a form or provide a date while delivering any information. Undoubtedly, this component can be called critical for business applications. Just imagine how much your business can suffer due to a badly tuned and developed calendar. Thus, this component should be given special attention and meticulousness in development. In this article, we will look at criteria for a good calendar in web applications. Also, we will show you the best libraries in different frameworks for building your own solutions based on them. Qualities of a good calendar for web apps We have picked the criteria for a good calendar from our previous article on date-pickers. Obviously, we can adapt these to calendar plugins. We divided our evaluation criteria into 4 blocks. Documentation. It is vital for whatever you’re using to be well-documented in order to learn how to build or reconstruct it. The product with no or lacking documentation does not have a right to exist. Customization. A great library should come with options that can be updated to add or remove certain functionality. This especially applies to open-source software. Compatibility. Who wants to visit a site with a datepicker that only works in recent versions of Chrome and Webkit browsers? Many business apps still work in legacy browsers. User Experience. Ask yourself whether the plugin will be convenient for the needs of your user? Does it fit your product style? The looks and quality of the docs are not that important compared to how the library will actually deal with your task. Top calendar libraries We have included various calendar libraries based on React, Angular, Vue, Bootstrap or jQuery. Some of them are more developed, some are easier to customize. Hope this catalog will help you in your work. Fullcalendar.io GitHub stars: 9400 Price and License: MIT Website/Demo: https://fullcalendar.io/ Github: https://github.com/fullcalendar/fullcalendar Type of installation: NPM, Yarn Frameworks: React, Vue, Angular This is a good choice for those who know what they want. There are no detailed step-by-step guides that describe what to do to get the goal. Only a brief Getting Started Guide and Documentation Page. Lightweight. The library is easily customizable and has many different components. The website, demos, and documentation give the impression of a mature product, which you’re not scared to use. With this, you can plan resources and mark events. Timeline view and various themes are also there. A good asset of this library is the documentation for developing in React, Vue, and Angular. Tui calendar GitHub stars: 7328 Price and License: MIT Website/Demo: http://ui.toast.com/tui-calendar Github: https://github.com/nhn/tui.calendar Type of installation: Via package managers or CDN Frameworks: React, Vue, Angular wrappers Tui is a part of a TUI library. It is built on top or jquery with options of using React, Angular and Vue wrappers. The calendar supports various view types: daily, weekly, monthly(6 weeks, 2 weeks, 3 weeks) and efficient management of milestone and task schedules. You can change the first day of the week, customize the date and schedule information UI(including a header and a footer of grid cell). The product has full documentation and can be installed via package managers of Content Delivery Network. CLNDR GitHub stars: 2760 Price and License: MIT Website/Demo: http://kylestetz.github.io/CLNDR/ Github: https://github.com/kylestetz/CLNDR Type of installation: Via package managers or CDN Frameworks: React, Vue, Angular wrappers CLNDR.js is a jQuery calendar plugin that, unlike most calendar plugins, doesn’t generate markup. Instead, you provide an Underscore.js HTML template, and in return, CLNDR gives you a wealth of data to use within it. HTML templates are well-suited to this task because they allow us the flexibility to specify where we want the data to go in our markup. CLNDR takes your template and injects some data into it. The data contains everything you need to create a calendar. Kendo UI Scheduler GitHub stars: 2160 Price and License: Apache License, $899 – $2199 Website/Demo: https://demos.telerik.com/kendo-ui/scheduler/index Github: – Type of installation: package managers Frameworks: React, Angular, Vue, jQuery Kendo UI is a big and advanced JavaScript framework. It contains tons of widgets and tools. Maybe it’s not a good idea to use its Scheduler Widget if you’re not interested in other components. The Kendo UI documentation is well written, and you can check out a bunch of Scheduler demos supplemented with code examples. Regarding the coding, it won’t take much time to build a basic scheduler and add some features to it. The default view is a little bit plain, but it’s easy to change that. React big calendar GitHub stars: 3254 Price and License: MIT Website/Demo: http://intljusticemission.github.io/react-big-calendar/examples/index.html Github: https://github.com/intljusticemission/react-big-calendar Type of installation: package managers Frameworks: React React big calendar is an event calendar component built for React. It is made for modern browsers (read: IE10+) and uses flexbox over the classic tables-ception approach. React big calendar includes two options for handling the date formatting and culture localization, depending on your preference of DateTime libraries. You can use either the Moment.js or Globalize.js localizers. Out of the box, you can include the compiled CSS files and be up and running. But, sometimes, you may want to style Big Calendar to match your application styling. For this reason, SASS files are included with Big Calendar. SASS implementation provides a file containing color and sizing variables that you can update to fit your application. Mobiscroll responsive calendar GitHub stars: – Price and License: free, $95, $595 Website/Demo: https://mobiscroll.com/responsive-calendar Github: – Type of installation: copy and paste script Frameworks: Angular, Ionic, React, jQuery, plain JS Mobiscroll calendar is a multiframework responsive calendar, which can work in mobile, web and tablet devices. Together with Single and Multiple selection types, users are able to select not just days one by one, but full weeks as well. It also enables users to easily change years and months without consecutive swiping. Mobiscroll helps users visualize two to three months in a row by displaying multiple months. It can provide helpful information in the form of text in day cells. With Mobiscroll you can highlight dates that have a specific meaning to the users. Additionally, you might use icons and text to give it meaning. The product supports localization and multilingual apps. It provides a UI with the correct culture settings. RTL availability also included. Syncfusion react calendar GitHub stars: – Price and License: $2495 – $4995 for all components Website/Demo: https://www.syncfusion.com/react-ui-components/react-calendar Github: – Type of installation: copy and paste script Frameworks: Angular, Blazor, plain JS, Vue, React The Syncfusion calendar is a component to display the date and days of the week. It provides the month, year, and decade view options to quickly navigate to the desired date. It supports minimum dates, maximum dates and disabled dates to restrict the date selection. The product is lightweight and easily configurable. You can choose across four different themes, including Material design. Apart from the standard, built-in theme, the Calendar component provides complete control over its appearance, allowing you to customize the style to suit your application. Angular calendar GitHub stars: 1662 Price and License: MIT Website/Demo: https://mattlewis92.github.io/angular-calendar/#/kitchen-sink Github: https://github.com/mattlewis92/angular-calendar Type of installation: package manager Frameworks: Angular The product is a calendar component for Angular 6.0+ that can display events on a month, week or day view. The template is highly customizable. You can build your own components instead of those not meeting your project specs. Please note that this library is not optimized for mobile. You will need to do it yourself. Bootstrap calendar GitHub stars: 2867 Price and License: MIT Website/Demo: http://bootstrap-calendar.eivissapp.com/ Github: https://github.com/Serhioromano/bootstrap-calendar Type of installation: package manager Frameworks: Bootstrap Full feature calendar based on the most popular HTML framework Twitter Bootstrap. This product is reusable. It means that there is no UI in this calendar. All buttons to switch view or load events are done separately. You will end up with your own unique calendar design. It is also template based – all views including year, month, week or day are based on templates. You can easily change the looks or style, even add a new custom view. If you use this product, it will be easy to adjust and style your calendar with LESS variables file. It uses AJAX to feed calendar with events. You provide URL and just return by this URL JSON list of events. Language files are connected separately with i18n. You can easily translate the calendar into your language. Holidays are also displayed on the calendar according to your language. Vcalendar GitHub stars: 1316 Price and License: MIT Website/Demo: https://vcalendar.io/ Github: https://github.com/nathanreyes/v-calendar Type of installation: package manager Frameworks: Vue V-Calendar is a clean and lightweight plugin for displaying simple, attributed calendars in Vue.js. It uses attributes to decorate the calendar with various visual indicators including highlighted date regions, dots, bars, content styles and popovers for simple tooltips and even custom slot content. Any single attribute may contain one object of each type and can be displayed for single dates, date ranges and even complex date patterns like every other Friday, the 15th of every month or the last Friday of every other month. Dhtmlx calendar GitHub stars: – Price and License: from $599 Website/Demo: https://dhtmlx.com/docs/products/dhtmlxCalendar/ Github: – Type of installation: package manager Frameworks: Vue, Angular, React This is quite a good choice if a calendar is all you want. There is an example of integration with Google maps, so you can extend the basic functionality if needed. The documentation page contains a set of guides that may be useful for beginners. The bunch of containers needed to make this scheduler work may confuse you from the start, but the overall coding process is quite obvious. The product has the following features: Cross-browser compatibility IE11+ support Full control with JavaScript API Ability to set inactive dates Configurable first day of the week Built-in multilingual support 12-hour and 24-hour time format 3 views: calendar, month, year This is quite a good choice if you want to build an enterprise product. The company has good support and flexibility in prices. Recap and conclusion We had a look at both basic and more advanced calendars. If you want a simple solution without support, but still easily customizable, then choose one of the free options. Considering more complex products, we presented paid solutions with good support quality. About Flatlogic At Flatlogic we develop admin dashboard templates and React Native templates. We are listed among Top 20 Web Development companies from Belarus and Lithuania. During the last 6 years, we have successfully completed more than 30 big projects for small startups and large enterprises. As a team, we always have a deep desire to help our clients. You might also like these articles: Originally published at flatlogic.com — React, Angular, Vue, Bootstrap & React Native templates and themes. Text source: Top Javascript Calendar Plugins
0 notes
Text
Filtering Lists Dynamically With Vue on the Server Side is Easier Than You’d Think
I recently attended the ARTIFACT conference in Austin, TX, and was inspired by a few talks about accessibility through the lens of site performance. It became clear to me that there is this tendency to rely on big JavaScript frameworks to handle the work — like React, Vue, and Angular — but that can be overkill in some cases. That is, negatively affecting site performance, and thus accessibility. At the same time, these frameworks can make development easier and more efficient for developers. My big takeaway from the conference was to see how a fast, performant experience can be balanced with my own development process.
This was on my mind as I was building a list-filtering feature on a project a few days after the conference. Pretty standard stuff: I needed a list of posts and some category filtering. I was using CraftCMS for front-end routes and templating as well as some Vue components here and there for some added JavaScript juiciness. Not a full-on “single page app” but more like a sprinkle of Vue.
The typical way one might approach this is to:
render the page with an empty div using Craft/Twig
mount a Vue component to that div
make an Ajax call from the Vue component to an API to gather the posts as JSON
render the posts and tie in the filtering.
Since the posts are held as an array within Vue, dynamic list rendering is a pretty cut and dry task.
Simple. Done, right? Well… that extra Ajax request means the user is presented with no content on the initial load depending on the user’s network, which might take some time. We could add a loading indicator, but maybe we can do better?
Preferably, the posts are rendered on the initial page request from the CMS.
But how do we get the static HTML “hooked up” with Vue for the filtering?
After taking a step back to rethink the problem, I realized I could use v-if directives to achieve the same thing with some inline JavaScript from Twig (“in the loop”). Below, I’ll show how I went about it.
My original project used CraftCMS, but I’m going to do the demos below in WordPress. This is just a concept. It can be applied to CraftCMS/Twig or any other CMS/templating engine combo.
First we need a filtering UI. This will likely go above the start of the loop in an archive template.
<?php $terms = get_terms( [ 'taxonomy' => 'post_tag', // I used tags in this example, but any taxonomy would do 'hide_empty' => true, 'fields' => 'names' ] ); if(!empty($terms)): ?> <div> Filter: <ul class="filters"> <li class="filters__item"><button class="filters__button" :class="{'filters__button--active': tag === ''}" @click="tag = ''">All</button></li> <?php foreach($terms as $term): ?> <li class="filters__item"> <button class="filters__button" :class="{'filters__button--active': tag === '<?php echo $term; ?>'}" @click="tag = '<?php echo $term; ?>'"><?php echo $term; ?></button> </li> <?php endforeach; ?> </ul> <p aria-live="polite">Showing posts tagged .</p> </div> <?php endif; ?>
Following along with the code, we get some tags from WordPress with get_terms() and output them in a foreach loop. You’ll notice the button for each tag has some Vue directives we’ll use later.
We have our loop!
<div class="posts"> <?php // Start the Loop. while ( have_posts() ) : the_post(); <article id="post-<?php the_ID(); ?>" <?php post_class(); ?> v-if='<?php echo json_encode(wp_get_post_tags(get_the_ID(), ['fields' => 'names'])); ?>.includes(tag) || tag === ""' > <header class="entry-header"> <h2><?php the_title(); ?></h2> </header> <div class="entry-content"> <?php the_excerpt(); ?> </div> </article> // End the loop. endwhile; ?> </div>
This is a pretty standard WordPress loop for posts. You’ll notice some Vue directives that make use of PHP outputting CMS content.
Aside from some styling, all that’s left is the Vue “app.” Are you ready for it? Here it is:
new Vue({ el: '#filterablePosts', data: { 'tag': '' } });
Yes, really, that’s all that’s needed in the JavaScript file to get this to work!
So, what’s going on here?
Well, instead of some JSON array of posts that gets fed into Vue, we output the posts on the initial page load with WordPress. The trick is to use PHP to output what’s needed in the Vue directives: v-if and :class.
What’s happening on the filter buttons is an onclick event handler (@click) that sets the Vue variable “tag” to the value of the WordPress post tag.
@click="tag = '<?php echo $term; ?>'"
Also, if that Vue variable equals the value of the button (in the :class directive), it adds an active class for the button. This is just for styling.
:class="{'filters__button--active': tag === '<?php echo $term; ?>'}"
For the list of articles, we conditionally display them based on the value of the Vue “tag” variable:
v-if='<?php echo json_encode(wp_get_post_tags(get_the_ID(), ['fields' => 'names'])); ?>.includes(tag) || tag === ""'
The PHP function json_encode allows us to output an array of post tags as JavaScript, which means we can use .includes() to see if the Vue “tag” variable is in that array. We also want to show the article if no tag is selected.
Here it is put together using the Twenty Nineteen theme template archive.php as a base:
<?php get_header(); ?> <section id="primary" class="content-area"> <main id="main" class="site-main"> <?php if ( have_posts() ) : ?> <header class="page-header"> <?php the_archive_title( '<h1 class="page-title">', '</h1>' ); ?> </header> <div class="postArchive" id="filterablePosts"> <?php $terms = get_terms( [ 'taxonomy' => 'post_tag', 'hide_empty' => true, 'fields' => 'names' ] ); if(!empty($terms)): ?> <div class="postArchive__filters"> Filter: <ul class="postArchive__filterList filters"> <li class="filters__item"><button class="filters__button" :class="{'filters__button--active': tag === ''}" @click="tag = ''" aria-controls="postArchive__posts">All</button></li> <?php foreach($terms as $term): ?> <li class="filters__item"> <button class="filters__button" :class="{'filters__button--active': tag === '<?php echo $term; ?>'}" @click="tag = '<?php echo $term; ?>'" aria-controls="postArchive__posts"><?php echo $term; ?></button> </li> <?php endforeach; ?> </ul> <p aria-live="polite">Showing posts tagged .</p> </div> <?php endif; ?> <div class="postArchive__posts"> <?php // Start the Loop. while ( have_posts() ) : the_post(); ?> <article id="post-<?php the_ID(); ?>" <?php post_class(); ?> v-if='<?php echo json_encode(wp_get_post_tags(get_the_ID(), ['fields' => 'names'])); ?>.includes(tag) || tag === ""' > <header class="entry-header"> <h2><?php the_title(); ?></h2> </header> <div class="entry-content"> <?php the_excerpt(); ?> </div> </article> <?php endwhile; // End the loop. ?> </div> </div> <?php // If no content, include the "No posts found" template. else : get_template_part( 'template-parts/content/content', 'none' ); endif; ?> </main> </section> <?php get_footer();
Here’s a working example on CodePen
See the Pen Dynamic List Filtering in Vue using Server-side data fetching by Dan Brellis (@danbrellis) on CodePen.
Bonus time!
You may have noticed that I added in an aria-live="polite" notifier below the filter button list to let assistive tech users know the content has changed.
<p aria-live="polite">Showing posts tagged .</p>
To get the postCount Vue variable, we add some extra JavaScript to our Vue component:
new Vue({ el: '#filterablePosts', data: { 'tag': '', 'postCount': '' }, methods: { getCount: function(){ let posts = this.$el.getElementsByTagName('article'); return posts.length; } }, beforeMount: function(){ this.postCount = this.getCount(); }, updated: function(){ this.postCount = this.getCount(); } });</p>
The new method getCount is used to select the article elements in our component div and return the length. Before the Vue component mounts we get the count to add to our new Vue postCount variable. Then, when the component updates after the user selects a tag, we get the count again and update our variable.
Filtering Lists Dynamically With Vue on the Server Side is Easier Than You’d Think published first on https://deskbysnafu.tumblr.com/
0 notes
Text
Laravel + Vue.js AdminPanel Generator
News / May 11, 2018
Laravel + Vue.js AdminPanel Generator
Laravel and Vue.js are often used together. With more tools on these technologies are released, here’s one of them – presenting to you Vue+Laravel Admin Panel Generator.
Disclaimer: I’m the founder and one of the developers of this tool, and also Laravel-only generator QuickAdminPanel, but the goal in this article is not only to present you the product, but explain what it generates, and how Vue + Laravel work together. Also, you will find an example project with source available on Github.
How does the generator work?
For those who prefer video, here’s a quick demo:
youtube
Now, let’s look at it with more details.
Step 1. You create your panel without coding, just adding menu items and fields.
Step 2. At any point, you can view the generated code, file by file.
Step 3. Then you download the code and install it – locally or on your remote server, with these commands:
composer install php artisan key:generate php artisan migrate --seed php artisan passport:install
Of course, your .env file should be configured at that point.
And then, on the front-end:
npm install npm run dev
Step 4. That’s it; you have your panel.
Step 5. The most important thing: you can change the code however you want, it’s pure Laravel+Vue, without our generator’s package as a dependency. That’s the main difference from packages like Voyager or Laravel Backpack (which are both excellent, by the way!).
What are we generating – structure of the project
After you download the project, you see something like this:
Generated Code: Back-end Laravel
Let’s first analyze the back-end Laravel part, which serves as API:
Here’s routes/api.php file:
Route::group(['prefix' => '/v1', 'middleware' => ['auth:api'], 'namespace' => 'Api\V1', 'as' => 'api.'], function () { Route::post('change-password', 'ChangePasswordController@changePassword')->name('auth.change_password'); Route::apiResource('roles', 'RolesController'); Route::apiResource('users', 'UsersController'); Route::apiResource('companies', 'CompaniesController'); Route::apiResource('employees', 'EmployeesController'); });
You can see apiResource for every CRUD, and also one separate POST for changing the password.
Controllers are namespaces under Api/V1, so here’s our app/Http/Controllers/Api/V1/CompaniesController.php:
namespace App\Http\Controllers\Api\V1; use App\Company; use App\Http\Controllers\Controller; use App\Http\Resources\Company as CompanyResource; use App\Http\Requests\Admin\StoreCompaniesRequest; use App\Http\Requests\Admin\UpdateCompaniesRequest; use Illuminate\Http\Request; class CompaniesController extends Controller { public function index() { return new CompanyResource(Company::with([])->get()); } public function show($id) { $company = Company::with([])->findOrFail($id); return new CompanyResource($company); } public function store(StoreCompaniesRequest $request) { $company = Company::create($request->all()); return (new CompanyResource($company)) ->response() ->setStatusCode(201); } public function update(UpdateCompaniesRequest $request, $id) { $company = Company::findOrFail($id); $company->update($request->all()); return (new CompanyResource($company)) ->response() ->setStatusCode(202); } public function destroy($id) { $company = Company::findOrFail($id); $company->delete(); return response(null, 204); } }
We have a typical resourceful Controller, with one exception – Resources classes, which have been available since Laravel 5.5.
In our case, every resource is a simple conversion to an array, here’s a file app/Http/Resources/Company.php
namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class Company extends JsonResource { /** * Transform the resource into an array. * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return parent::toArray($request); } }
But you can extend it, adding your logic on top – see more examples here and here.
Finally, Laravel Passport protects all the routes – when installing the project, you need to run this:
php artisan passport:install
As an overall back-end result, every Controller is responsible for that specific CRUD operations called to the API, from Vue.js front-end.
Generated Code: Front-end Vue.js
Now, let’s take a look at front-end part. The main file for this is resources/client/assets/js/app.js, where we initiate the Vue and some libraries:
// ... window.Vue = require('vue') Vue.prototype.$eventHub = new Vue() import router from './routes' import store from './store' import Datatable from 'vue2-datatable-component' import VueAWN from 'vue-awesome-notifications' import vSelect from 'vue-select' import datePicker from 'vue-bootstrap-datetimepicker' import VueSweetalert2 from 'vue-sweetalert2' import 'eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.css' Vue.use(Datatable) Vue.use(VueAWN, { position: 'top-right' }) Vue.use(datePicker) Vue.use(VueSweetalert2) Vue.component('back-buttton', require('./components/BackButton.vue')) Vue.component('bootstrap-alert', require('./components/Alert.vue')) Vue.component('event-hub', require('./components/EventHub.vue')) Vue.component('vue-button-spinner', require('./components/VueButtonSpinner.vue')) Vue.component('v-select', vSelect) moment.updateLocale(window.app_locale, { week: { dow: 1 } }) const app = new Vue({ data: { relationships: {}, dpconfigDate: { format: window.date_format_moment }, dpconfigTime: { format: window.time_format_moment }, dpconfigDatetime: { format: window.datetime_format_moment, sideBySide: true } }, router, store }).$mount('#app')
Next, every CRUD has its own set of components:
For showing the data table, we’re using vue2-datatable-component – here’s full code of resources/clients/assets/components/cruds/Companies/Index.vue:
<template> <section class="content-wrapper" style="min-height: 960px;"> <section class="content-header"> <h1>Companies</h1> </section> <section class="content"> <div class="row"> <div class="col-xs-12"> <div class="box"> <div class="box-header with-border"> <h3 class="box-title">List</h3> </div> <div class="box-body"> <div class="btn-group"> <router-link :to="{ name: xprops.route + '.create' }" class="btn btn-success btn-sm"> <i class="fa fa-plus"></i> Add new </router-link> <button type="button" class="btn btn-default btn-sm" @click="fetchData"> <i class="fa fa-refresh" :class="{'fa-spin': loading}"></i> Refresh </button> </div> </div> <div class="box-body"> <div class="row" v-if="loading"> <div class="col-xs-4 col-xs-offset-4"> <div class="alert text-center"> <i class="fa fa-spin fa-refresh"></i> Loading </div> </div> </div> <datatable v-if="!loading" :columns="columns" :data="data" :total="total" :query="query" :xprops="xprops" /> </div> </div> </div> </div> </section> </section> </template> <script> import { mapGetters, mapActions } from 'vuex' import DatatableActions from '../../dtmodules/DatatableActions' import DatatableSingle from '../../dtmodules/DatatableSingle' import DatatableList from '../../dtmodules/DatatableList' import DatatableCheckbox from '../../dtmodules/DatatableCheckbox' export default { data() { return { columns: [ { title: '#', field: 'id', sortable: true, colStyle: 'width: 50px;' }, { title: 'Name', field: 'name', sortable: true }, { title: 'Description', field: 'description', sortable: true }, { title: 'Actions', tdComp: DatatableActions, visible: true, thClass: 'text-right', tdClass: 'text-right', colStyle: 'width: 130px;' } ], query: { sort: 'id', order: 'desc' }, xprops: { module: 'CompaniesIndex', route: 'companies' } } }, created() { this.$root.relationships = this.relationships this.fetchData() }, destroyed() { this.resetState() }, computed: { ...mapGetters('CompaniesIndex', ['data', 'total', 'loading', 'relationships']), }, watch: { query: { handler(query) { this.setQuery(query) }, deep: true } }, methods: { ...mapActions('CompaniesIndex', ['fetchData', 'setQuery', 'resetState']), } } </script> <style scoped> </style>
Quite a lot of code, isn’t it? Of course, it could be more straightforward, but we tried to follow the official documentation and best practices, generating code for the cases that could be extended for bigger projects.
Next, we can take a look at Create.vue:
<template> <section class="content-wrapper" style="min-height: 960px;"> <section class="content-header"> <h1>Companies</h1> </section> <section class="content"> <div class="row"> <div class="col-xs-12"> <form @submit.prevent="submitForm"> <div class="box"> <div class="box-header with-border"> <h3 class="box-title">Create</h3> </div> <div class="box-body"> <back-buttton></back-buttton> </div> <bootstrap-alert /> <div class="box-body"> <div class="form-group"> <label for="name">Name</label> <input type="text" class="form-control" name="name" placeholder="Enter Name" :value="item.name" @input="updateName" > </div> <div class="form-group"> <label for="description">Description</label> <textarea rows="3" class="form-control" name="description" placeholder="Enter Description" :value="item.description" @input="updateDescription" > </textarea> </div> </div> <div class="box-footer"> <vue-button-spinner class="btn btn-primary btn-sm" :isLoading="loading" :disabled="loading" > Save </vue-button-spinner> </div> </div> </form> </div> </div> </section> </section> </template> <script> import { mapGetters, mapActions } from 'vuex' export default { data() { return { // Code... } }, computed: { ...mapGetters('CompaniesSingle', ['item', 'loading']) }, created() { // Code ... }, destroyed() { this.resetState() }, methods: { ...mapActions('CompaniesSingle', ['storeData', 'resetState', 'setName', 'setDescription']), updateName(e) { this.setName(e.target.value) }, updateDescription(e) { this.setDescription(e.target.value) }, submitForm() { this.storeData() .then(() => { this.$router.push({ name: 'companies.index' }) this.$eventHub.$emit('create-success') }) .catch((error) => { console.error(error) }) } } } </script> <style scoped> </style>
Edit and Show components for the CRUD are pretty similar, so won’t discuss them here.
In addition to that Vue code, there are many small details and helpers like Sweet Alert, Notifications, Datepickers, and setting/getting relationships data for the forms. I guess I will leave it for you to analyze.
Notice: The choice of Vue.js libraries is pretty subjective, and it was the most challenging part of the project – to choose the Vue libraries to trust. Ecosystem still lacks standards, or 100% trusted open-source – a lot of movement in the market, some libraries are better supported than others. So it’s always hard to guess, and the best libraries will probably change with time, or new ones will appear.
That’s the end of a quick overview of Vue+Laravel QuickAdminPanel, try it out here: https://vue.quickadminpanel.com
Finally, here’s the source of a demo-project with two CRUDs: Companies and Customers.
I hope our generator will not only save you time on writing code but also show you how Vue can work with Laravel. Our way of structuring this code is not the only way, and you can structure your code differently, but we tried our best to stick to standards.
via Laravel News https://ift.tt/2wzPFV6
0 notes
Text
Building a Simple Face Recognition App with Vue.js and Kairos
Face Detection and Recognition have become an increasingly popular topic these days. It’s a great advantage for a machine to know which user is in a picture. The applications of facial recognition in our world today are endless. From Face, iD unlock to identifying criminals on the run using real-time analysis of video feed.
What we’ll build
In this article, we’ll build a demo app with Kairos service in which users can upload different images of labeled faces and also try to recognize a person from an uploaded face
What is Kairos
Kairos is a leading AI engine provider which provides ‘Human Analytics’ features like Face Detection, Face Identification, Face Verification, etc. More features here. These features can be used to gather unique, real-time insights about users as they interact with your product.
Installation
The front-end part of the application is built with a Progressive Javascript Framework Vue.js and a node server on the backend which handles the interaction with Kairos API.
Dependencies
Before we begin, you need some things set up on your local machine
Node installed
Node Package Manager (npm ) installed
Once you confirm your installation, you can continue.
Step 1: Create a Kairos Account
Sign up for a free account.
After signing up, you’ll be redirected to the dashboard with your credentials
PS: Note your App ID and Key ( you’ll need them later )
Step 2: Set Up A Node Server
Initialize your node project and create a package.json file with:
npm init
Install necessary node modules/dependencies :
npm install fs express connect-multiparty kairos-api cors body-parser --save
fs - we need this to convert our image into a base64 mode for attachment express - we need this to enable our API routes connect-multiparty - needed to parse HTTP requests with content-type multipart/form-data kairos-api - Node SDK for Kairos cors - we need this to enable cors body-parser - we need this to attach the request body on express req object
Create an index.js file in your root directory and require the installed dependencies :
const fs = require('fs'); const cors = require('cors'); const express = require('express'); const Kairos = require('kairos-api'); const bodyParser = require('body-parser'); const multipart = require('connect-multiparty'); const app = express(); app.use(cors()); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); const multipartMiddleware = multipart(); [...]
Next, configure your Kairos client in the index.js file:
// API Configurations for KAIROS let kairo_client = new Kairos('APP_ID', 'APP_KEY');
Replace APP_ID and APP_KEY with the details from your dashboard
Add the route for uploading images to Kairos gallery. Let's call it /upload:
[...] app.post('/upload', multipartMiddleware, function(req, res) { // get base64 version of image and send that to Kairos for training let base64image = fs.readFileSync(req.files.image.path, 'base64'); var params = { image: base64image, subject_id: req.body.name, gallery_name: 'rekognize', }; console.log('sending to Kairos for training'); kairos_client.enroll(params).then(function(result) { // return status of upload return res.json({'status' : true }); }).catch(function(err) { // return status if upload return res.json({'status' : false}); }); }); [...]
Add the route for recognizing a person from an uploaded face. Let's call it /verify:
[...] app.post('/verify', multipartMiddleware, function(req, res) { // get base64 version of image and send that to Kairos for recognition let base64image = fs.readFileSync(req.files.image.path, 'base64'); var params = { image: base64image, gallery_name: 'rekognize', }; console.log('sending to Kairos for recognition'); kairos_client.recognize(params).then(function(result) { // return the response return res.json(result.body); }).catch(function(err) { // return status code as false return res.json({'status' : false}); }); });
Once the user makes a POST request to the /upload route, the route gets the image file from the HTTP Request, converts it to a base64 version and then uploads it to Kairos with the identifier for the image and the gallery you want the image to be in. You get a JSON Response telling you whether the upload was successful or not.
Also, when the user makes a POST request to the /verify route, the route gets the image file from the HTTP Request, converts it to a base64 version and then sends it to Kairos with the gallery name for it to check if there’s anyone with a similar face to the face being uploaded in the picture. Kairos then sends a JSON Response with the result of the operation, and we take further action on based on the response.
Step 3: Build the Frontend
To build the frontend, we would be using Vue.js as already mentioned earlier.
Install the Vue CLI :
npm install -g vue-cli
Create a simple Vue project using the Vue CLI tool installed earlier:
vue init simple facerecognizer
Inside the facerecognizer directory, create an index.html file and in the index.html file we have some basic forms that we need for the app to work.
Training
Firstly, we need a form that allows the user submit a picture of themselves to our node server and then from the server to kairos for training - for kairos to be able to recognize a face, they need to have some base images uploaded to a gallery which forms the training data for the prediction of faces for our application.
[...] <form enctype="multipart/form-data" @submit.prevent="onSubmit"> <div class="form-group"> <label for="">Name:</label> <input type="text" required class="form-control" placeholder="eg Ore" name="subject_name" v-model="model.name"> </div> <div class="form-group"> <label for="">File:</label> <input type="file" class="form-control" accept="image/*" name="image" v-on:change="upload($event.target.files)"> </div> <div class="form-group"> <button class="btn btn-primary" >Upload</button> </div> </form> [...]
We bind the upload form to an upload event handler. Once a user selects a file, there is a showPreview method called in the Vue instance below is invoked which shows a thumbnail preview of the image about to be uploaded to Kairos.
Now let's examine the Vue instance the upload form is linked to. We are going to build up our upload instance.
First, we specify element we want to bind the Vue Instance to and the data we want to render to the DOM:
[...] var upload = new Vue({ el: '#pills-upload', data: function() { return { model: { name: '', image: null, item: '' }, loading: '', uploadStatus: '', } }, [...]
Then, we define the methods on our Vue instance. For this instance, we have the upload, showPreview and onSubmit methods.
The upload method takes the image that was uploaded, resets the uploadStatus ( this is done so that when a user is performing multiple uploads, the status is cleared before each upload ) and then calls the showPreview method:
[...] methods: { upload: function(files) { this.model.image = files[0]; this.uploadStatus = ''; this.showPreview(files[0]); }, [...]
The showPreview method is responsible for displaying a preview of the uploaded image for the user to see how it looks
[...] showPreview: function(file) { var reader = new FileReader(); reader.onload = function (e) { document.getElementById("face_preview1").src= e.target.result; }; // read the image file as a data URL. reader.readAsDataURL(file); }, [...]
The onSubmit method is triggered when the upload button is clicked. It builds the form, populates it with data, sends a post request to the node server. When a response is received from the server, the uploadStatus is updated to let the user know if the image was successfully uploaded:
[...] onSubmit: function() { // Assemble form data const formData = new FormData() formData.append('image', this.model.image); formData.append('name', this.model.name); this.loading = "Uploading image....Please be patient." // Post to server axios.post('http://localhost:3128/upload', formData) .then(res => { // Post a status message this.loading = ''; if( res.status == true){ this.uploadStatus = 'Image has been uploaded successfully'; }else{ this.uploadStatus = 'there was an issue with the upload, try again'; } }) } } });
Recognition
Now we need to work on the recognition part of the app. Over here we have a form that facilitates the upload of the face picture to the server for recognition
<form enctype="multipart/form-data" @submit.prevent="onSubmit"> <div class="form-group"> <label for="">Upload Picture of Person to Recognise:</label> <input type="file" class="form-control" accept="image/*" name="image" v-on:change="upload($event.target.files)"> </div> <div class="form-group"> <button class="btn btn-primary" >Rekognize</button> <span class="fa fa-spin fa-spinner" id="verify_spinner" style="display:none;" aria-hidden="true"></span> </div> </form>
This is quite similar to the upload part; we bind the form to an event handler which makes the post request to the backend server that sends details to Kairos and gets JSON Response.
Now we examine the Vue instance the recognize form is linked to.
First, we specify the data we want to render to the DOM.
[...] var verify = new Vue({ el: '#pills-verify', data: function(){ return{ model: { image : null, }, loading: '', resultStatus: '', resultDetails: '', } }, [...]
Then, we define the methods on our Vue instance. For this instance, we have the upload,showPreview and onSubmit methods.
The upload method takes the image that was uploaded, clears the resultStatus and calls the showPreview method:
[...] methods: { upload: function(files) { this.model.image = files[0]; this.resultStatus = ''; this.showPreview(files[0]); }, [...]
The showPreview method is responsible for displaying a preview of the uploaded image for the user to see what is being sent for recognition:
[...] showPreview: function(file) { var reader = new FileReader(); reader.onload = function (e) { document.getElementById("face_preview2").src= e.target.result; }; // read the image file as a data URL. reader.readAsDataURL(file); }, [...]
The onSubmit method is triggered when the rekognize button is clicked. It builds a form with data from the instance and sends a post request to the /verify route on the node server.
[...] onSubmit: function() { // Assemble form data const formData = new FormData() formData.append('image', this.model.image); formData.append('name', this.model.name); this.loading = "Attempting to recognize you..please wait." [...]
When a response is returned from the server, we examine the response from the server and the resultStatus is updated with the name of the user if there are no errors.
[...] // Post to server axios.post('http://localhost:3128/verify', formData) .then(res => { // Post a status message saying the upload complete this.loading = ''; if( !res.data.Errors){ if(res.data.images[0].transaction.status != "success"){ this.resultStatus = 'don\'t know who you are! Try uploading a picture of yourself first in upload section'; }else{ this.resultStatus = 'What\'s good ' + res.data.images[0].transaction.subject_id + '! '; } this.resultDetails = res.data.images[0].transaction; }else{ this.resultStatus = 'don\'t know who you are! Try uploading a picture first in upload section'; } }) } } })
We all know it’s not every-time we Kairos will be able to successfully identify the face. In the JSON response, we check if there was an error i.e. if Kairos couldn’t find a matching face and we let the user know. If a matching face is successfully found, we send a welcome message.
Feel free to check out the source code here.
Conclusion
We have seen how to make a Simple Face Recognition App. The applications of this are quite numerous, you could add face authentication as one of the ways to authenticate your users, or you could also just use it to know who is interacting with your product to provide personalized experiences for your users.
Feel free to leverage the free account given to you by Kairos to give your #NextBillionUsers a great experience!
More Resources
Overlay Glasses/Masks on Avatars with Vue.js and Cloudinary
via Scotch.io http://ift.tt/2AKCcYC
0 notes