Skip to content
This repository was archived by the owner on Dec 8, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
5431848
Update Step1.vue
net8floz Feb 5, 2020
cd9830e
Merge branch 'master' into scss-fix
net8floz Feb 5, 2020
26787a5
Merge pull request #61 from codewizardshq/scss-fix
net8floz Feb 5, 2020
c0f2586
post registrations to slack
usrbinsam Feb 7, 2020
c908572
Merge pull request #62 from codewizardshq/slack-webhook
usrbinsam Feb 7, 2020
4ea0ead
real time messaging with Slack
usrbinsam Feb 8, 2020
31cb77f
Merge branch 'master' into slack-webhook
usrbinsam Feb 8, 2020
ab6405b
Merge pull request #63 from codewizardshq/slack-webhook
usrbinsam Feb 8, 2020
c16233a
Update CWHQBar.vue
net8floz Feb 11, 2020
9e5bba4
Update QuizBar.vue
net8floz Feb 11, 2020
7dd2109
Merge branch 'master' into scss-fix
net8floz Feb 11, 2020
e3d5f8a
Merge pull request #64 from codewizardshq/scss-fix
net8floz Feb 11, 2020
ffc40f5
Update SocialPopOver.vue
net8floz Feb 11, 2020
618eb51
Update SocialPopOver.vue
net8floz Feb 11, 2020
4c93098
Update QuizNeedHelp.vue
net8floz Feb 11, 2020
e52ba0a
Update QuizCountdown.vue
net8floz Feb 11, 2020
1070de4
Merge branch 'master' into scss-fix
net8floz Feb 11, 2020
2938106
Merge pull request #65 from codewizardshq/scss-fix
net8floz Feb 11, 2020
f7e75d9
Update QuizNeedHelp.vue
net8floz Feb 11, 2020
107cd37
Merge branch 'master' into scss-fix
net8floz Feb 11, 2020
958a1ab
Merge pull request #66 from codewizardshq/scss-fix
net8floz Feb 11, 2020
3901ce6
Update QuizBar.vue
net8floz Feb 13, 2020
276937f
Merge branch 'master' into scss-fix
net8floz Feb 13, 2020
ac7dbd3
Merge pull request #67 from codewizardshq/scss-fix
net8floz Feb 13, 2020
f801b4e
remove password from account confirmation email
usrbinsam Feb 19, 2020
bca687e
Merge pull request #68 from codewizardshq/welcome-email
usrbinsam Feb 19, 2020
7b3efeb
change FAQ to redirect to https://codewizardshq.com/challenge/
usrbinsam Feb 20, 2020
c0afc73
Merge branch 'master' into faq-redirect
usrbinsam Feb 20, 2020
37ad26e
Merge pull request #69 from codewizardshq/faq-redirect
usrbinsam Feb 20, 2020
4023535
voting: only count confirmed votes on the ballot
usrbinsam Feb 20, 2020
3da8f38
simplifies the age checker
net8floz Feb 20, 2020
45566a7
Merge pull request #70 from codewizardshq/date_fix
net8floz Feb 20, 2020
79f7ae0
changes momentjs text formatting
net8floz Feb 20, 2020
841283a
adds social links and more content to woah page
net8floz Feb 20, 2020
f6b0610
adds mobile warning
net8floz Feb 20, 2020
20df57b
linter fixes
net8floz Feb 20, 2020
88e3c8a
Merge pull request #71 from codewizardshq/woah_boah_page
net8floz Feb 20, 2020
fb3b966
changes content
net8floz Feb 20, 2020
412dfe7
adds github links
net8floz Feb 20, 2020
f720eed
Merge pull request #72 from codewizardshq/mobile-warning
net8floz Feb 20, 2020
33efdc4
Merge branch 'master' into github_links
net8floz Feb 20, 2020
ee480f4
Merge pull request #73 from codewizardshq/github_links
net8floz Feb 20, 2020
ef6bd00
adds twitter link
net8floz Feb 20, 2020
3e7abf5
Merge branch 'master' into woah_boah_page
net8floz Feb 20, 2020
46dc958
more font and label adjustments for forms
net8floz Feb 20, 2020
7270bd7
Merge pull request #74 from codewizardshq/woah_boah_page
net8floz Feb 20, 2020
a9033cd
Merge branch 'master' into more_form_revisions
net8floz Feb 20, 2020
077ef03
Merge pull request #75 from codewizardshq/more_form_revisions
net8floz Feb 20, 2020
e414718
Update CWHQBar.vue
net8floz Feb 21, 2020
2d495af
Merge branch 'master' into github_links
net8floz Feb 21, 2020
48ba94b
Update QuizNeedHelp.vue
net8floz Feb 21, 2020
a0191b4
Update QuizCountdown.vue
net8floz Feb 21, 2020
d39d610
Merge pull request #76 from codewizardshq/github_links
net8floz Feb 21, 2020
ed449f5
update event dates in FAQ
usrbinsam Feb 22, 2020
5611238
Revert "change FAQ to redirect to https://codewizardshq.com/challenge/"
usrbinsam Feb 22, 2020
88a7397
missed FAQ date
usrbinsam Feb 22, 2020
63d9a30
slack: add `!foundus` command for Margaret
usrbinsam Feb 24, 2020
03f8748
Merge pull request #77 from codewizardshq/slack-foundus-command
usrbinsam Feb 24, 2020
bba0dc1
fixes other property in registration
net8floz Feb 25, 2020
0ece720
Merge pull request #78 from codewizardshq/registration-fix
usrbinsam Feb 25, 2020
6c23637
adds email validation
net8floz Feb 26, 2020
312315c
fixes rank display on countdown
net8floz Feb 26, 2020
cf5b511
adds reminders for myself about how the submission works
net8floz Feb 26, 2020
2dc31c0
adds pagination and additional styles
net8floz Feb 26, 2020
7d53a15
fixes modal logic
net8floz Feb 26, 2020
370a2ff
Merge pull request #79 from codewizardshq/voting-touchup
net8floz Feb 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CodeChallenge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from . import core
from .api.eb import bp as eb_bp
from .api.questions import bp as questions_bp
from .api.slack import bp as slack_bp
from .api.users import bp as users_bp
from .api.vote import bp as vote_bp
from .auth import jwt
Expand Down Expand Up @@ -62,6 +63,7 @@ def create_app(config):
app.register_blueprint(q_cli_bp)
app.register_blueprint(clock_cli_bp)
app.register_blueprint(vote_bp)
app.register_blueprint(slack_bp)

@app.errorhandler(429)
def ratelimit_handler(e):
Expand Down
7 changes: 7 additions & 0 deletions CodeChallenge/api/eb.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from hmac import compare_digest

import requests
from flask import Blueprint, request, current_app, render_template
from flask_mail import Message

Expand Down Expand Up @@ -41,4 +42,10 @@ def worker():

mail.send(msg)

webhook = current_app.config.get("SLACK_WEBHOOK")
if webhook is not None:
requests.post(webhook, json=dict(
text=f"*NEW RANK* {core.current_rank()}"
))

return "", 200
91 changes: 91 additions & 0 deletions CodeChallenge/api/slack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import hmac
import re
import time

import requests
from flask import Blueprint, request, jsonify, current_app, abort
from sqlalchemy import func

from .. import core
from ..auth import Users
from ..models import db

bp = Blueprint("slackapi", __name__, url_prefix="/api/v1/slack")

CMDRE = re.compile(r"^!([^ ]+)", re.I)


@bp.before_request
def slack_verify():
ts = request.headers.get("X-Slack-Request-Timestamp")
secret = bytes(current_app.config.get("SLACK_SIGNING_SECRET"), "utf8")
body = request.data

if abs(time.time() - int(ts)) > 60 * 5:
abort(401)

sig_basestring = bytes(f"v0:{ts}:", "utf8")
sig_basestring += body

my_sig = "v0=" + hmac.new(secret, sig_basestring, digestmod="SHA256").hexdigest()
slack_sig = request.headers.get("X-Slack-Signature")
if not hmac.compare_digest(my_sig, slack_sig):
abort(401)


def post_message(channel, text):
rv = requests.post("https://slack.com/api/chat.postMessage",
headers=dict(
Authorization="Bearer " + current_app.config["SLACK_OAUTH_TOKEN"]
),
json=dict(
channel=channel,
text=text
))

rv.raise_for_status()


def handle_message(text, channel):
match = CMDRE.search(text)

if match is None:
return

command = match.group(1)

if command == "status":
rank = core.current_rank()
resp = f"*Current Rank:* {rank if rank != -1 else '(challenge not started)'}\n"
resp += f"*Max Rank:* {core.max_rank()}\n"
resp += f"*Next Rank:* {core.time_until_next_rank()}\n"
resp += f"*Total Users:* {core.user_count()}"

post_message(channel, resp)

if command == "foundus":
found_us = db.session.query(Users.found_us,
func.count(Users.found_us)) \
.group_by(Users.found_us) \
.order_by(Users.found_us) \
.all()

resp = ""
for row in found_us:
resp += f"*{row[0]}*: {row[1]}\n"

post_message(channel, resp)


@bp.route("/event", methods=["POST"])
def slack_event():
data = request.get_json()

if "challenge" in data:
return jsonify(challenge=data["challenge"])

event = data["event"]
if event["type"] == "message":
handle_message(event["text"], event["channel"])

return "", 200
17 changes: 15 additions & 2 deletions CodeChallenge/api/users.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import requests
from flask import Blueprint, jsonify, request, current_app, render_template
from flask_jwt_extended import (create_access_token, create_refresh_token,
get_current_user, get_jwt_identity,
Expand All @@ -6,6 +7,7 @@
unset_jwt_cookies)
from flask_limiter.util import get_remote_address
from flask_mail import Message
from sqlalchemy import func

from .. import core
from ..auth import (Users, hash_password, password_reset_token,
Expand Down Expand Up @@ -146,8 +148,7 @@ def register():
name = new_u.studentfirstname or new_u.parentfirstname
confirm_email.html = render_template("challenge_account_confirm.html",
name=name,
username=new_u.username,
password=password)
username=new_u.username)
confirm_email.extra_headers = {"List-Unsubscribe": "%unsubscribe_email%"}

# welcome email
Expand All @@ -162,6 +163,18 @@ def register():
mail.send(confirm_email)
mail.send(welcome_email)

if "SLACK_WEBHOOK" in current_app.config and not current_app.config.get("TESTING", False):
regcount = db.session.query(func.count(Users.id)).scalar()
webhook = current_app.config.get("SLACK_WEBHOOK")
requests.post(webhook, json=dict(
text="Event: New Registration\n\n"
f"*User*: {new_u.username}\n"
f"*Student*: {new_u.studentfirstname} {new_u.studentlastname}\n"
f"*Parent*: {new_u.parentfirstname} {new_u.parentlastname}\n"
f"*How'd you find us?* {new_u.found_us}\n"
f"\n*Total Registrations*: {regcount}"
))

return jsonify({"status": "success"})


Expand Down
7 changes: 6 additions & 1 deletion CodeChallenge/api/vote.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,15 @@ def get_contestants():
display = f"{ans.user.studentfirstname} " \
f"{ans.user.studentlastname[0]}."

confirmed_votes = []
for v in ans.votes:
if v.confirmed:
confirmed_votes.append(v)

contestants.append(dict(
id=ans.id,
text=ans.text,
numVotes=len(ans.votes),
numVotes=len(confirmed_votes),
firstName=ans.user.studentfirstname,
lastName=ans.user.studentlastname,
username=ans.user.username,
Expand Down
4 changes: 4 additions & 0 deletions CodeChallenge/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class DefaultConfig:
MG_PRIVATE_KEY = os.getenv("MG_PRIVATE_KEY")
MG_LIST = "codechallenge@school.codewizardshq.com"
WORKER_PASSWORD = os.getenv("WORKER_PASSWORD")
SLACK_WEBHOOK = os.getenv("SLACK_WEBHOOK")
SLACK_SIGNING_SECRET = os.getenv("SLACK_SIGNING_SECRET")
SLACK_OAUTH_TOKEN = os.getenv("SLACK_OAUTH_TOKEN")
SLACK_CHANNEL = os.getenv("SLACK_CHANNEL")

# no trailing /
EXTERNAL_URL = "https://challenge.codewizardshq.com"
Expand Down
5 changes: 5 additions & 0 deletions CodeChallenge/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from flask import current_app
from sqlalchemy import func

from .auth import Users
from .models import Question, db


Expand Down Expand Up @@ -68,3 +69,7 @@ def challenge_ended() -> bool:
return True

return False


def user_count() -> int:
return db.session.query(func.count(Users.id)).scalar()
1 change: 0 additions & 1 deletion CodeChallenge/templates/challenge_account_confirm.html
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@
<p><b>{{name}}, your account has been created.</b></p>
<br/>
<p>Login: {{username}}</p>
<p>Password: {{password}}</p>
<br/>
<p>Forgot your password? <a href="https://challenge.codewizardshq.com/forgot-password">Reset your password.</a></p>
</td>
Expand Down
6 changes: 4 additions & 2 deletions src/api/voting.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import routes from "./routes";
import request from "./request";

async function getBallot() {
return request(routes.voting_ballot);
async function getBallot(page, per) {
return request(routes.voting_ballot, {
params: { page, per }
});
}

async function cast(answerId, email) {
Expand Down
22 changes: 22 additions & 0 deletions src/components/MobileWarning.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<div class="mobile-warning" v-if="show">
<img src="/images/logo-small.png" class="mt-6 mb-6" />
<h2 class="mb-3">Come back on your desktop!</h2>
<p class="pa-10">
Our Coding Challenge platform was not created for mobile phones. Please
visit challenge.codewizardshq.com from your desktop for the best
experience.
</p>
<v-btn color="button" @click="show = false">Show me anyways</v-btn>
</div>
</template>

<script>
export default {
data() {
return {
show: true
};
}
};
</script>
25 changes: 15 additions & 10 deletions src/components/QuizNeedHelp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@
<v-card-text>
<v-row no-gutters class="pt-3">
<v-col
v-for="(icon, i) in icons"
v-for="icon in icons"
:key="icon.icon"
:cols="i == icons.length - 1 ? 12 : 6"
cols="6"
class="text-center"
>
<v-btn>
<v-btn :href="icon.to" target="_blank">
<v-icon>mdi-{{ icon.icon }}</v-icon>
</v-btn>
</v-col>
</v-row>
<a class="mt-6" href="https://github.com/codewizardshq/code-challenge"
>Check out the source code on GitHub!</a
>
</v-card-text>
</v-card>
</v-dialog>
Expand All @@ -33,19 +36,21 @@ export default {
dialog: false,
icons: [
{
icon: "twitter"
icon: "twitter",
to: "https://twitter.com/CodeWizardsHQ"
},
{
icon: "facebook"
icon: "facebook",
to: "https://www.facebook.com/events/501020200554546/"
},
{
icon: "whatsapp"
icon: "linkedin",
to: "https://www.linkedin.com/company/codewizardshq"
},
{
icon: "linkedin"
},
{
icon: "email"
icon: "email",
to:
"mailto:?subject=Join%20me%20in%20the%20CodeWizardsHQ%20Code%20Challenge!"
}
]
};
Expand Down
18 changes: 10 additions & 8 deletions src/components/SocialPopOver.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
:cols="i == icons.length - 1 ? 12 : 6"
class="text-center"
>
<v-btn>
<v-btn :to="icon.to" target="_blank">
<v-icon>mdi-{{ icon.icon }}</v-icon>
</v-btn>
</v-col>
Expand All @@ -35,19 +35,21 @@ export default {
isOpen: false,
icons: [
{
icon: "twitter"
icon: "twitter",
to: "https://twitter.com/CodeWizardsHQ"
},
{
icon: "facebook"
icon: "facebook",
to: "https://www.facebook.com/events/501020200554546/"
},
{
icon: "whatsapp"
icon: "linkedin",
to: "https://www.linkedin.com/company/codewizardshq"
},
{
icon: "linkedin"
},
{
icon: "email"
icon: "email",
to:
"mailto:?subject=Join%20me%20in%20the%20CodeWizardsHQ%20Code%20Challenge!"
}
]
})
Expand Down
5 changes: 1 addition & 4 deletions src/components/Toolbars/CWHQBar.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<template>
<v-toolbar class="cwhq-bar" :height="height" :max-height="height">
<v-container>
<v-spacer />
<a href="https://username.codewizardshq.com/edit/">Student Login</a>
<a href="https://username.codewizardshq.com/edit/">Parent Login</a>
<a href="https://codewizardshq.com/students/">Student Center</a>
<a href="https://codewizardshq.com/challenge">Back to CodeWizardsHQ</a>
</v-container>
</v-toolbar>
</template>
Expand Down
7 changes: 5 additions & 2 deletions src/components/Toolbars/QuizBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,13 @@
<v-list-item :to="{ name: 'faq' }">
<v-list-item-title>Check The FAQ</v-list-item-title>
</v-list-item>
<v-list-item href="https://discord.gg/fDWbCj9" target="_blank">
<v-list-item href="https://discord.gg/HKnpzjQ" target="_blank">
<v-list-item-title>Get Help On Discord</v-list-item-title>
</v-list-item>
<v-list-item href="https://www.facebook.com" target="_blank">
<v-list-item
href="https://www.facebook.com/events/501020200554546/"
target="_blank"
>
<v-list-item-title>Get Help On Facebook</v-list-item-title>
</v-list-item>
</v-list>
Expand Down
19 changes: 19 additions & 0 deletions src/store/quiz.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ import { quiz } from "@/api";
import moment from "moment";
import Vue from "vue";

moment.updateLocale("en", {
relativeTime: {
future: "in %s",
past: "%s ago",
s: "a few seconds",
ss: "%d seconds",
m: "a minute",
mm: "%d minutes",
h: "an hour",
hh: "%d hours",
d: "a day",
dd: "%d days",
M: "one month",
MM: "%d months",
y: "a year",
yy: "%d years"
}
});

const moduleName = "Quiz";

function parseDateResponse(dateResponse) {
Expand Down
Loading