def get_widgets(layout, placeholder, user=None, workspace=None, position=None, occupied_cells=[]): """ Gets widgets. In case if in restricted mode (``RESTRICT_PLUGIN_ACCESS`` is set to True), user argument should be provided. Based on it, the list of plugins is returned. Restrictions are bypassed in case if ``RESTRICT_PLUGIN_ACCESS`` is set to False or user given is a superuser. Placeholders are validated already. We don't need to have validation here. :param dash.base.BaseDashLayout layout: Layout object. :param string placeholder_uid: Placeholder uid. :param django.contrib.auth.models.User user: :param string workspace: Workspace slug. :param int position: Plugin position. :param list occupied_cells: List of already occupied cells. :return list: """ # We should get the layout, see loop through its' plugins and see which of those do have rendererrs. Then # we get all the plugins (based on whether they are restricted or not - get the list) and then filter # out those that do not have renderers. ensure_autodiscover() registered_widgets = {} plugin_widget_uids = plugin_widget_registry._registry.keys() if not RESTRICT_PLUGIN_ACCESS or getattr(user, 'is_superuser', False): for uid, plugin in plugin_registry._registry.items(): # We should make sure that there are widgets available for the placeholder. plugin_widget_uid = PluginWidgetRegistry.namify(layout.uid, placeholder.uid, uid) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells(layout, placeholder, uid, position, check_boundaries=True) if plugin_widget_uid in plugin_widget_uids and widget_occupied_cells is not False and \ not lists_overlap(widget_occupied_cells, occupied_cells): plugin_widget = plugin_widget_registry.get(plugin_widget_uid) kwargs = {'placeholder_uid': placeholder.uid, 'plugin_uid': uid} if workspace: kwargs.update({'workspace': workspace}) if position: kwargs.update({'position': position}) plugin_group = force_text(plugin.group) if not plugin_group in registered_widgets: registered_widgets[plugin_group] = [] if PY3: widget_name = force_text(plugin.name, encoding='utf-8') else: widget_name = force_text(plugin.name, encoding='utf-8').encode('utf-8') registered_widgets[plugin_group].append(( uid, '{0} ({1}x{2})'.format(widget_name, plugin_widget.cols, plugin_widget.rows), reverse('dash.add_dashboard_entry', kwargs=kwargs) )) else: allowed_plugin_uids = get_allowed_plugin_uids(user) for uid, plugin in plugin_registry._registry.items(): # We should make sure that there are widgets available for the placeholder and user has access to the # widget desired. plugin_widget_uid = PluginWidgetRegistry.namify(layout.uid, placeholder.uid, uid) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells(layout, placeholder, uid, position, check_boundaries=True) if uid in allowed_plugin_uids and plugin_widget_uid in plugin_widget_uids and \ widget_occupied_cells is not False and not lists_overlap(widget_occupied_cells, occupied_cells): plugin_widget = plugin_widget_registry.get(plugin_widget_uid) kwargs = {'placeholder_uid': placeholder.uid, 'plugin_uid': uid} if workspace: kwargs.update({'workspace': workspace}) if position: kwargs.update({'position': position}) plugin_group = force_text(plugin.group) if not plugin_group in registered_widgets: registered_widgets[plugin_group] = [] registered_widgets[plugin_group].append( ( uid, '{0} ({1}x{2})'.format(force_text(plugin.name), plugin_widget.cols, plugin_widget.rows), reverse('dash.add_dashboard_entry', kwargs=kwargs) ) ) return registered_widgets
def get_widgets(layout, placeholder, user=None, workspace=None, \ position=None, occupied_cells=[], sort_items=True): """ Gets widgets. In case if in restricted mode (``RESTRICT_PLUGIN_ACCESS`` is set to True), user argument should be provided. Based on it, the list of plugins is returned. Restrictions are bypassed in case if ``RESTRICT_PLUGIN_ACCESS`` is set to False or user given is a superuser. Placeholders are validated already. We don't need to have validation here. :param dash.base.BaseDashLayout layout: Layout object. :param string placeholder_uid: Placeholder uid. :param django.contrib.auth.models.User user: :param string workspace: Workspace slug. :param int position: Plugin position. :param list occupied_cells: List of already occupied cells. :param bool sort_items: If set to True, returned items are sorted. :return list: """ # We should get the layout, see loop through its' plugins and see which of # those do have rendererrs. Then we get all the plugins (based on whether # they are restricted or not - get the list) and then filter out those # that do not have renderers. ensure_autodiscover() registered_widgets = {} plugin_widget_uids = plugin_widget_registry._registry.keys() if not RESTRICT_PLUGIN_ACCESS or getattr(user, 'is_superuser', False): for uid, plugin in plugin_registry._registry.items(): # We should make sure that there are widgets available for the # placeholder. plugin_widget_uid = PluginWidgetRegistry.namify( layout.uid, placeholder.uid, uid ) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells( layout, placeholder, uid, position, check_boundaries=True ) if plugin_widget_uid in plugin_widget_uids \ and widget_occupied_cells is not False \ and not lists_overlap(widget_occupied_cells, occupied_cells): plugin_widget = plugin_widget_registry.get(plugin_widget_uid) kwargs = {'placeholder_uid': placeholder.uid, 'plugin_uid': uid} if workspace: kwargs.update({'workspace': workspace}) if position: kwargs.update({'position': position}) plugin_group = safe_text(plugin.group) if plugin_group not in registered_widgets: registered_widgets[plugin_group] = [] widget_name = safe_text(plugin.name) registered_widgets[plugin_group].append( ( uid, '{0} ({1}x{2})'.format(widget_name, \ plugin_widget.cols, \ plugin_widget.rows), reverse('dash.add_dashboard_entry', kwargs=kwargs) ) ) elif plugin_widget_uid in plugin_widget_uids and widget_occupied_cells is not False \ and lists_overlap(widget_occupied_cells, occupied_cells): workspace_id = None if workspace: workspace_id = DashboardWorkspace.objects.get(name=workspace).pk current_widget = DashboardEntry.objects.filter(position=int(position), layout_uid=layout.uid, workspace_id=workspace_id,)[0] pattern = re.compile(r'\d+x\d+') dimensions = pattern.search(str(current_widget.plugin_uid)) dimensions = (dimensions.group()).split('x') plugin_widget = plugin_widget_registry.get(plugin_widget_uid) if int(plugin_widget.cols) == int(dimensions[0]) and int(plugin_widget.rows) == int(dimensions[1]): kwargs = {'placeholder_uid': placeholder.uid, 'plugin_uid': uid} if workspace: kwargs.update({'workspace': workspace}) if position: kwargs.update({'position': position}) plugin_group = safe_text(plugin.group) if plugin_group not in registered_widgets: registered_widgets[plugin_group] = [] widget_name = safe_text(plugin.name) registered_widgets[plugin_group].append( ( uid, '{0} ({1}x{2})'.format(widget_name, \ plugin_widget.cols, \ plugin_widget.rows), reverse('dash.add_dashboard_entry', kwargs=kwargs) ) ) else: allowed_plugin_uids = get_allowed_plugin_uids(user) for uid, plugin in plugin_registry._registry.items(): # We should make sure that there are widgets available for the # placeholder and user has access to the widget desired. plugin_widget_uid = PluginWidgetRegistry.namify( layout.uid, placeholder.uid, uid ) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells( layout, placeholder, uid, position, check_boundaries=True ) if uid in allowed_plugin_uids \ and plugin_widget_uid in plugin_widget_uids \ and widget_occupied_cells is not False \ and not lists_overlap(widget_occupied_cells, occupied_cells): plugin_widget = plugin_widget_registry.get(plugin_widget_uid) kwargs = {'placeholder_uid': placeholder.uid, 'plugin_uid': uid} if workspace: kwargs.update({'workspace': workspace}) if position: kwargs.update({'position': position}) plugin_group = safe_text(plugin.group) if not plugin_group in registered_widgets: registered_widgets[plugin_group] = [] registered_widgets[plugin_group].append( ( uid, '{0} ({1}x{2})'.format(safe_text(plugin.name), \ plugin_widget.cols, \ plugin_widget.rows), reverse('dash.add_dashboard_entry', kwargs=kwargs) ) ) if sort_items: for key, prop in registered_widgets.items(): prop.sort() return registered_widgets
def get_widgets(layout, placeholder, user=None, workspace=None, \ position=None, occupied_cells=[], sort_items=True): """ Gets widgets. In case if in restricted mode (``RESTRICT_PLUGIN_ACCESS`` is set to True), user argument should be provided. Based on it, the list of plugins is returned. Restrictions are bypassed in case if ``RESTRICT_PLUGIN_ACCESS`` is set to False or user given is a superuser. Placeholders are validated already. We don't need to have validation here. :param dash.base.BaseDashLayout layout: Layout object. :param string placeholder_uid: Placeholder uid. :param django.contrib.auth.models.User user: :param string workspace: Workspace slug. :param int position: Plugin position. :param list occupied_cells: List of already occupied cells. :param bool sort_items: If set to True, returned items are sorted. :return list: """ # We should get the layout, see loop through its' plugins and see which of # those do have rendererrs. Then we get all the plugins (based on whether # they are restricted or not - get the list) and then filter out those # that do not have renderers. ensure_autodiscover() registered_widgets = {} plugin_widget_uids = plugin_widget_registry._registry.keys() if not RESTRICT_PLUGIN_ACCESS or getattr(user, 'is_superuser', False): for uid, plugin in plugin_registry._registry.items(): # We should make sure that there are widgets available for the # placeholder. plugin_widget_uid = PluginWidgetRegistry.namify( layout.uid, placeholder.uid, uid) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells(layout, placeholder, uid, position, check_boundaries=True) if plugin_widget_uid in plugin_widget_uids \ and widget_occupied_cells is not False \ and not lists_overlap(widget_occupied_cells, occupied_cells): plugin_widget = plugin_widget_registry.get(plugin_widget_uid) kwargs = { 'placeholder_uid': placeholder.uid, 'plugin_uid': uid } if workspace: kwargs.update({'workspace': workspace}) if position: kwargs.update({'position': position}) plugin_group = safe_text(plugin.group) if not plugin_group in registered_widgets: registered_widgets[plugin_group] = [] widget_name = safe_text(plugin.name) registered_widgets[plugin_group].append( ( uid, '{0} ({1}x{2})'.format(widget_name, \ plugin_widget.cols, \ plugin_widget.rows), reverse('dash.add_dashboard_entry', kwargs=kwargs) ) ) else: allowed_plugin_uids = get_allowed_plugin_uids(user) for uid, plugin in plugin_registry._registry.items(): # We should make sure that there are widgets available for the # placeholder and user has access to the widget desired. plugin_widget_uid = PluginWidgetRegistry.namify( layout.uid, placeholder.uid, uid) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells(layout, placeholder, uid, position, check_boundaries=True) if uid in allowed_plugin_uids \ and plugin_widget_uid in plugin_widget_uids \ and widget_occupied_cells is not False \ and not lists_overlap(widget_occupied_cells, occupied_cells): plugin_widget = plugin_widget_registry.get(plugin_widget_uid) kwargs = { 'placeholder_uid': placeholder.uid, 'plugin_uid': uid } if workspace: kwargs.update({'workspace': workspace}) if position: kwargs.update({'position': position}) plugin_group = safe_text(plugin.group) if not plugin_group in registered_widgets: registered_widgets[plugin_group] = [] registered_widgets[plugin_group].append( ( uid, '{0} ({1}x{2})'.format(safe_text(plugin.name), \ plugin_widget.cols, \ plugin_widget.rows), reverse('dash.add_dashboard_entry', kwargs=kwargs) ) ) if sort_items: for key, prop in registered_widgets.items(): prop.sort() return registered_widgets
def paste_entry_from_clipboard(request, layout, placeholder_uid, position, \ workspace=None, entries=[], check_only=False, \ clear_clipboard=True): """ Pastes entry from clipboard to the given placeholder of a workspace selected. :param django.http.HttpRequest request: :param str layout_uid: Placeholder UID. :param str placeholder_uid: Placeholder UID. :param int position: Position. :param mixed workspace: Either str or ``dash.models.DashboardWorkspace`` instance. If str is given, a database hit occurs in order to obtain the ``dash.models.DashboardWorkspace`` instance. Thus, if you have the workspace instance already, provide it as is, in order to minify database hits. :param iterable entries: If given, entries are not fetched but the existing iterable is used. Each item in the iterable should be an instance of ``dash.models.DashboardEntry``. :param bool check_only: If set to True, it's only checked if it's possible to paste from clipboard (the ``dashboard_entry.save()`` part is skipped, which means that the entry is not saved in the database). :return tuple (str, bool): (Plugin name, boolean True) tuple on success and (error message, boolean False) on failure. """ clipboard_plugin_data = get_plugin_data_from_clipboard(request, layout.uid) if not clipboard_plugin_data: return (_("Clipboard is empty!"), False) if not validate_placeholder_uid(layout, placeholder_uid): return (_("Invalid placeholder `{0}`.").format(placeholder_uid), False) user_plugin_uids = get_user_plugin_uids(request.user) if isinstance(workspace, DashboardWorkspace): workspace_obj = workspace else: if workspace: try: workspace_obj = DashboardWorkspace._default_manager \ .get(slug=workspace) except ObjectDoesNotExist as e: workspace_obj = None else: workspace_obj = None dashboard_entry = DashboardEntry( user=request.user, workspace=workspace_obj, layout_uid=layout.uid, placeholder_uid=placeholder_uid, plugin_uid=clipboard_plugin_data['plugin_uid'], plugin_data=clipboard_plugin_data['plugin_data'], position=position) # We should now check if we have a space for pasting the plugin. For that # we should get the plugin and see if there's a space available for # the (workspace, placeholder, user) triple given. # Get the plugin. plugin = dashboard_entry.get_plugin() if not plugin.uid in user_plugin_uids: return (_("You're not allowed to " "use the {0} plugin.".format(safe_text(plugin.name))), False) # Getting occupied cells placeholder = layout.get_placeholder(placeholder_uid) occupied_cells = build_cells_matrix(request.user, layout, placeholder, workspace=workspace) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells(layout, placeholder, plugin.uid, position, check_boundaries=True) if widget_occupied_cells is not False \ and not lists_overlap(widget_occupied_cells, occupied_cells): try: if not check_only: # Save data dashboard_entry.save() # Clear the clipboard clear_clipboard_data(request, layout.uid) return (plugin.uid, True) except Exception as e: return (str(e), False)
def add_dashboard_entry( request, placeholder_uid, plugin_uid, workspace=None, position=None, template_name='dash/add_dashboard_entry.html', template_name_ajax='dash/add_dashboard_entry_ajax.html'): """ Add dashboard entry. :param django.http.HttpRequest request: :param string placeholder_uid: Placeholder UID. :param string plugin_uid: Plugin UID. :param string workspace: Workspace slug. :param int position: If given, provided as position for the plugin (conflict resolution should take place). :param string template_name: :param string template_name_ajax: Template used for AJAX requests. :return django.http.HttpResponse: """ # Getting dashboard settings for the user. Then get users' layout. dashboard_settings = get_or_create_dashboard_settings(request.user) if workspace: workspace_slug = slugify_workspace(workspace) filters = { 'slug': workspace_slug, 'user': request.user, } if not dashboard_settings.allow_different_layouts: filters.update({ 'layout_uid': dashboard_settings.layout_uid, }) try: workspace = DashboardWorkspace._default_manager.get(**filters) except ObjectDoesNotExist as e: if dashboard_settings.allow_different_layouts: message = _('The workspace with slug "{0}" was not foundi.' ).format(workspace_slug) else: message = __( 'The workspace with slug "{0}" does not belong to ' 'layout "{1}".').format(workspace_slug, layout.name) messages.info(request, message) return redirect('dash.edit_dashboard') if dashboard_settings.allow_different_layouts and workspace: layout_uid = workspace.layout_uid else: layout_uid = dashboard_settings.layout_uid layout = get_layout(layout_uid=layout_uid, as_instance=True) if not validate_placeholder_uid(layout, placeholder_uid): raise Http404(ugettext("Invalid placeholder: {0}").format(placeholder)) if not validate_plugin_uid(plugin_uid): raise Http404(ugettext("Invalid plugin name: {0}").format(plugin_uid)) placeholder = layout.get_placeholder(placeholder_uid) # Cell that would be occupied by the plugin upon addition. widget_occupied_cells = get_occupied_cells(layout, placeholder, plugin_uid, position, check_boundaries=True, fail_silently=True) # Cells currently occupued in the workspace given. occupied_cells = build_cells_matrix(request.user, layout, placeholder, workspace) # Checking if it's still possible to insert a widget. if widget_occupied_cells is False \ or lists_overlap(widget_occupied_cells, occupied_cells): raise Http404(ugettext("Collisions detected")) plugin = plugin_registry.get(plugin_uid)(layout.uid, placeholder_uid) plugin.request = request if plugin.add_form_template: template_name = plugin.add_form_template # Template context context = {'layout': layout, 'dashboard_settings': dashboard_settings} obj = DashboardEntry() obj.layout_uid = layout.uid obj.placeholder_uid = placeholder_uid obj.plugin_uid = plugin_uid obj.user = request.user obj.workspace = workspace # If plugin has form, it is configurable which means we have to load the # plugin form and validate user input. plugin_form = plugin.get_form() if plugin_form: # If POST request and form data is valid, save the data and redirect # to the dashboard edit. if 'POST' == request.method: form = plugin.get_initialised_create_form_or_404( data=request.POST, files=request.FILES) if form.is_valid(): # Saving the plugin form data. form.save_plugin_data(request=request) # Getting the plugin data. obj.plugin_data = form.get_plugin_data(request=request) # If position given, use it. try: position = int(position) except Exception as e: position = None if position: obj.position = position # Save the object. obj.save() messages.info( request, _('The dashboard widget "{0}" was added ' 'successfully.').format(plugin.name)) # Redirect to the dashboard view. if obj.workspace: return redirect('dash.edit_dashboard', workspace=obj.workspace.slug) else: return redirect('dash.edit_dashboard') # If POST but data invalid, show the form with errors. else: form = plugin.get_initialised_create_form_or_404() context.update({ 'form': form, 'plugin_uid': plugin_uid, 'plugin': plugin }) # If plugin is not configurable, it's just saved as is. else: obj.save() return redirect('dash.edit_dashboard') if layout.add_dashboard_entry_ajax_template_name: template_name_ajax = layout.add_dashboard_entry_ajax_template_name context.update( {'add_dashboard_entry_ajax_template_name': template_name_ajax}) if request.is_ajax(): template_name = template_name_ajax elif layout.add_dashboard_entry_template_name: template_name = layout.add_dashboard_entry_template_name return render_to_response(template_name, context, context_instance=RequestContext(request))
def paste_entry_from_clipboard(request, layout, placeholder_uid, position, \ workspace=None, entries=[], check_only=False, \ clear_clipboard=True): """ Pastes entry from clipboard to the given placeholder of a workspace selected. :param django.http.HttpRequest request: :param str layout_uid: Placeholder UID. :param str placeholder_uid: Placeholder UID. :param int position: Position. :param mixed workspace: Either str or ``dash.models.DashboardWorkspace`` instance. If str is given, a database hit occurs in order to obtain the ``dash.models.DashboardWorkspace`` instance. Thus, if you have the workspace instance already, provide it as is, in order to minify database hits. :param iterable entries: If given, entries are not fetched but the existing iterable is used. Each item in the iterable should be an instance of ``dash.models.DashboardEntry``. :param bool check_only: If set to True, it's only checked if it's possible to paste from clipboard (the ``dashboard_entry.save()`` part is skipped, which means that the entry is not saved in the database). :return tuple (str, bool): (Plugin name, boolean True) tuple on success and (error message, boolean False) on failure. """ clipboard_plugin_data = get_plugin_data_from_clipboard(request, layout.uid) if not clipboard_plugin_data: return (_("Clipboard is empty!"), False) if not validate_placeholder_uid(layout, placeholder_uid): return (_("Invalid placeholder `{0}`.").format(placeholder_uid), False) user_plugin_uids = get_user_plugin_uids(request.user) if isinstance(workspace, DashboardWorkspace): workspace_obj = workspace else: if workspace: try: workspace_obj = DashboardWorkspace._default_manager \ .get(slug=workspace) except ObjectDoesNotExist as e: workspace_obj = None else: workspace_obj = None dashboard_entry = DashboardEntry( user = request.user, workspace = workspace_obj, layout_uid = layout.uid, placeholder_uid = placeholder_uid, plugin_uid = clipboard_plugin_data['plugin_uid'], plugin_data = clipboard_plugin_data['plugin_data'], position = position ) # We should now check if we have a space for pasting the plugin. For that # we should get the plugin and see if there's a space available for # the (workspace, placeholder, user) triple given. # Get the plugin. plugin = dashboard_entry.get_plugin() if not plugin.uid in user_plugin_uids: return (_("You're not allowed to " "use the {0} plugin.".format(safe_text(plugin.name))), False) # Getting occupied cells placeholder = layout.get_placeholder(placeholder_uid) occupied_cells = build_cells_matrix( request.user, layout, placeholder, workspace = workspace ) # Get cells occupied by plugin widget. widget_occupied_cells = get_occupied_cells( layout, placeholder, plugin.uid, position, check_boundaries=True ) if widget_occupied_cells is not False \ and not lists_overlap(widget_occupied_cells, occupied_cells): try: if not check_only: # Save data dashboard_entry.save() # Clear the clipboard clear_clipboard_data(request, layout.uid) return (plugin.uid, True) except Exception as e: return (str(e), False)