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

openapiベースに変更 #1221

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
98c17ac
setup oapi codegen
kaitoyama May 3, 2024
76acd76
wip
kaitoyama May 5, 2024
7a7fc48
until deletequestionnaire
kaitoyama May 14, 2024
df97a1d
some api implmented
kaitoyama Jun 18, 2024
60007b8
chore: Update Go version to 1.22 in GitHub Actions workflow
kaitoyama Jun 18, 2024
7f74909
fix version number
kaitoyama Jun 18, 2024
a17788f
upgrade go version
kaitoyama Jun 18, 2024
b34ce6e
wip
kaitoyama Jun 22, 2024
2e96d61
feat: implement GetQuestionnaireResult
Eraxyso Jul 22, 2024
9733c31
feat: PostQuestionnaireResponse handler
kavos113 Aug 7, 2024
a26ceea
feat: Insert QuestionnaireResponse
kavos113 Aug 7, 2024
65d79f5
fix: add missing error response
kavos113 Aug 16, 2024
af155ec
feat: implement GetMyResponses(wip)
Eraxyso Aug 12, 2024
1b700da
feat: implement GetResponse
Eraxyso Aug 12, 2024
b092327
feat: implement DeleteResponse
Eraxyso Aug 25, 2024
63892f4
feat: implement GetMyResponses(complete)
Eraxyso Aug 28, 2024
e21b78d
fix: fix some errors, optimize some implementations and add existence…
Eraxyso Aug 28, 2024
3b6fad2
Merge pull request #1264 from traPtitech/fix/openapi-#1243
kaitoyama Aug 29, 2024
bd06106
style: add missing space
Eraxyso Aug 30, 2024
54e993d
style: format code
Eraxyso Aug 30, 2024
1878011
style: remove unused import
Eraxyso Aug 30, 2024
7cba992
fix: specify model of db request in functions respondents/GetMyRespon…
Eraxyso Sep 2, 2024
0421e8e
Merge pull request #1265 from traPtitech/fix/openapi-1
Eraxyso Sep 2, 2024
42cf45f
Merge remote-tracking branch 'origin/main' into fix/openapi
kaitoyama Sep 3, 2024
17018e4
refactor swagger and use type
kaitoyama Sep 3, 2024
ba21a4a
Merge remote-tracking branch 'origin/main' into fix/openapi
kaitoyama Sep 3, 2024
6418720
impl editresponse handler
kavos113 Sep 5, 2024
2a0e45e
impl: adapter between openapi.ResponseBody and struct to insert db
kavos113 Sep 12, 2024
4ca29b5
impl: edit response controller
kavos113 Sep 12, 2024
b93eea9
Merge pull request #1268 from traPtitech/fix/openapi-#1248
kavos113 Sep 20, 2024
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
344 changes: 344 additions & 0 deletions controller/adapter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
package controller

import (
"strconv"

"github.com/labstack/echo/v4"
"github.com/traPtitech/anke-to/model"
"github.com/traPtitech/anke-to/openapi"
"gopkg.in/guregu/null.v4"
)

func questionnaireInfo2questionnaireSummary(questionnaireInfo model.QuestionnaireInfo, allResponded bool, hasMyDraft bool, hasMyResponse bool, respondedDateTimeByMe null.Time) *openapi.QuestionnaireSummary {
res := openapi.QuestionnaireSummary{
AllResponded: allResponded,
CreatedAt: questionnaireInfo.CreatedAt,
Description: questionnaireInfo.Description,
HasMyDraft: hasMyDraft,
HasMyResponse: hasMyResponse,
// IsAllowingMultipleResponses: questionnaireInfo.IsAllowingMultipleResponses,
// IsAnonymous: questionnaireInfo.IsAnonymous,
// IsPublished: questionnaireInfo.IsPublished,
IsTargetingMe: questionnaireInfo.IsTargeted,
ModifiedAt: questionnaireInfo.ModifiedAt,
QuestionnaireId: questionnaireInfo.ID,
Title: questionnaireInfo.Title,
}
if respondedDateTimeByMe.Valid {
res.RespondedDateTimeByMe = &respondedDateTimeByMe.Time
} else {
res.RespondedDateTimeByMe = nil
}
if questionnaireInfo.ResTimeLimit.Valid {
res.ResponseDueDateTime = &questionnaireInfo.ResTimeLimit.Time
} else {
res.ResponseDueDateTime = nil
}
return &res
}

func convertResponseViewableBy(resShareType openapi.ResShareType) string {
switch resShareType {
case "admins":
return "administrators"
case "respondents":
return "respondents"
case "anyone":
return "public"
default:
return "administrators"
}
}

func convertResSharedTo(resSharedTo string) openapi.ResShareType {
switch resSharedTo {
case "administrators":
return "admins"
case "respondents":
return "respondents"
case "public":
return "anyone"
default:
return "admins"
}

}

func createUsersAndGroups(users []string, groups []string) openapi.UsersAndGroups {
res := openapi.UsersAndGroups{
Users: users,
Groups: groups,
}
return res
}

func convertOptions(options []model.Options) openapi.QuestionSettingsSingleChoice {
res := openapi.QuestionSettingsSingleChoice{}
for _, option := range options {
res.Options = append(res.Options, option.Body)
}
return res
}

func convertQuestions(questions []model.Questions) []openapi.Question {
res := []openapi.Question{}
for _, question := range questions {
q := openapi.Question{
CreatedAt: question.CreatedAt,
// Description: question.Description,
IsRequired: question.IsRequired,
QuestionId: question.ID,
QuestionnaireId: question.QuestionnaireID,
Title: question.Body,
}
switch question.Type {
case "Text":
q.FromQuestionSettingsText(
openapi.QuestionSettingsText{
QuestionType: "Text",
},
)
case "TextArea":
q.FromQuestionSettingsText(
openapi.QuestionSettingsText{
QuestionType: "TextLong",
},
)
case "Number":
q.FromQuestionSettingsNumber(
openapi.QuestionSettingsNumber{
QuestionType: "Number",
},
)
case "Radio":
q.FromQuestionSettingsSingleChoice(
openapi.QuestionSettingsSingleChoice{
QuestionType: "Radio",
Options: convertOptions(question.Options).Options,
},
)
case "MultipleChoice":
q.FromQuestionSettingsMultipleChoice(
openapi.QuestionSettingsMultipleChoice{
QuestionType: "MultipleChoice",
Options: convertOptions(question.Options).Options,
},
)
case "LinearScale":
q.FromQuestionSettingsScale(
openapi.QuestionSettingsScale{
QuestionType: "LinearScale",
MinLabel: &question.ScaleLabels[0].ScaleLabelLeft,
MaxLabel: &question.ScaleLabels[0].ScaleLabelRight,
MinValue: question.ScaleLabels[0].ScaleMin,
MaxValue: question.ScaleLabels[0].ScaleMax,
},
)
}
}
return res
}

func convertRespondents(respondents []model.Respondents) []string {
res := []string{}
for _, respondent := range respondents {
res = append(res, respondent.UserTraqid)
}
return res
}

func questionnaire2QuestionnaireDetail(questionnaires model.Questionnaires, adminUsers []string, adminGroups []string, targetUsers []string, targetGroups []string, respondents []string) openapi.QuestionnaireDetail {
res := openapi.QuestionnaireDetail{
Admins: createUsersAndGroups(adminUsers, adminGroups),
CreatedAt: questionnaires.CreatedAt,
Description: questionnaires.Description,
// IsAllowingMultipleResponses: questionnaires.IsAllowingMultipleResponses,
// IsAnonymous: questionnaires.IsAnonymous,
// IsPublished: questionnaires.IsPublished,
ModifiedAt: questionnaires.ModifiedAt,
QuestionnaireId: questionnaires.ID,
Questions: convertQuestions(questionnaires.Questions),
Respondents: respondents,
ResponseDueDateTime: &questionnaires.ResTimeLimit.Time,
ResponseViewableBy: convertResSharedTo(questionnaires.ResSharedTo),
Targets: createUsersAndGroups(targetUsers, targetGroups),
Title: questionnaires.Title,
}
return res
}

func respondentDetail2Response(ctx echo.Context, respondentDetail model.RespondentDetail) (openapi.Response, error) {
oResponseBodies := []openapi.ResponseBody{}
for j, r := range respondentDetail.Responses {
oResponseBody := openapi.ResponseBody{}
switch r.QuestionType {
case "Text":
if r.Body.Valid {
oResponseBody.FromResponseBodyText(
openapi.ResponseBodyText{
Answer: r.Body.String,
QuestionType: "Text",
},
)
}
case "TextArea":
if r.Body.Valid {
oResponseBody.FromResponseBodyText(
openapi.ResponseBodyText{
Answer: r.Body.String,
QuestionType: "TextLong",
},
)
}
case "Number":
if r.Body.Valid {
answer, err := strconv.ParseFloat(r.Body.String, 32)
if err != nil {
ctx.Logger().Errorf("failed to convert string to float: %+v", err)
return openapi.Response{}, err
}
oResponseBody.FromResponseBodyNumber(
openapi.ResponseBodyNumber{
Answer: float32(answer),
QuestionType: "Number",
},
)
}
case "MultipleChoice":
if r.Body.Valid {
answer := []int{}
questionnaire, _, _, _, _, _, err := model.NewQuestionnaire().GetQuestionnaireInfo(ctx.Request().Context(), r.QuestionID)
if err != nil {
ctx.Logger().Errorf("failed to get questionnaire info: %+v", err)
return openapi.Response{}, err
}
for _, a := range r.OptionResponse {
for i, o := range questionnaire.Questions[j].Options {
if a == o.Body {
answer = append(answer, i)
}
}
}
oResponseBody.FromResponseBodyMultipleChoice(
openapi.ResponseBodyMultipleChoice{
Answer: answer,
QuestionType: "MultipleChoice",
},
)
}
case "Checkbox":
if r.Body.Valid {
questionnaire, _, _, _, _, _, err := model.NewQuestionnaire().GetQuestionnaireInfo(ctx.Request().Context(), r.QuestionID)
if err != nil {
ctx.Logger().Errorf("failed to get questionnaire info: %+v", err)
return openapi.Response{}, err
}
for _, a := range r.OptionResponse {
for i, o := range questionnaire.Questions[j].Options {
if a == o.Body {
oResponseBody.FromResponseBodySingleChoice(
openapi.ResponseBodySingleChoice{
Answer: i,
QuestionType: "SingleChoice",
},
)
}
}
}
}
case "LinearScale":
if r.Body.Valid {
answer, err := strconv.Atoi(r.Body.String)
if err != nil {
ctx.Logger().Errorf("failed to convert string to int: %+v", err)
return openapi.Response{}, err
}
oResponseBody.FromResponseBodyScale(
openapi.ResponseBodyScale{
Answer: answer,
QuestionType: "LinearScale",
},
)
}
}
oResponseBodies = append(oResponseBodies, oResponseBody)
}

res := openapi.Response{
Body: oResponseBodies,
IsDraft: respondentDetail.SubmittedAt.Valid,
ModifiedAt: respondentDetail.ModifiedAt,
QuestionnaireId: respondentDetail.QuestionnaireID,
Respondent: respondentDetail.TraqID,
ResponseId: respondentDetail.ResponseID,
SubmittedAt: respondentDetail.SubmittedAt.Time,
}

return res, nil
}

func responseBody2ResponseMetas(body []openapi.ResponseBody, questions []model.Questions) ([]*model.ResponseMeta, error) {
res := []*model.ResponseMeta{}

for i, b := range body {
switch questions[i].Type {
case "Text":
bText, err := b.AsResponseBodyText()
if err != nil {
return nil, err
}
res = append(res, &model.ResponseMeta{
QuestionID: questions[i].ID,
Data: bText.Answer,
})
case "TextLong":
bTextLong, err := b.AsResponseBodyTextLong()
if err != nil {
return nil, err
}
res = append(res, &model.ResponseMeta{
QuestionID: questions[i].ID,
Data: bTextLong.Answer,
})
case "Number":
bNumber, err := b.AsResponseBodyNumber()
if err != nil {
return nil, err
}
res = append(res, &model.ResponseMeta{
QuestionID: questions[i].ID,
Data: strconv.FormatFloat(float64(bNumber.Answer), 'f', -1, 32),
})
case "SingleChoice":
bSingleChoice, err := b.AsResponseBodySingleChoice()
if err != nil {
return nil, err
}
res = append(res, &model.ResponseMeta{
QuestionID: questions[i].ID,
Data: strconv.FormatInt(int64(bSingleChoice.Answer), 10),
})
case "MultipleChoice":
bMultipleChoice, err := b.AsResponseBodyMultipleChoice()
if err != nil {
return nil, err
}
for _, a := range bMultipleChoice.Answer {
res = append(res, &model.ResponseMeta{
QuestionID: questions[i].ID,
Data: strconv.FormatInt(int64(a), 10),
})
}
case "LinearScale":
bScale, err := b.AsResponseBodyScale()
if err != nil {
return nil, err
}
res = append(res, &model.ResponseMeta{
QuestionID: questions[i].ID,
Data: strconv.FormatInt(int64(bScale.Answer), 10),
})
}
}
return res, nil
}
Loading
Loading