Skip to content

Commit

Permalink
Refactors Form
Browse files Browse the repository at this point in the history
  • Loading branch information
gbdubs committed Dec 9, 2023
1 parent 2cc077f commit 7b73766
Show file tree
Hide file tree
Showing 35 changed files with 409 additions and 403 deletions.
2 changes: 1 addition & 1 deletion frontend/components/CopyToClipboardButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface Props {
}
const props = defineProps<Props>()
const prefix = 'CopyToClipboardButton'
const prefix = 'components/CopyToClipboardButton'
const tt = (key: string) => t(`${prefix}.${key}`)
const statePrefix = `${prefix}[${useStateIDGenerator().id()}]`
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/IconButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ const props = withDefaults(defineProps<Props>(), {
tooltipClass: undefined,
offlineSafe: undefined,
})
const tt = computed(() => {
const tooltip = computed(() => {
const result = { value: props.alt, class: props.tooltipClass }
return result
})
</script>

<template>
<PVButton
v-tooltip="tt"
v-tooltip="tooltip"
:icon="props.icon"
:aria-label="props.alt"
:class="props.buttonClass"
Expand Down
34 changes: 14 additions & 20 deletions frontend/components/form/EditorField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,38 @@ import { useSlots } from 'vue'
import { type EditorField, type EditorValue, isValid } from '@/lib/editor'
const { t } = useI18n()
const tt = (key: string) => t(`FormEditorField.${key}`)
const tt = (key: string) => t(`components/form/EditorField.${key}`)
interface Props {
editorField: EditorField<any, keyof any>
editorValue: EditorValue<any, keyof any>
helpText?: string
startHelpTextExpanded?: boolean
isLoading?: boolean
loadingLabel?: string
invalidLabel?: string
validLabel?: string
}
const props = withDefaults(defineProps<Props>(), {
helpText: undefined,
startHelpTextExpanded: false,
loading: false,
loadingLabel: tt('Loading...'),
invalidLabel: tt('Needs Attention'),
validLabel: '',
isLoading: false,
})
const slots = useSlots()
const helpTextSlotExists = computed(() => slots['help-text'] !== undefined)
const valid = computed(() => isValid(props.editorValue))
const hasValidation = computed(() => (props.editorValue.validation ?? []).length > 0)
const valid = computed(() => isValid(props.editorField, props.editorValue))
const hasValidation = computed(() => (props.editorField.validation ?? []).length > 0)
const loadingLabel = computed(() => props.editorField.loadingLabel ?? tt('Loading...'))
const invalidLabel = computed(() => props.editorField.invalidLabel ?? tt('Needs Attention'))
const validLabel = computed(() => props.editorField.validLabel ?? '')
const startHelpTextExpanded = computed(() => props.editorField.startHelpTextExpanded ?? false)
</script>

<template>
<FormField
:label="props.editorField.label"
:help-text="props.helpText"
:start-help-text-expanded="props.startHelpTextExpanded"
:is-loading="props.loading"
:loading-label="props.loadingLabel"
:help-text="props.editorField.helpText"
:start-help-text-expanded="startHelpTextExpanded"
:is-loading="props.isLoading"
:loading-label="loadingLabel"
:has-validation="hasValidation"
:is-valid="valid"
:invalid-label="props.invalidLabel"
:valid-label="props.validLabel"
:invalid-label="invalidLabel"
:valid-label="validLabel"
>
<template
v-if="helpTextSlotExists"
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/form/Field.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useSlots } from 'vue'
const slots = useSlots()
const { t } = useI18n()
const prefix = 'FormField'
const prefix = 'components/form/Field'
const tt = (s: string) => t(`${prefix}.${s}`)
interface Props {
Expand Down
44 changes: 27 additions & 17 deletions frontend/components/incompleteupload/Editor.vue
Original file line number Diff line number Diff line change
@@ -1,48 +1,58 @@
<script setup lang="ts">
import { type EditorIncompleteUpload } from '@/lib/editor'
import {
type EditorIncompleteUploadFields as EditorFields,
type EditorIncompleteUploadValues as EditorValues,
} from '@/lib/editor'
const prefix = 'components/incompleteupload/Editor'
const { t } = useI18n()
const tt = (key: string) => t(`${prefix}.${key}`)
interface Props {
editorIncompleteUpload: EditorIncompleteUpload
editorValues: EditorValues
editorFields: EditorFields
}
interface Emits {
(e: 'update:editorIncompleteUpload', ei: EditorIncompleteUpload): void
(e: 'update:editorValues', evs: EditorValues): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const model = computed({
get: () => props.editorIncompleteUpload,
set: (editorIncompleteUpload: EditorIncompleteUpload) => { emit('update:editorIncompleteUpload', editorIncompleteUpload) },
const efs = computed(() => props.editorFields)
const evs = computed({
get: () => props.editorValues,
set: (editorValues: EditorValues) => { emit('update:editorValues', editorValues) },
})
</script>

<template>
<div>
<FormEditorField
help-text="The name of this uploaded source file."
:editor-field="model.name"
:editor-field="efs.name"
:editor-value="evs.name"
>
<PVInputText
v-model="model.name.currentValue"
v-model="evs.name.currentValue"
/>
</FormEditorField>
<FormEditorField
help-text="The description of this upload - helpful for record keeping, not used for anything."
:editor-field="model.description"
:editor-field="efs.description"
:editor-value="evs.description"
>
<PVTextarea
v-model="model.description.currentValue"
v-model="evs.description.currentValue"
auto-resize
/>
</FormEditorField>
<FormEditorField
help-text="When enabled, this upload can be accessed by administrators to help with debugging. Only turn this on if you're comfortable with system administrators accessing this data."
:editor-field="model.adminDebugEnabled"
:editor-field="efs.adminDebugEnabled"
:editor-value="evs.adminDebugEnabled"
>
<ExplicitInputSwitch
v-model:value="model.adminDebugEnabled.currentValue"
on-label="Administrator Debugging Access Enabled"
off-label="No Administrator Access Enabled"
v-model:value="evs.adminDebugEnabled.currentValue"
:on-label="tt('Administrator Debugging Access Enabled')"
:off-label="tt('No Administrator Access Enabled')"
/>
</FormEditorField>
</div>
Expand Down
79 changes: 42 additions & 37 deletions frontend/components/initiative/Editor.vue
Original file line number Diff line number Diff line change
@@ -1,110 +1,115 @@
<script setup lang="ts">
import { type EditorInitiative } from '@/lib/editor'
import {
type EditorInitiativeFields as EditorFields,
type EditorInitiativeValues as EditorValues,
} from '@/lib/editor'
interface Props {
editorInitiative: EditorInitiative
editorFields: EditorFields
editorValues: EditorValues
}
interface Emits {
(e: 'update:editorInitiative', ei: EditorInitiative): void
(e: 'update:editorValues', evs: EditorValues): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const model = computed({
get: () => props.editorInitiative,
set: (editorInitiative: EditorInitiative) => { emit('update:editorInitiative', editorInitiative) },
const efs = computed(() => props.editorFields)
const evs = computed({
get: () => props.editorValues,
set: (evs) => { emit('update:editorValues', evs) },
})
</script>

<template>
<div>
<FormEditorField
help-text="The name of the PACTA initiative."
:editor-field="model.name"
:editor-field="efs.name"
:editor-value="evs.name"
>
<PVInputText
v-model="model.name.currentValue"
v-model="evs.name.currentValue"
/>
</FormEditorField>
<FormEditorField
help-text="This is the immutable unique identifier for the initiative. It can only contain alphanumeric characters, underscores, and dashes. This value will be shown in URLs, but will typically not be user visible."
:editor-field="model.id"
:editor-field="efs.id"
:editor-value="evs.id"
>
<PVInputText
v-model="model.id.currentValue"
:disabled="!!model.id.originalValue"
v-model="evs.id.currentValue"
:disabled="!!evs.id.originalValue"
/>
</FormEditorField>
<FormEditorField
help-text="An optional description of the organization or entity that is hosting this initiative."
:editor-field="model.affiliation"
:editor-field="efs.affiliation"
:editor-value="evs.affiliation"
>
<PVInputText
v-model="model.affiliation.currentValue"
v-model="evs.affiliation.currentValue"
/>
</FormEditorField>
<FormEditorField
help-text="The description of the initiative that will be shown to the public. Newlines will be respected."
:editor-field="model.publicDescription"
:editor-field="efs.publicDescription"
:editor-value="evs.publicDescription"
>
<PVTextarea
v-model="model.publicDescription.currentValue"
v-model="evs.publicDescription.currentValue"
auto-resize
/>
</FormEditorField>
<FormEditorField
help-text="The description of the initiative that will be shown to members of the inititiative. Newlines will be respected."
:editor-field="model.internalDescription"
:editor-field="efs.internalDescription"
:editor-value="evs.internalDescription"
>
<PVTextarea
v-model="model.internalDescription.currentValue"
v-model="evs.internalDescription.currentValue"
auto-resize
/>
</FormEditorField>
<FormEditorField
help-text="When disabled, anyone can join this initiative. When enabled, initiative administrators can mint invitation codes that they can share with folks to allow them to join the project."
:editor-field="model.requiresInvitationToJoin"
:editor-field="efs.requiresInvitationToJoin"
:editor-value="evs.requiresInvitationToJoin"
>
<ExplicitInputSwitch
v-model:value="model.requiresInvitationToJoin.currentValue"
v-model:value="evs.requiresInvitationToJoin.currentValue"
on-label="Requires Invitation To Join"
off-label="Anyone Can Join"
/>
</FormEditorField>
<FormEditorField
:editor-field="model.isAcceptingNewMembers"
help-text="When enabled, new members can join the project through the joining mechanism selected above."
:editor-field="efs.isAcceptingNewMembers"
:editor-value="evs.isAcceptingNewMembers"
>
<ExplicitInputSwitch
v-model:value="model.isAcceptingNewMembers.currentValue"
v-model:value="evs.isAcceptingNewMembers.currentValue"
on-label="Accepting New Members"
off-label="Closed To New Members"
/>
</FormEditorField>
<FormEditorField
:editor-field="model.isAcceptingNewPortfolios"
help-text="When enabled, initiative members can add new portfolios to the initiative."
:editor-field="efs.isAcceptingNewPortfolios"
:editor-value="evs.isAcceptingNewPortfolios"
>
<ExplicitInputSwitch
v-model:value="model.isAcceptingNewPortfolios.currentValue"
v-model:value="evs.isAcceptingNewPortfolios.currentValue"
on-label="Accepting New Portfolios"
off-label="Closed To New Portfolios"
/>
</FormEditorField>
<FormEditorField
:editor-field="model.language"
help-text="What language should reports have when they are generated for this initiative?"
:editor-field="efs.language"
:editor-value="evs.language"
>
<LanguageSelector
v-model:value="model.language.currentValue"
v-model:value="evs.language.currentValue"
/>
</FormEditorField>
<FormEditorField
help-text="What version of the PACTA algorithm should this initiative use to generate reports?"
:editor-field="model.pactaVersion"
:editor-field="efs.pactaVersion"
:editor-value="evs.pactaVersion"
>
<PactaversionSelector
v-model:value="model.pactaVersion.currentValue"
v-model:value="evs.pactaVersion.currentValue"
/>
</FormEditorField>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/initiative/Toolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { t } = useI18n()
const { getMaybeMe } = useSession()
const { isAdmin, maybeMe } = await getMaybeMe()
const prefix = 'InitiativeToolbar'
const prefix = 'components/initiative/Toolbar'
const tt = (key: string) => t(`${prefix}.${key}`)
interface Props {
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/locale/Selector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const locales = computed<Option[]>(() => baseLocales.value as Option[])
const locale = computed<Option>(
() => presentOrFileBug(locales.value.find(o => o.code === baseLocale.value)))
const prefix = 'LocaleSelector'
const prefix = 'components/locale/Selector'
const tt = (s: string) => t(`${prefix}.${s}`)
const visible = useState<boolean>(`${prefix}.visible`, () => false)
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/modal/Error.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const error = useError()
const router = useRouter()
const { t } = useI18n()
const prefix = 'ModalError'
const prefix = 'components/modal/Error'
const tt = (s: string) => t(`${prefix}.${s}`)
interface Props {
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/modal/FakeUsers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const { $msal: { signOut } } = useNuxtApp()
const { signIn } = useSignIn()
const { getMaybeMe, refreshMaybeMe } = useSession()
const prefix = 'ModalFakeUsers'
const prefix = 'components/modal/FakeUsers'
const tt = (s: string) => t(`${prefix}.${s}`)
// TODO(grady) move this to an env-specific location, omit the component if empty.
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/modal/PermissionDenied.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const router = useRouter()
const { t } = useI18n()
const localePath = useLocalePath()
const prefix = 'ModalPermissionDenied'
const prefix = 'components/modal/PermissionDenied'
const tt = (s: string) => t(`${prefix}.${s}`)
const navigateBack = () => {
Expand Down
Loading

0 comments on commit 7b73766

Please sign in to comment.