def action_import_ods(self, resource, context, form): # Check if lpod is install ? if lpod_is_install is False: msg = ERROR(u'Please install LPOD') return context.come_back(msg) # Get models root = context.root shop = get_shop(resource) models = shop.get_resource('products-models').get_resources() # Open ODF file filename, mimetype, body = form['file'] f = StringIO(body) document = odf_get_document(f) for table in document.get_body().get_tables(): model_name = table.get_name() csv = CSVFile(string=table.to_csv()) for row in csv.get_rows(): reference = row[0] declination_name = row[1] stock = row[-3] price1 = row[-2] price2 = row[-1] product_brains = root.search( reference=reference).get_documents() if len(product_brains) > 1: print 'Reference %s %s' % (reference, len(product_brains)) continue product_brain = product_brains[0] product = root.get_resource(product_brain.abspath) declination = product.get_resource(declination_name) # Set change declination.set_property('stock-quantity', int(stock)) context.message = MSG(u'Import has been done') return
class SVG(Image): class_id = 'image/svg+xml' class_title = MSG(u'Image SVG') # Fields data = File_Field(required=True, class_handler=SVGFile)
def get_before_namespace(self, resource, context): # Set organizer infos in ${before} owner = resource.get_owner() owner = resource.get_resource(owner).get_title() owner_msg = MSG(u'<p id="event-owner">Created by <em>{owner}</em></p>') owner_msg = owner_msg.gettext(owner=owner).encode('utf-8') return XMLParser(owner_msg)
class CSV_ODS_Writer(prototype): name = 'ooo' title = MSG(u"CSV for OpenOffice.org / LibreOffice") mimetype = 'text/comma-separated-values' extension = 'csv' encoding = 'UTF-8' separator = "," newline = "\n" def __init__(cls, columns, name): cls.columns = columns cls.csv = CSVFile() def get_nrows(cls): return cls.csv.get_nrows() def add_row(cls, row, is_header=False): values = [] for i, value in enumerate(row): column = cls.columns[i] value = column.encode(value) if type(value) is unicode: value = value.encode(cls.encoding) else: value = str(value) values.append(value) cls.csv.add_row(values) def to_str(cls): return cls.csv.to_str(separator=cls.separator, newline=cls.newline)
class ConfigMail_Edit(AutoEdit): title = MSG(u'Email options') description = mail_description fields = [ 'emails_from_addr', 'emails_reply_to', 'emails_signature', 'contacts' ]
class Users_Browse(BrowseUsers): table_actions = [ BrowseButton(access='is_admin', name='switch_state', title=MSG(u'Switch state')) ] def action_switch_state(self, resource, context, form): # Verify if after this operation, all is ok usernames = form['ids'] if context.user.name in usernames: context.message = ERROR(u'You cannot change your state yourself.') return database = resource.database for username in usernames: user = database.get_resource('/users/%s' % username) email = user.get_value('email') user_state = user.get_value('user_state') if user_state == 'active': user.set_value('user_state', 'inactive') send_email('switch-state-deactivate', context, email) elif user_state == 'inactive': user.set_value('user_state', 'active') send_email('switch-state-activate', context, email) else: # pending continue # Ok context.message = messages.MSG_CHANGES_SAVED
class Archive_View(STLView): access = 'is_allowed_to_view' title = MSG(u'View') template = '/ui/ikaaro/binary/Archive_view.xml' schema = {'target': PathDataType, 'update': Boolean} def get_namespace(self, resource, context): filename = resource.get_value('filename') or resource.get_title() contents = [ process_name(x)[1] + u'\n' for x in resource.get_value('data').get_contents() ] contents = ''.join(contents) # Extract archive extract = context.root.is_allowed_to_edit(context.user, resource) if extract: widget = PathSelectorWidget('target', value='..').render() else: widget = None # Ok return { 'filename': filename, 'contents': contents, 'extract': extract, 'widget': widget } def _get_form(self, resource, context): form = super(Archive_View, self)._get_form(resource, context) # Get the target resource target = form['target'] target = resource.get_resource(target, soft=True) if target is None: raise FormError, ERROR(u'Target does not exist.') if isinstance(target, Folder) is False: raise FormError, ERROR(u'Target must be a folder.') return form def action(self, resource, context, form): # Get the list of paths to extract handler = resource.get_value('data') paths = handler.get_contents() paths.sort() # Get the target resource target = form['target'] target = resource.get_resource(target) # Make the resources language = resource.get_edit_languages(context)[0] target.extract_archive(handler, language, update=form['update']) # Ok message = MSG(u'Files extracted') goto = context.get_link(target) return context.come_back(message, goto=goto)
class Payments_ChoosePayment(STLForm): access = 'is_authenticated' title = MSG(u'Choose a payment way') template = '/ui/backoffice/payments/choose_payment.xml' total_price = {'with_tax': decimal('0'), 'without_tax': decimal('0')} def get_namespace(self, resource, context): total_price = self.total_price namespace = {'payments': [], 'total_price': total_price} for mode in resource.search_resources(cls=PaymentWay): logo = mode.get_property('logo') if logo: logo = mode.get_resource(logo, soft=True) shipping_groups = mode.get_property('only_this_groups') user_group = context.user.get_property('user_group') if len(shipping_groups) > 0 and user_group not in shipping_groups: continue if mode.is_enabled(context) is False: continue namespace['payments'].append({ 'name': mode.name, 'value': mode.get_title(), 'description': mode.get_payment_way_description(context, total_price), 'logo': str(context.resource.get_pathto(logo)) if logo else None, 'enabled': True }) return namespace
class UserEmail_Field(Email_Field): title = MSG(u'E-mail Address') indexed = True stored = True required = True unique = True
class Text_Edit(File_Edit): title = MSG(u'Edit') icon = 'edit.png' fields = ['title', 'data', 'file', 'description', 'subject', 'share'] def get_value(self, resource, context, name, datatype): if name == 'data': data = resource.get_value('data') if data is None: return '' return data.to_str() proxy = super(Text_Edit, self) return proxy.get_value(resource, context, name, datatype) def set_value(self, resource, context, name, form): if name == 'data': if form.get('file'): return False old_data = resource.get_value('data') old_value = old_data.to_str() value = form['data'] # Remove ^M character value = '\n'.join(value.splitlines()) if old_value == value: return False # Save new text old_data.load_state_from_string(value) context.database.change_resource(resource) return False return super(Text_Edit, self).set_value(resource, context, name, form)
def get_items(self, context): options = [] root = get_context().root base_abspath = self.get_property('base_abspath') base_resource = root.get_resource(base_abspath) search = root.search(format='category', parent_paths=base_abspath) items_list = [base_resource] for brain in search.get_documents(sort_by='abspath'): items_list.append(root.get_resource(brain.abspath)) for resource in items_list: abspath = str(resource.get_abspath()) selected = context.resource.get_abspath() == abspath uri = get_reference(context.get_link(resource)) uri.query = context.uri.query title = resource.get_title() if abspath == base_abspath: title = MSG(u'All') options.append({ 'name': abspath, 'criterium': 'category', 'query': PhraseQuery('parent_paths', abspath), 'selected': selected, 'uri': uri, 'css': 'selected' if selected else None, 'title': title }) return options
class CSV_AddRow(RowForm): title = MSG(u'Add Row') icon = 'new.png' actions = [ Button(access=True, css='button-ok', title=MSG(u'Add'), show=True) ] def action(self, resource, context, form): row = [form[name] for name, title in resource.get_columns()] handler = resource.get_csv_handler() row = handler.add_row(row) # Ok message = INFO(u'New row added.') goto = ';edit_row?index=%s' % row.number return context.come_back(message, goto=goto)
def get_widgets(self, resource, context): if len(ContactOptions(resource=resource).get_options()) == 1: to = HiddenWidget('to') else: to = SelectWidget('to', title=MSG(u'Recipient')) return [ to, TextWidget('from', title=MSG(u'Your email address'), size=40), TextWidget('subject', title=MSG(u'Message subject'), size=40), MultilineWidget('message_body', title=MSG(u'Message body'), rows=8, cols=50), CaptchaWidget('captcha') ]
class Group_BrowseUsers(BrowseUsers): schema = {'ids': String(multiple=True)} table_actions = [BrowseButton(access='is_admin', title=MSG(u'Update'))] @proto_lazy_property def _property_name(self): return self.resource.parent.property_name def get_item_value(self, resource, context, item, column): if column == 'checkbox': user = context.root.get_resource(item.abspath) groups = user.get_value(self._property_name) return item.name, str(resource.abspath) in groups proxy = super(Group_BrowseUsers, self) return proxy.get_item_value(resource, context, item, column) def action(self, resource, context, form): group_id = str(resource.abspath) root = resource.get_resource('/') for user in root.get_resources('users'): groups = set(user.get_value(self._property_name)) if user.name in form['ids']: groups.add(group_id) else: groups.discard(group_id) user.set_value(self._property_name, list(groups)) context.message = MSG_CHANGES_SAVED
class Product_View(STLForm): access = 'is_allowed_to_view' title = MSG(u'View') scripts = ['/ui/shop/js/declinations.js'] def get_template(self, resource, context): product_model = resource.get_product_model() if product_model is not None: return get_skin_template(context, '/product/product_view_%s.xml' % product_model.name, '/product/product_view.xml') return get_skin_template(context, '/product/product_view.xml') def get_schema(self, resource, context): return merge_dicts(STLForm.get_schema(self, resource, context), resource.get_purchase_options_schema()) def get_namespace(self, resource, context): context.scripts.append('/ui/shop/js/declinations.js') declinations = list(resource.search_resources(cls=Declination)) javascript_products = resource.get_javascript_namespace(declinations) purchase_options = resource.get_purchase_options_namespace(declinations) return merge_dicts(resource.get_namespace(context), javascript_products=javascript_products, purchase_options=purchase_options) action_add_to_cart_schema = {'quantity': Integer(default=1)} def action_add_to_cart(self, resource, context, form): """ Add to cart """ cart = ProductCart(context) # Check if we can add to cart if not resource.is_buyable(context): msg = MSG(u"This product isn't buyable") return context.come_back(msg) # Get purchase options declination = None kw = {} for key in resource.get_purchase_options_schema(): if form[key] is not None: kw[key] = form[key] if kw: declination = resource.get_declination(kw) if declination is None: context.message = ERROR(u'Declination not exist') return # Check if product is in stock cart_quantity = cart.get_product_quantity_in_cart(resource.name) total_quantity = cart_quantity + form['quantity'] if not resource.is_in_stock_or_ignore_stock(total_quantity, declination): msg = u"Quantity in stock insufficient." return context.come_back(MSG(msg)) # Add to cart cart.add_product(resource, form['quantity'], declination) # Information message context.message = INFO(u'Product added to cart !')
class ShopModule_Edit(DBResource_Edit): title = MSG(u'Edit') access = 'is_allowed_to_edit' base_schema = {'title': Unicode, 'timestamp': DateTime(readonly=True)} base_widgets = [timestamp_widget, title_widget] def get_schema(self, resource, context): return merge_dicts(self.base_schema, resource.item_schema) def get_widgets(self, resource, context): return self.base_widgets + resource.item_widgets def action(self, resource, context, form): # Check edit conflict self.check_edit_conflict(resource, context, form) if context.edit_conflict: return # Save changes title = form['title'] language = resource.get_content_language(context) resource.set_property('title', title, language=language) for key, datatype in resource.item_schema.items(): if getattr(datatype, 'multilingual', False) is True: resource.set_property(key, form[key], language) else: resource.set_property(key, form[key]) # Ok context.message = messages.MSG_CHANGES_SAVED
class WebPage_View(BaseView): access = 'is_allowed_to_view' title = MSG(u'View') icon = 'view.png' def GET(self, resource, context): return resource.get_html_data()
def action(self, resource, context, form): root = context.root to_addr = resource.get_property('to_addr') subject = MSG(u'Message from form: "%s"' % resource.get_title()).gettext() text = [] handler = resource.handler get_value = handler.get_record_value from_addr = to_addr for record in handler.get_records_in_order(): name = get_value(record, 'name') datatype = get_value(record, 'datatype') value = form[name] # XXX Render on datatype ? if datatype == 'product': shop = get_shop(resource) site_root = resource.get_site_root() product = context.root.get_resource(value) base_uri = shop.get_property('shop_uri') end_uri = site_root.get_pathto(product) value = get_reference(base_uri).resolve(end_uri) elif datatype == 'email': # XXX Set from_addr from_addr = value title = get_value(record, 'title') text.append('*%s* \n\n %s' % (title, value)) text = '\n\n\n'.join(text) root.send_email(to_addr, subject, from_addr=from_addr, text=text, subject_with_host=False) return resource.get_property('final_message')
def action(self, resource, context, form): # Check register key key = resource.get_property('user_state').get_parameter('key') if not key: context.message = MSG(u'User is not pending') return if form['key'] != key: context.message = messages.MSG_BAD_KEY return # Check passwords password = form['newpass'] password2 = form['newpass2'] if password != password2: context.message = messages.MSG_PASSWORD_MISMATCH return # Set user resource.set_value('password', password) resource.del_property('user_state') # Set cookie resource._login(password, context) # Send email to_addr = resource.get_value('email') send_email('register-send-confirmation', context, to_addr, user=resource) # Ok message = INFO(u'Operation successful! Welcome.') return context.come_back(message, goto='./')
class Calendar(DBResource): class_id = 'calendar' class_title = MSG(u'Calendar') class_views = ['edit'] # Fields title = DBResource.title(required=True) hidden_for_users = Char_Field(multiple=True) color = Color_Field(title=MSG(u'Color'), default='#0467BA', required=True) owner = Owner_Field # Views _fields = ['title', 'color'] new_instance = Calendar_NewInstance(fields=_fields) edit = Calendar_Edit(fields=_fields)
class File_NewInstance(AutoAdd): title = MSG(u'Upload File') fields = ['data', 'title', 'location', 'progressbar'] progressbar = ProgressBar_Field def get_new_resource_name(self, form): name = super(File_NewInstance, self).get_new_resource_name(form) if name: return name filename, mimetype, body = form['data'] name, extension, language = FileName.decode(filename) if mimetype not in ('application/xhtml+xml', 'text/html'): name = FileName.encode((name, extension, None)) return name def make_new_resource(self, resource, context, form): # 1. Make the resource container = form['container'] name = form['name'] filename, mimetype, body = form['data'] language = container.get_edit_languages(context)[0] child = container._make_file(name, filename, mimetype, body, language) form['child'] = child # 2. Set properties return self.init_new_resource(resource, context, form)
class Configuration(Folder): class_id = 'configuration' class_title = MSG(u'Configuration') is_content = False class_core_views = ['edit_languages', 'broken_links', 'orphans'] def init_resource(self, **kw): super(Configuration, self).init_resource(**kw) for name, module in self._modules.items(): self.make_resource(name, module, soft=True) # Plugins _modules = {} @classmethod def register_module(cls, module): cls._modules[module.config_name] = module @classmethod def unregister_module(cls, name): del cls._modules[name] # Views view = Configuration_View edit_languages = Config_EditLanguages broken_links = Config_BrokenLinks orphans = Config_Orphans(config_group='webmaster')
class DBResource_Changes(STLView): access = 'is_admin' title = MSG(u'Changes') template = '/ui/revisions/changes.xml' query_schema = {'revision': String(mandatory=True), 'to': String} def get_namespace(self, resource, context): revision = context.query['revision'] to = context.query['to'] root = context.root worktree = context.database.worktree if to is None: # Case 1: show one commit try: diff = worktree.git_diff(revision) except EnvironmentError, e: error = unicode(str(e), 'utf_8') context.message = ERROR(u"Git failed: {error}", error=error) return {'metadata': None, 'stat': None, 'changes': None} metadata = worktree.get_metadata() author_name = metadata['author_name'] metadata['author_name'] = root.get_user_title(author_name) stat = worktree.git_stats(revision) else:
def action(self, resource, context, form): email = form['email'].strip() # 1. Make the user, or get it results = context.database.search(format='user', email=email) if len(results) == 0: # New user user = context.root.make_user() for name in self.fields: field = self.get_field(name) if field and getattr(field, 'persistent', True): self.set_value(user, context, name, form) user.update_pending_key() email_id = 'user-ask-for-confirmation' else: # User already registered user = results.get_resources().next() email_id = 'register-already-registered' # 2. Send email send_email(email_id, context, email, user=user) # 3. Show message message = MSG( u'<div id="registration-end-msg">' u'An email has been sent to you, to finish the registration ' u'process follow the instructions detailed in it.</div>') return message.gettext().encode('utf-8')
def get_search_actions(self, resource, context): search_button = Button(access=True, resource=resource, context=context, css='button-search', title=MSG(u'Search')) return [search_button]
class Form_Export(BaseView): access = 'is_allowed_to_view' title = MSG(u"Download form") def GET(self, resource, context): encoding = 'cp1252' # FIXME #if not resource.is_ready(): # msg = MSG(u"Your form is not finished yet.") # return context.come_back(msg, goto='/') # construct the csv csv = CSVFile() csv.add_row(["Chapitre du formulaire", "rubrique", "valeur"]) schema = resource.get_schema() handler = resource.get_value('data') for name, datatype in sorted(schema.iteritems()): if name in ('ctime', 'mtime'): continue value = handler.get_value(name, schema) data = force_encode(value, datatype, encoding) if type(data) is not str: raise ValueError, str(type(datatype)) csv.add_row([datatype.pages[0], name, data]) # Return as CSV context.set_content_type('text/comma-separated-values') context.set_content_disposition('attachment', filename="%s.csv" % (resource.name)) # Ok return csv.to_str(separator=';')
def get_namespace(self, resource, context): progress = Shop_Progress(index=6, title=MSG(u'Payment end')) return { 'ref': context.query['ref'], 'progress': progress.GET(resource, context), 'user_name': context.user.name }
class Form_Print(STLView): access = 'is_allowed_to_view' title = MSG(u"Print form") template = '/ui/goodforms/form/print.xml' styles = ['/ui/goodforms/print.css'] pages = [] def get_page_title(self, resource, context): return resource.get_form_title() def get_namespace(self, resource, context): set_print(context) context.bad_types = set() forms = [] for page_number in resource.get_page_numbers(): formpage = resource.get_formpage(page_number) view = getattr(resource, 'page%s' % page_number) ns = merge_dicts(formpage.get_namespace(resource, view, context, skip_print=True), title=formpage.get_title()) forms.append(ns) namespace = {} namespace['forms'] = forms return namespace
class End_Field(Datetime_Field): datatype = DateTime(time_is_required=False) stored = True title = MSG(u'End') required = True widget = Datetime_Field.widget(value_time_default=time(10, 0))
class FileSizeValidator(BaseValidator): validator_id = 'file-size' max_size = 1024 * 1024 * 10 errors = {'too_big': MSG(u'Your file is too big. ({size})')} def check(self, value): filename, mimetype, body = value size = len(body) if size > self.max_size: kw = { 'size': self.pretty_bytes(size), 'max_size': self.pretty_bytes(self.max_size) } self.raise_default_error(kw) def pretty_bytes(self, b): # 1 Byte = 8 Bits # 1 Kilobyte = 1024 Bytes # 1 Megabyte = 1048576 Bytes # 1 Gigabyte = 1073741824 Bytes if b < 1024: return u'%.01f Bytes' % b elif b < 1048576: return u'%.01f KB' % (b / 1024) elif b < 1073741824: return u'%.01f MB' % (b / 1048576) return u'%.01f GB' % (b / 1073741824)