Categories
Vuetify

Vuetify — Hover

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Hover

The v-hover component lets us handle hover states for any component.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-hover v-slot:default="{ hover }">
          <v-card :elevation="hover ? 12 : 2" class="mx-auto" height="350" max-width="350">
            <v-card-text class="my-4 text-center title">Hover over me!</v-card-text>
          </v-card>
        </v-hover>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

to add the hover functionality with the v-hover component.

We can add the disabled prop to v-hover to disable hover effects.

Open/Close Delay

We can set a delay when opening or closing the hover effect with the open-delay and close-delay props.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-hover v-slot:default="{ hover }" open-delay="200">
          <v-card :elevation="hover ? 12 : 2" class="mx-auto" height="350" max-width="350">
            <v-card-text class="my-4 text-center title">Hover over me!</v-card-text>
          </v-card>
        </v-hover>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

to set a 200ms open delay.

Hover List

We can make a hover list with the v-hover component.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-container class="pa-4 text-center">
          <v-row class="fill-height" align="center" justify="center">
            <template v-for="(item, i) in items">
              <v-col :key="i" cols="12" md="4">
                <v-hover v-slot:default="{ hover }">
                  <v-card :elevation="hover ? 12 : 2" :class="{ 'on-hover': hover }">
                    <v-img :src="item.img" height="225px">
                      <v-card-title class="title white--text">
                        <v-row class="fill-height flex-column" justify="space-between">
                          <p class="mt-4 subheading text-left">{{ item.title }}</p>

<div>
                            <p
                              class="ma-0 body-1 font-weight-bold font-italic text-left"
                            >{{ item.text }}</p>
                            <p
                              class="caption font-weight-medium font-italic text-left"
                            >{{ item.subtext }}</p>
                          </div>
                        </v-row>
                      </v-card-title>
                    </v-img>
                  </v-card>
                </v-hover>
              </v-col>
            </template>
          </v-row>
        </v-container>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        title: "Title",
        text: "Text",
        subtext: "Subtext",
        img: "https://picsum.photos/200",
      },
      {
        title: "Title",
        text: "Text",
        subtext: "Subtext",
        img: "https://picsum.photos/200",
      },
      {
        title: "Title",
        text: "Text",
        subtext: "Subtext",
        img: "https://picsum.photos/200",
      },
    ],
    transparent: "rgba(255, 255, 255, 0)",
  }),
};
</script>

We have 3 slides each in their own v-card component.

They are inside a v-hover component so that we see a hover effect when our mouse is over the square.

Transitions

We can add our own transitions for v-hover .

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-hover v-slot:default="{ hover }">
          <v-card class="mx-auto" color="grey lighten-4" max-width="600">
            <v-img :aspect-ratio="16/9" src="[https://cdn.vuetifyjs.com/images/cards/kitchen.png](https://cdn.vuetifyjs.com/images/cards/kitchen.png)">
              <v-expand-transition>
                <div
                  v-if="hover"
                  class="d-flex transition-fast-in-fast-out orange darken-2 v-card--reveal display-3 white--text"
                  style="height: 100%;"
                >$100.99</div>
              </v-expand-transition>
            </v-img>
            <v-card-text class="pt-6" style="position: relative;">
              <v-btn absolute color="orange" class="white--text" fab large right top>
                <v-icon>mdi-cart</v-icon>
              </v-btn>
              <div class="font-weight-light grey--text title mb-2">Perfect meal</div>
            </v-card-text>
          </v-card>
        </v-hover>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

<style>
.v-card--reveal {
  align-items: center;
  bottom: 0;
  justify-content: center;
  opacity: 0.5;
  position: absolute;
  width: 100%;
}
</style>

to add a v-expand-transition to create our hover effect.

We display the price when we hover over the image.

The styles make the overlay text centered and translucent.

Conclusion

We can add hover effect with the v-hover component.

The transition is built-in but we can also customize to what we want.

Categories
Vuetify

Vuetify — Slide Group

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Slide Item Active Class

We can change the active class of the slide items with the active-class prop:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group
            v-model="model"
            class="pa-4"
            prev-icon="mdi-minus"
            next-icon="mdi-plus"
            show-arrows
            active-class="success"
          >
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                [@click](http://twitter.com/click "Twitter profile for @click")="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

The show-arrows prop make the navigation arrow show on both sies.

Also, we have the active-class prop to style the selected item differently.

Mandatory

We can make at least one item be selected in the group with the mandatory prop:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group
            v-model="model"
            class="pa-4"
            prev-icon="mdi-minus"
            next-icon="mdi-plus"
            show-arrows
            mandatory
          >
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                @click="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

Now the first item will be selected by default.

Pseudo Carousel

We can display content below the selected slide.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group v-model="model" class="pa-4" show-arrows>
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                @click="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>

          <v-expand-transition>
            <v-sheet v-if="model != null" color="grey lighten-4" height="200" tile>
              <v-row class="fill-height" align="center" justify="center">
                <h3 class="title">{{ model }}</h3>
              </v-row>
            </v-sheet>
          </v-expand-transition>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

We added the v-expand-transition component below the v-slide-group to show what we want to the user.

We’ll see a transition effect when we click on the item.

model has the index of the item we clicked on.

Conclusion

We can add slides with the v-slide-group component and let us select items when we click on it.

Categories
Vuetify

Vuetify — List Items and Slide Items

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Mandatory List Item

We can add the mandatory prop to make choosing an item mandatory:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-list flat>
          <v-list-item-group v-model="model" color="indigo" active-class="border">
            <v-list-item v-for="(item, i) in items" :key="i">
              <v-list-item-icon>
                <v-icon v-text="item.icon"></v-icon>
              </v-list-item-icon>

<v-list-item-content>
                <v-list-item-title v-text="item.text"></v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list-item-group>
        </v-list>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        icon: "mdi-wifi",
        text: "Wifi",
      },
      {
        icon: "mdi-bluetooth",
        text: "Bluetooth",
      },
      {
        icon: "mdi-chart-donut",
        text: "Data Usage",
      },
    ],
    model: undefined
  }),
};
</script>

Custom Active Class

The active-class prop can be set to set a custom class for an active item.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-list flat>
          <v-list-item-group v-model="model" color="indigo" active-class="border">
            <v-list-item v-for="(item, i) in items" :key="i">
              <v-list-item-icon>
                <v-icon v-text="item.icon"></v-icon>
              </v-list-item-icon>

<v-list-item-content>
                <v-list-item-title v-text="item.text"></v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list-item-group>
        </v-list>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        icon: "mdi-wifi",
        text: "Wifi",
      },
      {
        icon: "mdi-bluetooth",
        text: "Bluetooth",
      },
      {
        icon: "mdi-chart-donut",
        text: "Data Usage",
      },
    ],
    model: undefined
  }),
};
</script>

<style scoped>
.border {
  border: 1px solid red;
}
</style>

We just added the border class to see a red outline.

Slide Groups

The v-slide-group component is used to display paginated information.

For instance, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group
            v-model="model"
            class="pa-4"
            prev-icon="mdi-minus"
            next-icon="mdi-plus"
            show-arrows
          >
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                @click="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

to add the v-slide-group component with the v-slide-item components inside for the items.

We use the active boolean to check if the item is selected.

And the toggle function lets us toggle the active state.

Conclusion

We can group items with list item groups and slide item groups.

Categories
Node.js Best Practices

Node.js Best Practices — Tokens and Secrets

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing Node apps.

Support Blacklisting JWTs

We should be able to blacklist JSON web tokens so that we can lock out malicious users,

There are no mechanisms to do this for most systems.

We can add a list of untrusted tokens to prevent them from logging in.

Prevent Brute-Force Attacks Against Authorization

Brute-force attacks against authorization can be prevented with rate limiting.

For instance, we can limit the login attempts by the block repeated failed login requests.

Run Node.js as a Non-root User

Non-root user should be used to run Node apps.

This way, they can do whatever they want in our system.

We can bake that into the Docker image or set it with the -u flag.

Limit Payload Size Using a Reverse Proxy or a Middleware

Payload size should be limited to avoid overloading our systems.

This can help with preventing DOS attacks.

If the requests’ body size is small, less damage can be done.

We can set express body parser to accept small size payloads with the limit option.

Avoid JavaScript eval Statements

We can avoid JavaScript eval statements.

They’re insecure since code is run from a string.

It also makes optimizations and debugging impossible.

setTimeout , setInterval , and the Function constructor also run code from strings.

So we should avoid passing strings to them as well.

Prevent Evil RegEx from Overloading Single Thread Execution

There’s some regex that we should avoid.

To make data validation easy, we can use a library like validator.js or look up safe regex we can use with safe-regex to detect vulnerable regex patterns to avoid.

Bad regex can make our app susceptible to DOS attacks that block the event loop.

This will make our app hang.

Avoid Module Loading Using a Variable

We shouldn’t call require with a variable.

This way, we can’t let attackers pass anything into the require function.

For instance, instead of writing:

const insecure = require(helperPath);

We write:

const uploadHelpers = require('./helpers/upload');

This also applies to other paths we pass in like when we read a file with fs.readFile .

Run Unsafe Code in a Sandbox

If we have any unsafe code, we should run them in a sandbox.

This way, they can’t get to the outside world and potentially do damage.

NPM packages can be sandboxed. A dedicated process can also be sandboxed.

Take Extra Care When Working with Child Processes

If we run child processes in our Node app, we should sanitize the command string so that we can run without risks.

If we don’t escape them, then attackers can run anything they want, which can be catastrophic.

Hide Error Details from Clients

If there are any details about errors that expose the internals of our system, we should hide them from clients.

This way, the chance of attackers finding ways to attack our app is much lower.

Anything like paths, stack traces, and more should be hidden.

Conclusion

We should hide sensitive data, isolate risky code, and escape any strings that are potentially malicious.

Categories
Node.js Best Practices

Node.js Best Practices — Test and Arrow Functions

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing Node apps.

Use Arrow Function Expressions

Arrow functions are a great feature of modern JavaScript.

It lets us write callbacks without binding to a new value of this inside the callback.

Also, it’s more compact.

We should use to avoid bugs and have easier to read code.

Write API Tests

API tests let us check the results of our APIs.

We’ll know right away from the tests if we don’t get what we want.

They’re fast so we can test without lifting a finger.

Also, they’re great for documenting how to call our APIs.

There’re other kinds of tests like performance tests, database tests, etc. that we can do as well.

Include 3 Parts in Each Test Name

Our tests should be self explanatory.

So we should state in the test name what’s being tested.

Also, we should state what circumstances are being tested and what’s the expected result.

This way, no one will be confused with what we’re testing.

For instance, we can write:

describe('Item Service', () => {  
  describe('Add new item', () => {  
    it('When no price is specified, then the item status rejected', () => {  
      const item = new ItemService().add(...);  
      expect(item.status).to.equal('rejected');  
    });  
  });  
});

We have the describes labeling what unit we’re testing.

And the string we pass into it has the scenario we’re testing.

The expect call and the it string have the expectation.

Detect Code Issues with a Linter

We can detect code issues with a linter so that we can detect antipatterns early.

To make this easy, we can add a pre-commit hook that runs before a commit is made to do the check.

Avoid Global Test Fixtures and Seeds and Add Data Per Test

Test fixtures should be added per test.

And the data should be scrubbed after each test.

This way, we won’t have tests that are dependent on each other.

With this done, every test should run in isolation so we can run them in any order.

Inspect for Vulnerable Dependencies

We should inspect for vulnerable dependencies so that we can update them.

This way, we can update them and avoid attackers attacking our app with those vulnerabilities.

To do this, we can run npm audit or other tools.

Tag Our Tests

We can tag our tests so that they run before a commit is made.

We run the ones that must be run to prevent committing any that breaks out code.

Otherwise, we’ll run all tests all the time, which is probably too slow for most apps before commit.

Check Test Coverage

Checking for test coverage lets us identify any decreases and check for things we missed in our tests.

Tools like Istanbul/nyc can check test coverage in our code so that we get a clear idea of what’s needed to be tested.

Conclusion

We should use arrow functions.

And we should have good test coverage in our code.