Skip to content

Commit

Permalink
Merge branch 'frontend-react' of https://github.com/mraron/njudge int…
Browse files Browse the repository at this point in the history
…o frontend-react
  • Loading branch information
dbence2002 committed Sep 25, 2023
2 parents 1047d89 + 8e3a7d5 commit bcd9f2d
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 59 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/concrete/table/SubmissionTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ function TestCase0({ testCase, index }) {
}

function SubmissionTable0({ status }) {
const testCases = status.groups[0].testCases;
const testCasesContent = testCases.map((testCase, index) => (
const testCases = status.groups?.[0].testCases;
const testCasesContent = testCases?.map((testCase, index) => (
<div className="mb-3">
<TestCase0 testCase={testCase} index={index} key={index} />
</div>
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/problem/ProblemStatement.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ function ProblemAttachment({ type, name, href }) {
const { t } = useTranslation();
return (
<li>
<Link
<a
className="link no-underline flex items-start my-0.5"
to={href}>
href={`http://localhost:5555${href}`} download>
{type === "file" && (
<SVGAttachmentFile cls="w-5 h-5 mr-2 shrink-0" />
)}
Expand All @@ -212,7 +212,7 @@ function ProblemAttachment({ type, name, href }) {
: t("problem_statement.file")}
&nbsp;({name})
</span>
</Link>
</a>
</li>
);
}
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/pages/profile/ProfileSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import UserContext from "../../contexts/user/UserContext";

function PasswordChangeFrame() {
const { t } = useTranslation();
const { user } = useParams();
const [oldPw, setOldPw] = useState("");
const [newPw, setNewPw] = useState("");
const [newPwConfirm, setNewPwConfirm] = useState("");
Expand All @@ -26,7 +27,7 @@ function PasswordChangeFrame() {
/>
);
const handleChangePassword = async () => {
changePassword(oldPw, newPw, newPwConfirm).then((resp) => {
changePassword(user, oldPw, newPw, newPwConfirm).then((resp) => {
if (resp.success) {
window.flash("flash.successful_password_change", "success");
} else {
Expand Down Expand Up @@ -78,6 +79,7 @@ function PasswordChangeFrame() {

function OtherSettingsFrame({ data }) {
const { t } = useTranslation();
const { user } = useParams();
const [showUnsolved, setShowUnsolved] = useState(data.showUnsolved);
const [hideSolved, setHideSolved] = useState(data.hideSolved);
const titleComponent = (
Expand All @@ -87,7 +89,7 @@ function OtherSettingsFrame({ data }) {
/>
);
const handleSaveSettings = async () => {
saveSettings(showUnsolved, hideSolved).then((resp) => {
saveSettings(user, showUnsolved, hideSolved).then((resp) => {
if (resp.success) {
window.flash(t("flash.successful_settings_save"), "success");
} else {
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/util/settings.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export async function saveSettings(showUnsolved, hideSolved) {
export async function saveSettings(user, showUnsolved, hideSolved) {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
Expand All @@ -8,14 +8,14 @@ export async function saveSettings(showUnsolved, hideSolved) {
}),
};
const response = await fetch(
"/api/v2/user/profile/save_settings/other/",
`/api/v2/user/profile/${user}/settings/other/`,
requestOptions,
);
const data = await response.json();
return { ...data, success: response.ok };
}

export async function changePassword(oldPw, newPw, newPwConfirm) {
export async function changePassword(user, oldPw, newPw, newPwConfirm) {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
Expand All @@ -26,7 +26,7 @@ export async function changePassword(oldPw, newPw, newPwConfirm) {
}),
};
const response = await fetch(
"/api/v2/user/profile/save_settings/change_password/",
`/api/v2/user/profile/${user}/settings/change_password/`,
requestOptions,
);
const data = await response.json();
Expand Down
31 changes: 19 additions & 12 deletions internal/web/handlers/problemset/problem.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,27 @@ type ProblemAttachment struct {
Href string `json:"href"`
}

func ProblemAttachmentsFromProblem(tr i18n.Translator, prob problem.Problem) []ProblemAttachment {
res := make([]ProblemAttachment, 0)
type ProblemAttachmentData struct {
Statements []ProblemAttachment `json:"statements"`
Files []ProblemAttachment `json:"files"`
}

func ProblemAttachmentDataFromProblem(tr i18n.Translator, ps, probName string, prob problem.Problem) ProblemAttachmentData {
res := ProblemAttachmentData{
Statements: make([]ProblemAttachment, 0),
Files: make([]ProblemAttachment, 0),
}
for _, pdf := range prob.Problem.Statements().FilterByType(problems.DataTypePDF) {
res = append(res, ProblemAttachment{
Type: "statement",
res.Statements = append(res.Statements, ProblemAttachment{
Name: pdf.Locale(),
Href: "#",
Type: "pdf",
Href: fmt.Sprintf("/api/v2/problemset/%s/%s/pdf/%s/", ps, probName, pdf.Locale()),
})
}
for _, elem := range prob.Attachments() {
res = append(res, ProblemAttachment{
Type: "file",
res.Files = append(res.Files, ProblemAttachment{
Name: elem.Name(),
Href: "#",
Href: fmt.Sprintf("/api/v2/problemset/%s/%s/attachment/%s/", ps, probName, elem.Name()),
})
}
return res
Expand All @@ -93,14 +100,14 @@ func GetProblem(DB *sqlx.DB) echo.HandlerFunc {
return err
}

pattachs := ProblemAttachmentsFromProblem(tr, prob)
pdata := ProblemAttachmentDataFromProblem(tr, c.Param("name"), c.Param("problem"), prob)

return c.JSON(http.StatusOK, struct {
Info ProblemInfo `json:"info"`
Attachments []ProblemAttachment `json:"attachments"`
Info ProblemInfo `json:"info"`
Attachments ProblemAttachmentData `json:"attachments"`
}{
*pinfo,
pattachs,
pdata,
})
}
}
Expand Down
65 changes: 36 additions & 29 deletions internal/web/handlers/user/profile/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import (
"fmt"
"github.com/mraron/njudge/internal/web/handlers/problemset"
"github.com/mraron/njudge/internal/web/helpers/ui"
"github.com/mraron/njudge/pkg/problems"
"github.com/volatiletech/sqlboiler/v4/boil"
"golang.org/x/crypto/bcrypt"
"golang.org/x/net/context"
"net/http"

"github.com/jmoiron/sqlx"
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/web/domain/submission"
"github.com/mraron/njudge/internal/web/helpers"
"github.com/mraron/njudge/internal/web/helpers/i18n"
"github.com/mraron/njudge/internal/web/helpers/pagination"
"github.com/mraron/njudge/internal/web/models"
Expand Down Expand Up @@ -104,7 +103,7 @@ func GetProfile(DB *sqlx.DB) echo.HandlerFunc {
}
}

func GetSubmissions(statusPageService services.StatusPageService) echo.HandlerFunc {
func GetSubmissions(DB *sqlx.DB, problemStore problems.Store, statusPageService services.StatusPageService) echo.HandlerFunc {
type request struct {
Page int `query:"page"`
}
Expand Down Expand Up @@ -137,30 +136,40 @@ func GetSubmissions(statusPageService services.StatusPageService) echo.HandlerFu
return err
}

c.Set("title", tr.Translate("%s's submissions", u.Name))
return c.Render(http.StatusOK, "user/profile/submissions", struct {
User *models.User
StatusPage *submission.StatusPage
}{u, statusPage})
statusRows := make([]*problemset.StatusRow, len(statusPage.Submissions))
for i := range statusPage.Submissions {
sub := &statusPage.Submissions[i]
if statusRows[i], err = problemset.StatusRowFromSubmission(c.Request().Context(), DB.DB,
problemStore, tr, sub); err != nil {
return err
}
}

return c.JSON(http.StatusOK, struct {
PaginationData pagination.Data `json:"paginationData"`
Submissions []*problemset.StatusRow `json:"submissions"`
}{statusPage.PaginationData, statusRows})
}
}

func GetSettings(DB *sqlx.DB) echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*models.User)

helpers.DeleteFlash(c, "ChangePassword")
return c.Render(http.StatusOK, "user/profile/settings", struct {
User *models.User
}{u})
return c.JSON(http.StatusOK, struct {
ShowUnsolved bool `json:"showUnsolved"`
}{u.ShowUnsolvedTags})
}
}

func PostSettingsChangePassword(DB *sqlx.DB) echo.HandlerFunc {
type request struct {
PasswordOld string `form:"passwordOld"`
PasswordNew1 string `form:"passwordNew1"`
PasswordNew2 string `form:"passwordNew2"`
PasswordOld string `json:"oldPw"`
PasswordNew1 string `json:"newPw"`
PasswordNew2 string `json:"newPwConfirm"`
}
type response struct {
Message string `json:"message"`
}
return func(c echo.Context) error {
tr := c.Get("translator").(i18n.Translator)
Expand All @@ -172,18 +181,21 @@ func PostSettingsChangePassword(DB *sqlx.DB) echo.HandlerFunc {
}

if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(data.PasswordOld)); err != nil {
helpers.SetFlash(c, "ChangePassword", tr.Translate("Wrong old password."))
return c.Redirect(http.StatusFound, "../")
return c.JSON(http.StatusUnprocessableEntity, response{
Message: tr.Translate("Wrong old password."),
})
}

if len(data.PasswordNew1) == 0 {
helpers.SetFlash(c, "ChangePassword", tr.Translate("It's required to give a new password."))
return c.Redirect(http.StatusFound, "../")
return c.JSON(http.StatusUnprocessableEntity, response{
Message: tr.Translate("It's required to give a new password."),
})
}

if data.PasswordNew1 != data.PasswordNew2 {
helpers.SetFlash(c, "ChangePassword", tr.Translate("The two given passwords doesn't match."))
return c.Redirect(http.StatusFound, "../")
return c.JSON(http.StatusUnprocessableEntity, response{
Message: tr.Translate("The two given passwords doesn't match."),
})
}

res, err := bcrypt.GenerateFromPassword([]byte(data.PasswordNew1), bcrypt.DefaultCost)
Expand All @@ -196,15 +208,13 @@ func PostSettingsChangePassword(DB *sqlx.DB) echo.HandlerFunc {
return err
}

return c.Redirect(http.StatusFound, "../")
return c.JSON(http.StatusOK, "")
}
}

func PostSettingsMisc(DB *sqlx.DB) echo.HandlerFunc {
type request struct {
ShowTagsForUnsolved string `form:"showTagsForUnsolved"`

ShowTagsForUnsolvedBool bool
ShowTagsForUnsolved bool `json:"showUnsolved"`
}
return func(c echo.Context) error {
u := c.Get("user").(*models.User)
Expand All @@ -213,11 +223,8 @@ func PostSettingsMisc(DB *sqlx.DB) echo.HandlerFunc {
if err := c.Bind(&data); err != nil {
return err
}
if data.ShowTagsForUnsolved == "true" {
data.ShowTagsForUnsolvedBool = true
}

u.ShowUnsolvedTags = data.ShowTagsForUnsolvedBool
u.ShowUnsolvedTags = data.ShowTagsForUnsolved
if _, err := u.Update(c.Request().Context(), DB, boil.Whitelist(models.UserColumns.ShowUnsolvedTags)); err != nil {
return err
}
Expand Down
22 changes: 15 additions & 7 deletions internal/web/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ func (s *Server) prepareRoutes(e *echo.Echo) {
//psProb.GET("/ranklist", problemset.GetProblemRanklist(s.DB))
psProb.POST("/tags", problemset.PostProblemTag(services.NewSQLTagsService(s.DB.DB)))
psProb.GET("/delete_tag/:id", problemset.DeleteProblemTag(services.NewSQLTagsService(s.DB.DB)))
psProb.GET("/pdf/:language/", problemset.GetProblemPDF())
psProb.GET("/attachment/:attachment/", problemset.GetProblemAttachment())
//psProb.GET("/pdf/:language/", problemset.GetProblemPDF())
//psProb.GET("/attachment/:attachment/", problemset.GetProblemAttachment())
psProb.GET("/:file", problemset.GetProblemFile())

u := e.Group("/user")
Expand All @@ -81,12 +81,12 @@ func (s *Server) prepareRoutes(e *echo.Echo) {

pr := u.Group("/profile", profile.SetProfileMiddleware(s.DB))
//pr.GET("/:name/", profile.GetProfile(s.DB))
pr.GET("/:name/submissions/", profile.GetSubmissions(services.NewSQLStatusPageService(s.DB.DB)))
//pr.GET("/:name/submissions/", profile.GetSubmissions(services.NewSQLStatusPageService(s.DB.DB)))

prs := pr.Group("/:name/settings", user.RequireLoginMiddleware(), profile.PrivateMiddleware())
prs.GET("/", profile.GetSettings(s.DB))
prs.POST("/change_password/", profile.PostSettingsChangePassword(s.DB))
prs.POST("/misc/", profile.PostSettingsMisc(s.DB))
_ = pr.Group("/:name/settings", user.RequireLoginMiddleware(), profile.PrivateMiddleware())
//prs.GET("/", profile.GetSettings(s.DB))
//prs.POST("/change_password/", profile.PostSettingsChangePassword(s.DB))
//prs.POST("/misc/", profile.PostSettingsMisc(s.DB))

apiGroup := e.Group("/api")

Expand All @@ -109,6 +109,12 @@ func (s *Server) prepareRoutes(e *echo.Echo) {

pr := u.Group("/profile", profile.SetProfileMiddleware(s.DB))
pr.GET("/:name/", profile.GetProfile(s.DB))
pr.GET("/:name/submissions/", profile.GetSubmissions(s.DB, s.ProblemStore, services.NewSQLStatusPageService(s.DB.DB)))

prs := pr.Group("/:name/settings", user.RequireLoginMiddleware(), profile.PrivateMiddleware())
prs.GET("/", profile.GetSettings(s.DB))
prs.POST("/change_password/", profile.PostSettingsChangePassword(s.DB))
prs.POST("/other/", profile.PostSettingsMisc(s.DB))

u.GET("/auth/", func(c echo.Context) error {

Expand Down Expand Up @@ -143,6 +149,8 @@ func (s *Server) prepareRoutes(e *echo.Echo) {
psProb.GET("/", problemset.GetProblem(s.DB))
psProb.GET("/submissions/", problemset.GetProblemStatus(s.DB, s.ProblemStore, services.NewSQLStatusPageService(s.DB.DB)))
psProb.GET("/ranklist/", problemset.GetProblemRanklist(s.DB))
psProb.GET("/pdf/:language/", problemset.GetProblemPDF())
psProb.GET("/attachment/:attachment/", problemset.GetProblemAttachment())

v2.GET("/submission/:id/", handlers.GetSubmission(s.DB, s.ProblemStore, services.NewSQLSubmission(s.DB.DB))).Name = "getSubmission"

Expand Down

0 comments on commit bcd9f2d

Please sign in to comment.