Skip to content
Snippets Groups Projects
Commit a7c813ce authored by David, Sebastian's avatar David, Sebastian
Browse files

Delete citation_parser_ui.py

parent 8485fb72
Branches
No related tags found
1 merge request!8UI Hinzufügen
import base64
import re
import dash
from dash import dcc
from dash import html
from dash import callback_context
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
from input.interface import InputInterface
import input.publication
app = dash.Dash(__name__)
# List of options when inputting data and generating the graph
additional_options = ['Update Automatically','Smart Input']
# Reads the contents of info_box.txt. They can later be displayed by pressing the corresponding button.
f = open('info_box.txt', 'r')
boxcontent = f.read()
f.close()
app.layout = html.Div([
# Layer 0: For the Header and Help Function(s)
html.Div([
html.Button(id='show-info',children='Show Info',n_clicks=0),
html.Div(id='info-box')
]),
# Layer 1: For all mandatory Inputs
html.Div([
"Input: ",
# A simple box for inputting a string. Value is transmitted upon pressen return or clicking out of the box.
dcc.Input(id='input-string', value='', type='text',debounce=True),
# Forward recursion. Values between 1 and 10 can be entered.
dcc.Input(id='forward-depth',value='1',type='number',min='1',max='10'),
# Backward recursion. Values between 1 and 10 can be entered.
dcc.Input(id='backward-depth',value='1',type='number',min='1',max='10'),
# Upload box. Can be used via drag-and-drop or byclicking on it to open a file viewer.
dcc.Upload(
id="upload-data",
children=html.Div(
["Drag and drop or click to select a file to upload."]),
style={
"width": "30%",
"height": "60px",
"lineHeight": "60px",
"borderWidth": "1px",
"borderStyle": "dashed",
"borderRadius": "5px",
"textAlign": "center",
"margin": "10px",
})
]),
# Layer 2: For the checklist, Remove-/Start-Buttons and input-error-message
html.Div([
# All input DOIs are collected in this checklist. It is initialized to avoid error messages.
dcc.Checklist(id='input-checklist',options=[],labelStyle = dict(display='block'),value=[]),
# Displays error message if 'Smart Input' is active.
html.Div(id='input-err',style={'color':'red'}),
# Clears the entire list.
html.Button(id='clear-all-button',children='Clear All'),
# Clear all selected elements.
html.Button(id='clear-selected-button',children='Clear Selected'),
# Starts the process that generates a graph.
html.Button(id='start-button',children='Generate Graph')
]),
# Layer 3: For additional Options (e.g. Topological Sort)
html.Div([
html.H4('Additional Options'),
# A checklist of all additional options that are listed above.
dcc.Checklist(id='additional-options',
options=[{'label':k,'value':k} for k in additional_options],
value=[])
]),
# Layer 4: For the Graph
html.Div([
html.Div(id='test-output')
])
])
@app.callback(
Output('input-checklist','options'),
Output('input-checklist','value'),
Output('input-string','value'),
Output('input-err','children'),
Input('input-string','value'),
Input('clear-all-button','n_clicks'),
Input('clear-selected-button','n_clicks'),
Input('upload-data','contents'),
State('input-checklist','options'),
State('input-checklist','value'),
State('additional-options','value')
)
def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs,selected_inputs,additional_options):
'''
Most important callback function. Updates the checklist that holds all inputs.
State of the checklist as input is needed so that previews entries are readded.
input-string is required as Output to clear the input box after each input.
Different actions are performed depending on which input triggered the callback.
The value-attribute of input-checklist must be updates so that the values
of deleted elements no longer appear in the list of selected elements.
:param input_value: given by dcc.Input
:type input_value: string
:param btn1: signals pressing of clear-all-button
:type btn1: int
:param btn2: signals pressing of clear-selected-button
:type btn2: int
:param filecontents: the contents of an uploaded file
:type filecontents: bit-string
:param all_inputs: all labels and values from the checklist,
regardless if they have been checked or not
:type all_inputs: list of dictionaries with 2 entries each
:param selected_inputs: values of all checked elements
:type selected_inputs: list of strings
:param addtitional_options: all checked additional options
:type additional_options: list of strings
'''
# changed_id is used to determine which Input has triggered the callback
changed_id = [p['prop_id'] for p in callback_context.triggered][0]
# if clear-all-button was pressed:
if 'clear-all-button' in changed_id:
return list(),list(),'',''
# if clear-selected-button was pressed:
if 'clear-selected-button' in changed_id:
all_inputs = [i for i in all_inputs if i['value'] not in selected_inputs]
return all_inputs,list(),'',''
# when a new element is added via dcc.Input
if 'input-string' in changed_id:
# Creates a list of previously added inputs to make sure nothing is added twice
currValues = [x['value'] for x in all_inputs]
if input_value not in currValues:
# if 'Smart Input' is selected, the input will be checked for validity
# and a more readable string will be returned
if 'Smart Input' in additional_options:
try:
# Attempts to call get_publication. If unsuccesful,
# the DOI is not added and an error message is returned
i = InputInterface()
pub = i.get_publication(input_value)
except Exception as err:
return options,selected_inputs,'','{}'.format(err)
# Creates a more readable string to display in the checklist
rep_str = pub.contributors[0] + ',' + pub.journal + ',' + pub.publication_date
all_inputs.append({'label':rep_str, 'value':input_value})
# if 'Smart Input' is not selected, the input value is added as is,
# without checking for validity.
else:
all_inputs.append({'label':input_value,'value':input_value})
return all_inputs,selected_inputs,'',''
# when a txt-file is uploaded
if 'upload-data.contents' in changed_id:
if filecontents:
# Skips the info portion that is added when a file is uploaded
found = base64.b64decode(re.search(',(.+?)$', filecontents).group(1))
# Returns the binary string into a proper text
text = found.decode('utf-8')
# Creates a list of inputs by splitting the lines
list_of_inputs = (text.strip().split('\n'))
CurrValues = [x['value'] for x in all_inputs]
# For every line the same actions as for a single input are performed
for input_value in list_of_inputs:
if input_value not in CurrValues:
if 'Smart Input' in additional_options:
try:
i = InputInterface()
pub = i.get_publication(input_value)
except Exception as err:
return all_inputs,selected_inputs,'','{}'.format(err)
rep_str = pub.contributors[0] + ',' + pub.journal + ',' + pub.publication_date
all_inputs.append({'label':rep_str, 'value':input_value})
else:
all_inputs.append({'label':input_value,'value':input_value})
return all_inputs,selected_inputs,'',''
# when the programm is first started:
# if this is not done, the input_checklist will be generated
# with one element that contains an empty string
if input_value == '':
app.layout['input-checklist'].options.clear()
return list(),list(),'',''
@app.callback(
Output('info-box','children'),
Input('show-info','n_clicks')
)
def show_hide_info_box(n_clicks):
'''
This callback shows and hides the (first) info-box by, checking how often
the button has been pressed. The text was loaded at the top.
:param n_clicks: number of times show-info has been clicked.
'type n_clicks: int
'''
if n_clicks % 2 == 0:
return ''
else:
return html.Div(boxcontent, style={'whiteSpace': 'pre-line'})
@app.callback(
Output('test-output','children'),
Input('start-button','n_clicks'),
Input('input-checklist','options'),
Input('input-checklist','value'),
Input('forward-depth','value'),
Input('backward-depth','value'),
State('additional-options','value')
)
def generate_output(n_clicks,all_inputs,selected_inputs,
forward_depth,backward_depth,additional_options):
'''
Basic structure for a callback that generates an output. This is only a
proof of concept and has noting to do with the intended output yet.
:param n_clicks: how often has Generate Graph been clicked
:type n_clicks: int
:param all_inputs: all labels and values from the checklist,
regardless if they have been checked or not
:type all_inputs: list of dictionaries with 2 entries each
:param selected_inputs: values of all checked elements
:type selected_inputs: list of strings
:param forward_depth: forward recursion depth
:type forward_depth: unsigned int
:param backward_depth: backward recursion depth
:type backward_depth: unsigned int
:param additional_options: value of all selected additional options
:type additional_options: list of strings
'''
changed_id = [p['prop_id'] for p in callback_context.triggered][0]
if n_clicks is None:
raise PreventUpdate
elif 'Update Automatically' in additional_options \
or 'start-button' in changed_id:
s = ''
for i in range(len(all_inputs)):
x = all_inputs[i]['value']
if x in selected_inputs:
s += x*(abs(int(forward_depth)-int(backward_depth)))
else:
s += x*(int(forward_depth)+int(backward_depth))
return s
else:
raise PreventUpdate
if __name__ == '__main__':
app.run_server(debug=True)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment