Tuesday, January 4, 2022

How to install icon fonts in vuetify vue application

This is a quick tutorial on how we can install icon fonts for material icons and font awesome

Although vuetify uses material design icons, that might not be sufficient all the time so we need to use some other library for it.

We can simply install a font by including the specified icon library CDN. For this, go to the project directory and inside it, you can see the index.html file under the public folder.  


Here, add the material icons and font awesome icon CDN link as below.

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.x/css/font-awesome.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css">
After adding this, we can simply use icons for e.g: 

From font awesome, simply use the fa- prefixed on icon name:
<v-icon left color="blue" size="50">fa-twitter</v-icon>
For google fonts, go to the google font and click the icon, we can see the icon font name similar as below, simply use the name.
<v-icon left color="blue" size="50">logout</v-icon>
Share:

How to implement social media share buttons in Vue.js

In this tutorial, we are going to implement the social media share button using Vue.js.

Here, we are using the dependency called vue-socials which is very handy while implementing social media share buttons. It contains almost all the social share button functionality that we need and is lightweight and highly customizable.

In this tutorial, we are going to implement the Facebook and Twitter share button as an example. 


Install Dependency:

Go to your project directory and install the dependency.

If you are using the npm package manager

For Vue 2: 
npm install vue-socials
For Vue 3:
npm install vue-socials@next

If you are using the yarn package manager
# Vue 2
yarn add vue-socials

# Vue 3
yarn add vue-socials@next

Now, it's time to import the required share button components. Here we are creating the SocialMediaShare.vue component for demo. 

Inside this component, we are going to import the Facebook and Twitter share button component as below:
import { SFacebook, STwitter } from 'vue-socials'
Now, we need to register the components
  components: { SFacebook, STwitter }
After component registration, let us use it into the template
<div >
    <s-facebook
            :window-features="windowFeatures"
            :share-options="facebookShareOptions"
            :use-native-behavior="useNativeBehavior"
            @popup-close="onClose"
            @popup-open="onOpen"
            @popup-block="onBlock"
            @popup-focus="onFocus"
            style="text-decoration:none"
    >
        <svg
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                aria-hidden="true"
                focusable="false"
        >
            <path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/>
        </svg>
    </s-facebook>
    <s-twitter
            :window-features="windowFeatures"
            :share-options="twitterShareOptions"
            :use-native-behavior="useNativeBehavior"
            @popup-close="onClose"
            @popup-open="onOpen"
            @popup-block="onBlock"
            @popup-focus="onFocus"
            style="text-decoration:none"
    >
        <svg
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                aria-hidden="true"
                focusable="false"
        >
            <path
                    d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"
            />
        </svg>
    </s-twitter>
</div>
We are using some random SVG for icons, we can use the images or custom icons. 




Let's create the data and methods:
data () {
    return {
      windowFeatures: {},
      facebookShareOptions: {
        url: 'https://github.com/',
        quote: 'Quote',
        hashtag: '#Github',
      },
      twitterShareOptions: {
        url: 'https://github.com/',
        text: 'Hello world',
        hashtags: ['hash', 'tag'],
        via: 'twitterdev',
      },
      useNativeBehavior: false,
    }
  },
  methods:{
    onClose() {},
    onOpen() {},
    onBlock() {},
    onFocus() {},
  }

If we run the application we can see something like this:


Click on icons, we can share the content on those social media. We can change the content from data in component. 

For now, we are using the Github link and dummy text as examples.

If we want to import all the share buttons available then import all components as below inside main.js file.
 // Vue 2
import Vue from 'vue'
import VueSocials from 'vue-socials';

Vue.use(VueSocials)

// Vue 3

import { createApp } from 'vue'
import VueSocials from 'vue-socials';
import App from './App.vue'

const app = createApp(App)
app.use(VueSocials)
The overall implementation of the above example looks as below:
<template>
    <div >
        <s-facebook
                :window-features="windowFeatures"
                :share-options="facebookShareOptions"
                :use-native-behavior="useNativeBehavior"
                @popup-close="onClose"
                @popup-open="onOpen"
                @popup-block="onBlock"
                @popup-focus="onFocus"
                style="text-decoration:none"
        >
            <svg
                    xmlns="http://www.w3.org/2000/svg"
                    width="24"
                    height="24"
                    viewBox="0 0 24 24"
                    aria-hidden="true"
                    focusable="false"
            >
                <path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/>
            </svg>
        </s-facebook>
        <s-twitter
                :window-features="windowFeatures"
                :share-options="twitterShareOptions"
                :use-native-behavior="useNativeBehavior"
                @popup-close="onClose"
                @popup-open="onOpen"
                @popup-block="onBlock"
                @popup-focus="onFocus"
                style="text-decoration:none"
        >
            <svg
                    xmlns="http://www.w3.org/2000/svg"
                    width="24"
                    height="24"
                    viewBox="0 0 24 24"
                    aria-hidden="true"
                    focusable="false"
            >
                <path
                        d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"
                />
            </svg>
        </s-twitter>
    </div>
</template>

<script>
    import { SFacebook, STwitter } from 'vue-socials'

    export default {
        name: "SocialMediaShare",
        components: { SFacebook, STwitter },
        data () {
            return {
                windowFeatures: {},
                facebookShareOptions: {
                    url: 'https://github.com/',
                    quote: 'Quote',
                    hashtag: '#Github',
                },
                twitterShareOptions: {
                    url: 'https://github.com/',
                    text: 'Hello world',
                    hashtags: ['hash', 'tag'],
                    via: 'twitterdev',
                },
                useNativeBehavior: false,
            }
        },
        methods:{
            onClose() {},
            onOpen() {},
            onBlock() {},
            onFocus() {},
        }
    }
</script>
Check out for other share button lists, usage, and demo from these links.

Share:

How to resolve the encoding issue while building Java Application

In this tutorial, we are going to understand the different scenarios where we might get encoding issues while building the Java application as a war or jar file and deploy it to the server. 

The main encoding issue here is, for some languages like Hebrew, Chinese, Arabic, etc there might get the chance of appearing as question marks instead of actual specific text. This issue might be due to different cases.

1. Sometimes the serverside rendering language like jsp, gsp pages might cause the issue we can use the following tag in those pages.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

2. We might get the issue due to database data where we don't set the configugre the utf-8 encoding. To resolve the issue we can set the jdbc connection url as follows:
jdbc:mysql://hostname/database_naeme?useUnicode=yes&&characterEncoding=UTF-8

3. If our application contains some other language that requires saving operation in the database. Better to create the database using encoding using the following command for the MySQL database.
CREATE DATABASE database_name DEFAULT CHARACTER SET "utf8" COLLATE "utf8_general_ci";
Make sure to change the actual database instead of [database_name].

4. If we are using hibernate then better to configure the settings as
hibernate.connection.charSet=UTF-8
hibernate.connection.characterEncoding=UTF-8
hibbernate.connection.useUnicode=true

5. If we are using build tools like Jenkins for deployment we need to configure the encoding In Jenkins: we can create a global variable and set encoding config as below:



Share:

How to open the Dicom Image in Linux

This is a short tutorial on how we can open and view the Dicom images in Linux operating system.

Here, we will install weasis desktop application to view the Dicom images.

Installation

Download the desired weasis installer compatible with your operating system from weasis website. 

For Linux, download the .deb installer. Go to the download folder and open the terminal and execute the .deb file


sudo dpkg -i weasis_3.8.0-1_amd64.deb

Here, weasis_3.8.0-1_amd64.deb is the downloaded file, you can use your own downloaded .deb file.

Now, you are good to go to open the Dicom images. Go to the sample image and select the image and right-click, you can see open with weasis option, select and view the image. Or simply double click on the image which will open the installed weasis application to view the Dicom image.




Key Features
  • Display all kinds of DICOM files (including multi-frame, enhanced, MPEG-2, MPEG-4, MIME Encapsulation, SR, PR, KOS, AU, RT and ECG)
  • Image manipulation (pan, zoom, windowing, presets, rotation, flip, scroll, crosshair, filtering...)
  • Viewer for common image formats (TIFF, BMP, GIF, JPEG, PNG, RAS, HDR, and PNM)
  • Layouts for comparing series or studies
  • Advanced series synchronization options
  • Display Presentation States (GSPS) and Key Object Selection
  • Create key images (Key Object Selection object) by selection
  • Support of Modality LUTs, VOI LUTs, and Presentation LUTs (even non-linear) 
  • Support of several screens with different calibration, support of HiDPI (High Dots Per Inch) monitors, full-screen mode
  • Multiplanar reconstructions and Maximum Intensity Projection
  • Display Structured Reports
  • Display and search into all DICOM attributes
  • Display cross-lines Measurement and annotation tools
  • Region statistics of pixels (Min, Max, Mean, StDev, Skewness, Kurtosis, Entropy)
  • Histogram of modality values 
  • SUV measurement 
  • Save measurements and annotations in DICOM PR or XML file
  • Import CD/DVD and local DICOM files 
  • Export DICOM with several options (DICOMDIR, ZIP, ISO image file with Weasis, TIFF, JPEG, PNG...)
  • Magnifier glass Native and DICOM printing 
  • Read DICOM image containing float or double data (Parametric Map)
  • DICOM ECG Viewer
Share:

Saturday, December 18, 2021

How to change Grails App server port in application.yml

This is a quick tutorial on how to set server port while running grails application. By default, grails will use the embedded tomcat server running on port 8080.

Sometimes if another process is using port 8080 then we might get a port address already in use error.

So, what we will do is to change the default port in the config. In grails 3.x version we can set up the custom port inside application.yml file.

Inside application.yml file lets add the following config setup to override the default port 8080.
server:
    port : "8090"
Now if we run the application, it will run on port 8090. 

If we want to configure the setup within the environment then we can do as below:
environments:
    development:
        server:
            port : "8090"
This will set the server port only for the development environment. Re-run the application.
Share:

Thursday, December 9, 2021

How to resolve port already in use or kill the running process

 On Linux:


step1: if the process is running at port 3000 then, firstly we have to kill this process for this open your terminal and type

lsof -w -n -i tcp:3000

which shows all the list of open file which is running at port 3000. Here, lsof stands for ls = list and of = opened file. You can see list with pid number.


step2: type sudo kill -9 6911 where 6911 is pid number. Here 9 has its own meaning which is defined as kill command "SIGKILL" you can see this by typing in the terminal as kill -l . You can use -SIGKILL instead of -9.


On Windows:

Open and run command prompt as administrator and type the following command:
   
   netstat -ano | findstr :8080

This command will find and list the process that uses this port 8080.

Now, we need to kill the process, for this use following command:

   taskkill /pid 5884 /f

Where 5884 is the PID number. Use the process PID number obtained previously.
Share:

Sunday, November 21, 2021

Error occurred running Grails CLI: No profile found for name [web]. (Use --stacktrace to see the full trace)

In grails application, the error mentioned below might occur.

 

Error |
Error occurred running Grails CLI: No profile found for name [web]. (Use --stacktrace to see the full trace)

Process finished with exit code 1
This might be of different reason. Let's try to fix it by deleting the build folder under the application and re-run the application. 

This might work in most cases if this doesn't help then try to clean the app. 

If you are using the command line then type the following command to clean the application.
grails clean
if you are using the IntelliJ idea then Ctr+Alt+G opens the command window and use the following command.
clean
Now, re-run the app.
Share:

How to configure multiple database in Grails application

In this tutorial, we are going to learn how to configure multiple databases in the grails 3.x application. This is necessary when you are dealing with multiple databases from the same application especially when dealing with an existing remote database. We are using different MySql databases for testing.

Let's create three MySql databases called db_default, db_one, db_two. Let's look into the application.yml file to configure the different databases and we will do it for the development environment, in other environments, the procedure will be the same.


environments:
    development:
        dataSource:
            dbCreate: update
            url: jdbc:mysql://localhost:3306/db_default
            driverClassName: com.mysql.jdbc.Driver
            dialect: org.hibernate.dialect.MySQL5InnoDBDialect
            username: root
            password: root
Here, we are setting the default database as db_default. So for this database, all the gorm queries will be the same as in a normal application.

Now, let's set up for other two databases.
        dataSources:
            first:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_one
                dbCreate: update
            second:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_two
                dbCreate: update

For more than two, we need to define the databases by defining dataSources and giving the corresponding names. Here the custom name is whatever name you want. We are giving the name first for db_one and second for db_two.

The overall implementation for application.yml file looks as below:
environments:
    development:
        dataSource:
            dbCreate: update
            url: jdbc:mysql://localhost:3306/db_default
            driverClassName: com.mysql.jdbc.Driver
            dialect: org.hibernate.dialect.MySQL5InnoDBDialect
            username: root
            password: root
        dataSources:
            first:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_one
                dbCreate: update
            second:
                dialect: org.hibernate.dialect.MySQLInnoDBDialect
                driverClassName: com.mysql.jdbc.Driver
                username: root
                password: root
                url: jdbc:mysql://localhost:3306/db_two
                dbCreate: update
Now, how we can use the domain classes for the specific databases. Let's create a simple domain class called Book.groovy.
class Book {
    String title
    
    static mapping = {
        datasource 'first' 
    }
}
In the above example, the Book table is mapped to the db_one database so all operations regarding this will be in db_one database. Similarly, we can map the second database as well. We can map the single domain to multiple databases as below:
class Book {
    String title
    
    static mapping = {
        datasources([ConnectionSource.DEFAULT, 'first', 'second'])
    }
}
In the above example, the Book domain will be available in all the databases.

Now, let's look into how we can query for the specific database.

The first DataSource specified is the default when not using an explicit namespace, so in this case, the default one is used. But you can call GORM methods on the 'first' or 'second' DataSource with the DataSource name, for example:
def book = Book.first.get(1) // this will get from db_one
book.first.save() //this will save in db_one
def book = Book.second.get(1) // this will get from db_two
book.second.save() // this will save in db_two
def book = Book.get(1) // this will get from db_default
book.save() // this will save in db_default

We can use groovy native SQL as well. Let's look at the example. 
import grails.transaction.Transactional
import groovy.sql.Sql
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier

import javax.sql.DataSource

@Transactional
class DbOneService {

    @Autowired
    @Qualifier('dataSource_first')
    DataSource dataSource

    def test() {
        def sql = new Sql(dataSource)
        def rows = sql.rows("select * from....")
        println "rows: "+rows
    }
}
Here, we are creating the DbOneService which is annotated with Qualifier where the db_one database name is configured as dataSource_first. This will provide the db_one database connection to do DB operation. You can simply execute the native SQL command as shown above. Similarly, we can do the same for the second database called db_two.
import grails.transaction.Transactional
import groovy.sql.Sql
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier

import javax.sql.DataSource

@Transactional
class DbTwoService {

    @Autowired
    @Qualifier('dataSource_second')
    DataSource dataSource

    def test() {
        def sql = new Sql(dataSource)
        def rows = sql.rows("select * from....")
        println "rows: "+rows
    }
}
This way, we can deal with multiple databases.
Share:

Saturday, November 20, 2021

How to convert Matlab functions into c or c++ code

In this tutorial, we are going to learn how we can convert the Matlab function into the c or c++ code. Note that the existing Matlab function needs to have c/c++ code generation extended capabilities.

Let's look into the sample Matlab scripts.

codegen.m

function y = codegen(I1)
 %#codegen
 y = typecast(I1, 'double');
Here, we are going to generate c code for function typecast of Matlab as given here. You can see the function does have the c/c++ code generation capabilities.

The first thing to do is add %#codegen as shown above. Open the file script on the editor and go to the APPS tab on the Matlab editor and you can find the MATLAB Coder option. Click on it.



Once you click on the MATLAB Coder option you can see the screen as below:



Select the script file created i.e codegen.m and the below screen will pop up and click the Next button for further steps.



Now, click on the link as shown below to add the input i.e I1 in our case which is defined in the function.



Now, lets define the input data.




Once click on the next button you can see the screen to check the issue, so you either check the issue or remove it by clicking on the screen outside of it. And click next to generate the code.
Click on generate button to generate the code. After build success, you can see the generated code as below:



This is a sample example for code generation. You can use the same methodologies for other Matlab inbuild functions to generate code in c/c++.
Share:

Wednesday, November 17, 2021

How to Compress(Zip) and Decompress(Unzip) byte array in Java

In this tutorial, we are going to compress and decompress the bytes array. The process may be required when serializing data as a binary file especially when the bytes array has non-unique data.

Let's create the method that compresses the bytes array.


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;
public static byte[] compress(byte[] bytes) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream);
        deflaterOutputStream.write(bytes);
        deflaterOutputStream.close();
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return compressedBytes;
    }

This method will compress the bytes array. If this results in no reduction in length then the data might be unique or tend to be unique. If the data is truly unique random values then the compression might produce the greater length as well. Compression always has overhead to allow for future decompression.

Now, let's create a method that will decompress or unzip the underlying compressed data. 
import java.util.zip.InflaterInputStream;
import java.io.ByteArrayInputStream;
public static byte[] decompress(byte[] bytes) throws IOException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        InflaterInputStream inflaterInputStream = new InflaterInputStream(byteArrayInputStream);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int read;
        while ((read = inflaterInputStream.read()) != -1) {
            byteArrayOutputStream.write(read);
        }
        inflaterInputStream.close();
        byteArrayInputStream.close();
        byteArrayOutputStream.close();
        return byteArrayOutputStream.toByteArray();
    }
Let's create a test example to run these methods.

    public static void main(String[] args) {
        byte[] b = new byte[10000]; // bytes data with 0 values
        System.out.println("Initial Data Size : "+ b.length);
        try {
            byte[] compressedBytes = compress(b);
            System.out.println("Compressed Data Size : "+ compressedBytes.length);
            byte[] decompressedBytes = decompress(compressedBytes);
            System.out.println("Decompressed Data Size: "+ decompressedBytes.length);
        } catch (IOException e) {
            System.out.println("Error while zipping due to : "+e.getMessage());
        }
    }
Output:
Initial Data Size : 10000
Compressed Data Size : 33
Decompressed Data Size: 10000
There is an options to add different algorithm while doing compression using Deflater class as below
import java.util.zip.Deflater;
public static byte[] compress(byte[] bytes) throws IOException {
        Deflater deflater = new Deflater(Deflater.HUFFMAN_ONLY);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
        deflaterOutputStream.write(bytes);
        deflaterOutputStream.close();
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return compressedBytes;
    }
Here is overall code implementation:

Zip.java

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
import java.io.ByteArrayInputStream;

public class Zip {

    public static void main(String[] args) {
        byte[] b = new byte[10000]; // bytes data with 0 values
        System.out.println("Initial Data Size : " + b.length);
        try {
            byte[] compressedBytes = compress(b);
            System.out.println("Compressed Data Size : " + compressedBytes.length);
            byte[] decompressedBytes = decompress(compressedBytes);
            System.out.println("Decompressed Data Size: " + decompressedBytes.length);
        } catch (IOException e) {
            System.out.println("Error while zipping due to : " + e.getMessage());
        }
    }

    public static byte[] compress(byte[] bytes) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream);
        deflaterOutputStream.write(bytes);
        deflaterOutputStream.close();
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return compressedBytes;
    }

    public static byte[] decompress(byte[] bytes) throws IOException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        InflaterInputStream inflaterInputStream = new InflaterInputStream(byteArrayInputStream);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int read;
        while ((read = inflaterInputStream.read()) != -1) {
            byteArrayOutputStream.write(read);
        }
        inflaterInputStream.close();
        byteArrayInputStream.close();
        byteArrayOutputStream.close();
        return byteArrayOutputStream.toByteArray();
    }
}
Share: