lodash#capitalize TypeScript Examples

The following examples show how to use lodash#capitalize. 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.tsx    From backstage with Apache License 2.0 7 votes vote down vote up
export function tooltipValueFormatter(durationOrCount: number, name: string) {
  return [
    <span style={infoText}>
      {capitalize(name)}:{' '}
      {name.endsWith(' count')
        ? durationOrCount
        : formatDuration(durationOrCount)}
    </span>,
    null,
  ];
}
Example #2
Source File: index.ts    From json-schema-yup-transform with MIT License 6 votes vote down vote up
createNotSchema = (
  [key, value]: [string, NotSchema],
  jsonSchema: JSONSchema
): Yup.MixedSchema<string> => {
  const label = value.title || capitalize(key);
  const message = getErrorMessage(value.description, CompositSchemaTypes.NOT, [key, { title: value.title }]) || `${label} matches alternatives`;
  const schema = createValidationSchema(
    [key, value.not as JSONSchema],
    jsonSchema
  );

  return Yup.mixed().test("not-schema", message, function (current) {
    return schema.isValidSync(current, this.options) === false;
  });
}
Example #3
Source File: nav-bar.tsx    From homebridge-zigbee-nt with Apache License 2.0 6 votes vote down vote up
CONFIGURED_PAGES = [
  {
    label: capitalize(Page.HOME),
    value: Page.HOME,
  },
  {
    label: capitalize(Page.DEVICES),
    value: Page.DEVICES,
  },
  {
    label: capitalize(Page.COORDINATOR),
    value: Page.COORDINATOR,
  },
]
Example #4
Source File: index.tsx    From admin with MIT License 6 votes vote down vote up
TableViewHeader: React.FC<TableViewHeaderProps> = ({
  views,
  activeView = views[0],
  setActiveView,
}) => {
  return (
    <div className="flex inter-large-semibold gap-x-base text-grey-40">
      {views.map((k, i) => (
        <div
          key={i}
          className={clsx("cursor-pointer", {
            ["text-grey-90"]: k === activeView,
          })}
          onClick={() => {
            if (setActiveView) {
              setActiveView(k)
            }
          }}
        >
          {capitalize(k)}
        </div>
      ))}
    </div>
  )
}
Example #5
Source File: index.stories.tsx    From pancake-toolkit with GNU General Public License v3.0 6 votes vote down vote up
Default: React.FC = () => {
  return (
    <>
      <Box mb="32px">
        <button type="button">Unstyled Button</button>
      </Box>
      <Box mb="32px">
        {Object.values(variants).map((variant) => {
          return (
            <Box key={variant} mb="32px">
              {Object.values(scales).map((scale) => {
                return (
                  <Button key={scale} variant={variant} scale={scale} mr="8px">
                    {`${capitalize(variant)} ${scale.toUpperCase()}`}
                  </Button>
                );
              })}
            </Box>
          );
        })}
      </Box>
      <Box>
        <Button mr="8px" disabled>
          Disabled
        </Button>
        <Button variant="secondary" disabled>
          Disabled
        </Button>
      </Box>
    </>
  );
}
Example #6
Source File: OrderByButton.tsx    From querybook with Apache License 2.0 6 votes vote down vote up
OrderByButton: React.FC<ISortButtonProps> = ({
    asc,
    orderByField,
    orderByFieldSymbol,
    className,

    onOrderByFieldToggle = NOOP,
    onAscToggle = NOOP,
}) => {
    const buttonSymbol = useMemo(
        () => orderByFieldSymbol ?? capitalize(orderByField.slice(0, 2)),
        [orderByField, orderByFieldSymbol]
    );

    return (
        <span className={clsx('OrderByButton', className)}>
            <TextToggleButton
                value={false}
                onChange={onAscToggle}
                tooltip={asc ? 'Ascending' : 'Descending'}
                tooltipPos="left"
                text={asc ? '↑' : '↓'}
            />
            <TextToggleButton
                value={false}
                onChange={onOrderByFieldToggle}
                tooltip={`Order by ${orderByField}`}
                tooltipPos="left"
                text={buttonSymbol}
            />
        </span>
    );
}
Example #7
Source File: EntityListDocsTable.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
EntityListDocsTable = (props: EntityListDocsTableProps) => {
  const { columns, actions } = props;
  const { loading, error, entities, filters } = useEntityList();
  const { isStarredEntity, toggleStarredEntity } = useStarredEntities();
  const [, copyToClipboard] = useCopyToClipboard();

  const title = capitalize(filters.user?.value ?? 'all');

  const defaultActions = [
    actionFactories.createCopyDocsUrlAction(copyToClipboard),
    actionFactories.createStarEntityAction(
      isStarredEntity,
      toggleStarredEntity,
    ),
  ];

  if (error) {
    return (
      <WarningPanel
        severity="error"
        title="Could not load available documentation."
      >
        <CodeSnippet language="text" text={error.toString()} />
      </WarningPanel>
    );
  }

  return (
    <DocsTable
      title={title}
      entities={entities}
      loading={loading}
      actions={actions || defaultActions}
      columns={columns}
    />
  );
}
Example #8
Source File: index.ts    From json-schema-yup-transform with MIT License 6 votes vote down vote up
createAnyOfSchema = (
  [key, value]: [string, AnyOfSchema],
  jsonSchema: JSONSchema
): Yup.MixedSchema<string> => {
  const label = value.title || capitalize(key);
  const message = getErrorMessage(value.description, CompositSchemaTypes.ANYOF, [key, { title: value.title }]) || `${label} does not match alternatives`;
  const schemas = value.anyOf.map((val) =>
    createValidationSchema([key, val as JSONSchema], jsonSchema)
  );

  return Yup.mixed().test("one-of-schema", message, function (current) {
    return schemas.some((s) => s.isValidSync(current, this.options));
  });
}
Example #9
Source File: index.stories.tsx    From vvs-ui with GNU General Public License v3.0 6 votes vote down vote up
Default: React.FC = () => {
  return (
    <>
      <Box mb="32px">
        <button type="button">Unstyled Button</button>
      </Box>
      <Box mb="32px">
        {Object.values(variants).map((variant) => {
          return (
            <Box key={variant} mb="32px">
              {Object.values(scales).map((scale) => {
                return (
                  <Button key={scale} variant={variant} scale={scale} mr="8px">
                    {`${capitalize(variant)} ${scale.toUpperCase()}`}
                  </Button>
                );
              })}
            </Box>
          );
        })}
      </Box>
      <Box>
        <Button mr="8px" disabled>
          Disabled
        </Button>
        <Button variant="secondary" disabled>
          Disabled
        </Button>
      </Box>
    </>
  );
}
Example #10
Source File: RoundSettings.tsx    From fishbowl with MIT License 6 votes vote down vote up
function RoundSettings() {
  const currentGame = React.useContext(CurrentGameContext)

  return (
    <RoundSettingsList>
      {currentGame.rounds.map((round, index) => {
        return (
          <ListItem key={round.id}>
            <ListItemText>
              <Box pl={2}>
                {index + 1}. {capitalize(round.value)}
              </Box>
            </ListItemText>
          </ListItem>
        )
      })}
    </RoundSettingsList>
  )
}
Example #11
Source File: index.stories.tsx    From vvs-ui with GNU General Public License v3.0 6 votes vote down vote up
Default: React.FC = () => {
  const [progress, setProgress] = useState(random(1, 100));

  const handleClick = () => setProgress(random(1, 100));

  return (
    <div style={{ padding: "32px", width: "400px" }}>
      {Object.values(variants).map((variant) => {
        return (
          <Box key={variant} mb="16px">
            <Heading size="md" mb="8px">
              {capitalize(variant)}
            </Heading>
            <Progress variant={variant} primaryStep={progress} />
          </Box>
        );
      })}
      <Heading size="md" mb="8px">
        Small
      </Heading>
      <Progress scale="sm" primaryStep={progress} />
      <div style={{ marginTop: "32px" }}>
        <Button type="button" scale="sm" onClick={handleClick}>
          Random Progress
        </Button>
      </div>
    </div>
  );
}
Example #12
Source File: GroupCompetition.ts    From discord-bot with MIT License 6 votes vote down vote up
buildContent(competition: Competition) {
    const isTeamCompetition = competition.type === 'team';

    const lines = [
      `**Metric:**: ${getEmoji(competition.metric)} ${getMetricName(competition.metric)}`,
      `**Type:**: ${capitalize(competition.type)}`,
      `**Participants:** ${competition.participants.length}`,
      `**Duration:** ${competition.duration}`,
      `**Total gained:** ${toKMB(competition.totalGained || 0)}`,
      ''
    ];

    if (isTeamCompetition) {
      lines.push('**Teams:**');
      lines.push(...this.getTeamData(competition));
    } else {
      lines.push('**Top Participants:**');
      lines.push(...this.getParticipantData(competition));
    }

    return lines.join('\n');
  }
Example #13
Source File: AnalysisDisplay.tsx    From abacus with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Displays the Analysis decision.
 */
export default function AnalysisDisplay({
  analysis,
  experiment,
}: {
  analysis: Recommendation
  experiment: ExperimentFull
}): JSX.Element {
  const decorationClasses = useDecorationStyles()
  switch (analysis.decision) {
    case Decision.ManualAnalysisRequired:
      return (
        <Tooltip title='Contact @experimentation-review on #a8c-experiments'>
          <span className={decorationClasses.tooltipped}>Manual analysis required</span>
        </Tooltip>
      )
    case Decision.MissingAnalysis:
      return <>Not analyzed yet</>
    case Decision.Inconclusive:
      return <>Inconclusive</>
    case Decision.NoDifference:
      return <>No difference</>
    case Decision.VariantBarelyAhead: {
      return <>{capitalize(getChosenVariation(experiment, analysis)?.name)} barely ahead</>
    }
    case Decision.VariantAhead: {
      return <>{capitalize(getChosenVariation(experiment, analysis)?.name)} ahead</>
    }
    case Decision.VariantWins: {
      return <>{capitalize(getChosenVariation(experiment, analysis)?.name)} wins</>
    }
    default:
      throw new Error('Missing Decision.')
  }
}
Example #14
Source File: path.ts    From free-swagger with MIT License 5 votes vote down vote up
createDefaultApiName = (url: string, method: Method): string => {
  return `${camelcase(last(url.split('/')) ?? '')}By${capitalize(method)}`
}
Example #15
Source File: metrics.ts    From wise-old-man with MIT License 5 votes vote down vote up
function getMetricValueKey(metric: Metric) {
  return `${metric}${capitalize(MetricProps[metric].measure)}`;
}
Example #16
Source File: use-grid-columns.tsx    From admin with MIT License 5 votes vote down vote up
useGridColumns = (product, isEditing) => {
  const defaultFields = [
    { header: "Title", field: "title" },
    { header: "SKU", field: "sku" },
    { header: "EAN", field: "ean" },
    { header: "Inventory", field: "inventory_quantity" },
  ]

  if (isEditing) {
    const optionColumns = product.options.map((o) => ({
      header: o.title,
      field: "options",
      formatter: (variantOptions) => {
        const displayVal = variantOptions.find((val) => val.option_id === o.id)
        return displayVal?.value || " - "
      },
    }))

    return [
      ...optionColumns,
      {
        header: "Prices",
        field: "prices",
        formatter: (prices) => `${prices.length} price(s)`,
      },
      ...defaultFields,
    ]
  } else {
    return [
      {
        header: "Variant",
        field: "options",
        formatter: (value) => {
          const options = value.map((v) => {
            if (v.value) {
              return capitalize(v.value)
            }
            return capitalize(v)
          })

          return options.join(" / ")
        },
        readOnly: true,
        headCol: true,
      },
      ...defaultFields,
    ]
  }
}
Example #17
Source File: model-factory.ts    From ts-japi with Apache License 2.0 5 votes vote down vote up
ModelFactory = {
 addArrayAttribute<T extends typeof Base, U extends typeof Base>(
  name: string,
  target: T,
  source: U
 ) {
  const getterName = `get${capitalize(camelCase(name))}`;
  target.afterRemoveHook = target.afterRemoveHook ?? [];
  target.beforeSaveHook = target.beforeSaveHook ?? [];
  target.prototype = target.prototype ?? ({} as any);
  (target.prototype as any)[getterName] = function <Target>(this: Target) {
   return findAllExisting((this as any)[name], (id: string) => source.find(id));
  };
  target.afterRemoveHook.push(<Target, Source extends Base>(model: Target) => {
   (model as any)[getterName]().map((m: Source) => source.remove(m));
  });
  target.beforeSaveHook.push(<Target>(model: Target) => {
   findAllExisting((model as any)[name], (id: string) => source.find(id));
  });
 },
 addSingleAttribute<T extends typeof Base, U extends typeof Base>(
  name: string,
  othername: string,
  target: T,
  source: U
 ) {
  const getterName = `get${capitalize(camelCase(name))}`;
  target.beforeSaveHook = target.beforeSaveHook ?? [];
  target.prototype = target.prototype ?? ({} as any);
  (target.prototype as any)[getterName] = function <Target>(this: Target) {
   return source.find((this as any)[name]);
  };
  target.beforeSaveHook.push(<Target extends Base>(model: Target) => {
   const sourceModel = (model as any)[getterName]();
   if (!sourceModel) throw new Error(`no ${name}`);
   pushIfNotExists(sourceModel[othername], model.id, (id) => id === model.id);
  });
 },
 createModel<T extends typeof Base>(model: T) {
  model.storage = [];
  model.find = function (this: T, id: string) {
   if (this.beforeFindHook) this.beforeFindHook.forEach((hook) => hook(id));
   const result = this.storage.find((u) => u.id === id);
   if (this.afterFindHook) this.afterFindHook.forEach((hook) => hook(id));
   return result;
  };
  model.remove = function <U extends Base>(this: T, obj: U) {
   if (this.beforeRemoveHook) this.beforeRemoveHook.forEach((hook) => hook(obj));
   let idx = this.storage.findIndex((u) => u.id === obj.id);
   if (typeof idx === "number") {
    delete this.storage[idx];
   }
   if (this.afterRemoveHook) this.afterRemoveHook.forEach((hook) => hook(obj));
   return obj;
  };
  model.save = function <U extends Base>(this: T, model: U) {
   if (this.beforeSaveHook) this.beforeSaveHook.forEach((hook) => hook(model));
   pushIfNotExists(this.storage, model, (m) => m.id === model.id);
   if (this.afterSaveHook) this.afterSaveHook.forEach((hook) => hook(model));
   return model;
  };
 },
}
Example #18
Source File: emails.ts    From commonwealth with GNU General Public License v3.0 5 votes vote down vote up
createImmediateNotificationEmailObject = async (notification_data, category_id, models) => {
  if (notification_data.chainEvent && notification_data.chainEventType) {
    // construct compatible CW event from DB by inserting network from type
    const evt: CWEvent = {
      blockNumber: notification_data.chainEvent.block_number,
      data: notification_data.chainEvent.event_data as IChainEventData,
      network: notification_data.chainEventType.event_network as SupportedNetwork,
    };

    try {
      const chainEventLabel = ChainEventLabel(notification_data.chainEventType.chain, evt);
      if (!chainEventLabel) return;

      const subject = `${process.env.NODE_ENV !== 'production' ? '[dev] ' : ''
        }${chainEventLabel.heading} event on ${capitalize(notification_data.chainEventType.chain)}`;

      return {
        from: 'Commonwealth <[email protected]>',
        to: null,
        bcc: null,
        subject,
        templateId: DynamicTemplate.ImmediateEmailNotification,
        dynamic_template_data: {
          notification: {
            chainId: notification_data.chainEventType.chain,
            blockNumber: notification_data.chainEvent.blockNumber,
            subject,
            label: subject,
            path: null,
          }
        }
      };
    } catch (err) {
      console.error(`Failed to label chain event: ${err.message}`);
    }
  } else if (category_id !== NotificationCategories.NewReaction && category_id !== NotificationCategories.ThreadEdit) {
    const [
      emailSubjectLine, subjectCopy, actionCopy, objectCopy, communityCopy, excerpt, proposalPath, authorPath
    ] = await getForumNotificationCopy(models, notification_data as IPostNotificationData, category_id);
    return {
      from: 'Commonwealth <[email protected]>',
      to: null,
      bcc: null,
      subject: (process.env.NODE_ENV !== 'production' ? '[dev] ' : '') + emailSubjectLine,
      templateId: DynamicTemplate.ImmediateEmailNotification,
      dynamic_template_data: {
        notification: {
          subject: emailSubjectLine,
          author: subjectCopy,
          action: actionCopy,
          rootObject: objectCopy,
          community: communityCopy,
          excerpt,
          proposalPath,
          authorPath,
        }
      }
    };
  }
}
Example #19
Source File: index.ts    From context-mod with MIT License 5 votes vote down vote up
getActionUniqueName() {
        return this.name === this.getKind() ? capitalize(this.getKind()) : `${capitalize(this.getKind())} - ${this.name}`;
    }
Example #20
Source File: index.tsx    From strapi-plugin-comments with MIT License 5 votes vote down vote up
DetailsEntity = ({
  data = {},
  schema = {},
  config = {},
  filters,
  onFiltersChange,
}) => {
  const { entryLabel = {} } = config;
  const { attributes = {} } = schema;
  const keys = Object.keys(attributes);
  const entityLabelKey = first(entryLabel[data?.uid]);

  const FIELDS_LIMIT = 5;
  const itemKeys = take(
    keys.filter(
      (_) =>
        attributes[_].type === "string" &&
        !isNil(data[_]) &&
        _ !== entityLabelKey
    ),
    FIELDS_LIMIT
  );

  const formatLabel = (label = "") =>
    label
      .split("_")
      .map((_) => capitalize(_))
      .join(" ");

  const entityIsRenderable =
    data && !isEmpty(data) && (!isEmpty(itemKeys) || data[entityLabelKey]);

  return (
    <Box padding={4}>
      {entityIsRenderable && (
        <Box marginBottom={4}>
          <Typography
            variant="sigma"
            textColor="neutral600"
            id="entity-details"
          >
            {getMessage("page.details.panel.entity", "Details")}
          </Typography>
          <Box paddingTop={2} paddingBottom={4}>
            <Divider />
          </Box>
          <Stack size={itemKeys.length}>
            <Flex direction="column" alignItems="flex-start">
              <Typography fontWeight="bold">
                {formatLabel(entityLabelKey)}
              </Typography>
              <Typography>{data[entityLabelKey]}</Typography>
            </Flex>
            {itemKeys.map((_) => (
              <Flex
                key={`prop_${_}`}
                direction="column"
                alignItems="flex-start"
              >
                <Typography fontWeight="bold">{formatLabel(_)}</Typography>
                <Typography>{data[_]}</Typography>
              </Flex>
            ))}
          </Stack>
        </Box>
      )}
      <Box>
        <Typography variant="sigma" textColor="neutral600" id="view-filters">
          {getMessage("page.details.filters.label", "View")}
        </Typography>
        <Box paddingTop={2} paddingBottom={4}>
          <Divider />
        </Box>
        <DetailsFilters data={filters} onChange={onFiltersChange} />
      </Box>
    </Box>
  );
}
Example #21
Source File: TemplateTypePicker.test.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
describe('<TemplateTypePicker/>', () => {
  it('renders available entity types', async () => {
    const rendered = await renderWithEffects(
      <ApiProvider apis={apis}>
        <MockEntityListContextProvider
          value={{
            filters: { kind: new EntityKindFilter('template') },
            backendEntities: entities,
          }}
        >
          <TemplateTypePicker />
        </MockEntityListContextProvider>
      </ApiProvider>,
    );
    expect(rendered.getByText('Categories')).toBeInTheDocument();
    fireEvent.click(rendered.getByTestId('categories-picker-expand'));

    entities.forEach(entity => {
      expect(
        rendered.getByLabelText(capitalize(entity.spec!.type as string)),
      ).toBeInTheDocument();
    });
  });

  it('sets the selected type filters', async () => {
    const rendered = await renderWithEffects(
      <ApiProvider apis={apis}>
        <MockEntityListContextProvider
          value={{
            filters: { kind: new EntityKindFilter('template') },
            backendEntities: entities,
          }}
        >
          <TemplateTypePicker />
        </MockEntityListContextProvider>
      </ApiProvider>,
    );

    fireEvent.click(rendered.getByTestId('categories-picker-expand'));
    expect(rendered.getByLabelText('Service')).not.toBeChecked();
    expect(rendered.getByLabelText('Website')).not.toBeChecked();

    fireEvent.click(rendered.getByLabelText('Service'));
    fireEvent.click(rendered.getByTestId('categories-picker-expand'));
    expect(rendered.getByLabelText('Service')).toBeChecked();
    expect(rendered.getByLabelText('Website')).not.toBeChecked();

    fireEvent.click(rendered.getByLabelText('Website'));
    fireEvent.click(rendered.getByTestId('categories-picker-expand'));
    expect(rendered.getByLabelText('Service')).toBeChecked();
    expect(rendered.getByLabelText('Website')).toBeChecked();

    fireEvent.click(rendered.getByLabelText('Service'));
    fireEvent.click(rendered.getByTestId('categories-picker-expand'));
    expect(rendered.getByLabelText('Service')).not.toBeChecked();
    expect(rendered.getByLabelText('Website')).toBeChecked();

    fireEvent.click(rendered.getByLabelText('Website'));
    fireEvent.click(rendered.getByTestId('categories-picker-expand'));
    expect(rendered.getByLabelText('Service')).not.toBeChecked();
    expect(rendered.getByLabelText('Website')).not.toBeChecked();
  });
});
Example #22
Source File: common.tsx    From reddium with MIT License 5 votes vote down vote up
unsplashCredits = (filename: string) =>
  capitalize(filename.split("-").slice(0, -2).join(" "))
Example #23
Source File: my-reports.page.ts    From fyle-mobile-app with MIT License 5 votes vote down vote up
async onDeleteReportClick(erpt: ExtendedReport) {
    if (['DRAFT', 'APPROVER_PENDING', 'APPROVER_INQUIRY'].indexOf(erpt.rp_state) === -1) {
      const cannotDeleteReportPopOver = await this.popoverController.create({
        component: PopupAlertComponentComponent,
        componentProps: {
          title: 'Cannot Delete Report',
          message: `${capitalize(replace(erpt.rp_state, '_', ' '))} report cannot be deleted.`,
          primaryCta: {
            text: 'Close',
            action: 'continue',
          },
        },
        cssClass: 'pop-up-in-center',
      });

      await cannotDeleteReportPopOver.present();
    } else {
      const deleteReportPopover = await this.popoverController.create({
        component: FyDeleteDialogComponent,
        cssClass: 'delete-dialog',
        backdropDismiss: false,
        componentProps: {
          header: 'Delete Report',
          body: 'Are you sure you want to delete this report?',
          infoMessage: 'Deleting the report will not delete any of the expenses.',
          deleteMethod: () => this.reportService.delete(erpt.rp_id),
        },
      });

      await deleteReportPopover.present();
      const { data } = await deleteReportPopover.onDidDismiss();

      if (data && data.status === 'success') {
        from(this.loaderService.showLoader())
          .pipe(
            tap(() => this.trackingService.deleteReport()),
            finalize(async () => {
              await this.loaderService.hideLoader();
              this.doRefresh();
            })
          )
          .subscribe(noop);
      }
    }
  }
Example #24
Source File: mobile_sidebar.tsx    From commonwealth with GNU General Public License v3.0 5 votes vote down vote up
view() {
    const CurrentCommunityMenu = (
      <Menu class="CurrentCommunityMenu">
        {app.isLoggedIn() ? (
          <Menu class="NewProposalMenu">
            <MenuItem
              label="Create New"
              iconLeft={Icons.PLUS}
              onclick={(e) => {
                e.stopPropagation();
                this.showNewThreadOptions = !this.showNewThreadOptions;
              }}
            />
            {this.showNewThreadOptions && (
              <NewProposalMenu candidates={[]} mobile={true} />
            )}
          </Menu>
        ) : (
          <MenuItem
            label="Login"
            iconLeft={Icons.LOG_IN}
            onclick={() => {
              app.modals.create({ modal: LoginModal });
            }}
          />
        )}
        <MenuDivider />
        {app.chain && <DiscussionSection mobile={true} />}
        {app.chain && <GovernanceSection mobile={true} />}
        {app.chain && <ChatSection mobile={true} />}
        {app.chain && <ExternalLinksModule />}
      </Menu>
    );

    return (
      <div class="MobileSidebar">
        <Tabs>
          {app.activeChainId() && (
            <TabItem
              label={capitalize(app.activeChainId())}
              active={this.activeTab === MenuTabs.CurrentCommunity}
              onclick={(e) => {
                e.stopPropagation();
                this.activeTab = MenuTabs.CurrentCommunity;
              }}
            />
          )}
          {app.activeChainId() && (
            <TabItem
              label="Communities"
              active={this.activeTab === MenuTabs.AllCommunities}
              onclick={(e) => {
                e.stopPropagation();
                this.activeTab = MenuTabs.AllCommunities;
              }}
            />
          )}
          <TabItem
            label="Account"
            active={this.activeTab === MenuTabs.Account}
            onclick={(e) => {
              e.stopPropagation();
              this.activeTab = MenuTabs.Account;
            }}
          />
        </Tabs>
        {this.activeTab === MenuTabs.CurrentCommunity ? (
          CurrentCommunityMenu
        ) : this.activeTab === MenuTabs.AllCommunities ? (
          <Menu class="AllCommunitiesMenu">
            <CommunitySelector isMobile={true} />
          </Menu>
        ) : (
          <MobileAccountMenu />
        )}
      </div>
    );
  }
Example #25
Source File: status-chart.tsx    From backstage with Apache License 2.0 4 votes vote down vote up
export function StatusChart(props: StatusChartProps) {
  const { analysis } = props;

  const { zoomFilterValues } = useZoom();
  const { zoomProps, getZoomArea } = useZoomArea();

  const values = useMemo(() => {
    return analysis.daily.values.map(value => {
      const totTriggers = analysis.daily.triggerReasons.reduce(
        (prev, cur) => prev + (value[cur as TriggerReason] ?? 0),
        0,
      );

      if (!totTriggers) {
        return value;
      }

      return {
        ...value,
        ...Object.fromEntries(
          analysis.daily.triggerReasons.map(reason => [
            reason,
            (value[reason as TriggerReason] ?? 0) / totTriggers,
          ]),
        ),
      };
    });
  }, [analysis.daily]);

  const triggerReasonLegendPayload = useMemo(
    (): NonNullable<LegendProps['payload']> =>
      analysis.daily.triggerReasons.map(reason => ({
        value: humanTriggerReason(reason),
        type: 'line',
        id: reason,
        color: triggerColorMap[reason as TriggerReason] ?? '',
      })),
    [analysis.daily.triggerReasons],
  );

  const statusesLegendPayload = useMemo(
    (): NonNullable<LegendProps['payload']> =>
      analysis.daily.statuses.map(status => ({
        value: capitalize(status),
        type: 'line',
        id: status,
        color: statusColorMap[status as FilterStatusType] ?? '',
      })),
    [analysis.daily.statuses],
  );

  const legendPayload = useMemo(
    (): NonNullable<LegendProps['payload']> => [
      ...triggerReasonLegendPayload,
      ...statusesLegendPayload,
    ],
    [statusesLegendPayload, triggerReasonLegendPayload],
  );

  const tooltipFormatter = useMemo(() => {
    const reasonSet = new Set(analysis.daily.triggerReasons);

    return (percentOrCount: number, name: string) => {
      const label = reasonSet.has(name)
        ? humanTriggerReason(name)
        : capitalize(name);
      const valueText = reasonSet.has(name)
        ? `${(percentOrCount * 100).toFixed(0)}%`
        : percentOrCount;

      return [
        <span>
          {label}: {valueText}
        </span>,
        null,
      ];
    };
  }, [analysis.daily.triggerReasons]);

  const zoomFilteredValues = useMemo(
    () => zoomFilterValues(values),
    [values, zoomFilterValues],
  );

  const barSize = getBarSize(analysis.daily.values.length);

  return (
    <Accordion defaultExpanded={analysis.daily.statuses.length > 1}>
      <AccordionSummary expandIcon={<ExpandMoreIcon />}>
        <Typography>
          Build count per status over build trigger reason
        </Typography>
      </AccordionSummary>
      <AccordionDetails>
        {values.length === 0 ? (
          <Alert severity="info">No data</Alert>
        ) : (
          <ResponsiveContainer width="100%" height={140}>
            <ComposedChart data={zoomFilteredValues} {...zoomProps}>
              <Legend payload={legendPayload} />
              <CartesianGrid strokeDasharray="3 3" />
              <XAxis
                dataKey="__epoch"
                type="category"
                tickFormatter={tickFormatterX}
              />
              <YAxis yAxisId={1} type="number" tickCount={5} name="Count" />
              <YAxis yAxisId={2} type="number" name="Triggers" hide />
              <Tooltip
                labelFormatter={labelFormatterWithoutTime}
                formatter={tooltipFormatter}
              />
              {triggerReasonLegendPayload.map(reason => (
                <Fragment key={reason.id}>
                  <Area
                    isAnimationActive={false}
                    type="monotone"
                    dataKey={reason.id!}
                    stackId="triggers"
                    yAxisId={2}
                    stroke={triggerColorMap[reason.id as TriggerReason] ?? ''}
                    fillOpacity={0.5}
                    fill={triggerColorMap[reason.id as TriggerReason] ?? ''}
                  />
                </Fragment>
              ))}
              {[...analysis.daily.statuses].reverse().map(status => (
                <Fragment key={status}>
                  <Bar
                    isAnimationActive={false}
                    type="monotone"
                    barSize={barSize}
                    dataKey={status}
                    stackId="statuses"
                    yAxisId={1}
                    stroke={statusColorMap[status as FilterStatusType] ?? ''}
                    fillOpacity={0.8}
                    fill={statusColorMap[status as FilterStatusType] ?? ''}
                  />
                </Fragment>
              ))}
              {getZoomArea({ yAxisId: 1 })}
            </ComposedChart>
          </ResponsiveContainer>
        )}
      </AccordionDetails>
    </Accordion>
  );
}
Example #26
Source File: index.tsx    From fishbowl with MIT License 4 votes vote down vote up
function Play() {
  const { t } = useTranslation()
  const titleClasses = useTitleStyle()
  const currentGame = React.useContext(CurrentGameContext)
  const currentPlayer = React.useContext(CurrentPlayerContext)

  const [startReview] = useStartReviewMutation()

  const [
    hasDismissedInstructionCard,
    setHasDismissedInstructionCard,
  ] = React.useState(false)

  const completedCardIds = flatMap(
    currentGame.turns,
    (turn) => turn.completed_card_ids
  )

  const activeTurn = last(currentGame.turns)
  const activePlayer = currentGame.players.find(
    (player) => player.id === activeTurn?.player_id
  )

  const [activeTurnPlayState, setActiveTurnPlayState] = React.useState(
    playStateFromTurn(activeTurn)
  )
  React.useEffect(() => {
    setActiveTurnPlayState(playStateFromTurn(activeTurn))
  }, [activeTurn])

  const secondsLeft = useSecondsLeft(activeTurnPlayState)

  // countdown timer
  React.useEffect(() => {
    if (
      activeTurnPlayState === ActiveTurnPlayState.Playing &&
      secondsLeft <= 0
    ) {
      setActiveTurnPlayState(ActiveTurnPlayState.Reviewing)
      if (currentPlayer.id === activeTurn?.player_id && activeTurn?.id) {
        startReview({
          variables: {
            currentTurnId: activeTurn.id,
          },
        })
      }
    }
  }, [secondsLeft]) // eslint-disable-line react-hooks/exhaustive-deps

  if (!activeTurn || !activePlayer) {
    return null
  }

  const numCompletedCards = completedCardIds.length
  const totalNumCards = currentGame.cards.length
  const numRounds = currentGame.rounds.length

  if (numCompletedCards === numRounds * totalNumCards) {
    return <NoMoreRounds />
  }

  const roundMarkers = [...Array(numRounds).keys()]
  let roundNum = Math.floor(numCompletedCards / totalNumCards)
  const currentRoundId = currentGame.rounds[roundNum].id
  const nextRoundId = currentGame.rounds[roundNum + 1]?.id

  let roundMarker = numCompletedCards / totalNumCards
  let round = ""
  if (roundMarkers.includes(roundMarker)) {
    const value = capitalize(currentGame.rounds[roundMarker].value)
    round = GameRound[value as GameRound]
    if (round) {
      round = t(`howToPlay.round.${round.toLowerCase()}.name`, round)
    } else {
      round = value
    }
  }

  const yourTurn = activePlayer.id === currentPlayer.id
  const yourTeamTurn =
    activePlayer.team ===
    currentPlayerTeam(currentPlayer.id, currentGame.players)

  let titleText = null
  let content = null
  if (yourTurn) {
    titleText = t("play.yourTurn.title", "Your Turn")
    content = (
      <YourTurnContent
        yourTeamPlayers={filter(
          currentGame.players,
          (player) => activePlayer.team === player.team
        )}
        cardsInBowl={drawableCards(currentGame.turns, currentGame.cards)}
        secondsLeft={secondsLeft}
        activePlayer={activePlayer}
        activeTurn={activeTurn}
        activeTurnPlayState={activeTurnPlayState}
        onStart={() => {
          setActiveTurnPlayState(ActiveTurnPlayState.Playing)
        }}
        onOutOfCards={() => {
          setActiveTurnPlayState(ActiveTurnPlayState.Reviewing)
          startReview({
            variables: {
              currentTurnId: activeTurn.id,
            },
          })
        }}
        currentRoundId={currentRoundId}
        nextRoundId={nextRoundId}
      />
    )
  } else if (yourTeamTurn) {
    titleText = t("play.yourTeam.title", "You're Guessin'")
    content = (
      <YourTeamTurnContent
        activePlayer={activePlayer}
        activeTurn={activeTurn}
      />
    )
  } else {
    titleText = t("play.otherTeam.title", "You're Chillin'")
    content = (
      <OtherTeamContent activePlayer={activePlayer} activeTurn={activeTurn} />
    )
  }

  return (
    <Grid container direction="column" alignItems="center" spacing={2}>
      <Grid item>
        <Typography variant="h4" className={titleClasses.title}>
          {titleText}
        </Typography>
      </Grid>
      <Grid item>
        <Divider
          variant="middle"
          style={{
            width: 150,
            height: 2,
            backgroundColor:
              TeamColor[
                currentPlayerTeam(currentPlayer.id, currentGame.players) as Team
              ] || grey[600],
          }}
        />
      </Grid>

      {round && !hasDismissedInstructionCard && (
        <Grid item>
          <Box mb={1}>
            <GameRoundInstructionCard
              round={round}
              roundNumber={Number(roundMarker + 1)}
              onDismiss={() => {
                setHasDismissedInstructionCard(true)
              }}
            />
          </Box>
        </Grid>
      )}
      <Grid item>
        <TurnContextPanel
          secondsLeft={Math.round(Math.max(secondsLeft, 0)) || 0}
        />
      </Grid>
      <Grid item>{content}</Grid>

      {currentPlayer.role === PlayerRole.Host && (
        <Grid item>
          <HostControls
            activePlayer={activePlayer}
            activeTurn={activeTurn}
            currentRoundId={currentRoundId}
          />
        </Grid>
      )}
    </Grid>
  )
}
Example #27
Source File: index.tsx    From strapi-plugin-comments with MIT License 4 votes vote down vote up
Settings = () => {
  useFocusWhenNavigate();

  const { notifyStatus } = useNotifyAT();
  const { trackUsage } = useTracking();
  const trackUsageRef = useRef(trackUsage);
  const toggleNotification = useNotification();
  const { lockApp, unlockApp } = useOverlayBlocker();

  const viewPermissions = useMemo(
    () => ({
      access: pluginPermissions.settings.read,
      change: pluginPermissions.settings.change,
    }),
    []
  );

  const {
    isLoading: isLoadingForPermissions,
    allowedActions: { canAccess, canChange },
  } = useRBAC(viewPermissions);

  const [restoreConfigmationVisible, setRestoreConfigmationVisible] =
    useState(false);
  const [restartRequired, setRestartRequired] = useState(false);
  const [contentTypeExpanded, setContentTypeExpanded] = useState(undefined);

  const { fetch, restartMutation, submitMutation, restoreMutation } =
    useConfig(toggleNotification);
  const {
    data: configData,
    isLoading: isConfigLoading,
    err: configErr,
  }: ToBeFixed = fetch;

  const {
    data: allCollectionsData,
    isLoading: areCollectionsLoading,
    err: collectionsErr,
  }: ToBeFixed = useQuery(["get-all-content-types", canAccess], () =>
    fetchAllContentTypes(toggleNotification)
  );

  const {
    data: allRolesData,
    isLoading: areRolesLoading,
    err: rolesErr,
  }: ToBeFixed = useQuery(["get-all-roles", canAccess], () =>
    fetchRoles(toggleNotification)
  );

  const isLoading =
    isLoadingForPermissions ||
    isConfigLoading ||
    areCollectionsLoading ||
    areRolesLoading;
  const isError = configErr || collectionsErr || rolesErr;

  const preparePayload = ({
    enabledCollections,
    gqlAuthEnabled,
    approvalFlow,
    entryLabel,
    clientUrl,
    clientEmail,
    ...rest
  }: ToBeFixed) => ({
    ...rest,
    enabledCollections,
    approvalFlow: approvalFlow.filter((_) => enabledCollections.includes(_)),
    entryLabel: {
      ...Object.keys(entryLabel).reduce(
        (prev, curr) => ({
          ...prev,
          [curr]: enabledCollections.includes(curr)
            ? entryLabel[curr]
            : undefined,
        }),
        {}
      ),
      "*": entryLabel["*"],
    },
    reportReasons: configData?.reportReasons,
    client: clientEmail || clientUrl ? {
      contactEmail: clientEmail,
      url: clientUrl,
    } : undefined,
    gql: gqlAuthEnabled ? { auth: true } : undefined,
  });

  if (isLoading || isError) {
    return (
      <LoadingIndicatorPage>
        {getMessage("page.settings.loading")}
      </LoadingIndicatorPage>
    );
  }

  const regexUID = !isLoading
    ? new RegExp(
        parseRegExp(fetch.data.regex?.uid).value,
        parseRegExp(fetch.data.regex?.uid).flags
      )
    : null;

  const allRoles = allRolesData?.data || [];
  const allCollections =
    !isLoading &&
    allCollectionsData.filter(
      ({ uid }: ToBeFixed) =>
        first(uid.split(regexUID).filter((s) => s && s.length > 0)) === "api"
    );
  const enabledCollections =
    configData?.enabledCollections
      ?.map((uid: ToBeFixed) =>
        allCollections.find((_) => _.uid === uid) ? uid : undefined
      )
      .filter((_: ToBeFixed) => _) || [];
  const entryLabel = configData?.entryLabel || {};
  const approvalFlow = configData?.approvalFlow || [];
  const badWords = isNil(configData?.badWords) ? true : configData?.badWords;
  const isGQLPluginEnabled = configData?.isGQLPluginEnabled;
  const gqlAuthEnabled = configData?.gql?.auth || undefined;
  const moderatorRoles =
    configData?.moderatorRoles?.filter((code: ToBeFixed) =>
      allRoles.find((_: ToBeFixed) => _.code === code)
    ) || [];
  const clientUrl = configData?.client?.url;
  const clientEmail = configData?.client?.contactEmail;

  const changeApprovalFlowFor = (
    uid: ToBeFixed,
    current: ToBeFixed,
    value: ToBeFixed
  ) => {
    const currentSet = new Set(current);
    if (value) {
      currentSet.add(uid);
    } else {
      currentSet.delete(uid);
    }
    return Array.from(currentSet);
  };

  const changeEntryLabelFor = (
    uid: ToBeFixed,
    current: ToBeFixed,
    value: ToBeFixed
  ) => ({
    ...current,
    [uid]: value && !isEmpty(value) ? [...value] : undefined,
  });

  const handleUpdateConfiguration = async (form: ToBeFixed) => {
    if (canChange) {
      lockApp();
      const payload = preparePayload(form);
      await submitMutation.mutateAsync(payload);
      const enabledCollectionsChanged = !isEqual(
        payload.enabledCollections,
        configData?.enabledCollections
      );
      const gqlAuthChanged = !isEqual(payload.gql?.auth, configData?.gql?.auth);
      if (enabledCollectionsChanged || gqlAuthChanged) {
        setRestartRequired(true);
      }
      unlockApp();
    }
  };

  const handleRestoreConfirmation = () => setRestoreConfigmationVisible(true);
  const handleRestoreConfiguration = async () => {
    if (canChange) {
      lockApp();
      await restoreMutation.mutateAsync();
      unlockApp();
      setRestartRequired(true);
      setRestoreConfigmationVisible(false);
    }
  };
  const handleRestoreCancel = () => setRestoreConfigmationVisible(false);

  const handleRestart = async () => {
    if (canChange) {
      lockApp();
      await restartMutation.mutateAsync();
      setRestartRequired(false);
      unlockApp();
    }
  };
  const handleRestartDiscard = () => setRestartRequired(false);

  const handleSetContentTypeExpanded = (key: ToBeFixed) =>
    setContentTypeExpanded(key === contentTypeExpanded ? undefined : key);

  const boxDefaultProps = {
    background: "neutral0",
    hasRadius: true,
    shadow: "filterShadow",
    padding: 6,
  };

  return (
    <Main>
      <Formik
        initialValues={{
          enabledCollections,
          moderatorRoles,
          badWords,
          approvalFlow,
          entryLabel,
          clientEmail,
          clientUrl,
          gqlAuthEnabled,
        }}
        enableReinitialize={true}
        onSubmit={handleUpdateConfiguration}
      >
        {({ handleSubmit, setFieldValue, values }: ToBeFixed) => (
          <Form noValidate onSubmit={handleSubmit}>
            <HeaderLayout
              title={getMessage("page.settings.header.title")}
              subtitle={getMessage("page.settings.header.description")}
              primaryAction={
                <CheckPermissions
                  permissions={pluginPermissions.settingsChange}
                >
                  <Button
                    type="submit"
                    startIcon={<Check />}
                    disabled={restartRequired}
                  >
                    {getMessage("page.settings.actions.submit")}
                  </Button>
                </CheckPermissions>
              }
            />
            <ContentLayout>
              <Stack size={4}>
                {restartRequired && (
                  <RestartAlert
                    closeLabel={getMessage(
                      "page.settings.actions.restart.alert.cancel"
                    )}
                    title={getMessage(
                      "page.settings.actions.restart.alert.title"
                    )}
                    action={
                      <Box>
                        <Button onClick={handleRestart} startIcon={<Play />}>
                          {getMessage("page.settings.actions.restart")}
                        </Button>
                      </Box>
                    }
                    onClose={handleRestartDiscard}
                  >
                    {getMessage(
                      "page.settings.actions.restart.alert.description"
                    )}
                  </RestartAlert>
                )}

                <Box {...boxDefaultProps}>
                  <Stack size={4}>
                    <Typography variant="delta" as="h2">
                      {getMessage("page.settings.section.general")}
                    </Typography>
                    <Grid gap={4}>
                      <GridItem col={12}>
                        <Select
                          name="enabledCollections"
                          label={getMessage(
                            "page.settings.form.enabledCollections.label"
                          )}
                          placeholder={getMessage(
                            "page.settings.form.enabledCollections.placeholder"
                          )}
                          hint={getMessage(
                            "page.settings.form.enabledCollections.hint"
                          )}
                          onClear={() =>
                            setFieldValue("enabledCollections", [], false)
                          }
                          value={values.enabledCollections}
                          onChange={(value: ToBeFixed) =>
                            setFieldValue("enabledCollections", value, false)
                          }
                          disabled={restartRequired}
                          multi
                          withTags
                        >
                          {allCollections.map(
                            ({ uid, schema: { displayName } }: ToBeFixed) => (
                              <Option key={uid} value={uid}>
                                {displayName}
                              </Option>
                            )
                          )}
                        </Select>
                      </GridItem>
                      {!isEmpty(values.enabledCollections) && (
                        <GridItem col={12}>
                          <AccordionGroup
                            label={getMessage(
                              "page.settings.form.contentTypesSettings.label"
                            )}
                            labelAction={
                              <Tooltip
                                description={getMessage(
                                  "page.settings.form.contentTypesSettings.tooltip"
                                )}
                              >
                                <Information aria-hidden={true} />
                              </Tooltip>
                            }
                          >
                            {orderBy(values.enabledCollections).map((uid) => {
                              const {
                                schema: { displayName, attributes = {} },
                              } = allCollections.find((_) => _.uid === uid);
                              const stringAttributes = Object.keys(
                                attributes
                              ).filter((_) => attributes[_].type === "string");
                              const key = `collectionSettings-${uid}`;
                              return (
                                <Accordion
                                  expanded={contentTypeExpanded === key}
                                  toggle={() =>
                                    handleSetContentTypeExpanded(key)
                                  }
                                  key={key}
                                  id={key}
                                  size="S"
                                >
                                  <AccordionToggle
                                    title={displayName}
                                    togglePosition="left"
                                  />
                                  <AccordionContent>
                                    <Box padding={6}>
                                      <Stack size={4}>
                                        <FormSwitch
                                          name={`collectionSettings-${uid}-approvalFlow`}
                                          label={getMessage(
                                            "page.settings.form.approvalFlow.label"
                                          )}
                                          hint={getMessage({
                                            id: "page.settings.form.approvalFlow.hint",
                                            props: { name: displayName },
                                          })}
                                          selected={values.approvalFlow.includes(
                                            uid
                                          )}
                                          onChange={() =>
                                            setFieldValue(
                                              "approvalFlow",
                                              changeApprovalFlowFor(
                                                uid,
                                                values.approvalFlow,
                                                !values.approvalFlow.includes(
                                                  uid
                                                )
                                              ),
                                              []
                                            )
                                          }
                                          onLabel={getMessage(
                                            "compontents.toogle.enabled"
                                          )}
                                          offLabel={getMessage(
                                            "compontents.toogle.disabled"
                                          )}
                                          disabled={restartRequired}
                                          visibleLabels
                                        />
                                        {!isEmpty(stringAttributes) && (
                                          <Select
                                            name={`collectionSettings-${uid}-entryLabel`}
                                            label={getMessage(
                                              "page.settings.form.entryLabel.label"
                                            )}
                                            placeholder={getMessage(
                                              "page.settings.form.entryLabel.placeholder"
                                            )}
                                            hint={getMessage(
                                              "page.settings.form.entryLabel.hint"
                                            )}
                                            onClear={() =>
                                              setFieldValue(
                                                "entryLabel",
                                                changeEntryLabelFor(
                                                  uid,
                                                  values.entryLabel
                                                )
                                              )
                                            }
                                            value={values.entryLabel[uid] || []}
                                            onChange={(value: ToBeFixed) =>
                                              setFieldValue(
                                                "entryLabel",
                                                changeEntryLabelFor(
                                                  uid,
                                                  values.entryLabel,
                                                  value
                                                )
                                              )
                                            }
                                            multi
                                            withTags
                                            disabled={restartRequired}
                                          >
                                            {stringAttributes.map((key) => (
                                              <Option
                                                key={`collectionSettings-${uid}-entryLabel-${key}`}
                                                value={key}
                                              >
                                                {capitalize(
                                                  key.split("_").join(" ")
                                                )}
                                              </Option>
                                            ))}
                                          </Select>
                                        )}
                                      </Stack>
                                    </Box>
                                  </AccordionContent>
                                </Accordion>
                              );
                            })}
                          </AccordionGroup>
                        </GridItem>
                      )}
                    </Grid>
                  </Stack>
                </Box>

                <Box {...boxDefaultProps}>
                  <Stack size={4}>
                    <Typography variant="delta" as="h2">
                      {getMessage("page.settings.section.additional")}
                    </Typography>
                    <Grid gap={4}>
                      <GridItem col={6} xs={12}>
                        <ToggleInput
                          name="badWords"
                          label={getMessage(
                            "page.settings.form.badWords.label"
                          )}
                          hint={getMessage("page.settings.form.badWords.hint")}
                          checked={values.badWords}
                          onChange={({ target: { checked } }: ToBeFixed) =>
                            setFieldValue("badWords", checked, false)
                          }
                          onLabel={getMessage("compontents.toogle.enabled")}
                          offLabel={getMessage("compontents.toogle.disabled")}
                          disabled={restartRequired}
                        />
                      </GridItem>
                      {isGQLPluginEnabled && (
                        <GridItem col={6} xs={12}>
                          <ToggleInput
                            name="gqlAuthEnabled"
                            label={getMessage(
                              "page.settings.form.gqlAuth.label"
                            )}
                            hint={getMessage("page.settings.form.gqlAuth.hint")}
                            checked={values.gqlAuthEnabled}
                            onChange={({ target: { checked } }: ToBeFixed) =>
                              setFieldValue("gqlAuthEnabled", checked, false)
                            }
                            onLabel={getMessage("compontents.toogle.enabled")}
                            offLabel={getMessage("compontents.toogle.disabled")}
                            disabled={restartRequired}
                          />
                        </GridItem>
                      )}
                    </Grid>
                  </Stack>
                </Box>

                <Box {...boxDefaultProps}>
                  <Stack size={4}>
                    <Typography variant="delta" as="h2">
                      {getMessage("page.settings.section.client")}
                    </Typography>
                    <Grid gap={4}>
                      <GridItem col={3} xs={12}>
                        <TextInput
                          type="url"
                          name="clientUrl"
                          label={getMessage(
                            "page.settings.form.client.url.label"
                          )}
                          hint={getMessage("page.settings.form.client.url.hint")}
                          value={values.clientUrl}
                          onChange={({ target: { value } }: ToBeFixed) =>
                            setFieldValue("clientUrl", value, false)
                          }
                          disabled={restartRequired}
                        />
                      </GridItem>
                      <GridItem col={3} xs={12}>
                        <TextInput
                          type="email"
                          name="clientEmail"
                          label={getMessage(
                            "page.settings.form.client.email.label"
                          )}
                          hint={getMessage("page.settings.form.client.email.hint")}
                          value={values.clientEmail}
                          onChange={({ target: { value } }: ToBeFixed) =>
                            setFieldValue("clientEmail", value, false)
                          }
                          disabled={restartRequired}
                        />
                      </GridItem>
                      <GridItem col={6} xs={12}>
                        <Select
                          name="moderatorRoles"
                          label={getMessage(
                            "page.settings.form.moderatorRoles.label"
                          )}
                          placeholder={getMessage(
                            "page.settings.form.moderatorRoles.placeholder"
                          )}
                          hint={getMessage(
                            "page.settings.form.moderatorRoles.hint"
                          )}
                          onClear={() =>
                            setFieldValue("moderatorRoles", [], false)
                          }
                          value={values.moderatorRoles}
                          onChange={(value: ToBeFixed) =>
                            setFieldValue("moderatorRoles", value, false)
                          }
                          disabled={restartRequired}
                          multi
                          withTags
                        >
                          {allRoles.map(({ code, name }: ToBeFixed) => (
                            <Option key={code} value={code}>
                              {name}
                            </Option>
                          ))}
                        </Select>
                      </GridItem>
                    </Grid>
                  </Stack>
                </Box>

                <CheckPermissions
                  permissions={pluginPermissions.settingsChange}
                >
                  <Box {...boxDefaultProps}>
                    <Stack size={4}>
                      <Stack size={2}>
                        <Typography variant="delta" as="h2">
                          {getMessage("page.settings.section.restore")}
                        </Typography>
                        <Typography variant="pi" as="h4">
                          {getMessage("page.settings.section.restore.subtitle")}
                        </Typography>
                      </Stack>
                      <Grid gap={4}>
                        <GridItem col={6}>
                          <Button
                            variant="danger-light"
                            startIcon={<Refresh />}
                            onClick={handleRestoreConfirmation}
                          >
                            {getMessage("page.settings.actions.restore")}
                          </Button>

                          <ConfirmationDialog
                            isVisible={restoreConfigmationVisible}
                            isActionAsync={restoreMutation.isLoading}
                            header={getMessage(
                              "page.settings.actions.restore.confirmation.header"
                            )}
                            labelConfirm={getMessage(
                              "page.settings.actions.restore.confirmation.button.confirm"
                            )}
                            iconConfirm={<Refresh />}
                            onConfirm={handleRestoreConfiguration}
                            onCancel={handleRestoreCancel}
                          >
                            {getMessage(
                              "page.settings.actions.restore.confirmation.description"
                            )}
                          </ConfirmationDialog>
                        </GridItem>
                      </Grid>
                    </Stack>
                  </Box>
                </CheckPermissions>
              </Stack>
            </ContentLayout>
          </Form>
        )}
      </Formik>
    </Main>
  );
}
Example #28
Source File: user.ts    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
UserBlock: m.Component<{
  user: Account<any> | AddressInfo | Profile;
  hideIdentityIcon?: boolean;
  popover?: boolean;
  showRole?: boolean;
  showAddressWithDisplayName?: boolean;
  addressDisplayOptions?: IAddressDisplayOptions;
  searchTerm?: string;
  showChainName?: boolean;
  hideOnchainRole?: boolean;
  selected?: boolean;
  compact?: boolean;
  linkify?: boolean;
  avatarSize?: number;
}> = {
  view: (vnode) => {
    const {
      user,
      hideIdentityIcon,
      popover,
      showRole,
      searchTerm,
      hideOnchainRole,
      showAddressWithDisplayName,
      showChainName,
      selected,
      compact,
      linkify,
      addressDisplayOptions,
    } = vnode.attrs;

    const { showFullAddress, autoTruncate, maxCharLength } =
      vnode.attrs.addressDisplayOptions || {};

    let profile;
    if (user instanceof AddressInfo) {
      if (!user.chain || !user.address) return;
      profile = app.profiles.getProfile(user.chain, user.address);
    } else if (user instanceof Profile) {
      profile = user;
    } else {
      profile = app.profiles.getProfile(user.chain.id, user.address);
    }

    const highlightSearchTerm =
      profile?.address &&
      searchTerm &&
      profile.address.toLowerCase().includes(searchTerm);
    const highlightedAddress = highlightSearchTerm
      ? (() => {
          const isNear = profile.address.chain === 'near';
          const queryStart = profile.address.toLowerCase().indexOf(searchTerm);
          const queryEnd = queryStart + searchTerm.length;

          return [
            m('span', profile.address.slice(0, queryStart)),
            m('mark', profile.address.slice(queryStart, queryEnd)),
            m('span', profile.address.slice(queryEnd, profile.address.length)),
          ];
        })()
      : null;

    const children = [
      m('.user-block-left', [
        m(User, {
          user,
          avatarOnly: true,
          avatarSize: vnode.attrs.avatarSize || 28,
          popover,
        }),
      ]),
      m('.user-block-center', [
        m('.user-block-name', [
          m(User, {
            user,
            hideAvatar: true,
            hideIdentityIcon,
            showAddressWithDisplayName,
            addressDisplayOptions,
            popover,
            showRole,
          }),
        ]),
        m(
          '.user-block-address',
          {
            class: profile?.address ? '' : 'no-address',
          },
          [
            m(
              '',
              highlightSearchTerm
                ? highlightedAddress
                : showFullAddress
                ? profile.address
                : formatAddressShort(profile.address, profile.chain)
            ),
            profile?.address && showChainName && m('.address-divider', ' · '),
            showChainName &&
              m(
                '',
                typeof user.chain === 'string'
                  ? capitalize(user.chain)
                  : capitalize(user.chain.name)
              ),
          ]
        ),
      ]),
      m('.user-block-right', [
        m(
          '.user-block-selected',
          selected ? m(CWIcon, { iconName: 'check' }) : ''
        ),
      ]),
    ];

    const userLink = profile
      ? `/${app.activeChainId() || profile.chain}/account/${
          profile.address
        }?base=${profile.chain}`
      : 'javascript:';

    return linkify
      ? link('.UserBlock', userLink, children)
      : m(
          '.UserBlock',
          {
            class: compact ? 'compact' : '',
          },
          children
        );
  },
}
Example #29
Source File: fulfillment.tsx    From admin with MIT License 4 votes vote down vote up
FormattedFulfillment = ({
  setFullfilmentToShip,
  order,
  fulfillmentObj,
}) => {
  const dialog = useImperativeDialog()
  const notification = useNotification()

  const cancelFulfillment = useAdminCancelFulfillment(order.id)
  const cancelSwapFulfillment = useAdminCancelSwapFulfillment(order.id)
  const cancelClaimFulfillment = useAdminCancelClaimFulfillment(order.id)

  const { fulfillment } = fulfillmentObj
  const hasLinks = !!fulfillment.tracking_links?.length

  const getData = () => {
    switch (true) {
      case !!fulfillment?.claim_order_id:
        return {
          resourceId: fulfillment.claim_order_id,
          resourceType: "claim",
        }
      case !!fulfillment?.swap_id:
        return {
          resourceId: fulfillment.swap_id,
          resourceType: "swap",
        }
      default:
        return { resourceId: order?.id, resourceType: "order" }
    }
  }

  const handleCancelFulfillment = async () => {
    const { resourceId, resourceType } = getData()

    const shouldCancel = await dialog({
      heading: "Cancel fulfillment?",
      text: "Are you sure you want to cancel the fulfillment?",
    })

    if (!shouldCancel) {
      return
    }

    switch (resourceType) {
      case "swap":
        return cancelSwapFulfillment.mutate(
          { swap_id: resourceId, fulfillment_id: fulfillment.id },
          {
            onSuccess: () =>
              notification("Success", "Successfully canceled swap", "success"),
            onError: (err) =>
              notification("Error", getErrorMessage(err), "error"),
          }
        )
      case "claim":
        return cancelClaimFulfillment.mutate(
          { claim_id: resourceId, fulfillment_id: fulfillment.id },
          {
            onSuccess: () =>
              notification("Success", "Successfully canceled claim", "success"),
            onError: (err) =>
              notification("Error", getErrorMessage(err), "error"),
          }
        )
      default:
        return cancelFulfillment.mutate(fulfillment.id, {
          onSuccess: () =>
            notification("Success", "Successfully canceled order", "success"),
          onError: (err) =>
            notification("Error", getErrorMessage(err), "error"),
        })
    }
  }

  return (
    <div className="flex w-full justify-between">
      <div className="flex flex-col space-y-1 py-2">
        <div className="text-grey-90">
          {fulfillment.canceled_at
            ? "Fulfillment has been canceled"
            : `${fulfillmentObj.title} Fulfilled by ${capitalize(
                fulfillment.provider_id
              )}`}
        </div>
        <div className="flex text-grey-50">
          {!fulfillment.shipped_at ? "Not shipped" : "Tracking"}
          {hasLinks &&
            fulfillment.tracking_links.map((tl, j) => (
              <TrackingLink key={j} trackingLink={tl} />
            ))}
        </div>
      </div>
      {!fulfillment.canceled_at && !fulfillment.shipped_at && (
        <div className="flex items-center space-x-2">
          <Actionables
            actions={[
              {
                label: "Mark Shipped",
                icon: <PackageIcon size={"20"} />,
                onClick: () => setFullfilmentToShip(fulfillment),
              },
              {
                label: "Cancel Fulfillment",
                icon: <CancelIcon size={"20"} />,
                onClick: () => handleCancelFulfillment(),
              },
            ]}
          />
        </div>
      )}
    </div>
  )
}