Exemplo n.º 1
0
    def make_controller_template(self):
        """Make boilerplate controller template."""
        make_boilerplate("controller._py", self)

        if not self.istable:
            make_boilerplate("test_controller._py", self.as_dict())

        if not self.istable:
            make_boilerplate("controller.js", self.as_dict())
            #make_boilerplate("controller_list.js", self.as_dict())
            if not os.path.exists(
                    frappe.get_module_path(
                        frappe.scrub(self.module), 'doctype',
                        frappe.scrub(self.name), 'tests')):
                make_boilerplate("test_controller.js", self.as_dict())

        if self.has_web_view:
            templates_path = frappe.get_module_path(frappe.scrub(self.module),
                                                    'doctype',
                                                    frappe.scrub(self.name),
                                                    'templates')
            if not os.path.exists(templates_path):
                os.makedirs(templates_path)
            make_boilerplate('templates/controller.html', self.as_dict())
            make_boilerplate('templates/controller_row.html', self.as_dict())
Exemplo n.º 2
0
def make_records_in_module(app, module):
    dashboards_path = frappe.get_module_path(
        module, "{module}_dashboard".format(module=module))
    charts_path = frappe.get_module_path(module, "dashboard chart")
    cards_path = frappe.get_module_path(module, "number card")

    paths = [dashboards_path, charts_path, cards_path]
    for path in paths:
        make_records(path)
Exemplo n.º 3
0
def get_messages_from_page_or_report(doctype, name, module=None):
    if not module:
        module = frappe.db.get_value(doctype, name, "module")
    file_path = frappe.get_module_path(module, doctype, name, name)
    messages = get_messages_from_file(file_path + ".js")

    return clean(messages)
Exemplo n.º 4
0
def get_messages_from_doctype(name):
	"""Extract all translatable messages for a doctype. Includes labels, Python code,
	Javascript code, html templates"""
	messages = []
	meta = frappe.get_meta(name)

	messages = [meta.name, meta.module]

	if meta.description:
		messages.append(meta.description)

	# translations of field labels, description and options
	for d in meta.get("fields"):
		messages.extend([d.label, d.description])

		if d.fieldtype=='Select' and d.options:
			options = d.options.split('\n')
			if not "icon" in options[0]:
				messages.extend(options)

	# translations of roles
	for d in meta.get("permissions"):
		if d.role:
			messages.append(d.role)

	messages = [message for message in messages if message]
	messages = [('DocType: ' + name, message) for message in messages if is_translatable(message)]

	# extract from js, py files
	doctype_file_path = frappe.get_module_path(meta.module, "doctype", meta.name, meta.name)
	messages.extend(get_messages_from_file(doctype_file_path + ".js"))
	messages.extend(get_messages_from_file(doctype_file_path + "_list.js"))
	messages.extend(get_messages_from_file(doctype_file_path + "_list.html"))
	messages.extend(get_messages_from_file(doctype_file_path + "_calendar.js"))
	return messages
Exemplo n.º 5
0
def get_messages_from_doctype(name):
    messages = []
    meta = frappe.get_meta(name)

    messages = [meta.name, meta.module]

    if meta.description:
        messages.append(meta.description)

    # translations of field labels, description and options
    for d in meta.get("fields"):
        messages.extend([d.label, d.description])

        if d.fieldtype=='Select' and d.options \
         and not d.options.startswith("attach_files:"):
            options = d.options.split('\n')
            if not "icon" in options[0]:
                messages.extend(options)

    # translations of roles
    for d in meta.get("permissions"):
        if d.role:
            messages.append(d.role)

    # extract from js, py files
    doctype_file_path = frappe.get_module_path(meta.module, "doctype",
                                               meta.name, meta.name)
    messages.extend(get_messages_from_file(doctype_file_path + ".js"))
    messages.extend(get_messages_from_file(doctype_file_path + "_list.js"))
    messages.extend(get_messages_from_file(doctype_file_path + "_list.html"))
    messages.extend(get_messages_from_file(doctype_file_path + "_calendar.js"))
    return clean(messages)
def create_new_connection(module, connection_name):
	if not frappe.conf.get('developer_mode'):
		frappe.msgprint(_('Please enable developer mode to create new connection'))
		return
	# create folder
	module_path = frappe.get_module_path(module)
	connectors_folder = os.path.join(module_path, 'connectors')
	frappe.create_folder(connectors_folder)

	# create init py
	create_init_py(module_path, 'connectors', '')

	connection_class = connection_name.replace(' ', '')
	file_name = frappe.scrub(connection_name) + '.py'
	file_path = os.path.join(module_path, 'connectors', file_name)

	# create boilerplate file
	with open(file_path, 'w') as f:
		f.write(connection_boilerplate.format(connection_class=connection_class))

	# get python module string from file_path
	app_name = frappe.db.get_value('Module Def', module, 'app_name')
	python_module = os.path.relpath(
		file_path, '../apps/{0}'.format(app_name)).replace(os.path.sep, '.')[:-3]

	return python_module
Exemplo n.º 7
0
def create_new_connection(module, connection_name):
    if not frappe.conf.get('developer_mode'):
        frappe.msgprint(
            _('Please enable developer mode to create new connection'))
        return
    # create folder
    module_path = frappe.get_module_path(module)
    connectors_folder = os.path.join(module_path, 'connectors')
    frappe.create_folder(connectors_folder)

    # create init py
    create_init_py(module_path, 'connectors', '')

    connection_class = connection_name.replace(' ', '')
    file_name = frappe.scrub(connection_name) + '.py'
    file_path = os.path.join(module_path, 'connectors', file_name)

    # create boilerplate file
    with open(file_path, 'w') as f:
        f.write(
            connection_boilerplate.format(connection_class=connection_class))

    # get python module string from file_path
    app_name = frappe.db.get_value('Module Def', module, 'app_name')
    python_module = os.path.relpath(file_path,
                                    '../apps/{0}'.format(app_name)).replace(
                                        os.path.sep, '.')[:-3]

    return python_module
Exemplo n.º 8
0
def get_messages_from_page_or_report(doctype, name, module=None):
	if not module:
		module = frappe.db.get_value(doctype, name, "module")
	file_path = frappe.get_module_path(module, doctype, name, name)
	messages = get_messages_from_file(file_path + ".js")

	return clean(messages)
Exemplo n.º 9
0
def create_new_connection(module, connection_name):
    if not frappe.conf.get("developer_mode"):
        frappe.msgprint(
            _("Please enable developer mode to create new connection"))
        return
    # create folder
    module_path = frappe.get_module_path(module)
    connectors_folder = os.path.join(module_path, "connectors")
    frappe.create_folder(connectors_folder)

    # create init py
    create_init_py(module_path, "connectors", "")

    connection_class = connection_name.replace(" ", "")
    file_name = frappe.scrub(connection_name) + ".py"
    file_path = os.path.join(module_path, "connectors", file_name)

    # create boilerplate file
    with open(file_path, "w") as f:
        f.write(
            connection_boilerplate.format(connection_class=connection_class))

    # get python module string from file_path
    app_name = frappe.db.get_value("Module Def", module, "app_name")
    python_module = os.path.relpath(file_path,
                                    "../apps/{0}".format(app_name)).replace(
                                        os.path.sep, ".")[:-3]

    return python_module
Exemplo n.º 10
0
def get_messages_from_doctype(name):
	"""Extract all translatable messages for a doctype. Includes labels, Python code,
	Javascript code, html templates"""
	messages = []
	meta = frappe.get_meta(name)

	messages = [meta.name, meta.module]

	if meta.description:
		messages.append(meta.description)

	# translations of field labels, description and options
	for d in meta.get("fields"):
		messages.extend([d.label, d.description])

		if d.fieldtype=='Select' and d.options:
			options = d.options.split('\n')
			if not "icon" in options[0]:
				messages.extend(options)

	# translations of roles
	for d in meta.get("permissions"):
		if d.role:
			messages.append(d.role)

	messages = [message for message in messages if message]
	messages = [('DocType: ' + name, message) for message in messages if is_translatable(message)]

	# extract from js, py files
	doctype_file_path = frappe.get_module_path(meta.module, "doctype", meta.name, meta.name)
	messages.extend(get_messages_from_file(doctype_file_path + ".js"))
	messages.extend(get_messages_from_file(doctype_file_path + "_list.js"))
	messages.extend(get_messages_from_file(doctype_file_path + "_list.html"))
	messages.extend(get_messages_from_file(doctype_file_path + "_calendar.js"))
	return messages
Exemplo n.º 11
0
def get_messages_from_doctype(name):
	messages = []
	meta = frappe.get_meta(name)

	messages = [meta.name, meta.module]

	if meta.description:
		messages.append(meta.description)

	# translations of field labels, description and options
	for d in meta.get("fields"):
		messages.extend([d.label, d.description])

		if d.fieldtype=='Select' and d.options \
			and not d.options.startswith("attach_files:"):
			options = d.options.split('\n')
			if not "icon" in options[0]:
				messages.extend(options)

	# translations of roles
	for d in meta.get("permissions"):
		if d.role:
			messages.append(d.role)

	# extract from js, py files
	doctype_file_path = frappe.get_module_path(meta.module, "doctype", meta.name, meta.name)
	messages.extend(get_messages_from_file(doctype_file_path + ".js"))
	messages.extend(get_messages_from_file(doctype_file_path + "_list.js"))
	messages.extend(get_messages_from_file(doctype_file_path + "_list.html"))
	messages.extend(get_messages_from_file(doctype_file_path + "_calendar.js"))
	return clean(messages)
Exemplo n.º 12
0
def delete_controllers(doctype, module):
    """
	Delete controller code in the doctype folder
	"""
    module_path = get_module_path(module)
    dir_path = os.path.join(module_path, 'doctype', frappe.scrub(doctype))

    shutil.rmtree(dir_path)
Exemplo n.º 13
0
	def make_controller_template(self):
		"""Make boilerplate controller template."""
		make_boilerplate("controller._py", self)

		if not self.istable:
			make_boilerplate("test_controller._py", self.as_dict())
			make_boilerplate("controller.js", self.as_dict())
			#make_boilerplate("controller_list.js", self.as_dict())
			if not os.path.exists(frappe.get_module_path(frappe.scrub(self.module),
				'doctype', frappe.scrub(self.name), 'tests')):
				make_boilerplate("test_controller.js", self.as_dict())

		if self.has_web_view:
			templates_path = frappe.get_module_path(frappe.scrub(self.module), 'doctype', frappe.scrub(self.name), 'templates')
			if not os.path.exists(templates_path):
				os.makedirs(templates_path)
			make_boilerplate('templates/controller.html', self.as_dict())
			make_boilerplate('templates/controller_row.html', self.as_dict())
Exemplo n.º 14
0
	def get_web_template(self, suffix=''):
		'''Returns the relative path of the row template for this doctype'''
		module_name = frappe.scrub(self.module)
		doctype = frappe.scrub(self.name)
		template_path = frappe.get_module_path(module_name, 'doctype',
			doctype, 'templates', doctype + suffix + '.html')
		if os.path.exists(template_path):
			return '{module_name}/doctype/{doctype_name}/templates/{doctype_name}{suffix}.html'.format(
				module_name = module_name, doctype_name = doctype, suffix=suffix)
		return None
Exemplo n.º 15
0
	def get_web_template(self, suffix=''):
		'''Returns the relative path of the row template for this doctype'''
		module_name = frappe.scrub(self.module)
		doctype = frappe.scrub(self.name)
		template_path = frappe.get_module_path(module_name, 'doctype',
			doctype, 'templates', doctype + suffix + '.html')
		if os.path.exists(template_path):
			return '{module_name}/doctype/{doctype_name}/templates/{doctype_name}{suffix}.html'.format(
				module_name = module_name, doctype_name = doctype, suffix=suffix)
		return None
Exemplo n.º 16
0
	def get_web_template(self, suffix=""):
		"""Returns the relative path of the row template for this doctype"""
		module_name = frappe.scrub(self.module)
		doctype = frappe.scrub(self.name)
		template_path = frappe.get_module_path(
			module_name, "doctype", doctype, "templates", doctype + suffix + ".html"
		)
		if os.path.exists(template_path):
			return "{module_name}/doctype/{doctype_name}/templates/{doctype_name}{suffix}.html".format(
				module_name=module_name, doctype_name=doctype, suffix=suffix
			)
		return None
Exemplo n.º 17
0
def _get_messages_from_page_or_report(doctype, name, module=None):
	if not module:
		module = frappe.db.get_value(doctype, name, "module")

	doc_path = frappe.get_module_path(module, doctype, name)

	messages = get_messages_from_file(os.path.join(doc_path, frappe.scrub(name) +".py"))

	if os.path.exists(doc_path):
		for filename in os.listdir(doc_path):
			if filename.endswith(".js") or filename.endswith(".html"):
				messages += get_messages_from_file(os.path.join(doc_path, filename))

	return messages
Exemplo n.º 18
0
def _get_messages_from_page_or_report(doctype, name, module=None):
    if not module:
        module = frappe.db.get_value(doctype, name, "module")
    doc_path = frappe.get_module_path(module, doctype, name)
    messages = get_messages_from_file(doc_path + name + ".js")
    messages += get_messages_from_file(doc_path + name + ".html")
    messages += get_messages_from_file(doc_path + name + ".py")

    if doctype == "Page":
        for fname in os.listdir(doc_path):
            if fname.endswith(".html"):
                messages += get_messages_from_file(doc_path + fname)

    return clean(messages)
Exemplo n.º 19
0
def export_module_json(doc, is_standard, module):
	"""Make a folder for the given doc and add its json file (make it a standard
		object that will be synced)"""
	if (not frappe.flags.in_import and getattr(frappe.get_conf(),'developer_mode', 0)
		and is_standard):
		from frappe.modules.export_file import export_to_files

		# json
		export_to_files(record_list=[[doc.doctype, doc.name]], record_module=module)

		path = os.path.join(frappe.get_module_path(module), scrub(doc.doctype),
			scrub(doc.name), scrub(doc.name))

		return path
Exemplo n.º 20
0
def _get_messages_from_page_or_report(doctype, name, module=None):
	if not module:
		module = frappe.db.get_value(doctype, name, "module")

	doc_path = frappe.get_module_path(module, doctype, name)

	messages = get_messages_from_file(os.path.join(doc_path, frappe.scrub(name) +".py"))

	if os.path.exists(doc_path):
		for filename in os.listdir(doc_path):
			if filename.endswith(".js") or filename.endswith(".html"):
				messages += get_messages_from_file(os.path.join(doc_path, filename))

	return messages
Exemplo n.º 21
0
def export_module_json(doc, is_standard, module):
	"""Make a folder for the given doc and add its json file (make it a standard
		object that will be synced)"""
	if (not frappe.flags.in_import and getattr(frappe.get_conf(),'developer_mode', 0)
		and is_standard):
		from frappe.modules.export_file import export_to_files

		# json
		export_to_files(record_list=[[doc.doctype, doc.name]], record_module=module,
			create_init=is_standard)

		path = os.path.join(frappe.get_module_path(module), scrub(doc.doctype),
			scrub(doc.name), scrub(doc.name))

		return path
Exemplo n.º 22
0
def get_default_listview_fields(doctype):
    meta = frappe.get_meta(doctype)
    path = frappe.get_module_path(frappe.scrub(meta.module), "doctype",
                                  frappe.scrub(meta.name),
                                  frappe.scrub(meta.name) + ".json")
    doctype_json = frappe.get_file_json(path)

    fields = [
        f.get("fieldname") for f in doctype_json.get("fields")
        if f.get("in_list_view")
    ]

    if meta.title_field and not meta.title_field.strip() in fields:
        fields.append(meta.title_field.strip())

    return {doctype: fields}
Exemplo n.º 23
0
	def set_base_class_for_controller(self):
		'''Updates the controller class to subclass from `WebsiteGenertor`,
		if it is a subclass of `Document`'''
		controller_path = frappe.get_module_path(frappe.scrub(self.module),
			'doctype', frappe.scrub(self.name), frappe.scrub(self.name) + '.py')

		with open(controller_path, 'r') as f:
			code = f.read()

		class_string = '\nclass {0}(Document)'.format(self.name.replace(' ', ''))
		if '\nfrom frappe.model.document import Document' in code and class_string in code:
			code = code.replace('from frappe.model.document import Document',
				'from frappe.website.website_generator import WebsiteGenerator')
			code = code.replace('class {0}(Document)'.format(self.name.replace(' ', '')),
				'class {0}(WebsiteGenerator)'.format(self.name.replace(' ', '')))

		with open(controller_path, 'w') as f:
			f.write(code)
Exemplo n.º 24
0
	def set_base_class_for_controller(self):
		'''Updates the controller class to subclass from `WebsiteGenertor`,
		if it is a subclass of `Document`'''
		controller_path = frappe.get_module_path(frappe.scrub(self.module),
			'doctype', frappe.scrub(self.name), frappe.scrub(self.name) + '.py')

		with open(controller_path, 'r') as f:
			code = f.read()

		class_string = '\nclass {0}(Document)'.format(self.name.replace(' ', ''))
		if '\nfrom frappe.model.document import Document' in code and class_string in code:
			code = code.replace('from frappe.model.document import Document',
				'from frappe.website.website_generator import WebsiteGenerator')
			code = code.replace('class {0}(Document)'.format(self.name.replace(' ', '')),
				'class {0}(WebsiteGenerator)'.format(self.name.replace(' ', '')))

		with open(controller_path, 'w') as f:
			f.write(code)
Exemplo n.º 25
0
def get_messages_from_doctype(name):
	messages = []
	meta = frappe.get_meta(name)

	messages = [meta.name, meta.module]

	for d in meta.get("fields"):
		messages.extend([d.label, d.description])

		if d.fieldtype=='Select' and d.options \
			and not d.options.startswith("link:") \
			and not d.options.startswith("attach_files:"):
			options = d.options.split('\n')
			if not "icon" in options[0]:
				messages.extend(options)

	# extract from js, py files
	doctype_file_path = frappe.get_module_path(meta.module, "doctype", meta.name, meta.name)
	messages.extend(get_messages_from_file(doctype_file_path + ".js"))
	return clean(messages)
Exemplo n.º 26
0
def get_messages_from_doctype(name):
    messages = []
    meta = frappe.get_meta(name)

    messages = [meta.name, meta.module]

    for d in meta.get("fields"):
        messages.extend([d.label, d.description])

        if d.fieldtype=='Select' and d.options \
         and not d.options.startswith("attach_files:"):
            options = d.options.split('\n')
            if not "icon" in options[0]:
                messages.extend(options)

    # extract from js, py files
    doctype_file_path = frappe.get_module_path(meta.module, "doctype",
                                               meta.name, meta.name)
    messages.extend(get_messages_from_file(doctype_file_path + ".js"))
    return clean(messages)
Exemplo n.º 27
0
def get_default_listview_filters(doctype):
    meta = frappe.get_meta(doctype)
    table_fields = meta.get_table_fields()

    fields = {}

    for meta in [meta] + table_fields:
        if meta.doctype == "DocField":
            meta = frappe.get_meta(meta.options)

        path = frappe.get_module_path(frappe.scrub(meta.module), "doctype",
                                      frappe.scrub(meta.name),
                                      frappe.scrub(meta.name) + ".json")
        doctype_json = frappe.get_file_json(path)

        fields[meta.name] = [
            f.get("fieldname") for f in doctype_json.get("fields")
            if f.get("in_standard_filter")
        ]

    return fields
Exemplo n.º 28
0
def install_web():
	#site_path = frappe.get_site_path()
	module_path = frappe.get_module_path("reaction_ecommerce")
	reaction_home = os.path.abspath(os.path.join(module_path, ".."))
	reaction_www = os.path.abspath(os.path.join(reaction_home, "www"))
	reaction_web = os.path.abspath(os.path.join(reaction_www, "webreaction"))

	#make webreaction folder
	#frappe.create_folder(reaction_web)

	#git clone https://github.com/reactioncommerce/reaction.git
	#git("clone", "https://github.com/reactioncommerce/reaction.git")
	run_cmd(reaction_www, "git", "clone", "https://github.com/reactioncommerce/reaction.git", "webreaction")


	#git clone reaction efrappe
	reaction_plugins_path = os.path.abspath(os.path.join(reaction_web, "imports/plugins/custom"))
	run_cmd(reaction_plugins_path, "git", "clone", "https://github.com/saguas/efrappe.git")

	#install meteor npm packages
	info = """
		*********************************************************
		*   installing web meteor npm packages                  *
		*********************************************************
	"""
	print info
	run_cmd(reaction_web, "meteor", "npm", "install")
	#make public symlinks src .meteor/local/build/programs/web.browser and eweb in reaction_ecommerce/www/webreaction
	public_path = os.path.abspath(os.path.join(reaction_home, "public"))
	src = os.path.join(reaction_web, ".meteor/local/build/programs/web.browser")
	dst = os.path.join(public_path, "websrc")

	#make src .meteor/local/build/programs/web.browser
	os.symlink(src, dst)

	#make eweb reaction_ecommerce/www/webreaction
	src = reaction_web
	dst = os.path.join(public_path, "eweb")
	os.symlink(src, dst)
Exemplo n.º 29
0
	def make_controller_template(self):
		"""Make boilerplate controller template."""
		make_boilerplate("controller._py", self)

<<<<<<< HEAD
		if not (self.istable or self.issingle):
=======
		if not self.istable:
>>>>>>> 176d241496ede1357a309fa44a037b757a252581
			make_boilerplate("test_controller._py", self.as_dict())

		if not self.istable:
			make_boilerplate("controller.js", self.as_dict())
			#make_boilerplate("controller_list.js", self.as_dict())
			if not os.path.exists(frappe.get_module_path(frappe.scrub(self.module),
				'doctype', frappe.scrub(self.name), 'tests')):
				make_boilerplate("test_controller.js", self.as_dict())

		if self.has_web_view:
			templates_path = frappe.get_module_path(frappe.scrub(self.module), 'doctype', frappe.scrub(self.name), 'templates')
			if not os.path.exists(templates_path):
				os.makedirs(templates_path)
			make_boilerplate('templates/controller.html', self.as_dict())
			make_boilerplate('templates/controller_row.html', self.as_dict())

	def make_amendable(self):
		"""If is_submittable is set, add amended_from docfields."""
		if self.is_submittable:
			if not frappe.db.sql("""select name from tabDocField
				where fieldname = 'amended_from' and parent = %s""", self.name):
					self.append("fields", {
Exemplo n.º 30
0
def get_module_path(module):
    """Returns path of the given module"""
    return frappe.get_module_path(module)
Exemplo n.º 31
0
def get_module_path(module):
	"""Returns path of the given module"""
	return frappe.get_module_path(module)
Exemplo n.º 32
0
 def get_default_cmd(self, function="get_context"):
   cmd = os.path.join("{}.{}.{}.{}.{}".format(frappe.get_module_path(scrub(self.module)), scrub(self.doctype),
                                              scrub(self.name), scrub(self.name), function))
   cmd = '.'.join(cmd.split('/')[-2:])
   return cmd
Exemplo n.º 33
0
def create_report_files(site_name, report_name):
    # users can change the installation path, the operating
    # user or even have multiple benchs running in the same instance.

    # by default it is located at `/home/frappe/frappe-bench`

    # so, lets make sure we get the right path

    # get the base `frappe-bench` path where the system
    # is installed

    _base_path = frappe.utils.get_bench_path()

    # scrub to remove any trailing spaces or if it is a more complex name
    # by more than one word

    # we just want to make sure and do anything we can to guess
    # what the user wants and do it right

    _site_name = frappe.scrub(site_name)

    _sites_path = "/".join([_base_path, "sites"])

    # lets bring all the frappe sites setup on this instance

    _all_sites = frappe.utils \
     .get_sites(sites_path=_sites_path)

    # if the site does not exist in this instance
    # exit and let the user know

    if _site_name not in _all_sites:
        print ("Site {site} does not exist" \
         .format(site=_site_name))
        sys_exit()

    if _site_name != "all":
        _all_sites = [_site_name]

    module_exists = False

    for site in _all_sites:

        # initialize frappe for the current site.
        # reset thread locals `frappe.local`

        frappe.init(site=site, sites_path=_sites_path)

        # connect to site database instance
        # frappe.connect will try to init again
        # this is fine as we don't any other solution by now

        frappe.connect(site=site)

        # we now can import the frappe.db object

        from frappe import db

        # if the report exists in at least one site
        # that could mean we are posibly overriding the content
        # of the controllers

        # so, lets make sure that this never happens
        # if we prove it to be true, we don't want to write to the files
        # this is why we use two loops

        if not db.exists("Report", {
                "report_name": report_name,
        }):
            # mark the flag as true

            module_exists = True

            # and skip this round

        report = frappe.get_doc("Report", report_name)

        report_path = frappe.get_module_path(report.module, "report",
                                             report_name)

        frappe.create_folder(report_path, with_init=True)

        report.create_report_py()

        # lets close the connection and release werkzeug local

        frappe.destroy()