Commit 08df8c2c authored by Sanyam Khurana's avatar Sanyam Khurana

refactor(*): Adding Generic Menu

See merge request new-contributor-wizard-team/new-contributor-wizard!13
parents 42b3d3c7 b566fda9
v0.0.1
## July 30 2018
- Generic Menus added in module_box to be used in any of the course modules for Menu navigation, Tools Menu and Tutorials Menu (Shashank Kumar - realslimshanky)
- Project restructued to provide meaningful separation between course modules and other modules (Shashank Kumar - realslimshanky)
## July 20 2018
- Adding additional block in Tools and Tutorials menu to invite contributors by providing link to the project repository. (Shashank Kumar - realslimshanky)
......
[
{
"application_settings": {
"tutorials": [],
"tools": []
}
},
{
"blog": {
"tutorials": [],
"tools": []
}
},
{
"cli": {
"tutorials": [],
"tools": []
}
},
{
"communication": {
"tutorials": [],
"tools": []
}
},
{
"encryption": {
"tutorials": [
{
"title": "Encryption 101",
"difficulty": "Beginner"
}
],
"tools": [
{
"title": "Display and manage key pair",
"difficulty": "Beginner"
},
{
"title": "Create key pair",
"difficulty": "Beginner"
},
{
"title": "Encrypt a message",
"difficulty": "Intermediate"
},
{
"title": "Decrypt a message",
"difficulty": "Intermediate"
}
]
}
},
{
"how_to_use": {
"tutorials": [],
"tools": []
}
},
{
"profile_settings": {
"tutorials": [],
"tools": []
}
},
{
"theme_settings": {
"tutorials": [],
"tools": []
}
},
{
"vcs": {
"tutorials": [],
"tools": []
}
},
{
"way_ahead": {
"tutorials": [],
"tools": []
}
}
]
[
{"application_settings": []},
{"blog": []},
{"cli": []},
{"communication": []},
{"encryption":[
{
"tutorials": [
{
"Encryption 101": {
"difficulty": "Beginner"
}
}
]
},
{
"tools": [
{
"Display and manage key pair": {
"difficulty": "Beginner"
},
"Create key pair": {
"difficulty": "Beginner"
},
"Encrypt a message": {
"difficulty": "Intermediate"
},
"Decrypt a message": {
"difficulty": "Intermediate"
}
}
]
}
]
},
{"how_to_use": []},
{"profile_settings": []},
{"theme_settings": []},
{"vcs": []},
{"way_ahead": []}
]
......@@ -87,6 +87,8 @@ There are two type of testing being done for this application.
- `modules` - This directory should and only contain the application login for different modules integrated to the Root Application. For example, this should contain the source for all application logic the tutorials and tools.
- `course_modules` - This directory contains all the Courseware modules and their tools and tutorials.
- `tests` - This directory should and only contain the Test written for the application, both for application logic and GUI.
- `ui` - This directory should and only contain the `.kv` files which uses Kivy Language in order to create the widget tree.
......@@ -136,6 +138,8 @@ There are two type of testing being done for this application.
### The Courseware
The courseware modules are preset inside the `course_modules/` directory.
- How To Use - This module helps user getting started with New Contributor Wizard application and is placed in `how_to_use/`
- Communication - This module helps user understand importance of communication and the tools involved like IRC and mailing lists and is places in `communication/`
......
......@@ -2,14 +2,16 @@
Modules containing Blog classes
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_file('./ui/blog.kv')
from modules.module_box.module_box import ModuleBox
class Blog(BoxLayout):
'''
Blog class for tutorials and tools
'''
pass
def __init__(self, **kwargs):
super(Blog, self).__init__(**kwargs)
self.module_box = ModuleBox("blog")
self.add_widget(self.module_box)
......@@ -2,14 +2,16 @@
Modules containing CLI classes
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_file('./ui/cli.kv')
from modules.module_box.module_box import ModuleBox
class CLI(BoxLayout):
'''
Command Line Interface class for tutorials and tools
CLI class for tutorials and tools
'''
pass
def __init__(self, **kwargs):
super(CLI, self).__init__(**kwargs)
self.module_box = ModuleBox("cli")
self.add_widget(self.module_box)
......@@ -2,14 +2,16 @@
Modules containing Communication classes
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_file('./ui/communication.kv')
from modules.module_box.module_box import ModuleBox
class Communication(BoxLayout):
'''
Communication class for tutorials and tools
'''
pass
def __init__(self, **kwargs):
super(Communication, self).__init__(**kwargs)
self.module_box = ModuleBox("communication")
self.add_widget(self.module_box)
'''
Modules containing Encryption classes
'''
from kivy.uix.boxlayout import BoxLayout
from modules.module_box.module_box import ModuleBox
class Encryption(BoxLayout):
'''
Encryption class for tutorials and tools
'''
def __init__(self, **kwargs):
super(Encryption, self).__init__(**kwargs)
self.module_box = ModuleBox("encryption")
self.add_widget(self.module_box)
......@@ -8,21 +8,20 @@ from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.clock import Clock
from modules.encryption.tools.all_tools.exceptions import GPGError
from modules.encryption.tools.all_tools.services import create_gpg_key_pair
from modules.encryption.tools.all_tools.validations import (
from modules.course_modules.encryption.tools.exceptions import GPGError
from modules.course_modules.encryption.tools.services import create_gpg_key_pair
from modules.course_modules.encryption.tools.validations import (
validate_email, validate_name, validate_comment, validate_expire_date
)
Builder.load_file('./ui/encryption/all_tools/create_key_pair.kv')
Builder.load_file('./ui/encryption/create_key_pair.kv')
class CreateKeyPairPopup(Popup):
'''
CreateKeyPairPopup displays popup to inform about key creation progress
'''
pass
class CreateKeyPair(BoxLayout):
......
......@@ -7,13 +7,13 @@ from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.lang import Builder
from modules.encryption.tools.all_tools.exceptions import GPGError
from modules.encryption.tools.all_tools.services import (
from modules.course_modules.encryption.tools.exceptions import GPGError
from modules.course_modules.encryption.tools.services import (
list_gpg_all_keys, decrypt_message, create_key_listing_widget
)
Builder.load_file('./ui/encryption/all_tools/decrypt_a_message.kv')
Builder.load_file('./ui/encryption/decrypt_a_message.kv')
class KeyColumnBox(GridLayout):
......
......@@ -7,13 +7,13 @@ from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.lang import Builder
from modules.encryption.tools.all_tools.utils import extract_key_uid_info
from modules.encryption.tools.all_tools.services import (
from modules.course_modules.encryption.tools.utils import extract_key_uid_info
from modules.course_modules.encryption.tools.services import (
list_gpg_all_keys, export_single_key
)
Builder.load_file('./ui/encryption/all_tools/display_and_manage_key_pair.kv')
Builder.load_file('./ui/encryption/display_and_manage_key_pair.kv')
class KeyColumnBox(GridLayout):
......
......@@ -7,12 +7,12 @@ from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.lang import Builder
from modules.encryption.tools.all_tools.services import (
from modules.course_modules.encryption.tools.services import (
list_gpg_all_keys, encrypt_message, create_key_listing_widget
)
Builder.load_file('./ui/encryption/all_tools/encrypt_a_message.kv')
Builder.load_file('./ui/encryption/encrypt_a_message.kv')
class KeyColumnBox(GridLayout):
......
......@@ -5,8 +5,8 @@ from subprocess import check_output
import gnupg
from modules.encryption.tools.all_tools.exceptions import GPGError
from modules.encryption.tools.all_tools.utils import extract_key_uid_info
from modules.course_modules.encryption.tools.exceptions import GPGError
from modules.course_modules.encryption.tools.utils import extract_key_uid_info
GNUPG_HOME = 'gnupg_home'
IS_KEY_PRIVATE = True
......
......@@ -4,8 +4,8 @@ Validation functions for encryption.tools module
import re
from datetime import datetime as dt
from modules.encryption.tools.all_tools.exceptions import GPGError
from modules.encryption.tools.all_tools.utils import (
from modules.course_modules.encryption.tools.exceptions import GPGError
from modules.course_modules.encryption.tools.utils import (
clean_email, clean_name
)
......
......@@ -4,7 +4,6 @@ Modules containing How To Use classes
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_file('./ui/how_to_use.kv')
......@@ -13,4 +12,3 @@ class HowToUse(BoxLayout):
HowToUser class for introduction on how to user New
Contributor Wizard
'''
pass
......@@ -2,14 +2,16 @@
Modules containing Version Control System classes
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_file('./ui/vcs.kv')
from modules.module_box.module_box import ModuleBox
class VCS(BoxLayout):
'''
VCS class for tutorials and tools
'''
pass
def __init__(self, **kwargs):
super(VCS, self).__init__(**kwargs)
self.module_box = ModuleBox("vcs")
self.add_widget(self.module_box)
......@@ -2,15 +2,16 @@
Modules containing Way Ahead classes
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_file('./ui/way_ahead.kv')
from modules.module_box.module_box import ModuleBox
class WayAhead(BoxLayout):
'''
WayAhead class for tutorials and tools
'''
pass
\ No newline at end of file
def __init__(self, **kwargs):
super(WayAhead, self).__init__(**kwargs)
self.module_box = ModuleBox("way_ahead")
self.add_widget(self.module_box)
......@@ -11,16 +11,13 @@ try:
except ImportError:
logging.info('Dashboard: Install navigationdrawer from garden')
from modules.blog.blog import Blog
from modules.cli.cli import CLI
from modules.communication.communication import Communication
from modules.encryption.encryption import Encryption
from modules.how_to_use.how_to_use import HowToUse
from modules.vcs.vcs import VCS
from modules.way_ahead.way_ahead import WayAhead
from modules.settings.application import ApplicationSettings
from modules.settings.profile import ProfileSettings
from modules.settings.theme import ThemeSettings
from modules.course_modules.blog.blog import Blog
from modules.course_modules.cli.cli import CLI
from modules.course_modules.communication.communication import Communication
from modules.course_modules.encryption.encryption import Encryption
from modules.course_modules.how_to_use.how_to_use import HowToUse
from modules.course_modules.vcs.vcs import VCS
from modules.course_modules.way_ahead.way_ahead import WayAhead
Builder.load_file('./ui/dashboard.kv')
......@@ -30,4 +27,3 @@ class Dashboard(BoxLayout, Screen):
'''
Dashboard class to integrate courseware and settings
'''
pass
'''
Modules containing Encryption classes
Modules containing ModuleBox classes
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from modules.encryption.tutorials import tutorials
from modules.encryption.tools import tools
from modules.module_box.module_tools_menu import ModuleToolsMenu
from modules.module_box.module_tutorials_menu import ModuleTutorialsMenu
Builder.load_file('./ui/encryption/encryption.kv')
Builder.load_file('./ui/module_box/module_box.kv')
class Encryption(BoxLayout):
class ModuleBox(BoxLayout):
'''
Encryption class for tutorials and tools
ModuleBox class for tutorials and tools
'''
def __init__(self, **kwargs):
super(Encryption, self).__init__(**kwargs)
def __init__(self, root_module_name, **kwargs):
super(ModuleBox, self).__init__(**kwargs)
self.all_options = {
'tutorials': tutorials.Tutorials(),
'tools': tools.Tools(),
'tutorials': ModuleTutorialsMenu(root_module_name),
'tools': ModuleToolsMenu(root_module_name),
}
self.all_options_items = list(self.all_options.keys())
def enable_option(self, option_to_enable):
'''
enable_menu function focuses on concerned menu items or settings which is clicked and
removes focus from all other menu items and settings
enable_menu function focuses on concerned menu items or settings which
is clicked and removes focus from all other menu items and settings
'''
option_to_enable_widget = self.ids[option_to_enable + '_box']
option_to_enable_color = option_to_enable_widget.canvas.before.children[0].rgba
widget_canvas = option_to_enable_widget.canvas
option_to_enable_color = widget_canvas.before.children[0].rgba
if option_to_enable_color != [1, 1, 1, 1]:
self.ids[option_to_enable + '_box'].canvas.before.children[0].rgba = [1, 1, 1, 1]
self.ids[option_to_enable + '_box'].canvas.before.children[0].rgba\
= [1, 1, 1, 1]
self.ids[option_to_enable].color = (0, 0, 0, 1)
# removing enabled option from the list in order to disable all other options
# removing enabled option from the list in order to disable all
# other options
options_to_disable = self.all_options_items[:]
options_to_disable.remove(option_to_enable)
for option in options_to_disable:
self.ids[option + '_box'].canvas.before.children[0].rgba = [0, 0, 0, 1]
self.ids[option + '_box'].canvas.before.children[0].rgba =\
[0, 0, 0, 1]
self.ids[option].color = (1, 1, 1, 1)
self.ids['encryption_content_box'].remove_widget(self.all_options[option])
self.ids['module_content_box'].remove_widget(
self.all_options[option]
)
self.ids['encryption_content_box'].add_widget(self.all_options[option_to_enable])
self.ids['module_content_box'].add_widget(
self.all_options[option_to_enable]
)
'''
Modules containing Tools classes for Encryption
Modules containing Tools classes for Abstraction
'''
import json
from importlib import import_module
......@@ -9,44 +9,46 @@ from kivy.factory import Factory
from kivy.uix.boxlayout import BoxLayout
Builder.load_file('./ui/encryption/tools.kv')
Builder.load_file('./ui/module_box/tools.kv')
class ToolBox(BoxLayout):
'''
ToolBox class to present available tools
'''
pass
class BackToToolsMenu(BoxLayout):
'''
BackToToolsMenu class presents back button and tool title
'''
pass
class Tools(BoxLayout):
class ModuleToolsMenu(BoxLayout):
'''
Tools class to present Tools menu of Encryption
ModuleToolsMenu class to present Tools Menu
'''
def __init__(self, **kwargs):
super(Tools, self).__init__(**kwargs)
def __init__(self, root_module_name, **kwargs):
super(ModuleToolsMenu, self).__init__(**kwargs)
self.all_tools = {}
self.removed_tools_menu = None
self.root_module_name = root_module_name
with open('data/root.json') as data:
with open('data/module_data.json') as data:
json_data = json.loads(data.read())
self.encryption_data = json_data[4]["encryption"]
for key, value in self.encryption_data[1]["tools"][0].items():
value['title'] = key
tool_key = '_'.join(key.lower().split())
self.all_tools[tool_key] = value
self.populate_tools_menu()
for data in json_data:
if self.root_module_name in data.keys():
self.module_data = data[self.root_module_name]
break
if self.module_data["tools"]:
for tool in self.module_data["tools"]:
tool_key = '_'.join(tool['title'].lower().split())
self.all_tools[tool_key] = tool
self.populate_tools_menu()
self.ids['module_tools_menu'].add_widget(Factory.InvitingContributors())
def populate_tools_menu(self):
'''
......@@ -65,15 +67,13 @@ class Tools(BoxLayout):
tool_color = difficulty_palette[tool_difficulty]
tool_box_widget = ToolBox()
tool_box_widget.ids['tool_button'].bind(on_press=self.open_tool)
tool_box_widget.id = key # pylint: disable=invalid-name
tool_box_widget.id = key
tool_box_widget.canvas.before.children[0].rgba = tool_color
tool_box_widget.ids['tool_box_title'].text = tool_title
tool_box_widget.ids['tool_box_difficulty'].text = tool_difficulty
self.ids['tools_menu'].add_widget(tool_box_widget)
self.ids['module_tools_menu'].add_widget(tool_box_widget)
self.import_tool_modules(key)
self.ids['tools_menu'].add_widget(Factory.InvitingContributors())
def import_tool_modules(self, tool_to_import):
'''
import_tool_modules try to import tool_to_import named module and also
......@@ -81,7 +81,10 @@ class Tools(BoxLayout):
'''
module_name = tool_to_import
class_name = ''.join(tool_to_import.title().split('_'))
tool_module = import_module('modules.encryption.tools.all_tools.' + module_name)
tool_module = import_module(
'modules.course_modules.' + self.root_module_name + '.tools.' +
module_name
)
tool_class = getattr(tool_module, class_name)
self.all_tools[tool_to_import]['module'] = tool_module
self.all_tools[tool_to_import]['class'] = tool_class
......@@ -96,14 +99,15 @@ class Tools(BoxLayout):
self.remove_widget(self.children[0])
box_layout = BoxLayout()
box_layout.id = 'tools_menu' # pylint: disable=invalid-name
box_layout.id = 'module_tools_menu'
box_layout.orientation = 'vertical'
back_to_tool_menu = BackToToolsMenu()
tool_title_object = back_to_tool_menu.ids['tool_title']
tool_title_object.text = self.all_tools[tool_id]['title']
tool_id_object = self.all_tools[tool_id]
back_to_tool_menu.ids['tool_title'].text = tool_id_object['title']
back_to_tool_menu.ids['tools_menu_button'].bind(
on_press=self.back_to_tools_menu)
on_press=self.back_to_tools_menu
)
box_layout.add_widget(back_to_tool_menu)
box_layout.add_widget(self.all_tools[tool_id]['class']())
......@@ -111,8 +115,7 @@ class Tools(BoxLayout):
def back_to_tools_menu(self, button_object):
'''
back_to_tools_menu removes the tool widget and replaces it with tools
menu
back_to_tools_menu removed the tool widget and replaces tools menu
'''
self.remove_widget(button_object)
self.remove_widget(self.children[0])
......
'''
Modules containing Tutorials classes for Encryption
Modules containing Tutorials classes for Abstraction
'''
import os
import json
......@@ -8,10 +8,10 @@ from kivy.lang import Builder
from kivy.factory import Factory
from kivy.uix.boxlayout import BoxLayout
from modules.parser import tutorial_parser
from modules.parsers import tutorial_parser
Builder.load_file('./ui/encryption/tutorials.kv')
Builder.load_file('./ui/module_box/tutorials.kv')
class TutorialBox(BoxLayout):
......@@ -26,27 +26,31 @@ class BackToTutorialsMenu(BoxLayout):
'''
class Tutorials(BoxLayout):
class ModuleTutorialsMenu(BoxLayout):
'''
Tutorials class for Encryption
ModuleTutorialsMenu class to present Tutorials Menu
'''
def __init__(self, **kwargs):
super(Tutorials, self).__init__(**kwargs)
def __init__(self, root_module_name, **kwargs):
super(ModuleTutorialsMenu, self).__init__(**kwargs)
self.all_tutorials = {}
self.removed_tutorials_menu = None
self.root_module_name = root_module_name
with open('data/root.json') as data:
with open('data/module_data.json') as data:
json_data = json.loads(data.read())
self.encryption_data = json_data[4]["encryption"]
for key, value in self.encryption_data[0]["tutorials"][0].items():
value['title'] = key
tutorial_key = '_'.<