lodash#uniqueId JavaScript Examples

The following examples show how to use lodash#uniqueId. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: create.js    From holo-schedule with MIT License 6 votes vote down vote up
create = (name, { onMessage = noop } = {}) => {
  portByName[name] = {
    name,
    postMessage: message => new Promise((res, rej) => {
      const id = uniqueId()
      setPendingMessage(id, { res, rej, name, message })
      if (!port) {
        connectPort()
      }
      port.postMessage({ isResponse: false, id, name, message })
    }),
    onMessage,
  }
  return portByName[name]
}
Example #2
Source File: menu.js    From qatrade_admin with MIT License 6 votes vote down vote up
/**
 * 给菜单数据补充上 path 字段
 * https://github.com/d2-projects/d2-admin/issues/209
 * @param {Array} menu 原始的菜单数据
 */
function supplementMenuPath (menu) {
  return menu.map(e => ({
    ...e,
    path: e.path || uniqueId('d2-menu-empty-'),
    ...e.children ? {
      children: supplementMenuPath(e.children)
    } : {}
  }))
}
Example #3
Source File: makeUniqueId.jsx    From covid19-testing with Apache License 2.0 6 votes vote down vote up
// makeUniqueId creates an ID suitable for identifying an HTML element.
// IDs are unique to the current execution context.
// To automatically provide a unique ID to your React component, use the
// UniqueFieldIs higher order component.
export default function makeUniqueId(label: ?string): string {
  const prefix = label ? slug(label.toLowerCase()) : 'unnamed';

  // eslint-disable-next-line local/use-emdash
  return uniqueId(`${prefix}-`);
}
Example #4
Source File: menu.js    From d2admin-permission with MIT License 6 votes vote down vote up
/**
 * 给菜单数据补充上 path 字段
 * https://github.com/d2-projects/d2-admin/issues/209
 * @param {Array} menu 原始的菜单数据
 */
function supplementMenuPath (menu) {
  return menu.map(e => ({
    ...e,
    path: e.path || uniqueId('d2-menu-empty-'),
    ...e.children ? {
      children: supplementMenuPath(e.children)
    } : {}
  }))
}
Example #5
Source File: index.js    From d2-crud-plus-with-d2admin-starter with MIT License 6 votes vote down vote up
/**
 * @description 给菜单数据补充上 path 字段
 * @description https://github.com/d2-projects/d2-admin/issues/209
 * @param {Array} menu 原始的菜单数据
 */
function supplementPath (menu) {
  return menu.map(e => ({
    ...e,
    path: e.path || uniqueId('d2-menu-empty-'),
    ...e.children ? {
      children: supplementPath(e.children)
    } : {}
  }))
}
Example #6
Source File: index.js    From django-vue-admin-pro with Apache License 2.0 6 votes vote down vote up
/**
 * @description 给菜单数据补充上 path 字段
 * @description https://github.com/d2-projects/d2-admin/issues/209
 * @param {Array} menu 原始的菜单数据
 */
function supplementPath (menu) {
  return menu.map(e => ({
    ...e,
    path: e.path || uniqueId('d2-menu-empty-'),
    ...e.children ? {
      children: supplementPath(e.children)
    } : {}
  }))
}
Example #7
Source File: useNewTeamMembers.js    From datapass with GNU Affero General Public License v3.0 6 votes vote down vote up
useNewTeamMembers = ({
  user,
  team_members,
  contactConfiguration,
}) =>
  useMemo(
    () =>
      chain(contactConfiguration)
        .keys()
        .map((type) => {
          const isMemberAlreadyInitialized = team_members.some(
            ({ type: t }) => t === type
          );
          if (isMemberAlreadyInitialized) {
            return null;
          }

          const tmp_id = uniqueId(`tmp_`);
          let newTeamMember = { type, tmp_id };
          if (type === 'demandeur') {
            newTeamMember = {
              ...newTeamMember,
              email: user.email,
            };
          }
          return newTeamMember;
        })
        .compact()
        .value(),
    [user, team_members, contactConfiguration]
  )
Example #8
Source File: CopyToCliboardButton.js    From datapass with GNU Affero General Public License v3.0 6 votes vote down vote up
CopyToCliboardButton = ({ textToCopy }) => {
  const [id] = useState(uniqueId());
  const clipboard = new ClipboardJS(`#clipboard-${id}`);

  clipboard.on('success', function (e) {
    e.trigger.classList.add('tooltip-opened');
    e.clearSelection();
    setTimeout(() => e.trigger.classList.remove('tooltip-opened'), 3000);
  });

  return (
    <button
      title="Copier dans le presse papier"
      id={`clipboard-${id}`}
      data-clipboard-text={textToCopy}
      className="inline-icon-button tooltip-controlled"
      tooltip="Copié !"
    >
      <ContentCopyIcon
        color={'var(--border-action-high-blue-france)'}
        size={14}
      />
    </button>
  );
}
Example #9
Source File: RadioInput.js    From datapass with GNU Affero General Public License v3.0 6 votes vote down vote up
RadioInput = ({
  label,
  name,
  options = [],
  value = null,
  disabled,
  onChange,
  required,
}) => {
  // id will be set once when the component initially renders, but never again
  // we generate an unique id prefixed by the field name
  const [id] = useState(uniqueId(name));

  return (
    <FieldsetWrapper title={label} required={required}>
      {options.map(({ id: optionId, label: optionLabel }) => (
        <div key={`${id}-${optionId}`} className="fr-radio-group">
          <input
            type="radio"
            name={name}
            id={`${id}-${optionId}`}
            value={optionId}
            checked={value === optionId}
            onChange={onChange}
            disabled={disabled ? 'disabled' : false}
            required={required}
          />
          <Label id={`${id}-${optionId}`} label={optionLabel} />
        </div>
      ))}
    </FieldsetWrapper>
  );
}
Example #10
Source File: CheckboxInput.js    From datapass with GNU Affero General Public License v3.0 6 votes vote down vote up
CheckboxInput = ({
  label,
  helper,
  meta,
  name,
  value = null,
  disabled,
  onChange,
  required,
  ...rest
}) => {
  // id will be set once when the component initially renders, but never again
  // we generate an unique id prefixed by the field name
  const [id] = useState(uniqueId(name));

  return (
    <div className="fr-checkbox-group">
      <input
        onChange={onChange}
        disabled={disabled ? 'disabled' : false}
        checked={value}
        type="checkbox"
        name={name}
        id={id}
        required={required}
        {...rest}
      />
      <Label
        id={id}
        label={label}
        required={required}
        helper={helper}
        meta={meta}
      />
    </div>
  );
}
Example #11
Source File: enhancedArray.js    From holo-schedule with MIT License 6 votes vote down vote up
createEnhancedArray = (target = [], limit = Infinity) => {
  const enhancedArray = reactive(target)

  Object.defineProperty(enhancedArray, 'any', {
    get() {
      return enhancedArray.length > 0
    },
  })

  Object.defineProperty(enhancedArray, 'last', {
    get() {
      return enhancedArray[enhancedArray.length - 1]
    },
  })

  enhancedArray.add = (item = {}) => {
    const indexedItem = { $id: uniqueId(), ...item }
    enhancedArray.push(indexedItem)

    if (enhancedArray.length > limit) {
      enhancedArray.shift()
    }

    return indexedItem
  }

  // Changes made by lodash#remove would not traced by Vue
  enhancedArray.remove = item => {
    const index = enhancedArray.indexOf(item)

    if (index === -1) return

    enhancedArray.splice(index, 1)
  }

  return enhancedArray
}
Example #12
Source File: TextAreaInput.js    From datapass with GNU Affero General Public License v3.0 5 votes vote down vote up
TextAreaInput = ({
  label,
  helper,
  meta,
  name,
  placeholder = '',
  value = null,
  disabled,
  onChange,
  ariaLabel,
  required,
  rows = 10,
}) => {
  // id will be set once when the component initially renders, but never again
  // we generate an unique id prefixed by the field name
  const [id] = useState(uniqueId(name));

  return (
    <div className="fr-input-group">
      <Label
        id={id}
        label={label}
        required={required}
        helper={helper}
        meta={meta}
      />
      <textarea
        className="fr-input"
        rows={rows}
        onChange={onChange}
        name={name}
        placeholder={placeholder}
        id={id}
        readOnly={disabled}
        value={value}
        aria-label={ariaLabel}
        required={required}
      />
    </div>
  );
}
Example #13
Source File: SelectInput.js    From datapass with GNU Affero General Public License v3.0 5 votes vote down vote up
SelectInput = ({
  label,
  name,
  helper,
  meta,
  options = [],
  value,
  disabled,
  onChange,
  required,
  useOtherOption = false,
}) => {
  // id will be set once when the component initially renders, but never again
  // we generate an unique id prefixed by the field name
  const [id] = useState(uniqueId(name));

  const isOtherSelected = useMemo(
    () => useOtherOption && !options.map(({ id: i }) => i).includes(value),
    [useOtherOption, options, value]
  );

  return (
    <SideBySideWrapper>
      <div className="fr-select-group">
        <Label
          id={id}
          label={label}
          required={required}
          helper={helper}
          meta={meta}
        />
        <select
          id={id}
          className="fr-select"
          name={name}
          value={isOtherSelected ? '' : value}
          disabled={disabled}
          onChange={onChange}
          required={required}
        >
          {options.map(({ id, label: optionLabel }) => (
            <option key={id} value={id}>
              {optionLabel}
            </option>
          ))}
          {useOtherOption && (
            <option key="" value="">
              Autre
            </option>
          )}
        </select>
      </div>
      {isOtherSelected && (
        <TextInput
          label="Précisez :"
          name={name}
          value={value}
          disabled={disabled}
          onChange={onChange}
          required={required}
          ariaLabel={`Précisez le ${label}`}
        />
      )}
    </SideBySideWrapper>
  );
}
Example #14
Source File: Input.js    From datapass with GNU Affero General Public License v3.0 5 votes vote down vote up
Input = ({
  type = 'text',
  label,
  helper,
  meta,
  name,
  placeholder = '',
  value = null,
  disabled,
  onChange,
  ariaLabel,
  required,
  ...rest
}) => {
  // id will be set once when the component initially renders, but never again
  // we generate an unique id prefixed by the field name
  const [id] = useState(uniqueId(name));

  return (
    <div className="fr-input-group">
      <Label
        id={id}
        label={label}
        required={required}
        helper={helper}
        meta={meta}
      />
      <input
        className="fr-input"
        type={type}
        onChange={onChange}
        name={name}
        placeholder={placeholder}
        id={id}
        readOnly={disabled}
        value={value}
        aria-label={ariaLabel}
        required={required}
        {...rest}
      />
    </div>
  );
}
Example #15
Source File: resources.js    From file-picker with Apache License 2.0 5 votes vote down vote up
export function buildResource(resource) {
  const ext = resource.type !== 'dir' ? _extName(resource.name) : ''
  return {
    type: resource.type === 'dir' ? 'folder' : resource.type,
    // actual file id (string)
    id: resource.fileInfo['{http://owncloud.org/ns}fileid'],
    // temporary list id, to be used for view only and for uniqueness inside the list
    viewId: uniqueId('file-'),
    starred: resource.fileInfo['{http://owncloud.org/ns}favorite'] !== '0',
    mdate: resource.fileInfo['{DAV:}getlastmodified'],
    size: (function () {
      if (resource.type === 'dir') {
        return resource.fileInfo['{http://owncloud.org/ns}size']
      } else {
        return resource.fileInfo['{DAV:}getcontentlength']
      }
    })(),
    extension: (function () {
      return ext
    })(),
    name: path.basename(resource.name),
    path: resource.name,
    permissions: resource.fileInfo['{http://owncloud.org/ns}permissions'] || '',
    etag: resource.fileInfo['{DAV:}getetag'],
    sharePermissions:
      resource.fileInfo['{http://open-collaboration-services.org/ns}share-permissions'],
    shareTypes: (function () {
      let shareTypes = resource.fileInfo['{http://owncloud.org/ns}share-types']
      if (shareTypes) {
        shareTypes = chain(shareTypes)
          .filter(
            (xmlvalue) =>
              xmlvalue.namespaceURI === 'http://owncloud.org/ns' &&
              xmlvalue.nodeName.split(':')[1] === 'share-type'
          )
          .map((xmlvalue) => parseInt(xmlvalue.textContent || xmlvalue.text, 10))
          .value()
      }
      return shareTypes || []
    })(),
    privateLink: resource.fileInfo['{http://owncloud.org/ns}privatelink'],
    owner: {
      username: resource.fileInfo['{http://owncloud.org/ns}owner-id'],
      displayName: resource.fileInfo['{http://owncloud.org/ns}owner-display-name']
    },
    canUpload: function () {
      return this.permissions.indexOf('C') >= 0
    },
    canDownload: function () {
      return this.type !== 'folder'
    },
    canBeDeleted: function () {
      return this.permissions.indexOf('D') >= 0
    },
    canRename: function () {
      return this.permissions.indexOf('N') >= 0
    },
    canShare: function () {
      return this.permissions.indexOf('R') >= 0
    },
    canCreate: function () {
      return this.permissions.indexOf('C') >= 0
    },
    isMounted: function () {
      return this.permissions.indexOf('M') >= 0
    },
    isReceivedShare: function () {
      return this.permissions.indexOf('S') >= 0
    }
  }
}
Example #16
Source File: index.js    From datapass with GNU Affero General Public License v3.0 4 votes vote down vote up
TextInputWithSuggestions = ({
  label,
  name,
  options = [],
  value,
  disabled,
  onChange,
  required,
}) => {
  // id will be set once when the component initially renders, but never again
  // we generate an unique id prefixed by the field name
  const [id] = useState(uniqueId(name));

  const [suggestions, setSuggestions] = useState([]);

  // from https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
  const normalize = (string = '') =>
    string
      .toLowerCase()
      .normalize('NFD')
      .replace(/\p{Diacritic}/gu, '')
      .replace(/[^\w\s]/gi, ' ');

  useEffect(() => {
    const newSuggestions = chain(options)
      .map(({ id, label }) => ({
        id,
        label,
        distance: levenshtein(normalize(value), normalize(label)).similarity,
      }))
      .sortBy(['distance'])
      .reverse()
      .filter(({ distance }) => distance > 0.25)
      .take(10)
      .value();

    setSuggestions(newSuggestions);
  }, [options, value]);

  const [isDropDownOpen, setIsDropDownOpen] = useState(false);
  const [activeSuggestion, setActiveSuggestion] = useState(null);

  const closeDropDown = () => {
    setIsDropDownOpen(false);
    setActiveSuggestion(null);
  };

  const onKeyDown = (e) => {
    if (e.key === 'Tab' && isDropDownOpen) {
      e.preventDefault();
      closeDropDown();
    }

    if (e.key === 'Enter' && !isDropDownOpen) {
      e.preventDefault();
      setIsDropDownOpen(true);
    }

    if (e.key === 'Escape' && isDropDownOpen) {
      e.preventDefault();
      closeDropDown();
    }

    if (e.key === 'ArrowDown' && !isDropDownOpen) {
      e.preventDefault();
      setIsDropDownOpen(true);
      setActiveSuggestion(0);
    }

    if (e.key === 'ArrowDown' && isDropDownOpen && isNull(activeSuggestion)) {
      e.preventDefault();
      setActiveSuggestion(0);
    }

    if (e.key === 'ArrowDown' && isDropDownOpen && isNumber(activeSuggestion)) {
      e.preventDefault();
      setActiveSuggestion(min([activeSuggestion + 1, suggestions.length - 1]));
    }

    if (e.key === 'ArrowUp' && isDropDownOpen) {
      e.preventDefault();
      setActiveSuggestion(max([activeSuggestion - 1, 0]));
    }

    if (e.key === 'Enter' && isDropDownOpen) {
      e.preventDefault();
      onChange({
        target: { name, value: suggestions[activeSuggestion]?.label },
      });
      closeDropDown();
    }
  };

  const handleChange = (value) => {
    closeDropDown();
    onChange({ target: { name, value } });
  };

  return (
    <div className="fr-input-group">
      <label htmlFor={id}>
        {label}
        {required && ' *'}
      </label>
      <input
        className="fr-input"
        type="text"
        onChange={onChange}
        name={name}
        id={id}
        readOnly={disabled}
        value={value}
        required={required}
        onKeyDown={onKeyDown}
        onClick={() => setIsDropDownOpen(true)}
        onInput={() => setIsDropDownOpen(true)}
      />
      {!disabled && isDropDownOpen && !isEmpty(suggestions) && (
        <Dropdown onOutsideClick={closeDropDown} fillWidth>
          {suggestions.map(({ id, label }, index) => (
            <div
              key={id}
              className={`datapass-text-input-suggestion ${
                activeSuggestion === index
                  ? 'datapass-text-input-active-suggestion'
                  : ''
              }`}
              onClick={() => handleChange(label)}
            >
              {label}
            </div>
          ))}
        </Dropdown>
      )}
    </div>
  );
}
Example #17
Source File: index.js    From datapass with GNU Affero General Public License v3.0 4 votes vote down vote up
ÉquipeSection = ({
  initialContacts = {},
  responsableTechniqueNeedsMobilePhone = false,
}) => {
  const {
    isUserEnrollmentLoading,
    disabled,
    onChange,
    enrollment: { team_members = [] },
  } = useContext(FormContext);
  const { user } = useAuth();
  const contactConfiguration = useMemo(() => {
    const defaultInitialContacts = {
      demandeur: {
        header: 'Demandeur',
        description: getDefaultDemandeurDescription(),
        forceDisable: true,
      },
      responsable_traitement: {
        header: 'Responsable de traitement',
        description: getDefaultResponsableTraitementDescription(),
      },
      delegue_protection_donnees: {
        header: 'Délégué à la protection des données',
        description: getDefaultDelegueProtectionDonneesDescription(),
      },
      responsable_technique: {
        header: 'Responsable technique',
        description: getDefaultResponsableTechniqueDescription(
          responsableTechniqueNeedsMobilePhone
        ),
        displayMobilePhoneLabel: responsableTechniqueNeedsMobilePhone,
      },
    };

    return chain(defaultInitialContacts)
      .assign(initialContacts)
      .omitBy((p) => !p)
      .value();
  }, [initialContacts, responsableTechniqueNeedsMobilePhone]);

  const newTeamMembers = useNewTeamMembers({
    user,
    team_members,
    contactConfiguration,
  });

  useEffect(() => {
    if (!isUserEnrollmentLoading && !disabled && !isEmpty(newTeamMembers)) {
      onChange({
        target: {
          name: 'team_members',
          value: [...team_members, ...newTeamMembers],
        },
      });
    }
  }, [
    isUserEnrollmentLoading,
    disabled,
    onChange,
    team_members,
    newTeamMembers,
  ]);

  const displayIdForAdministrator = useMemo(
    () => user && user.roles.includes('administrator'),
    [user]
  );

  const updateWithUserInformation = useCallback(
    (index) => {
      if (team_members[index]?.email !== user.email) {
        onChange({
          target: {
            name: `team_members[${index}].email`,
            value: user.email,
          },
        });
      }
      if (team_members[index]?.given_name !== user.given_name) {
        onChange({
          target: {
            name: `team_members[${index}].given_name`,
            value: user.given_name,
          },
        });
      }
      if (team_members[index]?.family_name !== user.family_name) {
        onChange({
          target: {
            name: `team_members[${index}].family_name`,
            value: user.family_name,
          },
        });
      }
      if (team_members[index]?.phone_number !== user.phone_number) {
        onChange({
          target: {
            name: `team_members[${index}].phone_number`,
            value: user.phone_number,
          },
        });
      }
      if (team_members[index]?.job !== user.job) {
        onChange({
          target: {
            name: `team_members[${index}].job`,
            value: user.job,
          },
        });
      }
    },
    [team_members, user, onChange]
  );

  useEffect(() => {
    if (!isUserEnrollmentLoading && !disabled && !isEmpty(team_members)) {
      const currentDemandeurIndex = team_members.findIndex(
        ({ type, email }) => type === 'demandeur' && email === user.email
      );

      if (currentDemandeurIndex !== -1) {
        updateWithUserInformation(currentDemandeurIndex);
      }
    }
  }, [
    isUserEnrollmentLoading,
    disabled,
    team_members,
    user,
    updateWithUserInformation,
  ]);

  const addTeamMemberFactory = (type) => {
    const tmp_id = uniqueId(`tmp_`);
    const newTeamMember = { type, tmp_id };

    return () =>
      onChange({
        target: {
          name: 'team_members',
          value: [...team_members, newTeamMember],
        },
      });
  };

  const removeTeamMember = (index) => {
    onChange({
      target: {
        name: 'team_members',
        value: [
          ...team_members.slice(0, index),
          ...team_members.slice(index + 1),
        ],
      },
    });
  };

  return (
    <ScrollablePanel scrollableId={SECTION_ID}>
      <h2>{SECTION_LABEL}</h2>
      <ExpandableQuote title="Comment renseigner la liste des contacts ?" large>
        {Object.entries(contactConfiguration).map(([type, { description }]) => (
          <p key={type}>{description}</p>
        ))}
      </ExpandableQuote>
      <CardContainer flex={false}>
        {Object.entries(contactConfiguration).map(
          ([
            type,
            {
              header,
              forceDisable,
              displayMobilePhoneLabel,
              displayIndividualEmailLabel,
              displayGroupEmailLabel,
              contactByEmailOnly,
              multiple,
            },
          ]) => (
            <React.Fragment key={type}>
              {team_members
                .filter(({ type: t }) => t === type)
                .map(({ id, tmp_id, ...team_member }) => (
                  <Contact
                    heading={header}
                    key={id || tmp_id}
                    id={id}
                    index={findIndex(team_members, ({ id: i, tmp_id: t_i }) => {
                      if (id) {
                        // if id is defined match on id field
                        return i === id;
                      }
                      if (tmp_id) {
                        // if id is not defined and tmp_id is defined
                        // match on tmp_id
                        return t_i === tmp_id;
                      }
                      return false;
                    })}
                    {...team_member}
                    displayMobilePhoneLabel={displayMobilePhoneLabel}
                    displayIndividualEmailLabel={displayIndividualEmailLabel}
                    displayGroupEmailLabel={displayGroupEmailLabel}
                    contactByEmailOnly={contactByEmailOnly}
                    displayIdForAdministrator={displayIdForAdministrator}
                    disabled={forceDisable || disabled}
                    onChange={onChange}
                    onDelete={multiple && !id && removeTeamMember}
                    onUpdateWithUserInformation={updateWithUserInformation}
                    canUpdatePersonalInformation={
                      team_member.email === user.email &&
                      (team_member.given_name !== user.given_name ||
                        team_member.family_name !== user.family_name ||
                        team_member.phone_number !== user.phone_number ||
                        team_member.job !== user.job)
                    }
                  />
                ))}
              {!disabled && multiple && (
                <AddCard
                  label={`ajouter un ${header.toLowerCase()}`}
                  onClick={addTeamMemberFactory(type)}
                />
              )}
            </React.Fragment>
          )
        )}
      </CardContainer>
    </ScrollablePanel>
  );
}