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

feat(shared-types): move core, FormFeedback related types to root shared folder #2394

Merged
merged 5 commits into from
Jul 27, 2021
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
12 changes: 12 additions & 0 deletions shared/types/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface ErrorDto {
message: string
}

export interface SuccessMessageDto {
message: string
}

export interface PrivateFormErrorDto extends ErrorDto {
isPageFound: true
formTitle: string
}
43 changes: 43 additions & 0 deletions shared/types/form/form_feedback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Merge } from 'type-fest'
import { DateString } from '../generic'
import { FormDto } from './form'

export type SubmitFormFeedbackBodyDto = {
isPreview?: boolean
rating: number
comment?: string
}

/**
* Typing for individual form feedback
*/
export type FormFeedbackBase = {
rating: number
comment?: string
formId: FormDto['_id']
created?: Date
lastModified?: Date
}

// Convert to serialized version.
export type FormFeedbackDto = Merge<
FormFeedbackBase,
{ created?: DateString; lastModified?: DateString }
>

export type ProcessedFeedbackMeta = {
index: number
timestamp: number
rating: number
comment: string
// Note that this date is not a DateString, it is actually "D MMM YYYY"
// format.
date: string
dateShort: string
}

export type FormFeedbackMetaDto = {
average?: string
count: number
feedback: ProcessedFeedbackMeta[]
}
4 changes: 2 additions & 2 deletions src/app/modules/feedback/__tests__/feedback.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import getFormFeedbackModel from 'src/app/models/form_feedback.server.model'

import dbHandler from 'tests/unit/backend/helpers/jest-db'

import { GetFormFeedbackDto } from '../../../../types/api/form_feedback'
import { FormFeedbackMetaDto } from '../../../../types/api/form_feedback'
import { DatabaseError } from '../../core/core.errors'
import * as FeedbackService from '../feedback.service'

Expand Down Expand Up @@ -201,7 +201,7 @@ describe('feedback.service', () => {
const actualResult = await FeedbackService.getFormFeedbacks(mockFormId)

// Assert
const expectedResult: GetFormFeedbackDto = {
const expectedResult: FormFeedbackMetaDto = {
count: 1,
average: '3.00',
feedback: [
Expand Down
8 changes: 4 additions & 4 deletions src/app/modules/feedback/feedback.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import mongoose from 'mongoose'
import { ResultAsync } from 'neverthrow'

import { IFormFeedbackSchema } from '../../../types'
import { GetFormFeedbackDto } from '../../../types/api/form_feedback'
import { ProcessedFeedback } from '../../../types/form_feedback'
import { FormFeedbackMetaDto } from '../../../types/api/form_feedback'
import { ProcessedFeedbackMeta } from '../../../types/form_feedback'
import { createLoggerWithLabel } from '../../config/logger'
import getFormFeedbackModel from '../../models/form_feedback.server.model'
import { getMongoErrorMessage } from '../../utils/handle-mongo-error'
Expand Down Expand Up @@ -61,7 +61,7 @@ export const getFormFeedbackStream = (
*/
export const getFormFeedbacks = (
formId: string,
): ResultAsync<GetFormFeedbackDto, DatabaseError> => {
): ResultAsync<FormFeedbackMetaDto, DatabaseError> => {
return ResultAsync.fromPromise(
FormFeedbackModel.find({ formId }).sort({ created: 1 }).exec(),
(error) => {
Expand Down Expand Up @@ -89,7 +89,7 @@ export const getFormFeedbacks = (
let totalRating = 0
const processedFeedback = feedbacks.map((fb, idx) => {
totalRating += fb.rating
const response: ProcessedFeedback = {
const response: ProcessedFeedbackMeta = {
// 1-based indexing.
index: idx + 1,
timestamp: moment(fb.created).valueOf(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import {
FieldCreateDto,
FieldUpdateDto,
} from 'src/types/api'
import { GetFormFeedbackDto } from 'src/types/api/form_feedback'
import { FormFeedbackMetaDto } from 'src/types/api/form_feedback'

import {
generateDefaultField,
Expand Down Expand Up @@ -2421,7 +2421,7 @@ describe('admin-form.controller', () => {
it('should return 200 with feedback response successfully', async () => {
// Arrange
const mockRes = expressHandler.mockResponse()
const expectedFormFeedback: GetFormFeedbackDto = {
const expectedFormFeedback: FormFeedbackMetaDto = {
count: 212,
feedback: [
{
Expand Down
15 changes: 9 additions & 6 deletions src/app/modules/form/admin-form/admin-form.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
FieldCreateDto,
FieldUpdateDto,
FormDto,
FormFeedbackMetaDto,
FormFieldDto,
FormUpdateParams,
PermissionsUpdateDto,
Expand Down Expand Up @@ -590,9 +591,10 @@ export const handleCountFormSubmissions = [
* @returns 422 when user in session cannot be retrieved from the database
* @returns 500 when database error occurs
*/
export const handleCountFormFeedback: ControllerHandler<{
formId: string
}> = async (req, res) => {
export const handleCountFormFeedback: ControllerHandler<
{ formId: string },
number | ErrorDto
> = async (req, res) => {
const { formId } = req.params
const sessionUserId = (req.session as Express.AuthedSession).user._id

Expand Down Expand Up @@ -733,9 +735,10 @@ export const handleStreamFormFeedback: ControllerHandler<{
* @returns 422 when user in session cannot be retrieved from the database
* @returns 500 when database error occurs
*/
export const handleGetFormFeedback: ControllerHandler<{
formId: string
}> = (req, res) => {
export const handleGetFormFeedback: ControllerHandler<
{ formId: string },
FormFeedbackMetaDto | ErrorDto
> = (req, res) => {
const { formId } = req.params
const sessionUserId = (req.session as Express.AuthedSession).user._id

Expand Down
4 changes: 2 additions & 2 deletions src/public/modules/forms/helpers/FeedbackCsvGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import moment from 'moment-timezone'

import { FormFeedbackResponseDto } from '../../../../types/api/form_feedback'
import { FormFeedbackDto } from '../../../../../shared/types/form/form_feedback'

import { CsvGenerator } from './CsvGenerator'

Expand All @@ -16,7 +16,7 @@ export class FeedbackCsvGenerator extends CsvGenerator {
/**
* Generate a string representing a form feedback CSV line record
*/
addLineFromFeedback(feedback: FormFeedbackResponseDto) {
addLineFromFeedback(feedback: FormFeedbackDto) {
const createdAt = moment(feedback.created)
.tz('Asia/Singapore')
.format('DD MMM YYYY hh:mm:ss A')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ObjectId } from 'bson'
import moment from 'moment-timezone'

import { FormFeedbackResponseDto } from '../../../../../types/api/form_feedback'
import { FormFeedbackDto } from '../../../../../../shared/types/form/form_feedback'
import { DateString } from '../../../../../../shared/types/generic'
import { FeedbackCsvGenerator } from '../FeedbackCsvGenerator'

describe('FeedbackCsvGenerator', () => {
Expand All @@ -21,12 +22,14 @@ describe('FeedbackCsvGenerator', () => {
it('should add line successfully if created and lastmodified dates are provided', () => {
// Arrange
const feedbackCsv = new FeedbackCsvGenerator(1)
const feedback: FormFeedbackResponseDto = {
const feedback: FormFeedbackDto = {
rating: 3,
comment: 'some comment',
formId: new ObjectId().toHexString(),
created: new Date('2019-11-05T13:12:14'),
lastModified: new Date('2019-11-05T13:12:14'),
created: new Date('2019-11-05T13:12:14').toISOString() as DateString,
lastModified: new Date(
'2019-11-05T13:12:14',
).toISOString() as DateString,
}
const insertedCreatedDate = moment(feedback.created)
.tz('Asia/Singapore')
Expand All @@ -47,7 +50,7 @@ describe('FeedbackCsvGenerator', () => {
it('should add line successfully if comment, created and lastmodified dates are not provided', () => {
// Arrange
const feedbackCsv = new FeedbackCsvGenerator(1)
const feedback: FormFeedbackResponseDto = {
const feedback: FormFeedbackDto = {
rating: 3,
formId: new ObjectId().toHexString(),
}
Expand Down
23 changes: 12 additions & 11 deletions src/public/services/FormFeedbackService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import axios from 'axios'

import { SuccessMessageDto } from '../../../shared/types/core'
import {
FormFeedbackPostDto,
FormFeedbackResponseDto,
GetFormFeedbackDto,
} from '../../types/api/form_feedback'
FormFeedbackDto,
FormFeedbackMetaDto,
SubmitFormFeedbackBodyDto,
} from '../../../shared/types/form/form_feedback'
import { FeedbackCsvGenerator } from '../modules/forms/helpers/FeedbackCsvGenerator'

// Exported for testing
Expand All @@ -15,14 +16,14 @@ export const ADMIN_FORM_ENDPOINT = '/api/v3/admin/forms'
* Post feedback for a given form.
* @param formId the id of the form to post feedback for
* @param feedbackToPost object containing the feedback
* @returns the posted feedback
* @returns success message
*/
export const postFeedback = async (
formId: string,
feedbackToPost: FormFeedbackPostDto,
): Promise<FormFeedbackResponseDto> => {
feedbackToPost: SubmitFormFeedbackBodyDto,
): Promise<SuccessMessageDto> => {
return axios
.post<FormFeedbackResponseDto>(
.post<SuccessMessageDto>(
`${PUBLIC_FORM_ENDPOINT}/${formId}/feedback`,
feedbackToPost,
)
Expand All @@ -36,9 +37,9 @@ export const postFeedback = async (
*/
export const getFeedback = async (
formId: string,
): Promise<GetFormFeedbackDto> => {
): Promise<FormFeedbackMetaDto> => {
return axios
.get<GetFormFeedbackDto>(`${ADMIN_FORM_ENDPOINT}/${formId}/feedback`)
.get<FormFeedbackMetaDto>(`${ADMIN_FORM_ENDPOINT}/${formId}/feedback`)
.then(({ data }) => data)
}

Expand All @@ -65,7 +66,7 @@ export const downloadFeedback = async (
const expectedNumResponses = await countFeedback(formId)

return axios
.get<FormFeedbackResponseDto[]>(
.get<FormFeedbackDto[]>(
`${ADMIN_FORM_ENDPOINT}/${formId}/feedback/download`,
)
.then(({ data }) => {
Expand Down
9 changes: 1 addition & 8 deletions src/types/api/core.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
export interface ErrorDto {
message: string
}

export interface PrivateFormErrorDto extends ErrorDto {
isPageFound: true
formTitle: string
}
export * from '../../../shared/types/core'
22 changes: 1 addition & 21 deletions src/types/api/form_feedback.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1 @@
import { ProcessedFeedback } from '../form_feedback'

export type FormFeedbackPostDto = {
isPreview?: boolean
rating: number
comment?: string
}

export type FormFeedbackResponseDto = {
rating: number
comment?: string
formId: string
created?: Date
lastModified?: Date
}

export type GetFormFeedbackDto = {
average?: string
count: number
feedback: ProcessedFeedback[]
}
export { FormFeedbackMetaDto } from '../../../shared/types/form/form_feedback'
1 change: 1 addition & 0 deletions src/types/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from './examples'
export * from './encrypt_submission'
export * from './email_submission'
export * from './submission'
export * from './form_feedback'
28 changes: 8 additions & 20 deletions src/types/form_feedback.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
import { Document, Model, QueryCursor } from 'mongoose'
import { Merge } from 'type-fest'

import { FormFeedbackBase } from '../../shared/types/form/form_feedback'

import { IFormSchema } from './form'

export type ProcessedFeedback = {
index: number
timestamp: number
rating: number
comment: string
date: string
dateShort: string
}
export { ProcessedFeedbackMeta } from '../../shared/types/form/form_feedback'

export interface IFormFeedback {
formId: IFormSchema['_id']
rating: number
comment?: string
}
export type IFormFeedback = Merge<
FormFeedbackBase,
{ formId: IFormSchema['_id'] }
>
export interface IFormFeedbackSchema extends IFormFeedback, Document {
created?: Date
lastModified?: Date
Expand All @@ -26,13 +21,6 @@ export interface IFormFeedbackDocument extends IFormFeedbackSchema {
lastModified: Date
}

export interface IFormFeedbackSchema extends Document, IFormFeedback {}

export interface IFormFeedbackDoc extends IFormFeedbackSchema {
lastModified: Date
created: Date
}

export interface IFormFeedbackModel extends Model<IFormFeedbackSchema> {
/**
* Returns a cursor for all feedback for the form with formId.
Expand Down