date-fns#formatISO TypeScript Examples

The following examples show how to use date-fns#formatISO. 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: date-picker-accepter.tsx    From platyplus with MIT License 6 votes vote down vote up
DatePickerAccepter: React.ElementType<
  DatePickerProps &
    FormControlAccepterProps & { date?: boolean; time?: boolean }
> = ({
  value,
  defaultValue,
  onChange,
  date = true,
  time = false,
  ...props
}) => {
  const formatter = useCallback(
    (v) => {
      if (v == null) return null
      return formatISO(v, {
        representation: !time ? 'date' : !date ? 'time' : 'complete'
      })
    },
    [date, time]
  )
  const internalValue = value == null ? null : parseISO(value)

  return (
    <DatePicker
      oneTap
      value={internalValue}
      onChange={(dateValue, event) => onChange(formatter(dateValue), event)}
      {...props}
    />
  )
}
Example #2
Source File: Date.tsx    From nextjs-netlify-blog-template with MIT License 6 votes vote down vote up
export default function Date({ date }: Props) {
  return (
    <time dateTime={formatISO(date)}>
      <span>{format(date, "LLLL d, yyyy")}</span>
      <style jsx>
        {`
          span {
            color: #9b9b9b;
          }
        `}
      </style>
    </time>
  );
}
Example #3
Source File: JsonLdMeta.tsx    From nextjs-netlify-blog-template with MIT License 6 votes vote down vote up
export default function JsonLdMeta({
  url,
  title,
  keywords,
  date,
  author,
  image,
  description,
}: Props) {
  return (
    <Head>
      <script
        {...jsonLdScriptProps<BlogPosting>({
          "@context": "https://schema.org",
          "@type": "BlogPosting",
          mainEntityOfPage: config.base_url + url,
          headline: title,
          keywords: keywords ? undefined : keywords.join(","),
          datePublished: formatISO(date),
          author: author,
          image: image,
          description: description,
        })}
      />
    </Head>
  );
}
Example #4
Source File: VideoForm.hooks.ts    From atlas with GNU General Public License v3.0 5 votes vote down vote up
useVideoFormDraft = (
  watch: UseFormWatch<VideoWorkspaceVideoFormFields>,
  dirtyFields: FieldNamesMarkedBoolean<VideoWorkspaceVideoFormFields>
) => {
  const { activeChannelId } = useAuthorizedUser()
  const { editedVideoInfo, setEditedVideo } = useVideoWorkspace()
  const { updateDraft, addDraft } = useDraftStore((state) => state.actions)

  // we pass the functions explicitly so the debounced function doesn't need to change when those functions change
  const debouncedDraftSave = useRef(
    debounce(
      (
        channelId: string,
        tab: VideoWorkspace,
        data: VideoWorkspaceVideoFormFields,
        addDraftFn: typeof addDraft,
        updateDraftFn: typeof updateDraft,
        updateSelectedTabFn: typeof setEditedVideo
      ) => {
        const draftData: RawDraft = {
          ...data,
          channelId: activeChannelId,
          type: 'video',
          publishedBeforeJoystream: isDateValid(data.publishedBeforeJoystream)
            ? formatISO(data.publishedBeforeJoystream as Date)
            : null,
        }
        if (tab.isNew) {
          addDraftFn(draftData, tab.id)
          updateSelectedTabFn({ ...tab, isNew: false })
        } else {
          updateDraftFn(tab.id, draftData)
        }
      },
      700
    )
  )

  // save draft on form fields update
  useEffect(() => {
    if (!editedVideoInfo?.isDraft) {
      return
    }

    const subscription = watch((data) => {
      if (!Object.keys(dirtyFields).length) {
        return
      }

      debouncedDraftSave.current(activeChannelId, editedVideoInfo, data, addDraft, updateDraft, setEditedVideo)
    })
    return () => {
      subscription.unsubscribe()
    }
  }, [addDraft, dirtyFields, editedVideoInfo, updateDraft, setEditedVideo, watch, activeChannelId])

  const flushDraftSave = useCallback(() => {
    debouncedDraftSave.current.flush()
  }, [])

  return { flushDraftSave }
}
Example #5
Source File: index.ts    From integration-services with Apache License 2.0 5 votes vote down vote up
getDateStringFromDate = (date: Date): string | null | undefined => {
	return date && formatISO(date);
}
Example #6
Source File: CommentItem.test.tsx    From knboard with MIT License 5 votes vote down vote up
comment: TaskComment = {
  id: 1,
  author: 1,
  created: formatISO(new Date(2012, 8, 18, 19, 0, 52)),
  modified: formatISO(new Date(2015, 9, 15, 20, 2, 53)),
  task: 1,
  text: "foobar",
}
Example #7
Source File: VideoForm.tsx    From atlas with GNU General Public License v3.0 4 votes vote down vote up
VideoForm: React.FC<VideoFormProps> = React.memo(({ onSubmit, setFormStatus }) => {
  const [moreSettingsVisible, setMoreSettingsVisible] = useState(false)
  const [cachedEditedVideoId, setCachedEditedVideoId] = useState('')
  const [royaltiesFieldEnabled, setRoyaltiesFieldEnabled] = useState(false)
  const mintNftFormFieldRef = useRef<HTMLDivElement>(null)

  const { editedVideoInfo } = useVideoWorkspace()
  const { tabData, loading: tabDataLoading, error: tabDataError } = useVideoWorkspaceData()

  const {
    chainState: { nftMaxCreatorRoyaltyPercentage, nftMinCreatorRoyaltyPercentage },
  } = useJoystream()
  const resolveAsset = useRawAssetResolver()

  const deleteVideo = useDeleteVideo()
  const isEdit = !editedVideoInfo?.isDraft
  const isNew = !isEdit
  const mintNft = editedVideoInfo?.mintNft

  const { categories, error: categoriesError } = useCategories(undefined, {
    onError: (error) => SentryLogger.error('Failed to fetch categories', 'VideoWorkspace', error),
  })

  const {
    register,
    control,
    handleSubmit: createSubmitHandler,
    getValues,
    setValue,
    watch,
    trigger,
    reset,
    formState: { errors, dirtyFields, isDirty, touchedFields, isValid },
  } = useForm<VideoWorkspaceVideoFormFields>({
    shouldFocusError: true,
    mode: 'onChange',
  })

  const videoFieldsLocked = tabData?.mintNft && isEdit

  // manage assets used by the form
  const {
    handleVideoFileChange,
    handleThumbnailFileChange,
    videoHashPromise,
    thumbnailHashPromise,
    files,
    mediaAsset,
    thumbnailAsset,
    hasUnsavedAssets,
  } = useVideoFormAssets(watch, getValues, setValue, dirtyFields)

  // manage draft saving
  const { flushDraftSave } = useVideoFormDraft(watch, dirtyFields)

  // reset form whenever edited video gets updated
  useEffect(() => {
    if (editedVideoInfo.id === cachedEditedVideoId || !tabData || tabDataLoading) {
      return
    }
    setCachedEditedVideoId(editedVideoInfo.id)

    reset(tabData)
  }, [tabData, tabDataLoading, reset, mintNft, editedVideoInfo.id, cachedEditedVideoId, setValue])

  // animate scroll to Mint an NFT switch and toggle it, if user selected it from video tile context menu
  useEffect(() => {
    if (!mintNft || !mintNftFormFieldRef.current || !tabData || getValues('mintNft') || touchedFields.mintNft) {
      return
    }
    const scrollTimeout = setTimeout(
      () => mintNftFormFieldRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' }),
      SCROLL_TIMEOUT
    )
    const setMintNftTimeout = setTimeout(
      () => setValue('mintNft', tabData.mintNft || mintNft, { shouldTouch: true }),
      MINT_NFT_TIMEOUT
    )

    return () => {
      clearTimeout(scrollTimeout)
      clearTimeout(setMintNftTimeout)
    }
  }, [touchedFields, mintNft, setValue, tabData, getValues])

  const handleSubmit = useCallback(() => {
    flushDraftSave()

    const handler = createSubmitHandler(async (data) => {
      if (!editedVideoInfo) {
        return
      }

      const { video: videoInputFile, thumbnail: thumbnailInputFile } = data.assets
      const videoAsset = resolveAsset(videoInputFile.id)
      const thumbnailAsset = resolveAsset(thumbnailInputFile.cropId)

      if (isNew && (!videoAsset || !videoHashPromise)) {
        ConsoleLogger.error('Video file cannot be empty')
        return
      }

      if (isNew && (!thumbnailAsset || !thumbnailHashPromise)) {
        ConsoleLogger.error('Thumbnail cannot be empty')
        return
      }

      const license = {
        code: data.licenseCode ?? undefined,
        attribution: data.licenseAttribution ?? undefined,
        customText: data.licenseCustomText ?? undefined,
      }
      const anyLicenseFieldsDirty =
        dirtyFields.licenseCode || dirtyFields.licenseAttribution || dirtyFields.licenseCustomText

      const metadata: VideoInputMetadata = {
        ...(isNew || dirtyFields.title ? { title: data.title } : {}),
        ...(isNew || dirtyFields.description ? { description: data.description } : {}),
        ...(isNew || dirtyFields.category ? { category: Number(data.category) } : {}),
        ...(isNew || dirtyFields.isPublic ? { isPublic: data.isPublic } : {}),
        ...((isNew || dirtyFields.hasMarketing) && data.hasMarketing != null
          ? { hasMarketing: data.hasMarketing }
          : {}),
        ...((isNew || dirtyFields.isExplicit) && data.isExplicit != null ? { isExplicit: data.isExplicit } : {}),
        ...((isNew || dirtyFields.language) && data.language != null ? { language: data.language } : {}),
        ...(isNew || anyLicenseFieldsDirty ? { license } : {}),
        ...((isNew || dirtyFields.publishedBeforeJoystream) && data.publishedBeforeJoystream != null
          ? {
              publishedBeforeJoystream: formatISO(data.publishedBeforeJoystream),
            }
          : {}),
        ...(isNew || dirtyFields.assets?.video
          ? {
              mimeMediaType: videoInputFile?.mimeType,
            }
          : {}),
        ...(isNew || dirtyFields.assets?.video ? { duration: Math.round(videoInputFile?.duration || 0) } : {}),
        ...(isNew || dirtyFields.assets?.video ? { mediaPixelHeight: videoInputFile?.mediaPixelHeight } : {}),
        ...(isNew || dirtyFields.assets?.video ? { mediaPixelWidth: videoInputFile?.mediaPixelWidth } : {}),
      }

      const videoWidth = videoInputFile?.mediaPixelWidth
      const videoHeight = videoInputFile?.mediaPixelHeight
      const assets: VideoFormAssets = {
        ...(videoAsset?.blob && videoInputFile.id && videoHashPromise
          ? {
              media: {
                id: videoInputFile.id,
                blob: videoAsset.blob,
                url: videoAsset.url || undefined,
                hashPromise: videoHashPromise,
                dimensions: videoWidth && videoHeight ? { height: videoHeight, width: videoWidth } : undefined,
              },
            }
          : {}),
        ...(thumbnailAsset?.blob && thumbnailInputFile.cropId && thumbnailInputFile.originalId && thumbnailHashPromise
          ? {
              thumbnailPhoto: {
                id: thumbnailInputFile.cropId,
                originalId: thumbnailInputFile.originalId,
                blob: thumbnailAsset.blob,
                url: thumbnailAsset.url || undefined,
                hashPromise: thumbnailHashPromise,
                dimensions: thumbnailInputFile?.assetDimensions,
                cropData: thumbnailInputFile?.imageCropData,
              },
            }
          : {}),
      }

      const nftMetadata: NftIssuanceInputMetadata | undefined = data.mintNft
        ? {
            royalty: data.nftRoyaltiesPercent || undefined,
          }
        : undefined

      onSubmit({
        metadata,
        assets,
        nftMetadata,
      })
    })

    return handler()
  }, [
    createSubmitHandler,
    dirtyFields,
    editedVideoInfo,
    flushDraftSave,
    isNew,
    onSubmit,
    resolveAsset,
    thumbnailHashPromise,
    videoHashPromise,
  ])

  const actionBarPrimaryText = watch('mintNft') ? 'Publish & mint' : !isEdit ? 'Publish & upload' : 'Publish changes'

  const isFormValid = (isEdit || !!mediaAsset) && !!thumbnailAsset && isValid
  const formStatus: VideoWorkspaceFormStatus = useMemo(
    () => ({
      hasUnsavedAssets,
      isDirty,
      isDisabled: isEdit ? isDirty || !!mintNft : isFormValid,
      actionBarPrimaryText,
      isValid: isFormValid,
      triggerFormSubmit: handleSubmit,
      triggerReset: reset,
    }),
    [actionBarPrimaryText, handleSubmit, hasUnsavedAssets, isDirty, isEdit, isFormValid, mintNft, reset]
  )

  // sent updates on form status to VideoWorkspace
  useEffect(() => {
    setFormStatus(formStatus)
  }, [formStatus, setFormStatus])

  const handleDeleteVideo = () => {
    editedVideoInfo && deleteVideo(editedVideoInfo.id)
  }

  const categoriesSelectItems: SelectItem[] =
    categories?.map((c) => ({
      name: c.name || 'Unknown category',
      value: c.id,
    })) || []

  const getHiddenSectionLabel = () => {
    if (videoFieldsLocked) {
      return `${moreSettingsVisible ? 'Hide' : 'Show'} non-editable fields`
    }
    return `Show ${moreSettingsVisible ? 'less' : 'more'} settings`
  }

  if (tabDataError || categoriesError) {
    return <ViewErrorFallback />
  }

  const videoEditFields = (
    <>
      <DescriptionTextArea
        {...register('description', textFieldValidation({ name: 'Description', maxLength: 5000 }))}
        maxLength={5000}
        placeholder="Description of the video to share with your audience"
        error={!!errors.description}
        helperText={errors.description?.message}
        disabled={videoFieldsLocked}
      />
      <FormField title="Video category">
        <Controller
          name="category"
          control={control}
          rules={requiredValidation('Video category')}
          render={({ field: { value, onChange, ref } }) => (
            <Select
              containerRef={ref}
              value={value}
              items={categoriesSelectItems}
              onChange={onChange}
              error={!!errors.category && !value}
              helperText={errors.category?.message}
              disabled={videoFieldsLocked}
            />
          )}
        />
      </FormField>
      <FormField title="Video language">
        <Controller
          name="language"
          control={control}
          rules={requiredValidation('Video language')}
          render={({ field: { value, onChange } }) => (
            <Select
              value={value}
              items={languages}
              onChange={onChange}
              error={!!errors.language && !value}
              helperText={errors.language?.message}
              disabled={videoFieldsLocked}
            />
          )}
        />
      </FormField>
      <ExtendedMarginFormField title="Video visibility">
        <Controller
          name="isPublic"
          control={control}
          defaultValue={true}
          rules={{
            validate: (value) => value !== null,
          }}
          render={({ field: { value, onChange } }) => (
            <RadioCardButtonsContainer>
              <OptionCardRadio
                value="true"
                label="Public"
                onChange={() => onChange(true)}
                selectedValue={value?.toString()}
                helperText="Visible to all"
                disabled={videoFieldsLocked}
              />
              <OptionCardRadio
                value="false"
                label="Unlisted"
                onChange={() => onChange(false)}
                selectedValue={value?.toString()}
                helperText="Visible with link only"
                disabled={videoFieldsLocked}
              />
            </RadioCardButtonsContainer>
          )}
        />
      </ExtendedMarginFormField>
    </>
  )

  return (
    <FormWrapper as="form" onSubmit={handleSubmit}>
      <Controller
        name="assets"
        control={control}
        render={() => (
          // don't remove this div
          // without this element position sticky won't work
          <div>
            <StyledMultiFileSelect
              files={files}
              onVideoChange={handleVideoFileChange}
              onThumbnailChange={handleThumbnailFileChange}
              editMode={isEdit}
              disabled={videoFieldsLocked}
              maxVideoSize={10 * 1024 * 1024 * 1024}
            />
          </div>
        )}
      />
      <InputsContainer>
        <Controller
          name="title"
          control={control}
          rules={textFieldValidation({ name: 'Video Title', minLength: 3, maxLength: 60, required: true })}
          render={({ field: { value, onChange } }) => (
            <StyledTitleArea
              onChange={onChange}
              value={value}
              min={3}
              max={60}
              placeholder="Video title"
              disabled={videoFieldsLocked}
            />
          )}
        />
        {!videoFieldsLocked && videoEditFields}
        <SwitchFormField title="Mint NFT" ref={mintNftFormFieldRef}>
          <SwitchNftWrapper>
            <Controller
              name="mintNft"
              control={control}
              defaultValue={false}
              render={({ field: { value, onChange } }) => (
                <Switch
                  label="Mint NFT for this video"
                  value={value}
                  onChange={(e) => {
                    if (!e?.currentTarget.checked) {
                      trigger()
                      setRoyaltiesFieldEnabled(false)
                      setValue('nftRoyaltiesPercent', undefined)
                    }
                    onChange(e)
                  }}
                  disabled={videoFieldsLocked}
                />
              )}
            />
            <Information
              placement="top"
              arrowDisabled
              text="Minting an NFT creates a record of ownership on the blockchain that can be put on sale. This will not impact your intellectual rights of the video."
            />
          </SwitchNftWrapper>
          {watch('mintNft') && (
            <>
              <Banner
                id="issuing-nft"
                dismissable={false}
                icon={<StyledSvgWarning width={24} height={24} />}
                description={
                  !videoFieldsLocked ? (
                    <Text variant="t200">
                      You <YellowText>won’t be able to edit this video</YellowText> once you mint an NFT for it.
                    </Text>
                  ) : (
                    <Text variant="t200">
                      Many fields are disabled after minting an NFT for this video -
                      <VideoLink to={absoluteRoutes.viewer.video(editedVideoInfo.id)}>
                        &nbsp;go to it's video page.
                      </VideoLink>
                    </Text>
                  )
                }
              />
              <FormField
                switchProps={{
                  value: videoFieldsLocked ? !!watch('nftRoyaltiesPercent') : royaltiesFieldEnabled,
                  onChange: (e) => {
                    if (e?.currentTarget.checked) {
                      setValue('nftRoyaltiesPercent', 1)
                    } else {
                      setValue('nftRoyaltiesPercent', undefined, { shouldValidate: true })
                      trigger()
                    }
                    setRoyaltiesFieldEnabled(!!e?.currentTarget.checked)
                  },
                  disabled: videoFieldsLocked,
                }}
                title="Set creator's royalties"
                infoTooltip={{ text: 'Setting royalties lets you earn commission from every sale of this NFT.' }}
              >
                <TextField
                  type="number"
                  {...register('nftRoyaltiesPercent', {
                    valueAsNumber: true,
                    min: {
                      value: nftMinCreatorRoyaltyPercentage,
                      message: `Creator royalties cannot be lower than ${nftMinCreatorRoyaltyPercentage}%`,
                    },
                    max: {
                      value: nftMaxCreatorRoyaltyPercentage,
                      message: `Creator royalties cannot be higher than ${nftMaxCreatorRoyaltyPercentage}%`,
                    },
                  })}
                  error={!!errors.nftRoyaltiesPercent}
                  placeholder="—"
                  helperText={errors.nftRoyaltiesPercent?.message}
                  nodeEnd={<Pill variant="default" label="%" />}
                  disabled={videoFieldsLocked || !royaltiesFieldEnabled}
                />
              </FormField>
            </>
          )}
        </SwitchFormField>
        <MoreSettingsHeader>
          <Button
            size="large"
            iconPlacement="right"
            textOnly
            icon={moreSettingsVisible ? <SvgActionChevronT /> : <SvgActionChevronB />}
            onClick={() => setMoreSettingsVisible(!moreSettingsVisible)}
          >
            {getHiddenSectionLabel()}
          </Button>
          <MoreSettingsDescription as="p" variant="t200" secondary visible={!moreSettingsVisible}>
            {!videoFieldsLocked
              ? `License, content rating, published before, marketing${isEdit ? ', delete video' : ''}`
              : 'Description, video category, video language, video visibility, licence, content rating, published before, marketing'}
          </MoreSettingsDescription>
        </MoreSettingsHeader>
        <MoreSettingsSection expanded={moreSettingsVisible}>
          {videoFieldsLocked && videoEditFields}
          <FormField title="License">
            <Controller
              name="licenseCode"
              control={control}
              rules={requiredValidation('License')}
              render={({ field: { value, onChange, ref } }) => (
                <Select
                  containerRef={ref}
                  value={value}
                  items={knownLicensesOptions}
                  placeholder="Choose license type"
                  onChange={onChange}
                  error={!!errors.licenseCode && !value}
                  helperText={errors.licenseCode?.message}
                  disabled={videoFieldsLocked}
                />
              )}
            />
          </FormField>
          {knownLicenses.find((license) => license.code === watch('licenseCode'))?.attributionRequired && (
            <FormField title="License attribution" optional>
              <TextField
                {...register(
                  'licenseAttribution',
                  textFieldValidation({ name: 'License attribution', maxLength: 5000 })
                )}
                placeholder="Type your attribution here"
                error={!!errors.licenseAttribution}
                helperText={errors.licenseAttribution?.message}
                disabled={videoFieldsLocked}
              />
            </FormField>
          )}

          {watch('licenseCode') === CUSTOM_LICENSE_CODE && (
            <FormField title="Custom license">
              <TextArea
                {...register(
                  'licenseCustomText',
                  textFieldValidation({ name: 'License', maxLength: 5000, required: false })
                )}
                maxLength={5000}
                placeholder="Type your license content here"
                error={!!errors.licenseCustomText}
                helperText={errors.licenseCustomText?.message}
              />
            </FormField>
          )}

          <ExtendedMarginFormField
            title="Content rating"
            description="If the content you are publishing contains explicit material (sex, violence, etc.), please mark it as mature."
          >
            <Controller
              name="isExplicit"
              control={control}
              defaultValue={false}
              rules={{
                validate: (value) => value !== null,
              }}
              render={({ field: { value, onChange, ref } }) => (
                <RadioButtonsContainer>
                  <RadioButton
                    ref={ref}
                    value="false"
                    label="All audiences"
                    onChange={() => onChange(false)}
                    selectedValue={value?.toString()}
                    error={!!errors.isExplicit}
                    helperText={errors.isExplicit ? 'Content rating must be selected' : ''}
                    disabled={videoFieldsLocked}
                  />
                  <RadioButton
                    value="true"
                    label="Mature"
                    onChange={() => onChange(true)}
                    selectedValue={value?.toString()}
                    error={!!errors.isExplicit}
                    helperText={errors.isExplicit ? 'Content rating must be selected' : ''}
                    disabled={videoFieldsLocked}
                  />
                </RadioButtonsContainer>
              )}
            />
          </ExtendedMarginFormField>
          <ExtendedMarginFormField
            title="Prior publication"
            optional
            description="If the content you are publishing was originally published outside of Joystream, please provide the original publication date."
          >
            <Controller
              name="publishedBeforeJoystream"
              control={control}
              rules={{
                validate: (value) => pastDateValidation(value),
              }}
              render={({ field: { value, onChange } }) => (
                <Datepicker
                  value={value}
                  onChange={onChange}
                  error={!!errors.publishedBeforeJoystream}
                  helperText={errors.publishedBeforeJoystream ? 'Please provide a valid date.' : ''}
                  disabled={videoFieldsLocked}
                />
              )}
            />
          </ExtendedMarginFormField>
          <FormField title="Marketing" optional>
            <Controller
              name="hasMarketing"
              control={control}
              render={({ field: { value, onChange } }) => (
                <Checkbox
                  value={value ?? false}
                  label="My video features a paid promotion material"
                  onChange={onChange}
                  disabled={videoFieldsLocked}
                />
              )}
            />
          </FormField>
          {isEdit && !videoFieldsLocked && (
            <DeleteVideoButton fullWidth size="large" variant="destructive-secondary" onClick={handleDeleteVideo}>
              Delete video
            </DeleteVideoButton>
          )}
        </MoreSettingsSection>
      </InputsContainer>
    </FormWrapper>
  )
})