Post image
Strategy

Finished Catalogue and Label Design For Concrete Products : …


I just wrapped up an exciting project and my client was thrilled with how it turned out! They were looking for a cohesive visual style for their concrete products, resulting in a catalogue design, brochure design, and new product labels. The goal was to make all their collateral unified and have the look of their products match the value of the quality they provide. Check out the full project here!

Post image
Post image
Post image



Source link

Storing sessions in distributed cache
Strategy

ASP.NET Core Session Storage Strategies


Since the HTTP protocol used by web applications is a stateless protocol, data is not stored anywhere; for every web request, a new HTTP connection is opened by the browser. For catering situations in which saving your data is crucial, ASP.NET Core provides sessions for storing user data. This data store is maintained by the ASP.NET Core application itself on the same server as the application. 

Although ASP.NET Core provides an in-memory session provider that stores sessions, sometimes the load needs to be balanced. In these scenarios, session storage strategies, like sticky sessions or distributed cache, come into use.

Sticky Sessions a Big No, Why?

When using sticky sessions, a load balancer is used, and all the user requests are directed to a single server. The main disadvantage of using sticky sessions for your ASP.NET Core application is the improper distribution of load. Sometimes the requests increase to such a level that they completely overload the server responsible for maintaining data. Also, if this server goes down, data may be completely lost, causing a single point of failure.

Storing ASP.NET Core Sessions in Distributed Cache

Distributed cache resolves all the issues faced when using sticky sessions. A distributed cache is a cache store used by multiple application servers, typically maintained as an external service for keeping and accessing data. The major advantage of a distributed cache is that it not only increases scalability but also increases the performance of an ASP.NET Core Application. The diagram below shows how a distributed cache serves its purpose for storing sessions. Multiple servers can be added in the distributed cache cluster, making it linearly scalable. Users communicate with the ASP.NET Core web farm through a load balancer. The web farm further uses a distributed cache for storing sessions services provider.

Storing sessions in distributed cache

Storing sessions in distributed cache

ASP.NET Core’s Default IDistributedCache Interface

IDistributedCache interface is provided by Microsoft for integrating a distributed cache in ASP.NET Core applications. The application interacts with the cache using this interface regardless of the cache implementation being used. Here is how you can configure your session store provider through IDistributedCache.

Note: All of these methods have an async overload as well.

Using the IDistributedCache

Here is a small example to help you understand how to use the IDistributed cache.

IDistributedCache Interface Limitations

There are certain limitations when using the IDistributedCache interface. ASP.NET Core session implementation omitted a few features that were previously supported in ASP.NET Core Session State. These include:

  1. Session Locking.
  2. Byte [] for Custom Objects.

Apart from these, if you implement the IDistributedCache interface for your ASP.NET Core application, you would not have various cache features that you get by using an implementation provided by a distributed cache solution such as NCache.

ASP.NET Core Session Provider for Distributed Cache

Distributed cache, such as NCache, provides an easy to use implementation for session storage. This not only saves your time in writing your own provider but also gives you access to various distributed cache features. Distributed cache (NCache) also tackles limitations of IDistributedCache mentioned above. It provides an internal session locking mechanism and also supports custom objects.

Configuring Session Provider for Distributed Cache

For configuration of the session provider for distributed cache, there is less programming effort required. Distributed cache, such as NCache, allows you to configure its provider by either configuring all settings in Startup.cs class or by reading them through theAppSettings.json file in your ASP.NET Core application.

The following example shows how to configure a distributed cache (NCache) provider in the Startup.cs class of your ASP.NET Core application:

Using Distributed Cache With ASP.NET Core Sessions

After successful configuration of distributed cache (NCache) for storing sessions, you can easily use it in your ASP.NET Core application for Read and Write operations. The following block of code represents how to fetch an item from the cache and how to insert an item in it.

Conclusion

For configuring NCache Session Provider for ASP.NET Core applications, very little coding is required. It is very easy to configure and you do not have to write very long code snippets. Apart from this, NCache provides other benefits including:

  • High Availability.
  • Linearly Scalable.
  • Intelligent Session Replication.
  • Fast Dynamic Compact Serialization.

To sum it all up, NCache is not only fast but scalable. It is purely native .NET, which makes it very feasible for fitting in your .NET application stack.

Further Reading



Source link

How Reactive Threads Works (Part 1)
Strategy

How Reactive Threads Works (Part 1)


Reactive or non-blocking processing is in high demand, but before adopting it, you should understand its thread model. For a thread model, two things are very important: knowing thread communication and execution flows. In this article, I will try to go in-depth for both these aspects.

What Is Reactive Programming?

There are several definitions on the web. The Wiki definition is a bit theoretical and generic. From a threading perspective, my version is Reactive Programming is the processing of the asynchronous event stream on which you can observe”                                                                    

You can find much more discussion about reactive programming on the web, but for now, let’s stick to our topic of Reactive Thread Models. Let’s start with a very simple reactive use case, where we want to return the sum of an integer array. What this means is that our main request thread should not get blocked while processing the sum of an integer array. 

You might also like: Understanding Reactor Pattern: Thread-Based and Event-Driven

Let’s start by creating a simple WebServer and trying to depict the same.

Here, we are creating a socket server, opening a socket, and keeping the socket alive until the asynchronous processing is complete. Asynchronous processing is happening by calling the nonBlockingSum and passing the consumer function or lambada as observable. Once the sum is ready, our function/lambada will get a callback. From callback, we return the sum value to the client via socket.

So if you call the URL, http://localhost:9090, in parallel/sequence, you will get the following response:

The above is just to depict the reactive stuff. You should use netty/undertow/servlet 3.1 as the reactive webserver. Now let’s get somewhat deep and try to understand the following flows:

  1. Blocking Call
  2. Non blocking call
  3. Non blocking call with thread execution
  4. Serial business flow processing
  5. Parallel business flow processing

We are going to use the Spring WebFlux, which is built on top of the Reactor framework for reactive programming. Let’s cover sections 1 and 2 in this article and other sections in Part 2 so that it will be very easy to understand.

We are going to write a simple sum method and make it reactive using the supplier function.

1) Blocking Call

As shown in the diagram, the request thread is getting blocked until the computation of the sum is completed. If we execute, the code will get the following response:

This clearly shows that the blocking call waited until the sum execution was completed.

2) Non Blocking Call

Here, the request thread is not blocked, and the execution of the sum is shifted to a thread allocated from the thread pool. Callback and function/lambada is also executed on the same thread. If we execute, the code will get the following response:

This clearly shows that the request thread didn’t wait until the sum was computed. Also, the consumer and sum were processed in the same thread.

Section 3, 4 and 5 will be covered in Part 2, and you can get the code on GitHub.

Further Reading

What Does It Mean to Be ‘Reactive?’

Is Spring Reactive Already Obsolete? A Look at Inversion of Thread Coupling



Source link

Connect to a MongoDB Database Using Node.js
Strategy

Connect to a MongoDB Database Using Node.js


Use Node.js? Want to learn MongoDB? This is the series for you!

In this Quick-Start series, I’ll walk you through the basics of how to get started using MongoDB with Node.js. In today’s post, we’ll work through connecting to a MongoDB database from a Node.js script, retrieving a list of databases, and printing the results to your console.

Set Up

Before we begin, we need to ensure you’ve completed a few prerequisite steps.

Install Node.js

First, make sure you have a supported version of Node.js installed (the MongoDB Node.js Driver requires Node 4.x or greater and for these examples, I’ve used Node.js 10.16.3).

You might also like: Use MongoDB Node.js Native Driver Without Mongoose

Install the MongoDB Node.js Driver

The MongoDB Node.js Driver allows you to easily interact with MongoDB databases from within Node.js applications. You’ll need the driver in order to connect to your database and execute the queries described in this Quick Start series.

If you don’t have the MongoDB Node.js Driver installed, you can install it with the following command.

At the time of writing, this installed version 3.3.2 of the driver. Running npm list mongodb will display the currently installed driver version number. For more details on the driver and installation, see the official documentation.

Create a Free MongoDB Atlas Cluster and Load the Sample Data

Next, you’ll need a MongoDB database. Your database will be stored inside of a cluster. At a high level, a cluster is a set of nodes where copies of your database will be stored.

The easiest way to get started with MongoDB is to use Atlas, MongoDB’s fully-managed database-as-a-service. Head over to Atlas and create a new cluster in the free tier. Once your tier is created, load the sample data.

Get started with an M0 cluster on Atlas today. It’s free forever, and it’s the easiest way to try out the steps in this blog series.

If you’re not familiar with how to create a new cluster and load the sample data, check out this video tutorial from MongoDB Developer Advocate Maxime Beugnet.

Get Your Cluster’s Connection Info

The final step is to prep your cluster for connection.

In Atlas, navigate to your cluster and click CONNECT. The Cluster Connection Wizard will appear.

The Wizard will prompt you to whitelist your current IP address and create a MongoDB user if you haven’t already done so. Be sure to note the username and password you use for the new MongoDB user as you’ll need them in a later step.

Next, the Wizard will prompt you to choose a connection method. Select Connect Your Application. When the Wizard prompts you to select your driver version, select Node.js and 3.0 or later. Copy the provided connection string.

For more details on how to access the Connection Wizard and complete the steps described above, see the official documentation.

Connect to Your Database From a Node.js Application

Now that everything is set up, it’s time to code! Let’s write a Node.js script that connects to your database and lists the databases in your cluster.

Import MongoClient

The MongoDB module exports MongoClient, and that’s what we’ll use to connect to a MongoDB database. We can use an instance of MongoClient to connect to a cluster, access the database in that cluster, and close the connection to that cluster.

Create Our Main Function

Let’s create an asynchronous function named main() where we will connect to our MongoDB cluster, call functions that query our database, and disconnect from our cluster.

The first thing we need to do inside of main() is create a constant for our connection URI. The connection URI is the connection string you copied in Atlas in the previous section. When you paste the connection string, don’t forget to update <username> and <password> to be the credentials for the user you created in the previous section. Note: the username and password you provide in the connection string are NOT the same as your Atlas credentials.

Now that we have our URI, we can create an instance of MongoClient.

Note: When you run this code, you may see DeprecationWarnings around the URL string parser and the Server Discover and Monitoring engine. If you see these warnings, you can remove them by passing options to the MongoClient. For example, you could instantiate MongoClient by calling  new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }). See the Node.js MongoDB Driver API documentation for more information on these options.

Now we’re ready to use MongoClient to connect to our cluster. client.connect() will return a promise. We will use the await keyword when we call client.connect() to indicate that we should block further execution until that operation has completed.

Now we are ready to interact with our database. Let’s build a function that prints the names of the databases in this cluster. It’s often useful to contain this logic in well named functions in order to improve the readability of your codebase. Throughout this series, we’ll create new functions similar to the function we’re creating here as we learn how to write different types of queries. For now, let’s call a function named listDatabases().

Let’s wrap our calls to functions that interact with the database in a try/catch statement so that we handle any unexpected errors.

We want to be sure we close the connection to our cluster, so we’ll end our try/catch with a finally statement.

Once we have our main() function written, we need to call it. Let’s send the errors to the console.

Putting it all together, our main() function and our call to it will look something like the following.

List the Databases in Our Cluster

In the previous section, we referenced the listDatabases() function. Let’s implement it!

This function will retrieve a list of databases in our cluster and print the results in the console.

Save Your File

You’ve been implementing a lot of code. Save your changes, and name your file something like connection.js. To see a copy of the complete file, visit the nodejs-quickstart GitHub repo.

Execute Your Node.js Script

Now you’re ready to test your code! Execute your script by running a command like the following in your terminal: node connection.js

You will see output like the following:

What’s Next?

Today, you were able to connect to a MongoDB database from a Node.js script, retrieve a list of databases in your cluster, and view the results in your console. Nice!

In future posts in this series, we’ll dive into each of the CRUD (create, read, update, and delete) operations as well as topics like change streams, transactions, and the aggregation pipeline, so you’ll have the tools you need to successfully interact with data in your databases.

Series Versions

The examples in this article were created with the following application versions:

Stay tuned for the rest of the series!

Further Reading

Building MongoDB Dashboard Using Node.js

Intro to MongoDB



Source link

ballerina-on-bridge-in-woods
Strategy

Developing Ballerina Project With Ballerina CLI Tool


ballerina-on-bridge-in-woods

Ballerina is a general-purpose programming language particularly intended for the implementation of distributed network applications. Ballerina has built-in modules to build a distributed web application with only a few lines of code. Ballerina provides a CLI tool for the maintenance of your Ballerina project. This article is a brief introduction to the Ballerina CLI tool and how it was used.

You can download Ballerina distribution from the official Ballerina website. You can begin writing a Ballerina program once you download and install it. You can check the version of the ballerina installation by executing the following command.

ballerina version

This command prints the installed version of the Ballerina. You can also check the Ballerina installed folder by running the following command.

ballerina home

You may also like: Data Integration With Ballerina

Creating a New Ballerina Project Using CLI

You can use the following Ballerina CLI command to create a new Ballerina project. This command creates a new folder containing the Ballerina.toml file and the src directory. All of your Ballerina descriptions and dependencies are included in this Ballerina.toml file.

ballerina new <project-name>

Now, you can begin working on your project in the freshly created Ballerina project. The following command generates a module to begin writing your own Ballerina code. You should change the current directory to the Ballerina project folder to perform this command.

ballerina add <module-name>

This command generates the Ballerina folder structure inside the Ballerina module along with the Hello World Code sample in Ballerina. <project_home>/src/<module_name>/main.bal becomes the main entry point for your application.

Tests for the module should be placed inside <project_home>/src/<module_name>/tests/ the directory. The “Hello, World” program in the main.bal is as follows: 

import ballerina/io;

public function main() {
    io:println("Hello World!");
}

You can build the project together with the test by running the following command. You can prevent running test cases by adding the —skip-test option at the end of the build command.

ballerina build <module-name>

The build command builds the source code and converts it into a Java program in the <project_home>/target/bin/ folder. If you inspect this folder, you can see a jar file with the name of the module. You can run this jar file on JVM the same way you run the standard Java program.

If you need to run a module without building, you can try the following command. Here, you can run either the module or the Ballerina file.

ballerina run {<bal-file> | <module-name>}

Ballerina keep cache inside the Ballerina project. It keeps following caches in-order to speed up the building process.

  • BALO files fetched from Central.
  • BIR files generated during the compilation.
  • JAR file generated during the compilation

By executing the following command, Ballerina clears the cache inside the ballerina project.

ballerina clean

You can run tests only with the Ballerina program by running the following command. You can test the whole module by adding the -a  option, or you can only test the particular module by specifying the name of the module.

ballerina test <module-name>

Collaborate With Others Through the Ballerina Central

Ballerina Central landing page

Ballerina Central landing page

Ballerina Central is the main place where developers can share their software with other developers. Ballerina Central functions the same way that git works. By pushing the modules, you can upload your modules to Ballerina Central. In the same way, you can use the module constructed by others by pulling modules. You can browse the available modules on the Ballerina Central website.

The following command can be used to search for a Ballerina module by using CLI instead of searching from Ballerina central website.

ballerina search <key-word>

Once you list the necessary module, you can pull the module into your project by running the following command.

ballerina pull <org-name>/<module-name>[:<version>]

The organization name is a logical name used for grouping modules under a common namespace. For instance, you can take the Twitter module that can be used to access the Twitter API by running the following command.

ballerina pull wso2/twitter:0.9.26

You can use a twitter client to write a simple Ballerina code as follows to send a tweet.

import wso2/twitter;

twitter:TwitterConfiguration twitterConfig = {
    clientId: testClientId,
    clientSecret: testClientSecret,
    accessToken: testAccessToken,
    accessTokenSecret: testAccessTokenSecret,
    clientConfig: { secureSocket: {
                        trustStore: {
                            path: "${ballerina.home}/bre/security/ballerinaTruststore.p12",
                            password: "ballerina"
                        }
                    }
                  }
};

public function main() {
twitter:Client twitterClient = new(twitterConfig);

string status = "Twitter endpoint test";
    var result = twitterClient->tweet(status);
    if (result is twitter:Status) {
        // If successful, print the tweet ID and text.
        io:println("Tweet ID: ", result.id);
        io:println("Tweet: ", result.text);
    } else {
        // If unsuccessful, print the error returned.
        io:println("Error: ", result);
    }
}

If you need to publish a module in Ballerina Central, you need to create an account in Ballerina Central. Then you can get a secret token and put it into the <USER_HOME>/.ballerina/Settings.toml file. Always remember to set organization name correctly in Ballerina.toml file in your <project_home>.

Secure Passwords With Ballerina Encrypt Command

In some scenarios, you may need to use a password inside your code. Assume, for example, that you need to create a Twitter bot. Here, we just keep security tokens as plain text inside the code itself. But keeping a password inside the code is a bad practice, as it reveals a password to someone else who can see your source code. Ballerina provides support to hide your password from the source code and only reveal it during runtime.

To encrypt a value, you need to run the following command first. This command first asks for a value to be encrypted. Then, you can ask for a password and verify that password.

ballerina encrypt

This command generates an encrypted value using the CBC mode with the AES method. You can now read the secret value from the source code as follows.

import ballerina/io;
import ballerina/config;

public function main() {
    io:println(config:getAsString("secret.password"));
}

Here, we use the config module to read the config file. secret.password is an alias for the real value. When this application is running, you should provide an encrypted value as a command line argument.

ballerina run sample --secret.password="@encrypted:{MOT+c6216tQLzSxiDfXclFg75q1ktY6+3VlCa6uhn40=}"

When Ballerina starts running, ask for a password. Use the password you used to encrypt the value. This program will print the word you set with the ballerina encrypt command.

Conclusion

In this blog post, we’ve gone through the CLI features provided by the Ballerina. You can easily create, build and test Ballerina projects using the Ballerina CLI. Ballerina Central can be used to re-use modules developed by other Ballerina developers. You can also share your module with others. 

Related Articles



Source link

breakout
Strategy

Fluid Width Video | CSS-Tricks


IN A WORLD of responsive and fluid layouts on the web, ONE MEDIA TYPE stands in the way of perfect harmony: video. There are lots of ways in which video can be displayed on your site. You might be self-hosting the video and presenting it via the HTML5 <video> tag. You might be using YouTube, Vimeo, or some other video provider that provides <iframe> code to display videos. Let’s cover how to make them all fluid width while maintaining an appropriate height based on their aspect ratio.

In each of these video-embedding scenarios, it is very common for a static width and height to be declared.

<video width="400" height="300" controls ... ></video>

<iframe width="400" height="300" ... ></iframe>

<!-- maybe even super old school -->
<object width="400" height="300" ... />
<embed width="400" height="300" ... />

Guess what? Declaring static widths isn’t a good idea in fluid width environments. What if the parent container for that video shrinks narrower than the declared 400px? It will bust out and probably look ridiculous and embarrassing.

breakout
Simple and contrived, but still ridiculous and embarassing.

So can’t we just do this?

<video width="100%" ... ></video>

Well, yep, you can! If you are using standard HTML5 video, that will make the video fit the width of the container. It’s important that you remove the height declaration when you do this so that the aspect ratio of the video is maintained as it grows and shrinks, lest you get awkward “bars” to fill the empty space (unlike images, the actual video maintains it’s aspect ratio regardless of the size of the element).

You can get there via CSS (and not worry about what’s declared in the HTML) like this:

video {
  /* override other styles to make responsive */
  width: 100%    !important;
  height: auto   !important;
}

<iframe> Video (YouTube, Vimeo, etc.)

Our little trick from above isn’t going to help us when dealing with video that is delivered via <iframe>. Forcing the width to 100% is effective, but when we set height: auto, we end up with a static height of 150px1, which is far too squat for most video and makes for more R&E (Ridiculous and Embarrassing).

Fortunately, there are a couple of possible solutions here. One of them was pioneered by Thierry Koblentz and presented on A List Apart in 2009: Creating Intrinsic Ratios for Video. With this technique, you wrap the video in another element which has an intrinsic aspect ratio, then absolute position the video within that. That gives us fluid width with a reasonable height we can count on.

<div class="videoWrapper">
  <!-- Copy & Pasted from YouTube -->
  <iframe width="560" height="349" src="http://www.youtube.com/embed/n_dZNLr2cME?rel=0&hd=1" frameborder="0" allowfullscreen></iframe>
</div>
.videoWrapper {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 */
  height: 0;
}
.videoWrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

There is a clever adaptation of this that allows you to adjust the aspect ratio right from the HTML, like:

<div class="videoWrapper" style="--aspect-ratio: 3 / 4;">
  <iframe ...>
.videoWrapper {
  ...
  /* falls back to 16/9, but otherwise uses ratio from HTML */
  padding-bottom: calc(var(--aspect-ratio, .5625) * 100%); 
}

Some old school video embedding uses <object> and <embed> tags, so if you’re trying to be comprehensive, update that wrapper selector to:

.videoWrapper iframe,
.videoWrapper embed,
.videoWrapper object { }

But, but… aspect ratios, legacy content, non-tech users, etc.

The above technique is awesome, but it has several possible limitations:

  1. It requires a wrapper element, so just straight up copy-and-pasting code from YouTube is out. Users will need to be a bit savvier.
  2. If you have legacy content and are redesigning to be fluid, all old videos need HTML adjustments.
  3. All videos need to be the same aspect ratio. Otherwise, they’ll be forced into a different aspect ratio and you’ll get the “bars”. Or, you’ll need a toolbox of class names you can apply to adjust it which is an additional complication.

If either of these limitations applies to you, you might consider a JavaScript solution.

Imagine this: when the page loads all videos are looked at and their aspect ratio is saved. Once right away, and whenever the window is resized, all the videos are resized to fill the available width and maintain their aspect ratio. Using the jQuery JavaScript Library, that looks like this:

// Find all YouTube videos
// Expand that selector for Vimeo and whatever else
var $allVideos = $("iframe[src^='//www.youtube.com']"),

  // The element that is fluid width
  $fluidEl = $("body");

// Figure out and save aspect ratio for each video
$allVideos.each(function() {

  $(this)
    .data('aspectRatio', this.height / this.width)

    // and remove the hard coded width/height
    .removeAttr('height')
    .removeAttr('width');

});

// When the window is resized
$(window).resize(function() {

  var newWidth = $fluidEl.width();

  // Resize all videos according to their own aspect ratio
  $allVideos.each(function() {

    var $el = $(this);
    $el
      .width(newWidth)
      .height(newWidth * $el.data('aspectRatio'));

  });

// Kick off one resize to fix all videos on page load
}).resize();

That’s sorta what became FitVids.js

Except rather than deal with all that resizing business, FitVids.js loops over all the videos and adds the aspect-ratio enabling HTML wrapper and CSS necessary. That’s way more efficient than needing to bind to a window resize handler!

Plain JavaScript instead

jQuery is rather out of favor these days. Fortunately, Dave has a Vanilla version (that is BYO CSS):



Source link

shared components library
Strategy

How to Effectively Maintain CSS in a Large Application


In this article, I’ll cover one of the ways how CSS maintenance can be achieved. Don’t take it as a single right way of doing it, I’m only going to share which approach works for me and is proven to be good scaled and shared between several projects.

Before diving into details let’s have a look at this picture and see how several large UI products can be built inside of the single organization. They use custom components and share them between products, to give them the same look and feel and gain performance in development, as problems have to be solved only once and can be reused across products.

You may also like: How to Deal With CSS Issues in IE When You Have No Idea How to Fix Them

shared components library

What do we have here? For simplicity, we only have one shared library of components and two different applications/products in the organization. We have two shared components as the date component and the scheduler component. Which are designed in a specific way and we would like to give them custom configurable behavior, that’s why we even created them.

Currently, in application A only Date component is used and in application B both components are utilized.

What kind of things we can do to make our products looking similar? Of course, styles have to be shared! Every default component has to look the same, colors across products should be also identical. What can we do for that? First of all, I recommend using in any project reset.css , you can find a lot of examples on the internet, that’s one of them https://meyerweb.com/eric/tools/css/reset/. After that, we have to define all styles/rules for all components in organisation.(css|less|sass) file. 

 Once it’s finished the rest of the components have to contain isolated styles, so it can be reused in different projects and don’t affect the behavior of adjusted or parent components. One of the things how to achieve it is to give unique identifiers. I’ll give an example of how to do it with LESS:

It is achieved by creating a hierarchy of styles, so that means datepicker_navigation--next will be applied only inside of custom-date-component component. As the component name also prepended with the name of the library, it makes the chance of class duplication close to zero.

To make the navigation by styles fast, it’s better to use the same name for the component, file name, and CSS class name.

If you start messing with names, you will be in a situation to do unnecessary navigations to figure out which classname relates to which component. Even if you use some generic styles for components, better keep the same strategy and locate the common classname inside.

Now let’s imagine that you need to add the same Admin page for application A which already exists for application B. By abiding by the same strategy inside of the application by keeping each block in isolated style will make that sharing of components easy.

What to do if Date component in application B has extra styling needed — you keep that override inside of .application-b  class name.

In that case all styles from .custom-date-component and on top of that color  is overridden only for application B. Even when Admin page is added to application A styles going to be in shape, as a red color only will be applied for application B. If you need to do it for Admin page, not application related, then you do override of .admin-page  not .application-b

Note: One common mistake which I always see, keep all such overrides related to a component, not higher to hierarchy, not lower. If you do this:

Keep it inside of Admin Page Component, not application B project globally, or some parent component. Otherwise, you start losing control of what comes from where and there would be no reusability. As just locating the same component in another project will require digging, finding the missing styles which have to be picked up from other places.

 Recap of the most important rules:

  • Keep all global styles in a separate file.
  • Keep styles of components(pages, layouts) in isolation all the time.
  • Keep the same name across the javascript file name, component name, style file name, and style class name.

These simple rules will make your system effectively maintain and scale. As it will have predictable behavior what is super important on a scale. Navigation to the proper place in code with minimum effort, which will play a great role in your overall performance. When the application grows it’s hard to remember all details and you have constantly navigated through the code.

You might think of, that’s super simple! Yes, it is! But you can’t imagine how hard to keep everybody on the same page and keep track that the process is to keep following it. Take the process seriously on the review process of pull requests and do train new people when they join a project.

Looking forward to your comments and feedback. Feel free also to share your way of working with styles in a large application.

Further Reading

Scale Your Frontend Application

DRYing Up CSS

CSS Position: Relative vs Position Absolute



Source link

Post image
Strategy

What’s causing these gaps in the performance profiler? : web…


I’m writing a React application that is parsing a small csv file (26rows x 8 cols) that is shown in a table.

When I select the file to parse everything hangs for a couple of hundred milliseconds. I’ve tried running this multiple times, and some times it’s really quick, and some not so much…

So I check the performance profiler in Firefox to see if I can figure out what is taking so long, and I see this:

Post image

As you can see there are two large holes where seemingly no work is being done. Can someone explain why it behaves like this? Is something else happening that just isn’t showing up in the chart or how can that happen?



Source link

How to Make a Line Chart With CSS
Strategy

How to Make a Line Chart With CSS


Line,  bar, and pie charts are the bread and butter of dashboards and are the basic components of any data visualization toolkit. Sure, you can use SVG or a JavaScript chart library like Chart.js or a complex tool like D3 to create those charts, but what if you don’t want to load yet another library into your already performance-challenged website?

There are plenty of articles out there for creating CSS-only bar charts, column charts, and pie charts, but if you just want a basic line chart, you’re out of luck. While CSS can “draw lines” with borders and the like, there is no clear method for drawing a line from one point to another on an X and Y coordinate plane. 

Well, there is a way! If all you need is a simple line chart, there’s no need to load in a huge JavaScript library or even reach for SVG. You can make everything you need with just CSS and a couple of custom properties in your HTML. Word of warning, though. It does involve a bit of trigonometry. If that didn’t scare you off, then roll up your shirt sleeves, and let’s get started!

Here’s a peek at where we’re headed:

Let’s start with the baseline

If you are creating a line chart by hand (as in, literally drawing lines on a piece of graph paper), you would start by creating the points, then connecting those points to make the lines. If you break the process down like that, you can recreate any basic line chart in CSS. 

Let’s say we have an array of data to display points on an X and Y coordinate system, where days of the week fall along the X-axis and the numeric values represent points on the Y-axis.

[
  { value: 25, dimension: "Monday" },
  { value: 60, dimension: "Tuesday" },
  { value: 45, dimension: "Wednesday" },
  { value: 50, dimension: "Thursday" },
  { value: 40, dimension: "Friday" }
]

Let’s create an unordered list to hold our data points and apply some styles to it. Here’s our HTML:

<figure class="css-chart" style="--widget-size: 200px;">
  <ul class="line-chart">
    <li>
      <div class="data-point" data-value="25"></div>
    </li>
    <li>
      <div class="data-point" data-value="60"></div>
    </li>
    <li>
      <div class="data-point" data-value="45"></div>
    </li>
    <li>
      <div class="data-point" data-value="50"></div>
    </li>
    <li>
      <div class="data-point" data-value="40"></div>
    </li>
  </ul>
</figure>

A couple notes to glean here. First is that we’re wrapping everything in a <figure> element, which is a nice semantic HTML way of saying this is self-contained content, which also provides us the optional benefit of using a <figcaption>, should we need it. Secondly, notice that we’re storing the values in a data attribute we’re calling data-value that’s contained in its own div inside a list item in the unordered list. Why are we using a separate div instead of putting the class and attribute on the list items themselves? It’ll help us later when we get to drawing lines.

Lastly, note that we have an inlined custom property on the parent <figure>  element that we’re calling --widget-size. We’ll use that in the CSS, which is going to look like this:

/* The parent element */
.css-chart {
  /* The chart borders */
  border-bottom: 1px solid;
  border-left: 1px solid;
  /* The height, which is initially defined in the HTML */
  height: var(--widget-size);
  /* A little breathing room should there be others items around the chart */
  margin: 1em;
  /* Remove any padding so we have as much space to work with inside the element */
  padding: 0;
  position: relative;
  /* The chart width, as defined in the HTML */
  width: var(--widget-size);
}


/* The unordered list holding the data points, no list styling and no spacing */
.line-chart {
  list-style: none;
  margin: 0;
  padding: 0;
}


/* Each point on the chart, each a 12px circle with a light border */
.data-point {
  background-color: white;
  border: 2px solid lightblue;
  border-radius: 50%;
  height: 12px;
  position: absolute;
  width: 12px;
}

The above HTML and CSS will give us this not-so-exciting starting point:

Well, it sort of looks like a chart.

Rendering data points

That doesn’t look like much yet. We need a way to draw each data point at its respective X and Y coordinate on our soon-to-be chart. In our CSS, we’ve set the .data-point class to use absolute positioning and we set a fixed width and height on its parent .css-chart container with a custom property. We can use that to calculate our X and Y positions.

Our custom property sets the chart height at 200px and, in our values array, the largest value is 60. If we set that data point as the highest point on the chart’s Y axis at 200px, then we can use the ratio of any value in our data set to 60 and multiply that by 200 to get the Y coordinate of all of our points. So our largest value of 60 will have a Y value that can be calculated like this:

(60 / 60) * 200 = 200px 

And our smallest value of 25 will end up with a Y value calculated the same way:

(25 / 60) * 200 = 83.33333333333334px

Getting the Y coordinate for each data point is easier. If we are spacing the points equally across the graph, then we can divide the width of the chart (200px) by the number of values in our data array (5) to get 40px. That means the first value will have an X coordinate of 40px (to leave a margin for a left axis if we want one), and the last value will have an X coordinate of 200px.

You just got mathed! 🤓

For now, let’s add inline styles to each of the divs in the list items. Our new HTML becomes this, where the inline styles contain the calculated positioning for each point.

<figure class="css-chart">
  <ul class="line-chart">
    <li>
      <div class="data-point" data-value="25" style="bottom: 83.33333333333334px; left: 40px;"></div>
    </li>
    <li>
      <div class="data-point" data-value="60" style="bottom: 200px; left: 80px;"></div>
    </li>
    <li>
      <div class="data-point" data-value="45" style="bottom: 150px; left: 120px;"></div>
    </li>
    <li>
      <div class="data-point" data-value="50" style="bottom: 166.66666666666669pxpx; left: 160px;"></div>
    </li>
    <li>
      <div class="data-point" data-value="40" style="bottom: 133.33333333333331px; left: 200px;"></div>
    </li>
  </ul>
</figure>
We have a chart!

Hey, that looks a lot better! But even though you can see where this is going, you still can’t really call this a line graph. No problem. We only need to use a little more math to finish our game of connect-the-dots. Take a look at the picture of our rendered data points again. Can you see the triangles that connect them? If not, maybe this next picture will help:

Why is that important? Shhh, the answer’s coming up next.

Rendering line segments

See the triangles now? And they’re not just any old triangles. They’re the best kind of triangles (for our purposes anyway) because they are right triangles! When we calculated the Y coordinates of our data points earlier, we were also calculating the length of one leg of our right triangle (i.e. the “run” if you think of it as a stair step). If we calculate the difference in the X coordinate from one point to the next, that will tell us the length of another side of our right triangle (i.e. the “rise” of a stair step). And with those two pieces of information, we can calculate the length of the magical hypotenuse which, as it turns out, is exactly what we need to draw to the screen in order to connect our dots and make a real line chart.

For example, let’s take the second and third points on the chart.

<!-- ... --> 


<li>
  <div class="data-point" data-value="60" style="bottom: 200px; left: 80px;"></div>
</li>
<li>
  <div class="data-point" data-value="45" style="bottom: 150px; left: 120px;"></div>
</li>


<!-- ... -->

The second data point has a Y value of 200 and the third data point has a Y value of 150, so the opposite side of the triangle connecting them has a length of 200 minus 150, or 50. It has an adjacent side that is 40 pixels long (the amount of spacing we put between each of our points).

That means the length of the hypotenuse is the square root of 50 squared plus 40 squared, or 64.03124237432849.

The hypotenuse is what we need to draw our line graph

Let’s create another div inside of each list item in the chart that will serve as the hypotenuse of a triangle drawn from that point. Then we’ll set an inline custom property on our new div that contains the length of that hypotenuse.

<!-- ... -->


<li>
  <div class="data-point" data-value="60"></div>
  <div class="line-segment" style="--hypotenuse: 64.03124237432849;"></div>
</li>


<!-- ... -->

While we’re at it, our line segments are going to need to know their proper X and Y coordinates, so let’s remove the inline styles from our .data-point elements and add CSS custom properties to their parent (the <li> element) instead. Let’s call these properties, creatively, --x and --y. Our data points don’t need to know about the hypotenuse (the length of our line segment), so we can add a CSS custom property for the length of the hypotenuse directly to our .line-segment. So now our HTML will look like this:

<!-- ... -->


<li style="--y: 200px; --x: 80px">
  <div class="data-point" data-value="60"></div>
  <div class="line-segment" style="--hypotenuse: 64.03124237432849;"></div>
</li>


<!-- ... -->

We’ll need to update our CSS to position the data points with those new custom properties and style up the new .line-segment div we added to the markup:

.data-point {
  /* Same as before */


  bottom: var(--y);
  left: var(--x);
}


.line-segment {
  background-color: blue;
  bottom: var(--y);
  height: 3px;
  left: var(--x);
  position: absolute;
  width: calc(var(--hypotenuse) * 1px);
}
We have all of the parts now. They just don’t fit together correctly yet.

Well, we have line segments now but this isn’t at all what we want. To get a functional line chart, we need to apply a transformation. But first, let’s fix a couple of things.

First off, our line segments line up with the bottom of our data points, but we want the origin of the line segments to be the center of the data point circles. We can fix that with a quick CSS change to our .data-point styles. We need to adjust their X and Y position to account for both the size of the data point and its border as well as the width of the line segment.

.data-point {
  /* ... */


  /* The data points have a radius of 8px and the line segment has a width of 3px, 
    so we split the difference to center the data points on the line segment origins */
  bottom: calc(var(--y) - 6.5px);
  left: calc(var(--x) - 9.5px);
}

Secondly, our line segments are being rendered on top of the data points instead of behind them. We can address that by putting the line segment first in our HTML:

<!-- ... -->


<li style="--y: 200px; --x: 80px">
    <div class="line-segment" style="--hypotenuse: 64.03124237432849;"></div>
    <div class="data-point" data-value="60"></div>
</li>


<!-- ... -->

Applying transforms, FTW

We’ve almost got it now. We just need to do one last bit of math. Specifically, we need to find the measure of the angle that faces the opposite side of our right triangle and then rotate our line segment by that same number of degrees.

How do we do that? Trigonometry! You may recall the little mnemonic trick to remember how sine, cosine and tangent are calculated:

  • SOH (Sine = Opposite over Hypotenuse
  • CAH (Cosine = Adjacent over Hypotenuse)
  • TOA (Tangent = Opposite over Adjacent)

You can use any of them because we know the length of all three sides of our right triangle. I picked sine, so that that leaves us with this equation:

sin(x) = Opposite / Hypotenuse

The answer to that equation will tell us how to rotate each line segment to have it connect to the next data point. We can quickly do this in JavaScript using Math.asin(Opposite / Hypotenuse). It will give us the answer in radians though, so we’ll need to multiply the result by (180 / Math.PI).

Using the example of our second data point from earlier, we already worked out that the opposite side has a length of 50 and the hypotenuse has a length of 64.03124237432849, so we can re-write our equation like this:

sin(x) = 50 /  64.03124237432849 = 51.34019174590991

That’s the angle we’re looking for! We need to solve that equation for each of our data points and then pass the value as a CSS custom property on our .line-segment elements. That will give us HTML that looks like this:

<!-- ... -->


<li style="--y: 200px; --x: 80px">
  <div class="data-point" data-value="60"></div>
  <div class="line-segment" style="--hypotenuse: 64.03124237432849; --angle: 51.34019174590991;"></div>
</li>


<!-- ... -->

And here’s where we can apply those properties in the CSS:

.line-segment {
  /* ... */
  transform: rotate(calc(var(--angle) * 1deg));
  width: calc(var(--hypotenuse) * 1px);
}

Now when we render that, we have our line segments!

Well, the line segments are definitely rotated. We need one more step.

Wait, what? Our line segments are all over the place. What now? Oh, right. By default, transform: rotate() rotates around the center of the transformed element. We want the rotation to occur from the bottom-left corner to angle away from our current data point to the next one. That means we need to set one more CSS property on our .line-segment class.

.line-segment {
  /* ... */
  transform: rotate(calc(var(--angle) * 1deg));
  transform-origin: left bottom;
  width: calc(var(--hypotenuse) * 1px);
}

And, now when we render it, we finally get the CSS-only line graph we’ve been waiting for.

At last! A line graph!

Important note: When you calculate the value of the opposite side (the “rise”), make sure it’s calculated as the “Y position of the current data point” minus the “Y position of the next data point.” That will result in a negative value when the next data point is a larger value (higher up on the graph) than the current data point which will result in a negative rotation. That’s how we ensure the line slopes upwards.

When to use this kind of chart

This approach is great for a simple static site or for a dynamic site that uses server-side generated content. Of course, it can also be used on a site with client-side dynamically generated content, but then you are back to running JavaScript on the client. The CodePen at the top of this post shows an example of client-side dynamic generation of this line chart.

The CSS calc() function is highly useful, but it can’t calculate sine, cosine, and tangent for us. That means you’d have to either calculate your values by hand or write a quick function (client-side or server-side) to generate the needed values (X, Y, hypotenuse and angle) for our CSS custom properties.

I know some of you got through this and will feel like it’s not vanilla CSS if it requires a script to calculate the values — and that’s fair. The point is that all of the chart rendering is done in CSS. The data points and the lines that connect them are all done with HTML elements and CSS that works beautifully, even in a statically rendered environment with no JavaScript enabled. And perhaps more importantly, there’s no need to download yet another bloated library just to render a simple line graph on your page.

Potential improvements

As with anything, there’s always something we can do to take things to the next level. In this case, I think there are three areas where this approach could be improved.

Responsiveness

The approach I’ve outlined uses a fixed size for the chart dimensions, which is exactly what we don’t want in a responsive design. We can work around this limitation if we can run JavaScript on the client. Instead of hard-coding our chart size, we can set a CSS custom property (remember our --widget-size property?), base all of the calculations on it, and update that property when the container or window either initially displays or resizes using some form of a container query or a window resize listener.

Tooltips

We could add a ::before pseudo-element to  .data-point to display the data-value information it contains in a tooltip on hover over the data point. This is a nice-to-have sort of touch that helps turn our simple chart into a finished product.

Axis lines

Notice that the chart axises are unlabeled? We could distribute labels representing the highest value, zero, and any number of points between them on the axis.

Margins

I tried to keep the numbers as simple as possible for this article, but in the real world, you would probably want to include some margins in the chart so that data points don’t overlap the extreme edges of their container. That could be as simple as subtracting the width of a data point from the range of your y coordinates. For the X coordinates, you could similarly remove the width of a data point from the total width of the chart before dividing it up into equal regions.


And there you have it! We just took a good look at an approach to charting in CSS, and we didn’t even need a library or some other third-party dependency to make it work. 💥



Source link

The drain from The Raven Hotel, Altered Carbon
Strategy

The drain from The Raven Hotel, Altered Carbon


The drain from The Raven Hotel, Altered Carbon

submitted by /u/dangerboydesign
[comments]



Source link