1.0.8¶
Here’s what’s new in Release 1.0.8 (14 July 2017):
Bug fixes
- Charts now save to notebooks properly, making it easier to share visualizations without having to re-run cells to view rendered output (#402).
- Data now loads correctly when running PixieDust in a plain Python notebook. The fix allows users to load data into a pandas DataFrame in a notebook when Spark is not present (#359).
- Visualizations for Google region maps are now updated to display two different maps in separate div elements. This update fixes an issue where multiple PixieDust renders for Google maps would target the same div and overwrite each other (#396).
- The GitHub org containing PixieDust changed its name. A redirect is in place, and all github.io links have now been updated to reflect the new org name (#393).
Enhancements
- An alpha release of PixieApps is now live and documented. PixieApps are inspired by the Angular.js framework, and provide the high-level building blocks for making data science experiments more repeatable and easier to run. Developers can use PixieApps to run interactive UI elements, directly from notebook cells (#287).
- The project has added a data browser for MongoDB. It comes as an out-of-the-box PixieApp. Because schemas in MongoDB are flexible, the PixieApp browser makes exploring Mongo collections more straightforward from within notebooks (#400).


org.jsmpp.session.connection.socket
Classes
ServerSocketConnection
ServerSocketConnectionFactory
SocketConnection
SocketConnectionFactory


For a brief moment I forgot this amazing 1975 Pontiac Firebird is a 1975 Pontiac Firebird
by Jason WeisbergerI found myself actually considering this Pontiac Firebird.
The 400ci L78 V8 reportedly was rebuilt to stock specs in 2015, and the car is said to have accumulated less than 500 miles since. The V8 was rated at 185 horsepower when new and is equipped with a Rochester four-barrel carburetor and a dual-snorkel air-cleaner housing. Components for the factory air conditioning have been removed, but the bracketry remains. The carburetor was adjusted in February 2019, and service in November 2019 included checking the fluids and changing the engine oil. Power is sent to the rear wheels through a TH350 three-speed automatic transmission that, per the seller, is a replacement component installed at the time of the engine rebuild.
I wonder if it rattles.


src/mutation.js
/**
* A change in a text document.
*
* This is an abstract class that does nothing.
* It should be subclasses and its methods overriden.
*/
export default class TextMutation {
/**
* Creates a new text mutation concerning the specified text element.
*
* @param {TextElement} element - The text element being mutated.
*/
constructor(element) {
// TODO: validate
/**
* The text element being mutated.
* @type {TextElement}
*/
this.element = element;
}
/**
* The start index at which this mutation takes place in the text document.
*
* If the mutation affects an existing range of text, this must be the start index (inclusive) of that range.
* If the mutation only adds new text, this must be the index at which that text will be inserted.
*
* @returns {integer} The index at which this mutation takes place in the text document.
*/
get start() {
return undefined;
}
/**
* The end index at which this mutation takes place in the text document.
*
* If the mutation affects an existing range of text, this must be the end index (exclusive) of that range.
* If the mutation only adds new text, this must be `undefined`.
*
* @returns {integer|undefined} The end index (exclusive) of the existing text range affected by this mutation, or `undefined` if the mutation only adds new text.
*/
get end() {
return undefined;
}
/**
* The positive or negative difference of the total length of the text document after the mutation is applied.
*
* * If the mutation adds 3 characters, the delta is 3.
* * If the mutation adds 5 characters and removes 7, the delta is -2.
*
* @returns {integer} The number of characters added to or removed from the document by this mutation.
*/
get delta() {
return 0;
}
/**
* Applies this mutation to the specified text.
*
* @param {string} text - The text to change.
* @returns {string} The changed text.
*/
apply(text) {
return text;
}
}


Oru Mexican Aparatha is an upcoming Indian Malayalam film directed by Tom Emmatty and written by Jude Anthany Joseph. The film stars Tovino Thomas, Roopesh Peethambaran, Neeraj Madhav and Sunil Sukhada in the lead roles.
For MoreBasheerinte Premalekahanam (English: Basheer's love letter) is a 2017 Malayalam movie directed by Aneesh Anwar. The film features Farhan Faasil and Sana Althaf in the lead roles. The movie, set in the 1980s, is a romantic comedy.
Vivek Anirudh, the young filmmaker is all set to can a time-travel movie to take viewers to unknown realms.Tovino Thomas will play the lead role and the female lead role will be handled by Aditi Ravi who is a new comer.The script is penned by Kiran K. S and Abhilash Kuttappan. Sajid Nasser is the cinematographer of the film.
Georgettan's Pooram is an upcoming 2016 Malayalam film directed by K. Biju, starring Dileep in lead role. The screenplay is written by Y. V. Rajesh based on a story by Biju. It is produced by Arun Gosh under the banner of Shivani Entertainments and Chandni Creations. Principal Photography began in October in Thrissur
The Great Father is an upcoming Indian Malayalam film directed by Haneef Adeni. It is produced by Prithviraj Sukumaran, Arya, Santhosh Sivan, and Shaji Nadesan under the banner of August Cinema. It stars Mammootty, Arya, Sneha and Shaam in the lead roles. The film was planned to release on 25 December 2016 on Christmas, but was postponed to 27 January 2017.
Ezra is an upcoming 2017 Indian Malayalam horror thriller film written and directed by Jay K, starring Prithviraj Sukumaran. Major filming locations were Fort Kochi and Sri Lanka. Principal photography began in late-June 2016. The film is scheduled for release in January 2017.
For more Click Here.Jomonte Suvisheshangal is an upcoming Indian Malayalam family drama film directed by Sathyan Anthikkad and written by Iqbal Kuttippuram. The film stars Dulquer Salmaan and Mukesh in the lead roles.Dulquer Salmaan does the role of Jomon, son of a business tycoon named Vincent (Mukesh) from Thrissur. Muthumani and Vinu Mohan are said to be playing Jomon's older sister and brother. The story revolves around this family and it also concentrates on the father-son relationship.
Munthirivallikal Thalirkkumbol (English: When the Grapevines Sprout) is an upcoming Indian Malayalam domestic drama film directed by Jibu Jacob and written by M. Sindhuraj, loosely based on the Malayalam short story Pranayopanishath by V. J. James. Produced and distributed by Weekend Blockbusters of Sophia Paul, the film stars Mohanlal and Meena, respectively as Panchayat secretary Ulahannan and his wife Annyamma. The soundtrack would feature songs composed by Bijibal and M. Jayachandran, and a film score by Bijibal. Sindhuraj obtained the right for adapting Pranayopanishath from James when it was first published in a Malayalam magazine in 2011. In 2015, he was approached by Paul for screenwriting a film for Weekend Blockbusters, planned with Mohanlal in the lead role. He suggested a plot idea based on the short story and began developing the screenplay that year, with Jacob hired to direct the film. Principal photography commenced on 15 July 2016 in Kozhikode, Kerala where over 80 percent of the film was shot. Additional portions were shot at various locations in Alappuzha and concluded filming at Shimla in October 2016. Munthirivallikal Thalirkkumbol was originally set for a Christmas opening, scheduled to be released on 22 December 2016 in India. But was delayed as the screening of Malayalam films were halted at the time due to an indefinite strike between the associations of theatres and producers in Kerala. The film is awaiting to re-schedule as soon as the strike is over.
Fukri is an upcoming 2017 Malayalam film written and directed by Siddique, starring Jayasurya in the lead role. It is produced by Siddique, Vaishak Rajan, and Jenso Jose under the banners of S Talkies and Vaishaka Cynyma. It is scheduled to release in December 2016.


_R is a programming language and free software environment for statistical computing and graphics supported by the R Foundation for Statistical Computing. The R language is widely used among statisticians and data miners for developing statistical software and data analysis. Polls, data mining surveys and studies of scholarly literature databases show substantial increases in popularity in recent years. As of November 2019, R ranks 16th in the TIOBE index, a measure of popularity of programming languages. (Wikipedia)*
Here are some common algorithms that can be applied to almost all data problems:
Please ensure to follow the points stated below if you would like to contribute:
.
or
_
to seperate terms, such as results.df
for a
data frame containing some results) and filenames (follow the convention
that has been followed for files under the directory your committing
to).


The Seattle Lilla Spelmanslag is a group of young musicians that play traditional Scandinavian music. The word “lilla” in Swedish means young while the word “spelman” means fiddler and “lag” is a guild or society.
Young people from age 8 to 18 come together to play, perform and enjoy folk music from Scandinavia within a community of young musicians.
Our goal is to provide an experience of the Nordic music traditions, and the culture around them. We support this in a tolerant, kind, respectful environment that recognizes the contribution that each musician makes to the whole. We
use performance as a vehicle for teaching poise, confidence and presence, while building musicianship, teamwork and leadership. The group has only three rules: smile, have fun and keep your bow moving.
The Seattle Lilla Spelmanslag is a performance group. Members perform for a variety of occasions including for dancing, concerts for community organizations like schools and churches and we march in parades. We perform at festivals,
such as Yulefest at the Nordic Heritage Museum, Skandia Folkdance Society’s Midsommarfest, and of course at the Northwest Folklife Festival. To see a list of our past performances, click here.
"This group has given my daughter performance opportunities that are different from what she gets in her normal orchestra. The Lilla Lag has allowed her to grow in ways that she wants to grow."
The Seattle Lilla Spelmanslag is now a nonprofit organization! You may donate by personal check, or by credit or debit card. Donations to the Seattle Lilla Spelmanslag are tax-deductible.
Martha is passionate about Nordic fiddling and about working with children. She believes that playing music should be both fun and accessible. When not working with the Seattle Lilla Spelmanslag, Martha can be found performing,
dancing, working in her garden, or practicing aikido.


NOT a commercial site! All data comes from Yahoo Finance and otherinternet resources. NO guarantee for accuracy. Main idea for the site is to explore and experiment with AI and ML technology and their application in index forecasting and stock portfolio selection.BECAUTIOUS with the data presented hereafter。THANKS！
SP500 Forecast by RNN
The Chart below shows SP500 index forecast by a simple RNN model, predicting index values for next five trading days at 9:30 PM (US/Eastern time) each day according the closing index values of thatday and preceding 29 days. （Blue line is actual index values. Orange line is predicted values after last trading days closing. Green line is forecast values for next five trading days.)
subtitle2
Next table shows the forecast values for next five days and their probabilities -the most likely instances are adopted in the chart above. The model will generate a probability distribution for the index to be forecast and choose the most likely instances as its forecast values. The top 2 forecast values and their probabilities would be helpful.
Note:
- The forecast value is actually a range around the number instead of a precise value. And the probability is the probability of the value falling into the range. Giving out a precise value is for simplicity reason and easiness to demo in chart!
- The probability is a result of the model's algorithm, not the probability of actual occurrence. It is more meaningful when compared to itself than considering the absolute value.
- Forecast value for next day is better than the rest, if any good.
The site is set for personal interest. Not used for business and investment decisions. the user hold the liability of his or her own decision whether or not using the result displayed in this site. Any idea and suggestion please mail to<EMAIL_ADDRESS>。
THANKS!


"{{quote.description}}"
Author:{{quote.author}}
This quote was created {{quote.publishDate | dateCount}} days ago


It’s the World vs. Facebook, all over again. Recently, the U.S. House Committee on Financial Services is calling on Facebook to halt its…
dan.17-Jul-19 09:25 PM
wow yup
and they didnt embellish on it beyond that did they(edited)
whats weird is why theyre ok with it... theres a lot of things htey cant enforce but are illegal
actionslacks17-Jul-19 09:27 PM
the atomic dex exemption...
polycryptoblog17-Jul-19 09:27 PM
What exactly is illegal about it?
dan.17-Jul-19 09:28 PM
nothing, just meant theres things elsewhere that are illegal but not really enforcable(edited)
actionslacks17-Jul-19 09:29 PM
If it gets too big they can simply have it removed from google play and the apple store though
muh terrorism
dan.17-Jul-19 09:29 PM
thats a good point
actionslacks17-Jul-19 09:31 PM
they cant come after the individual freedoms, yet. so we have a window of opportunity here
2
dan.17-Jul-19 09:33 PM
lets say the government has reasons for not mentioning... lets say the mass media has their reasons for not covering it... the only people talking about the repercussions of DEX/privacy coins are us crypto plebs ourselves. It could make a good article somewhere cause.... its interesting as hell.
1
haha yes
actionslacks17-Jul-19 09:37 PM
pretty cool to see all the pirate nodes popping up around my area. yesss, muahahaha, it's growing.
dan.17-Jul-19 09:38 PM
i noticed that too.... i live almost in the middle of no where too
Tek17-Jul-19 09:52 PM
I just bought in
call whalero
actionslacks17-Jul-19 09:53 PM
sold your dash bags eh?
Tek17-Jul-19 09:53 PM
selling dash
nah
dash is more secure than bitcoin now
and usable with low fees and instant transactions
selling dash
i don't sell crypto I buy crypto
buy buy buy buy
i did sell all my KMD after the hack
still havn't bought everything back yet
alts just look so juicy right ow
dukeleto17-Jul-19 09:57 PM
that is why they will go down even more
Tek17-Jul-19 09:57 PM
doubt.
dukeleto17-Jul-19 09:58 PM
Praying for alt season still?
Tek17-Jul-19 09:58 PM
the ones that are supposed to die
will go down
more
i don't pray for materialistic gains my dude
I couldn't care less bout money.
actionslacks17-Jul-19 10:00 PM
I pray for metaphysical gains
Tek17-Jul-19 10:00 PM
good
i can't decide if i want EOS in my folio
actionslacks17-Jul-19 10:03 PM
I think EOS is supposed to die
Tek17-Jul-19 10:04 PM
maybe that's why I'm hesitatin
actionslacks17-Jul-19 10:06 PM
I think there is gonna be some reshuffling once binance drops the hammer. I'm waiting for that to get back in. I did sell my non kmd alt bag at the top though.
Congressman Davidson asks Meltem Demirors about shitcoins. Visit https://ledgerstatus.com for a great podcast. And follow this channel. The full hearing can ...
 Meltem Demirors is Chief Strate...
that's ironic considering that Bitcoin only current use case is pyramid scheme
CryptoNinjaa18-Jul-19 09:37 AM
And for Dpow purpose
2
hyperDEX18-Jul-19 09:44 AM
nice little 50k sell wall appearing again. Need whalebro to eat that
Sanyadurnov18-Jul-19 10:17 AM
@hyperDEX someone accumulating coins.
wolfgang18-Jul-19 10:36 AM
so ahhhh when $100 KMD?
Markus18-Jul-19 10:47 AM
maybe never
1
1
1
yorklab18-Jul-19 10:49 AM
Lots of large sell orders. Seems strange to see that now.
Sanyadurnov18-Jul-19 10:49 AM
Who know the future ? When kmd 2$ ?
Markus18-Jul-19 10:50 AM
Cause kmd market seem to be pretty manipulated by a few selected ppl


Class tag is used in a similar fashion as ID tag but rather than applying for individual tags they can be formed as a group
Hello World!!


Summary
Inventory Health
Demand
Seller
Buyer
Product
Brand
CBT
Health
more
$40.34M
GMV
+13.23%
GMV YoY
$5.12M
Revenue
2.17M
Transactions
$32.01
ASP
$2.21M
Subsidy
$5.11M
Deals GMV
Inventory
more
2.34M
Total Listings
Demand
more
54.1M
Searches
Top KW
Top Movers
Seasonal KW
not available
not available
Seller
more
231.4K
Sellers
Buyer
more
Coming Soon
38.2%
Male
42.5%
Female
51.1%
Phone
42.2%
Computer
35.1%
Shopping Enthusiast
35.2%
Treasure Hunter
Product
more
34.1%
Product ID Coverage
Top Product
Top Movers
not available
not available
Brand
more
34.1%
Branded GMV Penetration
Top Brand
Top Movers
not available
Health Content
Inventory Content
Demand Content
Seller Content
Buyer Content
Product Content
Brand Content
CBT Content


{% include header.html %}
Feature List
Light Transport
- Unidirectional Path Tracing
- Stochastic Progressive Photon Mapping
- Light Tracing
Rendering Modes
- Single-pass rendering
- Multi-pass rendering
- Progressive rendering
- Time-limited progressive rendering
- Interactive rendering
- Scene editing during interactive rendering
- Spectral rendering (31 bands in 400-700 nm)
- RGB rendering
Subsurface Scattering
- Raytraced Subsurface Scattering
- Animation-friendly
- No precomputation or storage
- Available in interactive rendering
- Exposed to OSL shaders
- Support for SSS sets
Subsurface Scattering Profiles
- Gaussian
- Standard Dipole
- Better Dipole
- Directional Dipole
- Normalized Diffusion
- Random Walk (path traced)
Reflection Models
- Lambertian BRDF (purely diffuse)
- Specular BRDF (perfect mirror)
- Specular BSDF (clear transparency)
- Diffuse BTDF (diffuse transparency)
- Oren-Nayar Microfacet BRDF
- Ward Microfacet BRDF
- Blinn Microfacet BRDF
- GGX Microfacet BRDF
- Disney's principled, layered BRDF
- Anisotropic Ashikhmin-Shirley BRDF
- Kelemen BRDF
- Glossy BRDF
- Physically-based metal BRDF
- Physically-based plastic BRDF
- Physically-based glass BSDF
- Sheen BRDF
- Arbitrary mixtures of BRDFs
- Energy compensation in microfacet models
Volume Rendering
- Single scattering
- Multiple scattering
- Homogeneous media
- Isotropic phase function
- Henyey-Greenstein phase function
Non-Photorealistic Rendering
- Toon shading (OSL shader)
- Ray traced contours (OSL shader)
Camera Models
- Pinhole camera
- Orthographic camera
- Spherical camera
- Fisheye lens camera with multiple projections
- Thin lens camera (depth of field)
- Polygonal diaphragm shapes
- Image-based diaphragm shapes
- Camera shift
Light Source Models
- Point light
- Spot light
- Gobos
- Directional/parallel light
- Mesh light
- Purely diffuse emission profile
- Cone-shaped emission profile
- Image-based lighting
- Latitude-longitude environment maps
- Mirror-ball environment maps
- Preetham physically-based day sky
- Hosek & Wilkie physically-based day sky
- Physically-based sun
- Environment transforms
Visualization Tools
- Low-overhead capture of light paths
- Interactive exploration of light paths
- Efficient binary light paths file format
- False colors mapping
- MATLAB's Jet color map
- Perceptually uniform color maps
- Relative luminance (Rec. 709) isolines
Motion Blur
- Camera motion blur
- Transformation motion blur
- Deformation motion blur
- Arbitrarily number of motion steps
- Shutter opening/closing curves
Production Features
- Open Shading Language (OSL) support
- OSL shader library
- OSL implementation of Maya shading nodes
- On-the-fly compilation of OSL shaders
- OpenColorIO support
- Built-in BCD denoiser
- Command line tool for offline denoising
- Disney's SeExpr expressions
- AOVs
- Cryptomatte support
- Adaptive sampling
- Paintable mask-based sampling
- Hierarchical instancing
- Per-instance visibility flags
- Alpha mapping
- Matte support
- Automatic color space conversions
- Fixed or varying sampling patterns per frame
- Ray differentials
- Ray Bias
- Light Near Start
- Low Light Threshold
- Max Ray Intensity
- Roughness Clamping
- Bounce limits per scattering types
- Automatic tracking of indices of refraction
- Nested dielectrics
- Packed, single-file scenes for easy transport
- Render stamps
- Render checkpointing (resumable renders)
- Search paths for external assets
- Dozens of diagnostic modes
- Pausable rendering
Interoperability
- Windows, Linux and macOS (64-bit)
- OBJ geometry files
- OpenEXR, TIFF, HDR, PNG, JPEG, PSD...
- Open Shading Language support
- OpenColorIO support
- Native Image Engine's Gaffer integration
- Native Autodesk® 3ds Max® 2017+ plugin
- Native Autodesk® Maya® 2018+ plugin
- Blender 2.79 and Blender 2.80+ plugins
- Substance Painter-compatible OSL shader
Hackability
- 100% open source, MIT license
- Exceptionally clean, fully reviewed code
- Full featured C++ API
- Full featured Python 2.x/3.x API
- Full extensibility via external C++ plugins
- Embedded Python scripting
- More than 1500 built-in unit tests
- Hundreds of built-in performance tests
- Rich, automatic functional test suite
Performance
- Multithreaded, scalable
- SSE / SSE2 / SSE 4.2 vectorization
- Memory-bounded texture cache
- Filter Importance Sampling
- Multiple Importance Sampling
- Efficient handling of alpha maps
- Advanced many-light sampling
- Experimental Intel® Embree backend
Tools
- Advanced graphical tool for scene inspection and rendering
- Command line renderer
- Command line denoiser
- Dropbox-based render farm tools
- OSL compiler and tools
Infrastructure
- Git for source control
- GitHub for repositories hosting, issue tracking, wikis
- CMake build system
- Continuous integration (Travis CI, AppVeyor)
- Discord server
- Discourse forum
- appleseedhq.net email addresses
{% include footer.html %}


While going through the tasks on how to clean the data from Wikipedia I realised,
that after the completion of step two there where people missing in the list.
I couldn't wrap my head around how that could happen since I'm not too familiar with backreference in regex.
But since I had some time yesterday and a great amount of fun in the course over all,
I took a closer look at the regex and found the thing, that let people from the list go missing.
Since the regex is always referencing to the two stars at the beginnig of the lines that don't have a seperate date -
since two or more people died on that specific day - it starts overwriting lines when it gets executed the second
(or third I can't remember correctly right now) time. I couldn't solve the problem with regex alone, so I tried a solution in
python which looks like this and which works as substitution to steps 2 and 3 in the cleaning of the data from Wikipedia.
(Since I'm using a code prettifier, the &ndash gets displayed as the actual single character
not the string of characters as I had it in the original code. I also prepared the data so that &ndash == –.)
import re
import sys
s = sys.stdin
so = sys.stdout
xs = s.readlines()
xss = ' '
xsss = xss.join(xs)
y = re.findall("\* \[+\w+ \d+\]+\n", xsss)
d = 0
clean = ''
for i in range(len(xs)):
if '**' not in xs[i] and '–' not in xs[i]:
if i == 0:
d = 0
else:
d += 1
elif "**" in xs[i]:
x = re.sub("\*{2} ", y[d].strip('\n') + ' – ', xs[i])
clean += x
else:
clean += xs[i]
so.write(clean)


--- layout: page status: publish published: true title: Location author: display_name: Jessie Pechmann login: jpechmann email<EMAIL_ADDRESS>url: '' author_login: jpechmann author_email<EMAIL_ADDRESS>wordpress_id: 2857 wordpress_url: http://gis.utah.gov/?page_id=2857 date: '2011-10-21 14:47:35 -0600' date_gmt: '2011-10-21 20:47:35 -0600' categories: [] tags: - SDE - sgid - Data - utah - gis - map - mapping - dataset - download - agrc - layer - shapefile - geodatabase - metadata - shp - gdb - kml - lyr - digital - geographic - information - database - state - statewide - vector - overview - category - services - daas - arcgis ---
| Product Name | Type | Steward(s) | Description | |
|---|---|---|---|---|
| click a product name for more information and download links | ||||
| Address Points | GIS Data Layer | AGRC, Local Governments | Address point locations in Utah. This dataset is a work in progress and some counties are more complete than others. | |
| Address System Quadrants | GIS Data Layer | AGRC, Local Governments | Polygons that depict the four quadrants of each address system in Utah. | |
| Address Locators | Locator Service | AGRC | Composite address locators for geocoding that reference the statewide Transportation.Roads feature class and address point data in Utah. | |
| Cities Towns Locations | GIS Data Layer | AGRC | Cities, towns, and other locations for cartographic purposes. | |
| Building Footprints | GIS Data Layer | AGRC, Local Governments | Building footprints in Salt Lake City, Cottonwood Heights, Summit County, Utah County, Washington County, and Weber County. | |
| GNIS | GIS Data Layer | USGS | Point locations from the Geographic Names Information System (GNIS), which was developed by the USGS. | |
| Place Name Areas | GIS Data Layer | AGRC | Polygons of places commonly on a map. Includes cities, counties, political districts, zipcodes, etc. | |
| United States Postal Service | GIS Data Layer | AGRC & USPS | Locations of post offices, P.O. box only zipcodes in Utah and zipcode areas. | |
| UDOT State Map Features | GIS Data Layer | UDOT | UDOT's map's cities, places of interest, & state parks locations. | |
Related Data (see also)


infrastructure
Coming soon.
Old Prejudices, New Tools: India’s WhatsApp Mob Killings
Facebook’s connection with ethnic violence is primarily considered in the Myanmar case, but one FB product has more weight in the developing world than any other: WhatsApp. The WhatsApp saga raises deep questions about technology’s potential to exacerbate our worst qualities. What role do companies have in self-regulating and what role do governments have in regulating these companies without endangering civil liberties? And what implications do these dynamics have for the 2019 Indian general elections?
Show Me the Money: Scaling Social Tech Ventures
Non-profit social ventures today are bound to stringent financial constraints on how they operate. There are important structural differences in how a non-profit social tech venture is allowed to operate relative to its for-profit counterpart, many of which challenge fundamental norms that dominate today’s business landscape: what’s the return profile for investors? To what end are financial incentives structured? We want to explore the reasons why these financial bounds prevent so many non-profit social tech ventures from achieving the mission at scale.
The Pen as a Sword: IP and Open Source
Currently, it is taken for granted that academic research should be open-source and thus easily accessible and modifiable by the general public. Across academia, this seems to take moral precedence from the notion of egalitarianism and general distribution of resources; however, this only holds if the final product distributed is in fact a public moral good. Intellectual property (IP) rights can therefore have a very complicated relationship to the open source outputs of academia, which only becomes more problematic when that academic output is then transformed into a company operating at scale. We want to therefore explore the role that IP has in sustaining a healthy open source ecosystem.
Request for Proposal: Let's Change Gov Tech Procurement
This piece will dive into the why government tech procurement seems to be exponentially outpaced by the rate of innovation. In particular, we’ll examine the complicated history of the RFP process and how it took such a stranglehold within the government. We’ll close by providing our thoughts on some of the current solutions that different governmental departments are exploring, looping in many prominent thought leaders into our discussion.


Modules
Website Pages
Landing Pages
Blogs
Account Details
Agencies
Billing Information
Plans
Users
Navigation
Hero
Footer
Columns
Tabs
Offers
Cards
Social
Bling
Portals
Add portal
Integrate
419314 integrate.com
ITA
419314 www.internationalteflacademy.com
Lean Labs
419314 www.lean-labs.com
Integrate
419314 campaigndrive.com
Hey Spencer!
Welcome to Sprocket Rocket!
Let's Do This
Please use a larger browser window to use Sprocket Rocket.


Authentication in Angular with NGRX
In this tutorial, we’ll add authentication to Angular using NGRX Store and Effects.
This post assumes that you a have basic working knowledge of Angular (2+), TypeScript, RxJS and the Redux design pattern. If you’re new to NGRX, check out the awesome Comprehensive Introduction to @ngrx/store guide.
Dependencies:
- Angular CLI v1.7.3 (Angular v5.2.0)
- Node v9.11.0
- NGRX Store v5.2.0
- NGRX Effects v5.2.0
Final app:
Contents
- Objectives
- Token-based Authentication
- Project Setup
- Routing and Components
- Workflow
- Configure Forms
- NGRX Store
- Configure Auth Service
- NGRX Effects
- Configure Login
- Configure Signup
- Configure Logout
- Update the Templates
- Add HTTP Interceptor
- Route Guard
- Conclusion
Objectives
By the end of this tutorial, you will be able to…
- Develop a fully-functioning Angular app with authentication
- Discuss the benefits and drawbacks of using token-based authentication
- Implement user authentication with tokens
- Utilize NGRX Store for state management
- Isolate and manage side effects with NGRX Effects
- Set up an HTTP Interceptor to hijack outgoing requests and incoming responses
- Configure route-based authorization with route guards
Token-based Authentication
With token-based Authentication, users send their credentials to an authentication server to obtain a signed token. The client then stores this token locally, usually in localStorage or in a cookie. Every subsequent call to the server, for a protected resource, includes that signed token that the server then verifies before granting access to the desired resource.
Benefits:
- Stateless: Since the token contains all information required for the server to verify a user’s identity, scaling is easier as we don’t need to worry about maintaining a session store on the server-side.
- Single Sign On: After a token is generated, you can have your users access a number of different resources and services without having to prompt them for their login credentials.
Drawbacks:
- Cross-site Scripting (XSS) attacks: Storing tokens in either local or session storage can lead to XSS attacks. Because of this, it’s a good idea to store tokens in a cookie with
httpOnly
andsecure
flags.
Although we won’t be covering server-side token creation in this post, it’s worth noting that a JSON Web Token is a popular standard for creating tokens. Just keep in mind that since a JWT is signed rather than encrypted it should never contain sensitive information like a user’s password.
With that, here’s the full user auth process:
- End user sends their credentials to the server
- Server verifies the credentials and, if correct, generates a token, which is then passed back to the client
- Client stores the token in localStorage or in a cookie
- Client sends the token alongside any subsequent requests to the server
For more on token-based auth, along with the pros and cons of using it vs. session-based auth, please review the following articles:
Project Setup
Begin by installing the Angular CLI globally, if you don’t already have it:
$ npm install -g<EMAIL_ADDRESS>Then, create a new Angular project:
$ ng new angular-auth-ngrx
$ cd angular-auth-ngrx
Run the server:
$ ng serve
Then, in your browser of choice, navigate to http://localhost:4200. You should see the “Welcome to app!” message along with the Angular logo in the browser.
Kill the server. Then, install Bootstrap:
$ npm install<EMAIL_ADDRESS>--save
After installation, update the styles configuration in the .angular-cli.json file at the project root:
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
"styles.css"
],
Add a container to the src/index.html page:
<!doctype html>

<meta charset="utf-8">
<title>AngularAuthNgrx</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">

<app-root></app-root>

Run the server again to view the updated styles:
Routing and Components
Next, let’s add three components and configure some basic routes:
| Component | Purpose | Route |
|---|---|---|
Landing |
Landing page | / |
LogIn |
Authenticating existing users | /log-in |
SignUp |
Registering new users | /sign-up |
Start by generating the components:
$ ng generate component components/landing
$ ng generate component components/sign-up
$ ng generate component components/log-in
Next, add the RouterModule import to the app.module.ts file:
import { RouterModule } from '@angular/router';
Add the following route configuration, to the imports
array, to map each of the components we just created to a URL:
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
Your app.module.ts should now look like:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { LandingComponent } from './components/landing/landing.component';
import { SignUpComponent } from './components/sign-up/sign-up.component';
import { LogInComponent } from './components/log-in/log-in.component';
@NgModule({
declarations: [
AppComponent,
LandingComponent,
SignUpComponent,
LogInComponent
],
imports: [
BrowserModule,
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Fire up the server and test each URL in the browser:
- http://localhost:4200
- http://localhost:4200/log-in
- http://localhost:4200/sign-up
- http://localhost:4200/notreal
We know that the routes are configured correctly since /notreal
redirects to /
(and renders the LandingComponent
) while /log-in
and /sign-up
work just fine. Now, we still need to use the RouterOutlet
directive to tell Angular where to insert each of our HTML templates.
Replace the contents of the app.component.html file with the <router-outlet>
tag:
<router-outlet></router-outlet>
Run the app again. Make sure you are shown the correct component when you visit each of the URLs in the browser.
Finally, update src/app/components/landing/landing.component.html:

Angular + NGRX

Log in
Sign up

And, with that, we’re ready to start adding authentication!
Workflow
Configure Forms
- Add form to the
SignUpComponent
- Define the
User
Model - Add form to the
LogInComponent
NGRX Store
- Install NGRX Store
- Add files and folders for the actions and reducers
- Define the state
Configure Auth Service
- Spin up the fake back-end server
- Add a service
NGRX Effects
- Install NGRX Effects
- Add effects file
Configure Login
- Login
- Dispatch
LogIn
action - Add action
- Add effect (to dispatch either
LogInSuccess
orLogInFailure
)
- Dispatch
- Login Success
- Add action
- Add reducer (to create new state)
- Add effect (to add token to localStorage and redirect user)
- Login Failure
- Add action
- Add reducer (to create new state)
- Add effect
Configure Signup
- Signup
- Dispatch
SignUp
action - Add action
- Add effect (to dispatch either
SignUpSuccess
orSignUpFailure
)
- Dispatch
- Signup Success
- Add action
- Add reducer (to create new state)
- Add effect (to add token to localStorage and redirect user)
- Signup Failure
- Add action
- Add reducer (to create new state)
- Add effect
Configure Logout
- Logout
- Dispatch
LogIn
action - Add action
- Add reducer (to create new state)
- Add effect (to remove token from localStorage)
- Dispatch
Update the Templates
- Add error messages to the forms
- Update the components
- Add messages to the templates
- Update the
LandingComponent
Add HTTP Interceptor
- Configure the interceptor
- Handle unauthorized responses
- Add new route
Route Guard
- Configure the interface
- Protect the route
Let’s get to it!
Configure Forms
Add form to the SignUpComponent
Start with the template:

Sign up

<form (ngSubmit)="onSubmit()" ngNativeValidate>

Email
<input
[(ngModel)]="user.email"
name="email"
type="email"
required
class="form-control"
id="email"
placeholder="enter your email">

Password
<input
[(ngModel)]="user.password"
name="password"
type="password"
required
class="form-control"
id="password"
placeholder="enter a password">

<button type="submit" class="btn btn-primary">Submit</button>
Cancel
</form>

Already have an account?
Log in!

Since Angular now automatically adds a novalidate
attribute to forms, we used the ngNativeValidate
directive to turn the browser’s native form validation back on.
Feel free to use Angular’s form validation.
Then, wire up the component itself:
import { Component, OnInit } from '@angular/core';
import { User } from '../../models/user';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
user: User = new User();
constructor() { }
ngOnInit() {
}
onSubmit(): void {
console.log(this.user);
}
}
Add the FormsModule
to app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { LandingComponent } from './components/landing/landing.component';
import { SignUpComponent } from './components/sign-up/sign-up.component';
import { LogInComponent } from './components/log-in/log-in.component';
@NgModule({
declarations: [
AppComponent,
LandingComponent,
SignUpComponent,
LogInComponent
],
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Run the application. The app should fail to build, and you should see the following error in the terminal since the User
model does not exist:
ERROR in src/app/components/sign-up/sign-up.component.ts(3,22): error TS2307:
Cannot find module '../../models/user'.
Kill the server.
Define the User
Model
Moving along, let’s generate a new model class:
$ ng generate class models/user
Then update src/app/models/user.ts:
export class User {
id?: string;
email?: string;
password?: string;
token?: string;
}
Run the server again. The app should compile just fine and the terminal should be error-free. Try submitting the form. You should see the user model logged to the JavaScript Console:
Add form to the LogInComponent
Again, start with the template:

Log in

<form (ngSubmit)="onSubmit()" ngNativeValidate>

Email
<input
[(ngModel)]="user.email"
name="email"
type="email"
required
class="form-control"
id="email"
placeholder="enter your email">

Password
<input
[(ngModel)]="user.password"
name="password"
type="password"
required
class="form-control"
id="password"
placeholder="enter a password">

<button type="submit" class="btn btn-primary">Submit</button>
Cancel
</form>

Don't have an account?
Sign up!

Then, update the LogInComponent
itself:
import { Component, OnInit } from '@angular/core';
import { User } from '../../models/user';
@Component({
selector: 'app-log-in',
templateUrl: './log-in.component.html',
styleUrls: ['./log-in.component.css']
})
export class LogInComponent implements OnInit {
user: User = new User();
constructor() { }
ngOnInit() {
}
onSubmit(): void {
console.log(this.user);
}
}
Test it out! Like the sign up form, you should see the user model logged to the JavaScript Console.
With that, let’s move on to NGRX!
NGRX Store
Install NGRX Store
State management is difficult. As your application scales, state generally scatters across your application, tucked away in various nooks and crannies. Although it’s not an issue yet, it’s a good idea to set a solid foundation to help ensure that, going forward, state management is easier and more predictable. This is where NGRX Store comes into play. It helps to solve this problem by managing state in a single, immutable data store.
Core tenets
- State is a single immutable data structure
- Actions describe state changes
- Pure functions called reducers take the previous state and the next action to compute the new state
- State accessed with the Store, an observable of state and an observer of actions
In a nutshell, NGRX Store builds on Redux’s core patterns by adding in RxJS. It’s specifically designed for Angular apps.
Building blocks:
- Store - single, immutable data structure
- Actions - describe changes to state
- Reducers - pure functions that create a new state
Example:
Install:
$ npm install<EMAIL_ADDRESS>--save
Add files and folders for the actions and reducers
Next, we need to add a bit of structure for the actions and reducers. Within “src/app”, add a new folder called “store”. Then, add the following folders to “store”:
- “actions”
- “reducers”
Add a file called app.states.ts as well. Finally, add a single file to each folder:
- auth.actions.ts
- auth.reducers.ts
You should now have:
└── store
├── actions
│ └── auth.actions.ts
├── app.states.ts
└── reducers
└── auth.reducers.ts
You could also group actions and reducers by domain. Actions and reducers would live at the component level, in other words. If you decide to go that route, you should probably create a “common” folder for actions and reducers that are used across a number of components. Auth actions and reducers should then live in “common”.
Define the state
Before creating any actions or reducers, let’s define structure of the store in src/app/store/reducers/auth.reducers.ts:
import { User } from '../../models/user';
export interface State {
// is a user authenticated?
isAuthenticated: boolean;
// if authenticated, there should be a user object
user: User | null;
// error message
errorMessage: string | null;
}
Remember: State is a single, immutable data structure.
Also, add an initialState
object:
export const initialState: State = {
isAuthenticated: false,
user: null,
errorMessage: null
};
Then, define the top-level state interface in src/app/store/app.states.ts:
import * as auth from './reducers/auth.reducers';
export interface AppState {
authState: auth.State;
}
This is a map of keys to the inner state types.
Configure Auth Service
Spin up the fake back-end server
In this section we’ll spin up a fake back-end that the client can communicate with. The app itself is a basic Node/Express application with the following routes:
| URL | HTTP Verb | Action |
|---|---|---|
| http://localhost:1337/ping | GET | Sanity Check |
| http://localhost:1337/register | POST | Register a new user |
| http://localhost:1337/login | POST | Log a user in |
| http://localhost:1337/status | GET | Get user status |
Just keep in mind that the back-end does not create a real JSON Web Token (JWT). Feel free to swap it out for a working back-end or use the final application from the Token-Based Authentication with Node blog post, if you’d like.
Within a new terminal window, clone down the repo, install the dependencies, and spin up the app:
$ git clone https://github.com/testdrivenio/fake-token-api
$ cd fake-token-api
$ npm install
$ npm start
In your browser, http://localhost:1337/ping should return "pong!"
.
Add the service
Back in Angular land, we need to wire up a service that’s responsible for making API calls to the fake back-end:
$ ng generate service services/auth
Add the service as a provider in the @NgModule
definition and import the HttpClientModule
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { LandingComponent } from './components/landing/landing.component';
import { SignUpComponent } from './components/sign-up/sign-up.component';
import { LogInComponent } from './components/log-in/log-in.component';
import { AuthService } from './services/auth.service';
@NgModule({
declarations: [
AppComponent,
LandingComponent,
SignUpComponent,
LogInComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
],
providers: [AuthService],
bootstrap: [AppComponent]
})
export class AppModule { }
Add the following methods to the service:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { User } from '../models/user';
@Injectable()
export class AuthService {
private BASE_URL = 'http://localhost:1337';
constructor(private http: HttpClient) {}
getToken(): string {
return localStorage.getItem('token');
}
logIn(email: string, password: string): Observable<any> {
const url = `${this.BASE_URL}/login`;
return this.http.post<User>(url, {email, password});
}
signUp(email: string, password: string): Observable<User> {
const url = `${this.BASE_URL}/register`;
return this.http.post<User>(url, {email, password});
}
}
Both the logIn
and signUp
methods return Observable
s and create new User
s. We’ll need to subscribe to logIn
and signUp
, after a successful form submission, to send the respective HTTP requests within the effects module.
NGRX Effects
Install NGRX Effects
NGRX Effects listen for actions dispatched from the NGRX Store, perform some logic (e.g., a side effect), and then dispatch a new action.
Install:
$ npm install<EMAIL_ADDRESS>--save
Add effects file
Then, within the “store” folder, add a new folder called “effects”. And, within that folder, add a new file called auth.effects.ts:
import { Injectable } from '@angular/core';
import { Action } from '@ngrx/store';
import { Router } from '@angular/router';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/catch';
import { tap } from 'rxjs/operators';
import { AuthService } from '../../services/auth.service';
@Injectable()
export class AuthEffects {
constructor(
private actions: Actions,
private authService: AuthService,
private router: Router,
) {}
// effects go here
}
Then, register the effects module in @NgModule
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { EffectsModule } from '@ngrx/effects';
import { AppComponent } from './app.component';
import { LandingComponent } from './components/landing/landing.component';
import { SignUpComponent } from './components/sign-up/sign-up.component';
import { LogInComponent } from './components/log-in/log-in.component';
import { AuthService } from './services/auth.service';
import { AuthEffects } from './store/effects/auth.effects';
@NgModule({
declarations: [
AppComponent,
LandingComponent,
SignUpComponent,
LogInComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
EffectsModule.forRoot([AuthEffects]),
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
],
providers: [AuthService],
bootstrap: [AppComponent]
})
export class AppModule { }
Configure Login
Login
Dispatch LogIn
action
First, after a successful form submission, we need to dispatch a LogIn
action, which will send an action and a parameter to a reducer to eventually create a new state.
src/app/components/log-in/log-in.component.ts:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { User } from '../../models/user';
import { AppState } from '../../store/app.states';
import { LogIn } from '../../store/actions/auth.actions';
@Component({
selector: 'app-log-in',
templateUrl: './log-in.component.html',
styleUrls: ['./log-in.component.css']
})
export class LogInComponent implements OnInit {
user: User = new User();
constructor(
private store: Store<AppState>
) { }
ngOnInit() {
}
onSubmit(): void {
const payload = {
email: this.user.email,
password: this.user.password
};
this.store.dispatch(new LogIn(payload));
}
}
With the Angular server running, you should see the following error since we still need to set up the module for the actions along with the LogIn
action:
ERROR in src/app/components/log-in/log-in.component.ts(6,23): error TS2306:
File 'angular-auth-ngrx/src/app/store/actions/auth.actions.ts' is not a module.
Add action
Actions describe changes to state. They are dispatched to a reducer, which will then create a new state.
Update src/app/store/user.actions.ts like so:
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login'
}
Add the action class as well:
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export type All =
| LogIn;
You should now have:
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login'
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export type All =
| LogIn;
Add effect (to dispatch either LogInSuccess
or LogInFailure
)
Add the first effect to src/app/store/effects/auth.effects.ts
@Effect()
LogIn: Observable<any> = this.actions
.ofType(AuthActionTypes.LOGIN)
.map((action: LogIn) => action.payload)
.switchMap(payload => {
return this.authService.logIn(payload.email, payload.password)
.map((user) => {
console.log(user);
return new LogInSuccess({token: user.token, email: payload.email});
})
.catch((error) => {
console.log(error);
return Observable.of(new LogInFailure({ error: error }));
});
});
The ofType
operator filters the action by a type. It accepts multiple action types, so one effect can handle a number of actions. Then, with map
, we “map” the action to its payload. This, essentially, returns an observable with just the payload. The switchMap
is used to switch back to the response observable but still use the payload as an argument in the switchMap
function.
Add the import:
import {
AuthActionTypes,
LogIn, LogInSuccess, LogInFailure,
} from '../actions/auth.actions';
For AJAX requests, it’s a good practice to also dispatch a success or error action based on the result of the request.
Login Success
Add action
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login',
LOGIN_SUCCESS = '[Auth] Login Success',
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export class LogInSuccess implements Action {
readonly type = AuthActionTypes.LOGIN_SUCCESS;
constructor(public payload: any) {}
}
export type All =
| LogIn
| LogInSuccess;
Add reducer (to create new state)
Reducers are pure functions that create a new state.
When the log in is successful, we need to set isAuthenticated
to true
and add the token and email to the user
object.
Update src/app/store/reducers/auth.reducers.ts:
export function reducer(state = initialState, action: All): State {
switch (action.type) {
case AuthActionTypes.LOGIN_SUCCESS: {
return {
...state,
isAuthenticated: true,
user: {
token: action.payload.token,
email: action.payload.email
},
errorMessage: null
};
}
default: {
return state;
}
}
}
Add the import:
import { AuthActionTypes, All } from '../actions/auth.actions';
Import the reducers into the Angular module:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { AppComponent } from './app.component';
import { LandingComponent } from './components/landing/landing.component';
import { SignUpComponent } from './components/sign-up/sign-up.component';
import { LogInComponent } from './components/log-in/log-in.component';
import { AuthService } from './services/auth.service';
import { AuthEffects } from './store/effects/auth.effects';
import { reducers } from './store/app.states';
@NgModule({
declarations: [
AppComponent,
LandingComponent,
SignUpComponent,
LogInComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
StoreModule.forRoot(reducers, {}),
EffectsModule.forRoot([AuthEffects]),
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
],
providers: [AuthService],
bootstrap: [AppComponent]
})
export class AppModule { }
Then, update app.states.ts, adding in the reducers:
import * as auth from './reducers/auth.reducers';
export interface AppState {
authState: auth.State;
}
export const reducers = {
auth: auth.reducer
};
Add effect (to add token to localStorage and redirect user)
@Effect({ dispatch: false })
LogInSuccess: Observable<any> = this.actions.pipe(
ofType(AuthActionTypes.LOGIN_SUCCESS),
tap((user) => {
localStorage.setItem('token', user.payload.token);
this.router.navigateByUrl('/');
})
);
Version 5.5 of RXJS introduced the pipe
method, which is used to compose a number of functions to act on the observable. Again, ofType
associates the effect with an action while tap
performs a side effect transparently. In other words, it returns an observable identical to the source. In our case, we’re adding the token to localStorage and then redirecting the user to /
.
Check out the comments for pipe and tap, respectively, from the source code.
Login Failure
Add action
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login',
LOGIN_SUCCESS = '[Auth] Login Success',
LOGIN_FAILURE = '[Auth] Login Failure',
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export class LogInSuccess implements Action {
readonly type = AuthActionTypes.LOGIN_SUCCESS;
constructor(public payload: any) {}
}
export class LogInFailure implements Action {
readonly type = AuthActionTypes.LOGIN_FAILURE;
constructor(public payload: any) {}
}
export type All =
| LogIn
| LogInSuccess
| LogInFailure;
Add reducer (to create new state)
case AuthActionTypes.LOGIN_FAILURE: {
return {
...state,
errorMessage: 'Incorrect email and/or password.'
};
}
Add effect
@Effect({ dispatch: false })
LogInFailure: Observable<any> = this.actions.pipe(
ofType(AuthActionTypes.LOGIN_FAILURE)
);
Try it out. Make sure the token is added to localStorage and you are redirected after a successful log in:
- email:
<EMAIL_ADDRESS>- password:
test
The fake back-end will throw a 400
error if you use any email other than<EMAIL_ADDRESS>. As of now, nothing happens on the UI, though. We’ll wire up error messaging shorty.
Looking for a quick challenge? Refactor the
LogIn
effect to use thepipe
method. Clean up the code!
Configure Signup
Your turn! Configuring the sign up functionality is nearly the same as the log in functionality. Try it on your own before reviewing the post.
Signup
Dispatch SignUp
action
src/app/components/sign-up/sign-up.component.ts:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { User } from '../../models/user';
import { AppState } from '../../store/app.states';
import { SignUp } from '../../store/actions/auth.actions';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
user: User = new User();
constructor(
private store: Store<AppState>
) { }
ngOnInit() {
}
onSubmit(): void {
const payload = {
email: this.user.email,
password: this.user.password
};
this.store.dispatch(new SignUp(payload));
}
}
Add action
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login',
LOGIN_SUCCESS = '[Auth] Login Success',
LOGIN_FAILURE = '[Auth] Login Failure',
SIGNUP = '[Auth] Signup',
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export class LogInSuccess implements Action {
readonly type = AuthActionTypes.LOGIN_SUCCESS;
constructor(public payload: any) {}
}
export class LogInFailure implements Action {
readonly type = AuthActionTypes.LOGIN_FAILURE;
constructor(public payload: any) {}
}
export class SignUp implements Action {
readonly type = AuthActionTypes.SIGNUP;
constructor(public payload: any) {}
}
export type All =
| LogIn
| LogInSuccess
| LogInFailure
| SignUp;
Add effect (to dispatch either SignUpSuccess
or SignUpFailure
)
@Effect()
SignUp: Observable<any> = this.actions
.ofType(AuthActionTypes.SIGNUP)
.map((action: SignUp) => action.payload)
.switchMap(payload => {
return this.authService.signUp(payload.email, payload.password)
.map((user) => {
console.log(user);
return new SignUpSuccess({token: user.token, email: payload.email});
})
.catch((error) => {
console.log(error);
return Observable.of(new SignUpFailure({ error: error }));
});
});
Add the import:
import {
AuthActionTypes,
LogIn, LogInSuccess, LogInFailure,
SignUp, SignUpSuccess, SignUpFailure
} from '../actions/auth.actions';
Signup Success
Add action
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login',
LOGIN_SUCCESS = '[Auth] Login Success',
LOGIN_FAILURE = '[Auth] Login Failure',
SIGNUP = '[Auth] Signup',
SIGNUP_SUCCESS = '[Auth] Signup Success',
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export class LogInSuccess implements Action {
readonly type = AuthActionTypes.LOGIN_SUCCESS;
constructor(public payload: any) {}
}
export class LogInFailure implements Action {
readonly type = AuthActionTypes.LOGIN_FAILURE;
constructor(public payload: any) {}
}
export class SignUp implements Action {
readonly type = AuthActionTypes.SIGNUP;
constructor(public payload: any) {}
}
export class SignUpSuccess implements Action {
readonly type = AuthActionTypes.SIGNUP_SUCCESS;
constructor(public payload: any) {}
}
export type All =
| LogIn
| LogInSuccess
| LogInFailure
| SignUp
| SignUpSuccess;
Add reducer (to create new state)
case AuthActionTypes.SIGNUP_SUCCESS: {
return {
...state,
isAuthenticated: true,
user: {
token: action.payload.token,
email: action.payload.email
},
errorMessage: null
};
}
Add effect (to add token to localStorage and redirect user)
@Effect({ dispatch: false })
SignUpSuccess: Observable<any> = this.actions.pipe(
ofType(AuthActionTypes.SIGNUP_SUCCESS),
tap((user) => {
localStorage.setItem('token', user.payload.token);
this.router.navigateByUrl('/');
})
);
Signup Failure
Again, try this on your own!
Add action
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login',
LOGIN_SUCCESS = '[Auth] Login Success',
LOGIN_FAILURE = '[Auth] Login Failure',
SIGNUP = '[Auth] Signup',
SIGNUP_SUCCESS = '[Auth] Signup Success',
SIGNUP_FAILURE = '[Auth] Signup Failure',
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export class LogInSuccess implements Action {
readonly type = AuthActionTypes.LOGIN_SUCCESS;
constructor(public payload: any) {}
}
export class LogInFailure implements Action {
readonly type = AuthActionTypes.LOGIN_FAILURE;
constructor(public payload: any) {}
}
export class SignUp implements Action {
readonly type = AuthActionTypes.SIGNUP;
constructor(public payload: any) {}
}
export class SignUpSuccess implements Action {
readonly type = AuthActionTypes.SIGNUP_SUCCESS;
constructor(public payload: any) {}
}
export class SignUpFailure implements Action {
readonly type = AuthActionTypes.SIGNUP_FAILURE;
constructor(public payload: any) {}
}
export type All =
| LogIn
| LogInSuccess
| LogInFailure
| SignUp
| SignUpSuccess
| SignUpFailure;
Add reducer (to create new state)
case AuthActionTypes.SIGNUP_FAILURE: {
return {
...state,
errorMessage: 'That email is already in use.'
};
}
Add effect
@Effect({ dispatch: false })
SignUpFailure: Observable<any> = this.actions.pipe(
ofType(AuthActionTypes.SIGNUP_FAILURE)
);
You could combine
SignUpFailure
andLogInFailure
, to make a single effect:AuthFailure: Observable<any> = this.actions.pipe( ofType(AuthActionTypes.SIGNUP_FAILURE, AuthActionTypes.LOGIN_FAILURE) );
We’re now ready to test!
With the fake back-end running, try signing up with the following credentials:
- email:
<EMAIL_ADDRESS>- password:
test
Make sure that you are redirected after a successful attempt and that a token was added to localStorage. Also, ensure that nothing happens on an unsuccessful attempt (when you use an email other than<EMAIL_ADDRESS>). We still need to wire up the handling of the error to the template.
Configure Logout
Logout
Dispatch LogOut
action
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '../../store/app.states';
import { LogOut } from '../../store/actions/auth.actions';
@Component({
selector: 'app-landing',
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.css']
})
export class LandingComponent implements OnInit {
constructor(
private store: Store<AppState>
) { }
ngOnInit() {
}
logOut(): void {
this.store.dispatch(new LogOut);
}
}
Add action
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login',
LOGIN_SUCCESS = '[Auth] Login Success',
LOGIN_FAILURE = '[Auth] Login Failure',
SIGNUP = '[Auth] Signup',
SIGNUP_SUCCESS = '[Auth] Signup Success',
SIGNUP_FAILURE = '[Auth] Signup Failure',
LOGOUT = '[Auth] Logout',
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export class LogInSuccess implements Action {
readonly type = AuthActionTypes.LOGIN_SUCCESS;
constructor(public payload: any) {}
}
export class LogInFailure implements Action {
readonly type = AuthActionTypes.LOGIN_FAILURE;
constructor(public payload: any) {}
}
export class SignUp implements Action {
readonly type = AuthActionTypes.SIGNUP;
constructor(public payload: any) {}
}
export class SignUpSuccess implements Action {
readonly type = AuthActionTypes.SIGNUP_SUCCESS;
constructor(public payload: any) {}
}
export class SignUpFailure implements Action {
readonly type = AuthActionTypes.SIGNUP_FAILURE;
constructor(public payload: any) {}
}
export class LogOut implements Action {
readonly type = AuthActionTypes.LOGOUT;
}
export type All =
| LogIn
| LogInSuccess
| LogInFailure
| SignUp
| SignUpSuccess
| SignUpFailure
| LogOut;
Did you notice we’re not sending any parameters with the dispatch? Because of that, we left off the payload in the constructor.
Add reducer (to create new state)
case AuthActionTypes.LOGOUT: {
return initialState;
}
Add effect (to remove token from localStorage)
@Effect({ dispatch: false })
public LogOut: Observable<any> = this.actions.pipe(
ofType(AuthActionTypes.LOGOUT),
tap((user) => {
localStorage.removeItem('token');
})
);
Import:
import {
AuthActionTypes,
LogIn, LogInSuccess, LogInFailure,
SignUp, SignUpSuccess, SignUpFailure,
LogOut,
} from '../actions/auth.actions';
We’ll test this functionality out shortly.
Update the Templates
Add error messages to the forms
Update the components
LogInComponent
:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { User } from '../../models/user';
import { AppState, selectAuthState } from '../../store/app.states';
import { LogIn } from '../../store/actions/auth.actions';
@Component({
selector: 'app-log-in',
templateUrl: './log-in.component.html',
styleUrls: ['./log-in.component.css']
})
export class LogInComponent implements OnInit {
user: User = new User();
getState: Observable<any>;
errorMessage: string | null;
constructor(
private store: Store<AppState>
) {
this.getState = this.store.select(selectAuthState);
}
ngOnInit() {
this.getState.subscribe((state) => {
this.errorMessage = state.errorMessage;
});
};
onSubmit(): void {
const payload = {
email: this.user.email,
password: this.user.password
};
this.store.dispatch(new LogIn(payload));
}
}
Here, we’re subscribing to the store and assigning the errorMessage
to this.errorMessage
, which we can reference in our template.
Update app.states.ts:
import { createFeatureSelector } from '@ngrx/store';
import * as auth from './reducers/auth.reducers';
export interface AppState {
authState: auth.State;
}
export const reducers = {
auth: auth.reducer
};
export const selectAuthState = createFeatureSelector<AppState>('auth');
createFeatureSelector
is a selector used to query the state.
SignUpComponent
:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { User } from '../../models/user';
import { AppState, selectAuthState } from '../../store/app.states';
import { SignUp } from '../../store/actions/auth.actions';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
user: User = new User();
getState: Observable<any>;
errorMessage: string | null;
constructor(
private store: Store<AppState>
) {
this.getState = this.store.select(selectAuthState);
}
ngOnInit() {
this.getState.subscribe((state) => {
this.errorMessage = state.errorMessage;
});
}
onSubmit(): void {
const payload = {
email: this.user.email,
password: this.user.password
};
this.store.dispatch(new SignUp(payload));
}
}
Add messages to the templates
Login:

Log in

{{errorMessage}}

<form (ngSubmit)="onSubmit()" ngNativeValidate>

Email
<input
[(ngModel)]="user.email"
name="email"
type="email"
required
class="form-control"
id="email"
placeholder="enter your email">

Password
<input
[(ngModel)]="user.password"
name="password"
type="password"
required
class="form-control"
id="password"
placeholder="enter a password">

<button type="submit" class="btn btn-primary">Submit</button>
Cancel
</form>

Don't have an account?
Sign up!

Signup:

Sign up

{{errorMessage}}

<form (ngSubmit)="onSubmit()" ngNativeValidate>

Email
<input
[(ngModel)]="user.email"
name="email"
type="email"
required
class="form-control"
id="email"
placeholder="enter your email">

Password
<input
[(ngModel)]="user.password"
name="password"
type="password"
required
class="form-control"
id="password"
placeholder="enter a password">

<button type="submit" class="btn btn-primary">Submit</button>
Cancel
</form>

Already have an account?
Log in!

Test this out!
Update the LandingComponent
Update the component:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { AppState, selectAuthState } from '../../store/app.states';
import { LogOut } from '../../store/actions/auth.actions';
@Component({
selector: 'app-landing',
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.css']
})
export class LandingComponent implements OnInit {
getState: Observable<any>;
isAuthenticated: false;
user = null;
errorMessage = null;
constructor(
private store: Store<AppState>
) {
this.getState = this.store.select(selectAuthState);
}
ngOnInit() {
this.getState.subscribe((state) => {
this.isAuthenticated = state.isAuthenticated;
this.user = state.user;
this.errorMessage = state.errorMessage;
});
}
logOut(): void {
this.store.dispatch(new LogOut);
}
}
Next, update the Landing template so that the Log in and Sign up buttons are only visible when a user is not authenticated. Also, when the user is authenticated, a welcome message will be displayed along with a Log out button.

Angular + NGRX

<ng-template #doSomething>

You logged in {{user.email}}!

<button class="btn btn-primary" (click)="logOut()">Log out</button>
</ng-template>
<ng-template #doSomethingElse>
Log in
Sign up
</ng-template>

Test it out! Make sure the token is removed when the user logs out.
Finally, update the template once again to show the current application state. This is just for reference while developing, so be sure to remove it before deploying to production.
Template:

Angular + NGRX

<ng-template #doSomething>

You logged in {{user.email}}!

<button class="btn btn-primary" (click)="logOut()">Log out</button>
</ng-template>
<ng-template #doSomethingElse>
Log in
Sign up
</ng-template>

Current State

isAuthenticated - {{isAuthenticated}}

user.email - {{ user?.email || 'null'}}

user.token - {{ user?.token || 'null'}}

errorMessage - {{ errorMessage || 'null'}}

Add HTTP Interceptor
Configure the interceptor
The HttpInterceptor
interface is used to intercept and modify HTTP requests globally. We’ll use it to add the authentication token and content type to the request headers.
Create the service:
$ ng generate service services/token
Rename token.service.ts to token.interceptor.ts and then remove token.service.spec.ts.
import { Injectable, Injector } from '@angular/core';
import {
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AuthService } from './auth.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private authService: AuthService;
constructor(private injector: Injector) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.authService = this.injector.get(AuthService);
const token: string = this.authService.getToken();
request = request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return next.handle(request);
}
}
Import the TokenInterceptor
and HTTP_INTERCEPTORS
from @angular/common/http
to src/app/app.module.ts, and then add the interceptor as a provider in the @NgModule
definition:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppComponent } from './app.component';
import { LandingComponent } from './components/landing/landing.component';
import { SignUpComponent } from './components/sign-up/sign-up.component';
import { LogInComponent } from './components/log-in/log-in.component';
import { AuthService } from './services/auth.service';
import { AuthEffects } from './store/effects/auth.effects';
import { reducers } from './store/app.states';
import { TokenInterceptor } from './services/token.interceptor';
@NgModule({
declarations: [
AppComponent,
LandingComponent,
SignUpComponent,
LogInComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
StoreModule.forRoot(reducers, {}),
EffectsModule.forRoot([AuthEffects]),
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
],
providers: [
AuthService,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
],
bootstrap: [AppComponent]
})
export class AppModule { }
Now, when an HTTP request is made, the token (if it exists in localStorage) will be added to the header.
Handle unauthorized responses
The interceptor can also be used to intercept incoming HTTP responses. We can use it here to check for any 401
codes and redirect the user to the log in route:
import { Injectable, Injector } from '@angular/core';
import {
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest,
HttpResponse, HttpErrorResponse
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import { Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private authService: AuthService;
constructor(private injector: Injector) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.authService = this.injector.get(AuthService);
const token: string = this.authService.getToken();
request = request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return next.handle(request);
}
}
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(private router: Router) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.catch((response: any) => {
if (response instanceof HttpErrorResponse && response.status === 401) {
console.log(response);
}
return Observable.throw(response);
});
}
}
Add the ErrorInterceptor
to the provider array:
providers: [
AuthService,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true
}
],
Make sure to import it:
import {
TokenInterceptor, ErrorInterceptor
} from './services/token.interceptor';
We’ll test this out shortly.
Add new route
Generate the component:
$ ng generate component components/status
Update the router:
RouterModule.forRoot([
{ path: 'log-in', component: LogInComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: 'status', component: StatusComponent },
{ path: '', component: LandingComponent },
{ path: '**', redirectTo: '/' }
])
Dispatch a new action in the component:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '../../store/app.states';
import { GetStatus } from '../../store/actions/auth.actions';
@Component({
selector: 'app-status',
templateUrl: './status.component.html',
styleUrls: ['./status.component.css']
})
export class StatusComponent implements OnInit {
constructor(private store: Store<AppState>) { }
ngOnInit() {
this.store.dispatch(new GetStatus);
}
}
Add the action:
import { Action } from '@ngrx/store';
export enum AuthActionTypes {
LOGIN = '[Auth] Login',
LOGIN_SUCCESS = '[Auth] Login Success',
LOGIN_FAILURE = '[Auth] Login Failure',
SIGNUP = '[Auth] Signup',
SIGNUP_SUCCESS = '[Auth] Signup Success',
SIGNUP_FAILURE = '[Auth] Signup Failure',
LOGOUT = '[Auth] Logout',
GET_STATUS = '[Auth] GetStatus'
}
export class LogIn implements Action {
readonly type = AuthActionTypes.LOGIN;
constructor(public payload: any) {}
}
export class LogInSuccess implements Action {
readonly type = AuthActionTypes.LOGIN_SUCCESS;
constructor(public payload: any) {}
}
export class LogInFailure implements Action {
readonly type = AuthActionTypes.LOGIN_FAILURE;
constructor(public payload: any) {}
}
export class SignUp implements Action {
readonly type = AuthActionTypes.SIGNUP;
constructor(public payload: any) {}
}
export class SignUpSuccess implements Action {
readonly type = AuthActionTypes.SIGNUP_SUCCESS;
constructor(public payload: any) {}
}
export class SignUpFailure implements Action {
readonly type = AuthActionTypes.SIGNUP_FAILURE;
constructor(public payload: any) {}
}
export class LogOut implements Action {
readonly type = AuthActionTypes.LOGOUT;
}
export class GetStatus implements Action {
readonly type = AuthActionTypes.GET_STATUS;
}
export type All =
| LogIn
| LogInSuccess
| LogInFailure
| SignUp
| SignUpSuccess
| SignUpFailure
| LogOut
| GetStatus;
Effect:
@Effect({ dispatch: false })
GetStatus: Observable<any> = this.actions
.ofType(AuthActionTypes.GET_STATUS)
.map((action: GetStatus) => action)
.switchMap(payload => {
return this.authService.getStatus();
});
@Effect({ dispatch: false })
GetStatus: Observable<any> = this.actions
.ofType(AuthActionTypes.GET_STATUS)
.switchMap(payload => {
return this.authService.getStatus();
});
Add the getStatus
method to AuthService
:
getStatus(): Observable<User> {
const url = `${this.BASE_URL}/status`;
return this.http.get<User>(url);
}
Remove the token from localStorage (if it exists), since it’s invalid, and redirect the user:
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(private router: Router) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.catch((response: any) => {
if (response instanceof HttpErrorResponse && response.status === 401) {
localStorage.removeItem('token');
this.router.navigateByUrl('/log-in');
}
return Observable.throw(response);
});
}
}
Add a /status
link to the Landing template:

Angular + NGRX

<ng-template #doSomething>

You logged in {{user.email}}!

<button class="btn btn-primary" (click)="logOut()">Log out</button>
</ng-template>
<ng-template #doSomethingElse>
Log in
Sign up
</ng-template>
Status

Current State

isAuthenticated - {{isAuthenticated}}

user.email - {{ user?.email || 'null'}}

user.token - {{ user?.token || 'null'}}

errorMessage - {{ errorMessage || 'null'}}

Status template:

Status Works!

Home

Now, if you try to access /status
and are not logged in, you will be redirected to the /log-in
route:
You should also see the token added to the header when you hit the /status
route:
Route Guard
Try going to http://localhost:4200/status in the browser. Did you notice that the component will render for a second before re-directing? That’s because ngOnInit()
is fired after the component is created. We can use a route guard to prevent access to the route altogether so the redirect will happen before the component gets created.
Configure the interface
Create the service:
$ ng generate service services/auth-guard
Update:
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuardService implements CanActivate {
constructor(
public auth: AuthService,
public router: Router
) {}
canActivate(): boolean {
if (!this.auth.getToken()) {
this.router.navigateByUrl('/log-in');
return false;
}
return true;
}
}
So, we are using the CanActivate
route guard interface to implement the guard itself. In the canActivate
method, we check to see if a token is in localStorage, return the appropriate boolean, and (if necessary) redirect the user.
It’s probably worth looking at state as well, to get the value of
isAuthenticated
. Make this change on your own.
Protect the route
Update the route in app.module.ts:
{ path: 'status', component: StatusComponent, canActivate: [AuthGuard] },
Add the provider:
providers: [
AuthService,
AuthGuard,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true
}
],
Import canActivate
:
import { RouterModule, CanActivate } from '@angular/router';
Import the service:
import { AuthGuardService as AuthGuard } from './services/auth-guard.service';
You should no longer see the template flicker before being redirected.
Conclusion
This article took a look at how to add authentication to an Angular app using NGRX Store (to manage state) and Effects (to manage side-effects). The full code can be found in the angular-auth-ngrx repository.
Want to learn how to test this app? Check out the Testing Angular with Cypress and Docker blog post!
Looking for some challenges?
- Add some additional actions and effects:
[Auth] Signup Redirect
and[Auth] Login Redirect
- Refactor out native form validation (
ngNativeValidate
) and add in reactive Angular form validation - Add unit and end-to-end tests
- Configure NGRX Router Store so that the Angular Router has access to state
- Add Docker to simplify the development workflow (see Dockerizing an Angular App for more info)
- Remove all
console.log
statements - Use a cookie instead of localStorage


Oh! So I should take a dump then? Very well my boy!
GO TO THE BATHROOM.


import pysam
import pandas as pd
import sys
from collections import defaultdict
[docs]class BamFileReadParser:
"""
Used to simplify the opening and reading from BAM files. BAMs must be coordinate sorted and indexed.
:Example:
>>> from clubcpg.ParseBam import BamFileReadParser
>>> parser = BamFileReadParser("/path/to/data.BAM", quality_score=20, read1_5=3, read1_3=4, read2_5=7, read2_3=1)
>>> reads = parser.parse_reads("chr7", 10000, 101000)
>>> reads = parser.correct_cpg_positions(reads) # This step is optional
>>> matrix = parser.create_matrix(reads)
"""
[docs] def __init__(self, bamfile, quality_score, read1_5=None, read1_3=None,
read2_5=None, read2_3=None, no_overlap=True):
"""
Class used to read WGBSeq reads from a BAM file, extract methylation, and convert into data frame
:param bamfile: Path to bam file location
:param quality_score: Only include reads >= this fastq quality
:param read1_5: mbias ignore read1 5'
:param read1_3: mbias ignore read1 3'
:param read2_5: mbias ignore read2 5'
:param read2_3: mbias ignore read2 3'
:param no_overlap: bool. If overlap exists between two reads, ignore that region from read 2.
"""
self.mapping_quality = quality_score
self.bamfile = bamfile
self.read1_5 = read1_5
self.read1_3 = read1_3
self.read2_5 = read2_5
self.read2_3 = read2_3
self.full_reads = []
self.read_cpgs = []
self.no_overlap = no_overlap
if read1_5 or read2_5 or read1_3 or read2_3:
self.mbias_filtering = True
else:
self.mbias_filtering = False
self.OpenBamFile = pysam.AlignmentFile(bamfile, 'rb')
# Check for presence of index file
index_present = self.OpenBamFile.check_index()
if not index_present:
raise FileNotFoundError("BAM file index is not found. Please create it using samtools index")
# From open bam file, get locaiton of first read from the provided chromosome
def get_location_of_first_read(self, chromosome: str):
# Get reference lenghts
ref_lens = dict(zip(self.OpenBamFile.references, self.OpenBamFile.lengths))
for read in self.OpenBamFile.fetch(chromosome, 0, ref_lens[chromosome]):
reads_start_loc = read.reference_start
break
return reads_start_loc
# Get reads from the bam file, extract methylation state
[docs] def parse_reads(self, chromosome: str, start:int , stop: int):
"""
:param chromosome: chromosome as "chr6"
:param start: start coordinate
:param stop: end coordinate
:return: List of reads and their positional tags as assigned by bismark
"""
reads = []
for read in self.OpenBamFile.fetch(chromosome, start, stop):
if read.mapping_quality >= self.mapping_quality:
reads.append(read)
read_cpgs = []
for read in reads:
reduced_read = []
# Join EVERY XM tag with its aligned_pair location
for pair, tag in zip(read.get_aligned_pairs(), read.get_tag('XM')):
if pair[1]:
if read.flag == 83 or read.flag == 163 or read.flag == 16:
reduced_read.append((pair[1] - 1, tag))
else:
reduced_read.append((pair[1], tag))
else:
continue
# if MBIAS was set, slice the joined list
if self.mbias_filtering:
if read.is_read1:
mbias_5_prime = self.read1_5
# note taking the NEGATIVE of the value for the 3-prime
mbias_3_prime = -self.read1_3
if mbias_3_prime == 0:
mbias_3_prime = None
reduced_read = reduced_read[mbias_5_prime:mbias_3_prime]
if read.is_read2:
mbias_5_prime = self.read2_5
mbias_3_prime = -self.read2_3
if mbias_3_prime == 0:
mbias_3_prime = None
reduced_read = reduced_read[mbias_5_prime:mbias_3_prime]
read_cpgs.append(reduced_read)
self.full_reads = reads
self.read_cpgs = read_cpgs
# Correct overlapping paired reads if set, this is default behavior
if self.no_overlap:
try:
read_cpgs = self.fix_read_overlap(reads, read_cpgs)
except AttributeError:
print("Could not determine read 1 or 2. {}:{}-{}".format(chromosome, start, stop))
sys.stdout.flush()
# Filter the list for positions between start-stop and CpG (Z/z) tags
output = []
for read_cpg in read_cpgs:
temp = []
for pos, tag in read_cpg:
if pos and pos >= start and pos <= stop and (tag == 'Z' or tag == 'z'):
temp.append((pos, tag))
output.append(temp)
return output
[docs] def create_matrix(self, read_cpgs):
"""
Converted parsed reads into a pandas dataframe.
:param read_cpgs: read CpGs generated by self.parse_reads
:type read_cpgs: iterable
:return: matrix methylated (1) and unmethylated (0) states
:rtype: pd.DataFrame
"""
series = []
for data in read_cpgs:
positions = []
statues = []
for pos, status in data:
positions.append(pos)
statues.append(status)
series.append(pd.Series(statues, positions))
matrix = pd.concat(series, axis=1, ignore_index=True)
matrix = matrix.replace('Z', 1)
matrix = matrix.replace('z', 0)
return matrix.T
[docs] def fix_read_overlap(self, full_reads, read_cpgs):
"""Takes pysam reads and read_cpgs generated during parse reads and removes any
overlap between read1 and read2. If possible it also stitches read1 and read2 together to create
a super read.
:param full_reads: set of reads generated by self.parse_reads()
:param read_cpgs: todoo
:return: A list in the same format as read_cpgs input, but corrected for paired read overlap
"""
# data for return
fixed_read_cpgs = []
# Combine raw reads and extracted tags
combined = []
for read, state in zip(full_reads, read_cpgs):
combined.append((read, state))
# Get names of all the reads present
query_names = [x.query_name for x in full_reads]
# Match paired reads by query_name
tally = defaultdict(list)
for i, item in enumerate(query_names):
tally[item].append(i)
for key, value in sorted(tally.items()):
# A pair exists, process it
if len(value) == 2:
# Set read1 and read2 correctly
if combined[value[0]][0].is_read1:
read1 = combined[value[0]]
read2 = combined[value[1]]
elif combined[value[1]][0].is_read1:
read1 = combined[value[1]]
read2 = combined[value[0]]
# both reads have same value, this shouldn't be. Drop one completely, dont
# bother with overlap
elif combined[value[0]][0].is_read1 == combined[value[1]][0].is_read1:
fixed_read_cpgs.append(combined[value[0]][1])
continue
else:
raise AttributeError("Could not determine read 1 or read 2")
# Find amount of overlap
amount_overlap = 0
r1_bps = [x[0] for x in read1[1]]
r2_bps = [x[0] for x in read2[1]]
if min(r1_bps) < min(r2_bps):
trim_direction = 5
for bp in r2_bps:
if bp and bp in r1_bps:
amount_overlap += 1
else:
trim_direction = 3
for bp in r1_bps:
if bp and bp in r2_bps:
amount_overlap += 1
# remove the overlap by trimming or discarding
if amount_overlap == len(read2[1]):
# discard read 2, only append read 1
fixed_read_cpgs.append(read1[1])
else:
# trim overlap
if trim_direction == 5:
new_read2_cpgs = read2[1][amount_overlap:]
elif trim_direction == 3:
new_read2_cpgs = read2[1][:-amount_overlap]
# stitch together read1 and read2
read1[1].extend(new_read2_cpgs)
fixed_read_cpgs.append(read1[1])
elif len(value) == 1:
# No pair, add to output
fixed_read_cpgs.append(combined[value[0]][1])
return fixed_read_cpgs
[docs] @staticmethod
def correct_cpg_positions(output: list):
"""
For some reason, Bismark alignment produces instances where a CpG site location is incorrect by 1 bp, even
after accounting for DNA strand alignmment. This function fixes this. If two cpgs have positions such as 4, 5
(which is impossible because there needs to by a G between them) this function will convert all 5s to 4s. This
only needs to be applied to matrices which are empty after dropna() is called.
:param output: a list of lists of tuples. The output of self.parse_reads()
:return: list of the same style, execpt the first position in the tuple will have a corrected CpG position.
"""
# find all cpg positions
cpg_positions = []
for item in output:
if item:
for cpg in item:
cpg_positions.append(cpg[0])
cpg_positions = sorted(list(set(cpg_positions)))
# determine corrections
corrections = {}
for x in range(len(cpg_positions)):
try:
if cpg_positions[x + 1] == cpg_positions[x] + 1:
corrections[cpg_positions[x + 1]] = cpg_positions[x]
except IndexError: # end of cpg position list
pass
# correct items
corrected_output = []
for item in output:
corrected_item = []
if item:
for cpg in item:
if cpg[0] in corrections.keys():
new_cpg = (corrections[cpg[0]], cpg[1])
corrected_item.append(new_cpg)
else:
corrected_item.append(cpg)
corrected_output.append(corrected_item)
else:
corrected_output.append(item)
return corrected_output


I finally did it! I left Hugh. The man who was supposed to love and protect me, but whose fists left bruises and words left scars.  I knew that if Hugh found me, he would make me pay. Every night, I stared at the hotel door waiting for his pounding fists. My shadow, once my faithful companion, made my heart race. Safe House was my rescuer. The staff and counselors helped me to feel safe again. I know now that Hugh will never be able to reach me again.


There are three factors of development, namely economic, social and environmental factors. Countries can be classified according to their level of development by looking at wealth, education and health indicators.
The Human Development Index (HDI) measures wealth, education and health.


Controlling RGB LED with the web
Your browser does not support the html5 Canvas element
static
breath
flash


--- layout: default ---
Written {{ page.date | date_to_string }} by {% include authors.html authors=page.authors %}


THE DIGITAL SAVVY PHARMA MARKETER 2020
“Must have tool for every pharma marketer”
COMPANYServices
-
Customer Experience
A must have tool for pharma marketers to gain insights into the largest channel preferences, marketing-budget-allocations, technology utilization
-
Data and Analytics
A must have tool for pharma marketers to gain insights into the largest channel preferences, marketing-budget-allocations, technology utilization
-
Digital Transformation
A must have tool for pharma marketers to gain insights into the largest channel preferences, marketing-budget-allocations, technology utilization
-
Co-commercialization
A must have tool for pharma marketers to gain insights into the largest channel preferences, marketing-budget-allocations, technology utilization
-
R&D / Medical Transformation
A must have tool for pharma marketers to gain insights into the largest channel preferences, marketing-budget-allocations, technology utilization
-
Omnipresence CXM Platform
A must have tool for pharma marketers to gain insights into the largest channel preferences, marketing-budget-allocations, technology utilization
INSPIRATIONAL TESTIMONY
UPCOMING EVENTS
-
Global Pharmaceutical Regulatory Affairs Summit
Monday, AM - Tuesday,
203 St. Mountain View, San Franciso, California, USA -
World Drug Safety Congress Europe
Monday, AM - Tuesday,
203 St. Mountain View, San Franciso, California, USA -
Real World Data and Analytics Centers of Excellence
Monday, AM - Tuesday,
203 St. Mountain View, San Franciso, California, USA -
4th Promotional Review Committee Compliance & Best Practice
Monday, AM - Tuesday,
203 St. Mountain View, San Franciso, California, USA


Community pays tribute to girls found dead in a car south of Brisbane
by Jocelyn GarciaFlowers and teddy bears have been laid in front of a crime scene to pay tribute to two Logan girls who were found dead in a car outside the home south of Brisbane.
Paramedics were called to a home at Waterford West in Logan about 1.35pm on Saturday but were unable to revive the sisters, aged one and two.
Police said it appeared the sisters had died from exposure to extreme heat.
Mother of the girls Kerri-Ann Conley, 27, was charged with two counts of murder.
She will appear at Brisbane Magistrates Court on Monday.
Parents with babies and toddlers dropped stuffed animals and flowers outside the home on Sunday morning.
Mother Sarah Boyle said she was saddened by the death of the girls.
"I met the mother when [the eldest of the two girls] was six months of age at the laundromat on Queens Road and while she was doing her laundry, I offered to feed the baby and from there, I kept contact with her and lost contact over the last year," she said.
"She was probably only six months but she was a beautiful little thing and it's just sad to know that she and her sister are now dead."
Ms Boyle's daughter Chelsea left a stuffed animal in honour of the girls who died.
"It's so to keep the girls really happy and to see that people care about them," she said.
A neighbour, who wished to remain anonymous, said she felt sick to her stomach, knowing it happened so close to home.
"I've got three kids of my own and I just can't fathom how something like that could have happened," she said.
"And you just feel useless because you think living so close, you should've known something was not right.

"My heart definitely goes out to the family that's for sure."
The mother-of-five said it had affected her family, including her children.
"I've just told them it's a tragic accident that shouldn't have happened," she said.
"They've seen the news last night and they know it was two young girls and they've all been a little bit teary but it is a sad thing.
"I think the kids can sort of relate to how a little child would feel in that heat."
Ms Winduss said they were having a birthday cake for one of her daughters when they heard police sirens on Saturday.
"It wasn't until my friend and her son left her phone sitting in the back seat and she brought the phone back in and said to her son, 'mate you can't leave it in the car, it's nearly on fire'," she said.
"That's when we heard all the commotion and police cars flying passed but they were going that fast I didn't think they were going to stop just there."
Police are urging anyone with information to Policelink on 131 444 or Crime Stoppers on 1800 333 000.


All our yarns are spinned from first grade DCH cotton in imported automised machinery to attain superior quality. The quality and counts are very strictly controlled by well trained professionals which is the secret for our success to be as a legend in yarn market. Prompt supply and reasonable rates with no compromise in quality adds value to our success.
All our garments are knitted with 100% combed cotton to suit for all exotic climate & to provide you good comfort and keep you cool. Its good sweat absorbing property always keeps you hygenic and free minded. The fablics are knitted with imported machineries and the processing are undergone in softflow units in eco-friendly zero discharge plants as per govt. regulations. Which give good bleaching and color fastness for all our products. The fabrics are manually checked and cut into pieces and then stiched with imported machines with high graded stiching yarns by well trained persons to give a perfect fit. They are inspected with quality controllers and packed to render defect free products to our valuable customers.
* We also undertake job works.
*For more details of our products visit our Products page or contact us.


A team of supervilLANs has joined forces to organize the most kick-ass LAN-parties in Groningham...
On the 10th, 11th and 12th of April, 2015, the first of such events will be held. You can secure your spot at this event for no more than €13,37, and probably way less.
If all seats for your study association are taken, you may still sign up. You might still be invited if another attendee doesn't show up, or other study associations don't manage to fill up their seats.
The starting time of the event is currently 16:00, on Friday. This may be subject to change.
Register NowSuper Smash Bros.
Brush up on your controller-mashing skills because you can join the Super Smash Bros. competition. Best your oponents in a series of exciting games to win a pretty neat prize!
Team Fortress 2
In this contest, the four study associations send their most skilled players into battle on the whimsical sites of Team Fortress 2. Players are expected to defend the honor of their study association. There is an epic challenge cup at stake, and it is a legend of its own.
Unreal Tournament 2004
This game may know many objectives, but blasting one another to pieces must be the most recurrent one. Pick up those enforcers and lecture your enemy on the topic of pwning.
Don't forget to take your gear:
We're a big team with a broad and diverse set of skills especially useful for organising LAN-parties and other such events. We find our origins in four FMNS study associations:


In this exploration, we consider an L-C circuit that has started in it's ground state. This situation would be the natural starting point for a circuit that hadn't been disturbed in a long time.
We allow for a few possible perturbations and changes, some of which can made before the experiment starts, and some which can be made in the midst of the experiment.
In this circuit, we choose the flux in the primary inductor (L) to be the quantization variable. That means that we will look at the dynamics of the system as if the flux Φ were the position of a particle evolving in a pseudo-potential consisting of the energy stored in the inductor.


| 2023/06 - Present | Assistant Professor @ The Hong Kong University of Science and Technology (Guangzhou), China |
|---|---|
| 2022/12 - 2023/05 | Research Fellow @ National University of Singapore, Singapore |
| 2021/07 - 2021/12 | Research intern @ Sea AI Lab (SAIL), Singapore |
| 2018/11 - 2019/04 | Full-time research assistant @ National University of Singapore, Singapore |
| 2018/01 - 2018/09 | Algorithm engineer intern @ JD.COM, Beijing, China |
| 2017/01 - 2018/01 | Research intern @ Microsoft Research, Beijing, China |
| 2015/12 - 2016/09 | Research intern @ Microsoft Research, Beijing, China |