Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADD] ZARS-701 change text editor #36

Merged
merged 4 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,43 @@ declare module 'vue' {
DizMemberDetails: typeof import('./src/components/Proposals/Details/DizMemberDetails.vue')['default']
DocumentList: typeof import('./src/components/Proposals/Details/DocumentList.vue')['default']
EditProfileDialog: typeof import('./src/components/EditProfileDialog.vue')['default']
ElAside: typeof import('element-plus/es')['ElAside']
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElHeader: typeof import('element-plus/es')['ElHeader']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
ElMain: typeof import('element-plus/es')['ElMain']
ElOption: typeof import('element-plus/es')['ElOption']
ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSpace: typeof import('element-plus/es')['ElSpace']
ElStep: typeof import('element-plus/es')['ElStep']
ElSteps: typeof import('element-plus/es')['ElSteps']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTag: typeof import('element-plus/es')['ElTag']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElUpload: typeof import('element-plus/es')['ElUpload']
FdpgCheckbox: typeof import('./src/components/FdpgCheckbox.vue')['default']
FdpgCheckList: typeof import('./src/components/FdpgCheckList.vue')['default']
FdpgCheckNotes: typeof import('./src/components/FdpgCheckNotes.vue')['default']
Expand Down Expand Up @@ -57,6 +90,7 @@ declare module 'vue' {
FdpgStep: typeof import('./src/components/FdpgStep.vue')['default']
FdpgTable: typeof import('./src/components/FdpgTable.vue')['default']
FdpgTableDueDateRow: typeof import('./src/components/FdpgTableDueDateRow.vue')['default']
FdpgTextEditor: typeof import('./src/components/FdpgTextEditor.vue')['default']
FdpgUpload: typeof import('./src/components/FdpgUpload.vue')['default']
ImageList: typeof import('./src/components/Proposals/Details/ImageList.vue')['default']
InitiateContractDialog: typeof import('./src/components/InitiateContractDialog.vue')['default']
Expand Down Expand Up @@ -97,8 +131,12 @@ declare module 'vue' {
SignDialog: typeof import('./src/components/SignDialog.vue')['default']
TaskViewer: typeof import('./src/components/TaskViewer/TaskViewer.vue')['default']
TermsDialog: typeof import('./src/components/TermsDialog.vue')['default']
TextEditor: typeof import('./src/components/Shared/TextEditor.vue')['default']
UacAcceptProposalDialog: typeof import('./src/components/UacAcceptProposalDialog.vue')['default']
UacMemberDetails: typeof import('./src/components/Proposals/Details/UacMemberDetails.vue')['default']
ViewReportDialog: typeof import('./src/components/ViewReportDialog.vue')['default']
}
export interface ComponentCustomProperties {
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@braintree/sanitize-url": "^7.1.0",
"@fortawesome/fontawesome-free": "^6.7.1",
"@headlessui/vue": "^1.7.23",
"@vueup/vue-quill": "^1.2.0",
"@vueuse/core": "^12.0.0",
"axios": "^1.7.8",
"bootstrap-icons": "^1.11.3",
Expand Down
11 changes: 3 additions & 8 deletions src/components/DeclineDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
<p>{{ $t(description) }}</p>

<FdpgLabel html-for="proposal.declineReasonLabel" />
<FdpgInput
<FdpgTextEditor
v-model="declineReason"
data-testId="declineReason"
placeholder="proposal.declineReasonPlaceholder"
type="textarea"
:rows="2"
autosize
:placeholder="$t('proposal.declineReasonPlaceholder')"
/>
</div>

Expand Down Expand Up @@ -39,9 +36,8 @@ import { ref } from 'vue'
import type { TranslationSchema } from '@/plugins/i18n'
import { useVModel } from '@vueuse/core'
import FdpgLabel from './FdpgLabel.vue'
import FdpgInput from './FdpgInput.vue'
import FdpgTextEditor from './FdpgTextEditor.vue'
import FdpgDialog from './FdpgDialog.vue'

const emit = defineEmits(['update:modelValue', 'confirm'])

const props = defineProps({
Expand All @@ -67,7 +63,6 @@ const props = defineProps({
})

const declineReason = ref<string | undefined>(undefined)

const dialogOpen = useVModel(props, 'modelValue', emit)
const closeDialog = () => {
declineReason.value = undefined
Expand Down
22 changes: 9 additions & 13 deletions src/components/FdpgCheckNotes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@
<h2>{{ $t('proposal.fdpgCheckNotes') }}</h2>
</div>
<div v-if="isEditMode">
<FdpgInput
v-model="fdpgCheckNotes"
placeholder="proposal.checkNotesPlaceHolder"
:size="FdpgInputSize.Small"
type="textarea"
:rows="2"
autosize
/>
<FdpgTextEditor v-model="fdpgCheckNotes" :placeholder="$t('proposal.checkNotesPlaceHolder')"></FdpgTextEditor>
<el-button class="button__margin" type="primary" @click="sendFdpgCheckNotes">{{ $t('general.save') }}</el-button>
</div>
<div class="check-note-content" v-else>
Expand All @@ -22,16 +15,15 @@
</template>

<script setup lang="ts">
import FdpgInput from './FdpgInput.vue'
import { computed, ref } from 'vue'
import { useRoute } from 'vue-router'
import { useProposalStore } from '@/stores/proposal/proposal.store'
import { useAuthStore } from '@/stores/auth/auth.store'
import { Role } from '@/types/oidc.types'
import { FdpgInputSize } from '@/types/component.types'
import useNotifications from '@/composables/use-notifications'
import { useI18n } from 'vue-i18n'
import { ProposalStatus } from '@/types/proposal.types'
import FdpgTextEditor from './FdpgTextEditor.vue'

const { t } = useI18n()
const { params } = useRoute()
Expand All @@ -44,11 +36,15 @@ const sendFdpgCheckNotes = async () => {
try {
await proposalStore.updateFdpgCheckNotes(proposalId, fdpgCheckNotes.value)
showSuccessMessage(t('general.submitted'))
} catch(error:any ) {
} catch (error: any) {
showErrorMessage(error.message)
}
}
const isEditMode = computed(() => (authStore.singleKnownRole === Role.FdpgMember && proposalStore?.currentProposal?.status === ProposalStatus.FdpgCheck))
const isEditMode = computed(
() =>
authStore.singleKnownRole === Role.FdpgMember &&
proposalStore?.currentProposal?.status === ProposalStatus.FdpgCheck,
)
</script>

<style lang="scss" scoped>
Expand All @@ -58,4 +54,4 @@ const isEditMode = computed(() => (authStore.singleKnownRole === Role.FdpgMember
.check-note-content {
white-space: pre-line;
}
</style>
</style>
3 changes: 1 addition & 2 deletions src/components/FdpgCommentCreator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
}}</span>
</h5>
</div>
<div class="comment-card-body">
{{ comment.content }}
<div class="comment-card-body" v-html="comment.content">
</div>
<div class="comment-card-actions">
<div class="left">
Expand Down
14 changes: 2 additions & 12 deletions src/components/FdpgCommentForm.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
<template>
<FdpgInput
ref="inputRef"
v-model="comment"
placeholder="proposal.leaveAComment"
:size="FdpgInputSize.Small"
type="textarea"
:rows="2"
autosize
/>

<FdpgTextEditor v-model="comment" ref="inputRef" :placeholder="$t('proposal.leaveAComment')"></FdpgTextEditor>
<section role="region" class="action-row">
<div class="comment-field-actions">
<el-button
Expand Down Expand Up @@ -37,8 +28,7 @@
</template>

<script setup lang="ts">
import FdpgInput from '@/components/FdpgInput.vue'
import { FdpgInputSize } from '@/types/component.types'
import FdpgTextEditor from '@/components/FdpgTextEditor.vue'
import { useVModel } from '@vueuse/core'
import LocationSelect from '@/components/LocationSelect.vue'
import { useAuthStore } from '@/stores/auth/auth.store'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="header">
<div class="title-wrapper">
<h5 class="title">{{ $t(panel.header) }}{{ !loading ? ` (${proposals.length})` : '' }}</h5>
<div v-loading="loading" />
<div v-loading="loading"></div>
</div>
<div class="action-wrapper">
<el-button
Expand Down Expand Up @@ -88,7 +88,6 @@ const props = defineProps({
default: SortDirection.ASC,
},
})

const displayCount = ref<number>(props.defaultLength)
const loading = ref<boolean>(false)

Expand Down
59 changes: 59 additions & 0 deletions src/components/FdpgTextEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<div class="w-full">
<QuillEditor
theme="snow"
v-model:content="value"
contentType="html"
ref="textEditor"
:options="options"
:enable="!props.disabled"
:readOnly="props.disabled"
:placeholder="placeholder"
/>
</div>
</template>
<script setup lang="ts">
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import { computed, onBeforeMount, ref, watch } from 'vue'
const props = defineProps({
modelValue: String,
disabled: Boolean,
placeholder: String,
})
const emit = defineEmits(['update:modelValue'])

const textEditor = ref()
defineExpose({
textEditor,
})

const value = computed<string | null>({
get() {
return props.modelValue || null
},
set(val) {
emit('update:modelValue', val)
},
})
const options = ref({})
const placeholder = ref<string | undefined>('')

watch(
() => props.modelValue,
(newValue) => {
if (newValue === '') {
textEditor.value.setContents(null)
}
},
)

onBeforeMount(() => {
placeholder.value = !props.disabled ? props.placeholder : ''
})
</script>
<style>
.w-full {
width: 100%;
}
</style>
14 changes: 2 additions & 12 deletions src/components/MessageCenterAnswerCreator.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
<template>
<section class="answer-creator">
<FdpgInput
ref="inputRef"
v-model="answerContent"
placeholder="proposal.leaveAComment"
:size="FdpgInputSize.Small"
type="textarea"
:rows="2"
autosize
/>
<FdpgTextEditor ref="inputRef" v-model="answerContent" :placeholder="$t('proposal.leaveAComment')" />

<section role="region" class="action-row">
<div class="comment-field-actions">
Expand All @@ -34,12 +26,11 @@
</template>

<script setup lang="ts">
import FdpgInput from '@/components/FdpgInput.vue'
import FdpgTextEditor from '@/components/FdpgTextEditor.vue'
import type { IVisibilityMessage } from '@/composables/use-location-visibility'
import useLocationVisibility from '@/composables/use-location-visibility'
import { useAuthStore } from '@/stores/auth/auth.store'
import type { CommentType, ICommentDetail, ICreateAnswer } from '@/types/comment.interface'
import { FdpgInputSize } from '@/types/component.types'
import { MiiLocation } from '@/types/location.enum'
import { Role } from '@/types/oidc.types'
import type { PropType } from 'vue'
Expand All @@ -65,7 +56,6 @@ const authStore = useAuthStore()
const locationSelection = ref<MiiLocation[]>([])
const answerContent = ref<string>()
const inputRef = ref()

const emit = defineEmits(['toggleAnswerMode', 'createAnswer'])

const toggleAnswerMode = (value: boolean) => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/MessageCenterItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</template>
</div>

<div class="message-content">{{ message.content }}</div>
<div class="message-content" v-html="message.content"></div>

<section v-if="couldAnswer || authStore.singleKnownRole === Role.FdpgMember" role="region">
<el-button v-if="couldAnswer" link :disabled="isAnswerMode" @click="toggleAnswerMode(true)">
Expand Down
2 changes: 1 addition & 1 deletion src/components/ProjectReports.vue
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const handleDeleteReport = (event: Event, proposalId: string) => {
callback: async (decision: DecisionType) => (decision === 'confirm' ? await deleteReport(proposalId) : undefined),
})
}
const deleteReport = async (reportId) => {
const deleteReport = async (reportId: string) => {
try {
await proposalStore.deleteReport(proposalId.value, reportId)
} catch (error) {
Expand Down
6 changes: 3 additions & 3 deletions src/components/ReportDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
<el-col :sm="24">
<FdpgFormItem prop="content">
<FdpgLabel html-for="proposal.text" />
<FdpgInput
<FdpgtextEditor
v-model="report.content"
type="textarea"
data-testId="report.content"
placeholder="proposal.reportContentPlaceholder"
:placeholder="$t('proposal.reportContentPlaceholder')"
/>
</FdpgFormItem>
</el-col>
Expand Down Expand Up @@ -86,6 +85,7 @@ import FdpgFormItem from './FdpgFormItem.vue'
import FdpgInput from './FdpgInput.vue'
import FdpgLabel from './FdpgLabel.vue'
import FdpgUpload from './FdpgUpload.vue'
import FdpgtextEditor from './FdpgTextEditor.vue'

const { showErrorMessage } = useNotifications()
const ReportFormRef: Ref<typeof ElForm | undefined> = ref<typeof ElForm>()
Expand Down
11 changes: 8 additions & 3 deletions src/components/Shared/DefinitionCardItem.vue
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
<template>
<template v-if="value === undefined"> - </template>
<template v-else-if="definition.kind === 'translatable'">
{{ $t(`${definition.prefix}${value}`) }}
{{ t(`${definition.prefix}${value}`) }}
</template>

<template v-else-if="definition.kind === 'date'">
{{ getLocaleDateString(value as string | Date) }}
</template>

<template v-else-if="definition.kind === 'boolean'">
{{ $t(`${definition[value as string]}`) }}
{{ t(`${definition[value as string]}`) }}
</template>

<template v-else-if="definition.kind === 'lookup'">
{{ definition.lookupMap[value as string][definition.lookupKey] }}
</template>

<template v-else>{{ value }}</template>
<template v-else>
<div v-html="value"></div>
</template>
</template>

<script setup lang="ts">
import type { Definitions } from '@/components/Shared/definition-card.types'
import type { PropType } from 'vue'
import { getLocaleDateString } from '@/utils/date.util'
import { useI18n } from 'vue-i18n'

defineProps({
value: {
Expand All @@ -34,4 +37,6 @@ defineProps({
required: true,
},
})

const { t } = useI18n()
</script>
Loading
Loading