Compare commits
3
Commits
d9d2dbab74
...
38fc595725
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38fc595725 | ||
|
|
e04ce33891 | ||
|
|
bc653a0be4 |
+16
-17
@@ -1,21 +1,20 @@
|
|||||||
version: '3.7'
|
|
||||||
services:
|
services:
|
||||||
# app:
|
app:
|
||||||
# image: visual_critical_discourse_analysis:dev
|
image: visual_critical_discourse_analysis:dev
|
||||||
# container_name: visual_critical_discourse_analysis
|
container_name: visual_critical_discourse_analysis
|
||||||
# build:
|
build:
|
||||||
# context: .
|
context: .
|
||||||
# dockerfile: Dockerfile
|
dockerfile: ./web_ui/Dockerfile
|
||||||
# env_file:
|
env_file:
|
||||||
# - local.env
|
- local.env
|
||||||
# environment:
|
environment:
|
||||||
# - ENV=DEV
|
- ENV=DEV
|
||||||
# ports:
|
ports:
|
||||||
# - 8050:8050
|
- 8050:8050
|
||||||
# networks:
|
networks:
|
||||||
# - backend
|
- backend
|
||||||
# depends_on:
|
depends_on:
|
||||||
# - mongo
|
- mongo
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo:latest
|
image: mongo:latest
|
||||||
container_name: mongo
|
container_name: mongo
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
version: '3.7'
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: visual_critical_discourse_analysis:dev
|
image: visual_critical_discourse_analysis:dev
|
||||||
container_name: visual_critical_discourse_analysis
|
container_name: visual_critical_discourse_analysis
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: ./web_ui/Dockerfile
|
||||||
env_file:
|
env_file:
|
||||||
- server.env
|
- server.env
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
from .classes import VisualSyntaxModelOutput
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
from pydantic import BaseModel, ValidationError
|
|
||||||
from typing import List
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
class OptionNotSetException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ModelOutput(BaseModel):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def classname(cls) -> str:
|
|
||||||
"""Return classname."""
|
|
||||||
return cls.__name__
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def list_fields(cls) -> List[str]:
|
|
||||||
"""List options that are stored as attributes."""
|
|
||||||
return list(cls.model_fields.keys())
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_random(cls):
|
|
||||||
"""Instantiate with random numbers."""
|
|
||||||
kwargs = {field: random.random() for field in cls.list_fields()}
|
|
||||||
return cls(**kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_choice(cls, option: str):
|
|
||||||
"""Instantiate from choice."""
|
|
||||||
if option is None:
|
|
||||||
raise ValidationError()
|
|
||||||
assert isinstance(option, str), "option is not a string"
|
|
||||||
allowed_options_list = cls.list_fields()
|
|
||||||
assert option in allowed_options_list, \
|
|
||||||
f"{option} is not among allowed fields {allowed_options_list}"
|
|
||||||
kwargs = {field: 0 for field in cls.list_fields()}
|
|
||||||
kwargs[option] = 1
|
|
||||||
return cls(**kwargs)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
model_repr_str = f"{self.classname()}("
|
|
||||||
model_repr_str += ", ".join([
|
|
||||||
f"{field}={value:.3f}"
|
|
||||||
for field, value
|
|
||||||
in model_dict.items()
|
|
||||||
])
|
|
||||||
model_repr_str += ")"
|
|
||||||
return model_repr_str
|
|
||||||
|
|
||||||
def highest_score_field(self) -> str:
|
|
||||||
"""Return name of field with highest score."""
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
return max(model_dict, key=lambda k: model_dict[k])
|
|
||||||
|
|
||||||
def highest_score_value(self) -> float:
|
|
||||||
"""Return value of field with highest score."""
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
return max(model_dict.values())
|
|
||||||
|
|
||||||
|
|
||||||
class VisualSyntaxModelOutput(ModelOutput):
|
|
||||||
non_transactional_action: float
|
|
||||||
non_transactional_reaction: float
|
|
||||||
unidirectional_transactional_action: float
|
|
||||||
unidirectional_transactional_reaction: float
|
|
||||||
bidirectional_transactional_action: float
|
|
||||||
bidirectional_transactional_reaction: float
|
|
||||||
conversion: float
|
|
||||||
speech_process: float
|
|
||||||
classification_overt_taxonomy: float
|
|
||||||
analytical_exhaustive: float
|
|
||||||
analytical_disarranged: float
|
|
||||||
analytical_temporal: float
|
|
||||||
analytical_distributed: float
|
|
||||||
analytical_topological: float
|
|
||||||
analytical_exploded: float
|
|
||||||
analytical_inclusive: float
|
|
||||||
symbolic_suggestive: float
|
|
||||||
symbolic_attributive: float
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
m = VisualSyntaxModelOutput.from_random()
|
|
||||||
print(m)
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
CLASS_NAMES = [
|
|
||||||
"non transactional action",
|
|
||||||
"non transactional reaction",
|
|
||||||
"unidirectional transactional action",
|
|
||||||
"unidirectional transactional reaction",
|
|
||||||
"bidirectional transactional action",
|
|
||||||
"bidirectional transactional reaction",
|
|
||||||
"conversion",
|
|
||||||
"speech process",
|
|
||||||
"classification overt taxonomy",
|
|
||||||
"analytical exhaustive",
|
|
||||||
"analytical disarranged",
|
|
||||||
"analytical temporal",
|
|
||||||
"analytical distributed",
|
|
||||||
"anaytical topological",
|
|
||||||
"analytical exploded",
|
|
||||||
"analytical inclusive",
|
|
||||||
"symbolic suggestive",
|
|
||||||
"symbolic attributive"
|
|
||||||
]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from .classes import (
|
|
||||||
ContactModelOutput,
|
|
||||||
AngleModelOutput,
|
|
||||||
PointOfViewModelOutput,
|
|
||||||
DistanceModelOutput,
|
|
||||||
ModalityLightingModelOutput,
|
|
||||||
ModalityColorModelOutput,
|
|
||||||
ModalityDepthModelOutput
|
|
||||||
)
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
from pydantic import BaseModel, ValidationError
|
|
||||||
from typing import List
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
class ModelOutput(BaseModel):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def classname(cls) -> str:
|
|
||||||
"""Return classname."""
|
|
||||||
return cls.__name__
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def list_fields(cls) -> List[str]:
|
|
||||||
"""List options that are stored as attributes."""
|
|
||||||
return list(cls.model_fields.keys())
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_random(cls):
|
|
||||||
"""Instantiate with random numbers."""
|
|
||||||
kwargs = {field: random.random() for field in cls.list_fields()}
|
|
||||||
return cls(**kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_choice(cls, option: str):
|
|
||||||
"""Instantiate from choice."""
|
|
||||||
if option is None:
|
|
||||||
raise ValidationError()
|
|
||||||
assert isinstance(option, str)
|
|
||||||
allowed_options_list = cls.list_fields()
|
|
||||||
assert option in allowed_options_list, \
|
|
||||||
f"{option} is not among allowed fields {allowed_options_list}"
|
|
||||||
kwargs = {field: 0 for field in cls.list_fields()}
|
|
||||||
kwargs[option] = 1
|
|
||||||
return cls(**kwargs)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
model_repr_str = f"{self.classname()}("
|
|
||||||
model_repr_str += ", ".join([
|
|
||||||
f"{field}={value:.3f}"
|
|
||||||
for field, value
|
|
||||||
in model_dict.items()
|
|
||||||
])
|
|
||||||
model_repr_str += ")"
|
|
||||||
return model_repr_str
|
|
||||||
|
|
||||||
def highest_score_field(self) -> str:
|
|
||||||
"""Return name of field with highest score."""
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
return max(model_dict, key=lambda k: model_dict[k])
|
|
||||||
|
|
||||||
def highest_score_value(self) -> float:
|
|
||||||
"""Return value of field with highest score."""
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
return max(model_dict.values())
|
|
||||||
|
|
||||||
|
|
||||||
class ContactModelOutput(ModelOutput):
|
|
||||||
offer: float
|
|
||||||
demand: float
|
|
||||||
|
|
||||||
|
|
||||||
class AngleModelOutput(ModelOutput):
|
|
||||||
high: float
|
|
||||||
eye_level: float
|
|
||||||
low: float
|
|
||||||
|
|
||||||
|
|
||||||
class PointOfViewModelOutput(ModelOutput):
|
|
||||||
frontal: float
|
|
||||||
oblique: float
|
|
||||||
|
|
||||||
|
|
||||||
class DistanceModelOutput(ModelOutput):
|
|
||||||
long: float
|
|
||||||
medium: float
|
|
||||||
close: float
|
|
||||||
|
|
||||||
|
|
||||||
class ModalityLightingModelOutput(ModelOutput):
|
|
||||||
high: float
|
|
||||||
medium: float
|
|
||||||
low: float
|
|
||||||
|
|
||||||
|
|
||||||
class ModalityColorModelOutput(ModelOutput):
|
|
||||||
high: float
|
|
||||||
medium: float
|
|
||||||
low: float
|
|
||||||
|
|
||||||
|
|
||||||
class ModalityDepthModelOutput(ModelOutput):
|
|
||||||
high: float
|
|
||||||
medium: float
|
|
||||||
low: float
|
|
||||||
|
|
||||||
|
|
||||||
# class InterpersonalModelOutput(BaseModel):
|
|
||||||
# contact: ContactModelOutput
|
|
||||||
# angle: AngleModelOutput
|
|
||||||
# point_of_view: PointOfViewModelOutput
|
|
||||||
# distance: DistanceModelOutput
|
|
||||||
# modality_lighting: ModalityLightingModelOutput
|
|
||||||
# modality_color: ModalityColorModelOutput
|
|
||||||
# modality_depth: ModalityDepthModelOutput
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
m = ContactModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = AngleModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = PointOfViewModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = DistanceModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = ModalityLightingModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = ModalityColorModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = ModalityDepthModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
model_labels = {
|
|
||||||
"contact": [
|
|
||||||
"offer",
|
|
||||||
"demand"
|
|
||||||
],
|
|
||||||
"angle": [
|
|
||||||
"high",
|
|
||||||
"eye-level",
|
|
||||||
"low"
|
|
||||||
],
|
|
||||||
"point-of-view": [
|
|
||||||
"frontal",
|
|
||||||
"oblique"
|
|
||||||
],
|
|
||||||
"distance": [
|
|
||||||
"long",
|
|
||||||
"medium",
|
|
||||||
"close"
|
|
||||||
],
|
|
||||||
"modality lighting": [
|
|
||||||
"high",
|
|
||||||
"medium",
|
|
||||||
"low"
|
|
||||||
],
|
|
||||||
"modality color": [
|
|
||||||
"high",
|
|
||||||
"medium",
|
|
||||||
"low"
|
|
||||||
],
|
|
||||||
"modality depth": [
|
|
||||||
"high",
|
|
||||||
"medium",
|
|
||||||
"low"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
from .classes import (
|
|
||||||
InformationValueModelOutput,
|
|
||||||
FramingModelOutput,
|
|
||||||
SalienceModelOutput
|
|
||||||
)
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
from pydantic import BaseModel, ValidationError
|
|
||||||
from typing import List
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
class ModelOutput(BaseModel):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def classname(cls) -> str:
|
|
||||||
"""Return classname."""
|
|
||||||
return cls.__name__
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def list_fields(cls) -> List[str]:
|
|
||||||
"""List options that are stored as attributes."""
|
|
||||||
return list(cls.model_fields.keys())
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_random(cls):
|
|
||||||
"""Instantiate with random numbers."""
|
|
||||||
kwargs = {field: random.random() for field in cls.list_fields()}
|
|
||||||
return cls(**kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_choice(cls, option: str):
|
|
||||||
"""Instantiate from choice."""
|
|
||||||
if option is None:
|
|
||||||
raise ValidationError()
|
|
||||||
assert isinstance(option, str)
|
|
||||||
allowed_options_list = cls.list_fields()
|
|
||||||
assert option in allowed_options_list, \
|
|
||||||
f"{option} is not among allowed fields {allowed_options_list}"
|
|
||||||
kwargs = {field: 0 for field in cls.list_fields()}
|
|
||||||
kwargs[option] = 1
|
|
||||||
return cls(**kwargs)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
model_repr_str = f"{self.classname()}("
|
|
||||||
model_repr_str += ", ".join([
|
|
||||||
f"{field}={value:.3f}"
|
|
||||||
for field, value
|
|
||||||
in model_dict.items()
|
|
||||||
])
|
|
||||||
model_repr_str += ")"
|
|
||||||
return model_repr_str
|
|
||||||
|
|
||||||
def highest_score_field(self) -> str:
|
|
||||||
"""Return name of field with highest score."""
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
return max(model_dict, key=lambda k: model_dict[k])
|
|
||||||
|
|
||||||
def highest_score_value(self) -> float:
|
|
||||||
"""Return value of field with highest score."""
|
|
||||||
model_dict = self.model_dump()
|
|
||||||
return max(model_dict.values())
|
|
||||||
|
|
||||||
|
|
||||||
class InformationValueModelOutput(ModelOutput):
|
|
||||||
given_new: float
|
|
||||||
ideal_real: float
|
|
||||||
central_marginal: float
|
|
||||||
|
|
||||||
|
|
||||||
class FramingModelOutput(ModelOutput):
|
|
||||||
frame_lines: float
|
|
||||||
empty_space: float
|
|
||||||
colour_contrast: float
|
|
||||||
form_contrast: float
|
|
||||||
|
|
||||||
|
|
||||||
class SalienceModelOutput(ModelOutput):
|
|
||||||
size: float
|
|
||||||
colour: float
|
|
||||||
tone: float
|
|
||||||
form: float
|
|
||||||
positioning: float
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
m = InformationValueModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = FramingModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
m = SalienceModelOutput.from_random()
|
|
||||||
print(repr(m))
|
|
||||||
print(m.highest_score_field())
|
|
||||||
print(m.highest_score_value())
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
model_labels = {
|
|
||||||
"information value": [
|
|
||||||
"given-new",
|
|
||||||
"ideal-real",
|
|
||||||
"central-marginal"
|
|
||||||
],
|
|
||||||
"framing": [
|
|
||||||
"frame lines",
|
|
||||||
"empty space",
|
|
||||||
"colour contrast",
|
|
||||||
"form contrast"
|
|
||||||
],
|
|
||||||
"salience": [
|
|
||||||
"size",
|
|
||||||
"colour",
|
|
||||||
"tone",
|
|
||||||
"form",
|
|
||||||
"positioning"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from src.web.app import app
|
|
||||||
from src.web.app import server
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
from .layout import app_layout
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import dash_mantine_components as dmc
|
|
||||||
from dash import html
|
|
||||||
from pathlib import Path
|
|
||||||
from base64 import b64encode
|
|
||||||
|
|
||||||
# read init img
|
|
||||||
init_img_path = Path(__file__).parent / "init_img.png"
|
|
||||||
with open(init_img_path.absolute(), "rb") as fh:
|
|
||||||
init_img_enc = b64encode(fh.read()).decode("utf-8")
|
|
||||||
# generate init img string
|
|
||||||
init_img_src = f"data:image/png;base64, {init_img_enc}"
|
|
||||||
|
|
||||||
image_element = dmc.Center(
|
|
||||||
html.Img(
|
|
||||||
style={
|
|
||||||
"width": "100%",
|
|
||||||
},
|
|
||||||
id="image-container",
|
|
||||||
src=init_img_src
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# build stage
|
||||||
|
FROM python:3.12-slim-bookworm as BUILDER
|
||||||
|
|
||||||
|
# set environment variables
|
||||||
|
ENV PYTHONUNBUFFERED=1 \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PIP_NO_CACHE_DIR=off \
|
||||||
|
PIP_DISABLE_PIP_VERSION_CHECK=ON \
|
||||||
|
PIP_DEFAULT_TIMEOUT=100 \
|
||||||
|
DEBIAN_FRONTEND=noninteractive \
|
||||||
|
POETRY_HOME=/etc/poetry \
|
||||||
|
POETRY_VERSION=1.7.1 \
|
||||||
|
POETRY_VIRTUALENVS_IN_PROJECT=1 \
|
||||||
|
POETRY_VIRTUALENVS_CREATE=1 \
|
||||||
|
POETRY_NO_INTERACTION=1 \
|
||||||
|
POETRY_CACHE_DIR=/tmp/poetry_cache \
|
||||||
|
APP_HOME=/home/app
|
||||||
|
|
||||||
|
# update system
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
curl \
|
||||||
|
&& apt-get clean
|
||||||
|
|
||||||
|
# install poetry
|
||||||
|
RUN curl -sSL https://install.python-poetry.org | python3 -
|
||||||
|
ENV PATH="${POETRY_HOME}/bin:$PATH"
|
||||||
|
|
||||||
|
# install runtime dependencies
|
||||||
|
WORKDIR ${APP_HOME}
|
||||||
|
COPY poetry.lock pyproject.toml ./
|
||||||
|
RUN --mount=type=cache,target=${POETRY_CACHE_DIR} poetry install --without model
|
||||||
|
|
||||||
|
# final stage
|
||||||
|
FROM python:3.12-slim-bookworm
|
||||||
|
|
||||||
|
# copy virtualenv made by poetry
|
||||||
|
ENV APP_HOME=/home/app \
|
||||||
|
VIRTUAL_ENV=/home/app/.venv
|
||||||
|
COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
|
||||||
|
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
|
||||||
|
|
||||||
|
# create home directory and app user
|
||||||
|
RUN mkdir -p /home/app && \
|
||||||
|
addgroup --system app && \
|
||||||
|
adduser --system --group app
|
||||||
|
|
||||||
|
# add code while changing ownership
|
||||||
|
WORKDIR $APP_HOME
|
||||||
|
COPY --chown=app:app ./core ./core
|
||||||
|
COPY --chown=app:app ./web_ui/src ./src
|
||||||
|
|
||||||
|
# change to the app user
|
||||||
|
USER app
|
||||||
|
|
||||||
|
ENTRYPOINT [ "gunicorn", "src.main:server", "-b", "0.0.0.0:8050" ]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .app import app
|
||||||
@@ -245,3 +245,7 @@ def cycle_visual_communication_data(
|
|||||||
response[3] = annotation_values
|
response[3] = annotation_values
|
||||||
logging.info('finished getting visual communication: %s', vis_com_name)
|
logging.info('finished getting visual communication: %s', vis_com_name)
|
||||||
return tuple(response)
|
return tuple(response)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .layout import app_layout
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import dash_mantine_components as dmc
|
import dash_mantine_components as dmc
|
||||||
|
|
||||||
from .image import image_element
|
from .image import image_element
|
||||||
@@ -11,8 +13,8 @@ body_element = dmc.Container(
|
|||||||
grow=True,
|
grow=True,
|
||||||
children=[
|
children=[
|
||||||
dmc.Col([image_element], span=5),
|
dmc.Col([image_element], span=5),
|
||||||
dmc.Col([inputs_element], span=7)
|
dmc.Col([inputs_element], span=7),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from base64 import b64encode
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import dash_mantine_components as dmc
|
||||||
|
from dash import html
|
||||||
|
|
||||||
|
# read init img
|
||||||
|
init_img_path = Path(__file__).parent / 'init_img.png'
|
||||||
|
with open(init_img_path.absolute(), 'rb') as fh:
|
||||||
|
init_img_enc = b64encode(fh.read()).decode('utf-8')
|
||||||
|
# generate init img string
|
||||||
|
init_img_src = f"data:image/png;base64, {init_img_enc}"
|
||||||
|
|
||||||
|
image_element = dmc.Center(
|
||||||
|
html.Img(
|
||||||
|
style={
|
||||||
|
'width': '100%',
|
||||||
|
},
|
||||||
|
id='image-container',
|
||||||
|
src=init_img_src,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
@@ -1,23 +1,25 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import dash_mantine_components as dmc
|
import dash_mantine_components as dmc
|
||||||
|
|
||||||
from .labels import labels_element
|
from .labels import labels_element
|
||||||
|
|
||||||
next_button = dmc.Button(
|
next_button = dmc.Button(
|
||||||
"next".title(),
|
'next'.title(),
|
||||||
id="next-button",
|
id='next-button',
|
||||||
n_clicks=0,
|
n_clicks=0,
|
||||||
fullWidth=True,
|
fullWidth=True,
|
||||||
color="lime",
|
color='lime',
|
||||||
radius="sm",
|
radius='sm',
|
||||||
size="md",
|
size='md',
|
||||||
style={
|
style={
|
||||||
"height": "50px"
|
'height': '50px',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
inputs_element = dmc.SimpleGrid(
|
inputs_element = dmc.SimpleGrid(
|
||||||
children=[
|
children=[
|
||||||
labels_element,
|
labels_element,
|
||||||
next_button
|
next_button,
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import dash_mantine_components as dmc
|
import dash_mantine_components as dmc
|
||||||
|
|
||||||
from .stores import stores_element
|
|
||||||
from .alerts import alerts_element
|
from .alerts import alerts_element
|
||||||
from .header import header_element
|
|
||||||
from .body import body_element
|
from .body import body_element
|
||||||
|
from .header import header_element
|
||||||
|
from .stores import stores_element
|
||||||
|
|
||||||
|
|
||||||
app_layout = dmc.MantineProvider(
|
app_layout = dmc.MantineProvider(
|
||||||
theme={
|
theme={
|
||||||
"fontFamily": '"Inter", sans-serif',
|
'fontFamily': '"Inter", sans-serif',
|
||||||
"components": {
|
'components': {
|
||||||
"NavLink": {
|
'NavLink': {
|
||||||
"styles": {
|
'styles': {
|
||||||
"label": {
|
'label': {
|
||||||
"color": "#c2c7d0"
|
'color': '#c2c7d0',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
children=[
|
children=[
|
||||||
@@ -27,8 +29,8 @@ app_layout = dmc.MantineProvider(
|
|||||||
header_element,
|
header_element,
|
||||||
body_element,
|
body_element,
|
||||||
],
|
],
|
||||||
fluid=True
|
fluid=True,
|
||||||
),
|
),
|
||||||
|
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
@@ -6,10 +6,10 @@ from pathlib import Path
|
|||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
from src.web import app
|
from .app import app
|
||||||
|
|
||||||
# prepare optional local setup
|
# prepare optional local setup
|
||||||
env_path = Path(__file__).parent.parent / 'local.env'
|
env_path = Path(__file__).parent.parent.parent / 'local.env'
|
||||||
load_dotenv(env_path)
|
load_dotenv(env_path)
|
||||||
|
|
||||||
# ensure env vars set
|
# ensure env vars set
|
||||||
@@ -31,18 +31,19 @@ for env_var in necesasary_var_list:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# setup logging stream handler
|
# setup logging stream handler
|
||||||
fmt = (
|
FMT = (
|
||||||
'%(asctime)s | '
|
'%(asctime)s | '
|
||||||
'%(levelname)s | '
|
'%(levelname)s | '
|
||||||
'%(filename)s | '
|
'%(filename)s | '
|
||||||
'%(funcName)s | '
|
'%(funcName)s | '
|
||||||
'%(message)s'
|
'%(message)s'
|
||||||
)
|
)
|
||||||
datefmt = '%Y-%m-%d %H:%M:%S'
|
DATEFMT = '%Y-%m-%d %H:%M:%S'
|
||||||
logging.basicConfig(format=fmt, datefmt=datefmt, level=logging.INFO)
|
logging.basicConfig(format=FMT, datefmt=DATEFMT, level=logging.INFO)
|
||||||
|
|
||||||
logging.info('initialized app')
|
logging.info('initialized app')
|
||||||
server = app.server
|
server = app.server
|
||||||
|
server.config.update(SECRET_KEY=os.urandom(24))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# prepare local env vars
|
# prepare local env vars
|
||||||
Reference in New Issue
Block a user