Added support for CamelCase to RESTModelMixin. See #2480.

This commit is contained in:
Norman Jäckel 2017-01-18 16:29:13 +01:00
parent 0da7765dc0
commit 89192236fc
9 changed files with 73 additions and 25 deletions

View File

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-02-15 15:24
from __future__ import unicode_literals
from django.db import migrations
def rename_projector_message_slides(apps, schema_editor):
"""
Renames projector message slides in projector model.
Old name 'core/projectormessage', new name 'core/projector-message'.
"""
# We get the model from the versioned app registry;
# if we directly import it, it will be the wrong version.
Projector = apps.get_model('core', 'Projector')
for projector in Projector.objects.all():
new_config = {}
for key, value in projector.config.items():
new_config[key] = value
if value['name'] == 'core/projectormessage':
new_config[key]['name'] = 'core/projector-message'
projector.config = new_config
projector.save(skip_autoupdate=True)
class Migration(migrations.Migration):
dependencies = [
('core', '0003_auto_20161217_1158'),
]
operations = [
migrations.RunPython(
rename_projector_message_slides
),
]

View File

@ -34,7 +34,7 @@ class ProjectorMessageElement(ProjectorElement):
""" """
Short message on the projector. Rendered as overlay. Short message on the projector. Rendered as overlay.
""" """
name = 'core/projectormessage' name = 'core/projector-message'
def check_data(self): def check_data(self):
if not ProjectorMessage.objects.filter(pk=self.config_entry.get('id')).exists(): if not ProjectorMessage.objects.filter(pk=self.config_entry.get('id')).exists():

View File

@ -505,7 +505,7 @@ angular.module('OpenSlidesApp.core', [
'DS', 'DS',
function(DS) { function(DS) {
return DS.defineResource({ return DS.defineResource({
name: 'core/chatmessage', name: 'core/chat-message',
relations: { relations: {
belongsTo: { belongsTo: {
'users/user': { 'users/user': {
@ -689,7 +689,7 @@ angular.module('OpenSlidesApp.core', [
onConflict: 'replace', onConflict: 'replace',
relations: { relations: {
hasMany: { hasMany: {
'core/projectiondefault': { 'core/projection-default': {
localField: 'projectiondefaults', localField: 'projectiondefaults',
foreignKey: 'projector_id', foreignKey: 'projector_id',
} }
@ -713,7 +713,7 @@ angular.module('OpenSlidesApp.core', [
value.name != 'agenda/item-list' && value.name != 'agenda/item-list' &&
value.name != 'core/clock' && value.name != 'core/clock' &&
value.name != 'core/countdown' && value.name != 'core/countdown' &&
value.name != 'core/message' && value.name != 'core/projector-message' &&
value.name != 'agenda/current-list-of-speakers' ) { value.name != 'agenda/current-list-of-speakers' ) {
return_dict = { return_dict = {
'state': value.name.replace('/', '.')+'.detail.update', 'state': value.name.replace('/', '.')+'.detail.update',
@ -741,7 +741,7 @@ angular.module('OpenSlidesApp.core', [
'DS', 'DS',
function(DS) { function(DS) {
return DS.defineResource({ return DS.defineResource({
name: 'core/projectiondefault', name: 'core/projection-default',
relations: { relations: {
belongsTo: { belongsTo: {
'core/projector': { 'core/projector': {
@ -762,7 +762,7 @@ angular.module('OpenSlidesApp.core', [
'$http', '$http',
'Projector', 'Projector',
function(DS, jsDataModel, gettext, $http, Projector) { function(DS, jsDataModel, gettext, $http, Projector) {
var name = 'core/projectormessage'; var name = 'core/projector-message';
return DS.defineResource({ return DS.defineResource({
name: name, name: name,
useClass: jsDataModel, useClass: jsDataModel,
@ -778,7 +778,7 @@ angular.module('OpenSlidesApp.core', [
var isProjectedIds = this.isProjected(); var isProjectedIds = this.isProjected();
var self = this; var self = this;
var predicate = function (element) { var predicate = function (element) {
return element.name == name && element.id == self.id; return element.name === name && element.id === self.id;
}; };
_.forEach(isProjectedIds, function (id) { _.forEach(isProjectedIds, function (id) {
var uuid = _.findKey(Projector.get(id).elements, predicate); var uuid = _.findKey(Projector.get(id).elements, predicate);

View File

@ -57,7 +57,7 @@ angular.module('OpenSlidesApp.core.projector', ['OpenSlidesApp.core'])
template: 'static/templates/core/slide_countdown.html', template: 'static/templates/core/slide_countdown.html',
}); });
slidesProvider.registerSlide('core/projectormessage', { slidesProvider.registerSlide('core/projector-message', {
template: 'static/templates/core/slide_message.html', template: 'static/templates/core/slide_message.html',
}); });
} }

View File

@ -1344,7 +1344,7 @@ angular.module('OpenSlidesApp.core.site', [
ProjectorMessage.create(message).then(function(message){ ProjectorMessage.create(message).then(function(message){
$scope.projectors.forEach(function (projector) { $scope.projectors.forEach(function (projector) {
$http.post('/rest/core/projector/' + projector.id + '/activate_elements/', [{ $http.post('/rest/core/projector/' + projector.id + '/activate_elements/', [{
name: 'core/projectormessage', name: 'core/projector-message',
stable: true, stable: true,
id: message.id, id: message.id,
identify: true, identify: true,
@ -1358,7 +1358,7 @@ angular.module('OpenSlidesApp.core.site', [
$scope.removeIdentifierMessages = function () { $scope.removeIdentifierMessages = function () {
Projector.getAll().forEach(function (projector) { Projector.getAll().forEach(function (projector) {
_.forEach(projector.elements, function (element, uuid) { _.forEach(projector.elements, function (element, uuid) {
if (element.name == 'core/projectormessage' && element.id == $scope.identifierMessage.id) { if (element.name === 'core/projector-message' && element.id === $scope.identifierMessage.id) {
$http.post('/rest/core/projector/' + projector.id + '/deactivate_elements/', [uuid]); $http.post('/rest/core/projector/' + projector.id + '/deactivate_elements/', [uuid]);
} }
}); });
@ -1469,7 +1469,7 @@ angular.module('OpenSlidesApp.core.site', [
angular.element('#messageSendButton').addClass('disabled'); angular.element('#messageSendButton').addClass('disabled');
angular.element('#messageInput').attr('disabled', ''); angular.element('#messageInput').attr('disabled', '');
$http.post( $http.post(
'/rest/core/chatmessage/', '/rest/core/chat-message/',
{message: $scope.newMessage} {message: $scope.newMessage}
) )
.success(function () { .success(function () {
@ -1498,7 +1498,7 @@ angular.module('OpenSlidesApp.core.site', [
}); });
$scope.clearChatHistory = function () { $scope.clearChatHistory = function () {
$http.post('/rest/core/chatmessage/clear/'); $http.post('/rest/core/chat-message/clear/');
}; };
} }
]) ])

View File

@ -756,12 +756,6 @@ class MotionChangeRecommendation(RESTModelMixin, models.Model):
"""Return a string, representing this object.""" """Return a string, representing this object."""
return "Recommendation for Version %s, line %s - %s" % (self.motion_version_id, self.line_from, self.line_to) return "Recommendation for Version %s, line %s - %s" % (self.motion_version_id, self.line_from, self.line_to)
def get_root_rest_element(self):
"""
Returns this instance, which is the root REST element.
"""
return self
class Category(RESTModelMixin, models.Model): class Category(RESTModelMixin, models.Model):
""" """
@ -840,11 +834,6 @@ class MotionBlock(RESTModelMixin, models.Model):
def get_agenda_list_view_title(self): def get_agenda_list_view_title(self):
return self.title return self.title
@classmethod
def get_collection_string(cls):
# TODO: Fix generic method to support camelCase, #2480.
return 'motions/motion-block'
class MotionLog(RESTModelMixin, models.Model): class MotionLog(RESTModelMixin, models.Model):
"""Save a logmessage for a motion.""" """Save a logmessage for a motion."""

View File

@ -722,7 +722,7 @@ angular.module('OpenSlidesApp.motions', [
'gettextCatalog', 'gettextCatalog',
function (DS, Config, jsDataModel, diffService, lineNumberingService, gettextCatalog) { function (DS, Config, jsDataModel, diffService, lineNumberingService, gettextCatalog) {
return DS.defineResource({ return DS.defineResource({
name: 'motions/motionchangerecommendation', name: 'motions/motion-change-recommendation',
useClass: jsDataModel, useClass: jsDataModel,
methods: { methods: {
saveStatus: function() { saveStatus: function() {

View File

@ -1,5 +1,7 @@
from django.db import models from django.db import models
from .utils import convert_camel_case_to_pseudo_snake_case
class MinMaxIntegerField(models.IntegerField): class MinMaxIntegerField(models.IntegerField):
""" """
@ -46,7 +48,9 @@ class RESTModelMixin:
None if this is not a so called root rest instance. None if this is not a so called root rest instance.
""" """
# TODO Check if this is a root rest element class and return None if not. # TODO Check if this is a root rest element class and return None if not.
return '/'.join((cls._meta.app_label.lower(), cls._meta.object_name.lower())) return '/'.join(
(convert_camel_case_to_pseudo_snake_case(cls._meta.app_label),
convert_camel_case_to_pseudo_snake_case(cls._meta.object_name)))
def get_rest_pk(self): def get_rest_pk(self):
""" """

View File

@ -1,6 +1,24 @@
import re
import roman import roman
CAMEL_CASE_TO_PSEUDO_SNAKE_CASE_CONVERSION_REGEX_1 = re.compile('(.)([A-Z][a-z]+)')
CAMEL_CASE_TO_PSEUDO_SNAKE_CASE_CONVERSION_REGEX_2 = re.compile('([a-z0-9])([A-Z])')
def convert_camel_case_to_pseudo_snake_case(text):
"""
Converts camel case to pseudo snake case using hyphen instead of
underscore.
E. g. ThisText is converted to this-text.
Credits: epost (http://stackoverflow.com/a/1176023)
"""
s1 = CAMEL_CASE_TO_PSEUDO_SNAKE_CASE_CONVERSION_REGEX_1.sub(r'\1-\2', text)
return CAMEL_CASE_TO_PSEUDO_SNAKE_CASE_CONVERSION_REGEX_2.sub(r'\1-\2', s1).lower()
def to_roman(number): def to_roman(number):
""" """
Converts an arabic number within range from 1 to 4999 to the Converts an arabic number within range from 1 to 4999 to the