diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/main.py b/src/main.py deleted file mode 100644 index 803d203..0000000 --- a/src/main.py +++ /dev/null @@ -1,52 +0,0 @@ -from __future__ import annotations - -import logging -import os -from pathlib import Path - -from dotenv import load_dotenv - -from src.web import app - -# prepare optional local setup -env_path = Path(__file__).parent.parent / 'local.env' -load_dotenv(env_path) - -# ensure env vars set -necesasary_var_list = { - 'MONGO_HOST', - 'MONGO_DB', - 'MONGO_COLLECTION', - 'MONGO_USER', - 'MONGO_PASSWORD', - 'DASH_AUTH_USERNAME', - 'DASH_AUTH_PASSWORD', -} -for env_var in necesasary_var_list: - # ensure env var set - assert ( - env_var in os.environ - ), ( - f"environment variable not set: {env_var}" - ) - -# setup logging stream handler -fmt = ( - '%(asctime)s | ' - '%(levelname)s | ' - '%(filename)s | ' - '%(funcName)s | ' - '%(message)s' -) -datefmt = '%Y-%m-%d %H:%M:%S' -logging.basicConfig(format=fmt, datefmt=datefmt, level=logging.INFO) - -logging.info('initialized app') -server = app.server - -if __name__ == '__main__': - # prepare local env vars - os.environ['MONGO_HOST'] = 'localhost' - # run app - app.run(debug=True) - logging.info('started app') diff --git a/src/model_experiential/__init__.py b/src/model_experiential/__init__.py deleted file mode 100644 index a63e45d..0000000 --- a/src/model_experiential/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .classes import VisualSyntaxModelOutput diff --git a/src/model_experiential/classes.py b/src/model_experiential/classes.py deleted file mode 100644 index 1739af4..0000000 --- a/src/model_experiential/classes.py +++ /dev/null @@ -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()) diff --git a/src/model_experiential/output.py b/src/model_experiential/output.py deleted file mode 100644 index 188234f..0000000 --- a/src/model_experiential/output.py +++ /dev/null @@ -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" -] diff --git a/src/model_interpersonal/__init__.py b/src/model_interpersonal/__init__.py deleted file mode 100644 index 4599135..0000000 --- a/src/model_interpersonal/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from .classes import ( - ContactModelOutput, - AngleModelOutput, - PointOfViewModelOutput, - DistanceModelOutput, - ModalityLightingModelOutput, - ModalityColorModelOutput, - ModalityDepthModelOutput -) diff --git a/src/model_interpersonal/classes.py b/src/model_interpersonal/classes.py deleted file mode 100644 index 8444d64..0000000 --- a/src/model_interpersonal/classes.py +++ /dev/null @@ -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()) diff --git a/src/model_interpersonal/output.py b/src/model_interpersonal/output.py deleted file mode 100644 index 14c84a9..0000000 --- a/src/model_interpersonal/output.py +++ /dev/null @@ -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" - ] -} diff --git a/src/model_textual/__init__.py b/src/model_textual/__init__.py deleted file mode 100644 index a60055f..0000000 --- a/src/model_textual/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .classes import ( - InformationValueModelOutput, - FramingModelOutput, - SalienceModelOutput -) diff --git a/src/model_textual/classes.py b/src/model_textual/classes.py deleted file mode 100644 index e0c269d..0000000 --- a/src/model_textual/classes.py +++ /dev/null @@ -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()) diff --git a/src/model_textual/output.py b/src/model_textual/output.py deleted file mode 100644 index 8a4e08a..0000000 --- a/src/model_textual/output.py +++ /dev/null @@ -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" - ] -} diff --git a/src/web/__init__.py b/src/web/__init__.py deleted file mode 100644 index 3bb26dd..0000000 --- a/src/web/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from __future__ import annotations - -from src.web.app import app -from src.web.app import server diff --git a/src/web/app.py b/src/web/app.py deleted file mode 100644 index 151fcd9..0000000 --- a/src/web/app.py +++ /dev/null @@ -1,247 +0,0 @@ -from __future__ import annotations - -import logging -import os - -import dash_bootstrap_components as dbc -from dash import ALL -from dash import Dash -from dash import Input -from dash import Output -from dash import State -from dash_auth import BasicAuth -from pydantic import ValidationError - -from .layout import app_layout -from core.database import connect -from core.database import count_documents -from core.database import get_visual_communication -from core.database import NoDocumentFoundException -from core.database import upsert_annotation -from core.database import upsert_visual_communication -from core.database import VisualCommunication -from core.dto import ModelData - -# setup app -app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP]) -app.title = 'visual critical discourse analysis'.title() -app.layout = app_layout -server = app.server - -# setup authentication -AUTH_DICT = { - os.getenv('DASH_AUTH_USERNAME'): os.getenv('DASH_AUTH_PASSWORD'), -} -BasicAuth(app, AUTH_DICT) - -# connect to database -collection, db, client = connect() - - -# define callbacks -@app.callback( - Output('alert-element', 'is_open'), - Output('alert-element', 'children'), - Input('alert-message', 'data'), -) -def show_alert( - msg: str | None, -): - if msg is None or msg == '': - return False, '' - logging.info(f'updated alert message: {msg}') - return True, msg - - -@app.callback( - Output('success-element', 'is_open'), - Output('success-element', 'children'), - Input('success-message', 'data'), -) -def show_success( - msg: str | None, -): - if msg is None or msg == '': - return False, '' - logging.info(f"updated success message: {msg}") - return True, msg - - -@app.callback( - Output('progress-bar', 'value'), - Output('progress-bar', 'max'), - Output('progress-bar', 'label'), - Input('next-button', 'n_clicks'), - Input('upload-data', 'filename'), -) -def update_progress_bar( - n_clicks: int, - filename_list: list[str] | None, -): - logging.info('began updating progress bar') - global collection - # get values from database - num_total = count_documents( - collection=collection, - only_with_annotation=False, - ) - num_handled = count_documents( - collection=collection, - only_with_annotation=True, - ) - limit = int(num_total/20) - label_str = f"{num_handled}/{num_total}" if num_handled >= limit else '' - return num_handled, num_total, label_str - - -@app.callback( - Output('success-message', 'data', allow_duplicate=True), - Output('alert-message', 'data', allow_duplicate=True), - Input('upload-data', 'contents'), - State('upload-data', 'filename'), - prevent_initial_call=True, -) -def upload_images( - content_list: list[str] | None, - filename_list: list[str] | None, -): - logging.info('began uploading images') - global collection - # stop early if possible - if content_list is None or filename_list is None: - logging.warning('content_list is None -> nothing to upload') - return None, 'nothing selected to upload'.title() - # build list of visual communication - visual_communication_list = [] - for content, filename in zip(content_list, filename_list): - try: - image = VisualCommunication.decode_image(content) - vis_com = VisualCommunication( - name=filename, - image=image, - ) - except Exception as exc: - logging.warning( - ( - 'failed creating VisualCommunication object ' - f"from file {filename}" - ), - exc, - ) - else: - visual_communication_list.append(vis_com) - # upsert documents - success = upsert_visual_communication( - collection=collection, - visual_communication_list=visual_communication_list, - ) - if success: - logging.info(f"succesfully uploaded {len(filename_list)} images") - return 'successfully uploaded images'.title(), None - logging.warning('failed inserting images into database') - return None, 'failed uploading images'.title() - - -@app.callback( - Output('alert-message', 'data', allow_duplicate=True), - Output('vis-com-name', 'data'), - Output('image-container', 'src'), - Output({'type': 'annotation', 'index': ALL}, 'value'), - Input('next-button', 'n_clicks'), - State('vis-com-name', 'data'), - State('image-container', 'src'), - State({'type': 'annotation', 'index': ALL}, 'id'), - State({'type': 'annotation', 'index': ALL}, 'value'), - prevent_initial_call=True, -) -def cycle_visual_communication_data( - n_clicks: int, - vis_com_name: str, - image_src: str, - annotation_keys: list, - annotation_values: list, -): - logging.info('began cycling visual communication data') - global collection - # prepare default response - response = [ - '', - vis_com_name, - image_src, - annotation_values, - ] - # check if next-button clicked - if n_clicks == 0: - logging.info('stopping early: next-button has not yet been clicked') - return response - # check if visual communication name is set - if len(vis_com_name) > 0: - logging.info('saving annotations to database: %s', vis_com_name) - try: - # extract option keys - annotation_keys = [ - elem['index'] - for elem in annotation_keys - ] - # ensure all options are set - logging.info(annotation_keys) - for option, value in zip(annotation_keys, annotation_values): - if value is None: - raise ValueError(f"{option} is not set") - # prepare data to save - annotation_keys = [ - elem.replace(' ', '_') - for elem - in annotation_keys - ] - annotation_values = [ - elem.replace(' ', '_').lower() - for elem - in annotation_values - ] - annotation_map = { - key: value - for key, value - in zip(annotation_keys, annotation_values) - } - # instantiate ModelOutputs object - annotations = ModelData.from_annotations(**annotation_map) - # save data to database - upsert_annotation( - collection=collection, - vis_com_name=vis_com_name, - annotations=annotations, - ) - except (ValueError, ValidationError) as exc: - msg = f"failed saving annotation: {exc}" - logging.warning(msg) - response[0] = msg - return tuple(response) - # get new visual communication - logging.info('trying to get new visual communication') - try: - # get data - vis_com = get_visual_communication( - collection=collection, - with_annotation=False, - ) - # set variables - vis_com_name = vis_com.name - image_src = vis_com.webencoded_image() - if vis_com.prediction is not None: - # TODO: update to use optional predictions - pass - else: - # reset annotations - annotation_values = [None for elem in annotation_values] - except NoDocumentFoundException: - msg = 'no unannotated data in database' - logging.warning(msg) - response[0] = msg - return tuple(response) - else: - response[1] = vis_com_name - response[2] = image_src - response[3] = annotation_values - logging.info('finished getting visual communication: %s', vis_com_name) - return tuple(response) diff --git a/src/web/layout/__init__.py b/src/web/layout/__init__.py deleted file mode 100644 index e3ea6c9..0000000 --- a/src/web/layout/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .layout import app_layout diff --git a/src/web/layout/alerts.py b/src/web/layout/alerts.py deleted file mode 100644 index 8be4a69..0000000 --- a/src/web/layout/alerts.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import annotations - -import dash_bootstrap_components as dbc -from dash import html - - -alerts_element = html.Div( - children=[ - dbc.Alert( - children='', - id='alert-element', - dismissable=True, - fade=False, - is_open=False, - ), - dbc.Alert( - children='', - id='success-element', - is_open=False, - duration=1000, - ), - ], -) diff --git a/src/web/layout/body.py b/src/web/layout/body.py deleted file mode 100644 index 0765e34..0000000 --- a/src/web/layout/body.py +++ /dev/null @@ -1,18 +0,0 @@ -import dash_mantine_components as dmc - -from .image import image_element -from .inputs import inputs_element - - -body_element = dmc.Container( - fluid=True, - children=[ - dmc.Grid( - grow=True, - children=[ - dmc.Col([image_element], span=5), - dmc.Col([inputs_element], span=7) - ], - ) - ], -) diff --git a/src/web/layout/header.py b/src/web/layout/header.py deleted file mode 100644 index a4436f5..0000000 --- a/src/web/layout/header.py +++ /dev/null @@ -1,62 +0,0 @@ -from __future__ import annotations - -import dash_bootstrap_components as dbc -import dash_mantine_components as dmc -from dash import dcc -from dash import html - -title_element = dmc.Center( - children=[ - html.H2( - children=[ - 'Visual Critical Discourse Analysis Tool', - ], - ), - ], -) - -progress_bar_element = dbc.Progress( - id='progress-bar', - max=100, - value=0, - color='lime', - label='', - style={ - 'width': '400px', - }, -) - -upload_button_element = dcc.Upload( - children=[ - dmc.Button( - 'upload images'.title(), - id='upload-button', - color='lime', - n_clicks=0, - variant='outline', - radius='sm', - size='md', - ), - ], - multiple=True, - id='upload-data', - accept='image/png,image/jpeg,image/jpg', -) - -header_element = dmc.Header( - height=80, - children=[ - dmc.Group( - children=[ - title_element, - progress_bar_element, - upload_button_element, - ], - position='apart', - style={ - 'margin': '10px', - 'padding': '10px', - }, - ), - ], -) diff --git a/src/web/layout/image.py b/src/web/layout/image.py deleted file mode 100644 index a32819a..0000000 --- a/src/web/layout/image.py +++ /dev/null @@ -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 - ) -) diff --git a/src/web/layout/init_img.png b/src/web/layout/init_img.png deleted file mode 100644 index 7d821df..0000000 Binary files a/src/web/layout/init_img.png and /dev/null differ diff --git a/src/web/layout/inputs.py b/src/web/layout/inputs.py deleted file mode 100644 index a7a6802..0000000 --- a/src/web/layout/inputs.py +++ /dev/null @@ -1,23 +0,0 @@ -import dash_mantine_components as dmc - -from .labels import labels_element - -next_button = dmc.Button( - "next".title(), - id="next-button", - n_clicks=0, - fullWidth=True, - color="lime", - radius="sm", - size="md", - style={ - "height": "50px" - } -) - -inputs_element = dmc.SimpleGrid( - children=[ - labels_element, - next_button - ] -) diff --git a/src/web/layout/labels.py b/src/web/layout/labels.py deleted file mode 100644 index 510b70f..0000000 --- a/src/web/layout/labels.py +++ /dev/null @@ -1,113 +0,0 @@ -from __future__ import annotations - -import dash_mantine_components as dmc -from dash import dcc -from dash import html - -from core.dto import AngleData -from core.dto import ContactData -from core.dto import DistanceData -from core.dto import FramingData -from core.dto import InformationValueData -from core.dto import ModalityColorData -from core.dto import ModalityDepthData -from core.dto import ModalityLightingData -from core.dto import PointOfViewData -from core.dto import SalienceData -from core.dto import VisualSyntaxData - - -def generate_visual_syntax_options_map(): - """Generate map of titles and options for visual syntax labels.""" - options_map = {} - # add experiential labels - options_map['visual syntax'] = VisualSyntaxData.list_fields() - return options_map - - -def generate_interpersonal_options_map(): - """Generate map of titles and options for interpersonal labels.""" - options_map = {} - # add interpersonal labels - options_map['contact'] = ContactData.list_fields() - options_map['angle'] = AngleData.list_fields() - options_map['point of view'] = PointOfViewData.list_fields() - options_map['distance'] = DistanceData.list_fields() - options_map['modality lighting'] = ModalityLightingData.list_fields() - options_map['modality color'] = ModalityColorData.list_fields() - options_map['modality depth'] = ModalityDepthData.list_fields() - return options_map - - -def generate_textual_options_map(): - """Generate map of titles and options for textual labels.""" - options_map = {} - # add textual labels - options_map['information value'] = InformationValueData.list_fields() - options_map['framing'] = FramingData.list_fields() - options_map['salience'] = SalienceData.list_fields() - return options_map - - -# prepare experiential container -experiential_map = generate_visual_syntax_options_map() -experiential_container = dmc.Col( - children=[ - html.H4('experiential'.title()), - ], span=5, -) -for title, options in experiential_map.items(): - id_dict = {'type': 'annotation', 'index': title.replace('_', '-')} - experiential_container.children.append( - dmc.Container([ - html.B(title.title()), - dcc.RadioItems( - options=[text.replace('_', ' ') for text in options], - id=id_dict, - ), - ]), - ) -# prepare interpersonal container -interpersonal_map = generate_interpersonal_options_map() -interpersonal_container = dmc.Col( - children=[ - html.H4('interpersonal'.title()), - ], span=3, -) -for title, options in interpersonal_map.items(): - id_dict = {'type': 'annotation', 'index': title.replace('_', '-')} - interpersonal_container.children.append( - dmc.Container([ - html.B(title.title()), - dcc.RadioItems( - options=[text.replace('_', ' ') for text in options], - id=id_dict, - ), - ]), - ) -# prepare textual container -textual_map = generate_textual_options_map() -textual_container = dmc.Col( - children=[ - html.H4('textual'.title()), - ], span=4, -) -for title, options in textual_map.items(): - id_dict = {'type': 'annotation', 'index': title.replace('_', '-')} - textual_container.children.append( - dmc.Container([ - html.B(title.title()), - dcc.RadioItems( - options=[text.replace('_', ' ') for text in options], - id=id_dict, - ), - ]), - ) - -labels_element = dmc.Grid( - children=[ - experiential_container, - interpersonal_container, - textual_container, - ], -) diff --git a/src/web/layout/layout.py b/src/web/layout/layout.py deleted file mode 100644 index b8995cb..0000000 --- a/src/web/layout/layout.py +++ /dev/null @@ -1,34 +0,0 @@ -import dash_mantine_components as dmc - -from .stores import stores_element -from .alerts import alerts_element -from .header import header_element -from .body import body_element - - -app_layout = dmc.MantineProvider( - theme={ - "fontFamily": '"Inter", sans-serif', - "components": { - "NavLink": { - "styles": { - "label": { - "color": "#c2c7d0" - } - } - } - }, - }, - children=[ - stores_element, - alerts_element, - dmc.Container( - children=[ - header_element, - body_element, - ], - fluid=True - ), - - ] -) diff --git a/src/web/layout/stores.py b/src/web/layout/stores.py deleted file mode 100644 index 11c59da..0000000 --- a/src/web/layout/stores.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import annotations - -from dash import dcc -from dash import html - - -stores_element = html.Div( - children=[ - dcc.Store(id='alert-message', data=''), - dcc.Store(id='success-message', data=''), - dcc.Store(id='vis-com-name', data=''), - ], -)