Skip to content

Commit 31239e5

Browse files
committed
Add wizard for creating projects
1 parent 64ab2a9 commit 31239e5

File tree

4 files changed

+215
-197
lines changed

4 files changed

+215
-197
lines changed

gradient/cli/projects.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from gradient.cli import common
55
from gradient.cli.cli import cli
66
from gradient.commands import projects as projects_commands
7+
from gradient.wizards.projects import run_create_project_wizard
78

89

910
@cli.group("projects", help="Manage projects", cls=common.ClickGroup)
@@ -43,3 +44,8 @@ def create_project(api_key, **project):
4344
projects_api = client.API(config.CONFIG_HOST, api_key=api_key)
4445
command = projects_commands.CreateProjectCommand(api=projects_api)
4546
command.execute(project)
47+
48+
49+
@projects_group.command("wizard", help="Run create project wizard")
50+
def create_project_wizard():
51+
run_create_project_wizard()

gradient/wizards/projects.py

Lines changed: 10 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -1,203 +1,17 @@
1-
import collections
2-
3-
import six
4-
from prompt_toolkit import Application
5-
from prompt_toolkit.application import get_app
6-
from prompt_toolkit.key_binding import KeyBindings
7-
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
8-
from prompt_toolkit.layout import Layout, VSplit, HSplit, FloatContainer, Float
9-
from prompt_toolkit.shortcuts import message_dialog
10-
from prompt_toolkit.styles import Style
11-
from prompt_toolkit.widgets import Frame, Label, TextArea, RadioList, Box, Button, Dialog
12-
13-
from gradient import client, config
14-
from gradient.cli import common
151
from gradient.commands import projects as projects_commands
2+
from gradient.wizards import wizard
3+
from gradient.wizards.wizard import get_application
164

17-
if not six.PY2:
18-
unicode = str
19-
20-
bindings = KeyBindings()
21-
bindings.add(u'tab')(focus_next)
22-
bindings.add(u"right")(focus_next)
23-
bindings.add(u'enter')(focus_next)
24-
bindings.add(u"left")(focus_previous)
25-
bindings.add(u's-tab')(focus_previous)
26-
27-
28-
@bindings.add(u"c-c")
29-
def _(event):
30-
event.app.exit()
31-
32-
33-
@bindings.add('c-space')
34-
def _(event):
35-
" Initialize autocompletion, or select the next completion. "
36-
buff = event.app.current_buffer
37-
if buff.complete_state:
38-
buff.complete_next()
39-
else:
40-
buff.start_completion(select_first=False)
41-
42-
43-
default_question_style = u"green"
44-
45-
46-
class Question(object):
47-
def __init__(self, question):
48-
self.question = question
49-
self.question_widget = self._get_question_widget()
50-
self.answer_widget = self._get_answer_widget()
51-
self.widget = self._get_widget()
52-
53-
@property
54-
def answer(self):
55-
return self.answer_widget.text
56-
57-
def _get_question_widget(self):
58-
return Label(
59-
self.question,
60-
# style=self.style,
61-
)
62-
63-
def _get_answer_widget(self):
64-
return TextArea(multiline=False)
65-
66-
def _get_widget(self):
67-
return Frame(
68-
VSplit(
69-
[
70-
self.question_widget,
71-
self.answer_widget,
72-
],
73-
),
74-
)
75-
76-
77-
class RadioQuestion(Question):
78-
def __init__(self, question, answers):
79-
self.answers = answers
80-
super(RadioQuestion, self).__init__(question)
81-
82-
@property
83-
def answer(self):
84-
return self.answer_widget.current_value
85-
86-
def _get_answer_widget(self):
87-
return RadioList(self.answers)
88-
89-
90-
class Questions(object):
91-
def __init__(self):
92-
self._questions = collections.OrderedDict()
93-
94-
def add_text_question(self, field_name, question):
95-
q = Question(question)
96-
self._questions[field_name] = q
97-
98-
def add_radio_question(self, field_name, question, answers):
99-
q = RadioQuestion(question, answers)
100-
self._questions[field_name] = q
101-
102-
def get_widgets_list(self):
103-
return [question.widget for question in self._questions.values()]
104-
105-
def get_json(self):
106-
return {field_name: question.answer
107-
for field_name, question in self._questions.items()}
108-
109-
110-
questions = Questions()
111-
questions.add_text_question("name", u"Name: ")
112-
questions.add_text_question("repoName", u"Repository name: ")
113-
questions.add_text_question("repoUrl", u"Repository URL: ")
114-
questions.add_text_question("api_key", u"apiKey: ")
115-
116-
style = Style.from_dict({
117-
u"background": u"blue",
118-
})
119-
120-
121-
class DialogLogger(object):
122-
def log(self, msg):
123-
layout = get_app().layout
124-
dialog = Dialog(body=Label(text=msg))
125-
layout.container.floats.append(
126-
Float(content=dialog)
127-
)
128-
129-
def log_error_response(self, data):
130-
error_str = data.get("error")
131-
details = data.get("details")
132-
message = data.get("message")
133-
134-
if not any((error_str, details, message)):
135-
raise ValueError("No error messages found")
136-
137-
if error_str:
138-
try:
139-
self.error(error_str["message"])
140-
except (KeyError, TypeError):
141-
self.error(str(error_str))
142-
143-
if details:
144-
if isinstance(details, dict):
145-
for key, val in details.items():
146-
if isinstance(val, six.string_types):
147-
val = [val]
148-
149-
for v in val:
150-
msg = "{}: {}".format(key, str(v))
151-
self.error(msg)
152-
else:
153-
self.error(details)
154-
155-
if message:
156-
self.error(str(message))
157-
158-
159-
def accept_create():
160-
project = questions.get_json()
161-
api_key = project.pop("api_key", None)
162-
common.del_if_value_is_none(project)
163-
164-
projects_api = client.API(config.CONFIG_HOST, api_key=api_key)
165-
command = projects_commands.CreateProjectCommand(api=projects_api, logger_=DialogLogger())
166-
command.execute(project)
167-
get_app().exit()
168-
169-
170-
def accept_exit():
171-
get_app().exit()
172-
173-
174-
create_button = Button(u"Create", handler=accept_create)
175-
exit_button = Button(u"Exit", handler=accept_exit)
176-
177-
question_widgets = [
178-
Frame(body=Label(text=u"Create new job")),
179-
180-
]
181-
question_widgets += questions.get_widgets_list()
182-
question_widgets.append(Box(VSplit([create_button, exit_button])))
183-
184-
# float_container =
185-
# root_container = HSplit(
186-
# question_widgets,
187-
# # style=u"grey",
188-
# )
1895

6+
def run_create_project_wizard():
7+
w = wizard.Wizard(projects_commands.CreateProjectCommand, u"Create new project")
8+
w.add_text_questions(("name", u"Name: "),
9+
("repoName", u"Repository name: "),
10+
("repoUrl", u"Repository URL: "),
11+
("api_key", u"apiKey: "), )
19012

191-
root_container = FloatContainer(HSplit(question_widgets), [])
13+
root_container = w.get_layout()
19214

193-
application = Application(
194-
full_screen=True,
195-
layout=Layout(root_container, ),
196-
enable_page_navigation_bindings=True,
197-
key_bindings=bindings,
198-
style=style,
199-
mouse_support=True,
200-
)
15+
application = get_application(root_container)
20116

202-
if __name__ == '__main__':
20317
application.run()

0 commit comments

Comments
 (0)