Thomas  Granger

Thomas Granger

1560864072

Writing better Reducers with React and Typescript 3.4

Leveraging state reducers and immutability at scale can be tricky. Nonetheless the incredible arsenal of tools we have to handle that, it all comes around to a single pattern that resembles our application growth. Thus, application state is more than a challenge, is a narrative we tell ourselves every time we come back to the code.

When it comes to React, sometimes it doesn’t matter much how we approach designing the many pieces of state, but how we wire them together. We may rely on Redux, Context, useReducer, useState, or something totally different. But deep down all we want is that all pieces make sense when playing together. And for that, I was already convicted that Typescript can have an essential role, but now that version 3.4 is out, I’m thrilled.

Typescript is more than types.

People have a strong opinion about enforcing types in JavaScript. This makes me remember something meaningful I read once: we write code just like a writer writes proses.

JavaScript and Typescript discussions are generally about form and structure, and people usually forget about rhythm. After a few years using putting a .ts at the end of my files, it’s the latter I care the most, and on what Typescript can benefit us more.

In other words, instead of starting off writing interfaces for props, states and functions return’s, and making our feature too tied without writing a single line of runtime code, we spike into the code and use Typescript as we go, to connect the dots and make sure that future adjustments won’t compromise our app integrity. The bottom line is, we don’t have to do a TDD where T stands for Type.

Writing better Reducers

Before starting with code examples, we need to define better. So, a naive interpretation of what I want to achieve is:

  • Less error prone code: As my components grow, I want to focus on what is essential, and not having to manually check if the changes I’m writing are backwards compatible. Typescript automates that for me and even give me instant feedback.
  • No extra boilerplate for types definitions: The codebase I work on, indeed, has some generic interfaces that help me building up new types for special occasions. But I don’t think it’s productive (nor necessary) having to write helpers for every situation.
  • No code/type redundancy (DRY): We focus on letting our code to dictate our types and not the other way around.

Now, let’s build a reducer that encapsulates the state of a user. Assume we need to have a state like below:

const initialState = {
  name: '',
  points: 0,
  likesGames: true
}

type State = typeof initialState;

By doing type State = typeof initialState we already have 50% of the type definitions we’re going to write here. Also, the moment I make any change to that structure, it will be propagated to all the places I need it, highlighting what needs to be updated. Typescript will read State as:

type State = {
  name: string;
  points: number;
  likesGames: boolean;
}

For our actions, I’ll use the pattern where we define action creators beforehand, which I believe it’s the most common pattern out there. Also, for projects that are moving towards Typescript, this can be more friendly. An action can modify any amount of fields of the state at the same time. For simplicity, I’ll write an action creator for each field I have.

export function updateName(name: string) {
  return {
    type: ‘UPDATE_NAME’,
    name
  }
}

type Action = ReturnType<typeof updateName>

The ReturnType extracts the type of what is being returned from the function passed to its arguments. It’s available since Typescript 2.8. By using it, we don’t have to write twice the same object. But here is where the newest version (3.4) really shines. The problem with the above code is that, until now, Action would be interpreted as{ type: string, name: string } and thus, no useful information about the action itself would be considered when doing things like switch(action.type) or dispatch({ type: 'anything' }).

Const assertions

We now can lock down the type of any object and hint the compiler about immutability. From the release post,

  • Less error prone code: As my components grow, I want to focus on what is essential, and not having to manually check if the changes I’m writing are backwards compatible. Typescript automates that for me and even give me instant feedback.
  • No extra boilerplate for types definitions: The codebase I work on, indeed, has some generic interfaces that help me building up new types for special occasions. But I don’t think it’s productive (nor necessary) having to write helpers for every situation.
  • No code/type redundancy (DRY): We focus on letting our code to dictate our types and not the other way around.

Here’s our updated action using const assertions

export function updateName(name: string) {
  return <const>{
    type: ‘UPDATE_NAME’,
    name
  }
}

Resulting Type of the action

Finally, all typings for our actions is just as below, which now completes all the “extra” work we had in order to help another tool to give us better insights about our own code.

type Action = ReturnType<
 typeof updateName | typeof addPoints | typeof setLikesGames
>

Conclusion

Const assertions can be more helpful when writing reducers for Redux, as actions creators are more a common pattern for dispatching actions. Of course, this is just a tiny example of its capabilities. If you’re using Typescript with a similar approach than me and creating types as a consequence of the implementation, Reducers are just the beginning. A full gist of the example used here can be seen here.

#reactjs #typescript

What is GEEK

Buddha Community

Writing better Reducers with React and Typescript 3.4
Autumn  Blick

Autumn Blick

1598839687

How native is React Native? | React Native vs Native App Development

If you are undertaking a mobile app development for your start-up or enterprise, you are likely wondering whether to use React Native. As a popular development framework, React Native helps you to develop near-native mobile apps. However, you are probably also wondering how close you can get to a native app by using React Native. How native is React Native?

In the article, we discuss the similarities between native mobile development and development using React Native. We also touch upon where they differ and how to bridge the gaps. Read on.

A brief introduction to React Native

Let’s briefly set the context first. We will briefly touch upon what React Native is and how it differs from earlier hybrid frameworks.

React Native is a popular JavaScript framework that Facebook has created. You can use this open-source framework to code natively rendering Android and iOS mobile apps. You can use it to develop web apps too.

Facebook has developed React Native based on React, its JavaScript library. The first release of React Native came in March 2015. At the time of writing this article, the latest stable release of React Native is 0.62.0, and it was released in March 2020.

Although relatively new, React Native has acquired a high degree of popularity. The “Stack Overflow Developer Survey 2019” report identifies it as the 8th most loved framework. Facebook, Walmart, and Bloomberg are some of the top companies that use React Native.

The popularity of React Native comes from its advantages. Some of its advantages are as follows:

  • Performance: It delivers optimal performance.
  • Cross-platform development: You can develop both Android and iOS apps with it. The reuse of code expedites development and reduces costs.
  • UI design: React Native enables you to design simple and responsive UI for your mobile app.
  • 3rd party plugins: This framework supports 3rd party plugins.
  • Developer community: A vibrant community of developers support React Native.

Why React Native is fundamentally different from earlier hybrid frameworks

Are you wondering whether React Native is just another of those hybrid frameworks like Ionic or Cordova? It’s not! React Native is fundamentally different from these earlier hybrid frameworks.

React Native is very close to native. Consider the following aspects as described on the React Native website:

  • Access to many native platforms features: The primitives of React Native render to native platform UI. This means that your React Native app will use many native platform APIs as native apps would do.
  • Near-native user experience: React Native provides several native components, and these are platform agnostic.
  • The ease of accessing native APIs: React Native uses a declarative UI paradigm. This enables React Native to interact easily with native platform APIs since React Native wraps existing native code.

Due to these factors, React Native offers many more advantages compared to those earlier hybrid frameworks. We now review them.

#android app #frontend #ios app #mobile app development #benefits of react native #is react native good for mobile app development #native vs #pros and cons of react native #react mobile development #react native development #react native experience #react native framework #react native ios vs android #react native pros and cons #react native vs android #react native vs native #react native vs native performance #react vs native #why react native #why use react native

Let Developers Just Need to Grasp only One Button Component

 From then on, developers only need to master one Button component, which is enough.

Support corners, borders, icons, special effects, loading mode, high-quality Neumorphism style.

Author:Newton(coorchice.cb@alibaba-inc.com)

✨ Features

Rich corner effect

Exquisite border decoration

Gradient effect

Flexible icon support

Intimate Loading mode

Cool interaction Special effects

More sense of space Shadow

High-quality Neumorphism style

🛠 Guide

⚙️ Parameters

🔩 Basic parameters

ParamTypeNecessaryDefaultdesc
onPressedVoidCallbacktruenullClick callback. If null, FButton will enter an unavailable state
onPressedDownVoidCallbackfalsenullCallback when pressed
onPressedUpVoidCallbackfalsenullCallback when lifted
onPressedCancelVoidCallbackfalsenullCallback when cancel is pressed
heightdoublefalsenullheight
widthdoublefalsenullwidth
styleTextStylefalsenulltext style
disableStyleTextStylefalsenullUnavailable text style
alignmentAlignmentfalsenullalignment
textStringfalsenullbutton text
colorColorfalsenullButton color
disabledColorColorfalsenullColor when FButton is unavailable
paddingEdgeInsetsGeometryfalsenullFButton internal spacing
cornerFCornerfalsenullConfigure corners of Widget
cornerStyleFCornerStylefalseFCornerStyle.roundConfigure the corner style of Widget. round-rounded corners, bevel-beveled
strokeColorColorfalseColors.blackBorder color
strokeWidthdoublefalse0Border width. The border will appear when strokeWidth > 0
gradientGradientfalsenullConfigure gradient colors. Will override the color
activeMaskColorColorColors.transparentThe color of the mask when pressed
surfaceStyleFSurfacefalseFSurface.FlatSurface style. Default [FSurface.Flat]. See [FSurface] for details

💫 Effect parameters

ParamTypeNecessaryDefaultdesc
clickEffectboolfalsefalseWhether to enable click effects
hoverColorColorfalsenullFButton color when hovering
onHoverValueChangedfalsenullCallback when the mouse enters/exits the component range
highlightColorColorfalsenullThe color of the FButton when touched. effect:true required

🔳 Shadow parameters

ParamTypeNecessaryDefaultdesc
shadowColorColorfalseColors.greyShadow color
shadowOffsetOffsetfalseOffset.zeroShadow offset
shadowBlurdoublefalse1.0Shadow blur degree, the larger the value, the larger the shadow range

🖼 Icon & Loading parameters

ParamTypeNecessaryDefaultdesc
imageWidgetfalsenullAn icon can be configured for FButton
imageMargindoublefalse6.0Spacing between icon and text
imageAlignmentImageAlignmentfalseImageAlignment.leftRelative position of icon and text
loadingboolfalsefalseWhether to enter the Loading state
loadingWidgetWidgetfalsenullLoading widget in loading state. Will override the default Loading effect
clickLoadingboolfalsefalseWhether to enter Loading state after clicking FButton
loadingColorColorfalsenullLoading colors
loadingStrokeWidthdoublefalse4.0Loading width
hideTextOnLoadingboolfalsefalseWhether to hide text in the loading state
loadingTextStringfalsenullLoading text
loadingSizedoublefalse12Loading size

🍭 Neumorphism Style

ParamTypeNecessaryDefaultdesc
isSupportNeumorphismboolfalsefalseWhether to support the Neumorphism style. Open this item [highlightColor] will be invalid
lightOrientationFLightOrientationfalseFLightOrientation.LeftTopValid when [isSupportNeumorphism] is true. The direction of the light source is divided into four directions: upper left, lower left, upper right, and lower right. Used to control the illumination direction of the light source, which will affect the highlight direction and shadow direction
highlightShadowColorColorfalsenullAfter the Neumorphism style is turned on, the bright shadow color

📺 Demo

🔩 Basic Demo

// FButton #1
FButton(
  height: 40,
  alignment: Alignment.center,
  text: "FButton #1",
  style: TextStyle(color: Colors.white),
  color: Color(0xffffab91),
  onPressed: () {},
)

// FButton #2
FButton(
  padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
  text: "FButton #2",
  style: TextStyle(color: Colors.white),
  color: Color(0xffffab91),
  corner: FCorner.all(6.0),
)

// FButton #3
FButton(
  padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
  text: "FButton #3",
  style: TextStyle(color: Colors.white),
  disableStyle: TextStyle(color: Colors.black38),
  color: Color(0xffF8AD36),

  /// set disable Color
  disabledColor: Colors.grey[300],
  corner: FCorner.all(6.0),
)

By simply configuring text andonPressed, you can construct an available FButton.

If onPressed is not set, FButton will be automatically recognized as not unavailable. At this time, ** FButton ** will have a default unavailable status style.

You can also freely configure the style of FButton when it is not available via the disabledXXX attribute.

🎈 Corner & Stroke

// #1
FButton(
  width: 130,
  text: "FButton #1",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFF7043),
  onPressed: () {},
  clickEffect: true,
  
  /// 配置边角大小
  ///
  /// set corner size
  corner: FCorner.all(25),
),

// #2
FButton(
  width: 130,
  text: "FButton #2",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFFA726),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner(
    leftBottomCorner: 40,
    leftTopCorner: 6,
    rightTopCorner: 40,
    rightBottomCorner: 6,
  ),
),

// #3
FButton(
  width: 130,
  text: "FButton #3",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFFc900),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner(leftTopCorner: 10),
  
  /// 设置边角风格
  ///
  /// set corner style
  cornerStyle: FCornerStyle.bevel,
  strokeWidth: 0.5,
  strokeColor: Color(0xffF9A825),
),

// #4
FButton(
  width: 130,
  padding: EdgeInsets.fromLTRB(6, 16, 30, 16),
  text: "FButton #4",
  style: TextStyle(color: Colors.white),
  color: Color(0xff00B0FF),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner(
      rightTopCorner: 25,
      rightBottomCorner: 25),
  cornerStyle: FCornerStyle.bevel,
  strokeWidth: 0.5,
  strokeColor: Color(0xff000000),
),

You can add rounded corners to FButton via the corner property. You can even control each fillet individually。

By default, the corners of FButton are rounded. By setting cornerStyle: FCornerStyle.bevel, you can get a bevel effect.

FButton supports control borders, provided that strokeWidth> 0 can get the effect 🥳.

🌈 Gradient


FButton(
  width: 100,
  height: 60,
  text: "#1",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFFc900),
  
  /// 配置渐变色
  ///
  /// set gradient
  gradient: LinearGradient(colors: [
    Color(0xff00B0FF),
    Color(0xffFFc900),
  ]),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner.all(8),
)

Through the gradient attribute, you can build FButton with gradient colors. You can freely build many types of gradient colors.

🍭 Icon

FButton(
  width: 88,
  height: 38,
  padding: EdgeInsets.all(0),
  text: "Back",
  style: TextStyle(color: Colors.white),
  color: Color(0xffffc900),
  onPressed: () {
    toast(context, "Back!");
  },
  clickEffect: true,
  corner: FCorner(
    leftTopCorner: 25,
    leftBottomCorner: 25,),
  
  /// 配置图标
  /// 
  /// set icon
  image: Icon(
    Icons.arrow_back_ios,
    color: Colors.white,
    size: 12,
  ),

  /// 配置图标与文字的间距
  ///
  /// Configure the spacing between icon and text
  imageMargin: 8,
),

FButton(
  onPressed: () {},
  image: Icon(
    Icons.print,
    color: Colors.grey,
  ),
  imageMargin: 8,

  /// 配置图标与文字相对位置
  ///
  /// Configure the relative position of icons and text
  imageAlignment: ImageAlignment.top,
  text: "Print",
  style: TextStyle(color: textColor),
  color: Colors.transparent,
),

The image property can set an image for FButton and you can adjust the position of the image relative to the text, throughimageAlignment.

If the button does not need a background, just set color: Colors.transparent.

🔥 Effect


FButton(
  width: 200,
  text: "Try Me!",
  style: TextStyle(color: textColor),
  color: Color(0xffffc900),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner.all(9),
  
  /// 配置按下时颜色
  ///
  /// set pressed color
  highlightColor: Color(0xffE65100).withOpacity(0.20),
  
  /// 配置 hover 状态时颜色
  ///
  /// set hover color
  hoverColor: Colors.redAccent.withOpacity(0.16),
),

The highlight color of FButton can be configured through the highlightColor property。

hoverColor can configure the color when the mouse moves to the range of FButton, which will be used during Web development.

🔆 Loading

FButton(
  text: "Click top loading",
  style: TextStyle(color: textColor),
  color: Color(0xffffc900),
  ...

  /// 配置 loading 大小
  /// 
  /// set loading size
  loadingSize: 15,

  /// 配置 loading 与文本的间距
  ///
  // Configure the spacing between loading and text
  imageMargin: 6,
  
  /// 配置 loading 的宽
  ///
  /// set loading width
  loadingStrokeWidth: 2,

  /// 是否支持点击自动开始 loading
  /// 
  /// Whether to support automatic loading by clicking
  clickLoading: true,

  /// 配置 loading 的颜色
  ///
  /// set loading color
  loadingColor: Colors.white,

  /// 配置 loading 状态时的文本
  /// 
  /// set loading text
  loadingText: "Loading...",

  /// 配置 loading 与文本的相对位置
  ///
  /// Configure the relative position of loading and text
  imageAlignment: ImageAlignment.top,
),

// #2
FButton(
  width: 170,
  height: 70,
  text: "Click to loading",
  style: TextStyle(color: textColor),
  color: Color(0xffffc900),
  onPressed: () { },
  ...
  imageMargin: 8,
  loadingSize: 15,
  loadingStrokeWidth: 2,
  clickLoading: true,
  loadingColor: Colors.white,
  loadingText: "Loading...",

  /// loading 时隐藏文本
  ///
  /// Hide text when loading
  hideTextOnLoading: true,
)


FButton(
  width: 170,
  height: 70,
  alignment: Alignment.center,
  text: "Click to loading",
  style: TextStyle(color: Colors.white),
  color: Color(0xff90caf9),
  ...
  imageMargin: 8,
  clickLoading: true,
  hideTextOnLoading: true,

  /// 配置自定义 loading 样式
  ///
  /// Configure custom loading style
  loadingWidget: CupertinoActivityIndicator(),
),

Through the loading attribute, you can configure Loading effects for ** FButton **.

When FButton is in Loading state, FButton will enter an unavailable state, onPress will no longer be triggered, and unavailable styles will also be applied.

At the same time loadingText will overwritetext if it is not null.

The click start Loading effect can be achieved through the clickLoading attribute.

The position of loading will be affected by theimageAlignment attribute.

When hideTextOnLoading: true, if FButton is inloading state, its text will be hidden.

Through loadingWidget, developers can set completely customized loading styles.

Shadow


FButton(
  width: 200,
  text: "Shadow",
  textColor: Colors.white,
  color: Color(0xffffc900),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner.all(28),
  
  /// 配置阴影颜色
  ///
  /// set shadow color
  shadowColor: Colors.black87,

  /// 设置组件高斯与阴影形状卷积的标准偏差。
  /// 
  /// Sets the standard deviation of the component's Gaussian convolution with the shadow shape.
  shadowBlur: _shadowBlur,
),

FButton allows you to configure the color, size, and position of the shadow.

🍭 Neumorphism Style

FButton(

  /// 开启 Neumorphism 支持
  ///
  /// Turn on Neumorphism support
  isSupportNeumorphism: true,

  /// 配置光源方向
  ///
  /// Configure light source direction
  lightOrientation: lightOrientation,

  /// 配置亮部阴影
  ///
  /// Configure highlight shadow
  highlightShadowColor: Colors.white,

  /// 配置暗部阴影
  ///
  /// Configure dark shadows
  shadowColor: mainShadowColor,
  strokeColor: mainBackgroundColor,
  strokeWidth: 3.0,
  width: 190,
  height: 60,
  text: "FWidget",
  style: TextStyle(
      color: mainTextTitleColor, fontSize: neumorphismSize_2_2),
  alignment: Alignment.center,
  color: mainBackgroundColor,
  ...
)

FButton brings an incredible, ultra-high texture Neumorphism style to developers.

Developers only need to configure the isSupportNeumorphism parameter to enable and disable the Neumorphism style.

If you want to adjust the style of Neumorphism, you can make subtle adjustments through several attributes related to Shadow, among which:

shadowColor: configure the shadow of the shadow

highlightShadowColor: configure highlight shadow

FButton also provides lightOrientation parameters, and even allows developers to adjust the care angle, and has obtained different Neumorphism effects.

😃 How to use?

Add dependencies in the project pubspec.yaml file:

🌐 pub dependency

dependencies:
  fbutton: ^<version number>

⚠️ Attention,please go to [pub] (https://pub.dev/packages/fbutton) to get the latest version number of FButton

🖥 git dependencies

dependencies:
  fbutton:
    git:
      url: 'git@github.com:Fliggy-Mobile/fbutton.git'
      ref: '<Branch number or tag number>'

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add fbutton_nullsafety

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  fbutton_nullsafety: ^5.0.0

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:fbutton_nullsafety/fbutton_nullsafety.dart';

Download Details:

Author: Fliggy-Mobile

Source Code: https://github.com/Fliggy-Mobile/fbutton

#button  #flutter 

Dylan  Iqbal

Dylan Iqbal

1630408920

Big Data Visualization: What, Why, Tips and Tools

Wondering what is big data visualization and how you can apply it for your business? Here's a guide to help you get started.

Because we live in a data-driven society, it’s likely that you’re constantly bombarded with complex sets of data that you need to transmit to your coworkers in an easy-to-grasp way.

The challenge is that almost no one wants to look at large lists of numbers and data, and important information can be easily lost within the midst of chaotic spreadsheets. But there is a solution, and that is big data visualization.

Today, we’ll be covering what big data visualization is and why it’s important, different big data visualization techniques you can use, tips and tricks for creating easily intelligible large data sets and the best big data visualization tools you can use.

By the end of this article, you’ll feel like a real data scientist and be competent in creating pie charts, bar charts, heat maps, histograms, interactive charts and more for big data visualization.

So let’s get into it, shall we?

Table of Contents

What is Big Data Visualization?

Why is Data Visualization Important in Big Data?

What Are the Types of Big Data Visualization?

5 Big Data Visualization Tips for Beginners

4 Tools for Big Data Visualization

---

What is Big Data Visualization?

Big data visualization is the representation of large sets of data through visual aids, whether that be through pie charts, heat maps, bar charts or any other kind of chart types or visual representation.

Analyzing and understanding large data sets and data analytics is no easy task and it can be especially difficult trying to relay that same information to colleagues who are not data-driven or data scientists.

That’s where big data visualization comes in. By transforming your large data sets into visually appealing infographics or interactive charts, you can easily convey your data points to fellow decision-makers.

When your data is plotted out on graphs in a visual way and metrics are made easily readable, no data gets lost in the mix, no matter how large or small, and it makes decision-making for the future a breeze.

Because you can’t make adequate decisions or advance significantly without analyzing your raw data, it’s important that companies use great data visualization methods to keep everyone in the loop.

Let’s take BMW for example.

Image Source

In 2020, BMW was able to track the number of sales for electric cars that they had and then compare it to other car companies’ sales, but not only.

They also were able to track the countries that bought the highest amount of their electric cars.

Image Source

This is a prime example of big data visualization in action. When you track your analytics and data, you can see where your wins are and when to celebrate or where your losses are and how you can make adjustments for the future.

Now, imagine for a moment that all this information was just written out plainly on a spreadsheet and had unstructured data all over it.

It would be hard to understand and assess how the company is doing and would take a long time to communicate to employees how their work has affected the sales of the cars.

This is why visualizing big data is so important. With just a glance and within seconds, you can easily see what cars are selling best and in what countries.

No time is wasted going through spreadsheets and trying to make sense of unstructured data — just visual analytics laid out for all to see and understand.

 

Why is Data Visualization Important in Big Data?

We live in a time where the internet and social media have exploded at an extraordinary rate, and information can be gathered within seconds and at the tips of anyone’s fingers.

With the rise of this technological era, it’s important that data can be visualized and consumed quickly and efficiently — especially since the human brain now has an attention span of about 8 seconds, according to this study by the Technical University of Denmark.

Because companies, businesses and organizations can gather data more quickly than ever, this means that they need to be able to visualize that data in an equally quick and easily consumable way.

The best way to efficiently communicate your ever-coming, new data is through visualizing big data. This will bring your complex data to life and anyone who looks at it will be able to understand and grasp it with just a glance.

Customize this template and make it your own!

Edit and Download

Take the image above as an example. With just a quick look at the statistics that are clearly visualized, you can make a data-based assumption.

Now, imagine if this data was just written out plainly on a spreadsheet. It would take much longer to understand and make an assumption based on the numbers.

By using big data visualization techniques, you’ll be able to get the most value from your data and analytics and make sure that everyone who says your data analysis will be able to interpret, understand and use your data. This, in turn, will help your company excel.

When you use data visualization techniques, it will optimize your use of data, help decision making and planning go smoothly, you’ll be able to identify and mitigate risk, extract loads of useful data and insights and improve your overall strategy and direction of your company.

There are no losses to using a visual representation of data, only wins. But there are lots of different types of data visualization that you can use.

Let’s discuss the different types of big data visualization and assess which one will work best for you.

 

What Are the Types of Big Data Visualization?

There are lots of different types of data visualization that data analysts like to use and depending on the amount of data. A data analyst may choose to use a pie chart to express their numerical data or a bar chart.

When looking at big data analytics regarding locations, one might choose to use an interactive heat map or maybe a pivot table.

We’re going to look at 8 common types of big data visualization and some data visualization examples for each to help you decipher which one will work best for you.

 

Type #1: Line Charts

Customize this template and make it your own!

Edit and Download

A line chart, also known as a line graph, is a graphic representation of data that plots a fixed value on one side and a variable on the other.

A line chart is a fantastic way to represent the relationship of data. You can use a line chart to represent changes and fluctuations of things within a certain period of time.

 

Type #2: Bar Charts

Customize this template and make it your own!

Edit and Download

A bar chart, also known as a bar graph, uses bars to compare different data points or data sets.

Many data scientists will use bar charts to visually represent their data analysis. You can use a bar chart to compare large amounts of data, fluctuations of quantities or different categories.

The taller the bar, the larger the numerical value and vice versa.

 

Type #3: Pie Charts

Customize this template and make it your own!

Edit and Download

Pie charts, donut charts, circle graphs or whatever you choose to call them, are representations of data that are split into smaller segments and sizes to represent their numerical value.

When you use a pie chart, it becomes easy to see and compare how the different segments relate and differ from each other.

When using a pie chart, try not to overload it with too many different values. When you split the pie chart into more than 7 segments, it can become difficult to understand the data.

 

Type #4: Heat Maps

Image Source

A heat map is a visual representation of data that is laid out on a map or table and uses different nuances and intensities of colors to represent its data.

Using a heat map can be especially helpful when you need to analyze data that seems to be never-ending. When you have an extremely wide value range, using a heat map makes it much more simple to quickly visualize and analyze large amounts of complex data at a glance.

 

Type #5: Histograms

histogram - weights of newborns

Customize this template and make it your own!

Edit and Download

A histogram is a graphical and visual representation of complex data sets and the frequency of said numerical data displayed through bars.

Histograms are very similar to bar graphs but vary in the fact that they mostly focus on the repeated frequency of numerical data.

Type #6: Scatter Plots

Customize this template and make it your own!

Edit and Download

A scatter plot, scatter chart or scatter graph, is a diagram that uses dots to represent and emphasize the different values of two or more numeric variables on an X and Y-axis.

Scatter plots are extremely useful to use when you have multiple large data sets and you want to know how they relate to each other and compare the importance of each value.

 

Type #7: Treemaps

Create your own charts and graphs!

Get Started For Free!

Treemaps are the visual representation of hierarchical data by using color-coded rectangles.

Users can use treemaps as a method to compare multiple sets of data and reflect the weight of each value in a project.

 

Type #8: Funnel Charts

Customize this template and make it your own!

Edit and Download

Funnel charts are typically used in sales and represent the different stages that your users or customers go through during the sales process and demonstrate decreasing values as they move through your funnel.

By using a funnel chart, you can accurately see where you are losing or gaining your customers during the sales process.

 

5 Big Data Visualization Tips for Beginners

Now that we’ve covered what big data visualization is, its importance and 9 different types of data visualization, you may feel like you’re a professional in data science.

Now that you’re familiar with the basics of data visualization, it’s time that we equip you with some of our best data visualization techniques.

Here are our top 5 best data visualization techniques for you to use when creating a visual representation of your data.

 

Tip #1: Use a Powerful Data Visualization Tool

Customize this template and make it your own!

Edit and Download

You can’t create powerful graphs without a powerful data visualization tool.

Sure, you could use something like Google charts, but to create unique, engaging charts, you’ll want to use a data visualization tool like Visme that's packed with amazing functionality.

Visme is a powerful data visualization tool with many integration functionalities. As you can see in the image above, you can create everything from funnel charts and tables to interactive data maps and graphs in this editor.

When you need to visualize big data, Visme is the way to go. When you create a graph in our big data visualization tool, your data can be updated in real-time with our integration tools.

You can import all your data from Google Sheets, Microsoft Excel, Google Analytics and other data sources, then see it come to life automatically on your project while you sit back and relax.

Visme also has many open-source elements and graphics for you to use to keep your infographic intriguing. To have the perfect interactive data visualization, you can use word clouds, tables, treemaps, animated characters and graphic design elements and more to implement into your design.

They’re also a powerhouse filled with lots of useful and educational tutorials on how to create the perfect chart for your raw data. Visme also has lots of tutorials for all things graphic design.

So why not use a tool that has everything you need for creating visuals for your data analysis and tons of tutorials to go with it? You can start your free account with Visme today and start living out your data analyst dreams.

It’s important to use a strong data visualization software for your data analysis and presentations. Stick around and soon we’ll get into our list of best tools for big data visualization.

 

Tip #2: Pick the Correct Form of Big Data Visualization

Customize this template and make it your own!

Edit and Download

When it comes to visualizing your data, you need to make sure that you choose the correct chart type.

Because there are so many different ways to display your data, you need to weigh out the cons and pros of each and find out which one will work best for your infographic or presentation.

Take for example pie charts and bar graphs.

When you analyze data that is very different, you might want to use a pie chart. But if you want to represent data entries that are close together, you could use a bar chart for that.

If you’re trying to create data visualization for sales, you could use a funnel chart, pyramid chart or cone chart for that.

Each different visualization method has its time and place, and you need to analyze your data and think about what method will work best for your respective data.

Refer above to the “Big Data Visualization Types” section above to see which one will suit you best.

 

Tip #3: Make Sure Your Data is Easily Comprehensible

Customize this template and make it your own!

Edit and Download

The whole point of big data visualization is to make it easy to understand at a glance.

It won’t be easily intelligible if you just start piling in large amounts of unstructured data and simply hope for the best. Or imagine you have tens of tiny little numbers on a bar graph that no one can see or read.

You need to make sure that anyone on your team, whether a data scientist or not, can understand what you’re trying to convey at a glance.

You can do this by using clear and bold text, contrasting font colors and background colors, not adding too many values to one chart and using compelling images to highlight your point, just like in the example above.

By adding too much text or too many values to a single graph, you risk confusing your audience even more. So keep it as simple and concise as possible.

 

Tip #4: Always Use Legends to Further Explain Your Data

Customize this template and make it your own!

Edit and Download

Using legends is absolutely vital for making your data easy to understand, so whether you’re creating a pie chart or bar graph, make sure you’re using a legend.

A legend is an area of your design that further explains each segment of your chart.

Many times people will assign a color to a segment in their chart, just like in the example above, and on the side add a little graphic element that explains what each color represents.

The legend is responsible for keeping the audience engaged and understanding everything you’re trying to convey.

 

Tip #5: Use Multiple Charts for Big Data

Visualize big data easily with this drag-and-drop tool!

Try It For Free

If you have a large amount of data that needs to be conveyed to your team, try using multiple graphs to do so.

Incorporating tons of data into a single chart will only make it hard for the human brain to stay on track and focus to try and understand what you want to share.

The best rule of thumb to follow here is KISS — keep it simple, stupid.

So instead of simply adding all your data to one pie chart and making it have 30 pie slices, why not create multiple graphs and break it down into bite-sized pieces? Pun intended.

By creating multiple matching charts, you can keep your data easily intelligible, cohesive and right on brand.

Just like in the example above, you can clearly understand all the data that’s being displayed because it is written out on two different donut charts.

You want to make sure your information is understandable by anyone at a glance, and you can do so by breaking down your data.

 

4 Tools for Big Data Visualization

Now that you know essentially all there is to know about big data visualization, it’s time you choose a tool that will help you create those visuals.

We’ll be covering 4 data visualization software you can use to get the job done.

Let’s jump right into it.

 

Tool #1: Visme

Start visualizing data with beautiful charts and graphs!

Try It For Free

If you want to create compelling and professional data visualization, then you need a tool like Visme.

Visme makes it easy for both designers and non-designers alike to visualize their data in interactive and engaging ways.

For example, you can create incredible animated charts, add your own audio files to them that you can record right within the editor, add tons of professionally design data widgets and import all your data from third-party websites such as Microsoft Excel, Google sheets etc.

The best part? You can save endless amounts of time and effort by using one of our hundreds of customizable templates for displaying your data.

Simply scroll through tons of professionally design templates for charts and data choose one that suits your style.

Everything can be customized on each and every template and you can even add your own brand colors, logo and font to keep everything right on-brand with your other designs.

Not only can you create loads of beautiful charts, graphs and infographics with Visme, but you can also create anything else design-related. You can create presentations, infographics, multi-page reports and proposals, branded social graphics and more.

If you’re looking for a powerful data visualization tool with high functionality for many other types of designs, Visme is the one for you. Plus, you can create a free account and use for as long as you like — no trial period or hidden costs!

 

Tip #2: Tableau

Tableau is an interactive data visualization software with a focus on business intelligence. Their goal is to help people make data that can be easily understood by anyone.

Tableau is a tool that is used in the business intelligence industry and it can help you simplify raw data into a simple format. With drag and drop functionalities, you can create data visualization fairly quickly and then share it with others.

In Tableau you can create lots of different data visualizations, from a correlation matrix to a simple bar graph.

Another plus for the software is that you can infuse the Tableau dashboard with artificial intelligence and machine learning from Aible.

You can start a free trial with Tableau, but it is a bit pricey after your trial is up. At $70/month billed annually, you’ll have to make sure you absolutely love the product before buying it.

 

Tool #3: Microsoft’s Power BI

Power BI by Microsoft is a business analytics service that helps you create interactive data visualizations.

Whether your data is on an Excel spreadsheet an on-premises hybrid data warehouses, Power BI will help you bring that data together to create reports and graphs to share with your team.

There are three versions of Power BI that you can use: the desktop app, the mobile app or their website.

You can use Power BI to help you visualize big data with your team by using some of their other popular apps like Microsoft Excel and work together in real-time to create compelling data.

Power BI has some basic templates that you can use to get a jump start on creating your data.

Power BI is quite affordable, coming in at $9.99/month.

If you’re not completely sold on using Power BI, let’s move on to our next tool.

 

Tool #4: Datawrapper

Datawrapper is an online tool that you can use to create data visualizations that are interactive and responsive, with no code or programming languages like python or javascript required.

With big users like the New York Times and the UN, they do have quite a few things to boast about.

Data wrapper is an open-source and easy-to-use data visualization software where you can create basic charts and graphs, maps and line charts that can be embedded into your website.

As for the price, you can use their free plan and create lots of charts, maps and tables, but they will be watermarked and there are a few other inconveniences that come with the free plan.

The next plan comes in at $599/month, which is definitely on the pricey side.

And that concludes our list of 4 tools for data visualization.

 

Now Over to You

If you want a data visualization software that will help you convey your data in a fun and engaging way, then you most likely will love using Visme.

Not only is Visme a powerful data visualization tool, but it’s so much more. You can use Visme to create all of your graphic design needs, from sales presentations to pitch decks, social media posts, infographics, videos, eBooks and more.

What are you waiting for? Create your free account today and free your inner data scientist.

Originally published at https://visme.co

#datavisualization #bigdata

A Wrapper for Sembast and SQFlite to Enable Easy

FHIR_DB

This is really just a wrapper around Sembast_SQFLite - so all of the heavy lifting was done by Alex Tekartik. I highly recommend that if you have any questions about working with this package that you take a look at Sembast. He's also just a super nice guy, and even answered a question for me when I was deciding which sembast version to use. As usual, ResoCoder also has a good tutorial.

I have an interest in low-resource settings and thus a specific reason to be able to store data offline. To encourage this use, there are a number of other packages I have created based around the data format FHIR. FHIR® is the registered trademark of HL7 and is used with the permission of HL7. Use of the FHIR trademark does not constitute endorsement of this product by HL7.

Using the Db

So, while not absolutely necessary, I highly recommend that you use some sort of interface class. This adds the benefit of more easily handling errors, plus if you change to a different database in the future, you don't have to change the rest of your app, just the interface.

I've used something like this in my projects:

class IFhirDb {
  IFhirDb();
  final ResourceDao resourceDao = ResourceDao();

  Future<Either<DbFailure, Resource>> save(Resource resource) async {
    Resource resultResource;
    try {
      resultResource = await resourceDao.save(resource);
    } catch (error) {
      return left(DbFailure.unableToSave(error: error.toString()));
    }
    return right(resultResource);
  }

  Future<Either<DbFailure, List<Resource>>> returnListOfSingleResourceType(
      String resourceType) async {
    List<Resource> resultList;
    try {
      resultList =
          await resourceDao.getAllSortedById(resourceType: resourceType);
    } catch (error) {
      return left(DbFailure.unableToObtainList(error: error.toString()));
    }
    return right(resultList);
  }

  Future<Either<DbFailure, List<Resource>>> searchFunction(
      String resourceType, String searchString, String reference) async {
    List<Resource> resultList;
    try {
      resultList =
          await resourceDao.searchFor(resourceType, searchString, reference);
    } catch (error) {
      return left(DbFailure.unableToObtainList(error: error.toString()));
    }
    return right(resultList);
  }
}

I like this because in case there's an i/o error or something, it won't crash your app. Then, you can call this interface in your app like the following:

final patient = Patient(
    resourceType: 'Patient',
    name: [HumanName(text: 'New Patient Name')],
    birthDate: Date(DateTime.now()),
);

final saveResult = await IFhirDb().save(patient);

This will save your newly created patient to the locally embedded database.

IMPORTANT: this database will expect that all previously created resources have an id. When you save a resource, it will check to see if that resource type has already been stored. (Each resource type is saved in it's own store in the database). It will then check if there is an ID. If there's no ID, it will create a new one for that resource (along with metadata on version number and creation time). It will save it, and return the resource. If it already has an ID, it will copy the the old version of the resource into a _history store. It will then update the metadata of the new resource and save that version into the appropriate store for that resource. If, for instance, we have a previously created patient:

{
    "resourceType": "Patient",
    "id": "fhirfli-294057507-6811107",
    "meta": {
        "versionId": "1",
        "lastUpdated": "2020-10-16T19:41:28.054369Z"
    },
    "name": [
        {
            "given": ["New"],
            "family": "Patient"
        }
    ],
    "birthDate": "2020-10-16"
}

And we update the last name to 'Provider'. The above version of the patient will be kept in _history, while in the 'Patient' store in the db, we will have the updated version:

{
    "resourceType": "Patient",
    "id": "fhirfli-294057507-6811107",
    "meta": {
        "versionId": "2",
        "lastUpdated": "2020-10-16T19:45:07.316698Z"
    },
    "name": [
        {
            "given": ["New"],
            "family": "Provider"
        }
    ],
    "birthDate": "2020-10-16"
}

This way we can keep track of all previous version of all resources (which is obviously important in medicine).

For most of the interactions (saving, deleting, etc), they work the way you'd expect. The only difference is search. Because Sembast is NoSQL, we can search on any of the fields in a resource. If in our interface class, we have the following function:

  Future<Either<DbFailure, List<Resource>>> searchFunction(
      String resourceType, String searchString, String reference) async {
    List<Resource> resultList;
    try {
      resultList =
          await resourceDao.searchFor(resourceType, searchString, reference);
    } catch (error) {
      return left(DbFailure.unableToObtainList(error: error.toString()));
    }
    return right(resultList);
  }

You can search for all immunizations of a certain patient:

searchFunction(
        'Immunization', 'patient.reference', 'Patient/$patientId');

This function will search through all entries in the 'Immunization' store. It will look at all 'patient.reference' fields, and return any that match 'Patient/$patientId'.

The last thing I'll mention is that this is a password protected db, using AES-256 encryption (although it can also use Salsa20). Anytime you use the db, you have the option of using a password for encryption/decryption. Remember, if you setup the database using encryption, you will only be able to access it using that same password. When you're ready to change the password, you will need to call the update password function. If we again assume we created a change password method in our interface, it might look something like this:

class IFhirDb {
  IFhirDb();
  final ResourceDao resourceDao = ResourceDao();
  ...
    Future<Either<DbFailure, Unit>> updatePassword(String oldPassword, String newPassword) async {
    try {
      await resourceDao.updatePw(oldPassword, newPassword);
    } catch (error) {
      return left(DbFailure.unableToUpdatePassword(error: error.toString()));
    }
    return right(Unit);
  }

You don't have to use a password, and in that case, it will save the db file as plain text. If you want to add a password later, it will encrypt it at that time.

General Store

After using this for a while in an app, I've realized that it needs to be able to store data apart from just FHIR resources, at least on occasion. For this, I've added a second class for all versions of the database called GeneralDao. This is similar to the ResourceDao, but fewer options. So, in order to save something, it would look like this:

await GeneralDao().save('password', {'new':'map'});
await GeneralDao().save('password', {'new':'map'}, 'key');

The difference between these two options is that the first one will generate a key for the map being stored, while the second will store the map using the key provided. Both will return the key after successfully storing the map.

Other functions available include:

// deletes everything in the general store
await GeneralDao().deleteAllGeneral('password'); 

// delete specific entry
await GeneralDao().delete('password','key'); 

// returns map with that key
await GeneralDao().find('password', 'key'); 

FHIR® is a registered trademark of Health Level Seven International (HL7) and its use does not constitute an endorsement of products by HL7®

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add fhir_db

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  fhir_db: ^0.4.3

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:fhir_db/dstu2.dart';
import 'package:fhir_db/dstu2/fhir_db.dart';
import 'package:fhir_db/dstu2/general_dao.dart';
import 'package:fhir_db/dstu2/resource_dao.dart';
import 'package:fhir_db/encrypt/aes.dart';
import 'package:fhir_db/encrypt/salsa.dart';
import 'package:fhir_db/r4.dart';
import 'package:fhir_db/r4/fhir_db.dart';
import 'package:fhir_db/r4/general_dao.dart';
import 'package:fhir_db/r4/resource_dao.dart';
import 'package:fhir_db/r5.dart';
import 'package:fhir_db/r5/fhir_db.dart';
import 'package:fhir_db/r5/general_dao.dart';
import 'package:fhir_db/r5/resource_dao.dart';
import 'package:fhir_db/stu3.dart';
import 'package:fhir_db/stu3/fhir_db.dart';
import 'package:fhir_db/stu3/general_dao.dart';
import 'package:fhir_db/stu3/resource_dao.dart'; 

example/lib/main.dart

import 'package:fhir/r4.dart';
import 'package:fhir_db/r4.dart';
import 'package:flutter/material.dart';
import 'package:test/test.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final resourceDao = ResourceDao();

  // await resourceDao.updatePw('newPw', null);
  await resourceDao.deleteAllResources(null);

  group('Playing with passwords', () {
    test('Playing with Passwords', () async {
      final patient = Patient(id: Id('1'));

      final saved = await resourceDao.save(null, patient);

      await resourceDao.updatePw(null, 'newPw');
      final search1 = await resourceDao.find('newPw',
          resourceType: R4ResourceType.Patient, id: Id('1'));
      expect(saved, search1[0]);

      await resourceDao.updatePw('newPw', 'newerPw');
      final search2 = await resourceDao.find('newerPw',
          resourceType: R4ResourceType.Patient, id: Id('1'));
      expect(saved, search2[0]);

      await resourceDao.updatePw('newerPw', null);
      final search3 = await resourceDao.find(null,
          resourceType: R4ResourceType.Patient, id: Id('1'));
      expect(saved, search3[0]);

      await resourceDao.deleteAllResources(null);
    });
  });

  final id = Id('12345');
  group('Saving Things:', () {
    test('Save Patient', () async {
      final humanName = HumanName(family: 'Atreides', given: ['Duke']);
      final patient = Patient(id: id, name: [humanName]);
      final saved = await resourceDao.save(null, patient);

      expect(saved.id, id);

      expect((saved as Patient).name?[0], humanName);
    });

    test('Save Organization', () async {
      final organization = Organization(id: id, name: 'FhirFli');
      final saved = await resourceDao.save(null, organization);

      expect(saved.id, id);

      expect((saved as Organization).name, 'FhirFli');
    });

    test('Save Observation1', () async {
      final observation1 = Observation(
        id: Id('obs1'),
        code: CodeableConcept(text: 'Observation #1'),
        effectiveDateTime: FhirDateTime(DateTime(1981, 09, 18)),
      );
      final saved = await resourceDao.save(null, observation1);

      expect(saved.id, Id('obs1'));

      expect((saved as Observation).code.text, 'Observation #1');
    });

    test('Save Observation1 Again', () async {
      final observation1 = Observation(
          id: Id('obs1'),
          code: CodeableConcept(text: 'Observation #1 - Updated'));
      final saved = await resourceDao.save(null, observation1);

      expect(saved.id, Id('obs1'));

      expect((saved as Observation).code.text, 'Observation #1 - Updated');

      expect(saved.meta?.versionId, Id('2'));
    });

    test('Save Observation2', () async {
      final observation2 = Observation(
        id: Id('obs2'),
        code: CodeableConcept(text: 'Observation #2'),
        effectiveDateTime: FhirDateTime(DateTime(1981, 09, 18)),
      );
      final saved = await resourceDao.save(null, observation2);

      expect(saved.id, Id('obs2'));

      expect((saved as Observation).code.text, 'Observation #2');
    });

    test('Save Observation3', () async {
      final observation3 = Observation(
        id: Id('obs3'),
        code: CodeableConcept(text: 'Observation #3'),
        effectiveDateTime: FhirDateTime(DateTime(1981, 09, 18)),
      );
      final saved = await resourceDao.save(null, observation3);

      expect(saved.id, Id('obs3'));

      expect((saved as Observation).code.text, 'Observation #3');
    });
  });

  group('Finding Things:', () {
    test('Find 1st Patient', () async {
      final search = await resourceDao.find(null,
          resourceType: R4ResourceType.Patient, id: id);
      final humanName = HumanName(family: 'Atreides', given: ['Duke']);

      expect(search.length, 1);

      expect((search[0] as Patient).name?[0], humanName);
    });

    test('Find 3rd Observation', () async {
      final search = await resourceDao.find(null,
          resourceType: R4ResourceType.Observation, id: Id('obs3'));

      expect(search.length, 1);

      expect(search[0].id, Id('obs3'));

      expect((search[0] as Observation).code.text, 'Observation #3');
    });

    test('Find All Observations', () async {
      final search = await resourceDao.getResourceType(
        null,
        resourceTypes: [R4ResourceType.Observation],
      );

      expect(search.length, 3);

      final idList = [];
      for (final obs in search) {
        idList.add(obs.id.toString());
      }

      expect(idList.contains('obs1'), true);

      expect(idList.contains('obs2'), true);

      expect(idList.contains('obs3'), true);
    });

    test('Find All (non-historical) Resources', () async {
      final search = await resourceDao.getAll(null);

      expect(search.length, 5);
      final patList = search.toList();
      final orgList = search.toList();
      final obsList = search.toList();
      patList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Patient);
      orgList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Organization);
      obsList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Observation);

      expect(patList.length, 1);

      expect(orgList.length, 1);

      expect(obsList.length, 3);
    });
  });

  group('Deleting Things:', () {
    test('Delete 2nd Observation', () async {
      await resourceDao.delete(
          null, null, R4ResourceType.Observation, Id('obs2'), null, null);

      final search = await resourceDao.getResourceType(
        null,
        resourceTypes: [R4ResourceType.Observation],
      );

      expect(search.length, 2);

      final idList = [];
      for (final obs in search) {
        idList.add(obs.id.toString());
      }

      expect(idList.contains('obs1'), true);

      expect(idList.contains('obs2'), false);

      expect(idList.contains('obs3'), true);
    });

    test('Delete All Observations', () async {
      await resourceDao.deleteSingleType(null,
          resourceType: R4ResourceType.Observation);

      final search = await resourceDao.getAll(null);

      expect(search.length, 2);

      final patList = search.toList();
      final orgList = search.toList();
      patList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Patient);
      orgList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Organization);

      expect(patList.length, 1);

      expect(patList.length, 1);
    });

    test('Delete All Resources', () async {
      await resourceDao.deleteAllResources(null);

      final search = await resourceDao.getAll(null);

      expect(search.length, 0);
    });
  });

  group('Password - Saving Things:', () {
    test('Save Patient', () async {
      await resourceDao.updatePw(null, 'newPw');
      final humanName = HumanName(family: 'Atreides', given: ['Duke']);
      final patient = Patient(id: id, name: [humanName]);
      final saved = await resourceDao.save('newPw', patient);

      expect(saved.id, id);

      expect((saved as Patient).name?[0], humanName);
    });

    test('Save Organization', () async {
      final organization = Organization(id: id, name: 'FhirFli');
      final saved = await resourceDao.save('newPw', organization);

      expect(saved.id, id);

      expect((saved as Organization).name, 'FhirFli');
    });

    test('Save Observation1', () async {
      final observation1 = Observation(
        id: Id('obs1'),
        code: CodeableConcept(text: 'Observation #1'),
        effectiveDateTime: FhirDateTime(DateTime(1981, 09, 18)),
      );
      final saved = await resourceDao.save('newPw', observation1);

      expect(saved.id, Id('obs1'));

      expect((saved as Observation).code.text, 'Observation #1');
    });

    test('Save Observation1 Again', () async {
      final observation1 = Observation(
          id: Id('obs1'),
          code: CodeableConcept(text: 'Observation #1 - Updated'));
      final saved = await resourceDao.save('newPw', observation1);

      expect(saved.id, Id('obs1'));

      expect((saved as Observation).code.text, 'Observation #1 - Updated');

      expect(saved.meta?.versionId, Id('2'));
    });

    test('Save Observation2', () async {
      final observation2 = Observation(
        id: Id('obs2'),
        code: CodeableConcept(text: 'Observation #2'),
        effectiveDateTime: FhirDateTime(DateTime(1981, 09, 18)),
      );
      final saved = await resourceDao.save('newPw', observation2);

      expect(saved.id, Id('obs2'));

      expect((saved as Observation).code.text, 'Observation #2');
    });

    test('Save Observation3', () async {
      final observation3 = Observation(
        id: Id('obs3'),
        code: CodeableConcept(text: 'Observation #3'),
        effectiveDateTime: FhirDateTime(DateTime(1981, 09, 18)),
      );
      final saved = await resourceDao.save('newPw', observation3);

      expect(saved.id, Id('obs3'));

      expect((saved as Observation).code.text, 'Observation #3');
    });
  });

  group('Password - Finding Things:', () {
    test('Find 1st Patient', () async {
      final search = await resourceDao.find('newPw',
          resourceType: R4ResourceType.Patient, id: id);
      final humanName = HumanName(family: 'Atreides', given: ['Duke']);

      expect(search.length, 1);

      expect((search[0] as Patient).name?[0], humanName);
    });

    test('Find 3rd Observation', () async {
      final search = await resourceDao.find('newPw',
          resourceType: R4ResourceType.Observation, id: Id('obs3'));

      expect(search.length, 1);

      expect(search[0].id, Id('obs3'));

      expect((search[0] as Observation).code.text, 'Observation #3');
    });

    test('Find All Observations', () async {
      final search = await resourceDao.getResourceType(
        'newPw',
        resourceTypes: [R4ResourceType.Observation],
      );

      expect(search.length, 3);

      final idList = [];
      for (final obs in search) {
        idList.add(obs.id.toString());
      }

      expect(idList.contains('obs1'), true);

      expect(idList.contains('obs2'), true);

      expect(idList.contains('obs3'), true);
    });

    test('Find All (non-historical) Resources', () async {
      final search = await resourceDao.getAll('newPw');

      expect(search.length, 5);
      final patList = search.toList();
      final orgList = search.toList();
      final obsList = search.toList();
      patList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Patient);
      orgList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Organization);
      obsList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Observation);

      expect(patList.length, 1);

      expect(orgList.length, 1);

      expect(obsList.length, 3);
    });
  });

  group('Password - Deleting Things:', () {
    test('Delete 2nd Observation', () async {
      await resourceDao.delete(
          'newPw', null, R4ResourceType.Observation, Id('obs2'), null, null);

      final search = await resourceDao.getResourceType(
        'newPw',
        resourceTypes: [R4ResourceType.Observation],
      );

      expect(search.length, 2);

      final idList = [];
      for (final obs in search) {
        idList.add(obs.id.toString());
      }

      expect(idList.contains('obs1'), true);

      expect(idList.contains('obs2'), false);

      expect(idList.contains('obs3'), true);
    });

    test('Delete All Observations', () async {
      await resourceDao.deleteSingleType('newPw',
          resourceType: R4ResourceType.Observation);

      final search = await resourceDao.getAll('newPw');

      expect(search.length, 2);

      final patList = search.toList();
      final orgList = search.toList();
      patList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Patient);
      orgList.retainWhere(
          (resource) => resource.resourceType == R4ResourceType.Organization);

      expect(patList.length, 1);

      expect(patList.length, 1);
    });

    test('Delete All Resources', () async {
      await resourceDao.deleteAllResources('newPw');

      final search = await resourceDao.getAll('newPw');

      expect(search.length, 0);

      await resourceDao.updatePw('newPw', null);
    });
  });
} 

Download Details:

Author: MayJuun

Source Code: https://github.com/MayJuun/fhir/tree/main/fhir_db

#sqflite  #dart  #flutter 

Cayla  Erdman

Cayla Erdman

1601549700

What’s New In Typescript 4.0?

Today I am going to talk about new features in Typescript 4.0.

TypeScript 4.0 comes with lots of new features to make JavaScript development easier.

Labeled Tuple Elements

You can label tuple elements.

You can write:

type Range = [start: number, end: number];

to restrict args to have a string and a number.

you can also write:

type Foo = [first: number, second?: string, ...rest: any[]];

to have rest entries in your tuple.

If your tuple has type Foo, then the tuple starts with a number and a string.

Then the rest of the entries can be anything.

Labels don’t require you to name your variables differently when destructuring.

For example, if you have:

function foo(x: [first: string, second: number]) {
  const [a, b] = x;
}

then you can name the destructured variables anything you want.

#software-development #typescript-with-react #typescript #typescript-4 #react native