feat: Add more advanced voting
All checks were successful
Build Docker / Build Image (push) Successful in 22s
All checks were successful
Build Docker / Build Image (push) Successful in 22s
This commit is contained in:
parent
eaf0a23923
commit
e960d6d0ef
2
dist/bundle.js
vendored
2
dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
12
main.py
12
main.py
@ -15,6 +15,8 @@ app = Flask(__name__)
|
|||||||
dotenv.load_dotenv()
|
dotenv.load_dotenv()
|
||||||
|
|
||||||
CURRENT_VOTE = os.getenv('CURRENT_VOTE')
|
CURRENT_VOTE = os.getenv('CURRENT_VOTE')
|
||||||
|
OPTIONS = os.getenv('OPTIONS')
|
||||||
|
OPTIONS = json.loads(OPTIONS)
|
||||||
DISCORD_WEBHOOK = os.getenv('DISCORD_WEBHOOK')
|
DISCORD_WEBHOOK = os.getenv('DISCORD_WEBHOOK')
|
||||||
|
|
||||||
# If votes file doesn't exist, create it
|
# If votes file doesn't exist, create it
|
||||||
@ -52,7 +54,9 @@ def faviconPNG():
|
|||||||
def index():
|
def index():
|
||||||
year = datetime.datetime.now().year
|
year = datetime.datetime.now().year
|
||||||
votes = render.votes()
|
votes = render.votes()
|
||||||
return render_template('index.html',year=year,votes=votes, current_vote=CURRENT_VOTE)
|
options = render.options(OPTIONS)
|
||||||
|
|
||||||
|
return render_template('index.html',year=year,votes=votes, current_vote=CURRENT_VOTE, options=options)
|
||||||
|
|
||||||
@app.route('/<path:path>')
|
@app.route('/<path:path>')
|
||||||
def catch_all(path):
|
def catch_all(path):
|
||||||
@ -167,10 +171,8 @@ def send_discord_message(data):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Send the message as a POST request to the webhook URL
|
# Send the message as a POST request to the webhook URL
|
||||||
response = requests.post(DISCORD_WEBHOOK, data=json.dumps(message), headers={'Content-Type': 'application/json'})
|
if DISCORD_WEBHOOK is not None:
|
||||||
|
requests.post(DISCORD_WEBHOOK, data=json.dumps(message), headers={'Content-Type': 'application/json'})
|
||||||
# Print the response from the webhook (for debugging purposes)
|
|
||||||
print(response.text)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
79
render.py
79
render.py
@ -6,9 +6,20 @@ def votes():
|
|||||||
with open('data/votes.json') as file:
|
with open('data/votes.json') as file:
|
||||||
votes = json.load(file)
|
votes = json.load(file)
|
||||||
|
|
||||||
|
print(votes)
|
||||||
|
|
||||||
options = {}
|
options = {}
|
||||||
|
|
||||||
for vote in votes:
|
for vote in votes:
|
||||||
|
# Check if message is json
|
||||||
|
if vote["message"].startswith("{"):
|
||||||
|
message = json.loads(vote["message"])
|
||||||
|
for key in message:
|
||||||
|
if key in options:
|
||||||
|
options[key] += (int(message[key]) * int(vote["votes"]))
|
||||||
|
else:
|
||||||
|
options[key] = (int(message[key]) * int(vote["votes"]))
|
||||||
|
continue
|
||||||
if vote["message"] in options:
|
if vote["message"] in options:
|
||||||
options[vote["message"]] += vote["votes"]
|
options[vote["message"]] += vote["votes"]
|
||||||
else:
|
else:
|
||||||
@ -45,3 +56,71 @@ def votes():
|
|||||||
html += f'<canvas data-bss-chart=\'{json.dumps(chart_data)}\' class="chartjs-render-monitor"></canvas>'
|
html += f'<canvas data-bss-chart=\'{json.dumps(chart_data)}\' class="chartjs-render-monitor"></canvas>'
|
||||||
|
|
||||||
return html
|
return html
|
||||||
|
|
||||||
|
def options(options):
|
||||||
|
html = '<select id="vote" class="form-select" name="vote" onchange="showHideDiv()">'
|
||||||
|
for option in options:
|
||||||
|
html += f'<option value="{option}">{option}</option>'
|
||||||
|
|
||||||
|
html += '<option value="Advanced">Advanced</option>'
|
||||||
|
html += '</select>'
|
||||||
|
html += f'''
|
||||||
|
<script>function showHideDiv() {{
|
||||||
|
var selectedValue = document.getElementById("vote").value;
|
||||||
|
var divToToggle = document.getElementById("advancedOptions");
|
||||||
|
if (selectedValue === "Advanced") {{
|
||||||
|
divToToggle.style.display = "block";
|
||||||
|
}} else {{
|
||||||
|
divToToggle.style.display = "none";
|
||||||
|
// Set value of all inputs to 0
|
||||||
|
var inputs = document.querySelectorAll('#advancedOptions input[type="number"]');
|
||||||
|
inputs.forEach(function(input) {{
|
||||||
|
input.value = 0;
|
||||||
|
}});
|
||||||
|
// Set value of matching select to 100
|
||||||
|
var select = document.querySelector('#advancedOptions input[name="' + selectedValue + '"]');
|
||||||
|
select.value = 100;
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
</script>
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
html += '<div id="advancedOptions" style="display: none;margin-top: 25px;text-align: left;">'
|
||||||
|
lastOption = options[-1]
|
||||||
|
for option in options:
|
||||||
|
html += '<div class="form-group" style="margin-bottom: 10px;">'
|
||||||
|
html += f'<label for="{option}" style="display: inline;margin-right:10px;">{option}</label>'
|
||||||
|
value = 0
|
||||||
|
if option == options[0]:
|
||||||
|
value = 100
|
||||||
|
|
||||||
|
if not lastOption == option:
|
||||||
|
html += f'<input id="{option}" type="number" name="{option}" value="{value}" class="form-control" style="width: auto; display: inline;margin-right:10px;" min="0" max="100" onchange="updateLastInput()">'
|
||||||
|
html += '% of vote share<br>'
|
||||||
|
else:
|
||||||
|
html += f'<input id="{option}" type="number" name="{option}" value="0" class="form-control" style="width: auto; display: inline;margin-right:10px;" min="0" max="100" readonly>'
|
||||||
|
html += '% of vote share (automatically calculated)<br>'
|
||||||
|
|
||||||
|
|
||||||
|
html += '</div>'
|
||||||
|
html += '</div>'
|
||||||
|
|
||||||
|
|
||||||
|
html += f'''
|
||||||
|
<script>
|
||||||
|
function updateLastInput() {{
|
||||||
|
var inputs = document.querySelectorAll('#advancedOptions input[type="number"]:not([readonly])');
|
||||||
|
var sum = 0;
|
||||||
|
|
||||||
|
inputs.forEach(function(input) {{
|
||||||
|
sum += parseInt(input.value);
|
||||||
|
}});
|
||||||
|
|
||||||
|
var lastInput = document.getElementById('{lastOption}');
|
||||||
|
lastInput.value = 100 - sum;
|
||||||
|
}}
|
||||||
|
</script>
|
||||||
|
'''
|
||||||
|
|
||||||
|
return html
|
30
src/index.js
30
src/index.js
@ -97,13 +97,35 @@ document.addEventListener('DOMContentLoaded', async function() {
|
|||||||
|
|
||||||
document.getElementById('signMessageForm').addEventListener('submit', async function(event) {
|
document.getElementById('signMessageForm').addEventListener('submit', async function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const vote = document.getElementById('vote').value.trim(); // Get the value of the vote input field
|
// Get all inputs in #advancedOptions
|
||||||
|
const inputs = document.querySelectorAll('#advancedOptions input');
|
||||||
|
|
||||||
// Ensure the vote is not empty
|
// Store values in json with matching names
|
||||||
if (!vote) {
|
const options = {};
|
||||||
alert('Please enter your vote.');
|
inputs.forEach(input => {
|
||||||
|
options[input.name] = input.value;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(options);
|
||||||
|
// Make sure the votes total 100
|
||||||
|
let total = 0;
|
||||||
|
for (const key in options) {
|
||||||
|
if (options.hasOwnProperty(key)) {
|
||||||
|
const element = options[key];
|
||||||
|
total += parseInt(element);
|
||||||
|
// If value less than 0 or greater than 100, alert and return
|
||||||
|
if (element < 0 || element > 100) {
|
||||||
|
alert('Votes must be between 0 and 100');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (total !== 100) {
|
||||||
|
alert('Votes must total 100');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const vote = JSON.stringify(options);
|
||||||
|
|
||||||
// Encode the message as a buffer-like object
|
// Encode the message as a buffer-like object
|
||||||
const messageUint8Array = new TextEncoder().encode(vote);
|
const messageUint8Array = new TextEncoder().encode(vote);
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<h4><span id="percent">0</span>% of the voting power.</h4>
|
<h4><span id="percent">0</span>% of the voting power.</h4>
|
||||||
<p class="fs-5 text-muted mb-5">Vote here</p>
|
<p class="fs-5 text-muted mb-5">Vote here</p>
|
||||||
<form class="d-flex justify-content-center flex-wrap" id="signMessageForm" data-bs-theme="light">
|
<form class="d-flex justify-content-center flex-wrap" id="signMessageForm" data-bs-theme="light">
|
||||||
<div class="shadow-lg mb-3"><input class="form-control" type="text" id="vote" name="vote" value="{{vote}}" placeholder="Your Vote"></div>
|
<div class="shadow-lg mb-3">{{options|safe}}</div>
|
||||||
<div class="shadow-lg mb-3"><button class="btn btn-primary" type="submit">Vote</button></div>
|
<div class="shadow-lg mb-3"><button class="btn btn-primary" type="submit">Vote</button></div>
|
||||||
</form>
|
</form>
|
||||||
</div>{{votes|safe}}
|
</div>{{votes|safe}}
|
||||||
|
Loading…
Reference in New Issue
Block a user