Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Settings Menu #552

Draft
wants to merge 16 commits into
base: dev
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions protzilla/constants/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
USER_DATA_PATH = Path(PROJECT_PATH, "user_data")
RUNS_PATH = USER_DATA_PATH / "runs"
WORKFLOWS_PATH = USER_DATA_PATH / "workflows"
SETTINGS_PATH = USER_DATA_PATH / "settings"
EXTERNAL_DATA_PATH = Path(PROJECT_PATH, "user_data/external_data")
WORKFLOW_META_PATH = Path(PROJECT_PATH, "protzilla/constants/workflow_meta.json")
UI_PATH = Path(PROJECT_PATH, "ui")
Expand Down
2 changes: 1 addition & 1 deletion protzilla/data_preprocessing/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from plotly.graph_objects import Figure
from plotly.subplots import make_subplots

from ui.settings.plot_template import *
from protzilla.data_preprocessing.plots_helper import generate_tics
from protzilla.utilities import default_intensity_column
from protzilla.utilities.plot_template import *
from protzilla.constants.colors import *

def create_pie_plot(
Expand Down
34 changes: 0 additions & 34 deletions protzilla/utilities/plot_template.py

This file was deleted.

34 changes: 34 additions & 0 deletions protzilla/utilities/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,37 @@ def get_file_name_from_upload_path(upload_path: str) -> str:
base_name = file_name_randomized.split("_")[0]
file_extension = file_name_randomized.split(".")[-1]
return f"{base_name}.{file_extension}"


def parameters_from_post(post):
d = dict(post)
if "csrfmiddlewaretoken" in d:
del d["csrfmiddlewaretoken"]
parameters = {}
for k, v in d.items():
if len(v) > 1:
# only used for named_output parameters and multiselect fields
parameters[k] = v
else:
parameters[k] = convert_str_if_possible(v[0])
return parameters


def convert_str_if_possible(s):
try:
f = float(s)
return int(f) if int(f) == f else f
except ValueError:
if s == "checked":
# s is a checkbox
return True
if re.fullmatch(r"\d+(\.\d+)?(\|\d+(\.\d+)?)*", s):
# s is a multi-numeric input e.g. 1-0.12-5
numbers_str = re.findall(r"\d+(?:\.\d+)?", s)
numbers = []
for num in numbers_str:
num = float(num)
num = int(num) if int(num) == num else num
numbers.append(num)
return numbers
return s
6 changes: 5 additions & 1 deletion ui/main/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"django.contrib.messages",
"django.contrib.staticfiles",
"runs",
"settings",
]

MIDDLEWARE = [
Expand Down Expand Up @@ -127,7 +128,10 @@

STATIC_URL = "static/"

STATICFILES_DIRS = [BASE_DIR / "static"]
STATICFILES_DIRS = [
BASE_DIR / "static",
BASE_DIR / "settings/static"
]

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
Expand Down
1 change: 1 addition & 0 deletions ui/main/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
urlpatterns = [
path("", views.index),
path("runs/", include("runs.urls")),
path("settings/", include("settings.urls")),
path("databases", views.databases, name="databases"),
path("databases/upload", views.database_upload, name="database_upload"),
path("databases/delete", views.database_delete, name="database_delete"),
Expand Down
1 change: 1 addition & 0 deletions ui/main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def index(request):


def databases(request):
request.session['last_view'] = "databases"
databases = uniprot_databases()
df_infos = {}
if database_metadata_path.exists():
Expand Down
6 changes: 6 additions & 0 deletions ui/runs/static/runs/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,10 @@ html, body {
padding: 10px 8%;
margin-top: 10px;
background-color: rgb(255, 255, 255);
}
.plot-wrapper {
width: fit-content;
height: fit-content;
border: 1px solid #e8edf3;
border-radius: .375rem;
}
22 changes: 10 additions & 12 deletions ui/runs/templates/runs/details.html
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ <h3>{{ display_name }}</h3>
{% if current_plots %}
<div class="mt-4" id="plots">
{% for plot in current_plots %}
<div class="plot-wrapper">
<div class="plot-wrapper mb-2">
{{ plot|safe }}
</div>
{% endfor %}
Expand All @@ -225,15 +225,13 @@ <h3>{{ display_name }}</h3>
<div class="d-flex col">
{% if current_plots %}
<form action="{% url 'runs:download_plots' run_name %}">
<select class="form-select mb-2" name="format">
<option value="png" selected="selected">png</option>
<option value="tiff">tiff</option>
<option value="svg">svg</option>
<option value="pdf">pdf</option>
<option value="eps">eps</option>
<option value="jpg">jpg</option>
</select>
<button class="btn btn-grey">Download plots</button>
<button class="btn btn-grey d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download me-2" viewBox="0 0 16 16">
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z"/>
</svg>
Download plots
</button>
</form>
{% endif %}
</div>
Expand Down Expand Up @@ -278,11 +276,11 @@ <h5 class="modal-title" id="calculationInProgressModalLabel">Do you want back?</
Do you want to proceed?
<hr>
<a href="{% url 'runs:back' run_name %}" id = "backButton" class="btn btn-red mr-auto">Back</a>
<button id= "cancel" type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button id="cancel" type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% if not last_step %}
<button class="btn btn-red" {% if not results_exist %} disabled {% endif %} >Next</button>
Expand Down
13 changes: 11 additions & 2 deletions ui/runs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
format_trace,
get_memory_usage,
name_to_title,
parameters_from_post,
)
from protzilla.workflow import get_available_workflow_names
from protzilla.constants.paths import WORKFLOWS_PATH
Expand All @@ -38,13 +39,14 @@
make_name_field,
make_sidebar,
)
from ui.runs.views_helper import display_message, display_messages, parameters_from_post
from ui.runs.views_helper import display_message, display_messages

from .form_mapping import (
get_empty_plot_form_by_method,
get_filled_form_by_method,
get_filled_form_by_request,
)
from ui.settings.views import get_settings

active_runs: dict[str, Run] = {}

Expand All @@ -68,6 +70,9 @@ def detail(request: HttpRequest, run_name: str):
active_runs[run_name] = Run(run_name)
run: Run = active_runs[run_name]

request.session['last_view'] = "runs:detail"
request.session['run_name'] = run_name

# section, step, method = run.current_run_location()
# end_of_run = not step

Expand Down Expand Up @@ -173,6 +178,9 @@ def index(request: HttpRequest, index_error: bool = False):
:return: the rendered index page
:rtype: HttpResponse
"""

request.session['last_view'] = "runs:index"

return render(
request,
"runs/index.html",
Expand Down Expand Up @@ -447,7 +455,8 @@ def download_plots(request: HttpRequest, run_name: str):
if run_name not in active_runs:
active_runs[run_name] = Run(run_name)
run = active_runs[run_name]
format_ = request.GET["format"]
settings = get_settings("plots")
format_ = settings["file_format"]
index = run.steps.current_step_index
section = run.current_step.section
operation = run.current_step.operation
Expand Down
34 changes: 0 additions & 34 deletions ui/runs/views_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,6 @@
from ui.runs.utilities.alert import build_trace_alert


def parameters_from_post(post):
d = dict(post)
if "csrfmiddlewaretoken" in d:
del d["csrfmiddlewaretoken"]
parameters = {}
for k, v in d.items():
if len(v) > 1:
# only used for named_output parameters and multiselect fields
parameters[k] = v
else:
parameters[k] = convert_str_if_possible(v[0])
return parameters


def convert_str_if_possible(s):
try:
f = float(s)
return int(f) if int(f) == f else f
except ValueError:
if s == "checked":
# s is a checkbox
return True
if re.fullmatch(r"\d+(\.\d+)?(\|\d+(\.\d+)?)*", s):
# s is a multi-numeric input e.g. 1-0.12-5
numbers_str = re.findall(r"\d+(?:\.\d+)?", s)
numbers = []
for num in numbers_str:
num = float(num)
num = int(num) if int(num) == num else num
numbers.append(num)
return numbers
return s


def get_displayed_steps(
steps: StepManager,
) -> list[dict]: # TODO i think this broke with the new naming scheme, should be redone
Expand Down
6 changes: 6 additions & 0 deletions ui/settings/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class SettingsV2Config(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "settings"
78 changes: 78 additions & 0 deletions ui/settings/plot_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import plotly.io as pio
import plotly.graph_objects as go

from protzilla.disk_operator import YamlOperator
from protzilla.constants.colors import PLOT_PRIMARY_COLOR, PLOT_SECONDARY_COLOR
from protzilla.constants.paths import SETTINGS_PATH

def get_settings(section_id: str):
op = YamlOperator()
path = SETTINGS_PATH / (section_id + ".yaml")
settings = op.read(path)
return settings

def determine_font(params: dict):
"""
This method determines if a custom font was selected or not.
"""
if(params["font"] == "Custom"):
font = params["custom_font"]
else:
font = params["font"]
return font

class PlotTemplate:
def __init__(self):
params = get_settings("plots")
font = determine_font(params)
self.layout = go.Layout(
title={
"font": {
"size": params["heading_size"],
"family": font
},
"y": 0.98,
"x": 0.5,
"xanchor": "center",
"yanchor": "top"
},
font={
"size": params["text_size"],
"family": font
},
colorway=[PLOT_PRIMARY_COLOR, PLOT_SECONDARY_COLOR],
plot_bgcolor="white",
yaxis={
"gridcolor": "lightgrey",
"zerolinecolor": "lightgrey"
},
modebar={
"remove": ["autoScale2d", "lasso", "lasso2d", "toImage", "select2d"],
},
dragmode="pan",
height=params["height"],
width=params["width"]
)

def update(self, params: dict):
"""
Updates the used Plotly template. If the dictionary contains a known key, the value will be accepted and saved.
:param params: Dictionary containing properties of the Plotly template.
"""
font = determine_font(params)
self.layout.title.font.size = params["heading_size"]
self.layout.title.font.family = font
self.layout.font.size = params["text_size"]
self.layout.font.family = font
self.layout.height = params["height"]
self.layout.width = params["width"]

def apply(self):
"""
Applies the current template as default template.
"""
pio.templates["plotly_protzilla"] = go.layout.Template(layout=self.layout)

template = PlotTemplate()
template.apply()
pio.templates.default = "plotly_protzilla"
15 changes: 15 additions & 0 deletions ui/settings/static/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
$( document ).ready(function () {
$("#customFontInput").click(function () {
const radio = document.getElementById('customFontRadio');
const input = document.getElementById('customFontInput');
radio.checked = true;
})

$(".action-button").each(function () {
$(this).click(function () {
const form = document.getElementById("settings-form");
form.action = $(this).data("action");
form.submit();
});
});
});
Loading
Loading