26 Commits
Author SHA1 Message Date
auto afb833bd19 Add useCallback to optimize handleCheckForm
Refactored handleCheckForm using useCallback to prevent unnecessary re-renders. This ensures the function is only re-created when formData.backendFormName changes, improving performance. Updated useEffect dependencies to include handleCheckForm for proper effect cleanup.
2024-08-10 03:27:28 +02:00
auto 6215944972 Fix missing promise handling in formActiveRedirect
Added a then() clause to handle the resolved promise after calling handleCheckForm in the useEffect. This ensures any asynchronous operations complete as expected and avoids potential unhandled promise rejections.
2024-08-10 03:24:46 +02:00
auto a08c55ec41 Remove GenericForm import from App.tsx
GenericForm was imported but never used in App.tsx. This clean-up helps in maintaining the codebase by removing unnecessary imports, thus enhancing readability and reducing potential confusion.
2024-08-10 03:24:07 +02:00
auto 2a56144bbc Enhance npm cache clean error handling in Jenkinsfile
Wrapped npm cache clean command in a try-catch block to improve error handling. This ensures that the build process can proceed even if the npm cache clean step fails. Added an informational echo message for better diagnostics in case of failure.
2024-08-10 03:21:16 +02:00
auto 98b86363f5 Add npm install fallback and remove unused variable
Added a fallback npm install command in the Jenkinsfile to handle legacy peer dependencies. Also removed an unused variable from genericForm.tsx to improve code clarity and performance.
2024-08-10 03:19:26 +02:00
auto 75559af7c8 Add form active status check and redirection
Introduced `FormActiveRedirect` component to check if forms are active before rendering. Updated form data to include `backendFormName` and adjusted routes in `App.tsx` to use the new component. This ensures that inactive forms redirect users with a relevant message.
2024-08-10 03:10:25 +02:00
auto 21e23b98ad Remove unused Field import from GenericForm
This commit eliminates the unused Field import from Formik in the genericForm.tsx file. Removing unused imports helps maintain cleaner and more efficient code.
2024-08-10 00:27:24 +02:00
auto 67eddc0394 Merge branch 'refs/heads/dev' 2024-08-10 00:26:46 +02:00
auto d005b72634 Add react-select component and integrate into FormHTML
Added `react-select` library dependency to `package.json` and lock file. Created a new `FormHTML` component in `formHTML.tsx` to handle form field rendering, including support for `select` fields using `react-select` for multi-select functionality.
2024-08-10 00:25:44 +02:00
Peter 51642612ec More style changes 2024-08-09 23:16:41 +02:00
auto cde2a01dd9 Refactor form to use useFormik and FormikProvider
Replaced Formik component with useFormik hook and FormikProvider. This change simplifies the form implementation and separates the form's logic and presentation. The form now benefits from more direct access to formik methods and state.
2024-08-08 21:37:09 +02:00
Peter 4dda70effc Styling for forms 2024-08-08 21:32:37 +02:00
auto 960fc1707b Refactor conditional stage in Jenkinsfile
Updated the 'discord' stage condition to use 'anyOf' for more readable and maintainable branch checks. This change enhances the clarity of branch conditions, ensuring it triggers on either the 'main' or 'master' branches.
2024-08-08 20:38:05 +02:00
auto 94c336fb74 Add dropdown and additional info fields to form steps
Updated form interfaces to include optional dropdown and additional info properties. Adjusted form rendering logic to handle these new fields, providing clearer instructions and choices for users. Refined validation messages for consistency and clarity.
2024-08-08 20:33:15 +02:00
auto 7407372b03 Add branch condition to Discord notification stage
Previously, the Discord notification was sent for all branches. Now, the notification will only be sent for builds on the 'main' or 'master' branches, reducing unnecessary notifications.
2024-08-08 20:32:43 +02:00
auto 973b6b5e7d Add titles to form data and display them dynamically
Incorporated 'title' property into form data objects for dynamic rendering in the GenericForm component. This enhancement facilitates the use of specific titles for different forms, improving readability and user experience.
2024-08-07 00:41:11 +02:00
auto f52201b683 Rename variables for clarity and adjust download filename and contents
Renamed the parameter 'e' to 'formikValues' for better clarity in the handleSubmit function. Now load formikValues into the file that get's uploaded so it has the up to date form data. Changed the downloaded JSON filename from 'form_data.json' to 'your_form_data.json' to be more user-friendly.
2024-08-06 23:21:53 +02:00
auto 9a281ed76c Update backend URLs to use environment variables
Replaced hardcoded backend URLs with environment variables in contact, apply, and verify_email components. Added .env.development and .env.production files to define the base URLs for different environments. This improves flexibility and allows easier configuration changes.
2024-08-06 23:17:37 +02:00
auto 997baae4d3 Fix JSON serialization in error handling
Replaced steps variable with userInput for JSON serialization in error handling. This ensures that the correct data is saved as a JSON blob when a network error occurs.
2024-08-06 22:28:41 +02:00
auto 857d61e09d Add staff application form
Introduced a new form for staff applications based on the old staff application form.
2024-08-06 22:23:35 +02:00
auto d2f15d2627 Refactor forms to use a generic form component
Replaced the contact form with a generic form component to support multiple form configurations. Moved validation schema and form data to a new structure, allowing dynamic form rendering. Updated the App component to utilize this generic approach for handling different forms.
2024-08-06 21:07:20 +02:00
auto 2eef14ba2e Update API endpoints in contact and verify email forms
This commit changes the API endpoints in contact.tsx and verify_mail.tsx to use the new 'forms-backend.alttd.com' domain. This ensures that form submissions and email verifications are routed correctly to the updated backend.
2024-08-05 00:49:33 +02:00
auto c725d6e85d Update API endpoints to production URLs
Changed the API endpoints in contact and verify email forms from localhost URLs to the production server. This ensures that the forms submit data to the correct, live endpoints.
2024-08-05 00:28:27 +02:00
auto 90cc0edcf4 Fix strict equality check in contact form input handler
Updated the input change handler to use strict equality for comparing the previous and current length of the form value, ensuring more reliable condition checks and better handling of form state updates.
2024-08-04 23:21:05 +02:00
auto 7ab9e25eb5 Handle npm install retries with fallback options
Added an environment variable for maximum retries and a script to handle npm install with fallback to npm ci and retry mechanisms using --legacy-peer-deps and --force options. This might fix npm sucking.
2024-08-04 23:18:56 +02:00
auto a8ea5c38f1 Update npm install command in Jenkinsfile
Forced installation of npm packages and resolved legacy peer dependency issues by adding `--force` and `--legacy-peer-dep` flags to `npm install` command. This ensures compatibility with certain package versions that may have unresolved peer dependencies.
2024-08-04 23:10:42 +02:00
30 changed files with 1790 additions and 6466 deletions
+1
View File
@@ -0,0 +1 @@
REACT_APP_BACKEND_BASE_URL=http://localhost:8002
+1
View File
@@ -0,0 +1 @@
REACT_APP_BACKEND_BASE_URL=https://forms-backend.alttd.com
Vendored
+61 -3
View File
@@ -1,10 +1,62 @@
pipeline {
agent any
environment {
MAX_RETRIES = 5
}
stages {
stage('Gradle') {
steps {
sh 'npm install'
sh 'npm run build'
script {
def retryCount = 0
def success = false
// Clean npm cache and try normal install and npm ci once
try {
sh 'npm cache clean --force'
} catch (Exception e0) {
echo 'npm cache clean --force failed trying more things'
}
try {
sh 'npm install'
success = true
} catch (Exception e1) {
echo "npm install failed, trying npm ci..."
try {
sh 'npm ci'
success = true
} catch (Exception e2) {
echo "npm ci failed, proceeding to retry with --legacy-peer-deps and --force..."
}
}
// Retry with --legacy-peer-deps and --force if necessary
while (retryCount < MAX_RETRIES.toInteger() && !success) {
try {
sh 'npm install --legacy-peer-deps'
success = true
} catch (Exception e3) {
try {
sh 'npm install --force'
success = true
} catch (Exception e4) {
retryCount++
echo "Retry ${retryCount}/${MAX_RETRIES} failed"
}
}
try {
sh 'npm install --legacy-peer-deps --force'
success = true
} catch (Exception e4) {
echo "npm install --legacy-peer-deps --force failed"
}
}
if (!success) {
error "Failed to install dependencies after ${MAX_RETRIES} attempts"
}
sh 'npm run build'
}
}
}
stage('Archive') {
@@ -13,9 +65,15 @@ pipeline {
}
}
stage('discord') {
when {
anyOf {
branch 'main'
branch 'master'
}
}
steps {
discordSend description: "Build: ${BUILD_NUMBER}", showChangeset: true, result: currentBuild.currentResult, title: currentBuild.fullProjectName, webhookURL: env.discordwebhook
}
}
}
}
}
+427 -6220
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -16,6 +16,7 @@
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-scripts": "^5.0.1",
"react-select": "^5.8.0",
"typescript": "^5.3.3",
"web-vitals": "^3.5.1",
"yup": "^1.3.3"
Binary file not shown.
+361
View File
@@ -0,0 +1,361 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<metadata>
Created by FontForge 20161116 at Wed Feb 29 18:13:36 2012
By Jimmy Wärting
Copyright qrelly 2011
</metadata>
<defs>
<font id="Minecraft" horiz-adv-x="768" >
<font-face
font-family="Minecraft"
font-weight="400"
font-stretch="normal"
units-per-em="1024"
panose-1="0 0 4 0 0 0 0 0 0 0"
ascent="896"
descent="-128"
x-height="640"
cap-height="896"
bbox="0 -128 896 896"
underline-thickness="51"
underline-position="77"
unicode-range="U+0020-201D"
/>
<missing-glyph horiz-adv-x="0"
d="M448 127v142h-143v-142h143zM590 293v143h-285v-143h285zM448 459v143h-143v-143h143zM590 626v141h-142q-60 0 -101 -41q-42 -42 -42 -100h285zM0 0v896h896v-896h-896z" />
<glyph glyph-name=".notdef" horiz-adv-x="0"
d="M448 127v142h-143v-142h143zM590 293v143h-285v-143h285zM448 459v143h-143v-143h143zM590 626v141h-142q-60 0 -101 -41q-42 -42 -42 -100h285zM0 0v896h896v-896h-896z" />
<glyph glyph-name="glyph1" horiz-adv-x="0"
/>
<glyph glyph-name="glyph2" horiz-adv-x="256"
/>
<glyph glyph-name="space" unicode=" " horiz-adv-x="384"
/>
<glyph glyph-name="exclam" unicode="!" horiz-adv-x="256"
d="M0 0v128h128v-128h-128zM0 256v640h128v-640h-128z" />
<glyph glyph-name="quotedbl" unicode="&#x22;" horiz-adv-x="512"
d="M0 512v384h128v-384h-128zM256 512v384h128v-384h-128z" />
<glyph glyph-name="numbersign" unicode="#"
d="M384 384v128h-128v-128h128zM128 0v256h-128v128h128v128h-128v128h128v256h128v-256h128v256h128v-256h128v-128h-128v-128h128v-128h-128v-256h-128v256h-128v-256h-128z" />
<glyph glyph-name="dollar" unicode="$"
d="M256 0v128h-256v128h512v-128h-128v-128h-128zM512 256v128h128v-128h-128zM128 384v128h384v-128h-384zM0 512v128h128v-128h-128zM128 640v128h128v128h128v-128h256v-128h-512z" />
<glyph glyph-name="percent" unicode="%"
d="M0 0v128h128v-128h-128zM512 0v256h128v-256h-128zM128 128v256h128v-256h-128zM256 384v128h128v-128h-128zM384 512v256h128v-256h-128zM0 640v256h128v-256h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="ampersand" unicode="&#x26;"
d="M128 0v128h256v-128h-256zM512 0v128h128v-128h-128zM0 128v256h128v-256h-128zM512 384v128h128v-128h-128zM384 128v128h-128v128h-128v128h128v128h128v-256h128v-256h-128zM128 640v128h128v-128h-128zM384 640v128h128v-128h-128zM256 768v128h128v-128h-128z" />
<glyph glyph-name="quotesingle" unicode="'" horiz-adv-x="256"
d="M0 512v384h128v-384h-128z" />
<glyph glyph-name="parenleft" unicode="(" horiz-adv-x="640"
d="M256 0v128h256v-128h-256zM128 128v128h128v-128h-128zM0 256v384h128v-384h-128zM128 640v128h128v-128h-128zM256 768v128h256v-128h-256z" />
<glyph glyph-name="parenright" unicode=")" horiz-adv-x="640"
d="M0 0v128h256v-128h-256zM256 128v128h128v-128h-128zM384 256v384h128v-384h-128zM256 640v128h128v-128h-128zM0 768v128h256v-128h-256z" />
<glyph glyph-name="asterisk" unicode="*" horiz-adv-x="640"
d="M128 512v128h128v-128h-128zM384 512v128h128v-128h-128zM256 640v128h128v-128h-128zM128 768v128h128v-128h-128zM384 768v128h128v-128h-128z" />
<glyph glyph-name="plus" unicode="+"
d="M256 128v256h-256v128h256v256h128v-256h256v-128h-256v-256h-128z" />
<glyph glyph-name="comma" unicode="," horiz-adv-x="384"
d="M0 -128v128h128v-128h-128zM128 0v128h128v-128h-128z" />
<glyph glyph-name="hyphen" unicode="-"
d="M0 384v128h640v-128h-640z" />
<glyph glyph-name="period" unicode="." horiz-adv-x="256"
d="M0 0v128h128v-128h-128z" />
<glyph glyph-name="slash" unicode="/"
d="M0 0v128h128v-128h-128zM128 128v256h128v-256h-128zM256 384v128h128v-128h-128zM384 512v256h128v-256h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="zero" unicode="0"
d="M128 0v128h384v-128h-384zM256 384v128h128v-128h-128zM0 128v640h128v-384h128v-128h-128v-128h-128zM512 128v384h-128v128h128v128h128v-640h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="one" unicode="1"
d="M0 0v128h256v512h-128v128h128v128h128v-768h256v-128h-640z" />
<glyph glyph-name="two" unicode="2"
d="M0 0v256h128v-128h384v128h128v-256h-640zM128 256v128h128v-128h-128zM256 384v128h256v-128h-256zM0 640v128h128v-128h-128zM512 512v256h128v-256h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="three" unicode="3"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM512 128v256h128v-256h-128zM256 384v128h256v-128h-256zM0 640v128h128v-128h-128zM512 512v256h128v-256h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="four" unicode="4"
d="M128 512v128h128v-128h-128zM256 640v128h128v-128h-128zM512 0v256h-512v256h128v-128h384v384h-128v128h256v-896h-128z" />
<glyph glyph-name="five" unicode="5"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM512 128v384h128v-384h-128zM0 512v384h640v-128h-512v-128h384v-128h-512z" />
<glyph glyph-name="six" unicode="6"
d="M128 0v128h384v-128h-384zM512 128v256h128v-256h-128zM0 128v512h128v-128h384v-128h-384v-256h-128zM128 640v128h128v-128h-128zM256 768v128h256v-128h-256z" />
<glyph glyph-name="seven" unicode="7"
d="M256 0v384h128v-384h-128zM384 384v128h128v-128h-128zM512 512v256h-384v-128h-128v256h640v-384h-128z" />
<glyph glyph-name="eight" unicode="8"
d="M128 0v128h384v-128h-384zM0 128v256h128v-256h-128zM512 128v256h128v-256h-128zM128 384v128h384v-128h-384zM0 512v256h128v-256h-128zM512 512v256h128v-256h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="nine" unicode="9"
d="M128 0v128h256v-128h-256zM384 128v128h128v-128h-128zM0 512v256h128v-256h-128zM512 256v128h-384v128h384v256h128v-512h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="colon" unicode=":" horiz-adv-x="256"
d="M0 128v256h128v-256h-128zM0 512v256h128v-256h-128z" />
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="512"
d="M128 128v128h128v-128h-128zM256 256v128h128v-128h-128zM256 512v256h128v-256h-128z" />
<glyph glyph-name="less" unicode="&#x3c;" horiz-adv-x="640"
d="M384 0v128h128v-128h-128zM256 128v128h128v-128h-128zM128 256v128h128v-128h-128zM0 384v128h128v-128h-128zM128 512v128h128v-128h-128zM256 640v128h128v-128h-128zM384 768v128h128v-128h-128z" />
<glyph glyph-name="equal" unicode="="
d="M0 128v128h640v-128h-640zM0 512v128h640v-128h-640z" />
<glyph glyph-name="greater" unicode="&#x3e;" horiz-adv-x="640"
d="M0 0v128h128v-128h-128zM128 128v128h128v-128h-128zM256 256v128h128v-128h-128zM384 384v128h128v-128h-128zM256 512v128h128v-128h-128zM128 640v128h128v-128h-128zM0 768v128h128v-128h-128z" />
<glyph glyph-name="question" unicode="?"
d="M256 0v128h128v-128h-128zM256 256v128h128v-128h-128zM384 384v128h128v-128h-128zM0 640v128h128v-128h-128zM512 512v256h128v-256h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="at" unicode="@" horiz-adv-x="896"
d="M128 0v128h512v-128h-512zM0 128v640h128v-640h-128zM256 256v384h256v-256h128v384h128v-512h-512zM128 768v128h512v-128h-512z" />
<glyph glyph-name="A" unicode="A"
d="M0 0v768h128v-128h384v128h128v-768h-128v512h-384v-512h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="B" unicode="B"
d="M512 128v384h128v-384h-128zM512 640v128h128v-128h-128zM0 0v896h512v-128h-384v-128h384v-128h-384v-384h384v-128h-512z" />
<glyph glyph-name="C" unicode="C"
d="M128 0v128h384v-128h-384zM512 128v128h128v-128h-128zM0 128v640h128v-640h-128zM512 640v128h128v-128h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="D" unicode="D"
d="M512 128v640h128v-640h-128zM0 0v896h512v-128h-384v-640h384v-128h-512z" />
<glyph glyph-name="E" unicode="E"
d="M0 0v896h640v-128h-512v-128h256v-128h-256v-384h512v-128h-640z" />
<glyph glyph-name="F" unicode="F"
d="M0 0v896h640v-128h-512v-128h256v-128h-256v-512h-128z" />
<glyph glyph-name="G" unicode="G"
d="M128 0v128h384v-128h-384zM512 128v384h-128v128h256v-512h-128zM0 128v640h128v-640h-128zM128 768v128h512v-128h-512z" />
<glyph glyph-name="H" unicode="H"
d="M0 0v896h128v-256h384v256h128v-896h-128v512h-384v-512h-128z" />
<glyph glyph-name="I" unicode="I" horiz-adv-x="512"
d="M0 0v128h128v640h-128v128h384v-128h-128v-640h128v-128h-384z" />
<glyph glyph-name="J" unicode="J"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM512 128v768h128v-768h-128z" />
<glyph glyph-name="K" unicode="K"
d="M512 0v384h128v-384h-128zM384 384v128h128v-128h-128zM384 640v128h128v-128h-128zM0 0v896h128v-256h256v-128h-256v-512h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="L" unicode="L"
d="M0 0v896h128v-768h512v-128h-640z" />
<glyph glyph-name="M" unicode="M"
d="M256 512v128h128v-128h-128zM0 0v896h128v-128h128v-128h-128v-640h-128zM512 0v640h-128v128h128v128h128v-896h-128z" />
<glyph glyph-name="N" unicode="N"
d="M256 512v128h128v-128h-128zM0 0v896h128v-128h128v-128h-128v-640h-128zM512 0v384h-128v128h128v384h128v-896h-128z" />
<glyph glyph-name="O" unicode="O"
d="M128 0v128h384v-128h-384zM0 128v640h128v-640h-128zM512 128v640h128v-640h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="P" unicode="P"
d="M512 640v128h128v-128h-128zM0 0v896h512v-128h-384v-128h384v-128h-384v-512h-128z" />
<glyph glyph-name="Q" unicode="Q"
d="M128 0v128h256v-128h-256zM512 0v128h128v-128h-128zM384 128v128h128v-128h-128zM0 128v640h128v-640h-128zM512 256v512h128v-512h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="R" unicode="R"
d="M512 0v512h128v-512h-128zM512 640v128h128v-128h-128zM0 0v896h512v-128h-384v-128h384v-128h-384v-512h-128z" />
<glyph glyph-name="S" unicode="S"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM512 128v384h128v-384h-128zM128 512v128h384v-128h-384zM0 640v128h128v-128h-128zM128 768v128h512v-128h-512z" />
<glyph glyph-name="T" unicode="T"
d="M256 0v768h-256v128h640v-128h-256v-768h-128z" />
<glyph glyph-name="U" unicode="U"
d="M128 0v128h384v-128h-384zM0 128v768h128v-768h-128zM512 128v768h128v-768h-128z" />
<glyph glyph-name="V" unicode="V"
d="M256 0v128h128v-128h-128zM128 128v256h128v-256h-128zM384 128v256h128v-256h-128zM0 384v512h128v-512h-128zM512 384v512h128v-512h-128z" />
<glyph glyph-name="W" unicode="W"
d="M256 256v128h128v-128h-128zM0 0v896h128v-640h128v-128h-128v-128h-128zM512 0v128h-128v128h128v640h128v-896h-128z" />
<glyph glyph-name="X" unicode="X"
d="M0 0v384h128v-384h-128zM512 0v384h128v-384h-128zM128 384v128h128v-128h-128zM384 384v128h128v-128h-128zM256 512v128h128v-128h-128zM128 640v128h128v-128h-128zM384 640v128h128v-128h-128zM0 768v128h128v-128h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="Y" unicode="Y"
d="M256 0v640h128v-640h-128zM128 640v128h128v-128h-128zM384 640v128h128v-128h-128zM0 768v128h128v-128h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="Z" unicode="Z"
d="M0 0v256h128v-128h512v-128h-640zM128 256v128h128v-128h-128zM256 384v128h128v-128h-128zM384 512v128h128v-128h-128zM512 640v128h-512v128h640v-256h-128z" />
<glyph glyph-name="bracketleft" unicode="[" horiz-adv-x="640"
d="M128 0v896h384v-128h-256v-640h256v-128h-384z" />
<glyph glyph-name="backslash" unicode="\"
d="M512 0v128h128v-128h-128zM384 128v256h128v-256h-128zM256 384v128h128v-128h-128zM128 512v256h128v-256h-128zM0 768v128h128v-128h-128z" />
<glyph glyph-name="bracketright" unicode="]" horiz-adv-x="640"
d="M128 0v128h256v640h-256v128h384v-896h-384z" />
<glyph glyph-name="asciicircum" unicode="^"
d="M0 512v128h128v-128h-128zM512 512v128h128v-128h-128zM128 640v128h128v-128h-128zM384 640v128h128v-128h-128zM256 768v128h128v-128h-128z" />
<glyph glyph-name="underscore" unicode="_"
d="M0 0v128h640v-128h-640z" />
<glyph glyph-name="grave" unicode="`" horiz-adv-x="384"
d="M128 512v128h128v-128h-128zM0 640v256h128v-256h-128z" />
<glyph glyph-name="a" unicode="a"
d="M0 128v128h128v-128h-128zM128 0v128h384v128h-384v128h384v128h128v-512h-512zM128 512v128h384v-128h-384z" />
<glyph glyph-name="b" unicode="b"
d="M512 128v384h128v-384h-128zM256 512v128h256v-128h-256zM0 0v896h128v-384h128v-128h-128v-256h384v-128h-512z" />
<glyph glyph-name="c" unicode="c"
d="M128 0v128h384v-128h-384zM512 128v128h128v-128h-128zM0 128v384h128v-384h-128zM512 384v128h128v-128h-128zM128 512v128h384v-128h-384z" />
<glyph glyph-name="d" unicode="d"
d="M0 128v384h128v-384h-128zM128 512v128h256v-128h-256zM128 0v128h384v256h-128v128h128v384h128v-896h-512z" />
<glyph glyph-name="e" unicode="e"
d="M128 0v128h512v-128h-512zM0 128v384h128v-128h384v128h128v-256h-512v-128h-128zM128 512v128h384v-128h-384z" />
<glyph glyph-name="f" unicode="f" horiz-adv-x="640"
d="M128 0v512h-128v128h128v128h128v-128h256v-128h-256v-512h-128zM256 768v128h256v-128h-256z" />
<glyph glyph-name="g" unicode="g"
d="M0 -128v128h512v-128h-512zM0 256v256h128v-256h-128zM512 0v128h-384v128h384v256h-384v128h512v-640h-128z" />
<glyph glyph-name="h" unicode="h"
d="M512 0v512h128v-512h-128zM256 512v128h256v-128h-256zM0 0v896h128v-384h128v-128h-128v-384h-128z" />
<glyph glyph-name="i" unicode="i" horiz-adv-x="256"
d="M0 0v640h128v-640h-128zM0 768v128h128v-128h-128z" />
<glyph glyph-name="j" unicode="j"
d="M128 -128v128h384v-128h-384zM0 0v128h128v-128h-128zM512 0v640h128v-640h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="k" unicode="k" horiz-adv-x="640"
d="M384 0v128h128v-128h-128zM256 128v128h128v-128h-128zM256 384v128h128v-128h-128zM384 512v128h128v-128h-128zM0 0v896h128v-512h128v-128h-128v-256h-128z" />
<glyph glyph-name="l" unicode="l" horiz-adv-x="384"
d="M128 0v128h128v-128h-128zM0 128v768h128v-768h-128z" />
<glyph glyph-name="m" unicode="m"
d="M256 256v256h128v-256h-128zM512 0v512h128v-512h-128zM0 0v640h256v-128h-128v-512h-128zM384 512v128h128v-128h-128z" />
<glyph glyph-name="n" unicode="n"
d="M512 0v512h128v-512h-128zM0 0v640h512v-128h-384v-512h-128z" />
<glyph glyph-name="o" unicode="o"
d="M128 0v128h384v-128h-384zM0 128v384h128v-384h-128zM512 128v384h128v-384h-128zM128 512v128h384v-128h-384z" />
<glyph glyph-name="p" unicode="p"
d="M512 256v256h128v-256h-128zM0 -128v768h128v-128h128v-128h-128v-128h384v-128h-384v-256h-128zM256 512v128h256v-128h-256z" />
<glyph glyph-name="q" unicode="q"
d="M0 256v256h128v-256h-128zM128 512v128h256v-128h-256zM512 -128v256h-384v128h384v128h-128v128h128v128h128v-768h-128z" />
<glyph glyph-name="r" unicode="r"
d="M512 384v128h128v-128h-128zM0 0v640h128v-128h128v-128h-128v-384h-128zM256 512v128h256v-128h-256z" />
<glyph glyph-name="s" unicode="s"
d="M0 0v128h512v-128h-512zM512 128v128h128v-128h-128zM128 256v128h384v-128h-384zM0 384v128h128v-128h-128zM128 512v128h512v-128h-512z" />
<glyph glyph-name="t" unicode="t" horiz-adv-x="512"
d="M256 0v128h128v-128h-128zM128 128v384h-128v128h128v256h128v-256h128v-128h-128v-384h-128z" />
<glyph glyph-name="u" unicode="u"
d="M0 128v512h128v-512h-128zM128 0v128h384v512h128v-640h-512z" />
<glyph glyph-name="v" unicode="v"
d="M256 0v128h128v-128h-128zM128 128v128h128v-128h-128zM384 128v128h128v-128h-128zM0 256v384h128v-384h-128zM512 256v384h128v-384h-128z" />
<glyph glyph-name="w" unicode="w"
d="M0 128v512h128v-512h-128zM128 0v128h128v256h128v-256h128v512h128v-640h-512z" />
<glyph glyph-name="x" unicode="x"
d="M0 0v128h128v-128h-128zM512 0v128h128v-128h-128zM128 128v128h128v-128h-128zM384 128v128h128v-128h-128zM256 256v128h128v-128h-128zM128 384v128h128v-128h-128zM384 384v128h128v-128h-128zM0 512v128h128v-128h-128zM512 512v128h128v-128h-128z" />
<glyph glyph-name="y" unicode="y"
d="M0 -128v128h512v-128h-512zM0 256v384h128v-384h-128zM512 0v128h-384v128h384v384h128v-640h-128z" />
<glyph glyph-name="z" unicode="z"
d="M0 0v128h128v128h128v-128h384v-128h-640zM256 256v128h128v-128h-128zM384 384v128h-384v128h640v-128h-128v-128h-128z" />
<glyph glyph-name="braceleft" unicode="{" horiz-adv-x="640"
d="M256 0v128h256v-128h-256zM128 128v256h128v-256h-128zM0 384v128h128v-128h-128zM128 512v256h128v-256h-128zM256 768v128h256v-128h-256z" />
<glyph glyph-name="bar" unicode="|" horiz-adv-x="256"
d="M0 0v896h128v-896h-128z" />
<glyph glyph-name="braceright" unicode="}" horiz-adv-x="640"
d="M0 0v128h256v-128h-256zM256 128v256h128v-256h-128zM384 384v128h128v-128h-128zM256 512v256h128v-256h-128zM0 768v128h256v-128h-256z" />
<glyph glyph-name="asciitilde" unicode="~" horiz-adv-x="896"
d="M0 640v128h128v-128h-128zM384 640v128h256v-128h-256zM128 768v128h256v-128h-256zM640 768v128h128v-128h-128z" />
<glyph glyph-name="uni0410" unicode="&#x410;"
d="M0 0v768h128v-128h384v128h128v-768h-128v512h-384v-512h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="uni0411" unicode="&#x411;"
d="M512 128v384h128v-384h-128zM0 0v896h640v-128h-512v-128h384v-128h-384v-384h384v-128h-512z" />
<glyph glyph-name="uni0412" unicode="&#x412;"
d="M512 128v384h128v-384h-128zM512 640v128h128v-128h-128zM0 0v896h512v-128h-384v-128h384v-128h-384v-384h384v-128h-512z" />
<glyph glyph-name="uni0413" unicode="&#x413;"
d="M0 0v896h640v-128h-512v-768h-128z" />
<glyph glyph-name="uni0414" unicode="&#x414;"
d="M0 -128v256h128v640h128v-640h128v640h-128v128h256v-768h128v-256h-128v128h-384v-128h-128z" />
<glyph glyph-name="uni0415" unicode="&#x415;"
d="M0 0v896h640v-128h-512v-128h256v-128h-256v-384h512v-128h-640z" />
<glyph glyph-name="uni0416" unicode="&#x416;"
d="M0 0v512h128v-512h-128zM512 0v512h128v-512h-128zM0 640v256h128v-256h-128zM256 0v512h-128v128h128v256h128v-256h128v-128h-128v-512h-128zM512 640v256h128v-256h-128z" />
<glyph glyph-name="uni0417" unicode="&#x417;"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM512 128v384h128v-384h-128zM256 512v128h256v-128h-256zM0 640v128h128v-128h-128zM512 640v128h128v-128h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="uni0418" unicode="&#x418;"
d="M256 256v128h128v-128h-128zM0 0v896h128v-640h128v-128h-128v-128h-128zM512 0v384h-128v128h128v384h128v-896h-128z" />
<glyph glyph-name="uni0419" unicode="&#x419;"
d="M256 256v128h128v-128h-128zM0 0v896h128v-640h128v-128h-128v-128h-128zM256 768v128h128v-128h-128zM512 0v384h-128v128h128v384h128v-896h-128z" />
<glyph glyph-name="uni041A" unicode="&#x41a;"
d="M512 0v384h128v-384h-128zM384 384v128h128v-128h-128zM384 640v128h128v-128h-128zM0 0v896h128v-256h256v-128h-256v-512h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="uni041B" unicode="&#x41b;"
d="M0 0v640h128v-640h-128zM128 640v128h128v-128h-128zM512 0v768h-256v128h384v-896h-128z" />
<glyph glyph-name="uni041C" unicode="&#x41c;"
d="M256 512v128h128v-128h-128zM0 0v896h128v-128h128v-128h-128v-640h-128zM512 0v640h-128v128h128v128h128v-896h-128z" />
<glyph glyph-name="uni041D" unicode="&#x41d;"
d="M0 0v896h128v-256h384v256h128v-896h-128v512h-384v-512h-128z" />
<glyph glyph-name="uni041E" unicode="&#x41e;"
d="M128 0v128h384v-128h-384zM0 128v640h128v-640h-128zM512 128v640h128v-640h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="uni041F" unicode="&#x41f;"
d="M0 0v896h640v-896h-128v768h-384v-768h-128z" />
<glyph glyph-name="uni0420" unicode="&#x420;"
d="M512 640v128h128v-128h-128zM0 0v896h512v-128h-384v-128h384v-128h-384v-512h-128z" />
<glyph glyph-name="uni0421" unicode="&#x421;"
d="M128 0v128h384v-128h-384zM512 128v128h128v-128h-128zM0 128v640h128v-640h-128zM512 640v128h128v-128h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="uni0422" unicode="&#x422;"
d="M256 0v768h-256v128h640v-128h-256v-768h-128z" />
<glyph glyph-name="uni0423" unicode="&#x423;"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM0 640v256h128v-256h-128zM512 128v384h-384v128h384v256h128v-768h-128z" />
<glyph glyph-name="uni0424" unicode="&#x424;"
d="M0 512v256h128v-256h-128zM512 512v256h128v-256h-128zM256 0v384h-128v128h128v256h-128v128h384v-128h-128v-256h128v-128h-128v-384h-128z" />
<glyph glyph-name="uni0425" unicode="&#x425;"
d="M0 0v384h128v-384h-128zM512 0v384h128v-384h-128zM128 384v128h128v-128h-128zM384 384v128h128v-128h-128zM256 512v128h128v-128h-128zM128 640v128h128v-128h-128zM384 640v128h128v-128h-128zM0 768v128h128v-128h-128zM512 768v128h128v-128h-128z" />
<glyph glyph-name="uni0426" unicode="&#x426;" horiz-adv-x="896"
d="M640 -128v128h-640v896h128v-768h384v768h128v-768h128v-256h-128z" />
<glyph glyph-name="uni0427" unicode="&#x427;"
d="M0 640v256h128v-256h-128zM512 0v512h-384v128h384v256h128v-896h-128z" />
<glyph glyph-name="uni0428" unicode="&#x428;"
d="M0 0v896h128v-768h128v768h128v-768h128v768h128v-896h-640z" />
<glyph glyph-name="uni0429" unicode="&#x429;" horiz-adv-x="896"
d="M640 -128v128h-640v896h128v-768h128v768h128v-768h128v768h128v-768h128v-256h-128z" />
<glyph glyph-name="uni042A" unicode="&#x42a;" horiz-adv-x="896"
d="M640 128v384h128v-384h-128zM128 0v768h-128v128h256v-256h384v-128h-384v-384h384v-128h-512z" />
<glyph glyph-name="uni042B" unicode="&#x42b;" horiz-adv-x="1024"
d="M512 128v384h128v-384h-128zM0 0v896h128v-256h384v-128h-384v-384h384v-128h-512zM768 0v896h128v-896h-128z" />
<glyph glyph-name="uni042C" unicode="&#x42c;"
d="M512 128v384h128v-384h-128zM0 0v896h128v-256h384v-128h-384v-384h384v-128h-512z" />
<glyph glyph-name="uni042D" unicode="&#x42d;"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM0 640v128h128v-128h-128zM512 128v384h-256v128h256v128h128v-640h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="uni042E" unicode="&#x42e;" horiz-adv-x="896"
d="M384 0v128h256v-128h-256zM640 128v640h128v-640h-128zM0 0v896h128v-256h128v128h128v-640h-128v384h-128v-512h-128zM384 768v128h256v-128h-256z" />
<glyph glyph-name="uni042F" unicode="&#x42f;"
d="M0 0v512h128v-512h-128zM0 640v128h128v-128h-128zM512 0v512h-384v128h384v128h-384v128h512v-896h-128z" />
<glyph glyph-name="uni0430" unicode="&#x430;"
d="M0 128v128h128v-128h-128zM128 0v128h384v128h-384v128h384v128h128v-512h-512zM128 512v128h384v-128h-384z" />
<glyph glyph-name="uni0431" unicode="&#x431;"
d="M128 0v128h384v-128h-384zM512 128v384h128v-384h-128zM0 128v640h128v-128h384v-128h-384v-384h-128zM128 768v128h384v-128h-384z" />
<glyph glyph-name="uni0432" unicode="&#x432;"
d="M512 128v128h128v-128h-128zM512 384v128h128v-128h-128zM0 0v640h512v-128h-384v-128h384v-128h-384v-128h384v-128h-512z" />
<glyph glyph-name="uni0433" unicode="&#x433;"
d="M0 0v640h640v-128h-512v-512h-128z" />
<glyph glyph-name="uni0434" unicode="&#x434;"
d="M0 -128v256h128v384h128v-384h128v384h-128v128h256v-512h128v-256h-128v128h-384v-128h-128z" />
<glyph glyph-name="uni0435" unicode="&#x435;"
d="M128 0v128h512v-128h-512zM0 128v384h128v-128h384v128h128v-256h-512v-128h-128zM128 512v128h384v-128h-384z" />
<glyph glyph-name="uni0436" unicode="&#x436;"
d="M0 0v256h128v-256h-128zM512 0v256h128v-256h-128zM0 384v256h128v-256h-128zM256 0v256h-128v128h128v256h128v-256h128v-128h-128v-256h-128zM512 384v256h128v-256h-128z" />
<glyph glyph-name="uni0437" unicode="&#x437;"
d="M0 0v128h512v-128h-512zM512 128v128h128v-128h-128zM128 256v128h384v-128h-384zM512 384v128h128v-128h-128zM0 512v128h512v-128h-512z" />
<glyph glyph-name="uni0438" unicode="&#x438;"
d="M0 128v512h128v-512h-128zM128 0v128h384v512h128v-640h-512z" />
<glyph glyph-name="uni0439" unicode="&#x439;"
d="M0 128v512h128v-512h-128zM128 0v128h384v512h128v-640h-512zM256 640v128h128v-128h-128z" />
<glyph glyph-name="uni043A" unicode="&#x43a;"
d="M512 0v128h128v-128h-128zM384 128v128h128v-128h-128zM384 384v128h128v-128h-128zM0 0v640h128v-256h256v-128h-256v-256h-128zM512 512v128h128v-128h-128z" />
<glyph glyph-name="uni043B" unicode="&#x43b;"
d="M0 0v384h128v-384h-128zM128 384v128h128v-128h-128zM512 0v512h-256v128h384v-640h-128z" />
<glyph glyph-name="uni043C" unicode="&#x43c;"
d="M256 256v128h128v-128h-128zM0 0v640h128v-128h128v-128h-128v-384h-128zM512 0v384h-128v128h128v128h128v-640h-128z" />
<glyph glyph-name="uni043D" unicode="&#x43d;"
d="M0 0v640h128v-256h384v256h128v-640h-128v256h-384v-256h-128z" />
<glyph glyph-name="uni043E" unicode="&#x43e;"
d="M128 0v128h384v-128h-384zM0 128v384h128v-384h-128zM512 128v384h128v-384h-128zM128 512v128h384v-128h-384z" />
<glyph glyph-name="uni043F" unicode="&#x43f;"
d="M0 0v640h640v-640h-128v512h-384v-512h-128z" />
<glyph glyph-name="uni0440" unicode="&#x440;"
d="M512 128v384h128v-384h-128zM0 -128v768h512v-128h-384v-384h384v-128h-384v-128h-128z" />
<glyph glyph-name="uni0441" unicode="&#x441;"
d="M128 0v128h384v-128h-384zM512 128v128h128v-128h-128zM0 128v384h128v-384h-128zM512 384v128h128v-128h-128zM128 512v128h384v-128h-384z" />
<glyph glyph-name="uni0442" unicode="&#x442;"
d="M256 0v512h-256v128h640v-128h-256v-512h-128z" />
<glyph glyph-name="uni0443" unicode="&#x443;"
d="M0 -128v128h512v-128h-512zM0 256v384h128v-384h-128zM512 0v128h-384v128h384v384h128v-640h-128z" />
<glyph glyph-name="uni0444" unicode="&#x444;"
d="M0 256v256h128v-256h-128zM512 256v256h128v-256h-128zM256 0v128h-128v128h128v256h-128v128h384v-128h-128v-256h128v-128h-128v-128h-128z" />
<glyph glyph-name="uni0445" unicode="&#x445;"
d="M0 0v128h128v-128h-128zM512 0v128h128v-128h-128zM128 128v128h128v-128h-128zM384 128v128h128v-128h-128zM256 256v128h128v-128h-128zM128 384v128h128v-128h-128zM384 384v128h128v-128h-128zM0 512v128h128v-128h-128zM512 512v128h128v-128h-128z" />
<glyph glyph-name="uni0446" unicode="&#x446;"
d="M512 -128v128h-512v640h128v-512h256v512h128v-512h128v-256h-128z" />
<glyph glyph-name="uni0447" unicode="&#x447;"
d="M0 384v256h128v-256h-128zM512 0v256h-384v128h384v256h128v-640h-128z" />
<glyph glyph-name="uni0448" unicode="&#x448;"
d="M0 0v640h128v-512h128v384h128v-384h128v512h128v-640h-640z" />
<glyph glyph-name="uni0449" unicode="&#x449;" horiz-adv-x="896"
d="M640 -128v128h-640v640h128v-512h128v384h128v-384h128v512h128v-512h128v-256h-128z" />
<glyph glyph-name="uni044A" unicode="&#x44a;" horiz-adv-x="896"
d="M640 128v256h128v-256h-128zM128 0v512h-128v128h256v-128h384v-128h-384v-256h384v-128h-512z" />
<glyph glyph-name="uni044B" unicode="&#x44b;" horiz-adv-x="1024"
d="M512 128v256h128v-256h-128zM0 0v640h128v-128h384v-128h-384v-256h384v-128h-512zM768 0v640h128v-640h-128z" />
<glyph glyph-name="uni044C" unicode="&#x44c;"
d="M512 128v256h128v-256h-128zM0 0v640h128v-128h384v-128h-384v-256h384v-128h-512z" />
<glyph glyph-name="uni044D" unicode="&#x44d;"
d="M128 0v128h384v-128h-384zM0 128v128h128v-128h-128zM0 384v128h128v-128h-128zM512 128v128h-256v128h256v128h128v-384h-128zM128 512v128h384v-128h-384z" />
<glyph glyph-name="uni044E" unicode="&#x44e;" horiz-adv-x="896"
d="M384 0v128h256v-128h-256zM640 128v384h128v-384h-128zM0 0v640h128v-256h128v128h128v-384h-128v128h-128v-256h-128zM384 512v128h256v-128h-256z" />
<glyph glyph-name="uni044F" unicode="&#x44f;"
d="M0 0v256h128v-256h-128zM0 384v128h128v-128h-128zM512 0v256h-384v128h384v128h-384v128h512v-640h-128z" />
<glyph glyph-name="quoteleft" unicode="&#x2018;" horiz-adv-x="384"
d="M0 512v256h128v-256h-128zM128 768v128h128v-128h-128z" />
<glyph glyph-name="quoteright" unicode="&#x2019;" horiz-adv-x="384"
d="M0 512v128h128v-128h-128zM128 640v256h128v-256h-128z" />
<glyph glyph-name="quotedblleft" unicode="&#x201c;" horiz-adv-x="640"
d="M0 512v256h128v-256h-128zM256 512v256h128v-256h-128zM128 768v128h128v-128h-128zM384 768v128h128v-128h-128z" />
<glyph glyph-name="quotedblright" unicode="&#x201d;" horiz-adv-x="640"
d="M0 512v128h128v-128h-128zM256 512v128h128v-128h-128zM128 640v256h128v-256h-128zM384 640v256h128v-256h-128z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+167
View File
@@ -0,0 +1,167 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<metadata>
Created by FontForge 20161116 at Mon May 26 10:12:18 2014
By Jimmy Wärting
</metadata>
<defs>
<font id="Minecrafter" horiz-adv-x="679" >
<font-face
font-family="Minecrafter"
font-weight="400"
font-stretch="normal"
units-per-em="1000"
panose-1="0 0 0 0 0 0 0 0 0 0"
ascent="750"
descent="-250"
x-height="784"
cap-height="784"
bbox="19 -68 1247 790"
underline-thickness="0"
underline-position="0"
unicode-range="U+0020-007A"
/>
<missing-glyph horiz-adv-x="500"
/>
<glyph glyph-name=".notdef" horiz-adv-x="500"
/>
<glyph glyph-name=".null" horiz-adv-x="0"
/>
<glyph glyph-name="nonmarkingreturn" horiz-adv-x="1284"
d="M315 130l12 -13v-105l-12 -12h-86v130h86zM438 130v-34h-49v-13h49v-37h-49v-12h49v-34h-92v130h92zM519 34v12h-56v84h99v-34h-62v-13h62v-83h-99v34h56zM611 130v-130h-31v130h31zM636 117l12 13h93v-34h-68v-59h34q0 1 2 3t1 3q-2 2 -9 4t-10 2v31h50v-80h-93l-12 12
v105zM796 130q1 -2 3 -6.5t4 -6.5q1 -2 8.5 -9t9.5 -9t5 -6.5t4 -6.5v44h41v-130h-38q0 2 -2 6t-4 6t-9 9.5t-9 9.5t-5 6t-4 6v-43h-41v130h37zM945 34v12h-56v84h99v-34h-56v-13h56v-83h-99v34h56zM272 37h12v56h-12v-56zM80 340q0 -3 2.5 -10t4.5 -9q1 -1 9 -3t9 -3t3 -9
t3 -10q2 -1 3 -1h3h4q1 0 3 1q1 2 3 10t3 9t9 3t9 3q2 2 4.5 9t1.5 10h50v-180h-53v71q-1 0 -4.5 2.5t-4.5 1.5q-2 -2 -4 -6.5t-2 -6.5h-37q0 2 -2 6.5t-4 6.5q-2 1 -5 -1.5t-5 -2.5v-71h-52v180h49zM358 340v-180h-52v44h-25v-44h-52v180h129zM506 340q1 -2 3 -6.5t3 -6.5
l3 -3t4 -3v-142q-2 -1 -4 -3l-3 -3q-1 -2 -3 -6.5t-3 -6.5h-123v180h123zM673 340v-115h-77v-65h-53v180h130zM747 340v-180h-49v180h49zM784 222l6 6t6 7q2 0 7 2.5t6 3.5v4q0 2 0.5 3t0.5 2t-0.5 2t-0.5 3v4q-1 1 -6 3.5t-7 2.5q-1 2 -6 7l-6 6l-12 6v56h49q1 -2 3 -6.5
t3 -6.5l25 -25h3h3l25 25q1 2 3 6.5t3 6.5h49v-56q-1 -1 -5.5 -3t-6.5 -3q-3 -3 -10.5 -10t-7.5 -9q-1 0 -1.5 -3.5t-0.5 -5.5t0.5 -5.5t1.5 -3.5q0 -2 7.5 -9t10.5 -10q2 -1 6.5 -3t5.5 -3v-56h-49q-1 2 -3 6.5t-3 6.5l-25 25h-3h-3l-25 -25q-1 -2 -3 -6.5t-3 -6.5h-49v56z
M1093 340v-47h-74v-18h74v-50h-74v-18h74v-47h-130v180h130zM1170 340v-133h77v-47h-130v180h53zM438 210h25v80h-25v-80zM284 253h19v43h-19v-43zM599 278h18v12h-18v-12z" />
<glyph glyph-name="space" unicode=" " horiz-adv-x="500"
/>
<glyph glyph-name="space" unicode="&#xa0;" horiz-adv-x="500"
/>
<glyph glyph-name="Y" unicode="Y" horiz-adv-x="802"
d="M195 281v74h-74v74h-90v349h256v-188h74v-71h80v71h75v188h256v-349h-90v-74h-74v-74h-74v-287h-265v287h-74z" />
<glyph glyph-name="A" unicode="A"
d="M636 784v-784h-256v210h-87v-210h-256v784h599zM296 401h81v198h-81v-198z" />
<glyph glyph-name="B" unicode="b"
d="M636 784v-374h-68v-37h68v-373h-599v784h599zM296 210h81v74h-81v-74zM296 500h81v74h-81v-74z" />
<glyph glyph-name="c" unicode="c" horiz-adv-x="710"
d="M679 784v-207h-383v-370h383v-207h-642v784h642z" />
<glyph glyph-name="D" unicode="d" horiz-adv-x="704"
d="M589 784v-71h71v-642h-71v-71h-552v784h552zM296 210h105v364h-105v-364z" />
<glyph glyph-name="E" unicode="e" horiz-adv-x="667"
d="M630 784v-207h-334v-80h334v-210h-334v-80h334v-207h-593v784h593z" />
<glyph glyph-name="F" unicode="f" horiz-adv-x="660"
d="M630 784v-207h-334v-80h334v-210h-337v-287h-256v784h593z" />
<glyph glyph-name="g" unicode="g" horiz-adv-x="735"
d="M704 784v-207h-408v-367h201v142h207v-352h-667v784h667z" />
<glyph glyph-name="H" unicode="h" horiz-adv-x="716"
d="M287 784v-284h136v284h250v-784h-250v284h-136v-284h-250v784h250z" />
<glyph glyph-name="I" unicode="i" horiz-adv-x="327"
d="M284 784v-784h-247v784h247z" />
<glyph glyph-name="J" unicode="j" horiz-adv-x="648"
d="M355 207v577h250v-784h-586v207h336z" />
<glyph glyph-name="K" unicode="k" horiz-adv-x="685"
d="M287 784v-204h37v108h74v96h250v-275h-83v-74h-77v-86h77v-74h83v-275h-250v96h-74v108h-37v-204h-250v784h250z" />
<glyph glyph-name="L" unicode="l" horiz-adv-x="648"
d="M287 784v-577h336v-207h-586v784h250z" />
<glyph glyph-name="m" unicode="m" horiz-adv-x="864"
d="M287 784v-96h74v-108h136v108h74v96h250v-784h-250v333h-49v-92h-186v92h-49v-333h-250v784h250z" />
<glyph glyph-name="n" unicode="n" horiz-adv-x="741"
d="M287 784v-127h99v-132h61v259h250v-784h-250v127h-98v132h-62v-259h-250v784h250z" />
<glyph glyph-name="o" unicode="o" horiz-adv-x="759"
d="M716 784v-784h-679v784h679zM290 210h173v364h-173v-364z" />
<glyph glyph-name="P" unicode="p" horiz-adv-x="667"
d="M636 784v-559h-343v-225h-256v784h599zM296 414h81v185h-81v-185z" />
<glyph glyph-name="q" unicode="q" horiz-adv-x="759"
d="M37 -3v787h679v-846h-250v59h-429zM290 210h173v364h-173v-364z" />
<glyph glyph-name="R" unicode="r"
d="M636 784v-448h-68v-37h68v-299h-256v284h-87v-284h-256v784h599zM296 500h81v74h-81v-74z" />
<glyph glyph-name="S" unicode="s" horiz-adv-x="691"
d="M401 207v80h-364v497h617v-207h-364v-80h364v-497h-617v207h364z" />
<glyph glyph-name="T" unicode="t" horiz-adv-x="660"
d="M31 577v207h599v-207h-170v-577h-259v577h-170z" />
<glyph glyph-name="u" unicode="u" horiz-adv-x="716"
d="M287 784v-574h136v574h250v-784h-636v784h250z" />
<glyph glyph-name="V" unicode="v"
d="M90 120v142h-59v522h250v-574h111v574h250v-522h-59v-142h-86v-120h-321v120h-86z" />
<glyph glyph-name="w" unicode="w" horiz-adv-x="864"
d="M287 784v-377h49v93h186v-93h49v377h250v-784h-250v71h-74v89h-136v-89h-74v-71h-250v784h250z" />
<glyph glyph-name="x" unicode="x"
d="M117 355v74h-80v355h256v-241h87v241h256v-355h-80v-74h80v-355h-256v241h-87v-241h-256v355h80z" />
<glyph glyph-name="y" unicode="y" horiz-adv-x="660"
d="M114 355v74h-83v355h256v-284h87v284h256v-355h-84v-74h-80v-355h-259v355h-93z" />
<glyph glyph-name="z" unicode="z" horiz-adv-x="698"
d="M120 349v74h87v74h194v80h-364v207h617v-349h-83v-74h-86v-74h-195v-80h364v-207h-617v349h83z" />
<glyph glyph-name="one" unicode="1" horiz-adv-x="420"
d="M25 485v203h46v50h50v46h256v-784h-256v485h-96z" />
<glyph glyph-name="two" unicode="2" horiz-adv-x="704"
d="M108 423v74h287v80h-358v207h552v-71h71v-352h-71v-74h-293v-80h364v-207h-623v423h71z" />
<glyph glyph-name="three" unicode="3" horiz-adv-x="673"
d="M370 207v80h-333v210h333v80h-333v213h528v-77h71v-303h-43v-37h43v-302h-71v-71h-528v207h333z" />
<glyph glyph-name="four" unicode="4" horiz-adv-x="667"
d="M25 287v497h262v-284h74v284h263v-784h-263v287h-336z" />
<glyph glyph-name="five" unicode="5" horiz-adv-x="704"
d="M389 207v80h-281v74h-71v423h623v-207h-358v-80h287v-74h71v-352h-71v-71h-552v207h352z" />
<glyph glyph-name="six" unicode="6" horiz-adv-x="673"
d="M636 784v-207h-334v-80h334v-497h-599v784h599zM302 210h68v74h-68v-74z" />
<glyph glyph-name="seven" unicode="7" horiz-adv-x="660"
d="M19 577v207h599v-784h-263v577h-336z" />
<glyph glyph-name="eight" unicode="8"
d="M80 373v37h-43v374h599v-374h-43v-37h43v-373h-599v373h43zM302 210h68v74h-68v-74zM302 500h68v74h-68v-74z" />
<glyph glyph-name="nine" unicode="9"
d="M370 207v80h-333v497h599v-784h-599v207h333zM302 500h68v74h-68v-74z" />
<glyph glyph-name="zero" unicode="0"
d="M636 784v-784h-599v784h599zM302 210h68v364h-68v-364z" />
<glyph glyph-name="U" unicode="U" horiz-adv-x="710"
d="M37 77v688h250v-574h136v574h250v-688h-96v-96h-444v96h-96z" />
<glyph glyph-name="Q" unicode="Q" horiz-adv-x="809"
d="M133 -9v98h-96v593h96v96h487v-96h99v-500h53v-250h-306v59h-333zM290 204h173v364h-173v-364z" />
<glyph glyph-name="G" unicode="G" horiz-adv-x="735"
d="M37 90v592h96v96h571v-207h-408v-367h201v142h207v-352h-571v96h-96z" />
<glyph glyph-name="C" unicode="C" horiz-adv-x="704"
d="M37 96v592h96v96h540v-207h-383v-370h383v-207h-540v96h-96z" />
<glyph glyph-name="M" unicode="M" horiz-adv-x="809"
d="M287 784v-96h99v-89h37v89h99v96h243v-784h-243v333h-44v-86h-154v86h-37v-333h-250v784h250z" />
<glyph glyph-name="N" unicode="N" horiz-adv-x="809"
d="M293 784v-96h93v-92h99v-96h37v284h243v-784h-243v96h-99v92h-99v96h-37v-284h-250v784h256z" />
<glyph glyph-name="O" unicode="O" horiz-adv-x="802"
d="M37 96v592h90v96h543v-96h95v-592h-95v-96h-543v96h-90zM284 204h228v370h-228v-370z" />
<glyph glyph-name="Z" unicode="Z" horiz-adv-x="698"
d="M120 349v74h87v74h194v80h-364v207h617v-349h-83v-74h-86v-74h-195v-80h364v-207h-617v349h83z" />
<glyph glyph-name="b" unicode="B"
d="M636 784v-374h-68v-37h68v-373h-599v784h599zM296 210h81v74h-81v-74zM296 500h81v74h-81v-74z" />
<glyph glyph-name="d" unicode="D" horiz-adv-x="704"
d="M589 784v-71h71v-642h-71v-71h-552v784h552zM296 210h105v364h-105v-364z" />
<glyph glyph-name="e" unicode="E" horiz-adv-x="667"
d="M630 784v-207h-334v-80h334v-210h-334v-80h334v-207h-593v784h593z" />
<glyph glyph-name="f" unicode="F" horiz-adv-x="660"
d="M630 784v-207h-334v-80h334v-210h-337v-287h-256v784h593z" />
<glyph glyph-name="h" unicode="H" horiz-adv-x="716"
d="M287 784v-284h136v284h250v-784h-250v284h-136v-284h-250v784h250z" />
<glyph glyph-name="i" unicode="I" horiz-adv-x="327"
d="M284 784v-784h-247v784h247z" />
<glyph glyph-name="j" unicode="J" horiz-adv-x="648"
d="M355 207v577h250v-784h-586v207h336z" />
<glyph glyph-name="k" unicode="K" horiz-adv-x="685"
d="M287 784v-204h37v108h74v96h250v-275h-83v-74h-77v-86h77v-74h83v-275h-250v96h-74v108h-37v-204h-250v784h250z" />
<glyph glyph-name="l" unicode="L" horiz-adv-x="648"
d="M287 784v-577h336v-207h-586v784h250z" />
<glyph glyph-name="p" unicode="P" horiz-adv-x="667"
d="M636 784v-559h-343v-225h-256v784h599zM296 414h81v185h-81v-185z" />
<glyph glyph-name="r" unicode="R"
d="M636 784v-448h-68v-37h68v-299h-256v284h-87v-284h-256v784h599zM296 500h81v74h-81v-74z" />
<glyph glyph-name="s" unicode="S" horiz-adv-x="691"
d="M401 207v80h-364v497h617v-207h-364v-80h364v-497h-617v207h364z" />
<glyph glyph-name="t" unicode="T" horiz-adv-x="660"
d="M31 577v207h599v-207h-170v-577h-259v577h-170z" />
<glyph glyph-name="v" unicode="V"
d="M90 120v142h-59v522h250v-574h111v574h250v-522h-59v-142h-86v-120h-321v120h-86z" />
<glyph glyph-name="a" unicode="a"
d="M636 784v-784h-256v210h-87v-210h-256v784h599zM247 377h34v43h111v-43h34v132h-46v47h-87v-47h-46v-132zM197 574h81v74h-81v-74zM395 574h80v74h-80v-74z" />
<glyph glyph-name="X" unicode="X" horiz-adv-x="815"
d="M133 275v74h71v86h-71v74h-96v275h256v-96h74v-71h80v71h75v96h256v-275h-96v-74h-71v-86h71v-74h96v-275h-256v96h-75v71h-80v-71h-74v-96h-256v275h96z" />
<glyph glyph-name="W" unicode="W" horiz-adv-x="809"
d="M287 784v-333h37v86h154v-86h44v333h243v-784h-243v96h-99v89h-37v-89h-99v-96h-250v784h250z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<g>
<g>
<g>
<path d="M256,0C114.618,0,0,114.618,0,256s114.618,256,256,256s256-114.618,256-256S397.382,0,256,0z M256,469.333
c-117.818,0-213.333-95.515-213.333-213.333S138.182,42.667,256,42.667S469.333,138.182,469.333,256S373.818,469.333,256,469.333
z"/>
<path d="M347.582,198.248L256,289.83l-91.582-91.582c-8.331-8.331-21.839-8.331-30.17,0c-8.331,8.331-8.331,21.839,0,30.17
l106.667,106.667c8.331,8.331,21.839,8.331,30.17,0l106.667-106.667c8.331-8.331,8.331-21.839,0-30.17
C369.42,189.917,355.913,189.917,347.582,198.248z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 900 B

+3 -3
View File
@@ -2,14 +2,14 @@
--white: #FFFFFF;
--black: #282828;
--pureblack: #000000;
--font-color: #272727;
--grey: #A3A3A3;
--font-color: #272727;
--grey: #706F6F;
--link-color: #1f9bde;
--linkhover: #00d9ff;
--navlink: #4b4b4b;
--switch: #FBFBFE;
--error: #c23c3c;
--footer-color: #e9e9e9;
--footer-color: #e9e9e9;
}
@font-face {
+10 -2
View File
@@ -1,4 +1,3 @@
import ContactForm from "./components/contact_form/contact";
import './App.css';
import Home from "./components/home/home";
import {BrowserRouter, Route, Routes} from 'react-router-dom';
@@ -7,6 +6,9 @@ import Footer from "./components/footer/footer";
import VerifyMail from "./components/verify_email/verify_mail";
import ThankYou from "./components/verify_email/thank_you";
import DEBUG from "./components/DEBUG/DEBUG";
import {getFormProperties} from "./components/form/formData";
import {FormProperties} from "./components/form/formInterfaces";
import FormActiveRedirect from "./components/form/formActiveRedirect";
function App() {
return (
@@ -15,7 +17,13 @@ function App() {
<BrowserRouter basename="/">
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="/contact" element={<ContactForm/>}/>
{getFormProperties().map((property: FormProperties) => (
<Route
key={property.path}
path={property.path}
element={<FormActiveRedirect {...property.formData} />}
/>
))}
<Route path="/verify-email" element={<VerifyMail/>}/>
<Route path="/thank-you" element={<ThankYou/>}/>
{process.env.NODE_ENV === 'development' && <Route path="/debug" element={<DEBUG/>}/>}
-11
View File
@@ -1,11 +0,0 @@
.container {
display: flex;
align-items: center;
justify-content: center;
height: 300px;
}
button {
margin: 10px;
cursor: pointer;
}
-49
View File
@@ -1,49 +0,0 @@
.container {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
form {
max-width: 600px;
margin: auto;
padding: 20px;
}
h1 {
text-align: center;
color: #333;
}
label {
display: block;
margin-bottom: 20px;
}
input[type="text"],
input[type="email"],
textarea {
width: 100%;
padding: 10px;
font-size: 1em;
border-radius: 5px;
border: 1px solid #ccc;
}
button,
input[type="submit"] {
padding: 10px 20px;
font-size: 1em;
border-radius: 5px;
border: none;
color: #fff;
background-color: #007BFF;
cursor: pointer;
}
button[disabled],
input[type="submit"][disabled] {
background-color: #ccc;
}
-152
View File
@@ -1,152 +0,0 @@
import React, {useState} from "react";
import './Contact.css';
import {useNavigate} from 'react-router-dom'
import {validationSchema} from "./validationSchema";
import {ErrorMessage, Field, Form, Formik, FormikValues} from "formik";
type InputNames = "username" | "email" | "question";
interface Step {
label: string;
name: InputNames;
type: "text" | "email" | "textarea";
min_length: number;
max_length: number;
required: boolean;
pattern: string;
}
const ContactForm = () => {
const navigate = useNavigate();
const [currentStep, setCurrentStep] = useState<number>(0);
const steps: Step[] = [
{
label: "Username",
name: "username",
type: "text",
min_length: 3,
max_length: 16,
required: true,
pattern: ""
},
{
label: "Email",
name: "email",
type: "email",
min_length: 3,
max_length: 254,
required: true,
pattern: ""
},
{
label: "Question",
name: "question",
type: "textarea",
min_length: 10,
max_length: 2000,
required: true,
pattern: ""
},
]
const handleSubmit = async (e: FormikValues) => {
try {
const response = await fetch('http://localhost:8002/api/contact/submitContactForm', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(e)
})
if (!response.ok) {
alert("Your form submission was denied by the server, or the server was unable to process it, if you didn't mess with the data please contact the administrator at [email protected]");
} else {
navigate('/verify-email', {
state: {
email: e['email']
}
});
}
} catch (e) {
alert("Your form submission was denied by the server, if you didn't mess with the data please contact the administrator at [email protected]")
}
};
const next = () => {
setCurrentStep(current => current + 1)
}
const prev = () => {
setCurrentStep(current => Math.max(current - 1, 0))
}
const [prevLength, setPrevLength] = useState(0);
return (
<div className="container">
<div>
<h1>Contact Form</h1>
</div>
<div>
<Formik
initialValues={{username: '', email: '', question: ''}}
validationSchema={validationSchema}
onSubmit={(values: FormikValues) => {
handleSubmit(values);
}}
>
{({
touched,
errors,
isValid,
handleChange,
values,
setFieldTouched
}) => (
<Form>
<div>
<label>
{steps[currentStep].label}
<Field
type={steps[currentStep].type}
name={steps[currentStep].name}
required={steps[currentStep].required}
min={steps[currentStep].min_length}
max={steps[currentStep].max_length}
as={(steps[currentStep].type === "textarea") ? "textarea" : "input"}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
handleChange(e);
if (prevLength != values[steps[currentStep].name].length) {
setFieldTouched(steps[currentStep].name);
setPrevLength(values[steps[currentStep].name].length);
}
}}
/>
<ErrorMessage name={steps[currentStep].name} component="div"/>
</label>
</div>
<button type="button" onClick={prev} disabled={currentStep === 0}>
Previous
</button>
<button type="button" onClick={next}
hidden={currentStep === (steps.length - 1)}
disabled={(!touched[steps[currentStep].name] || !!errors[steps[currentStep].name]) || currentStep === (steps.length - 1)}>
Next
</button>
<input type="submit" value="Submit"
hidden={currentStep !== (steps.length - 1)}
disabled={!isValid || currentStep !== (steps.length - 1)}
/>
</Form>
)}
</Formik>
</div>
</div>
);
};
export default ContactForm;
@@ -1,20 +0,0 @@
import * as Yup from 'yup';
export const validationSchema = Yup.object().shape({
username: Yup.string()
.min(3, 'Username should be at least 3 characters')
.max(16, 'Username should not exceed 16 characters')
.matches(/^[a-zA-Z0-9_]*$/, 'Username should only include alphanumeric characters and underscore')
.required('Username is required'),
email: Yup.string()
.email('Invalid email')
.min(3, 'Email should be at least 3 characters')
.max(254, 'Email should not exceed 254 characters')
.required(),
question: Yup.string()
.min(10, 'Question should be at least 10 characters')
.max(2000, 'Question should not exceed 2000 characters')
.required('Question is required')
});
+137
View File
@@ -0,0 +1,137 @@
@font-face {
font-family: 'opensans';
src:url('/public/fonts/opensans.ttf') format('truetype'),
url('/public/fonts/opensans.eot') format('embedded-opentype'),
url('/public/fonts/opensans.svg') format('svg'),
url('/public/fonts/opensans.woff') format('woff');
}
@font-face {
font-family: 'opensans-bold';
src:url('/public/fonts/opensans-bold.ttf') format('truetype'),
url('/public/fonts/opensans-bold.eot') format('embedded-opentype'),
url('/public/fonts/opensans-bold.svg') format('svg'),
url('/public/fonts/opensans-bold.woff') format('woff');
}
@font-face {
font-family: 'minecraft-title';
src:url('/public/fonts/minecraft-title.ttf') format('truetype'),
url('/public/fonts/minecraft-title.eot') format('embedded-opentype'),
url('/public/fonts/minecraft-title.svg') format('svg'),
url('/public/fonts/minecraft-title.woff') format('woff');
}
@font-face {
font-family: 'minecraft-text';
src:url('/public/fonts/minecraft-text.ttf') format('truetype'),
url('/public/fonts/minecraft-text.eot') format('embedded-opentype'),
url('/public/fonts/minecraft-text.svg') format('svg'),
url('/public/fonts/minecraft-text.woff') format('woff');
}
.container {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
form {
max-width: 600px;
margin: auto;
padding: 20px;
margin-bottom: 90px;
}
h1 {
text-align: center;
color: #333;
margin-top: 100px;
}
.headline {
margin-bottom: 20px;
}
.description {
font-size: 0.85rem;
color: var(--grey);
}
label {
display: block;
}
input[type="text"],
input[type="email"],
textarea {
width: 100%;
padding: 10px;
font-size: 1em;
border-radius: 5px;
border: 1px solid #ccc;
}
input[type="date"] {
width: 150px;
padding: 5px 5px 5px 5px;
font-size: 16px;
border: 1px solid #CCC;
height: 34px;
border-radius: 5px;
}
button[disabled],
input[type="submit"][disabled] {
background-color: #ccc;
}
.button-outer {
display: inline-block;
font-family: 'minecraft-text', sans-serif;
font-size: 0.8em;
padding: 15px 35px;
background: var(--link-color);
color: #ffffff;
letter-spacing: 1px;
border: none;
border-radius: 5px;
height: auto;
transition: all 100ms cubic-bezier(0.55, 0.085, 0.68, 0.53), 0.5s background ease;
cursor: pointer;
text-shadow: 1px 1px 0px black;
margin: 10px;
}
.button-outer:hover {
color: var(--pureblack);
text-shadow: 1px 1px 0px white;
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.5);
transform: scale(1.1);
}
.button-outer:focus, .button-outer:active {
color: var(--white);
background: #8b8a8f;
}
select {
width: 150px;
padding: 5px 35px 5px 5px;
font-size: 16px;
border: 1px solid #CCC;
height: 34px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: url(../../../public/img/down-arrow.svg) 96% / 15% no-repeat #EEE;
border-radius: 5px;
}
.error-message {
color: var(--error);
margin: 5px 0 15px 0;
font-size: 0.8rem;
}
+218
View File
@@ -0,0 +1,218 @@
import {FormData} from "../formInterfaces";
import * as Yup from "yup";
export const apply: FormData = {
steps: [
{
label: "What is your Minecraft username?",
name: "username",
type: "text",
min_length: 3,
max_length: 16,
required: true,
},
{
label: "What is your email?",
name: "email",
type: "email",
min_length: 3,
max_length: 254,
required: true,
},
{
label: "What is your Discord username?",
name: "discord",
type: "text",
min_length: 2,
max_length: 32,
required: true,
},
{
label: "Do you meet the minimum pc requirements?",
name: "pc_requirements",
type: "dropdown",
min_length: 2,
max_length: 3,
required: true,
additional_info: "Use voice chat in Discord with reasonable audio quality\n" +
"Take screenshots through your pc (normally f2 in minecraft)\n" +
"Record your screen through your pc at 20fps+ and 720p+ at normal Minecraft settings (with free programs like OBS)\n",
drop_down: ["Yes", "No", ""],
},
{
label: "What is your age?",
name: "age",
type: "text",
min_length: 1,
max_length: 3,
required: true,
},
{
label: "What is your preferred pronoun?",
name: "pronoun",
type: "dropdown",
min_length: 0,
max_length: 16,
required: true,
drop_down: ["They/them", "She/her", "He/him", ""],
},
{
label: "When did you join Altitude?",
name: "join_date",
type: "date",
min_length: 4,
max_length: 32,
required: true,
},
{
label: "On average, how many hours per week are you available to moderate Altitude?",
name: "avg_time",
type: "text",
min_length: 1,
max_length: 2,
required: true,
},
{
label: "Which days are you normally able to come on?",
name: "available_days",
type: "select",
min_length: 6,
max_length: 128,
required: true,
drop_down: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
multiple: true
},
{
label: "What time of the day are you normally online?",
name: "available_time",
type: "textarea",
min_length: 3,
max_length: 256,
required: true,
},
{
label: "Do you have any previous experience being staff?",
name: "staff_experience",
type: "textarea",
min_length: 2,
max_length: 2000,
required: true,
},
{
label: "Which server plugins do you have experience with?",
name: "plugin_experience",
type: "textarea",
min_length: 2,
max_length: 2000,
required: true,
},
{
label: "Why are you interested in being a moderator on Altitude?",
name: "why_staff",
type: "textarea",
min_length: 2,
max_length: 2000,
required: true,
},
{
label: "What do you believe are the expectations of a moderator?",
name: "expectations_mod",
type: "textarea",
min_length: 2,
max_length: 2000,
required: true,
},
{
label: "You may share anything else you wish here.",
name: "other",
type: "textarea",
min_length: 2,
max_length: 2000,
required: false,
},
],
backend: `${process.env.REACT_APP_BACKEND_BASE_URL}/api/apply/staffApplication`,
userInput: {username: '', email: '', discord: '', pc_requirements: ''
, age: '', pronoun: '', join_date: '', avg_time: '', available_days: '', available_time: '', staff_experience: ''
, plugin_experience: '', why_staff: '', expectations_mod: '', other: ''
},
spec: Yup.object().shape({
username: Yup.string()
.min(3, 'Username should be at least 3 characters')
.max(16, 'Username should not exceed 16 characters')
.matches(/^[a-zA-Z0-9_]*$/, 'Username should only include alphanumeric characters and underscore')
.required('Please enter your username'),
email: Yup.string()
.email('Invalid email')
.min(3, 'Email should be at least 3 characters')
.max(254, 'Email should not exceed 254 characters')
.required('Please enter your email'),
discord: Yup.string()
.min(2, 'Discord name should be at least 2 characters')
.max(32, 'Discord name should be at most 32 characters')
.matches(/^(?!.*\.\.)([a-z0-9._]{2,32})$/, 'Please enter a valid Discord name')
.required('Please enter your Discord name'),
pc_requirements: Yup.string()
// .min(2, "Please answer yes or no")
// .max(3, "Please answer yes or no")
.matches(/(yes|no)$/i, 'Yes or no')
.required('An answer is required'),
age: Yup.number()
.typeError('Input must be a number')
.min(0, 'Please enter a valid age')
.max(999, 'We do not accept players older than 999 years old sorry!')
.required('You are required to fill out your age'),
pronoun: Yup.string()
.max(16, 'Pronouns can\'t be longer than 16 characters'),
join_date: Yup.date()
.required('Your join date is required, if you\'re not sure enter an estimated date'),
avg_time: Yup.number()
.typeError('Please enter a number')
.min(0, 'Please enter a positive number')
.max(168, 'There are only 168 hours in a week')
.required('Please enter the average time you will be available each week'),
available_days: Yup.lazy(value =>
Array.isArray(value)
? Yup.array().of(Yup.string()).min(1).max(7).required('Please select the days you will be available on')
: Yup.string().required('Please select the days you will be available on')
),
available_time: Yup.string()
.min(3, 'Please provide at least 3 characters')
.max(256, 'Please provide at most 256 characters')
.required('Please enter your available time'),
staff_experience: Yup.string()
.min(2, 'Please provide your experience as staff, if you don\'t have any you can say that instead')
.max(2000, 'Please provide at most 2000 characters')
.required('Please enter your staff experience or simply say you don\'t have any'),
plugin_experience: Yup.string()
.min(2, 'Please provide your experience with moderation plugins, if you don\'t have any you can say that instead')
.max(2000, 'Please provide at most 2000 characters')
.required('Please enter your plugin experience or simply say you don\'t have any'),
why_staff: Yup.string()
.min(2, 'Please provide your reason for wanting to be a moderator')
.max(2000, 'Please provide at most 2000 characters')
.required('Please enter your reason for wanting to be a moderator on Altitude'),
expectations_mod: Yup.string()
.min(2, 'Please provide your expectations of a moderator')
.max(2000, 'Please provide at most 2000 characters')
.required('Please enter your expectations of what a moderator does'),
other: Yup.string()
.max(2000, 'Please provide at most 2000 characters')
}),
title: "Staff Application",
backendFormName: "StaffApplication",
};
+53
View File
@@ -0,0 +1,53 @@
import {FormData} from "../formInterfaces";
import * as Yup from "yup";
export const contact: FormData = {
steps: [
{
label: "What is your Minecraft username?",
name: "username",
type: "text",
min_length: 3,
max_length: 16,
required: true,
},
{
label: "What is your email?",
name: "email",
type: "email",
min_length: 3,
max_length: 254,
required: true,
},
{
label: "What is your question?",
name: "question",
type: "textarea",
min_length: 10,
max_length: 2000,
required: true,
},
],
backend: `${process.env.REACT_APP_BACKEND_BASE_URL}/api/contact/submitContactForm`,
userInput: {username: '', email: '', question: ''},
spec: Yup.object().shape({
username: Yup.string()
.min(3, 'Username should be at least 3 characters')
.max(16, 'Username should not exceed 16 characters')
.matches(/^[a-zA-Z0-9_]*$/, 'Username should only include alphanumeric characters and underscore')
.required('Username is required'),
email: Yup.string()
.email('Invalid email')
.min(3, 'Email should be at least 3 characters')
.max(254, 'Email should not exceed 254 characters')
.required(),
question: Yup.string()
.min(10, 'Question should be at least 10 characters')
.max(2000, 'Question should not exceed 2000 characters')
.required('Question is required')
}),
title: "Contact Form",
backendFormName: "ContactForm",
};
@@ -0,0 +1,37 @@
import {FormData} from "./formInterfaces";
import {useEffect, useState, useCallback} from "react";
import GenericForm from "./genericForm";
const FormActiveRedirect = (formData: FormData) => {
const [isLoading, setLoading] = useState(true);
const [isFormActive, setFormActive] = useState(false);
const handleCheckForm = useCallback(async () => {
const result = await fetch(`${process.env.REACT_APP_BACKEND_BASE_URL}/api/checks/formActive`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ formName: formData.backendFormName })
});
const response = await result.json();
setFormActive(response.isActive);
setLoading(false);
}, [formData.backendFormName]);
useEffect(() => {
handleCheckForm().then(() => {});
}, [handleCheckForm]);
if (isLoading) {
return <div className={"container"}><h2>Checking if form is active</h2></div>;
}
if (!isFormActive) {
return <div className={"container"}><h2>The {formData.title} is not currently active</h2></div>;
}
return (
<GenericForm {...formData} />
);
}
export default FormActiveRedirect;
+18
View File
@@ -0,0 +1,18 @@
import {FormProperties} from "./formInterfaces";
import {contact} from "./data/contact";
import {apply} from "./data/apply";
const formProperties: FormProperties[] = [
{
path: 'contact',
formData: contact
},
{
path: 'apply',
formData: apply
},
]
export function getFormProperties(): FormProperties[] {
return formProperties
}
+91
View File
@@ -0,0 +1,91 @@
import React, {useState} from "react";
import './GenericForm.css';
import {Field} from "formik";
import {FormHandlerProps} from "./formInterfaces";
import ReactSelect from 'react-select';
const FormHTML: React.FC<FormHandlerProps> = ({
steps,
currentStep,
handleChange,
setFieldTouched,
setFieldValue,
values,
prevLength,
setPrevLength
}) => {
const currentField = steps[currentStep];
let fieldOptions = currentField.drop_down && Array.isArray(currentField.drop_down)
? currentField.drop_down.map((value: string) => ({ value, label: value }))
: [];
const fieldValues = values[currentStep] ? values[currentStep].split(', ').map(value => ({ value, label: value })) : []
const [selectedOptions, setSelectedOptions] = useState(fieldValues);
if (currentField.type === 'select') {
return (
<ReactSelect
name={currentField.name}
isMulti={true}
options={fieldOptions}
value={selectedOptions}
onChange={(selected) => {
let value: string = '';
if (selected === null) {
value = '';
setSelectedOptions([]);
} else if (Array.isArray(selected)) {
value = selected.map(s => s.value).join(', ');
setSelectedOptions(selected);
}
setFieldValue(currentField.name, value);
if (prevLength !== value.length) {
setFieldTouched(currentField.name);
setPrevLength(value.length);
}
}}
/>
);
} else if (currentField.type === 'dropdown') {
return (
<Field as="select"
name={steps[currentStep].name}
{...(steps[currentStep].multiple && { multiple: true })}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
handleChange(e);
if (prevLength !== values[steps[currentStep].name].length) {
setFieldTouched(steps[currentStep].name);
setPrevLength(values[steps[currentStep].name].length);
}
}}>
{steps[currentStep].drop_down?.map((option, i) => (
<option key={i} value={option}>
{option}
</option>
))}
</Field>
);
} else {
return (
<Field
type={steps[currentStep].type}
name={steps[currentStep].name}
required={steps[currentStep].required}
min={steps[currentStep].min_length}
max={steps[currentStep].max_length}
as={(steps[currentStep].type === "textarea") ? "textarea" : "input"}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
handleChange(e);
if (prevLength !== values[steps[currentStep].name].length) {
setFieldTouched(steps[currentStep].name);
setPrevLength(values[steps[currentStep].name].length);
}
}}
/>
);
}
};
export default FormHTML;
+47
View File
@@ -0,0 +1,47 @@
import * as Yup from "yup";
import React from "react";
type InputNames = "username" | "email" | "question" | "discord" | "pc_requirements" | "age" | "pronoun" | "join_date" |
"avg_time" | "available_days" | "available_time" | "staff_experience" | "plugin_experience" | "why_staff" |
"expectations_mod" | "other";
export interface Step {
label: string;
name: InputNames;
type: "text" | "email" | "textarea" | "date" | "dropdown" | "select";
min_length: number;
max_length: number;
required: boolean;
additional_info?: string;
drop_down?: string[]
multiple?: boolean
}
export interface UserInput {
[key: string]: string;
}
export type FormData = {
backendFormName: string;
steps: Step[];
backend: string;
userInput: UserInput;
spec: Yup.Schema<any>;
title: string;
}
export interface FormProperties {
path: string
formData: FormData;
}
export type FormHandlerProps = {
steps: Step[];
currentStep: number;
handleChange: (event: React.ChangeEvent<any>) => void;
setFieldTouched: (name: string) => void;
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void;
values: UserInput;
prevLength: number;
setPrevLength: (len: number) => void;
};
+138
View File
@@ -0,0 +1,138 @@
import React, {useState} from "react";
import './GenericForm.css';
import {useNavigate} from 'react-router-dom'
import {ErrorMessage, Form, FormikProvider, FormikValues, useFormik} from "formik";
import {Step, UserInput, FormData} from './formInterfaces';
import * as Yup from "yup";
import FormHTML from "./formHTML";
const GenericForm = (formData: FormData) => {
const steps: Step[] = formData.steps;
const backend: string = formData.backend;
const userInput: UserInput = formData.userInput;
const spec: Yup.Schema<any> = formData.spec;
const navigate = useNavigate();
const [currentStep, setCurrentStep] = useState<number>(0);
const handleSubmit = async (formikValues: FormikValues) => {
console.log(JSON.stringify(formikValues))
try {
const response = await fetch(backend, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formikValues)
})
if (!response.ok) {
let json: string = JSON.stringify(formikValues);
const blob = new Blob([json], {type: "application/json"});
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'your_form_data.json';
link.click();
URL.revokeObjectURL(url);
//TODO clean up
alert("Your form submission was denied by the server, or the server was unable to process it, if you didn't mess with the data please contact the administrator at [email protected]");
} else {
navigate('/verify-email', {
state: {
email: formikValues['email']
}
});
}
} catch (e) {
alert("Your form submission was denied by the server, if you didn't mess with the data please contact the administrator at [email protected]")
}
};
const next = () => {
setCurrentStep(current => current + 1)
}
const prev = () => {
setCurrentStep(current => Math.max(current - 1, 0))
}
const formik = useFormik({
initialValues: userInput,
validationSchema: spec,
onSubmit: (values) => {
handleSubmit(values);
},
});
const {
touched,
errors,
isValid,
handleChange,
values,
setFieldTouched,
setFieldValue,
} = formik;
const [prevLength, setPrevLength] = useState(0);
return (
<div>
<div>
<h1>{formData.title}</h1>
</div>
<div>
<FormikProvider value={formik}>
<Form>
<div>
<div>
<label>
<label className="headline">
{steps[currentStep].label}
</label>
<label className="description">
{
steps[currentStep].additional_info ?
steps[currentStep].additional_info?.split('\n').map((line, i) => (
<React.Fragment key={i}>{line}<br/></React.Fragment>
))
: null
}
</label>
</label>
<label>
<FormHTML steps={steps} currentStep={currentStep} handleChange={handleChange}
setFieldTouched={setFieldTouched} setFieldValue={setFieldValue} values={values}
prevLength={prevLength} setPrevLength={setPrevLength}>
</FormHTML>
</label>
</div>
<div>
<label className="error-message">
<ErrorMessage name={steps[currentStep].name} component="div"/>
</label>
</div>
<div>
<button style={{marginLeft: 0}} className="button-outer" type="button" onClick={prev} disabled={currentStep === 0}>
Previous
</button>
<button className={currentStep === (steps.length - 1) ? "" : "button-outer"} type="button" onClick={next}
hidden={currentStep === (steps.length - 1)}
disabled={(!touched[steps[currentStep].name] || !!errors[steps[currentStep].name]) || currentStep === (steps.length - 1)}>
Next
</button>
<input className={currentStep !== (steps.length - 1) ? "" : "button-outer"} type="submit" value="Submit"
hidden={currentStep !== (steps.length - 1)}
disabled={!isValid || currentStep !== (steps.length - 1)}
/>
</div>
</div>
</Form>
</FormikProvider>
</div>
</div>
);
};
export default GenericForm;
+1 -5
View File
@@ -4,11 +4,7 @@ import './Header.css';
const Header: FC = () => {
return (
<header>
<div></div>
<div></div>
</header>
<div></div>
)
};
+1 -1
View File
@@ -42,7 +42,7 @@ const VerifyMail: FC = () => {
eMail: email
}
console.log(verificationData);
fetch('http://localhost:8002/api/verify_email/form', {
fetch(`${process.env.REACT_APP_BACKEND_BASE_URL}/api/verify_email/form`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',