14 March 2024

React lazy component (import component)

Let's face it - there are some problems with React & Webpack.

When I create a Webpack bundle - All the files (js and css) are merged. (remember files Name Must Start with Capital letter- js , css,..)

It means that if I have some styles with the same name, the style will be applied on all the elements.

Ex:

In A component - there is an element like this:

<Button className="mybutton" label="close" />

with style like this:

.mybutton {color:red}

In B component - there is element with the same class name

<Button className="mybutton" label="open" />

So because I used the same style css class name - the Webpack bundle merged the css files of all the components, its means that we got red color to all components that use the same name. In the example component B got red color for the button.

I call it a bug (not a feature 😀)

In my project I created an app.js. In this file I import all the components. There, I noticed that as I mentioned earlier, one component get styled by another component.
As I remember in Angular, it gives all class names a new name with GUID. It means that in angular one component style does not affect another component.

Before:
we write this code in app.js to import our components

import MyComponent from './MyComponent';


The time and memory:

After:
Now my suggested solution:
const MyComponent = React.lazy(() => import('./MyComponent'));


It's means that ContactUs component now no longer has a style from ModSlider component, because we used React.Lazy.

To complete the job you need to wrap your code with Suspense



Now you need create your own fallback code (loading / spinner)

The time and memory:


On this example we saved almost 6 MB and 1 sec.... amusing 😃

This will automatically load the bundle containing the MyComponent when this component is first rendered.
React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.
The lazy component should then be rendered inside a Suspense component, which allows us to show some fallback content (such as a loading indicator) while we’re waiting for the lazy component to load.

**import React, { Suspense } from 'react';

 

const MyComponent = React.lazy(() => import('./MyComponent'));

 

function MyComponent() {

  return (

    <div>

      <Suspense fallback={<div>Loading...</div>}>

        <OtherComponent />

      </Suspense>

    </div>

  );

}

The fallback prop accepts any React elements that you want to render while waiting for the component to load. You can place the Suspense component anywhere above the lazy component. You can even wrap multiple lazy components with a single Suspense component.

import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

const AnotherComponent = React.lazy(() => import('./AnotherComponent'));

function MyComponent() {

  return (

    <div>

      <Suspense fallback={<div>Loading...</div>}>

        <section>

          <OtherComponent />

          <AnotherComponent />

        </section>

      </Suspense>

    </div>

  );

}

To support Webpack Chunk Name

const News = React.lazy(() => import(/*webpackChunkName:"News" */"../components/News/News"));

to webpack.config.js:

output: {

        path: path.resolve(__dirname, 'D:/Code/React/'),

        filename: 'Roi_bundle.js',

        chunkFilename:'[name].[chunkhash].js'

    },

 





18 January 2022

How to get the following ID in a SharePoint list

 hi...

More than a decade ago .. I wrote a kwizcom blog article - how to get the following ID in a SharePoint list

https://kwizcom.blogspot.com/2009/08/how-do-i-tell-what-next-list-item-id-is.html

This was valid for SharePoint 2007 and 2010 for sure.

I do not know when Microsoft changed the table in the database ..

But now in SharePoint 2019 they have created another table AllListsAux and the code should look like this

/// Get the next available item id from a list

/// < name="site">site

/// < name="listId">listId

///

public static int SharePointListNextItemId(SPSite site, Guid listId)

{

    int id = -1;

    SPSecurity.RunWithElevatedPrivileges(delegate ()

    {

        if (site.WebApplication.ContentDatabases.Count > 0)

        {

            string DBConnString = site.WebApplication.ContentDatabases[0].DatabaseConnectionString;

            using (SqlConnection con = new SqlConnection(DBConnString))

            {

                try

                {

                    con.Open();

                    using (SqlCommand command = con.CreateCommand())

                    {

                        command.CommandText = String.Format("select NextAvailableId from [AllListsAux] where ListID = '{0}'", listId.ToString());

                        id = (int)command.ExecuteScalar();

                    }

                }

                finally

                {

                    con.Close();

                }

            }

        }

    });

    return id;

}

Hope this helps!

25 May 2021

WSP not deployed in all SharePoint servers in the farm

If you want to deploy wsp file on the SharePoint farm ... and the installation failed on some of the farm servers -  then the solution is the timejob

SharePoint deploy

Run this code at SharePoint PowerShell

$farm  = Get-SPFarm

$disabledTimers = $farm.TimerService.Instances | where {$_.Status -ne "Online"}

if ($disabledTimers -ne $null)

{

    foreach ($timer in $disabledTimers)

    {

        Write-Host "Timer service instance on server " $timer.Server.Name " is not Online. Current status:" $timer.Status

        Write-Host "Attempting to set the status of the service instance to online"

        $timer.Status = [Microsoft.SharePoint.Administration.SPObjectStatus]::Online

        $timer.Update()

    }

}

else

{

    Write-Host "All Timer Service Instances in the farm are online! No problems found"

}

PowerShell timer job

Before reinstalling recycle time Job on each server

More info - read this forum


Yours,

Roi






29 January 2021

Create React, Angular or Vue widget at Liferay

In the last year I have made a small change in the professional aspect …

I switched from a Microsoft CMS (SharePoint) that works with .NET and windows IIS to a new CMS - Liferay

In Liferay, I work with Java, Linux servers with tomcat.(On AWS cloud)- I don't remember Microsoft 😖


Enough talking about myself... Let's do Liferay


Before 

You need to install before node.js, npm and yomoan. Also you need visual studio code.

Install the Liferay bundle generator

Run the following command (Create before folder for your project)

npm install -g yo generator-liferay-js

And now, generate the React project

yo liferay-js

nmp install

Select React Widget (Or Angular / Vue)

Now answer the questions about your project… (Name. category, localization etc… )

Liferay Angular

Chose with example code

Now the npm service installing the project 

The Code 

Open your project with visual studio code

Visual Studio Code

The package.json file is responsible for the settings of the project (name, version, category, etc.  …)

The assets\css\styles.css file is responsible for the style (you can add more files) .

The features\localization\Language.properties is the resource file. It can be a multiple languages, you need to and your local file like Language_iw.properties for Hebrew.

The features\configuration.json is the property of the widget. 

The files src\AppComponent.js and src\index.js are the files of the component.

You can add your new component like this.

Deploy

Run this command

npm run deploy

Liferay

On the page (at liferay) add your widget. You widget is under your category, and you can change the property that youadd on the json file.

Enjoy

Roi 


06 August 2020

Text To Speech (TTS) and Audio file with NativeScript

In my game - My first game (game for children), that created with NativeScript, I use audio and speak services.


The NativeScript is platform that use to develop an android (or IOS) app with angular and TypeScript.

Here is the class the use for Audio and Speak with NativeScript.

The speak if Text To Speech (TTS) from google.

The audio is mp3 file

import { TNSTextToSpeechSpeakOptions } from "nativescript-texttospeech";
import { TNSPlayerAudioPlayerOptions } from "nativescript-audio-player";
import * as timer from "tns-core-modules/timer";
import { Injectable } from "@angular/core";
import * as firebase from "nativescript-plugin-firebase";
@Injectable({
  providedIn: "root",
})
export class AudioAndSpeak {
  public audioTrackDurationany;
  public remainingDurationany// used to show the remaining time of the audio track
  private TTS = new TNSTextToSpeech();
  private _playerTNSPlayer;
  public isSpeakingboolean = false;
  constructor() {
    this._player = new TNSPlayer();
    this._player.debug = false;
  }
  public async speak(textstringlocal : string) {
    let isSpeaking = true;
    let  speakRate = 0.8;
    let speakOptionsSpeakOptions = {
      text: text,
      speakRate: speakRate,
      queue: true,
      locale : local,
      finishedCallback: async () => {
        isSpeaking = false;
      },
    };
    this.TTS.speak(speakOptions).then(() => console.log("End Speak"));
    return isSpeaking;
  }
  public async playSound(filePathstringfilePath2?: stringvolume? :number) {
    try {
      if(!volume)
      {
        volume = 1;
      }
      this._player.volume = volume;
      this.isSpeaking = true;
      const playerOptionsAudioPlayerOptions = {
        audioFile: filePath,
        loop: false,        
        completeCallback: async () => {
       
          await this._player.dispose();
          this.isSpeaking = false;          
         // player disposed
          if (filePath2) {
            this.playSound(filePath2);
          }
        },
        errorCallback: (errorObject=> {
          console.log('errorCallback')
          console.log(JSON.stringify(errorObject));
          this.isSpeaking = false;
        },
        infoCallback: (args=> {
          console.log(JSON.stringify(args));
        },
      };
      await this._player.playFromFile(playerOptions).catch((error=> {
        firebase.crashlytics.sendCrashLog('AudioAndSpeak -> playSound playFromFile :' + error);
        console.log(error);
        this.isSpeaking = false;
      });
 
      this.audioTrackDuration = await this._player.getAudioTrackDuration();
      // start audio duration tracking
      this._startDurationTracking(this.audioTrackDurationvolume);
    } catch (e) {
      console.error("AudioAndSpeak -> playSound"e);
      firebase.crashlytics.sendCrashLog('AudioAndSpeak -> playSound :' + e);
    }
  }
  private async _startDurationTracking(durationvolume) {
    if (this._player && this._player.isAudioPlaying()) {
      this._player.volume = volume;
      const timerId = timer.setInterval(() => {
        this.remainingDuration = duration - this._player.currentTime;
      }, 500);
    }
  }
}


You need yo add the service on the contractor

import { AudioAndSpeak } from "../../shared/AudioAndSpeak";

 constructor(
    ...
    private audioAndSpeakAudioAndSpeak,
    ...
  ) {...}

to call audio file

 this.audioAndSpeak.playSound(audioFilePath);

to call speak

this.audioAndSpeak.speak'TEXT' , "en-GB" );

Thanks,
Roi Kolbinger