144 lines
5.2 kB
1
defmodule BlogWeb.PythonDemoLive do
2
use BlogWeb, :live_view
3
require Logger
4
5
@impl true
6
def mount(_params, _session, socket) do
7
{:ok, assign(socket,
8
result: nil,
9
code: "",
10
executing: false,
11
error: nil
12
)}
13
end
14
15
@impl true
16
def handle_event("run-code", %{"code" => code}, socket) do
17
# Set executing flag to show a spinner
18
socket = assign(socket, executing: true)
19
20
# Send ourselves a message to execute the code asynchronously
21
send(self(), {:execute_python, code})
22
23
{:noreply, socket}
24
end
25
26
@impl true
27
def handle_info({:execute_python, code}, socket) do
28
result = Blog.PythonRunner.run_python_code(code)
29
30
socket = case result do
31
{:ok, output} ->
32
assign(socket, result: output, error: nil, executing: false)
33
34
{:error, error_msg} ->
35
assign(socket, error: error_msg, executing: false)
36
end
37
38
{:noreply, socket}
39
end
40
41
@impl true
42
def render(assigns) do
43
~H"""
44
<div class="mx-auto max-w-3xl p-4">
45
<h1 class="text-2xl font-bold mb-4">Python in Elixir</h1>
46
47
<div class="p-4 bg-gray-100 rounded-lg shadow-md">
48
<h2 class="text-xl font-semibold mb-2">Execute Python Code</h2>
49
<p class="mb-4 text-gray-600">Write your Python code below and execute it directly from Elixir:</p>
50
51
<form phx-submit="run-code">
52
<div class="mb-4">
53
<label for="code" class="block text-sm font-medium text-gray-700 mb-1">Python Code:</label>
54
<textarea
55
id="code"
56
name="code"
57
rows="8"
58
class="w-full p-3 border border-gray-300 rounded-md shadow-sm font-mono text-sm bg-gray-50"
59
spellcheck="false"
60
><%= @code %></textarea>
61
</div>
62
63
<div class="flex items-center justify-between">
64
<button
65
type="submit"
66
class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 flex items-center"
67
disabled={@executing}
68
>
69
<%= if @executing do %>
70
<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
71
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
72
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
73
</svg>
74
Executing...
75
<% else %>
76
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
77
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
78
</svg>
79
Execute Code
80
<% end %>
81
</button>
82
83
<button
84
type="button"
85
phx-click="reset"
86
class="text-gray-600 hover:text-gray-800 font-medium"
87
>
88
Reset Example
89
</button>
90
</div>
91
</form>
92
93
<%= if @result do %>
94
<div class="mt-6">
95
<h3 class="font-semibold text-gray-800 mb-2">Result:</h3>
96
<div class="p-4 bg-white rounded-md border border-gray-300 overflow-auto shadow-inner">
97
<pre class="text-sm font-mono text-black whitespace-pre-wrap bg-gray-50 p-3 rounded"><%= @result %></pre>
98
</div>
99
</div>
100
<% end %>
101
102
<%= if @error do %>
103
<div class="mt-6">
104
<h3 class="font-semibold text-red-600 mb-2">Error:</h3>
105
<div class="p-4 bg-red-50 rounded-md border border-red-300 overflow-auto shadow-inner">
106
<pre class="text-sm font-mono text-red-700 whitespace-pre-wrap"><%= @error %></pre>
107
</div>
108
</div>
109
<% end %>
110
</div>
111
112
<div class="mt-6 p-4 bg-blue-50 rounded-lg border border-blue-200">
113
<h3 class="font-semibold text-blue-800 mb-2">Examples to Try:</h3>
114
<ul class="list-disc pl-5 space-y-2 text-sm text-blue-800">
115
<li>
116
<code class="font-mono bg-blue-100 px-1 py-0.5 rounded">import math<br/>print("The square root of 16 is", math.sqrt(16))</code>
117
</li>
118
<li>
119
<code class="font-mono bg-blue-100 px-1 py-0.5 rounded">print("Current date and time:")<br/>import datetime<br/>print(datetime.datetime.now())</code>
120
</li>
121
<li>
122
<code class="font-mono bg-blue-100 px-1 py-0.5 rounded">data = [1, 2, 3, 4, 5]<br/>sum_of_squares = sum([x**2 for x in data])<br/>print("The sum of squares is", sum_of_squares)</code>
123
</li>
124
</ul>
125
</div>
126
</div>
127
"""
128
end
129
130
@impl true
131
def handle_event("reset", _params, socket) do
132
{:noreply, assign(socket,
133
code: """
134
def hello_world():
135
return "Hello from Python! 🐍"
136
137
result = hello_world()
138
result
139
""",
140
result: nil,
141
error: nil
142
)}
143
end
144
end
145