lodash#startCase TypeScript Examples

The following examples show how to use lodash#startCase. 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: utils.ts    From prism-frontend with MIT License 7 votes vote down vote up
function formatLayersCategories(layersList: {
  [key: string]: Array<LayerKey | TableKey>;
}): LayersCategoriesType {
  return map(layersList, (layerKeys, layersListKey) => {
    return {
      title: startCase(layersListKey),
      layers: layerKeys.filter(isLayerKey).map(key => {
        if (typeof key === 'object') {
          const group = (mapKeys(key, (_v, k: string) =>
            camelCase(k),
          ) as unknown) as MenuGroup;
          const mainLayer = group.layers.find(l => l.main);
          const layer = LayerDefinitions[mainLayer?.id as LayerKey];
          // eslint-disable-next-line fp/no-mutation
          layer.group = group;
          return layer;
        }
        return LayerDefinitions[key as LayerKey];
      }),
      tables: layerKeys.filter(isTableKey).map(key => TableDefinitions[key]),
    };
  });
}
Example #2
Source File: utils.ts    From prism-frontend with MIT License 7 votes vote down vote up
menuList: MenuItemsType = map(
  appConfig.categories,
  (layersCategories, categoryKey) => {
    if (!checkLayersCategories(layersCategories)) {
      throw new Error(
        `'${categoryKey}' in prism.json isn't a valid category. Check console for more details.`,
      );
    }
    return {
      title: startCase(categoryKey),
      icon: get(appConfig, `icons.${categoryKey}`, 'icon_vulnerable.png'),
      layersCategories: formatLayersCategories(layersCategories),
    };
  },
)
Example #3
Source File: utils.ts    From aqualink-app with MIT License 7 votes vote down vote up
/**
 * Returns a human friendly string of a order key.
 * @param orderKey key to return the string for.
 */
export function getOrderKeysFriendlyString(orderKey: OrderKeys) {
  switch (orderKey) {
    case OrderKeys.DHW:
      return "DHW";
    default:
      return startCase(orderKey);
  }
}
Example #4
Source File: bputils.ts    From o7 with MIT License 7 votes vote down vote up
async function printKeys(bp: any, keys: string[], valueModifier: number, total: { cost: number; }, isMobile: boolean) {
  let result = '```\n';
  let groupCost = 0;
  for (const key of keys) {
    if (!bp[key]) {
      continue;
    }
    const marketItem = await getMarketData(key);
    const quantity = Math.ceil(bp[key] * valueModifier);
    result += alignText(startCase(key), numeral(quantity).format('0,0'), isMobile);
    if (!marketItem) {
      result += '\n';
      continue;
    }
    const price = getLatestValidPrice(marketItem);
    const cost = price.buy * quantity;
    groupCost += cost;
    result += `${(isMobile ? '\n' : '')} [${numeral(price.buy).format('0[.]0a')} ISK > ${numeral(cost).format('0[.]0a')} ISK]\n`;
  }
  result += `\n${alignText('Total Cost', (`${numeral(groupCost).format('0[.]0a')} ISK`), isMobile)}`;
  total.cost += groupCost;
  return result + '```';
}
Example #5
Source File: Shortcut.tsx    From querybook with Apache License 2.0 6 votes vote down vote up
Shortcut: React.FunctionComponent = () => (
    <div className="Shortcut">
        {Object.entries(KeyMap).map(([sectionTitle, sectionKeys]) => (
            <div className="Shortcut-box" key={sectionTitle}>
                <Subtitle>{startCase(sectionTitle)}</Subtitle>
                {Object.values(sectionKeys).map((shortcut, idx) => {
                    const { key, name: keyComboName } = shortcut;
                    const keys = (key ?? '').split('-');
                    return (
                        <div className="Shortcut-item" key={idx}>
                            <div className="Shortcut-keys">
                                {keys.map((key, i) => {
                                    if (i === 0) {
                                        return (
                                            <KeyboardKey value={key} key={i} />
                                        );
                                    }
                                    return (
                                        <React.Fragment key={i}>
                                            <span className="pr4">+</span>
                                            <KeyboardKey value={key} />
                                        </React.Fragment>
                                    );
                                })}
                            </div>
                            <div className="Shortcut-text">{keyComboName}</div>
                        </div>
                    );
                })}
            </div>
        ))}
    </div>
)
Example #6
Source File: commands.ts    From o7 with MIT License 6 votes vote down vote up
export function getHelpEmbed(command: Command, prefix: string) {
  const embed = new MessageEmbed().setTitle(`${startCase(command.name)} Command Help`)
    .setColor(command.help?.color || '#fff500');
  embed.addField('Usage', `**${prefix}${command.alias[0]}** ${command.args && typeof command.args !== 'function' ? command.args.map(arg => arg.optional ? `(${arg.name} *optional)` : arg.name).join(' ') : ''}
${command.alias.length > 0 ? `*alias:* ${command.alias.slice(1).map(a => `**${prefix}${a}**`).join(', ')}` : ''}`);
  if (command.help) {
    embed.setDescription(command.help?.description);
    if (command.help.examples) {
      embed.addField('Examples:', command.help.examples.map(e => `\`${prefix}${command.alias[0]} ${e.args}\`${e.description ? `\n->${e.description}` : ''}`).join('\n\n'));
    }
  }
  return embed;
}
Example #7
Source File: help.ts    From o7 with MIT License 6 votes vote down vote up
function getHelpEmbeds(prefix: string, provider: CMProvider, initialEmbed: MessageEmbed): MessageEmbed[] {
  const embeds: MessageEmbed[] = [];
  let counter = 0;
  const done: { [id: string]: boolean; } = {};
  let embed = initialEmbed;
  provider.commands.forEach(command => {
    if (command.type === 'module') return; // TODO: iterate modules for help
    if (command.owner || command.disabled || done[command.alias[0]]) return;
    embed.addField(`${prefix}${command.alias[0]}`, command.help?.description || startCase(command.name));
    done[command.alias[0]] = true;
    if (++counter == 25) {
      embeds.push(embed);
      embed = new MessageEmbed().setColor(7506394);
      counter = 0;
    }
  });

  if (counter > 0) {
    embeds.push(embed);
    embed = new MessageEmbed().setColor(7506394);
  }

  provider.modules.forEach(module => {
    if (!module.commandGroup) return;
    embed.setTitle(`${startCase(module.name)}`);
    if (module.help) {
      embed.setDescription(module.help.description);
    }
    const moduledEmbeds = getHelpEmbeds(`${prefix}${module.commandGroup[0]} `, module, embed);
    embeds.push(...moduledEmbeds);
    embed = new MessageEmbed().setColor(7506394);
  });
  return embeds;
}
Example #8
Source File: pascal-case.ts    From prisma-nestjs-graphql with MIT License 5 votes vote down vote up
export function pascalCase(string: string) {
  return startCase(camelCase(string)).replace(/ /g, '');
}
Example #9
Source File: TransactionLogPane.tsx    From client with GNU General Public License v3.0 5 votes vote down vote up
humanizeTransactionType = (tx: Transaction) => startCase(tx.intent.methodName)
Example #10
Source File: NotificationManager.tsx    From client with GNU General Public License v3.0 5 votes vote down vote up
txInitError(methodName: ContractMethodName, failureReason: string) {
    this.notify(
      NotificationType.TxInitError,
      <span>
        {startCase(methodName)} failed. Reason: {failureReason}
      </span>
    );
  }
Example #11
Source File: commands.ts    From o7 with MIT License 5 votes vote down vote up
export async function processCommand(
  message: Message,
  commandProvider: { commands: Collection<string, Command | Module>; },
  content: string,
  prefix: string) {
  const [c, args] = content.split(/ (.+)/);
  const cmdString = c.toLowerCase();
  if (!commandProvider.commands.has(cmdString)) return;
  try {
    const command = commandProvider.commands.get(cmdString);
    if (!command || command.disabled) return;

    if (command.type === 'module') {
      return await processCommand(message, command, args, `${prefix}${(command.commandGroup as any)[0]} `);
    }

    if (command.channel) {
      if (command.channel === 'guild' && !message.guild) return;
      if (command.channel === 'dm' && message.guild) return;
    }

    if (command.owner && !message.client.owners.find(s => s === message.author.id)) return;

    if (command.userPermissions) {
      if (typeof command.userPermissions === 'function' && !command.userPermissions(message)) return;
      for (const permission of command.userPermissions as DiscordPermissions[]) {
        if (!message.member?.hasPermission(permission)) {
          return;
        }
      }
    }

    if (command.clientPermissions) {
      for (const permission of command.clientPermissions) {
        if (!message.guild?.me?.hasPermission(permission)) {
          return message.author.send(`It looks like I don't have the required permissions for the **${startCase(command.name)}** command on **${message.guild?.name}**.\nI need the following permission${command.clientPermissions.length > 1 ? 's' : ''} ${command.clientPermissions.map(p => `\`${p}\``).join(' ')}.`);
        }
      }
    }

    message.sendHelp = () => message.channel.send(getHelpEmbed(command, prefix));

    if (isHelp(command, args)) {
      return message.sendHelp();
    }

    if (typeof command.args === 'function') {
      const result = await command.args(message, command);
      if (!result) {
        return message.sendHelp();
      }
      command.handler(message, result);
      return true;
    } else {
      const parsedArgs = await parseArgs(command, args, message);
      if (parsedArgs?.failed) {
        return message.sendHelp();
      }
      command.handler(message, parsedArgs?.args);
      return true;
    }

  } catch (err) {
    console.error(err);
    message.channel.send(`I'm sorry, there was a problem executing that command.`);
  }
}
Example #12
Source File: reprocess.ts    From o7 with MIT License 5 votes vote down vote up
command: CommandDef = {
  name: 'reprocess',
  alias: ['reprocess', 'rp'],
  args: [{
    name: 'itemName',
    type: 'content',
  }],
  help: {
    description: 'This command will return the resources given when reprocessing an item. Default value returned assumes no skills trained, meaning 30% efficiency. Optionally, providing your reprocessing percentage will adjust the returned value based on the given value.',
    examples: [{
      args: 'spod',
      description: 'Returns the resources given when reprocessing Spodumain at 30% efficiency.'
    },{
      args: 'mk5 stasis web 50',
      description: 'Returns the resources given when reprocessing a MK5 Stasis Webifier at 50% efficiency.',
    }]
  },
  handler: (message: Message, args: { itemName: string; }) => {
    const parsedArgs = args.itemName.toLowerCase().match(/((?:mk\s?\d)?[a-zA-Z ]+) ?([0-9.]*)/);
    if (!parsedArgs) {
      return message.channel.send(`Sorry, I couldn't understand that.`);
    }

    const searchTerms = parsedArgs[1].trim();
    const searchResult = fuse.search(searchTerms);
    if (!searchResult || searchResult.length == 0) {
      return message.channel.send(`Sorry, I couldn't find any items that could be reprocessed using the item name \`${searchTerms}\`.`);
    }
    const reprocItem = searchResult[0].item;
    const percentage = Math.max(.3, Math.min(.615, (parsedArgs[2] ? parseFloat(parsedArgs[2]) : 30) * .01));

    const embed = new MessageEmbed()
      .setTitle(`${reprocItem.name} Reprocess Results`)
      .setDescription(`*efficiency ${numeral(percentage).format('0[.]0%')}*`);

    for (const key in reprocItem) {
      if (key == 'name') continue;
      if (reprocItem[key] === 0) continue;
      embed.addField(startCase(key), numeral(reprocItem[key] * percentage).format('0,0'), true);
    }

    return message.channel.send(embed);
  }
}
Example #13
Source File: config.ts    From solana-program-registry with Apache License 2.0 5 votes vote down vote up
makeProgramLabel = (author: Author, programName: string) =>
  `${author.info?.name ?? `@${author.name}`} - ${startCase(programName)}`
Example #14
Source File: SettingsSummary.tsx    From fishbowl with MIT License 5 votes vote down vote up
function SettingsSummary() {
  const { t } = useTranslation()
  const currentGame = React.useContext(CurrentGameContext)
  let cardPlayStyle = ""
  switch (currentGame.card_play_style) {
    case GameCardPlayStyleEnum.PlayersSubmitWords:
      const count = Number(currentGame.num_entries_per_player)
      const startingLetter = currentGame.starting_letter
      const submitWord = "Players will submit {{ count }} word"
      const startingWith = 'starting with the letter "{{ startingLetter }}"'

      if (startingLetter) {
        cardPlayStyle = t(
          "settings.summary.cardStyle.playersSubmitLetter",
          `${submitWord}, ${startingWith}.`,
          {
            count,
            startingLetter,
            defaultValue_plural: `${submitWord}s, all ${startingWith}.`,
          }
        )
      } else {
        cardPlayStyle = t(
          "settings.summary.cardStyle.playersSubmit",
          `${submitWord}.`,
          {
            count,
            defaultValue_plural: `${submitWord}s.`,
          }
        )
      }

      if (currentGame.screen_cards) {
        cardPlayStyle += ` ${t(
          "settings.summary.cardStyle.hostScreens",
          "The host will be able to screen words."
        )}`
      }
      break
    case GameCardPlayStyleEnum.HostProvidesWords:
      cardPlayStyle = t(
        "settings.summary.cardStyle.hostProvides",
        "The host will provide the words."
      )
      break
  }

  return (
    <>
      {cardPlayStyle}
      <br />
      <br />
      {t(
        "settings.summary.turnSeconds",
        "Turns will last {{ seconds }} seconds across rounds of {{ rounds }}.",
        {
          seconds: currentGame.seconds_per_turn,
          rounds: currentGame.rounds
            .map((round) => startCase(round.value))
            .join(", "),
        }
      )}{" "}
      {currentGame.allow_card_skips
        ? t(
            "settings.summary.cardSkips",
            "Players can skip cards during their turn."
          )
        : t(
            "settings.summary.noCardSkips",
            "Players cannot skip cards during their turn."
          )}
    </>
  )
}
Example #15
Source File: DataTableNavigatorSearch.tsx    From querybook with Apache License 2.0 4 votes vote down vote up
DataTableNavigatorSearch: React.FC<{
    metastoreId: number;
    searchString: string;
    onSearch: (s: string) => void;
    searchFilters: ITableSearchFilters;
    updateSearchFilter: <K extends keyof ITableSearchFilters>(
        filterKey: K,
        filterVal: ITableSearchFilters[K]
    ) => void;
    resetSearchFilter: () => void;

    showTableSearchResult: boolean;
}> = ({
    searchString,
    onSearch,
    searchFilters,
    updateSearchFilter,
    resetSearchFilter,

    showTableSearchResult,
}) => {
    const [showSearchFilter, , toggleSearchFilter] = useToggleState(false);
    const filterButtonRef = useRef<HTMLAnchorElement>();
    const searchFiltersSize = useMemo(() => Object.keys(searchFilters).length, [
        searchFilters,
    ]);
    const { key: sortSchemaKey, asc: sortSchemaAsc } = useSelector(
        (state: IStoreState) => state.dataTableSearch.schemas.sortSchemasBy
    );

    const updateTags = useCallback(
        (newTags: string[]) => {
            updateSearchFilter('tags', newTags.length ? newTags : null);
        },
        [updateSearchFilter]
    );

    const dispatch = useDispatch();

    const searchFiltersPickerDOM = showSearchFilter && (
        <Popover
            onHide={toggleSearchFilter}
            anchor={filterButtonRef.current}
            layout={['right', 'top']}
        >
            <div className="DataTableNavigatorSearchFilter">
                <SoftButton
                    title="Reset"
                    className="filter-reset-button"
                    size="small"
                    onClick={resetSearchFilter}
                />
                <div>
                    <SearchFilterRow
                        title="Featured"
                        className="toggle-padding"
                    >
                        <ToggleSwitch
                            checked={searchFilters.golden}
                            onChange={(checked) =>
                                updateSearchFilter(
                                    'golden',
                                    checked ? true : null
                                )
                            }
                        />
                    </SearchFilterRow>
                    <SearchFilterRow title="Schema">
                        <SearchBar
                            value={searchFilters?.schema ?? ''}
                            onSearch={(s: string) =>
                                updateSearchFilter(
                                    'schema',
                                    s.length ? s : null
                                )
                            }
                            placeholder="Full schema name"
                        />
                    </SearchFilterRow>
                    <SearchFilterRow title="Tags">
                        <TableTagGroupSelect
                            tags={searchFilters?.tags}
                            updateTags={updateTags}
                        />
                    </SearchFilterRow>
                </div>
            </div>
        </Popover>
    );

    return (
        <div className="DataTableNavigatorSearch flex-row">
            <SearchBar
                value={searchString}
                onSearch={onSearch}
                placeholder="Search by Name"
                transparent
            />

            {!showTableSearchResult && (
                <OrderByButton
                    className="mr4"
                    asc={sortSchemaAsc}
                    orderByField={startCase(sortSchemaKey)}
                    orderByFieldSymbol={sortSchemaKey === 'name' ? 'Aa' : 'Tc'}
                    onAscToggle={() => {
                        dispatch(changeSchemasSort(null, !sortSchemaAsc));
                    }}
                    onOrderByFieldToggle={() => {
                        dispatch(
                            changeSchemasSort(
                                sortSchemaKey === 'table_count'
                                    ? 'name'
                                    : 'table_count'
                            )
                        );
                    }}
                />
            )}

            <IconButton
                ref={filterButtonRef}
                size={'18px'}
                className="table-search-filter-button"
                noPadding
                onClick={toggleSearchFilter}
                icon="Sliders"
                active={searchFiltersSize > 0}
                ping={searchFiltersSize > 0 ? String(searchFiltersSize) : null}
            />
            {searchFiltersPickerDOM}
        </div>
    );
}
Example #16
Source File: SchemaTableItem.tsx    From querybook with Apache License 2.0 4 votes vote down vote up
SchemaTableItem: React.FC<{
    name: string;
    onLoadMore: () => Promise<any>;
    tables: ITableSearchResult[];
    selectedTableId: number;
    total: number;
    tableRowRenderer: (table: ITableSearchResult) => React.ReactNode;
    onSortChanged: (
        sortKey?: SchemaTableSortKey | null,
        sortAsc?: boolean | null
    ) => void;
    sortOrder: {
        asc: boolean;
        key: SchemaTableSortKey;
    };
}> = ({
    name,
    onLoadMore,
    tables,
    selectedTableId,
    total,
    tableRowRenderer,
    onSortChanged,
    sortOrder,
}) => {
    const [isExpanded, setIsExpanded] = useState<boolean>(false);
    const data = useMemo(() => prepareSchemaNames(tables, selectedTableId), [
        tables,
        selectedTableId,
    ]);

    return (
        <div className="SchemaTableItem mb12">
            <StyledItem className="horizontal-space-between navigator-header pl8">
                <div
                    className="schema-name flex1 flex-row"
                    onClick={() => setIsExpanded(!isExpanded)}
                >
                    <Title size="small" className="one-line-ellipsis">
                        {name}
                    </Title>
                </div>
                <OrderByButton
                    asc={sortOrder.asc}
                    orderByField={startCase(sortOrder.key)}
                    orderByFieldSymbol={sortOrder.key === 'name' ? 'Aa' : 'Is'}
                    onAscToggle={() => onSortChanged(null, !sortOrder.asc)}
                    onOrderByFieldToggle={() =>
                        onSortChanged(
                            sortOrder.key === 'name'
                                ? 'importance_score'
                                : 'name'
                        )
                    }
                />

                <div className="flex-row">
                    <SchemaIconButton
                        onClick={() => setIsExpanded(!isExpanded)}
                        icon={isExpanded ? 'ChevronDown' : 'ChevronRight'}
                    />
                </div>
            </StyledItem>

            {isExpanded && (
                <div className="board-scroll-wrapper">
                    {total === 0 ? (
                        <div className="empty-section-message">
                            No tables in {name}
                        </div>
                    ) : (
                        <InfinityScroll
                            elements={data}
                            onLoadMore={onLoadMore}
                            hasMore={!total || total > data.length}
                            itemRenderer={tableRowRenderer}
                            itemHeight={TABLE_ITEM_HEIGHT}
                            defaultListHeight={calculateMaxHeight(total)}
                            autoSizerStyles={{
                                height: `${calculateMaxHeight(total)}px`,
                            }}
                        />
                    )}
                </div>
            )}
        </div>
    );
}
Example #17
Source File: pricecheck.ts    From o7 with MIT License 4 votes vote down vote up
command: CommandDef = {
  name: 'price check',
  alias: ['pricecheck', 'pc', 'price', 'value', 'market'],
  args: [{
    name: 'itemName',
    type: 'content',
  }],
  help: {
    description: 'This command will return market price data which is queried from <https://eve-echoes-market.com>.',
    examples: [{
      args: 'caracal navy',
      description: 'Get the price details for a Caracal Navy Issue.',
    },{
      args: 'minerals',
      description: 'Get the prices of all minerals',
    },{
      args: 'ore',
      description: 'Get the prices of all ore.',
    },{
      args: 'planetary',
      description: 'Get the prices of all planetary resources.'
    }],
  },
  handler: async (message: Message, args: { itemName: string; }) => {

    if (customKeywords[args.itemName]) {
      const special = customKeywords[args.itemName];
      let embed = new MessageEmbed()
        .setTitle(`${startCase(special.title)} Prices`);
      let counter = 0;
      for (const key of special.keys) {
        const specialItem = await getMarketData(key);
        if (specialItem) {
          const itemInfo = items[specialItem.id];
          const price = getLatestValidPrice(specialItem);
          if (price) {
            embed.addField(itemInfo.name, `**B** ${numeral(price.buy).format('0[.]0a') || '__'} *ISK*\n**S** ${numeral(price.sell).format('0[.]0a') || '__'} *ISK*\n**V** ${numeral(price.volume).format('0,0') || 0}\n`, true)
          } else {
            embed.addField(startCase(key), 'unknown', true);
          }
        } else {
          embed.addField(startCase(key), 'unknown', true);
        }
        if (++counter === 24) {
          message.channel.send(embed);
          embed = new MessageEmbed();
        }
      }
      if (counter > 0) {
        message.channel.send(embed);
      }
      return;
    }
    
    try {
      const item = await getMarketData(args.itemName);
      if (!item) {
        message.channel.send(`I'm sorry, I wasn't able to find anything for those search terms.`);
        return;
      }

      const itemInfo = items[item.id];
      const price = getLatestValidPrice(item);
      if (!price) {
        message.channel.send(`I'm sorry, I wasn't able to find any prices for ${itemInfo.name}.`);
        return;
      }

      message.channel.send(new MessageEmbed()
          .setTitle(itemInfo.name)
          .setThumbnail(`https://storage.googleapis.com/o7-store/icons/${itemInfo.icon_id}.png`)
          .setDescription(`\
**Buy Order** ${numeral(price.buy).format('0[.]0a')}
**Sell Order** ${numeral(price.sell).format('0[.]0a')}
**Volume** ${price.volume || 0}
_last updated ${moment(price.time * 1000).fromNow()}_`)
        );

    } catch (err) {
      message.channel.send(`Oh No! Something went wrong and I was unable to get market data for that item.`);
    }
  }
}
Example #18
Source File: StructuredMetadataTable.test.tsx    From backstage with Apache License 2.0 4 votes vote down vote up
describe('<StructuredMetadataTable />', () => {
  it('renders without exploding', () => {
    const metadata = { hello: 'world' };
    const { getByText } = render(
      <StructuredMetadataTable metadata={metadata} />,
    );
    expect(getByText(metadata.hello)).toBeInTheDocument();
  });

  describe('Item Mappings', () => {
    it('Iterates over and displays every field in the map', () => {
      const metadata = {
        field1: 'one',
        field2: 'two',
        field3: 'three',
      } as const;
      const { getByText } = render(
        <StructuredMetadataTable metadata={metadata} />,
      );
      for (const [key, value] of Object.entries(metadata)) {
        expect(getByText(startCase(key))).toBeInTheDocument();
        expect(getByText(value)).toBeInTheDocument();
      }
    });

    it('Supports primitive value fields', () => {
      const metadata = { strField: 'my field', intField: 1 } as const;
      const { getByText } = render(
        <StructuredMetadataTable metadata={metadata} />,
      );

      for (const [key, value] of Object.entries(metadata)) {
        expect(getByText(startCase(key))).toBeInTheDocument();
        expect(getByText(value.toString())).toBeInTheDocument();
      }
    });

    it('Supports array fields', () => {
      const metadata = { arrayField: ['arrVal1', 'arrVal2'] } as const;
      const { getByText } = render(
        <StructuredMetadataTable metadata={metadata} />,
      );
      const keys = Object.keys(metadata);
      keys.forEach(value => {
        expect(getByText(startCase(value))).toBeInTheDocument();
      });
      metadata.arrayField.forEach(value => {
        expect(getByText(value)).toBeInTheDocument();
      });
    });

    it('Supports boolean values', () => {
      const metadata = { foo: true, bar: false };
      const expectedValues = [
        ['Foo', '✅'],
        ['Bar', '❌'],
      ];

      const { getAllByRole } = render(
        <StructuredMetadataTable metadata={metadata} />,
      );

      getAllByRole('row').forEach((row, index) => {
        const [firstCell, secondCell] = within(row).getAllByRole('cell');
        const [expectedKey, expectedValue] = expectedValues[index];

        expect(firstCell).toHaveTextContent(expectedKey);
        expect(secondCell).toHaveTextContent(expectedValue);
      });
    });

    it('Supports react elements', () => {
      const metadata = { react: <div id="findMe"> field </div> };
      const { getByText } = render(
        <StructuredMetadataTable metadata={metadata} />,
      );

      expect(getByText('field')).toBeInTheDocument();
    });

    it('Supports object elements', () => {
      const metadata = {
        config: { a: 1, b: 2 },
      } as const;
      const { getByText } = render(
        <StructuredMetadataTable metadata={metadata} />,
      );

      for (const [key, value] of Object.entries(metadata.config)) {
        expect(getByText(startCase(key), { exact: false })).toBeInTheDocument();
        expect(
          getByText(value.toString(), { exact: false }),
        ).toBeInTheDocument();
      }
    });
  });
});
Example #19
Source File: SubmissionForm.tsx    From fishbowl with MIT License 4 votes vote down vote up
function SubmissionForm(props: { onSubmit: () => void }) {
  const { t } = useTranslation()
  const currentPlayer = React.useContext(CurrentPlayerContext)
  const currentGame = React.useContext(CurrentGameContext)
  const [submitCards, { called }] = useSubmitCardsMutation()

  const numSubmitted = filter(
    currentGame.cards,
    (card) => card.player_id === currentPlayer.id
  ).length

  const numToSubmit =
    (currentGame.num_entries_per_player &&
      currentGame.num_entries_per_player - numSubmitted) ||
    0

  const [words, setWords] = React.useState<Array<string>>(
    Array.from(
      {
        length: numToSubmit,
      },
      () => ""
    )
  )

  React.useEffect(() => {
    setWords(
      Array.from(
        {
          length: numToSubmit,
        },
        () => ""
      )
    )
  }, [numToSubmit])

  const emptyWords = words.some((word) => word.length < 1)

  return (
    <>
      <Grid item>
        <Title
          text={t("cardSubmission.title", "Submit {{ count }} card", {
            count: numToSubmit,
            defaultValue_plural: "Submit {{ count }} cards",
          })}
        />
      </Grid>

      <Grid item>
        {t(
          "cardSubmission.description",
          'These cards will be put into the "fishbowl," and drawn randomly in rounds of {{ rounds }}. They can be words, familiar phrases, or inside jokes!',
          {
            rounds: currentGame.rounds
              .map((round) => startCase(round.value))
              .join(", "),
          }
        )}
      </Grid>

      {currentGame.starting_letter && (
        <Grid item>
          <Trans t={t} i18nKey="cardSubmission.descriptionLetter">
            {"They must start with the letter "}
            <b>{{ letter: currentGame.starting_letter.toLocaleUpperCase() }}</b>
            .
          </Trans>
        </Grid>
      )}

      <Grid item container direction="column" spacing={2} alignItems="center">
        {words.map((_, index) => {
          return (
            <Grid item key={index}>
              <SubmissionCard
                onChange={(value: string) => {
                  const newWords = cloneDeep(words)
                  newWords[index] = value
                  setWords(newWords)
                }}
                word={words[index]}
              />
            </Grid>
          )
        })}
      </Grid>

      <Grid item>
        <Button
          variant="contained"
          color="primary"
          size="large"
          disabled={called || emptyWords}
          onClick={async () => {
            await submitCards({
              variables: {
                cards: words.map((word) => {
                  return {
                    player_id: currentPlayer.id,
                    game_id: currentGame.id,
                    word: word,
                  }
                }),
              },
            })
            props.onSubmit()
          }}
        >
          {t("cardSubmission.submitButton", "Submit")}
        </Button>
      </Grid>
    </>
  )
}
Example #20
Source File: HistoryTable.tsx    From aqualink-app with MIT License 4 votes vote down vote up
HistoryTable = ({ site, uploadHistory, onDelete }: HistoryTableProps) => {
  const nUploads = uploadHistory.length;
  const classes = useStyles();
  const { timezone } = site;
  const timezoneAbbreviation = timezone
    ? moment().tz(timezone).zoneAbbr()
    : undefined;
  const dateFormat = "MM/DD/YYYY";

  const dataVisualizationButtonLink = (
    start: string,
    end: string,
    surveyPoint: number
  ) =>
    `/sites/${site.id}${requests.generateUrlQueryParams({
      start,
      end,
      surveyPoint,
    })}`;

  if (nUploads === 0) {
    return null;
  }

  return (
    <div className={classes.root}>
      <div>
        <Typography variant="h6" gutterBottom>
          {nUploads} {pluralize(nUploads, "file")} previously uploaded
        </Typography>
      </div>
      <TableContainer>
        <Table className={classes.table}>
          <TableHead>
            <TableRow>
              {tableHeaderTitles.map((title) => (
                <TableCell key={title} className={classes.headCell}>
                  <Typography {...tableCellTypographyProps}>{title}</Typography>
                </TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {uploadHistory.map(
              ({
                id,
                file,
                surveyPoint,
                sensorType,
                minDate,
                maxDate,
                createdAt,
              }) => {
                const row = [
                  file,
                  timezoneAbbreviation || timezone,
                  site.name,
                  surveyPoint.name,
                  startCase(sensorType),
                  moment(createdAt).format(dateFormat),
                ];
                return (
                  <TableRow key={id}>
                    {row.map((item) => (
                      <TableCell>
                        <Typography {...tableCellTypographyProps}>
                          {item}
                        </Typography>
                      </TableCell>
                    ))}
                    <TableCell>
                      <Button
                        component={Link}
                        to={dataVisualizationButtonLink(
                          minDate,
                          maxDate,
                          surveyPoint.id
                        )}
                        size="small"
                        variant="outlined"
                        color="primary"
                        className={classes.dateIntervalButton}
                      >
                        {moment(minDate).format(dateFormat)} -{" "}
                        {moment(maxDate).format(dateFormat)}
                      </Button>
                    </TableCell>
                    <TableCell>
                      <DeleteButton
                        onConfirm={() => onDelete([id])}
                        content={
                          <Typography color="textSecondary">
                            Are you sure you want to delete file &quot;
                            <span className={classes.bold}>{file}</span>&quot;?
                            Data between dates{" "}
                            <span className={classes.bold}>
                              {moment(minDate).format("MM/DD/YYYY HH:mm")}
                            </span>{" "}
                            and{" "}
                            <span className={classes.bold}>
                              {moment(maxDate).format("MM/DD/YYYY HH:mm")}
                            </span>{" "}
                            will be lost.
                          </Typography>
                        }
                      />
                    </TableCell>
                  </TableRow>
                );
              }
            )}
          </TableBody>
        </Table>
      </TableContainer>
    </div>
  );
}
Example #21
Source File: parse.ts    From tribeca-registry with Apache License 2.0 4 votes vote down vote up
parseGovernorConfig = async (
  raw: GovernorConfigRaw,
  cluster: Cluster
): Promise<GovernorConfig> => {
  const governance = await parseGovernance({
    ...raw.governance,
    network: cluster,
  });
  const quarry = raw.quarry ? parseQuarry(raw.quarry) : undefined;
  const mndeNftLocker = raw["mnde-nft-locker"]
    ? parseMndeNftLocker(raw["mnde-nft-locker"])
    : undefined;
  const nftLockerGauges = raw["nft-locker-gauges"]
    ? raw["nft-locker-gauges"].map((rawGaugeType) =>
        parseNftLockerGauges(rawGaugeType)
      )
    : undefined;

  return {
    slug: governance.slug,
    name: governance.name,
    description: governance.description,
    address: new PublicKey(governance.address),
    govToken: governance.token,
    iconURL: governance.iconURL,

    governance,
    proposals: raw.proposals,
    quarry,
    saves: raw.saves ? raw.saves.map(parseSAVE) : undefined,
    minter: quarry
      ? {
          mintWrapper: quarry?.mintWrapper,
          redeemer: quarry?.redeemer,
        }
      : undefined,
    gauge: quarry?.gauge
      ? {
          gaugemeister: quarry.gauge.gaugemeister,
          hidden: quarry.gauge.hidden,
        }
      : undefined,
    mndeNftLocker,
    nftLockerGauges,
    links: raw.links
      ? mapValues(raw.links, (link, key) => {
          if (typeof link === "string") {
            return {
              label: startCase(key),
              url: link,
            };
          }
          return link;
        })
      : undefined,
    addresses: raw.addresses
      ? mapValues(raw.addresses, (address, key) => {
          if (typeof address === "string") {
            return {
              label: startCase(key),
              address: new PublicKey(address),
            };
          }
          const {
            ["description-link"]: descriptionLink,
            type,
            ...addressProps
          } = address;
          if (type && !ADDRESS_TYPES.includes(type)) {
            throw new Error(
              `invalid type ${type} for address ${address.address}`
            );
          }
          return {
            ...addressProps,
            type: type as AddressType,
            descriptionLink,
            address: new PublicKey(address.address),
          };
        })
      : undefined,
  };
}