Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup Instructions? #52

Open
derwaldgeist opened this issue Jul 10, 2024 · 1 comment
Open

Setup Instructions? #52

derwaldgeist opened this issue Jul 10, 2024 · 1 comment

Comments

@derwaldgeist
Copy link

derwaldgeist commented Jul 10, 2024

The Github page claims that there is some setup instructions on this page:

https://github.com/FortAwesome/fa-icon-chooser/blob/main/packages/fa-icon-chooser/src/components/fa-icon-chooser/readme.md

but I can't find any there.

I am trying to embed the web component in Vue and would love to see how the web component has to be hooked up so it works. It would be enough to see this for plain vanilla JS. Yet not everybody is a web component pro :)

@damontgomery
Copy link

Here is the documentation on the properties that this component requires: https://github.com/FortAwesome/fa-icon-chooser/blob/main/packages/fa-icon-chooser/src/components/fa-icon-chooser/readme.md.

I'm not sure how you are expected to mount this using plain text given some of the properties are javascript functions. I could see a version of this that only requires a version or api token / kit token.

With plain JS, I think you can create the element and add the properties, then mount to the dom. In React, you can provide javascript functions as properties which is what we've done on our project.

Here is what I've done for React (TypeScript):

You need either a version like 6.6.0 or a api token and kit token. As far as I can tell the API URL is just https://api.fontawesome.com. You can start with the version since that doesn't require authorization. Maybe someone else can provide context as to why we need to provide getUrlText when it seems like common functionality. 🤷

import { QueryHandler } from '@fortawesome/fa-icon-chooser/dist/types/components/fa-icon-chooser/fa-icon-chooser';
import { UrlTextFetcher } from '@fortawesome/fa-icon-chooser/dist/types/utils/utils';
import config from 'temp/config';

// See https://github.com/FortAwesome/fa-icon-chooser/blob/main/packages/fa-icon-chooser/dev/runtime.js

// See https://github.com/FortAwesome/fa-icon-chooser/tree/main/packages/fa-icon-chooser-react.
// If a kitToken is provided, authorization is required with `apiToken`.

const {
  fontAwesomeApiUrl: apiURL,
  fontAwesomeApiToken: apiToken,
  fontAwesomeVersion: version,
  fontAwesomeKitToken: kitToken,
} = config;

export { version, kitToken };

// Use memory storage for now.
type AccessToken = {
  token: string;
  expiresAtEpochSeconds: number;
};

let accessToken: AccessToken | undefined = undefined;

// This function loads the Font Awesome library (as Text) which is then executed by the web component.
// Essentially, loads a configurable version of the library.
export const getUrlText: UrlTextFetcher = (url) =>
  fetch(url).then((response) => {
    if (response.ok) {
      return response.text();
    } else {
      throw new Error(`DEBUG: bad query for url: ${url}`);
    }
  });

export const getAccessToken = () => {
  // If we don't have an apiToken, we don't need to authenticate.
  if (!apiToken) {
    return Promise.resolve();
  }

  // If we already have a valid token, we don't need to get another one.
  if (accessToken && Math.floor(Date.now() / 1000) <= accessToken.expiresAtEpochSeconds) {
    return Promise.resolve();
  }

  return fetch(`${apiURL}/token`, {
    method: 'POST',
    headers: {
      authorization: `Bearer ${apiToken}`,
    },
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error('Failed to get an access token.');
      }
      return response.json();
    })
    .then((data) => {
      accessToken = {
        token: data['access_token'],
        expiresAtEpochSeconds: Math.floor(Date.now() / 1000) + data['expires_in'],
      };
    });
};

// Make queries for the Font Awesome chooser.
// This function handles authentication for the web component.
export const handleQuery: QueryHandler = (query, variables) =>
  getAccessToken()
    .then(() => {
      if (kitToken && !accessToken?.token) {
        throw new Error(
          'When using a kit, you must provide an apiToken so that an authorization token can be obtained.'
        );
      }

      const headers: {
        [key: string]: string;
      } = {
        'Content-Type': 'application/json',
      };

      if (accessToken) {
        headers['Authorization'] = `Bearer ${accessToken.token}`;
      }

      const cleanedQuery = query.replace(/\s+/g, ' ');

      return fetch(apiURL, {
        method: 'POST',
        headers,
        body: JSON.stringify({
          query: cleanedQuery,
          variables,
        }),
      });
    })
    .then((response) => {
      if (!response.ok) {
        throw new Error('bad query');
      }

      return response.json();
    });

We then load the component with

<FaIconChooser
  version={version}
  kitToken={kitToken}
  handleQuery={handleQuery}
  getUrlText={getUrlText}
  onFinish={handleResult}
/>

Where handleResult looks like

const handleResult = (event: CustomEvent<IconChooserResult>): void => {
  const prefix = event.detail?.prefix ?? '';
  const iconName = event.detail?.iconName ?? '';

  //...
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants