Communication screen - without club tool

This commit is contained in:
gnikwo 2017-10-17 15:13:29 +02:00
parent 23d86464c8
commit 8d1c648032
No known key found for this signature in database
GPG Key ID: 7498D7DF2F867695
16 changed files with 1091 additions and 9 deletions

View File

@ -39,4 +39,6 @@ class WeekmailAdmin(SearchModelAdmin):
admin.site.register(Sith)
admin.site.register(News, NewsAdmin)
admin.site.register(Weekmail, WeekmailAdmin)
admin.site.register(Screen)
admin.site.register(Poster)

View File

@ -32,10 +32,14 @@ from django.conf import settings
from django.contrib.staticfiles.templatetags.staticfiles import static
from django.core.mail import EmailMultiAlternatives
from core.models import User, Preferences, RealGroup, Notification
from django.utils import timezone
from core.models import User, Preferences, RealGroup, Notification, SithFile
from club.models import Club
class Sith(models.Model):
"""A one instance class storing all the modifiable infos"""
alert_msg = models.TextField(_("alert message"), default="", blank=True)
@ -183,3 +187,41 @@ class WeekmailArticle(models.Model):
def __str__(self):
return "%s - %s (%s)" % (self.title, self.author, self.club)
class Screen(models.Model):
name = models.CharField(_("name"), max_length=128)
club = models.ForeignKey(Club, related_name="screens", verbose_name=_("club"), null=False)
def active_posters(self):
now = timezone.now()
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(Q(date_end__isnull=True)|Q(date_end__gte=now))
def is_owned_by(self, user):
return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
def __str__(self):
return "%s: %s" % (self.club, self.name)
class Poster(models.Model):
name = models.CharField(_("name"), blank=False, null=False, max_length=128, default="")
file = models.ImageField(_("file"), null=False, upload_to="com/posters")
screens = models.ManyToManyField(Screen, related_name="posters")
date_begin = models.DateTimeField(blank=False, null=False, default=timezone.now)
date_end = models.DateTimeField(blank=True, null=True)
is_moderated = models.BooleanField(_("is moderated"), default=False)
moderator = models.ForeignKey(User, related_name="moderated_posters", verbose_name=_("moderator"), null=True, blank=True)
def save(self, *args, **kwargs):
if self.date_end and self.date_begin > self.date_end:
raise ValidationError
return super(Poster, self).save(*args, **kwargs)
def is_owned_by(self, user):
return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
def can_moderate(self, user):
return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
def __str__(self):
return self.name

View File

@ -0,0 +1,35 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Poster{% endtrans %}
{% endblock %}
{% block content %}
<div id="poster_edit">
<div id="title">
<div id="links" class="left">
<a id="list" class="link" href="{{ url("com:poster_list") }}">{% trans %}List{% endtrans %}</a>
</div>
<h3>{% trans %}Posters - edit{% endtrans %}</h3>
<div id="links" class="right">
<a class="link delete" href="{{ url("com:poster_delete", poster.id) }}">{% trans %}Delete{% endtrans %}</a>
</div>
</div>
<div id="poster">
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,52 @@
{% extends "core/base.jinja" %}
{% block script %}
{{ super() }}
<script src="{{ static('com/js/poster_list.js') }}"></script>
{% endblock %}
{% block title %}
{% trans %}Poster{% endtrans %}
{% endblock %}
{% block content %}
<div id="poster_list">
<div id="title">
<h3>{% trans %}Posters{% endtrans %}</h3>
<div id="links" class="right">
<a id="create" class="link" href="{{ url("com:poster_create") }}">{% trans %}Create{% endtrans %}</a>
<a id="moderation" class="link" href="{{ url("com:poster_moderate_list") }}">{% trans %}Moderation{% endtrans %}</a>
</div>
</div>
<div id="posters">
{% if posters.count() == 0 %}
<div id="no-posters">{% trans %}No posters{% endtrans %}</div>
{% else %}
{% for poster in posters %}
<div class="poster">
<div class="name">{{ poster.name }}</div>
<div class="image"><img src="{{ static(poster.file.url) }}"></img></div>
<div class="dates">
<div class="begin">{{ poster.date_begin | date("d/M/Y H:m") }}</div>
<div class="end">{{ poster.date_end | date("d/M/Y H:m") }}</div>
</div>
<a class="edit" href="{{ url("com:poster_edit", poster.id) }}">{% trans %}Edit{% endtrans %}</a>
</div>
{% endfor %}
{% endif %}
</div>
<div id="view"><div id="placeholder"></div></div>
</div>
{% endblock %}

View File

@ -0,0 +1,39 @@
{% extends "core/base.jinja" %}
{% block script %}
{{ super() }}
<script src="{{ static('com/js/poster_list.js') }}"></script>
{% endblock %}
{% block content %}
<div id="poster_list">
<div id="title">
<div id="links" class="left">
<a id="list" class="link" href="{{ url("com:poster_list") }}">{% trans %}List{% endtrans %}</a>
</div>
<h3>{% trans %}Posters - moderation{% endtrans %}</h3>
</div>
<div id="posters">
{% if object_list.count == 0 %}
<div id="no-posters">{% trans %}No objects{% endtrans %}</div>
{% else %}
{% for poster in object_list %}
<div class="poster">
<div class="name"> {{ poster.name }} </div>
<div class="image"> <img src="{{ static(poster.file.url) }}"></img> </div>
<a class="moderate" href="{{ url(moderation_url, object_id=poster.id) }}">Moderate</a>
</div>
{% endfor %}
{% endif %}
</div>
<div id="view"><div id="placeholder"></div></div>
</div>
{% endblock %}

View File

@ -0,0 +1,34 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Screen{% endtrans %}
{% endblock %}
{% block content %}
<div id="screen_edit">
<div id="title">
<div id="links" class="left">
<a id="list" class="link" href="{{ url("com:poster_list") }}">{% trans %}List{% endtrans %}</a>
</div>
<h3>{% trans %}Screen - edit{% endtrans %}</h3>
<div id="links" class="right">
<a class="link delete" href="{{ url("com:screen_delete", screen.id) }}">{% trans %}Delete{% endtrans %}</a>
</div>
</div>
<div id="screen">
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,40 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Screens{% endtrans %}
{% endblock %}
{% block content %}
<div id="screen_list">
<div id="title">
<h3>{% trans %}Screens{% endtrans %}</h3>
<div id="links" class="right">
<a id="create" class="link" href="{{ url("com:screen_create") }}">{% trans %}Create{% endtrans %}</a>
</div>
</div>
<div id="screens">
{% if screen_list.count() == 0 %}
<div id="no-screens">{% trans %}No screens{% endtrans %}</div>
{% else %}
{% for screen in screen_list %}
<div class="screen">
<div class="name">{{ screen.name }}</div>
<div class="club">Club: {{ screen.club }}</div>
<a class="edit" href="{{ url("com:screen_edit", screen.id) }}">{% trans %}Edit{% endtrans %}</a>
<a class="slideshow" href="{{ url("com:screen_slideshow", screen.id) }}" target="_blank">{% trans %}Slideshow{% endtrans %}</a>
</div>
{% endfor %}
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<title>{% trans %}Slideshow{% endtrans %}</title>
<link href="{{ scss('com/slideshow.scss') }}" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="slideshow">
<div id="slides">
{% for poster in posters %}
<div class="slide {% if loop.first %}center{% else %}right{% endif %}">
<img src="{{ static(poster.file.url) }}"></img>
</div>
{% endfor %}
</div>
<div id="progress_bullets">
{% for poster in posters %}
<div class="bullet {% if loop.first %}active{% endif %}"></div>
{% endfor %}
</div>
<div id="progress_bar"></div>
</div>
<script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script>
<script src="{{ static('com/js/slideshow.js') }}"></script>
</body>
</html>

View File

@ -47,5 +47,16 @@ urlpatterns = [
url(r'^mailings$', MailingListAdminView.as_view(), name='mailing_admin'),
url(r'^mailings/(?P<mailing_id>[0-9]+)/moderate$', MailingModerateView.as_view(), name='mailing_moderate'),
url(r'^mailings/(?P<mailing_id>[0-9]+)/delete$', MailingDeleteView.as_view(redirect_page='com:mailing_admin'), name='mailing_delete'),
url(r'^poster$', PosterListView.as_view(), name='poster_list'),
url(r'^poster/create$', PosterCreateView.as_view(), name='poster_create'),
url(r'^poster/(?P<poster_id>[0-9]+)/edit$', PosterEditView.as_view(), name='poster_edit'),
url(r'^poster/(?P<poster_id>[0-9]+)/delete$', PosterDeleteView.as_view(), name='poster_delete'),
url(r'^poster/moderate$', PosterModerateListView.as_view(), name='poster_moderate_list'),
url(r'^poster/(?P<object_id>[0-9]+)/moderate$', PosterModerateView.as_view(), name='poster_moderate'),
url(r'^screen$', ScreenListView.as_view(), name='screen_list'),
url(r'^screen/create$', ScreenCreateView.as_view(), name='screen_create'),
url(r'^screen/(?P<screen_id>[0-9]+)/slideshow$', ScreenSlideshowView.as_view(), name='screen_slideshow'),
url(r'^screen/(?P<screen_id>[0-9]+)/edit$', ScreenEditView.as_view(), name='screen_edit'),
url(r'^screen/(?P<screen_id>[0-9]+)/delete$', ScreenDeleteView.as_view(), name='screen_delete'),
]

View File

@ -40,7 +40,7 @@ from django import forms
from datetime import timedelta
from com.models import Sith, News, NewsDate, Weekmail, WeekmailArticle
from com.models import Sith, News, NewsDate, Weekmail, WeekmailArticle, Screen, Poster
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin, QuickNotifMixin
from core.views.forms import SelectDateTime
from core.models import Notification, RealGroup, User
@ -88,9 +88,27 @@ class ComTabsMixin(TabedViewMixin):
'slug': 'mailings',
'name': _("Mailing lists administration"),
})
tab_list.append({
'url': reverse('com:poster_list'),
'slug': 'posters',
'name': _("Posters list"),
})
tab_list.append({
'url': reverse('com:screen_list'),
'slug': 'screens',
'name': _("Screens list"),
})
return tab_list
class IsComAdminMixin(View):
def dispatch(self, request, *args, **kwargs):
if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or request.user.is_root):
raise PermissionDenied
return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs)
class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
model = Sith
template_name = 'core/edit.jinja'
@ -117,6 +135,14 @@ class IndexEditView(ComEditView):
success_url = reverse_lazy('com:index_edit')
class ModerateListView(ListView):
"""Generic view for moderation pages"""
class ModerateView(View):
"""Generic view for moderation pages"""
class WeekmailDestinationEditView(ComEditView):
fields = ['weekmail_destinations']
current_tab = "weekmail_destinations"
@ -465,3 +491,114 @@ class MailingModerateView(View):
return redirect('com:mailing_admin')
raise PermissionDenied
class PosterListView(IsComAdminMixin, ComTabsMixin, ListView):
"""List communication posters"""
current_tab = "posters"
model = Poster
template_name = 'com/poster_list.jinja'
def get_context_data(self, **kwargs):
kwargs = super(PosterListView, self).get_context_data(**kwargs)
kwargs['posters'] = Poster.objects.all().order_by('-date_begin')
return kwargs
class PosterCreateView(IsComAdminMixin, ComTabsMixin, CreateView):
"""Create communication poster"""
current_tab = "posters"
model = Poster
fields = ['name', 'file', 'screens', 'date_begin', 'date_end']
template_name = 'core/create.jinja'
success_url = reverse_lazy('com:poster_list')
class PosterEditView(IsComAdminMixin, ComTabsMixin, UpdateView):
"""Edit communication poster"""
pk_url_kwarg = "poster_id"
current_tab = "posters"
model = Poster
fields = ['name', 'file', 'screens', 'date_begin', 'date_end']
template_name = 'com/poster_edit.jinja'
success_url = reverse_lazy('com:poster_list')
class PosterDeleteView(IsComAdminMixin, ComTabsMixin, DeleteView):
"""Delete communication poster"""
pk_url_kwarg = "poster_id"
current_tab = "posters"
model = Poster
template_name = 'core/delete_confirm.jinja'
success_url = reverse_lazy('com:poster_list')
class PosterModerateListView(IsComAdminMixin, ComTabsMixin, ListView):
"""Moderate list communication poster"""
current_tab = "posters"
model = Poster
template_name = 'com/poster_moderate.jinja'
def get_context_data(self, **kwargs):
kwargs = super(PosterModerateListView, self).get_context_data(**kwargs)
kwargs['moderation_url'] = 'com:poster_moderate'
kwargs['object_list'] = Poster.objects.filter(is_moderated=False).all()
return kwargs
class PosterModerateView(IsComAdminMixin, ComTabsMixin, ModerateView):
"""Moderate communication poster"""
def get(self, request, *args, **kwargs):
obj = get_object_or_404(Poster, pk=kwargs['object_id'])
if obj.can_moderate(request.user):
obj.is_moderated = True
obj.moderator = request.user
obj.save()
return redirect('com:poster_moderate_list')
raise PermissionDenied
class ScreenListView(IsComAdminMixin, ComTabsMixin, ListView):
"""List communication screens"""
current_tab = "screens"
model = Screen
template_name = 'com/screen_list.jinja'
class ScreenSlideshowView(DetailView):
"""Slideshow of actives posters"""
pk_url_kwarg = "screen_id"
model = Screen
template_name = 'com/screen_slideshow.jinja'
def get_context_data(self, **kwargs):
kwargs = super(ScreenSlideshowView, self).get_context_data(**kwargs)
kwargs['posters'] = self.object.active_posters()
return kwargs
class ScreenCreateView(IsComAdminMixin, ComTabsMixin, CreateView):
"""Create communication screen"""
current_tab = "screens"
model = Screen
fields = ['name', 'club']
template_name = 'core/create.jinja'
success_url = reverse_lazy('com:screen_list')
class ScreenEditView(IsComAdminMixin, ComTabsMixin, UpdateView):
"""Edit communication screen"""
pk_url_kwarg = "screen_id"
current_tab = "screens"
model = Screen
fields = ['name', 'club']
template_name = 'com/screen_edit.jinja'
success_url = reverse_lazy('com:screen_list')
class ScreenDeleteView(IsComAdminMixin, ComTabsMixin, DeleteView):
"""Delete communication screen"""
pk_url_kwarg = "screen_id"
current_tab = "screens"
model = Screen
template_name = 'core/delete_confirm.jinja'
success_url = reverse_lazy('com:screen_list')

View File

@ -2,6 +2,7 @@
#
# Copyright 2016,2017
# - Skia <skia@libskia.so>
# - Nabos <gnikwo@hotmail.com>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
@ -28,9 +29,12 @@ from core.models import User, Page, RealGroup, SithFile
from django.contrib.auth.models import Group as AuthGroup
from haystack.admin import SearchModelAdmin
@admin.register(SithFile)
class SithFileAdmin(admin.ModelAdmin):
form = make_ajax_form(SithFile, {
'parent': 'files', # ManyToManyField
})
admin.site.unregister(AuthGroup)
admin.site.register(RealGroup)
class UserAdmin(SearchModelAdmin):
list_display = ["first_name", "last_name", "username", "email", "nick_name"]
@ -45,6 +49,11 @@ class UserAdmin(SearchModelAdmin):
admin.site.register(User, UserAdmin)
search_fields = ['username', 'first_name', 'last_name']
list_display = ('username', 'first_name', 'last_name')
list_filter = ['department', 'promo', 'groups']
list_per_page = 20
@admin.register(Page)
class PageAdmin(admin.ModelAdmin):
form = make_ajax_form(Page, {
@ -54,8 +63,6 @@ class PageAdmin(admin.ModelAdmin):
'view_groups': 'groups',
})
@admin.register(SithFile)
class SithFileAdmin(admin.ModelAdmin):
form = make_ajax_form(SithFile, {
'parent': 'files', # ManyToManyField
})
admin.site.register(User, UserAdmin)
admin.site.unregister(AuthGroup)
admin.site.register(RealGroup)

View File

@ -0,0 +1,22 @@
$(document).ready(function(){
$("#poster_list #view").click(function(e){
$("#view").removeClass("active");
});
$("#poster_list .poster").click(function(e){
el = $(e.target);
$("#poster_list #view #placeholder").html(el);
$("#view").addClass("active");
});
$(document).keyup(function(e) {
if (e.keyCode == 27) { // escape key maps to keycode `27`
e.preventDefault();
$("#view").removeClass("active");
}
});
});

View File

@ -0,0 +1,24 @@
$(document).ready(function(){
$("#poster_list #view").click(function(e){
$("#view").removeClass("active");
});
$("#poster_list .poster .image").click(function(e){
el = $(e.target);
if(el.hasClass("image"))
el = el.find("img")
$("#poster_list #view #placeholder").html(el.clone());
$("#view").addClass("active");
});
$(document).keyup(function(e) {
if (e.keyCode == 27) { // escape key maps to keycode `27`
e.preventDefault();
$("#view").removeClass("active");
}
});
});

View File

@ -0,0 +1,115 @@
$(document).ready(function(){
wait_time = 40 * 1000;
transition_time = 1000;
i = 0;
max = $("#slideshow .slide").length;
next_trigger = 0
function enterFullscreen() {
element = document.getElementById("slideshow");
$(element).addClass("fullscreen");
if(element.requestFullscreen) {
element.requestFullscreen();
} else if(element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if(element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if(element.msRequestFullscreen) {
element.msRequestFullscreen();
}
}
function exitFullscreen() {
element = document.getElementById("slideshow");
$(element).removeClass("fullscreen");
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
function init_progress_bar()
{
$("#slideshow #progress_bar").removeClass("progress");
$("#slideshow #progress_bar").addClass("init");
}
function start_progress_bar()
{
$("#slideshow #progress_bar").removeClass("init");
$("#slideshow #progress_bar").addClass("progress");
}
function next()
{
init_progress_bar();
slide = $($("#slideshow .slide").get(i % max));
slide.removeClass("center");
slide.addClass("left");
next_slide = $($("#slideshow .slide").get((i + 1) % max));
next_slide.removeClass("right");
next_slide.addClass("center");
$("#slideshow .bullet").removeClass("active");
bullet = $("#slideshow .bullet")[(i + 1) % max];
$(bullet).addClass("active");
i = (i + 1) % max;
setTimeout(function(){
others_left = $("#slideshow .slide.left");
others_left.removeClass("left");
others_left.addClass("right");
start_progress_bar();
next_trigger = setTimeout(next, wait_time);
}, transition_time);
}
init_progress_bar();
setTimeout(function(){
if(max > 1){
start_progress_bar();
setTimeout(next, wait_time);
}
}, 10);
$("#slideshow").click(function(e){
if(!$("#slideshow").hasClass("fullscreen"))
{
console.log("Entering fullscreen ...");
enterFullscreen();
}else{
console.log("Exiting fullscreen ...");
exitFullscreen();
}
});
$(document).keyup(function(e) {
if (e.keyCode == 27) { // escape key maps to keycode `27`
e.preventDefault();
console.log("Exiting fullscreen ...");
exitFullscreen();
}
});
});

View File

@ -0,0 +1,209 @@
body{
position: absolute;
width: 100vw;
height: 100vh;
padding: 0;
margin: 0;
}
#slideshow
{
position: relative;
background-color: lightgrey;
height: 100%;
*
{
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
&:hover{
&::before
{
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
content: "Click to expand";
color: white;
background-color: rgba(black, 0.5);
}
}
&.fullscreen
{
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: none;
&:before
{
display:none;
}
#slides
{
height: 100vh;
}
}
#slides
{
position: relative;
height: 100%;
overflow: hidden;
.slide
{
position: absolute;
width: 100%;
height: 100%;
display: inline-flex;
justify-content: center;
top: 0px;
background-color: grey;
transition: left 1s ease-out;
img
{
max-width: 100%;
max-height: 100%;
}
}
.slide.left
{
left: -100%;
}
.slide.center
{
left: 0px;
}
.slide.right
{
left: 100%;
transition: none;
}
}
#progress_bullets
{
position: absolute;
bottom: 10px;
width: 100%;
height: 10px;
display: flex;
justify-content: center;
margin-bottom: 10px;
.bullet
{
height: 10px;
width: 10px;
margin-left: 5px;
margin-right: 5px;
border-radius: 50%;
background-color: grey;
&.active
{
background-color: #c99836;
}
}
}
#progress_bar
{
position: absolute;
bottom: 0px;
height: 10px;
background-color: #304c83;
&.init
{
width: 0px;
transition: none;
}
&.progress
{
width: 100%;
transition: width 40s linear;
}
}
}

View File

@ -642,6 +642,289 @@ header {
display: block;
}
/*---------------------------POSTERS----------------------------*/
#poster_list, #screen_list, #poster_edit, #screen_edit{
position: relative;
#title{
position: relative;
padding: 10px;
margin: 10px;
border-bottom: 2px solid black;
h3{
display: flex;
justify-content: center;
align-items: center;
}
#links{
position: absolute;
display: flex;
bottom: 5px;
&.left{
left: 0;
}
&.right{
right: 0;
}
.link{
padding: 5px;
padding-left: 20px;
padding-right: 20px;
margin-left: 5px;
border-radius: 20px;
background-color: #ffaa00;
color: black;
&:hover{
color: black;
background-color: #c99836;
}
&.delete{
background-color: #cb0000;
}
}
}
}
#posters, #screens{
position: relative;
display: flex;
flex-wrap: wrap;
#no-posters, #no-screens{
display: flex;
justify-content: center;
align-items: center;
}
.poster, .screen{
min-width: 10%;
max-width: 20%;
display: flex;
flex-direction: column;
margin: 10px;
border: 2px solid darkgrey;
border-radius: 4px;
padding: 10px;
background-color: lightgrey;
*{
display: flex;
justify-content: center;
align-items: center;
}
.name{
padding-bottom: 5px;
margin-bottom: 5px;
border-bottom: 1px solid whitesmoke;
}
.image{
flex-grow: 1;
position: relative;
padding-bottom: 5px;
margin-bottom: 5px;
border-bottom: 1px solid whitesmoke;
img{
max-height: 20vw;
max-width: 100%;
}
&:hover{
&::before{
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
top: 0;
left: 0;
z-index: 10;
content: "Click to expand";
color: white;
background-color: rgba(black, 0.5);
}
}
}
.dates{
padding-bottom: 5px;
margin-bottom: 5px;
border-bottom: 1px solid whitesmoke;
*{
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
margin-left: 5px;
margin-right: 5px;
}
.begin, .end{
width: 48%;
}
.begin{
border-right: 1px solid whitesmoke;
padding-right: 2%;
}
}
.edit, .moderate, .slideshow{
padding: 5px;
border-radius: 20px;
background-color: #ffaa00;
color: black;
&:hover{
color: black;
background-color: #c99836;
}
&:nth-child(2n){
margin-top: 5px;
margin-bottom: 5px;
}
}
}
}
#view{
position: fixed;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
top: 0;
left: 0;
z-index: 10;
visibility: hidden;
background-color: rgba(10, 10, 10, 0.9);
overflow: hidden;
&.active{
visibility: visible;
}
#placeholder{
width: 80vw;
height: 80vh;
display: flex;
justify-content: center;
align-items: center;
top: 0;
left: 0;
img{
max-width: 100%;
max-height: 100%;
}
}
}
}
/*---------------------------ACCOUNTING----------------------------*/
#accounting {
.journal-table {