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

@artsofte/esw

v0.0.6

Published

Esw types

Downloads

11

Readme

ESW Docs

Общее

Платформа nocode имеет возможность встраивания виджетов. Виджет - это программный код выполняющийся на стороне нашей платформы. Виджет может отображать данные, делать запросы на сторонние ресурсы, взаимодействовать с сущностями платформы nocode

Реализация виджета

Простейший виджет

Сначала вам нужно реализовать сам виджет. Виджет - это js файл. Так выглядит самый простой виджет, который выводит на экран текст "Hello, world"

window.eswInit = () => {
  return new SimpleWidget();
};

class SimpleWidget {
  constructor() {
    const renderRoot: HTMLElement = getEswNamespace().renderRoot;
    renderRoot.innerText = "Hello, NoCode!";
  }
}

Наша платформа при работе с вашим файлом рассчитывает на наличие глобальной функции eswInit, которая возвращает инстанс виджета. Далее у этого инстанса будут вызываться хуки жизненного цикла.

 Использование TypeScript

Мы предоставляем npm пакет с декларациями типов сущностей платформы. Загрузить его можно с помощью команды

npm i @artsofte/esw

Исходный код и примеры

С кодом библиотеки @artsofte/esw можно ознакомиться на Github. Также можете ознакомиться с примерами виджетов Examples

Хуки жизненного цикла виджета

EswIsValid

Пример использования:

import { EswIsValid } from "@artsofte/esw";

window.eswInit = () => {
  return new SimpleWidget();
};

class SimpleWidget implements EswIsValid {
  public eswIsValid(): boolean {
    return true;
  }
}

При попытке клиента перехода на следующий шаг - виджеты на форме должны быть валидными. Если виджет не валиден, то система не позволяет пройти на следующий шаг. Если ваш виджет реализует интерфейс EswIsValid, то при попытке перехода на следующий шаг будет вызван метод eswIsValid.

EswAfterUnmount

Пример использования:

import { EswAfterUnmount } from "@artsofte/esw";

window.eswInit = () => {
  return new SimpleWidget();
};

class SimpleWidget implements EswAfterUnmount {
  private intervalId: number;

  constructor() {
    this.intervalId = setInterval(() => console.log("Hello, world"), 1000);
  }

  public eswAfterUnmount(): void {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
  }
}

Хук, обозначающий, что разметка вашего виджета уже удалена из DOM. Чаще всего используется для очистки таймеров, подписок.

EswOnSettingsChange

Пример использования:

import { Catalog, EswOnSettingsChange, GetSettingsReturn } from "@artsofte/esw";

interface IWidgetSettings {
  catalog: Catalog<{ name: string; value: string }>;
}

window.eswInit = (config: IWidgetSettings) => {
  return new CatalogReader(config);
};

window.eswInitSettings = (): GetSettingsReturn => {
  return {
    version: "v1",
    settings: [
      {
        type: "catalog",
        label: "Отображаемый каталог",
        saveTo: "catalog",
      },
    ],
  };
};

class CatalogReader implements EswOnSettingsChange {
  private readonly renderRoot: HTMLElement = getEswNamespace().renderRoot;

  constructor(private config: IWidgetSettings) {}

  public eswOnSettingsChange(config: IWidgetSettings): void {
    this.config = config;
    this.renderCatalogData();
  }

  private renderCatalogData(): void {
    this.config.catalog.content().then((data) => {
      this.renderRoot.innerText = JSON.stringify(data);
    });
  }
}

Данный хук вызывается при каждом изменении настроек в правом сайд-баре со стороны провайдера. Стоит обратить внимание на то, что данный хук не будет ни разу вызван при рендеринге виджета на клиентской форме.

Вывод настроек для провайдера

Платформа имеет встроенные механизмы справочников, модели документа и другие. Виджету требуется взаимодействие с ними. Всегда доступ к тем или иным сущностям выдает провайдер в правом сайд-баре. Например, виджет хочет записывать данные в модель документа. Тогда провайдер в правом сайде-баре выбирает область в модели документа, куда виджет имеет право писать данные. Другой пример, виджет хочет получить доступ до каталога: провайдер выбирает к какому каталогу именно виджет имеет доступ. Чтобы указать, какие настройки требуются - реализуйте глобальную функцию eswInitSettings. У каждой настройки есть параметр saveTo, этот параметр обозначает путь, куда в конфиге буду сохранены данные.

window.eswInitSettings = (): EswSettingsDeclaration => {
    return {
        version: "v1",
        settings: [
            {
                ...,
                saveTo: "param"
            }
        ]
    }
}

interface WidgetSettings {
    param: ... 
}

window.eswInit = (config: WidgetSettings) => {
    ...
}

Важно понимать, что при рендеринге на стороне провайдера config в метод eswInit будет пустым, так как провайдер еще не выбрал настройки. Объект будет наполняться по мере наполнения настроек провайдером.

Запись в модель документа

Виджет может записывать данные в модель документа. Для этого виджет должен вернуть требуемые настройки в методе initSettings

import {
  DocumentElement,
  EswAfterUnmount,
  GetSettingsReturn,
} from "@artsofte/esw";

window.eswInit = (config: IWidgetSettings) => {
  return new SimpleWidget(config);
};

interface IWidgetSettings {
  documentToken: DocumentElement<{ someData: string }>;
}

window.eswInitSettings = (): EswSettingsDeclaration => {
  return {
    version: "v1",
    settings: [
      {
        type: "documentElementWrite",
        label: "Запись в модель документа",
        saveTo: "documentToken",
        isRequired: true,
      },
    ],
  };
};

class SimpleWidget implements EswAfterUnmount {
  private readonly renderRoot: HTMLElement = getEswNamespace().renderRoot;

  private readonly intrevalId: number = 0;

  constructor(config: IWidgetSettings) {
    const isProvider = getEswNamespace().env.isProvider;

    if (isProvider) {
      this.renderProviderView();

      return;
    }

    let count = 0;

    this.intrevalId = setInterval(() => {
      count += 1;
      config.documentToken.patch("count", { value: count });
      this.renderRoot.innerHTML = `Count: ${count}`;
    }, 1000);
  }

  public eswAfterUnmount() {
    clearInterval(this.intrevalId);
  }

  private renderProviderView() {
    this.renderRoot.innerHTML = "Виджет патчит документ каждую секунду";
  }
}

Справочники

Виджет может читать данные из справочника, который к нему привяжет провайдер

import { Catalog, GetSettingsReturn } from "@artsfote/esw";

interface IWidgetSettings {
  catalog: Catalog<{ name: string; value: string }>;
}

window.eswInit = (config: IWidgetSettings) => {
  return new CatalogReader(config);
};

window.eswInitSettings = (): EswSettingsDeclaration => {
  return {
    version: "v1",
    settings: [
      {
        type: "catalog",
        label: "Отображаемый каталог",
        saveTo: "catalog",
      },
    ],
  };
};

class CatalogReader {
  private readonly renderRoot: HTMLElement = getEswNamespace().renderRoot;

  constructor(config: IWidgetSettings) {
    const isProvider = getEswNamespace().env.isProvider;

    if (isProvider) {
      this.renderProviderView();
    } else {
      config.catalog.content()
        .then((data) => this.render(data))
        .catch(() => this.renderError());
    }
  }

  private renderProviderView(): void {
    this.renderRoot.innerHTML = "Отображение каталогов";
  }

  private render(data: any): void {
    this.renderRoot.innerHTML = JSON.stringify(data);
  }

  private renderError(): void {
    this.renderRoot.innerHTML = "Ошибка чтения справочника";
  }
}

Другие настройки

  • select отображение селекта. В saveTo будет записан SelectItem

Использование бибилотек и фреймворков

Разработчик виджета может использовать любые доступные технологии. В директории examples есть примеры использования некоторых технологий. Платформа разрешает загружать как единый JS бандл, так и дает возможность загрузки множества скриптов по url. Нужно учесть, что рендеринг вашего скрипта происходит в shadow root, поэтому, нужно указать вашей библиотеке/фреймворку в какой именно HTML узел помещать разметку. Сам этот HTML узел можно получить вызвав следующий код: getEswNamespace().renderRoot

Ограничения

Рендеринг вашего html происходит вне встроенного iframe, а в рамках основного DOM в shadow-root. Это значит, что существует две разные среды JS, а значит разные инстансы глобальных объектов. Например, вы прослушиваете событие клика по кнопке. К прослушиванию добавляете callback, который принимает event с типом MouseEvent. Событие происходит в рамках основного DOM и передается в функцию, которая работает в рамках iframe. Поэтому проверка event instanceof MouseEvent не сработает. Так как event был создан в рамках основного окна и в прототипе лежит ссылка на MouseEvent основного окна. А вы совершаете проверку с MouseEvent вашего окна, в котором свои глобальные объект, никак не связанные с глобальными объектами основного окна.

Также часто можно наблюдать, когда создается прослушиватель на весь документ (document.addEventListener('click', () => {})). Это не будет работать в рамках виджета, так как document будет являться документом айфрейма. А так как iframe находится в head секции основного DOM, то клик по нему никогда не происходит. Нужно создавать прослушиватели только на свой корневой div элемент. Получить его можно при помощи getEswNamespace().renderRoot