Skip to content

Commit

Permalink
Merge branch 'frontend' of https://github.com/SELab-2/UGent-6 into fr…
Browse files Browse the repository at this point in the history
…ontend
  • Loading branch information
Aqua-sc committed May 23, 2024
2 parents 3410bd8 + 90642fc commit ce6dd2c
Show file tree
Hide file tree
Showing 14 changed files with 273 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ public void testRunDockerTest() throws IOException {

verify(dockerModel, times(1)).addZipInputFiles(file);
verify(dockerModel, times(1)).cleanUp();
verify(dockerModel, times(1)).addUtilFiles(extraFilesPathResolved);
assertEquals(1, filehandlerCalled.get());

/* artifacts are empty */
Expand All @@ -128,7 +127,6 @@ public void testRunDockerTest() throws IOException {
assertEquals(dockerTemplateTestOutput, result);
verify(dockerModel, times(2)).addZipInputFiles(file);
verify(dockerModel, times(2)).cleanUp();
verify(dockerModel, times(2)).addUtilFiles(extraFilesPathResolved);
assertEquals(1, filehandlerCalled.get());

/* aritifacts are null */
Expand All @@ -137,7 +135,6 @@ public void testRunDockerTest() throws IOException {
assertEquals(dockerTemplateTestOutput, result);
verify(dockerModel, times(3)).addZipInputFiles(file);
verify(dockerModel, times(3)).cleanUp();
verify(dockerModel, times(3)).addUtilFiles(extraFilesPathResolved);
assertEquals(1, filehandlerCalled.get());

/* No template */
Expand All @@ -147,7 +144,6 @@ public void testRunDockerTest() throws IOException {
assertEquals(dockerTestOutput, result);
verify(dockerModel, times(4)).addZipInputFiles(file);
verify(dockerModel, times(4)).cleanUp();
verify(dockerModel, times(4)).addUtilFiles(extraFilesPathResolved);

/* Error gets thrown */
when(dockerModel.runSubmission(testEntity.getDockerTestScript())).thenThrow(new RuntimeException("Error"));
Expand Down
1 change: 1 addition & 0 deletions frontend/public/docker_langauges/bash.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/public/docker_langauges/custom.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/public/docker_langauges/haskell.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/public/docker_langauges/node-js.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/public/docker_langauges/python.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
100 changes: 71 additions & 29 deletions frontend/src/components/forms/projectFormTabs/DockerFormTab.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,62 @@
import { UploadOutlined } from "@ant-design/icons"
import {Button, Form, Input, Switch, Upload} from "antd"
import { CodepenCircleFilled, InboxOutlined, UploadOutlined } from "@ant-design/icons"
import { Button, Dropdown, Form, Input, Menu, Select, SelectProps, Switch, Upload } from "antd"
import { TextAreaProps } from "antd/es/input"
import { FormInstance } from "antd/lib"
import {FC, useEffect} from "react"
import React, { FC, useEffect, useLayoutEffect, useMemo, useState } from "react"
import { useTranslation } from "react-i18next"
import useAppApi from "../../../hooks/useAppApi"
import MarkdownTooltip from "../../common/MarkdownTooltip"
import MarkdownTextfield from "../../input/MarkdownTextfield"
import TextArea from "antd/es/input/TextArea"

import BashIcon from "../../../../public/docker_langauges/bash.svg"
import PythonIcon from "../../../../public/docker_langauges/python.svg"
import NodeIcon from "../../../../public/docker_langauges/node-js.svg"
import HaskellIcon from "../../../../public/docker_langauges/haskell.svg"
import Custom from "../../../../public/docker_langauges/custom.svg"


type DockerLanguage = "bash" | "python" | "node" | "haskell" | "custom"
const languageOptions: Record<DockerLanguage, string> = {
bash: "fedora",
python: "python",
node: "node",
haskell: "haskell",
custom: ""
}

const imageToLanguage: Record<string, DockerLanguage> = {
fedora: "bash",
python: "python",
node: "node",
haskell: "haskell",
}


const languagesSelectorItems:SelectProps["options"] = [
{
label: <><img src={BashIcon} className="select-icon" />Bash</>,
value: "bash",
},{
label: <><img src={PythonIcon} className="select-icon" />Python</>,
value: "python",
}, {
label: <><img src={NodeIcon} className="select-icon" />NodeJS</>,
value: "node",
}, {
label: <><img src={HaskellIcon} className="select-icon" />Haskell</>,
value: "haskell",
}, {
label: <><img src={Custom} className="select-icon" />Custom</>,
value: "custom",
}
]



const DockerFormTab: FC<{ form: FormInstance }> = ({ form }) => {
const { t } = useTranslation()
const {message} = useAppApi()

const { message } = useAppApi()
const dockerImage = Form.useWatch("dockerImage", form)
const dockerTemplate = Form.useWatch("dockerTemplate", form)
const dockerMode = Form.useWatch("dockerMode", form)
Expand All @@ -28,6 +72,8 @@ const DockerFormTab: FC<{ form: FormInstance }> = ({ form }) => {
form.validateFields(["dockerScript", "dockerTemplate"])
}, [dockerDisabled])


const dockerImageSelect= useMemo(()=> imageToLanguage[dockerImage] || "custom",[dockerImage])

function isValidTemplate(template: string): string {
if (template.length === 0) {
Expand Down Expand Up @@ -56,7 +102,7 @@ const DockerFormTab: FC<{ form: FormInstance }> = ({ form }) => {
const isDescription = line.length >= 13 && line.substring(0, 13).toLowerCase() === ">description="
// option lines
if (line.toLowerCase() !== ">required" && line.toLowerCase() !== ">optional" && !isDescription) {
return t("project.tests.dockerTemplateValidation.inValidOptions", { line:lineNumber.toString() })
return t("project.tests.dockerTemplateValidation.inValidOptions", { line: lineNumber.toString() })
}
} else {
isConfigurationLine = false
Expand All @@ -69,31 +115,22 @@ const DockerFormTab: FC<{ form: FormInstance }> = ({ form }) => {
return ""
}



const normFile = (e: any) => {
if (Array.isArray(e)) {
return e;
return e
}
return e?.fileList;
};
return e?.fileList
}

let switchClassName = 'template-switch'
let switchClassName = "template-switch"
let scriptPlaceholder

if (withTemplate) {
switchClassName += ' template-switch-active'
scriptPlaceholder = "bash /shared/input/helloworld.sh > \"/shared/output/helloWorldTest\"\n"+
"bash /shared/input/helloug.sh > \"/shared/output/helloUGent\"\n"
switchClassName += " template-switch-active"
scriptPlaceholder = 'bash /shared/input/helloworld.sh > "/shared/output/helloWorldTest"\n' + 'bash /shared/input/helloug.sh > "/shared/output/helloUGent"\n'
} else {
switchClassName += ' template-switch-inactive'
scriptPlaceholder = "output=$(bash /shared/input/helloworld.sh)\n"+
"if [[ \"$output\" == \"Hello World\" ]]; then \n"+
" echo 'Test one is successful\n"+
" echo 'PUSH ALLOWED' > /shared/output/testOutput\n"+
"else\n"+
" echo 'Test one failed: script failed to print \"Hello World\"'\n"+
"fi"
switchClassName += " template-switch-inactive"
scriptPlaceholder = "output=$(bash /shared/input/helloworld.sh)\n" + 'if [[ "$output" == "Hello World" ]]; then \n' + " echo 'Test one is successful\n" + " echo 'PUSH ALLOWED' > /shared/output/testOutput\n" + "else\n" + " echo 'Test one failed: script failed to print \"Hello World\"'\n" + "fi"
}


Expand All @@ -110,11 +147,16 @@ const DockerFormTab: FC<{ form: FormInstance }> = ({ form }) => {
name="dockerImage"
>
<Input
style={{ marginTop: "8px" }}
addonBefore={
<Select
style={{ width: 150 }}
value={dockerImageSelect}
onChange={(val:DockerLanguage) => form.setFieldValue("dockerImage", languageOptions[val])}
options={languagesSelectorItems}
/>}
placeholder={t("project.tests.dockerImagePlaceholder")}
/>
</Form.Item>

<>
<Form.Item
rules={[{ required: !dockerDisabled, message: t("project.tests.dockerScriptRequired") }]}
Expand All @@ -127,10 +169,10 @@ const DockerFormTab: FC<{ form: FormInstance }> = ({ form }) => {
}
name="dockerScript"
>
<Input.TextArea
<TextArea
disabled={dockerDisabled}
autoSize={{ minRows: 8 }}
style={{ fontFamily: "monospace", whiteSpace: "pre", overflowX: "auto"}}
style={{ fontFamily: "monospace", whiteSpace: "pre", overflowX: "auto" }}
placeholder={scriptPlaceholder}
/>
</Form.Item>
Expand Down Expand Up @@ -224,4 +266,4 @@ const DockerFormTab: FC<{ form: FormInstance }> = ({ form }) => {
)
}

export default DockerFormTab
export default DockerFormTab
166 changes: 74 additions & 92 deletions frontend/src/components/forms/projectFormTabs/GeneralFormTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,106 +2,88 @@ import { DatePicker, Form, FormInstance, Input, Switch, Typography } from "antd"
import { useTranslation } from "react-i18next"
import { FC } from "react"
import MarkdownEditor from "../../input/MarkdownEditor"
import dayjs from 'dayjs';
import dayjs from "dayjs"

const GeneralFormTab: FC<{ form: FormInstance }> = ({ form }) => {
const { t } = useTranslation()
const description = Form.useWatch("description", form)
const visible = Form.useWatch("visible", form)
const { t } = useTranslation()
const description = Form.useWatch("description", form)
const visible = Form.useWatch("visible", form)

return (
<>
<Form.Item
label={t("project.change.name")}
name="name"
rules={[{ required: true, message: t("project.change.nameMessage") }]}
>
<Input />
</Form.Item>
return (
<>
<Form.Item
label={t("project.change.name")}
name="name"
rules={[{ required: true, message: t("project.change.nameMessage") }]}
>
<Input />
</Form.Item>

<Typography.Text>
{t("project.change.description")}
</Typography.Text>
<MarkdownEditor value={description} maxLength={5000} />
<Typography.Text>{t("project.change.description")}</Typography.Text>
<MarkdownEditor
value={description}
maxLength={5000}
/>

<Form.Item
label={t("project.change.visible")}
required
name="visible"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("project.change.visible")}
required
name="visible"
valuePropName="checked"
>
<Switch />
</Form.Item>

{!visible && (
<Form.Item
label={t("project.change.visibleAfter")}
tooltip={t("project.change.visibleAfterTooltip")}
name="visibleAfter"
>
<DatePicker
showTime
format="YYYY-MM-DD HH:mm:ss"
allowClear={true}
disabledDate={(current) => current && current.isBefore(dayjs().startOf('day'))}
/>
</Form.Item>
)}
{!visible && (
<Form.Item
label={t("project.change.visibleAfter")}
tooltip={t("project.change.visibleAfterTooltip")}
name="visibleAfter"
>
<DatePicker
showTime
format="YYYY-MM-DD HH:mm:ss"
allowClear={true}
disabledDate={(current) => current && current.isBefore(dayjs().startOf("day"))}
/>
</Form.Item>
)}

<Form.Item
label={t("project.change.maxScore")}
name="maxScore"
tooltip={t("project.change.maxScoreHelp")}
rules={[{ required: false, message: t("project.change.maxScoreMessage") }]}
>
<Input
min={1}
max={1000}
type="number"
/>
</Form.Item>
<Form.Item
label={t("project.change.maxScore")}
name="maxScore"
tooltip={t("project.change.maxScoreHelp")}
rules={[{ required: false, message: t("project.change.maxScoreMessage") }]}
>
<Input
min={1}
max={1000}
type="number"
/>
</Form.Item>

<Form.Item
label={t("project.change.deadline")}
name="deadline"
rules={[{ required: true }]}
>
<DatePicker
showTime={{
format: "HH:mm:ss",
disabledHours: () => {
const hours = [];
for (let i = 0; i < dayjs().hour(); i++) {
hours.push(i);
}
return hours;
},
disabledMinutes: (selectedHour) => {
const minutes = [];
if (selectedHour === dayjs().hour()) {
for (let i = 0; i < dayjs().minute(); i++) {
minutes.push(i);
}
}
return minutes;
},
disabledSeconds: (selectedHour, selectedMinute) => {
const seconds = [];
if (selectedHour === dayjs().hour() && selectedMinute === dayjs().minute()) {
for (let i = 0; i < dayjs().second(); i++) {
seconds.push(i);
}
}
return seconds;
},
}}
format="YYYY-MM-DD HH:mm:ss"
disabledDate={(current) => current && current.isBefore(dayjs().startOf('day'))}

/>
</Form.Item>
</>
)
<Form.Item
label={t("project.change.deadline")}
name="deadline"
rules={[{ required: true }]}
>
<DatePicker
showTime={{
format: "HH:mm:ss",
disabledHours: () => {
const hours = []
for (let i = 0; i < dayjs().hour(); i++) {
hours.push(i)
}
return hours
},
}}
format="YYYY-MM-DD HH:mm:ss"
disabledDate={(current) => current && current.isBefore(dayjs().startOf("day"))}
/>
</Form.Item>
</>
)
}

export default GeneralFormTab
Loading

0 comments on commit ce6dd2c

Please sign in to comment.