Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions frontend/css/green-coding.css
Original file line number Diff line number Diff line change
Expand Up @@ -445,3 +445,15 @@ a {
.hidden {
display: none !important;
}

.custom-mobile-divider {
display: none !important;
}

@media only screen and (max-width: 767px) {
.custom-mobile-divider {
display: block !important;
margin-top: 1em !important;
margin-bottom: 1em !important;
}
}
94 changes: 92 additions & 2 deletions frontend/js/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,69 @@ const populateFieldsFromURL = () => {
if (urlParams.has('schedule_mode')) {
document.querySelector('select[name="schedule_mode"]').value = escapeString(urlParams.get('schedule_mode'));
}
if (urlParams.has('usage_scenario_variables')) {
try {
const variables = JSON.parse(urlParams.get('usage_scenario_variables'));
const variablesContainer = document.getElementById('variables-container');
variablesContainer.innerHTML = '';

for (const key in variables) {
if (Object.hasOwnProperty.call(variables, key)) {
const match = key.match(/^__GMT_VAR_([\w]+)__$/);
if (match) {
addVariableField(match[1], variables[key]);
}
}
}
} catch (e) {
console.error('Failed to parse usage_scenario_variables from URL:', e);
}
}
}

const addVariableField = (keyPart = '', value = '') => {
const variablesContainer = document.getElementById('variables-container');
const newVariableRow = document.createElement('div');
newVariableRow.classList.add('variable-row', 'ui', 'grid', 'middle', 'aligned', 'stackable');

newVariableRow.innerHTML = `
<div class="seven wide column">
<div class="ui right labeled input fluid">
<div class="ui label">__GMT_VAR_</div>
<input type="text" placeholder="Key (Variables are optional. Leave empty if not needed)" class="variable-key" pattern="[\\w]+" title="Only alphanumeric characters and underscores are allowed." value="${escapeString(keyPart)}">
<div class="ui label">__</div>
</div>
</div>
<div class="one wide column computer only tablet only" style="text-align: center; padding: 0;">
=
</div>
<div class="eight wide column">
<div class="ui action input fluid">
<input type="text" placeholder="Value (Variables are optional. Leave empty if not needed)" class="variable-value" value="${escapeString(value)}">
<button type="button" class="ui red mini icon button remove-variable">
<i class="times icon"></i>
</button>
</div>
</div>
`;

variablesContainer.appendChild(newVariableRow);

const divider = document.createElement('div');
divider.classList.add('ui', 'divider', 'custom-mobile-divider');
variablesContainer.appendChild(divider);

updateRemoveButtonsVisibility();
};

const updateRemoveButtonsVisibility = () => {
const variableRows = document.querySelectorAll('#variables-container .variable-row');
variableRows.forEach(row => {
row.querySelector('.remove-variable').style.display = 'inline-block';
});

};


(async () => {

Expand All @@ -48,6 +109,14 @@ const populateFieldsFromURL = () => {
showNotification('Could not get machines data from API', err);
}

$('#add-variable').on('click', () => addVariableField());
addVariableField() // always add one empty row

$('#variables-container').on('click', '.remove-variable', function (e) {
$(this).closest('.variable-row').remove();
updateRemoveButtonsVisibility();
});


document.forms[0].onsubmit = async (event) => {
event.preventDefault();
Expand All @@ -56,6 +125,28 @@ const populateFieldsFromURL = () => {
const data = new FormData(form);
const values = Object.fromEntries(data.entries());

const usageScenarioVariables = {};
let validationError = false;
document.querySelectorAll('#variables-container .variable-row').forEach(row => {
const keyPart = row.querySelector('.variable-key').value.trim();
const value = row.querySelector('.variable-value').value.trim();
if (keyPart) {
if (!/^[\w]+$/.test(keyPart)) {
showNotification('Validation Error', `Variable part "${keyPart}" must only contain alphanumeric characters.`, 'error');
validationError = true;
return;
}
const key = `__GMT_VAR_${keyPart}__`;
usageScenarioVariables[key] = value;
}
});

if (validationError) {
return;
}

values.usage_scenario_variables = usageScenarioVariables;

for (let key in values) {
if (typeof values[key] === 'string') {
values[key] = values[key].trim();
Expand All @@ -65,12 +156,11 @@ const populateFieldsFromURL = () => {
try {
await makeAPICall('/v1/software/add', values);
form.reset()
document.getElementById('variables-container').innerHTML = '';
showNotification('Success', 'Save successful. Check your mail in 10-15 minutes', 'success');
} catch (err) {
showNotification('Could not get data from API', err);
}

}


})();
12 changes: 10 additions & 2 deletions frontend/request.html
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,16 @@ <h1 class="ui header float left">
<option value='statistical-significance'>Do 10 runs to evaluate statistical significance [Premium]</option>
</select>
</div>
<button class="positive ui button">Submit software</button>
</div>
<p style="text-align: right;">Define variables to be used. See the documentation <a href="https://docs.green-coding.io/docs/measuring/usage-scenario/#variables" target="_blank">here</a>.</p>
<div id="variables-container">
</div>
<div style="text-align: right;">
<button type="button" class="ui mini icon button" id="add-variable">
<i class="plus icon"></i> Add Variable
</button>
</div>
</div>
<button class="positive ui button" style="margin-top: 20px;">Submit software</button>
</form>
</div>
</div>
Expand Down