npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ziqni-tech/member-widget

v2.0.8

Published

Our Member Widget package enables you to quickly roll out your gamification experience. The package allows you to implement tournament leaderboards, achievements, missions, rewards and a message inbox in a most modular way.

Downloads

78

Readme

Gamification UX package

HTML/CSS and Vanilla JavaScript Ziqni Leaderboard / Achievements / Inbox-Messaging widget

Our widget "out of the box" is a product that you can use immediately by placing it on your existing game, on your website or include it into your Node project directly or anything that you need it to be used for. The widget is fully editable, re-adjustable, multilingual (all languages are supported), units of measure are also auto-generated by the system (all the currencies are pre defined in your private space) and it is a complementary product that gives the player a full in-depth gaming experience. All you have to do is:

Read more here

The widget is designed to work with the new ZIQNI platform APIs

Installation

The Leaderboard Widget package lives in npm. To install the latest stable version, run the following command:

npm install @ziqni-tech/member-widget

Or if you're using yarn:

yarn add @ziqni-tech/member-widget

Build

Prerequisites

  • NodeJS >= 10.10
  • NPM >= 6.x

Install the dependencies.

npm install

Run npm run build to generate production files inside build.

npm run build

You can include css file into the bundle by running one of the commands (images will also be compiled into base64 format):

npm run build -- --inlineCss=true

Coding standards

Code formatting rules are defined in .eslintrc. You can check your code against these standards by running:

npm run lint

To automatically fix any style violations in your code, you can run:

npm run lint -- --fix

Documentation

You can generate documentation by running:

npm run jsdoc

Command parameters:

Examples

Adding widget to your website

import MemberWidget from '@ziqni-tech/member-widget';

const instance = new MemberWidget({
  autoStart: false,
  debug: false,
  apiKey: '<api_key>',
  memberRefId: '<member_reference_id>',
  memberToken: '<member_token>', // You must specify either apiKey + memberRefId or memberToken! 
  language: 'en',
  currency: 'EUR',
  memberNameLength: 5, // The first 5 characters of the user name + '*****' will be displayed on the leaderboard
  loadCustomTranslations: true,
  enableNotifications: true,
  hideEmptyTabs: false,
  defaultLightTheme: false,
  timeZone: 'Europe/London', // 'UTC' by default
  productIds: [], // ProductIds array; [] by default
  instantWins: {
    enable:  false // This functionality is under development; the parameter is disabled by default
  },
  layout: {
    logoUrl: '',
    showThemeSwitcher: true, // true by default
  },
  awards: {
    showExpiredAwards: false // false by default
  },
  tournaments: {
    showTournamentsMenuPrizeColumn: false, // Hides the Prize column in the tournament select menu; true by default
    showBannerTimer: true, // true by default
    showDashboardTime: true, // true by default
    activeCompetitionId: '<id>' // null by default
  },
  historicalData: {
    finalisedCompetitions: 30, // Days; 30 by default
    messagesForTheLast: 30 // Days; 30 by default
  },
  navigation: {
    dashboard: {enable: true},
    tournaments: {
      enable: true,
      showFinishedTournaments: true
    },
    achievements: {
      enable: true,
      showReadyAchievements: false
    },
    rewards: {enable: true},
    inbox: {enable: true},
    missions: {enable: true},
  },
  leaderboard: {
    fullLeaderboardSize: 100,
    miniScoreBoard: {
      rankingsCount: 2 // The number of positions that will be displayed before and after the current user in miniScoreBoard
    },
    pointsFormatter: function(points) {
      if (isNaN(points)) {
        return points;
      }
      return Math.round(points)
    }
  },
  uri: {
    translationPath: '<path to custom json translation file>'
  },
  callbacks: {
    onContestStatusChanged: function (contestId, currentState, previousState) {
      console.log('contestId:', contestId);
      console.log('currentState:', currentState);
      console.log('previousState:', previousState);
    },
    onCompetitionStatusChanged: function (competitionId, currentState, previousState) {
      console.log('competitionId:', competitionId);
      console.log('currentState:', currentState);
      console.log('previousState:', previousState);
    },
  },
  resources: [
    'node_modules/@ziqni-tech/member-widget/build/css/theme/default-theme.css'
  ]
});

instance.init();

instance.refreshMemberToken('<New_Token>'); // If you use the memberToken parameter

Or

<script type="text/javascript">
	(function(w,d,s,u,o){
        w[o] = {
            apiKey: '<api_key>',
            memberRefId: '<member_reference_id>',
            language: "en",
            leaderboard: {
                fullLeaderboardSize: 50,
                topResultSize: 3,
                miniScoreBoard: {
                  rankingsCount: 2 // The number of positions that will be displayed before and after the current user in miniScoreBoard
                },
            },
            uri: {
                translationPath: ""
            },
            resources: [
                "<Path to your build /default-theme.css>"
            ]
        };
        var a=d.createElement(s), m=d.getElementsByTagName(s)[0];
        a.async=1;a.src=u;m.parentNode.insertBefore(a,m);
    })(window,document,'script','<Path to your build /ziqni-member-widget.js>',"_CLLBV3Opt");
</script>

Or

  <script type="text/javascript" src="<Path to your build /ziqni-member-widget-selfinit.js>"></script>

  <script type="text/javascript">
    const widgetInstance = new window._clLeaderBoardV3SelfInit({
      autoStart: false,
      debug: false,
      apiKey: '<api_key>',
      memberRefId: '<member_reference_id>',
      memberToken: '<member_token>', // You must specify either apiKey + memberRefId or memberToken!
      memberNameLength: 5, // The first 5 characters of the username + '*****' will be displayed on the leaderboard
      loadCustomTranslations: false,
      layout: {
        logoUrl: '',
        showThemeSwitcher: true,
      },
      tournaments: {
        showTournamentsMenuPrizeColumn: false // Hides the Prize column in the tournament select menu; true by default
      },
      navigation: {
        tournaments: {enable: true},
        achievements: {enable: true},
        rewards: {enable: true},
        inbox: {enable: true},
        missions: {enable: true},
      },
      leaderboard: {
        fullLeaderboardSize: 50,
        miniScoreBoard: {
          rankingsCount: 2 // The number of positions that will be displayed before and after the current user in miniScoreBoard
        },
        pointsFormatter: function(points) {
          if (isNaN(points)) {
            return points;
          }
          return Math.round(points)
        }
      },
      resources: [
        "<Path to your build /default-theme.css>"
      ]
    });

    widgetInstance.init();

    widgetInstance.refreshMemberToken('<New_Token>'); // If you use the memberToken parameter
  </script>

FAQ

How do I set the currency:

The setting "currency" needs to be set to the appropriate ISO key used in units of measure section

{
  currency: "usd"
}

How do I specify a custom stylesheet:

All styles are loaded as part of the initialisation, so overwriting the resources array variable with your stylesheet asset will allow you to load in the external stylesheets dynamically. There is no limit to how many stylesheets you can add as the widget will load all of them from the specified array.

How to disable Tournaments, Achievements, Rewards, Inbox or Missions tabs:

To disable Tournaments, Achievements, Rewards, Inbox or Missions tabs on the full widget preview the following settings has to be set to "false":

navigation: {    
  dashboard: {enable: false},
  tournaments: {enable: false},
  achievements: {enable: false},
  rewards: {enable: false},
  inbox: {enable: false},
  missions: {enable: false},
},

Note: at least one tab should be left enabled

How to disable Inbox/Messaging section:

To disable the inbox/messaging area on the full widget preview the following setting "messages.enabled" has to be set to "false":
{
  messages: {
      enable: false
  }
}

How to show the widget only if there are any available competitions:

The primary method “this.startup“ inside the "LbWidget" class is the one you should adjust to implement your scenario to achieve a pre-launch check, you can wrap what's inside of that method with the function:
this.checkForAvailableCompetitions()
This method collects all the necessary information about active, ready and finished competitions (example: _this.settings.tournaments.readyCompetitions will contain a list of upcoming competitions) so you can use the callback and the collected information to decide to show or hide the mini-scoreboard on startup based on your requirements.

Example:

<script type="text/javascript" src="<Path to your build /ziqni-member-widget-selfinit.js>"></script>
<script type="text/javascript">
    const widgetInstance = new window._clLeaderBoardV3SelfInit({
      <Your settings>
    });

    widgetInstance.checkForAvailableCompetitions(function () {
      if (widgetInstance.settings.tournaments.activeCompetitions.length) {
        widgetInstance.init();
      }
   })
</script>

How do I only show the competition tab if there is an active competition only and/or change the default tab to the achievements tab

The current flow is:

  1. once the mini scoreboard is clicked, the main layout gets initialized (unless it’s already not existing in the DOM)
  2. the navigation then gets reset to the initial competition tab

To achieve this scenario you would need to do an available competition check prior to the navigation reset and then hide/show tabs accordingly based on your business requirement. The code of interest would be on line inside the method called: "this.initLayout" in the "MainWidget" widget class, the method that resets the navigation is "_this.resetNavigation( callback )" this handles what navigation item to set as default for the user. You can either change this code directly or override that method after initialization inside the "this.startup" method for the class "LbWidget" by doing the following "_this.settings.mainWidget.resetNavigation = function(callback){}". There you can write some logic that would check what tabs to show/hide. Or you can overwrite this on a more global scope level where you initialize the widget "new LbWidget(window._CLLBV3Opt)" as you get full access to the settings and all other methods.

Localization - How do I translate the widget UI:

To enable translation the following steps need to be made:

  1. Translate your UI elements to the appropriate language and save it in a ".json" format using the following naming pattern translation_en.json JSON example
  2. The translations you define inside the file will be merged with the core translations on run time
* The default widget language is set to english "en", the widget will try to load look for an external translation 
resource based on the language setting and the "translationPath"

* If the resource path is used as "translation_:language.json" the widget script will try to replace ":language" with the 
current language setting and load the translation dynamically from an external source, example:
https://ziqni.cdn.ziqni.com/ziqni-tech/gamification-ux-package/_widgets/gamification-ux-package/i18n/translation_:language.json

* If custom translations are not required it is possible to disable them by changing "loadCustomTranslations" setting to "false"

Why we use SASS:

Here are some of the basic benefits of why we are using SASS:

  • provides the ability to use variables, allows you to store a value, or a set of values, and to reuse these variables throughout your SASS files as many times you want and wherever you want. Easy, powerful, and useful.
  • the improved syntax allows you to use a nested syntax, which is code contained within another piece of code that performs a wider function
  • provides mixin functionality: Mixins are like functions in other programming languages. They return a value or set of values and can take parameters including default values.
  • allows you to break apart your big complex CSS files into smaller chunks, this improves the ability to work on the same stylesheets for multiple teams
  • still supports the basic CSS syntax as SCSS syntax is CSS compatible