From 34ea96f09d5c5c80748526171ad5d3c44aef0679 Mon Sep 17 00:00:00 2001 From: Bryan Date: Fri, 3 Jan 2014 11:55:36 -0500 Subject: [PATCH] Adding License tracking, upstream file tracking, and displays. --- karmaworld/apps/licenses/__init__.py | 0 karmaworld/apps/licenses/admin.py | 10 ++ .../apps/licenses/migrations/0001_initial.py | 34 +++++ .../apps/licenses/migrations/__init__.py | 0 karmaworld/apps/licenses/models.py | 21 ++++ ...d_field_note_license__chg_field_note_ip.py | 119 ++++++++++++++++++ ...0011_auto__add_field_note_upstream_link.py | 110 ++++++++++++++++ karmaworld/apps/notes/models.py | 8 +- karmaworld/assets/css/note_course_pages.css | 2 +- karmaworld/settings/common.py | 1 + karmaworld/templates/notes/note_detail.html | 8 ++ 11 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 karmaworld/apps/licenses/__init__.py create mode 100644 karmaworld/apps/licenses/admin.py create mode 100644 karmaworld/apps/licenses/migrations/0001_initial.py create mode 100644 karmaworld/apps/licenses/migrations/__init__.py create mode 100644 karmaworld/apps/licenses/models.py create mode 100644 karmaworld/apps/notes/migrations/0010_auto__add_field_note_license__chg_field_note_ip.py create mode 100644 karmaworld/apps/notes/migrations/0011_auto__add_field_note_upstream_link.py diff --git a/karmaworld/apps/licenses/__init__.py b/karmaworld/apps/licenses/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/karmaworld/apps/licenses/admin.py b/karmaworld/apps/licenses/admin.py new file mode 100644 index 0000000..cb86508 --- /dev/null +++ b/karmaworld/apps/licenses/admin.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +# -*- coding:utf8 -*- +# Copyright (C) 2012 FinalsClub Foundation +""" Administration configuration for notes """ + +from django.contrib import admin + +from karmaworld.apps.licenses.models import License + +admin.site.register(License) diff --git a/karmaworld/apps/licenses/migrations/0001_initial.py b/karmaworld/apps/licenses/migrations/0001_initial.py new file mode 100644 index 0000000..a935882 --- /dev/null +++ b/karmaworld/apps/licenses/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'License' + db.create_table('licenses_license', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=80)), + ('html', self.gf('django.db.models.fields.TextField')()), + )) + db.send_create_signal('licenses', ['License']) + + + def backwards(self, orm): + # Deleting model 'License' + db.delete_table('licenses_license') + + + models = { + 'licenses.license': { + 'Meta': {'object_name': 'License'}, + 'html': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + } + } + + complete_apps = ['licenses'] \ No newline at end of file diff --git a/karmaworld/apps/licenses/migrations/__init__.py b/karmaworld/apps/licenses/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/karmaworld/apps/licenses/models.py b/karmaworld/apps/licenses/models.py new file mode 100644 index 0000000..603690d --- /dev/null +++ b/karmaworld/apps/licenses/models.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding:utf8 -*- +# Copyright (C) 2012 FinalsClub Foundation + +""" + Models for the licenses in the django app. +""" + +from django.db import models + +class License(models.Model): + """ + Track licenses for notes which are different from the default license + assumed for the site. + """ + + name = models.CharField(max_length=80) + html = models.TextField() + + def __unicode__(self): + return u'License: {0}'.format(self.name) diff --git a/karmaworld/apps/notes/migrations/0010_auto__add_field_note_license__chg_field_note_ip.py b/karmaworld/apps/notes/migrations/0010_auto__add_field_note_license__chg_field_note_ip.py new file mode 100644 index 0000000..ab712ca --- /dev/null +++ b/karmaworld/apps/notes/migrations/0010_auto__add_field_note_license__chg_field_note_ip.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + depends_on = ( + ('licenses', '0001_initial'), + ) + + def forwards(self, orm): + # Adding field 'Note.license' + db.add_column('notes_note', 'license', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['licenses.License'], null=True, blank=True), + keep_default=False) + + + # Changing field 'Note.ip' + db.alter_column('notes_note', 'ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39, null=True)) + + def backwards(self, orm): + # Deleting field 'Note.license' + db.delete_column('notes_note', 'license_id') + + + # Changing field 'Note.ip' + db.alter_column('notes_note', 'ip', self.gf('django.db.models.fields.IPAddressField')(max_length=15, null=True)) + + models = { + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'courses.course': { + 'Meta': {'ordering': "['-file_count', 'school', 'name']", 'unique_together': "(('school', 'name', 'instructor_name'),)", 'object_name': 'Course'}, + 'academic_year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'desc': ('django.db.models.fields.TextField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}), + 'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instructor_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'instructor_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'school': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['courses.School']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}) + }, + 'courses.school': { + 'Meta': {'ordering': "['-file_count', '-priority', 'name']", 'object_name': 'School'}, + 'alias': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'facebook_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'priority': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'blank': 'True'}), + 'usde_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'licenses.license': { + 'Meta': {'object_name': 'License'}, + 'html': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'notes.note': { + 'Meta': {'ordering': "['-uploaded_at']", 'object_name': 'Note'}, + 'course': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['courses.Course']"}), + 'file_type': ('django.db.models.fields.CharField', [], {'default': "'???'", 'max_length': '15', 'null': 'True', 'blank': 'True'}), + 'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'fp_file': ('django_filepicker.models.FPFileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'gdrive_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), + 'is_hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'license': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['licenses.License']", 'null': 'True', 'blank': 'True'}), + 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'pdf_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'thanks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'tweeted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow', 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['users.KarmaUser']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'}) + }, + 'taggit.tag': { + 'Meta': {'ordering': "['namespace', 'name']", 'object_name': 'Tag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'namespace': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + 'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"}) + }, + 'users.karmauser': { + 'Meta': {'object_name': 'KarmaUser'}, + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['notes'] diff --git a/karmaworld/apps/notes/migrations/0011_auto__add_field_note_upstream_link.py b/karmaworld/apps/notes/migrations/0011_auto__add_field_note_upstream_link.py new file mode 100644 index 0000000..031754b --- /dev/null +++ b/karmaworld/apps/notes/migrations/0011_auto__add_field_note_upstream_link.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Note.upstream_link' + db.add_column('notes_note', 'upstream_link', + self.gf('django.db.models.fields.URLField')(max_length=1024, null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Note.upstream_link' + db.delete_column('notes_note', 'upstream_link') + + + models = { + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'courses.course': { + 'Meta': {'ordering': "['-file_count', 'school', 'name']", 'unique_together': "(('school', 'name', 'instructor_name'),)", 'object_name': 'Course'}, + 'academic_year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'desc': ('django.db.models.fields.TextField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}), + 'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instructor_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'instructor_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'school': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['courses.School']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}) + }, + 'courses.school': { + 'Meta': {'ordering': "['-file_count', '-priority', 'name']", 'object_name': 'School'}, + 'alias': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'facebook_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'priority': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'blank': 'True'}), + 'usde_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'licenses.license': { + 'Meta': {'object_name': 'License'}, + 'html': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) + }, + 'notes.note': { + 'Meta': {'ordering': "['-uploaded_at']", 'object_name': 'Note'}, + 'course': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['courses.Course']"}), + 'file_type': ('django.db.models.fields.CharField', [], {'default': "'???'", 'max_length': '15', 'null': 'True', 'blank': 'True'}), + 'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'fp_file': ('django_filepicker.models.FPFileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'gdrive_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), + 'is_hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'license': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['licenses.License']", 'null': 'True', 'blank': 'True'}), + 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'pdf_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'thanks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'tweeted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow', 'null': 'True'}), + 'upstream_link': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['users.KarmaUser']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'}) + }, + 'taggit.tag': { + 'Meta': {'ordering': "['namespace', 'name']", 'object_name': 'Tag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'namespace': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + 'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"}) + }, + 'users.karmauser': { + 'Meta': {'object_name': 'KarmaUser'}, + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['notes'] \ No newline at end of file diff --git a/karmaworld/apps/notes/models.py b/karmaworld/apps/notes/models.py index 9beb0d5..100bd3e 100644 --- a/karmaworld/apps/notes/models.py +++ b/karmaworld/apps/notes/models.py @@ -23,6 +23,7 @@ from lxml.html import fromstring, tostring from taggit.managers import TaggableManager from karmaworld.apps.courses.models import Course +from karmaworld.apps.licenses.models import License import karmaworld.apps.notes.search as search fs = FileSystemStorage(location=settings.MEDIA_ROOT) @@ -39,13 +40,18 @@ def _choose_upload_to(instance, filename): class Document(models.Model): """ An Abstract Base Class representing a document intended to be subclassed - """ course = models.ForeignKey(Course) tags = TaggableManager(blank=True) name = models.CharField(max_length=255, blank=True, null=True) slug = models.SlugField(max_length=255, null=True) + # license if different from default + license = models.ForeignKey(License, blank=True, null=True) + + # provide an upstream file link + upstream_link = models.URLField(max_length=1024, blank=True, null=True) + # metadata relevant to the Upload process user = models.ForeignKey('users.KarmaUser', blank=True, null=True, on_delete=SET_NULL) ip = models.GenericIPAddressField(blank=True, null=True, diff --git a/karmaworld/assets/css/note_course_pages.css b/karmaworld/assets/css/note_course_pages.css index 039c418..bf17df4 100644 --- a/karmaworld/assets/css/note_course_pages.css +++ b/karmaworld/assets/css/note_course_pages.css @@ -12,7 +12,7 @@ margin-right: 3px; } -#note_status +#note_status, #note_pedigree { text-align: center; padding-top: 10px; diff --git a/karmaworld/settings/common.py b/karmaworld/settings/common.py index 0140618..0e7b0a5 100644 --- a/karmaworld/settings/common.py +++ b/karmaworld/settings/common.py @@ -215,6 +215,7 @@ LOCAL_APPS = ( 'karmaworld.apps.document_upload', 'karmaworld.apps.users', 'karmaworld.apps.moderation', + 'karmaworld.apps.licenses', ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps diff --git a/karmaworld/templates/notes/note_detail.html b/karmaworld/templates/notes/note_detail.html index 3e0d4bc..125c0c6 100644 --- a/karmaworld/templates/notes/note_detail.html +++ b/karmaworld/templates/notes/note_detail.html @@ -66,6 +66,14 @@ + {% if note.license %} +
+
+ {{ note.license.html|safe }} {% if note.upstream_link %}{{ note.upstream_link }}{% endif %} +
+
+ {% endif %} + {% if pdf_controls %} -- 2.25.1