171 lines
6.1 KiB
Python
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)
|