Commit 9ed9f047 authored by gijs's avatar gijs
Browse files

Merge branch 'master' of gitlab.constantvzw.org:osp/work.w

parents 29c6b6ff 42fa45ba
......@@ -133,7 +133,6 @@ STATICFILES_FINDERS = (
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', # this is default
'guardian.backends.ObjectPermissionBackend',
)
......
from django.contrib import admin
from guardian.admin import GuardedModelAdmin
from adminsortable2.admin import SortableAdminMixin, SortableInlineAdminMixin
from .models import Attachment, Score, FeaturedScore
......@@ -13,8 +12,10 @@ class AttachmentAdmin(admin.ModelAdmin):
pass
class ScoreAdmin(GuardedModelAdmin):
pass
class ScoreAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
# obj.user = request.user
super(ScoreAdmin, self).save_model(request, obj, form, change)
admin.site.register(FeaturedScore, FeaturedScoreAdmin)
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.15 on 2019-01-04 14:25
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('playground', '0022_auto_20181217_1010'),
]
operations = [
migrations.AddField(
model_name='score',
name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='creator', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='score',
name='is_public',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='score',
name='shared_with',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.15 on 2019-01-04 14:26
from __future__ import unicode_literals
from django.db import migrations
def populate_permissions(apps, schema_editor):
from guardian.shortcuts import get_users_with_perms
from guardian.utils import get_anonymous_user
# We can't import the models directly as it may be a newer
# version than this migration expects. We use the historical version.
Score = apps.get_model('playground', 'Score')
User = apps.get_model('auth', 'User')
creator = User.objects.get(username="jeanne")
anonymous_user = get_anonymous_user()
for score in Score.objects.all():
score.created_by = creator
users = get_users_with_perms(score)
score.is_public = users.filter(id=anonymous_user.id).exists()
users = users.exclude(id__in=[creator.id, anonymous_user.id])
for user in users:
score.shared_with.add(User.objects.get(id=user.id))
score.save()
class Migration(migrations.Migration):
dependencies = [
('playground', '0023_auto_20190104_1425'),
]
operations = [
migrations.RunPython(populate_permissions),
]
from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.postgres.fields import JSONField
from taggit.managers import TaggableManager
class Attachment(models.Model):
title = models.CharField(max_length=255)
attachment = models.FileField(blank=True, null=True)
......@@ -34,9 +37,17 @@ class Score(models.Model):
mainline = JSONField(blank=True)
language = models.TextField(blank=True)
is_public = models.BooleanField(default=False)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, related_name="creator")
shared_with = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
def __str__(self):
return self.title
# def save(self, *args, **kwargs):
# import ipdb; ipdb.set_trace()
# super(Score, self).save(*args, **kwargs) # Call the "real" save() method.
def get_absolute_url(self):
return "/partitions/{}".format(self.id)
......
......@@ -4,10 +4,12 @@ from rest_framework import serializers
from rest_framework_recursive.fields import RecursiveField
from taggit_serializer.serializers import (TagListSerializerField,
TaggitSerializer)
from guardian.shortcuts import assign_perm, get_users_with_perms, get_user_perms, remove_perm
### from guardian.shortcuts import assign_perm, get_users_with_perms, get_user_perms, remove_perm
from django.contrib.auth.models import User
from django.contrib.flatpages.models import FlatPage
from django.contrib.auth.validators import UnicodeUsernameValidator
class FlatPageSerializer(serializers.HyperlinkedModelSerializer):
......@@ -24,6 +26,13 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['username', 'id']
# Dealing with "A user with that username already exists." Thanks!
# https://medium.com/django-rest-framework/dealing-with-unique-constraints-in-nested-serializers-dade33b831d9
extra_kwargs = {
'username': {
'validators': [UnicodeUsernameValidator()],
}
}
class AttachmentSerializer(serializers.HyperlinkedModelSerializer):
......@@ -35,55 +44,40 @@ class AttachmentSerializer(serializers.HyperlinkedModelSerializer):
# read_only_fields = ('attachment',)
class PermissionListSerializer(serializers.ListSerializer):
def to_representation(self, obj):
perms = get_users_with_perms(obj, attach_perms=True)
return [{"username": k.username, "permissions": v} for k, v in perms.items()]
def to_internal_value(self, data):
print(data)
# return data
# I don't understand why I can't just return data
return {"permissions": data}
class PermissionSerializer(serializers.Serializer):
class Meta:
list_serializer_class = PermissionListSerializer
class ScoreSerializer(TaggitSerializer, serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField()
tags = TagListSerializerField(required=False)
permissions = PermissionSerializer(source="*", many=True)
is_editable = serializers.SerializerMethodField()
created_by = UserSerializer(required=False)
shared_with = UserSerializer(many=True, required=False)
class Meta:
model = Score
fields = '__all__'
def create(self, validated_data):
validated_data.pop('permissions', None)
validated_data["created_by"] = self.context['request'].user
instance = Score.objects.create(**validated_data)
assign_perm("view_score", self.context['request'].user, instance)
return instance
def get_is_editable(self, obj):
return self.context['request'].user.has_perm('change_score', obj)
current_user = self.context['request'].user
return obj.created_by == current_user or current_user in obj.shared_with.all()
def update(self, instance, validated_data):
# Dealing with "A user with that username already exists." Thanks!
# https://medium.com/django-rest-framework/dealing-with-unique-constraints-in-nested-serializers-dade33b831d9
created_by_data = validated_data.pop('created_by')
shared_with = validated_data.pop('shared_with')
self.instance.shared_with.clear()
for i in shared_with:
user = User.objects.get(username=i["username"])
if user:
print("adding {}".format(user.username))
self.instance.shared_with.add(user)
instance = super(ScoreSerializer, self).update(instance, validated_data)
for user, perms in get_users_with_perms(instance, attach_perms=True).items():
for perm in perms:
remove_perm(perm, user, instance)
for i in instance.permissions:
user = User.objects.get(username=i.get('username'))
perms = i.get('permissions')
for perm in perms:
assign_perm(perm, user, instance)
return instance
......
......@@ -76,7 +76,7 @@
@font-face {
font-family: 'GothicA1';
src: url("../fonts/GothicA1/GothicA1-Organon.ttf");
src: url("../fonts/GothicA1/GothicA1-Organon-ttfautohinted.ttf");
font-weight: lighter;
}
......@@ -506,7 +506,7 @@ section.hidden { display: none; }
.panel--score-meta .score-edit {
position: absolute;
right: 30px;
top: calc(30px + 1.25em);
top: calc(30px + 0em);
}
.read-only .score-edit {
......@@ -707,44 +707,42 @@ section.hidden { display: none; }
/* Score axis
========================================================================== */
ol { position: relative; }
.score__mainline {
position: relative;
left: calc(-1.9rem - 8px);
}
ol { --row-color: var(--color-01); --row-color-next: var(--color-02); --indent: 0px; --form-indent: 40px; }
.score__mainline { --row-color: var(--color-01); --row-color-next: var(--color-02); --indent: 0px; --form-indent: 40px; }
ol ol { --row-color: var(--color-02); --row-color-next: var(--color-03); --indent: calc(1 * var(--row-indent)); --form-indent: calc(-1 * var(--row-indent)); }
.score__mainline ol { --row-color: var(--color-02); --row-color-next: var(--color-03); --indent: calc(1 * var(--row-indent)); --form-indent: calc(-1 * var(--row-indent)); }
ol ol ol { --row-color: var(--color-03); --row-color-next: var(--color-04); --indent: calc(2 * var(--row-indent)); --form-indent: calc(-2 * var(--row-indent)); }
.score__mainline ol ol { --row-color: var(--color-03); --row-color-next: var(--color-04); --indent: calc(2 * var(--row-indent)); --form-indent: calc(-2 * var(--row-indent)); }
ol ol ol ol { --row-color: var(--color-04); --row-color-next: var(--color-05); --indent: calc(3 * var(--row-indent)); --form-indent: calc(-3 * var(--row-indent)); }
.score__mainline ol ol ol { --row-color: var(--color-04); --row-color-next: var(--color-05); --indent: calc(3 * var(--row-indent)); --form-indent: calc(-3 * var(--row-indent)); }
ol ol ol ol ol { --row-color: var(--color-05); --row-color-next: var(--color-06); --indent: calc(4 * var(--row-indent)); --form-indent: calc(-4 * var(--row-indent)); }
.score__mainline ol ol ol ol { --row-color: var(--color-05); --row-color-next: var(--color-06); --indent: calc(4 * var(--row-indent)); --form-indent: calc(-4 * var(--row-indent)); }
ol ol ol ol ol ol { --row-color: var(--color-06); --row-color-next: var(--color-07); --indent: calc(5 * var(--row-indent)); --form-indent: calc(-5 * var(--row-indent)); }
.score__mainline ol ol ol ol ol { --row-color: var(--color-06); --row-color-next: var(--color-07); --indent: calc(5 * var(--row-indent)); --form-indent: calc(-5 * var(--row-indent)); }
ol ol ol ol ol ol ol { --row-color: var(--color-07); --row-color-next: var(--color-08); --indent: calc(6 * var(--row-indent)); --form-indent: calc(-6 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol { --row-color: var(--color-07); --row-color-next: var(--color-08); --indent: calc(6 * var(--row-indent)); --form-indent: calc(-6 * var(--row-indent)); }
ol ol ol ol ol ol ol ol { --row-color: var(--color-08); --row-color-next: var(--color-09); --indent: calc(7 * var(--row-indent)); --form-indent: calc(-7 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol { --row-color: var(--color-08); --row-color-next: var(--color-09); --indent: calc(7 * var(--row-indent)); --form-indent: calc(-7 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol { --row-color: var(--color-09); --row-color-next: var(--color-10); --indent: calc(8 * var(--row-indent)); --form-indent: calc(-8 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol { --row-color: var(--color-09); --row-color-next: var(--color-10); --indent: calc(8 * var(--row-indent)); --form-indent: calc(-8 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-10); --row-color-next: var(--color-11); --indent: calc(9 * var(--row-indent)); --form-indent: calc(-9 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol ol { --row-color: var(--color-10); --row-color-next: var(--color-11); --indent: calc(9 * var(--row-indent)); --form-indent: calc(-9 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-11); --row-color-next: var(--color-12); --indent: calc(10 * var(--row-indent)); --form-indent: calc(-10 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-11); --row-color-next: var(--color-12); --indent: calc(10 * var(--row-indent)); --form-indent: calc(-10 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-12); --row-color-next: var(--color-01); --indent: calc(11 * var(--row-indent)); --form-indent: calc(-11 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-12); --row-color-next: var(--color-01); --indent: calc(11 * var(--row-indent)); --form-indent: calc(-11 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-01); --row-color-next: var(--color-02); --indent: calc(12 * var(--row-indent)); --form-indent: calc(-12 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-01); --row-color-next: var(--color-02); --indent: calc(12 * var(--row-indent)); --form-indent: calc(-12 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-02); --row-color-next: var(--color-03); --indent: calc(13 * var(--row-indent)); --form-indent: calc(-13 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-02); --row-color-next: var(--color-03); --indent: calc(13 * var(--row-indent)); --form-indent: calc(-13 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-03); --row-color-next: var(--color-04); --indent: calc(14 * var(--row-indent)); --form-indent: calc(-14 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-03); --row-color-next: var(--color-04); --indent: calc(14 * var(--row-indent)); --form-indent: calc(-14 * var(--row-indent)); }
ol ol ol ol ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-04); --row-color-next: var(--color-05); --indent: calc(15 * var(--row-indent)); --form-indent: calc(-15 * var(--row-indent)); }
.score__mainline ol ol ol ol ol ol ol ol ol ol ol ol ol ol ol { --row-color: var(--color-04); --row-color-next: var(--color-05); --indent: calc(15 * var(--row-indent)); --form-indent: calc(-15 * var(--row-indent)); }
[data-collapsed="true"] .sublines { display: none; }
......@@ -960,10 +958,20 @@ li.axis { position: relative; }
position: absolute;
top: 4.5em;
bottom: .5em;
left: var(--row-indent);
left: calc(var(--row-indent) - 20px); /* indent - (width / 2) */
width: 40px;
display: none;
}
/* .score__line:only-child > .axis-row > .sublines__metadata__wrapper { */
.score__line[data-len="1"] > .axis-row > .sublines__metadata__wrapper .tag:before {
content: ""!important;
}
[data-sublines="true"][data-collapsed="false"] > .axis-row > .sublines__metadata__wrapper {
display: block;
......@@ -991,18 +999,16 @@ li.axis { position: relative; }
z-index: 1;
font-weight: lighter;
position: relative;
left: -50%;
/* left: calc(var(--row-indent) - 50%); */
}
.tag[data-tag=""]:before,
.tag[data-tag=">"]:before { content: "\f8a6"; }
.tag[data-tag=">"]:before { content: "\f8b3"; }
.tag[data-tag="|"]:before { content: "\f8a7"; }
.tag[data-tag="||"]:before { content: "\f8a8"; }
.tag[data-tag="//"]:before { content: "\f89a"; }
.tag[data-tag=""]:before { content: "\f8a9"; }
.tag[data-tag="|"]:before { content: "\f8b4"; }
.tag[data-tag="||"]:before { content: "\f8b5"; }
.tag[data-tag=""]:before { content: "\f8b6"; }
.tag[data-tag="//"]:before { content: "\f8b7"; }
.alternative {
display: block;
......@@ -1017,8 +1023,6 @@ li.axis { position: relative; }
border-radius: .8em/50%;
z-index: 1;
position: relative;
/* left: calc(var(--row-indent) - 50%); */
left: -50%;
}
......@@ -1075,31 +1079,39 @@ li + li .alt-symbol { display: none; }
border: none !important;
}
[data-module="true"] > .axis-row > .axis-row--background-wrapper > .line__body {
/* transform: skew(-10deg); */
}
/* [data-module="true"] > .axis-row > .axis-row--background-wrapper > .line__body { */
/* transform: skew(-10deg); */
/* } */
[data-module="true"] > .axis-row > .axis-row--background-wrapper > .line__body > .line__title {
/* font-style: italic; */
font-style: italic;
/* font-weight: bolder; */
color: var(--background-color);
/* color: var(--background-color); */
/* letter-spacing: 3px; */
/* text-decoration: underline wavy; */
/* display: inline-block; */
/* transform: skew(10deg); */
}
[data-contingent="true"] > .axis-row > .axis-row--background-wrapper > .line__body > .line__title::before {
content: " ";
display: inline-block;
border: 8px solid transparent;
border-left-color: var(--background-color);
position: relative;
margin-right: -10px;
left: -7px;
top: 2px;
/* [data-contingent="true"] > .axis-row > .axis-row--background-wrapper > .line__body > .line__title::before { */
/* content: " "; */
/* display: inline-block; */
/* border: 8px solid transparent; */
/* border-left-color: var(--background-color); */
/* position: relative; */
/* margin-right: -10px; */
/* left: -7px; */
/* top: 2px; */
/* } */
[data-contingent="true"] > .axis-row > .axis-row--background-wrapper > .line__actant,
[data-contingent="true"] > .axis-row > .axis-row--background-wrapper > .line__adresse,
[data-contingent="true"] > .axis-row > .axis-row--background-wrapper > .line__body {
background: repeating-linear-gradient(-45deg, var(--background-color) 0px, var(--background-color) 1px, transparent 1px, transparent 5px), var(--row-color);
}
.axis-inline-title-form {
display: inline-block;
margin-top: -5px; /* Negative top padding line__body */
......@@ -1841,3 +1853,12 @@ ol[data-alternative]:before {
margin-top: var(--line-height);
margin-bottom: var(--line-height);
}
.autocomplete-suggestions { background: #FFF; overflow: auto; }
.autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden; color: var(--background-color); cursor: default; }
.autocomplete-selected { background: #F0F0F0; }
.autocomplete-suggestions strong { font-weight: bold; }
/* .autocomplete-group { padding: 2px 5px; } */
/* .autocomplete-group strong { display: block; border-bottom: 1px solid #000; } */
......@@ -28,6 +28,16 @@ window.W = window.W || {};
},
credits: function () {
document.title = 'Organon: Crédits';
var baseView = this.getOption('application').getView();
var view = new W.CreditsView();
baseView.showChildView('main', view);
baseView.getChildView('help').triggerMethod("hide");
},
userList: function () {
document.title = 'Organon: liste des utilisateurs';
......
......@@ -6,7 +6,6 @@ window.W = window.W || {};
(function(undefined) {
'use strict';
Marionette.TemplateCache.prototype.compileTemplate = function compileTemplate(rawTemplate, options) {
return W.extendedTemplate(rawTemplate, options);
}
......@@ -31,7 +30,6 @@ window.W = window.W || {};
W.config = W.config || {};
W.config.lang = W.utils.getUserLanguage();
var scoreApp = new W.ScoreApp();
scoreApp.start();
})();
......@@ -55,7 +55,7 @@ window.W = window.W || {};
W.ChoiceModel = Backbone.Model.extend({});
W.UserModel = Backbone.Model.extend({
W.UserModel = Backbone.RelationalModel.extend({
urlRoot: '/api/users/',
label: function () {
......@@ -74,9 +74,11 @@ window.W = window.W || {};
W.UserAuthModel = Backbone.Model.extend({
urlRoot: '/rest-auth/user/',
defaults: {
username: ""
},
idAttribute: "pk",
// defaults: {
// username: ""
// },
url: function () {
var original_url = Backbone.Model.prototype.url.call(this);
......@@ -84,6 +86,10 @@ window.W = window.W || {};
return parsed_url;
},
isLoggedIn: function () {
return this.model.id ? true : false
}
});
......@@ -123,7 +129,8 @@ window.W = window.W || {};
presentation: "",
effectif: "",
language: "",
permissions: {}
permissions: {},
shared_with: []
},
urlRoot: '/api/scores/',
......@@ -155,6 +162,17 @@ window.W = window.W || {};
includeInJSON: false,
type: Backbone.HasOne
}
},
{
type: Backbone.HasMany,
key: 'shared_with',
relatedModel: 'UserModel',
collectionType: 'UserCollection',
reverseRelation: {
key: 'score',
includeInJSON: false,
type: Backbone.HasOne
}
}
],
......@@ -294,6 +312,10 @@ window.W = window.W || {};
return _.reduce(this.get('sublines').models, function (depth, line) { return Math.max(line.getDepth(), depth); }, 0) + 1;
},
getChildCount: function () {
return this.get('sublines').length;
},
addSubLine: function () {
var sublines = this.get('sublines');
var title = "Sous axe " + (sublines.length + 1);
......
......@@ -10,6 +10,7 @@ window.W = window.W || {};
appRoutes: {
'': 'home',
'la-notation-w(/)': 'about',
'credits(/)': 'credits',
'partitions(/)': 'scoreList',
'partitions/:id(/)': 'scoreDetail',
'users(/)': 'userList',
......
......@@ -54,7 +54,7 @@ window.W.utils = window.W.utils || {};
if (string in entries) {
return entries[string];
} else {
console.log(string + " n'est pas traduit");
// console.log(string + " n'est pas traduit");
return string;
}
}
......
......@@ -931,11 +931,11 @@ window.W = window.W || {};
tagName: 'li',
className: 'axis score__line line',
// attributes: function () {
// return {
// id: "foo-" + this.model.get("title")
// }
// },
attributes: function () {
return {
'data-len': this.model.getChildCount()
}
},
template: '#node-template-vue',
......@@ -1590,6 +1590,9 @@ window.W = window.W || {};
el: '[data-name="effectif"]',
replaceElement: true