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 89 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 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
a3fe099
impl: add is_canceled to targets
kavos113 Nov 4, 2024
18465c9
impl: add reminder
kavos113 Nov 5, 2024
83be06e
fix: add migration
kavos113 Nov 5, 2024
0238851
feat: add is_anonymous to questionnaires
kavos113 Nov 5, 2024
11f351c
impl: add GetAnonymousRespondantDetails
kavos113 Nov 5, 2024
75d79a6
fix: add isAnonymous to tests
kavos113 Nov 5, 2024
4af03eb
fix: add db migration
kavos113 Nov 5, 2024
ce7cee4
impl: GetQuestionnaireMyRemindStatus
kavos113 Nov 5, 2024
0a92641
impl: add EditQuestionnaireRemindStatus
kavos113 Nov 5, 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
469e134
Merge branch 'fix/openapi' into fix/openapi-reminder
kavos113 Nov 8, 2024
f39b8ae
fix: remove GetAnonymousRespondantDetails
kavos113 Nov 9, 2024
44bda24
Merge branch 'fix/openapi' into fix/openapi-anonymous-response
kavos113 Nov 9, 2024
4c36179
fix: add is_anonymous to responsebody
kavos113 Nov 9, 2024
94d50da
Merge pull request #1282 from traPtitech/fix/openapi-delete_result_fo…
kaitoyama Nov 9, 2024
10a2f2e
Merge branch 'fix/openapi' into fix/openapi-anonymous-response
kaitoyama Nov 9, 2024
005db48
fix: prevent changing anonymous questionnaires to non-anonymous
Eraxyso Nov 10, 2024
4ae8961
fix: move questoinnaire_id from QuestionBase to Question as it is not…
Eraxyso Nov 11, 2024
e624d35
change status code
kaitoyama Nov 17, 2024
3639cb3
update spec
kaitoyama Dec 1, 2024
3278678
fix name
kaitoyama Dec 1, 2024
326fdee
Merge branch 'fix/openapi' into fix/openapi-anonymous-response
kaitoyama Dec 1, 2024
27edf87
Merge branch 'fix/openapi' into fix/openapi-reminder
kaitoyama Dec 1, 2024
eecf167
delete result controller
kaitoyama Dec 1, 2024
98d8c16
Merge pull request #1279 from traPtitech/fix/openapi-reminder
kaitoyama Dec 1, 2024
15150c7
Merge branch 'fix/openapi' into fix/openapi-anonymous-response
kaitoyama Dec 4, 2024
b934618
Merge pull request #1280 from traPtitech/fix/openapi-anonymous-response
kaitoyama Dec 4, 2024
02243ee
remove router
kaitoyama Dec 6, 2024
55a0dc5
wip introduce wire
kaitoyama Dec 6, 2024
f5708e1
fix GetQuestionnaireInfo
kaitoyama Dec 9, 2024
a183cb3
fix: add soring parameter for implementation and test of GetMyRespons…
Eraxyso Dec 10, 2024
76c285f
Merge pull request #1287 from traPtitech/fix/openapi-getmyresponseids…
kaitoyama Dec 12, 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
352 changes: 352 additions & 0 deletions controller/adapter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,352 @@
package controller

import (
"strconv"

"github.com/google/uuid"
"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 uuid.UUIDs) openapi.UsersAndGroups {
res := openapi.UsersAndGroups{
Users: users,
Groups: groups.Strings(),
}
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 []uuid.UUID, targetUsers []string, targetGroups []uuid.UUID, 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)
}

isAnonymous, err := model.NewQuestionnaire().GetResponseIsAnonymousByQuestionnaireID(ctx.Request().Context(), respondentDetail.QuestionnaireID)
if err != nil {
ctx.Logger().Errorf("failed to get response is anonymous: %+v", err)
return openapi.Response{}, err
}

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,
IsAnonymous: &isAnonymous,
}

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