MarcSkovMadsen commited on
Commit
9999841
·
verified ·
1 Parent(s): 977f354

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -91
app.py CHANGED
@@ -1,95 +1,133 @@
1
- import panel as pn
2
-
3
- pn.extension(sizing_mode="stretch_width", design="material")
4
-
5
- BUTTON_WIDTH = 125
6
-
7
- # We use intslider to avoid teaching users pn.rx. Is that a good thing?
8
- state_changed_count = pn.widgets.IntInput()
9
- tasks = pn.Column()
10
-
11
- def update_state_changed_count(*args):
12
- state_changed_count.value += 1
13
-
14
- def remove_task(task, *args):
15
- index = tasks.index(task)
16
- tasks.pop(index)
17
-
18
- def remove_all_tasks(*args):
19
- tasks.clear()
20
-
21
- def create_task(text):
22
- state = pn.widgets.Checkbox(align="center", sizing_mode="fixed")
23
- content = pn.pane.Markdown(text)
24
- remove = pn.widgets.Button(width=BUTTON_WIDTH, icon="trash", sizing_mode="fixed")
25
- task = pn.Row(state, content, remove, sizing_mode="stretch_width")
26
-
27
- pn.bind(remove_task, task, remove, watch=True)
28
- # We have to bind the below after the above!
29
- pn.bind(update_state_changed_count, state, remove, watch=True)
30
-
31
- return task
32
-
33
- def add_task(text, *args):
34
- if not text:
35
- return
36
 
37
- new_task = create_task(text)
38
- tasks.append(new_task)
39
 
40
- return tasks
41
-
42
- def get_state(*args):
43
- total_tasks = len(tasks)
44
- completed_tasks = sum(check[0].value for check in tasks)
45
- return f"{completed_tasks} of {total_tasks} tasks completed"
46
-
47
- def can_add(value_input):
48
- return not bool(value_input)
49
-
50
- def has_tasks(*args):
51
- return len(tasks) > 0
52
-
53
-
54
- add_task("Inspect the blades")
55
- add_task("Inspect the nacelle")
56
- add_task("Tighten the bolts")
57
-
58
- text_input = pn.widgets.TextInput(name="Task", placeholder="Enter a task")
59
-
60
- submit_task = pn.widgets.Button(
61
- name="Add",
62
- align="center",
63
- button_type="primary",
64
- width=BUTTON_WIDTH,
65
- sizing_mode="fixed",
66
- disabled=pn.bind(can_add, text_input.param.value_input)
67
- )
68
- clear = pn.widgets.Button(
69
- name="Remove All",
70
- button_type="primary",
71
- button_style="outline",
72
- width=BUTTON_WIDTH,
73
- sizing_mode="fixed",
74
- visible=pn.bind(has_tasks, state_changed_count)
75
- )
76
-
77
- def reset_text_input(*args):
78
- text_input.value = text_input.value_input = ""
79
-
80
- pn.bind(add_task, text_input, submit_task, watch=True)
81
- pn.bind(reset_text_input, text_input, submit_task, watch=True)
82
- pn.bind(remove_all_tasks, clear, watch=True)
83
- # We have to bind the below after the above!
84
- pn.bind(update_state_changed_count, text_input, submit_task, clear, watch=True)
85
 
86
- status_report = pn.bind(get_state, state_changed_count, tasks.param.objects)
87
 
88
- pn.Column(
89
- "## WTG Task List",
90
- status_report,
91
- pn.Row(text_input, submit_task),
92
- tasks,
93
- pn.Row(pn.Spacer(), clear),
94
- max_width=500,
95
- ).servable()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """The FeatureInput enables a user to select from a list of features and set their values"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ import param
 
4
 
5
+ import panel as pn
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
 
7
 
8
+ class FeatureInput(pn.widgets.CompositeWidget):
9
+ """The FeatureInput enables a user to select from a list of features and set their values
10
+
11
+ ## Example
12
+
13
+ ```python
14
+ features = {
15
+ "A": 1.0,
16
+ "B": 2.0,
17
+ "C": 3.0,
18
+ "D": 4.0,
19
+ }
20
+ selected_features = ["A", "C"]
21
+ widget = FeatureInput(features=features, selected_features=selected_features)
22
+ ```
23
+ """
24
+
25
+ value = param.Dict(
26
+ doc="The names of the features selected and their set values", allow_None=False
27
+ )
28
+
29
+ features = param.Dict(
30
+ doc="The names of the available features and their default values",
31
+ allow_None=False,
32
+ )
33
+ selected_features = param.ListSelector(
34
+ doc="The list of selected features", allow_None=False
35
+ )
36
+
37
+ _selected_widgets = param.ClassSelector(
38
+ class_=pn.Column, doc="The widgets used to edit the selected features"
39
+ )
40
+
41
+ _composite_type = pn.Column
42
+
43
+ def __init__(self, **params):
44
+ params["value"] = params.get("value", {})
45
+ params["features"] = params.get("features", {})
46
+ params["selected_features"] = params.get("selected_features", [])
47
+
48
+ params["_selected_widgets"] = self.param._selected_widgets.class_()
49
+
50
+ super().__init__(**params)
51
+
52
+ selected_features_widget = pn.widgets.MultiChoice.from_param(
53
+ self.param.selected_features, sizing_mode="stretch_width"
54
+ )
55
+
56
+ self._composite[:] = [selected_features_widget, self._selected_widgets]
57
+
58
+ @param.depends("features", watch=True, on_init=True)
59
+ def _reset_selected_features(self):
60
+ selected_features = []
61
+ for (
62
+ feature
63
+ ) in self.selected_features.copy():
64
+ if feature in self.features.copy():
65
+ selected_features.append(
66
+ feature
67
+ )
68
+
69
+ self.param.selected_features.objects = list(self.features)
70
+ self.selected_features = selected_features
71
+
72
+ @param.depends("selected_features", watch=True, on_init=True)
73
+ def _handle_selected_features_change(self):
74
+ org_value = self.value
75
+
76
+ self._update_selected_widgets(org_value)
77
+ self._update_value()
78
+
79
+ def _update_value(self, *args): # pylint: disable=unused-argument
80
+ new_value = {}
81
+
82
+ for widget in self._selected_widgets:
83
+ new_value[widget.name] = widget.value
84
+
85
+ self.value = new_value
86
+
87
+ def _update_selected_widgets(self, org_value):
88
+ new_widgets = {}
89
+
90
+ for feature in self.selected_features:
91
+ value = org_value.get(feature, self.features[feature])
92
+ widget = self._new_widget(feature, value)
93
+ new_widgets[feature] = widget
94
+
95
+ self._selected_widgets[:] = list(new_widgets.values())
96
+
97
+ def _new_widget(self, feature, value):
98
+ widget = pn.widgets.FloatInput(
99
+ name=feature, value=value, sizing_mode="stretch_width"
100
+ )
101
+ pn.bind(self._update_value, widget, watch=True)
102
+ return widget
103
+
104
+ def create_app():
105
+ features = {
106
+ "Blade Length (m)": 73.5,
107
+ "Cut-in Wind Speed (m/s)": 3.5,
108
+ "Cut-out Wind Speed (m/s)": 25,
109
+ "Grid Connection Capacity (MW)": 5,
110
+ "Hub Height (m)": 100,
111
+ "Rated Wind Speed (m/s)": 12,
112
+ "Rotor Diameter (m)": 150,
113
+ "Turbine Efficiency (%)": 45,
114
+ "Water Depth (m)": 30,
115
+ "Wind Speed (m/s)": 10,
116
+ }
117
+ selected_features = ["Wind Speed (m/s)", "Rotor Diameter (m)"]
118
+ widget = FeatureInput(
119
+ features=features,
120
+ selected_features=selected_features,
121
+ width=500,
122
+ styles={"border": "1px solid lightgray", "border-radius": "5px"},
123
+ )
124
+
125
+ return pn.Column(
126
+ "## Widget",
127
+ widget,
128
+ "## Value",
129
+ pn.pane.JSON(widget.param.value, width=500, height=300),
130
+ )
131
+
132
+ if pn.state.served:
133
+ create_app().servable()