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 60 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 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
91b0006
impl: insert validation when post questionnaire
kavos113 Sep 27, 2024
438b855
impl: update validations when edit questionnaire
kavos113 Sep 27, 2024
ae23e2f
fix: regex pattern validation for text
kavos113 Sep 28, 2024
88041f4
impl: check validation when post questionnaire response
kavos113 Sep 28, 2024
206a691
impl: check validation when edit response
kavos113 Sep 28, 2024
4758c6e
fix: PostQuestionnaire response 200 -> 201
kavos113 Oct 10, 2024
511b40c
fix: return 404 at GetQuestionnaire
kavos113 Oct 11, 2024
9eccbbf
fix: return 404 at GetQuestionnaireResponses
kavos113 Oct 11, 2024
bc1b71e
fix: return 404 at GetQuestionnaireResult
kavos113 Oct 11, 2024
674e25a
fix: return 404, 500 at GetResponse
kavos113 Oct 14, 2024
dc54c0d
fix: return 404, 405, 500 at EditResponse
kavos113 Oct 14, 2024
06cee26
fix: return 404, 405, 500 at DeleteResponse
kavos113 Oct 14, 2024
a69191b
Merge pull request #1274 from traPtitech/fix/openapi-statuscode
kavos113 Oct 17, 2024
5680dba
Merge pull request #1272 from traPtitech/fix/openapi-#1269
kaitoyama Oct 21, 2024
93705a0
impl: add IsPublished in questionnaires
kavos113 Oct 24, 2024
6f70f2d
impl: isPublished in questionnaires controller
kavos113 Oct 24, 2024
58d8bd2
fix: update test
kavos113 Oct 25, 2024
420479a
impl:db migration
kavos113 Oct 29, 2024
b9a1da8
feat: implement middleware
Eraxyso Oct 29, 2024
4ec607e
Merge pull request #1277 from traPtitech/fix/openapi-middleware
Eraxyso Oct 31, 2024
c2da3b4
Merge branch 'fix/openapi' into fix/openapi-questionnaire_draft
Eraxyso Oct 31, 2024
770fe38
feat: add middleware for checking questionnaire read permission
Eraxyso Oct 31, 2024
c6e7460
Merge pull request #1276 from traPtitech/fix/openapi-questionnaire_draft
Eraxyso Nov 2, 2024
ff2b2cf
Merge branch 'main' into fix/openapi
kaitoyama Nov 8, 2024
1963558
synchronize openapi schema
kaitoyama Nov 8, 2024
1cc2744
delete result endpoint
kaitoyama Nov 8, 2024
1018409
fix: delete function in handler for result
Eraxyso Nov 8, 2024
9a438ca
fix: update usage of Response.Respondent to handle its type change to…
Eraxyso Nov 8, 2024
94d50da
Merge pull request #1282 from traPtitech/fix/openapi-delete_result_fo…
kaitoyama Nov 9, 2024
4ae8961
fix: move questoinnaire_id from QuestionBase to Question as it is not…
Eraxyso Nov 11, 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