combo/combo/apps/dashboard/views.py

171 lines
6.1 KiB
Python

# combo - content management system
# Copyright (C) 2014-2017 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.urls import reverse
from django.db.models import Max, Min
from django.http import (
Http404,
HttpResponse,
HttpResponseBadRequest,
HttpResponseRedirect,
HttpResponseNotAllowed,
)
from django.utils.encoding import force_text
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View
from combo.data.models import CellBase, ConfigJsonCell
from combo.data.library import get_cell_class
from combo.public.views import render_cell
from .models import DashboardCell, Tile
from .templatetags.dashboard import get_cell_data
def dashboard_success(request, dashboard, cell_data):
dashboard_url = dashboard.page.get_online_url()
if request.is_ajax():
return HttpResponse(
json.dumps({'err': 0, 'url': request.build_absolute_uri(dashboard_url), 'cell_data': cell_data}),
content_type='application/json',
)
return HttpResponseRedirect(dashboard_url)
class DashboardAddTileView(View):
def get(self, request, *args, **kwargs):
if not request.user.is_authenticated:
raise PermissionDenied()
dashboard = DashboardCell.objects.filter(page__snapshot__isnull=True)[0]
cell = CellBase.get_cell(kwargs['cell_reference'])
if not cell.page.is_visible(request.user):
raise PermissionDenied()
if not cell.is_visible(user=request.user):
raise PermissionDenied()
cell.pk = None
cell.page = dashboard.page
cell.placeholder = '_dashboard'
cell.save()
tile = Tile(dashboard=dashboard, cell=cell, user=request.user, order=0)
if settings.COMBO_DASHBOARD_NEW_TILE_POSITION == 'first':
order = (
Tile.objects.filter(dashboard=dashboard, user=request.user)
.aggregate(Min('order'))
.get('order__min')
)
tile.order = order - 1 if order is not None else 0
elif settings.COMBO_DASHBOARD_NEW_TILE_POSITION == 'last':
order = (
Tile.objects.filter(dashboard=dashboard, user=request.user)
.aggregate(Max('order'))
.get('order_max')
)
tile.order = order + 1 if order is not None else 0
tile.save()
cell_data = get_cell_data(cell)
cell_data['remove_url'] = reverse(
'combo-dashboard-remove-tile', kwargs={'cell_reference': cell.get_reference()}
)
return dashboard_success(request, dashboard, cell_data)
dashboard_add_tile = DashboardAddTileView.as_view()
class DashboardRemoveTileView(View):
def get(self, request, *args, **kwargs):
cell = CellBase.get_cell(kwargs['cell_reference'])
try:
tile = Tile.get_by_cell(cell)
except Tile.DoesNotExist:
raise Http404()
if tile.user != request.user:
raise PermissionDenied()
dashboard = tile.dashboard
cell_data = get_cell_data(cell)
tile.delete()
# do not remove cell so it can directly be added back
cell_data['add_url'] = reverse(
'combo-dashboard-add-tile', kwargs={'cell_reference': cell.get_reference()}
)
return dashboard_success(request, dashboard, cell_data)
dashboard_remove_tile = DashboardRemoveTileView.as_view()
@csrf_exempt
def dashboard_auto_tile(request, *args, **kwargs):
if request.method != 'POST':
return HttpResponseNotAllowed(['post'])
try:
request_body = json.loads(force_text(request.body))
except json.JSONDecodeError:
return HttpResponseBadRequest('bad json request: "%s"' % request.body)
dashboard = DashboardCell.objects.filter(page__snapshot__isnull=True)[0]
cell = ConfigJsonCell(key=kwargs.get('key'), order=1, page_id=dashboard.page_id, placeholder='_auto_tile')
if cell.key not in settings.JSON_CELL_TYPES:
return HttpResponseBadRequest('bad request, invalid cell type: "%s"' % cell.key)
# only keep parameters that are actually defined for this cell type.
cell.parameters = {}
for field in settings.JSON_CELL_TYPES[cell.key].get('form') or []:
key = field['varname']
cell.parameters[key] = request_body.get(key)
if cell.parameters[key] is None and field.get('required', True):
return HttpResponseBadRequest('missing key: %s' % key)
# save cell so it can be reused later, for example to be added to
# dashboard, or to be used as reference in another page, etc.
cell.save()
response = render_cell(request, cell=cell)
response['x-add-to-dashboard-url'] = reverse(
'combo-dashboard-add-tile', kwargs={'cell_reference': cell.get_reference()}
)
return response
def dashboard_reorder_tiles(request, *args, **kwargs):
dashboard = DashboardCell.objects.filter(page__snapshot__isnull=True)[0]
new_order = request.GET['order'].split(',')
tiles = dict((str(x.id), x) for x in Tile.objects.filter(id__in=new_order))
for i, tile_id in enumerate(new_order):
tile = tiles.get(tile_id)
if tile.user != request.user:
raise PermissionDenied()
if tile:
tile.order = i
for tile in tiles.values():
tile.save()
return HttpResponse(status=204)