Using WebView with Flutter

Flutter comes with many packages that grant the possibility to run web pages in mobile apps. After research, the leader has been found: webview_flutter.

Why webview_flutter

First of all, it is currently maintained by the official Google team. When the development started, there were no official recommendations by the Flutter team on which package should be used.

The second reason why we started using this package — it gives us the possibility to share data between the web page and the flutter application in two directions. This feature was crucial when we investigated this case.

On iOS the WebView widget is backed by a WKWebView; On Android, the WebView widget is backed by a WebView.

How to set up webview_flutter

The setup is pretty easy. Install the library using the description on the official page.

How do we get data from a web page

JavascriptChannel gives us possibility to get data from web page. We set it up in the javascriptChannels list:

Firstly we choose the name for the channel in name parameter. This name will used to access channel from inside the web page. When we call the method channel from the page, onMessageReceived will be fired transporting the message.

Now let’s see how to send messages from the page. Firstly, webview_flutter mutates window object. If a web page has been loaded using this package it will have a property that we have defined in JavascriptChannel. In our case we can access the channel by calling:

We can use postMessage method to pass data to WebView and trigger onMessageReceived callback.

If you should use TypeScript in your project, you will need to override Window interface using following syntax:

How to pass data to a web page

In this particular case, we can not just use a JavascriptChannel, we should somehow inject some JavaScript code that will fire messages inside the web page. In this case, the web page will have a subscriber that will process the data received from the app.

The packagewebview_flutter comes with a solution. We can use WebViewController class that has runJavascript(String script) method:

Once script is executed and message is fired, a callback from inside the page is triggered:

Summary

In this article we have successfully transported data from a web page into Flutter application using WebView and vice versa.

Web page:

Send data: window.WebViewUserLocation.postMessage('');

Receive data: window.addEventListener('message', onMessageReceived);

Flutter app:

Send data:

Receive data: use JavascriptChannel

How to prevent sensitive data leakages through code repositories

Version control software (VCS) is essential for most modern software development practices. Among other benefits, software like Git, Mercurial, Bazaar, Perforce, CVS, and Subversion allows developers to save snapshots of their project history to enable better collaboration, revert to previous states, recover from unintended code changes, and manage multiple versions of the same codebase. These tools allow multiple developers to safely work on the same project and provide significant benefits even if you do not plan to share your work with others.

Although it is important to save your code in source control, it is equally important for some project assets to be kept out of your repository. Certain data like binary blobs and configuration files are best left out of source control for performance and usability reasons. But more importantly, sensitive data like passwords, secrets, and private keys should never be checked into a repository unprotected for security reasons.

Checking your Git Repository for Sensitive Data

First of all, once you started managing your secret security you need to check the repository for certain data. If you know an exact string that you want to search for, you can try using your VCS tool’s native search function to check whether the provided value is present in any commits. For example, with git, a command like this can search for a specific password:

git grep my_secret $(git rev-list --all)

Setting the security

Once you have removed sensitive data from the repository you should consider setting some internal tools to ensure you did not commit those files.

Ignoring Sensitive Files

The most basic way to keep files with sensitive data out of your repository is to leverage your VCS’s ignore functionality from the very beginning. VCS “ignore” files (like .gitignore) define patterns, directories, or files that should be excluded from the repository. These are a good first line of defense against accidentally exposing data. This strategy is useful because it does not rely on external tooling, the list of excluded items is automatically configured for collaborators, and it is easy to set up.

While VCS ignore functionality is useful as a baseline, it relies on keeping the ignore definitions up-to-date. It is easy to commit sensitive data accidentally prior to updating or implementing the ignore file. Ignore patterns that only have file-level granularity, so you may have to refactor some parts of your project if secrets are mixed in with code or other data that should be committed.

Using VCS Hooks to Check Files Prior to Committing

Most modern VCS implementations include a system called “hooks” for executing scripts before or after certain actions are taken within the repository. This functionality can be used to execute a script to check the contents of pending changes for sensitive material. The previously mentioned git-secrets tool has the ability to install pre-commit hooks that implement automatic checking for the type of content it evaluates. You can add your own custom scripts to check for whatever patterns you’d like to guard against.

Repository hooks provide a much more flexible mechanism for searching for and guarding against the addition of sensitive data at the time of commit. This increased flexibility comes at the cost of having to script all of the behavior you’d like to implement, which can potentially be a difficult process depending on the type of data you want to check. An additional consideration is that hooks are not shared as easily as ignore files, as they are not part of the repository that other developers copy. Each contributor will need to set up the hooks on their own machine, which makes enforcement a more difficult problem.

Adding Files to the Staging Area Explicitly

While more localized in scope, one simple strategy that may help you to be more mindful of your commits is to only add items to the VCS staging area explicitly by name. While adding files by wildcard or expansion can save some time, being intentional about each file you want to add can help prevent accidental additions that might otherwise be included. A beneficial side effect of this is that it generally allows you to create more focused and consistent commits, which helps with many other aspects of collaborative work.

Rules that you need to consider:

  • Never store unencrypted secrets in .git repositories. 
    A secret in a private repo is like a password written on a $20 bill, you might trust the person you gave it to, but that bill can end up in hundreds of peoples hands as a part of multiple transactions and within multiple cash registers.
  • Avoid git add * commands on git. 
    Using wildcard commands like git add *or git add . can easily capture files that should not enter a git repository, this includes generated files, config files and temporary source code. Add each file by name when making a commit and use git status to list tracked and untracked files.
  • Don’t rely on code reviews to discover secrets.
    It is extremely important to understand that code reviews will not always detect secrets, especially if they are hidden in previous versions of code. The reason code reviews are not adequate protection is because reviewers are only concerned with the difference between current and proposed states of the code, they do not consider the entire history of the project.
  • Use local environment variables, when feasible.
    An environment variable is a dynamic object whose value is set outside of the application. This makes them easier to rotate without having to make changes within the application itself. It also removes the need to have these written within source code, making them more appropriate to handle sensitive data.
  • Use automated secrets scanning on repositories.
    Implement real time alerting on repositories and gain visibility over where your secrets are with tools like GitGuardian

People with Culture: bringing Mission and Values to life

In this article, we’ll talk about how a company’s values and culture help it implement its strategies and mission. We’ll start with some definitions and introductions and then will identify the possible issues and practical solutions.

Disclaimer: we’ll be using an IT company as an example, so some aspects may appear a bit subjective.

Values, Mission, Strategy

The mission defines the company’s global goal, while strategy leads to its implementation through culture and values.

To develop high-tech products the world and future you will be proud of — FusionWorks

Company values must change through the years. Not because the old ones were bad, but because they are bad for what the company represents now. This is a normal process of getting mature. Just see how Uber changed its initial ‘pirate’ values into more enterprise ones — or you may watch the “Super Pumped” series instead. The same changes we experience in our personal lives. Several times. If not — this is a sign to think your life over.

At FusionWorks, we are going through the same process over and over again, sometimes it’s painful and time-consuming. There are core values such as honesty, openness and inclusion that should not be changed, but upgrades are inevitable for lots of things you thought are here forever. I love this process, but you? Will be great to see your thoughts in the comments.

Values determine the company’s culture code. Here are some aspects of why culture is so important:

Culture is not the thing you write in the company’s employee handbook, it’s what people talk about when you are not around.

Strategy is a promise, corporate culture is the execution.

Culture eats strategy for breakfast.

Culture is formed around what you do, not what you say. If you say you are a company that values health and wellness but then brings in doughnuts every morning there is a disconnect. It’s fine to value doughnuts, who doesn’t love them but it’s not ok when your words don’t match your actions. It kills the trust you have in your team.

Job seekers are most likely to choose one job over another because of the chosen employer’s culture, according to talent acquisition professionals surveyed by the Korn Ferry Institute.

Having this said, a strong company needs to make sure it has its culture code and it’s working. At FusionWorks we use the people and culture approachwhich is a more progressive way of dealing with people. It is people-based, not policy-based.

If you treat people like people, they will be happier.

We can have a meaningful impact on people’s lives by giving them a working environment where they can be themselves and thrive. Understand and help your team grow together through positive activities and encouragement.

Manifesto

The manifesto is a more deliberate expression of your values and also supports the mission you have. It’s typically an emotional story that captivates your audience, emotionally connects with them, and persuades them to support your brand. It’s always a good idea to have it before we proceed to practical steps.

We build a no-bullshit company. No secrets, no lies, transparent, accountable, driven by facts, respectful to all. Openness in every aspect.

We love being tech-oriented and this infuses everything we do.

We believe being people-centric motivates and inspires much better than policies and control.

We are committed to being learning-driven, changing with the world, changing the world.

— FusionWorks

A practical guide to people-centric culture

First, let’s list the things that may make employees unhappy. It doesn’t mean your company has all of them, but they should be considered:

  1. Lack of progression and self-development.
  2. Unsatisfactory salary or benefits.
  3. Unhappiness with leadership.
  4. Lack of flexible schedules.
  5. Boring tasks.
  6. Negative experience/incident.
  7. Lack of recognition.
  8. Dissatisfaction with the company culture.
  9. A need for better work-life balance.

So here we go with implementing the People and Culture strategy. We aren’t forgetting about Human Resources, we value it and everything that goes along with it. HR is policies, procedures, and paperwork — all extremely important. But remember, People and Culture is people-based, not policy-based.

Once the employee has been onboarded (by the fabulous Human Resource team), it is time to improve their well-being, integrate them into the company, and show their value. This engagement improves productivity, creates a positive environment for the employee to thrive in, and generates happiness. Lower turnover, happier employees, and better work.

When we identify the issues, we may choose from the solutions below (not all of them work for all companies).

Supporting employees with talent and career development programs

  1. Implement the grading system — Roles and Levels — and make sure it’s well-defined.
  2. Assign employees to their current Levels. Explain their Roles.
  3. Clearly define the steps to progress to the next level.
  4. Revise the employees’ levels once in 6 months.
  5. Acknowledge employees’ successes.

According to LinkedIn, 94 percent of employees would stay at a company if it invested in their career development.

Development programs should be designed to ensure alignment between your expectations for top talent and the organization’s goals and vision. Professional development can include coaching processes, training seminars, networking opportunities, mentoring, special projects, and more.

Creating a more flexible schedule

The reason for that is the world trend toward remote work. So if it is possible with your company — consider it.

  1. Allow flexible schedule.
  2. Allow remote work if possible.
  3. Encourage a healthy work-life balance.

Many employees value a flexible work environment over compensation. In fact, 72 percent of employees would search for new opportunities if their schedule wasn’t flexible. Implementing changes to work policies can help improve retention rates.

Implementing a feedback and performance appraisal process

  1. Regularly get feedback from clients (once in 3-6 months).
  2. Pass feedback to employees.

Feedback is especially useful during the development of retention plans, and 82 percent of employees appreciate it. Feedback is essential in a remote environment; it establishes a benchmark for behaviors and skills and highlights what employees need to remain happy with their employer. Companies must be open to listening to employees and implementing changes and actions required to keep top talent.

Employee turnover can be reduced by up to 31% by managers acknowledging employee successes. Source.

Offering challenging projects where people matter

  1. Work with the clients directly.
  2. Work on interesting projects that matter.
  3. Make sure the clients listen to the voices of the employees.
  4. Make sure our employees are growing and learning on the projects.
  5. Fire bad clients.

Developing an effective employer branding strategy

Showing you are great or being great? Both. Showing your successes with no real wins doesn’t work long-term and leads to internal discontent. Being great without showing this externally won’t make the employees feel proud of the company, as well as your potential customers and employees won’t know how beautiful you are.

Companies are u̶g̶l̶y̶ copies of their founders.

People want to work in a company which grows together with them, faster than them. Also, they rarely work for those and with those whom they don’t respect at least professionally, who are weaker.

  1. Plan marketing strategy: current employees, potential employees, and customers.
  2. Communicate company strategy, mission and successes both internally and externally.
  3. Engage employees in the company’s activities.

According to a LinkedIn study, a strong employer brand can reduce turnover by 28 percent and the cost of hiring by 50 percent.

The communication and dissemination of the company’s image and actions are key to maintaining employees’ interest in remaining with the company and contributing to its success through specific projects.

46% of employees stated that a lack of transparent leadership communication is driving them to seek new employment. Meanwhile, 79% of highly engaged employees have trust and confidence in their leaders. Source.

Making culture work

  1. Clearly define the company’s mission, culture, and values.
  2. Show employees the big picture and goals.
  3. Explain mission and values.
  4. Believe in your mission and values. If you don’t believe — change them.
  5. Follow them — management should be an example.
  6. Show how mission and values work in practice.

Offering competitive benefits

  1. Offer what others have.
  2. Offer what others don’t have (to stand out).
  3. Offer benefits that make employee’s life comfortable and disappear when they leave the company.

Companies that offer competitive compensation and benefits can see 56 percent lower attrition. With the ever-changing labor market, companies need to adapt to employees’ evolving and growing needs and expectations. Nowadays, the most valuable benefits include remote work flexibility, employee discounts, time off, and financial advice.

Creating an open environment

  1. Encourage employees to speak and voice their concerns, ideas, and opinions.
  2. Treat all employees equally, on all levels. No favoritism.
  3. Treat your employees as you treat your best customers.
  4. Create an environment where everyone feels comfortable and safe.

No one wants to feel excluded in an organization they are a part of. New hire wants to feel like they were hired for a reason, and that they are playing a key role in helping the business achieve its objectives.

Josh Bersin, founder and principal at Bersin by Deloitte, found that companies who deliberately work to encourage inclusion, diversity, development planning, and leadership development in their culture were 3.8 times more likely to be able to coach people for improved performance, 3.6 times more able to deal with personnel performance problems, and 2.9 times more likely to identify and build leaders. Source.

Instead of epilogue

In the final chapter, I’d like to show you the FusionWorks values we believe in and share with the team. They determine our culture code:

Shared understanding in everything we do. Nobody has a monopoly on the truth. Decisions are made together and actions are reasoned on all levels.

People over processes. We encourage independent decision-making and believe in the power of freedom and responsibility.

Building cognitive diversity. Inventions are done by teamwork with people with different mindsets and competencies.

Building quality products. The things we do determine who we are, create our reputation step by step and reflect our eternal pursuit of excellence.

Learning never stops. We believe gaining knowledge is a continuous process and help you invest in your education for mutual benefit.

Sharing is caring. We share our experience — successes and failures — to help others learn and grow.

Building long-term relationships. Both our employees and clients are the people we want to work with long-term.

Learn, make impact, have fun. We always support initiative, awareness, quality, spirit and creativity. As simple as it sounds.

Like, comment, share — it’s always welcome!

7Cs as the pillar of retention

A trust or corporate trust is a large grouping of business interests with significant market power, which may be embodied as a corporation or as a group of corporations that cooperate with one another in various ways. — FusionWorks

In the past, interpersonal relationships were created on the concept — I trust you until you will demonstrate I shouldn’t.

Today, due to competitiveness and many cultural reasons, interpersonal relationships are based on the concept — I do not trust you until you demonstrate I may.

I am not sure which theory is better, but we may surely agree that you may be an enthusiast, competent, and genius, but this means nothing for your success until others believe in you.

Any interpersonal relationship is based on trust and the relationship between employee-employer or the one between client-provider are not exceptions at all. Trust is like a safe feeling in someone’s sincerity. It is the firm belief that a company (it’s management, your colleagues and its services) retains its integrity, quality, and brand for a predictable period of time.

In practice, inspiring someone to trust you is a really hard work of mixing 7 essential elements. These are 7 ”C”-s of trust. Let’s discover them together.

First C is for CHARACTER
A company’s character, its Identity is the most difficult to fake, as this is the moral quality that manifests itself through perseverance, the firm will, and fairness. These are the primordial elements for someone to be trustworthy. One of the best ways to prove that you could be trusted is to accept when you are wrong. Everyone appreciates the courage to admit one’s own imperfection.

Second C is for COMPETENCE
It is very important to always find time for the personal and professional development of your skills. This is why, FusionWorks is always for sharing knowledge and we inspire our employees to learn continuously as learning is life, especially in our field. Competence in any field means training, reading, learning, and implementing in practice any single skill.

Nr. 3 C is for CONSOLIDATION of the company’s values 
This aspect is crucial as this is one of the first things to be observed by others. One’s first impression of your company is made in the first moments of your communication. The following moments from any discussion are for validating that first impression. This is why, when some of your employees are not sure about your company’s value, this is felt. The whole conversation will be dominated by a wrong/bad — emotions domino.

This article is powered by Empy.io — an all-in-one tool that helps HRs synchronize with the employees and handle all the internal requests in one single place. Try it for free!

4th C is for CONGRUENCE
Trust increases every time your actions (any employees ones) confirm your words (company-culture). The key is the harmony between verbal and non-verbal messages you and your employees spread into the world. In the lack of this harmony, your interlocutor could not believe your message and will have no trust in you as a company.

5th C is for CREDIBILITY
Credibility is the ability or power to stimulate the trust of others in your company. It means letting the person we spoke with understand that you, as a company, know very well what you are talking about and if they follow your advice, it will be good for them later. This C is the one most felt in the sales and in the recruitment field. As you will never get a super-contract or a rocket star without demonstrating your credibility.

6th C is for CONSISTENCE
consistent company easily gains the trust of others, no matter who are those — partners, clients, candidates, or employees. It is all too well known in marketing that a brand image is not built overnight. People need time to adapt, time to test, to form opinions, and to disseminate them.

7th C equals to COMPLETENESS
People generally have a very strong desire to close the processes that have begun. This “closure” eliminates stress. The explanation is given by a subtle psychological mechanism that shows that the value of stress is directly proportional to the number of unfinished processes. More specifically, when you have 15 distinct activities to solve, you will be more stressed than if you have only one, which involves the same length of work/time to complete. On this principle, we prefer not to engage in activities that do not seem to have a clear and predictable purpose. Consequently, in order to inspire trust, it is very important that what you offer, as a company — your product or service has a beginning and an end. When people know the purpose of an idea, they are more likely to believe in it.

When employees/clients are trusting that the organization provides them with (access to) their goal, both the employee/client and the company will benefit because

a) employee trust is the reason for employees to be motivated, productive and happy. What your employees give back makes the decision to focus on employee trust easier for business leaders. Or, as for many organizations who recognize the importance, it makes employee trust a top priority.

b) client trust is crucial for successful and productive-long-collaborations. This means greater advocacy, loyalty, and engagement from clients. This sets the tone for your business, and as clients advocate, businesses will be able to attract more customers who are ready to invest in their offering.

Encoding, storage, and retrieval OR about MEMORY, simple

As sharing is caring, in this article you will find some good lectures and curious experiments.- FusionWorks

One of my favorite definitions of ”Memory” is that this represents the process of maintaining information over time. Our memory helps us discover the world. We do not need every time a lot of information to absorb and to try to figure it out dealing with classifications or comparison.

There are moments when, being too engaged in an activity we forgot some elementary staff like to eat, to respond to a message, etc. In the era of information, it is a priority to understand fast and proceed to complete future tasks instead of analyzing what do we miss.

A large part of the research on memory is based on experiments conducted in laboratories. Those who take part in the experiments — the participants — are asked to perform tasks such as recalling lists of words and numbers. Both the setting — the laboratory — and the tasks are a long way from everyday life. In many cases, the setting is artificial and the tasks fairly meaningless. Does this matter? How can this help?

Memory is a single term that reflects a number of different abilities: holding information briefly while working with it (working memory), remembering episodes of one’s life (episodic memory), and our general knowledge of facts of the world (semantic memory), among other types. Remembering episodes involves three processes: encoding information (learning it, by perceiving it and relating it to past knowledge), storing it (maintaining it over time), and then retrieving it (accessing the information when needed). Failures can occur at any stage, leading to forgetting or to having false memories. The key to improving one’s memory is to improve processes of encoding and to use techniques that guarantee effective retrieval.

This article is powered by Empy.io — an all-in-one tool that helps HRs synchronize with the employees and handle all the internal requests in one single place. Try it for free!

Increasing your memory may help you in different manners. Firstly, you will force your brain to think, you will exercise it and make it stronger. Secondly, you will be much more productive. And third — your general well-being will increase as a result of self-esteem. Does this sound perfect? It is also easy to achieve!

  • Associate — combine what you want to remember with what you already know. You can associate places with people, names with songs, phone numbers with birthdays.
  • Practice — our brain has supernatural powers if we have enough patience to develop them. We can calculate in mind, memorize a voluminous number, or complete sudoku, what do you choose?
  • Focus — when we learn something new and quickly forget, we blame our memory, when in fact we were not paying attention to what we were doing. When you do something (or learn) dedicate yourself to the activity 100%. Being fully involved you will be surprised by the results!
  • Chewing gum — some research has shown that chewing gum improves memory. Thus, chewing gum during an exam can make it easier to remember everything we have learned.
  • Build a palace of memory — it’s an exercise for hundreds of years, but just as great. According to this technique, we are supposed to remember more easily anything with the idea that we have visual memories related to that something (it doesn’t matter if it’s real or imaginary).
  • Avoid stress — felt for a long time, stress affects the normal functioning of the brain, therefore decreasing memory capacity. As much as we can, let’s avoid it, finding more time for relaxing.
  • Get enough sleep — if your sleep doesn’t reach at least 7 hours a night, your brain has nowhere to take energy to function wonderfully.
  • Eat healthily — scientific studies have shown the link between food and memory. So, in order to improve it, we need vegetables, fruits, seafood, and green tea.
  • Keep fit — if your body is healthy, so will your mind. Exercising 20 minutes a day, we will look more beautiful not only physically, but also in terms of memory.
  • Read — you can improve your creativity by reading something special and imagining your video. In this way, you put your brain to work, and during the construction of images, you also develop your memory.

Yes, it seems like all these techniques are viable and all of them may be experienced very simply, but could these also feed the Misinformation Effect?

In a famous experiment conducted by Loftus, participants were shown video footage of a traffic accident. After watching the clip, the participants were then asked a number of questions about what they had observed, much in the same way police officers, accident investigators, and attorneys might question an eyewitness.

One of the questions asked was, “How fast were the cars going when they hit each other?” In some instances, however, a subtle change was made; participants were instead asked how fast the cars were going when they “smashed into” each other. What the researchers discovered was that simply using the word “smashed” instead of “hit” could change how the participants remembered the accident.

A week later, the participants were once again asked a series of questions, including “Did you see the broken glass?” Most of the participants correctly answered no, but those who had been asked the “smashed into” version of the question in the initial interview were more likely to incorrectly believe that they had indeed seen broken glass.

How can such a minor change lead to such differing memories of the same video clip? Experts suggest that this is an example of the misinformation effect at work. Other interesting experiments that seem curious.

The best version of employees — HOW and WHY

”…the most efficient way to make your employees happy is to understand their needs and mindsets.” — FusionWorks

A happy employee is a productive one. This is why it is very important to understand what makes not any, but YOUR employees happy. Knowing the individual motivators we may share care and strengthen what really matters.

Yes, it is priorly to allocate resources for employees’ motivation. What drives someone starts with communication. An empathic, non-violent (reading recommendation), and assertive one — this is when we learn to understand our employees, not only pretend we do. Mental and physical health at work is totally dependent on the working atmosphere. If you need a healthy employee you have to work on his / her well-being. This is a long process. Do not be scared or afraid when results will need time to be seen. This is normal. Below will be listed some crucial axioms to control and influence your employee motivation and in this way — to help them become the best versions of themselves. All of these were summarized while tested in time, on different employees (the difference was in one or some of these factors: age, gender, interests, temperament, education, and background), and could be used as steps for employee-admiration.

  1. When satisfaction and benefits are in a correlation with work-volumewe see a happy employee. We may easily monitor this correlation with 3 simple tools: 1–1’s, onboardings, performance review (in ideal cases onboardings and performance review meetings will be conducted by TL & HR), questionnaires (with direct questions and metaphorical ones, anonymous and not). Honestly, first in this list is my favorite tool, as during 1-on-1 it is very easy to understand the person you interact with. And this is much more than words. Here every single gesture is special and every single selected topic is crucial. Without a psychological background, things could be a little more challenging, but we are so lucky! A lot of information is available online and after some search and good reading — anyone could coordinate an awesome 1–1. Another advantage is that no 1-on-1 is the same. So, this kind of discussion is fascinating!

This article is powered by Empy.io — an all-in-one tool that helps HRs synchronize with the employees and handle all the internal requests in one single place. Try it for free!

2. Leaders influence employees. All of us need approval, no matter how old or how experienced we are. Being in a room where you have a leader, you need to understand that he/she is here for you. That you may ask anything and you will receive the needed / correct answer. The easiest way to influence your employees positively is to be an example they would love to follow: do not be afraid to ask for help (we are all humans, we all need help sometimes with something, and this is normal), do not doodle from answering questions (even if tricky ones. Find a real response and operate with it). If you want something to be changed, be the first who not only is ready for a change but has already begun this brilliant process: take different tasks, enroll in different pieces of training and projects (why not along with your employees).

3. A constructive, positive, and empathic attitude towards your employees encourages them to express their ideas and visions freely, to communicate as openly as possible, without fear of making mistakes or being judged. They said people never leave jobs, they leave bosses or teams. So help your team be the one everyone dreams to become a part of. Steps to be taken: grow a collaborative work-culture (team responsibility — team decisions, brand bearers while participating in different non-work-related activities), cherish your team (praise concrete behavior, encourage employees individuality, create a context for creativity expressing).

The most important, but at the same time, the most beautiful way to make your employees happy is to understand everyone’s needs and mindsets. Knowing what drives every single employee, investing in his/her wellbeing, we will reach the win-win solution: a happy employee is a productive one, a productive one is a valuable one, a valuable one is the loyal one. Loyal employees are the treasure any respectable company deserves.

Dear Procrastination, let’s break up!

“… procrastination is a well-known process: we leave the tasks for the last moment, then we panic.”

Your deadline is here. But your task is not in progress, it is not even started yet. And you do not rush to do it. You may recheck a 10th time if you have a new message. You may remind yourself about a very interesting video that must be reseen at this very moment. You are hungry. You have to respond to an urgent call. Yes, you understand that you need to work. Also you, as a rational being, understand that you have to force yourself to start this task/activity. But it is simply impossible. Yes, procrastination is a well-known process. We leave the things we have to do for the last moment, then we panic. Do you remember the Panic Moster Ted talk? This habit destroys us, but what would be the solution? Here are some options:

This article is powered by Empy.io — an all-in-one tool that helps HRs synchronize with the employees and handle all the internal requests in one single place. Try it for free!

1. Divide everything you need into small pieces. They say it is impossible to eat an elephant, but it could be done by breaking it into small pieces. One of the causes of procrastination is the understanding, on a subconscious level, of the excessive volume of the task. Focusing on small things we will be willing to quickly finish what we set out.

2. Change the work environment. Different environments have different impacts on our productivity. Choose where it is easier for you to do a certain activity.

3. Draw up a calendar and set deadlines for every particular activity. Having a single deadline for all activities is like an invitation to procrastinate.

4. Eliminate distracting factors. One of the reasons for procrastination is the availability of other occupations, so limit your access to what distracts you. Put the phone on silent, close all tabs where you do not work, do not leave any opportunity to escape!

5. Communicate with people who inspire you to action. The people in our entourage directly influence our behavior. By interacting with other people, each of us takes something from the interlocutor.

6. Clarify your goal. Maybe the cause of procrastination is the discrepancy between what you want to achieve and what you do. It happens that during our journey in reaching the goal, we grow and we already have other desires and needs. Instead of wasting time, take a break and decide what you really want to achieve.

7. Don’t complicate things. Are you waiting for a perfect time to start? Now is not the right time to start because x, y, z? Here’s a secret — the perfect moment will never be or is right now, you choose!

Wix + Viar.Live: VR websites made easy

Several years ago we at FusionWorks launched our awesome tool for 360° photographers — Viar.Live. Its goal was to offer an easy-to-use tool for creating virtual tours from 360° photos. Viar.Live was warmly accepted by the users and we got a lot of positive feedback, but one email really surprised us: we were approached by Wix with the suggestion of joining their app market with our application, which we eagerly accepted. The journey was not easy since Wix has a lot of specific requirements with which we had to comply, but finally we made it through and now it’s time to present the results.

Finding the Virtual Tours app on the market place

Just type “Virtual” in the Wix App Market or follow this link and add our app to your website.

Creating your first tour

To create a tour you don’t need to specifically create a 360° photo — any panorama made on your smartphone will work. Just click “Get Started” in the application settings and upload your photos.

Once the uploading and processing are over, click “Continue” to proceed to the tour editor. Once in it, start connecting panoramas by dragging thumbnails into appropriate connection places.

Besides connection points, you can also add link and information hotspots.

Once finished, just assign a newly created tour to the Virtual Tours widget and share your website!

Have a great day!

Genadii Ganebnyi,
CEO @ Viar.Live

Creating admin-like web applications with NestJS and React Admin. Part 2.

Introduction

In the first part, we showed how React Admin and NestJS can work together to quickly create a simple admin panel.

In this part, we will go a little bit beyond basic CRUD and cover the following topics:

  1. Handling one-to-many relationships
  2. Handling file uploads to Amazon S3
  3. Using the Google Maps input

Handling one-to-many relationships

To showcase this (and other points), we will change the domain model of our application. So instead of a guest list, we will manage companies and their addresses.

This will require the following entities and controllers to added to our API:

  • Company Entity with a declared relationship with Address Entity:
import {
Entity,
Column,
PrimaryGeneratedColumn,
BaseEntity,
OneToMany,
} from 'typeorm';
import { Type } from 'class-transformer';
import { AddressEntity } from '../address/address.entity';@Entity({ name: 'company' })
export class CompanyEntity extends BaseEntity {
@PrimaryGeneratedColumn()
id: number; @Column()
name: string; @Column()
description: string; @Column({
type: 'json',
comment: `[{ name: "string", url: "string"}]`,
nullable: true,
})
cover: Array<{ name: string, url: string }>; @OneToMany((type) => AddressEntity, (address) => address.company)
@Type((t) => AddressEntity)
addresses: AddressEntity[];

}
  • Address Entity:
import {
Entity,
Column,
PrimaryGeneratedColumn,
ManyToOne,
BaseEntity,
} from 'typeorm';
import { CompanyEntity } from '../company/company.entity';@Entity({ name: 'address' })
export class AddressEntity extends BaseEntity {
@PrimaryGeneratedColumn()
id: number; @Column()
name: string; @Column()
city: string; @Column()
street: string; @Column()
zip: string; @Column()
notes: string; @Column({ nullable: true })
companyId: number;
@ManyToOne(
(type) => CompanyEntity,
(company) => company.addresses
)
company: CompanyEntity;

}

The controllers for these entities are created using @nestjsx/crud. You can see how this can be done in the previous article.

From the admin UI perspective, we have to add new resources:

import React from 'react';
import { Admin, Resource } from 'react-admin';
import crudProvider from '@fusionworks/ra-data-nest-crud';
import companies from './Companies';
import addresses from './Addresses';
import { url } from './config/connection';const dataProvider = crudProvider(url);const App = () => (
<Admin dataProvider={dataProvider}>
<Resource name="company" {...companies} />
<Resource name="address" {...addresses} />
</Admin>
);export default App;

Add a file with views for address entity:

import React from 'react';
import {
Create,
SimpleForm,
TextInput,
Edit,
required,
TabbedShowLayout,
Tab,
TextField,
Show,
ReferenceField,
List,
Datagrid,
ReferenceInput,
SelectInput,
} from 'react-admin';const validateRequired = required();export const AddressCreate = props => {
const { location } = props;
const { companyId } = parse(location.search);
const redirect = companyId ? `/company/${companyId}/show/addresses`: false; return (
<Create {...props}>
<SimpleForm redirect={redirect}>
<TextInput source="name" validate={validateRequired} />
<TextInput source="city" validate={validateRequired} />
<TextInput source="street" validate={validateRequired} />
<TextInput source="zip" validate={validateRequired} />
<TextInput source="notes" validate={validateRequired} />
{companyId ? null : (
<ReferenceInput source="companyId" reference="company">
<SelectInput optionText="name" optionValue="id" />
</ReferenceInput>
)}
</SimpleForm>
</Create>
);
};const AddressTitle = ({ record }) => (<span>{`${record.name}`}</span>);export const AddressEdit = props => (
<Edit {...props} title={<AddressTitle />}>
<SimpleForm redirect={(basePath, id, data) =>
`/company/${data.companyId}/show/addresses`}>
<TextInput source="name" validate={validateRequired} />
<TextInput source="city" validate={validateRequired} />
<TextInput source="street" validate={validateRequired} />
<TextInput source="zip" validate={validateRequired} />
<TextInput source="notes" validate={validateRequired} />
</SimpleForm>
</Edit>
);export const AddressList = props => (
<List {...props}>
<Datagrid rowClick="show">
<TextField source="name" />
<TextField source="city" />
<TextField source="street" />
<TextField source="zip" />
<TextField source="notes" />
<ReferenceField
source="companyId"
reference="company"
linkType="show"
>
<TextField source="name" />
</ReferenceField>
</Datagrid>
</List>
);export const AddressShow = props => (
<Show {...props}>
<TabbedShowLayout>
<Tab label="resources.summary.name">
<TextField source="name" />
<TextField source="city" />
<TextField source="street" />
<TextField source="zip" />
<TextField source="notes" />
<ReferenceField
source="companyId"
reference="company"
linkType="show"
>
<TextField source="name" />
</ReferenceField>
</Tab>
</TabbedShowLayout>
</Show>
);export default {
list: AddressList,
create: AddressCreate,
edit: AddressEdit,
show: AddressShow,
};

Convert the company view form to a tabbed interface and add a control for displaying existing addresses to the second tab:

import React from 'react';
import randomstring from 'randomstring';
import { S3FileInput, S3FileField } from '@fusionworks/ra-s3-input';
import {
TabbedShowLayout,
Tab,
List,
Create,
SimpleForm,
Edit,
Show,
ReferenceManyField,
Datagrid,
EditButton,
TextField,
TextInput,
required,
} from 'react-admin';
import { url } from '../config/connection';
import AddAddressButton from './AddAddressButton';const validateRequired = required();const CompanyCreate = (props) => (
<Create {...props}>
<SimpleForm redirect="show">
<TextInput source="name" />
<TextInput source="description" />
</SimpleForm>
</Create>
);const CompanyTitle = ({ record }) => (<span>{record.name}</span>);const CompanyEdit = props => (
<Edit {...props} title={<CompanyTitle />}>
<SimpleForm redirect="list">
<TextInput source="name" />
<TextInput source="description" />
</SimpleForm>
</Edit>
);const CompanyShow = props => (
<Show {...props} title={<CompanyTitle />}>
<TabbedShowLayout>
<Tab label="summary">
<TextField source="name" />
<TextField source="description" />
</Tab>
<Tab label="addresses" path="addresses">
<ReferenceManyField reference="address" target="companyId" addLabel={false}>
<Datagrid>
<TextField source="name" />
<TextField source="city" />
<TextField source="street" />
<TextField source="notes" />
<EditButton />
</Datagrid>
</ReferenceManyField>
<AddAddressButton />
</Tab>
</TabbedShowLayout>
</Show>
);const CompanyDescription = ({ record }) => {
return <div>{record.description}</div>;
};
const CompanyList = props => (
<List {...props}>
<Datagrid rowClick="show" expand={<CompanyDescription />}>
<TextField source="name" />
</Datagrid>
</List>
);export default {
list: CompanyList,
create: CompanyCreate,
edit: CompanyEdit,
show: CompanyShow,
};

And finally, add an “Add address” button which will open the create address form:

import React from 'react';
import { Link } from 'react-router-dom';
import { withStyles } from '@material-ui/core/styles';
import { Button } from 'react-admin';const styles = {
button: {
marginTop: '1em',
},
};const AddAddressButton = ({ classes, record }) => (
<Button
className={classes.button}
variant="raised"
component={Link}
to={`/address/create?companyId=${record.id}`}
label="Add an address"
title="Add an address"
/>
);export default withStyles(styles)(AddAddressButton);

Handling file uploads to Amazon S3

Let’s say we would like to add some photos to our company record. We will store them on Amazon S3. To handle it from the UI perspective, we created a custom React Admin input — https://github.com/FusionWorks/react-admin-s3-file-upload/. Here is how it should be added to our application:

import randomstring from 'randomstring';
import { S3FileInput, S3FileField } from '@fusionworks/ra-s3-input';
import { url } from '../config/connection';
...
const CompanyCreate = (props) => (
<Create {...props}>
<SimpleForm redirect="show">
<TextInput source="name" />
<TextInput source="description" />
<S3FileInput
apiRoot={url}
source="cover"
validate={validateRequired}
uploadOptions={{
signingUrl: `${url}/s3/sign`,
s3path: `NestJsAdminBoilerplate/${randomstring.generate(10)}`,
multiple: true,
accept: 'image/*',
}}
multipleFiles
/>

</SimpleForm>
</Create>
);const CompanyTitle = ({ record }) => (<span>{record.name}</span>);const CompanyEdit = props => (
<Edit {...props} title={<CompanyTitle />}>
<SimpleForm redirect="list">
<TextInput source="name" />
<TextInput source="description" />
<S3FileInput
apiRoot={url}
source="cover"
validate={validateRequired}
uploadOptions={{
signingUrl: `${url}/s3/sign`,
s3path: `NestJsAdminBoilerplate/${randomstring.generate(10)}`,
multiple: true,
accept: 'image/*',
}}
multipleFiles
/>

</SimpleForm>
</Edit>
);const CompanyShow = props => (
<Show {...props} title={<CompanyTitle />}>
<TabbedShowLayout>
<Tab label="summary">
<TextField source="name" />
<TextField source="description" />
<S3FileField apiRoot={url} source="cover" />
</Tab>
<Tab label="addresses" path="addresses">
....

</Tab>
</TabbedShowLayout>
</Show>
);...

To make this component work, we will need some support from the API side for signing AWS API requests. Let’s add the required components to our NestJS-based backend.

Service:

import { Injectable } from '@nestjs/common';
import { InjectConfig, ConfigService } from 'nestjs-config';
import { S3 } from 'aws-sdk';
import { Request, Response } from 'express';
@Injectable()
export class S3Service {
private readonly s3Bucket: string;
private readonly s3Region: string;
private s3: S3;

constructor(
@InjectConfig() private config: ConfigService,
) {
this.s3Bucket = config.get('s3.bucket');
this.s3Region = config.get('s3.region');
this.s3 = new S3({ region: this.s3Region, signatureVersion: 'v4' });
}

async signIn(req: Request, res: Response): Promise<any> {
const { objectName, contentType, path = '' } = req.query;
const objectNameChunks = objectName.split('/');
const filename = objectNameChunks[objectNameChunks.length - 1];
const mimeType = contentType;
const fileKey = `${path}/${objectName}`;
const params = {
Bucket: this.s3Bucket,
Key: fileKey,
Expires: 60,
ContentType: mimeType,
ACL: 'private',
};

res.set({ 'Access-Control-Allow-Origin': '*' });

this.s3.getSignedUrl('putObject', params, (err, data) => {
if (err) {
res.statusMessage = 'Cannot create S3 signed URL';

return res.status(500);
}

res.json({
signedUrl: data,
publicUrl: '/s3/uploads/' + fileKey,
filename,
fileKey,
});
});
}

tempRedirect(id: string, key: string, res: Response) {
const params = {
Bucket: this.s3Bucket,
Key: `NestJsAdminBoilerplate/${id}/${key}`,
};

this.s3.getSignedUrl('getObject', params, (err, url) => {
res.redirect(url);
});
}

}

Controller:

import { Controller, Get, Req, Res, Param } from '@nestjs/common';
import { Request, Response } from 'express';
import { S3Service } from './s3.service';
@Controller('s3')
export class S3Controller {
constructor(private s3service: S3Service) { }

@Get('/sign')
sign(@Req() req: Request, @Res() res: Response) {
return this.s3service.signIn(req, res);
}

@Get('/uploads/NestJsAdminBoilerplate/:id/:key')
fileRedirect(@Param('id') id: string, @Param('key') key: string, @Res() res: Response) {
return this.s3service.tempRedirect(id, key, res);
}
}

And let’s add the necessary environment variables to .env:

# ...
AWS_ACCESS_KEY_ID = <your aws access key>
AWS_SECRET_ACCESS_KEY = 'your aws secret key'
AWS_BUCKET_NAME = 'your bucket'
AWS_BUCKET_REGION = 'your region'
# ...

And use these variables in the config file for S3:

export default {
region: process.env.AWS_BUCKET_REGION,
bucket: process.env.AWS_BUCKET_NAME,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
};

And we’re done with uploading images.

Using Google Maps input

Sometimes we need to associate some location on the map with one of our entities. For this purpose, we created a Google Maps input —https://github.com/FusionWorks/react-admin-google-maps. To use it we will need to update our Address Entity. We will store the pointer on the map like a JSON object in the JSON column in our DB.

import {
Entity,
Column,
PrimaryGeneratedColumn,
ManyToOne,
BaseEntity,
} from 'typeorm';
import { CompanyEntity } from '../company/company.entity';
@Entity({ name: 'address' })
export class AddressEntity extends BaseEntity {

...

@Column({
type: 'json',
nullable: true,
comment: '{ lng: string, lat: string }',
})
geo: { lng: string, lat: string };

...}

Now we need to update the views of addresses forms:

import { GMapInput, GMapField } from '@fusionworks/ra-google-maps-input';
import { parse } from 'query-string';
...export const AddressCreate = props => {
const { location } = props;
const { companyId } = parse(location.search);
const redirect = companyId ? `/company/${companyId}/show/addresses`: false;return (
<Create {...props}>
<SimpleForm redirect={redirect}> ... <GMapInput source="geo" searchable googleKey="YOUR KEY HERE" validate={validateRequired} />
</SimpleForm>
</Create>
);
};const AddressTitle = ({ record }) => (<span>{`${record.name}`}</span>);export const AddressEdit = props => (
<Edit {...props} title={<AddressTitle />}>
<SimpleForm redirect={(basePath, id, data) =>
`/company/${data.companyId}/show/addresses`}>

... <GMapInput source="geo" searchable googleKey="YOUR KEY HERE" validate={validateRequired} />
</SimpleForm>
</Edit>
);export const AddressShow = props => (
<Show {...props}>
<TabbedShowLayout>
<Tab label="resources.summary.name"> ... <GMapField source="geo" googleKey="YOUR KEY HERE" />
</Tab>
</TabbedShowLayout>
</Show>
);...

Once we’re done with this, we are ready to rock!

Run our backend from “api” folder:

yarn run start

And run our frontend part with react-admin from “admin-ui” folder:

yarn start

Conclusion

In this article, we touched on the relationship between entities, but there are many more topics that have not been addressed but will be described in the future. I will cover them in the next articles and we’ll see if this stack survives nicely. So stay tuned to the FusionWorks:

Useful links

Source code for the article: https://github.com/FusionWorks/nestjs-crud-react-admin-boilerplate

If you want to dive deeper yourself, here is the set of links to documentation that might be useful for you:

5 Easy Steps To Improve Your Productivity

“Let’s Work Smarter, Not Harder” — FusionWorks

If you work hard and spend a lot of time on an elementary task, it does not mean that you are productive. Firstly let’s try to analyze what productivity is.

Productivity is commonly defined as a ratio between the output volume and the volume of inputs. Or, the rapport between completed tasks and the time spent while completing them. Employee productivity (sometimes referred to as workforce productivity) is an assessment of the efficiency of a worker or group of workers. Typically, the productivity of a given worker will be assessed relative to an average for other employees doing similar work.

Now, when we have an idea of the productivity concept we may think about the ways to improve it. Try the following and you will definitely increase efficiency! Let’s start working smarter instead of harder:

This article is powered by Empy.io — an all-in-one tool that helps HRs synchronize with the employees and handle all the internal requests in one single place. Try it for free!

1) Finish planning. Start acting.

It’s good to take the time to plan your actions, but you can waste too many hours just planning. Check what you have to do and don’t wait, start! If you count tens of thousands of times the activities you have to undertake, you gain nothing. Avoid friendship with procrastination, break with it! You can do it. Start the activity. A small step is still a move forward.

2) Meetings can last a maximum of 30 minutes.

Are all the meetings so important? Who counted how many hours a week he/she spends for: on the way to/from the meeting, unimportant discussions, boring people? If you have what to skip, do it. But if you are sure of the importance of all meetings, drop them on time. Half an hour is the perfect time to find out the latest news, decide and go on happily.

3) Say YES only to the important things.

Someone said that the difference between a successful man/woman and a very successful one is the ability to say NO. Every time we agree to do something for another person, we waste our time on activities that have absolutely nothing to do with our mission and goals. As a result, we are unhappy. We have not achieved anything important. We are tired — half a day has passed for nothing. And we are depressed — we do not find meaning in what we do. We can achieve more if we only get involved in what matters, we know exactly what we do when we do it and why we do it.

4) Free your mind.

Our brains are overworked. We bombard them with all kinds of information and more and more voluminous. Why do we remember what we only need for a very short time? Why were all kinds of diaries invented? When we want our computer/phone to work faster, we get out of all sorts of unnecessary applications, as well the mind works. Everything we can write — meetings, classes, topics for discussion, questions, etc. — write down instead of trying to memorize.