aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2019-01-05 09:50:21 -0600
committerluxagraf <sng@luxagraf.net>2019-01-05 09:50:21 -0600
commitd5f430d3e1e2b274d8d8f744251e8b6b4b72ebd9 (patch)
tree094404cdf4eaba53b1e225b54212679f6f032afd
parent23b4b185e3f3f8b9f17eebc49110cb4696acdb39 (diff)
changed to custom modal, added saving animation for note editing.
-rw-r--r--TODO22
-rw-r--r--apps/accounts/models.py2
-rw-r--r--apps/accounts/signals.py3
-rw-r--r--apps/notes/migrations/0014_auto_20190104_1945.py56
-rw-r--r--apps/notes/migrations/0015_auto_20190104_1946.py31
-rw-r--r--apps/notes/models.py32
-rw-r--r--apps/notes/views.py32
-rw-r--r--apps/utils/widgets.py2
-rw-r--r--design/sass/_fonts.scss11
-rw-r--r--design/sass/_global.scss3
-rw-r--r--design/sass/_header.scss14
-rw-r--r--design/sass/_mixins.scss2
-rw-r--r--design/sass/_modal.scss72
-rw-r--r--design/sass/_notes.scss28
-rw-r--r--design/sass/screenv1.scss2
-rw-r--r--design/templates/base.html12
-rw-r--r--design/templates/django_registration/activation_complete.html5
-rw-r--r--design/templates/django_registration/registration_complete.html2
-rw-r--r--design/templates/notes/notebook_detail.html5
-rw-r--r--design/templates/notes/notes_detail.html2
-rw-r--r--design/templates/notes/notes_list.html9
-rw-r--r--design/templates/pages/page.html2
-rw-r--r--scripts/src/main-nav.js45
-rw-r--r--scripts/src/note-edit.js23
-rw-r--r--scripts/src/util.js21
25 files changed, 344 insertions, 94 deletions
diff --git a/TODO b/TODO
index c2a48c1..751e018 100644
--- a/TODO
+++ b/TODO
@@ -1,16 +1,20 @@
## Note and Notebooks
- * add defailt "trash" notebook and note manager to not show notes in the trash.
- * add delete note option to list and detail views
+ * side by side note view for comparing/adding annotations
+ * add delete note option to list
* notebook main -- add form for editing all notebooks
- * add loading animation when saving, hide when done.
* add search to notebook list on create and edit note pages
+ * covert notebook and tag menus to searchable dropdown
+ - menu default as an overflow div maybe? Select list?
+ - hide select list with JS, pull data into div
+ - add event to button to reveal menu
+ - add input box to top of menu for search
+ - make search hide menu items as you search
+ - make return open link
## Accounts
- * port modal login to new modal system
* make settings actually editable
* add settings for showing color
- * which editor???
* hook into groups to see if user is allowed to add more notebooks
* add payment via stripe
@@ -23,3 +27,11 @@
## Outlines
+
+# Done
+ * port modal login to new modal system
+ * add defailt "trash" notebook and note manager to not show notes in the trash.
+ * refactor models to get rid of null on TextFields
+ * add loading animation when saving, hide when done.
+ - need new type of modal with no close btn
+ - need to be resizeable
diff --git a/apps/accounts/models.py b/apps/accounts/models.py
index d000e3e..1b62ffd 100644
--- a/apps/accounts/models.py
+++ b/apps/accounts/models.py
@@ -26,4 +26,4 @@ class UserProfile(models.Model):
@cached_property
def get_notebook_list(self):
- return Notebook.objects.filter(owner=self.user).select_related()[:8]
+ return Notebook.objects.filter(owner=self.user).select_related().annotate(note_count=models.Count('note'))[:8]
diff --git a/apps/accounts/signals.py b/apps/accounts/signals.py
index 837a7ed..7c7f7c9 100644
--- a/apps/accounts/signals.py
+++ b/apps/accounts/signals.py
@@ -2,6 +2,7 @@ from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User, UserProfile
+from notes.models import Notebook
@receiver(post_save, sender=User)
@@ -10,3 +11,5 @@ def create_profile(sender, update_fields, created, instance, **kwargs):
if created:
user_profile = UserProfile.objects.create(user=instance)
user_profile.save()
+ user_trash_notebook = Notebook.objects.create(owner=instance, name="Trash")
+ user_trash_notebook.save()
diff --git a/apps/notes/migrations/0014_auto_20190104_1945.py b/apps/notes/migrations/0014_auto_20190104_1945.py
new file mode 100644
index 0000000..42398a3
--- /dev/null
+++ b/apps/notes/migrations/0014_auto_20190104_1945.py
@@ -0,0 +1,56 @@
+# Generated by Django 2.1.2 on 2019-01-05 01:45
+
+from django.db import migrations, models
+import django.db.models.manager
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('notes', '0013_remove_luxtag_owner'),
+ ]
+
+ operations = [
+ migrations.AlterModelManagers(
+ name='note',
+ managers=[
+ ('include_trash', django.db.models.manager.Manager()),
+ ],
+ ),
+ migrations.AlterModelManagers(
+ name='notebook',
+ managers=[
+ ('include_trash', django.db.models.manager.Manager()),
+ ],
+ ),
+ migrations.AlterField(
+ model_name='annotation',
+ name='body_html',
+ field=models.TextField(blank=True, default=''),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='annotation',
+ name='body_text',
+ field=models.TextField(blank=True, default=''),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='annotation',
+ name='highlight_text',
+ field=models.TextField(blank=True, default=''),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='note',
+ name='body_html',
+ field=models.TextField(blank=True, default=''),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='note',
+ name='body_text',
+ field=models.TextField(blank=True, default=''),
+ preserve_default=False,
+ ),
+ ]
diff --git a/apps/notes/migrations/0015_auto_20190104_1946.py b/apps/notes/migrations/0015_auto_20190104_1946.py
new file mode 100644
index 0000000..542dfc6
--- /dev/null
+++ b/apps/notes/migrations/0015_auto_20190104_1946.py
@@ -0,0 +1,31 @@
+# Generated by Django 2.1.2 on 2019-01-05 01:46
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('notes', '0014_auto_20190104_1945'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='luxtag',
+ name='color_rgb',
+ field=models.CharField(blank=True, default='', max_length=20),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='note',
+ name='url',
+ field=models.CharField(blank=True, default='', max_length=250),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='notebook',
+ name='color_rgb',
+ field=models.CharField(blank=True, default='', max_length=20),
+ preserve_default=False,
+ ),
+ ]
diff --git a/apps/notes/models.py b/apps/notes/models.py
index 9dc4f13..bfcb8ba 100644
--- a/apps/notes/models.py
+++ b/apps/notes/models.py
@@ -19,7 +19,7 @@ from taggit.models import TagBase, GenericTaggedItemBase
class LuxTag(TagBase):
- color_rgb = models.CharField(max_length=20, null=True, blank=True)
+ color_rgb = models.CharField(max_length=20, blank=True)
class Meta:
verbose_name = _("Tag")
@@ -34,16 +34,24 @@ class TaggedNotes(GenericTaggedItemBase):
tag = models.ForeignKey(LuxTag, related_name="%(app_label)s_%(class)s_items", on_delete=models.CASCADE)
+class NotebookManager(models.Manager):
+ def get_queryset(self):
+ return super().get_queryset().exclude(name='Trash')
+
+
class Notebook(models.Model):
""" Notebook model for Notes """
unique_id = models.UUIDField(default=uuid.uuid4, editable=False)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
- color_rgb = models.CharField(max_length=20, null=True, blank=True)
+ color_rgb = models.CharField(max_length=20, blank=True)
slug = models.SlugField(blank=True)
date_created = models.DateTimeField(blank=True, auto_now_add=True, editable=False)
date_updated = models.DateTimeField(blank=True, auto_now=True, editable=False)
+ include_trash = models.Manager()
+ objects = NotebookManager() # The default manager never shows the Notebook 'Trash'
+
class Meta:
unique_together = ("owner", "name")
@@ -69,21 +77,29 @@ class Notebook(models.Model):
return rgba
+class NoteManager(models.Manager):
+ def get_queryset(self):
+ return super().get_queryset().exclude(notebook__name='Trash')
+
+
class Note(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
date_created = models.DateTimeField(blank=True, auto_now_add=True, editable=False)
date_updated = models.DateTimeField(blank=True, auto_now=True, editable=False)
title = models.CharField(max_length=250)
- body_text = models.TextField(null=True)
- body_html = models.TextField(null=True, blank=True)
+ body_text = models.TextField(blank=True)
+ body_html = models.TextField(blank=True)
body_qjson = JSONField(null=True, blank=True)
- url = models.CharField(max_length=250, null=True, blank=True)
+ url = models.CharField(max_length=250, blank=True)
slug = models.SlugField(blank=True)
notebook = models.ForeignKey(Notebook, null=True, blank=True, on_delete=models.SET_NULL)
tags = TaggableManager(through=TaggedNotes, blank=True, help_text='Tags')
is_public = models.BooleanField(default=False)
+ include_trash = models.Manager()
+ objects = NoteManager() # The default manager never shows the notes in 'Trash'
+
class Meta:
unique_together = ("owner", "slug")
ordering = ("-date_created", "-date_updated")
@@ -108,9 +124,9 @@ class Annotation(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
date_created = models.DateTimeField(blank=True, auto_now_add=True, editable=False)
date_updated = models.DateTimeField(blank=True, auto_now=True, editable=False)
- highlight_text = models.TextField(null=True)
- body_text = models.TextField(null=True)
- body_html = models.TextField(null=True, blank=True)
+ highlight_text = models.TextField(blank=True)
+ body_text = models.TextField(blank=True)
+ body_html = models.TextField(blank=True)
body_qjson = JSONField(null=True, blank=True)
note = models.ForeignKey(Note, null=True, blank=True, on_delete=models.SET_NULL)
is_public = models.BooleanField(default=False)
diff --git a/apps/notes/views.py b/apps/notes/views.py
index 6751340..245e2ab 100644
--- a/apps/notes/views.py
+++ b/apps/notes/views.py
@@ -8,6 +8,7 @@ from django.db.models import Count
from django.views.generic.base import RedirectView
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
+from django.contrib import messages
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse, reverse_lazy
@@ -59,7 +60,7 @@ class NoteListView(BaseListView):
def get_context_data(self, **kwargs):
context = super(NoteListView, self).get_context_data(**kwargs)
- context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).exclude(name="Trash").annotate(note_count=Count('note'))
+ context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).annotate(note_count=Count('note'))
context['tag_list'] = LuxTag.objects.filter(note__owner=self.request.user).annotate(note_count=Count('note'))
return context
@@ -89,13 +90,19 @@ class NoteDetailView(LoggedInViewWithUser, AjaxableResponseMixin, UpdateView):
return context
def form_valid(self, form):
- self.object = form.save()
- tags = serializers.serialize("json", self.object.tags.all())
- data = {
- 'tags': tags,
- 'notebook': {'name': self.object.notebook.name, 'color': self.object.notebook.color_rgb}
- }
- return JsonResponse(data, safe=True)
+ if "trash" in self.request.POST:
+ form.instance.notebook = Notebook.include_trash.get(owner=self.request.user, name="Trash")
+ self.object = form.save()
+ messages.info(self.request, 'The note %s was moved to the trash. <a href="/nb/trash">View trash</a>' % (self.object.title), extra_tags='safe')
+ return redirect('notes:list')
+ else:
+ self.object = form.save()
+ tags = serializers.serialize("json", self.object.tags.all())
+ data = {
+ 'tags': tags,
+ 'notebook': {'name': self.object.notebook.name, 'color': self.object.notebook.color_rgb}
+ }
+ return JsonResponse(data, safe=True)
class NoteCreateView(LoggedInViewWithUser, CreateView):
@@ -173,7 +180,7 @@ class NotebookListView(LoggedInViewWithUser, CreateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
NotebookFormSet = modelformset_factory(Notebook, form=NotebookForm, extra=0)
- context['notebook_form_list'] = NotebookFormSet(queryset=Notebook.objects.filter(owner=self.request.user).exclude(name="Trash").select_related().annotate(note_count=Count('note')))
+ context['notebook_form_list'] = NotebookFormSet(queryset=Notebook.objects.filter(owner=self.request.user).select_related().annotate(note_count=Count('note')))
#context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).exclude(name="Trash").select_related().annotate(note_count=Count('note'))
#context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related()
return context
@@ -185,6 +192,13 @@ class NotebookListView(LoggedInViewWithUser, CreateView):
class NotebookDetailView(BaseDetailView):
model = Notebook
+ def get_queryset(self):
+ if not self.request.user.is_anonymous:
+ if self.kwargs["slug"] == 'trash':
+ return Notebook.include_trash.filter(owner=self.request.user)
+ else:
+ return Notebook.objects.filter(owner=self.request.user)
+
def get_object(self):
notebook = get_object_or_404(self.get_queryset().select_related(), owner=self.request.user, slug=self.kwargs["slug"])
self.form = NotebookForm(instance=notebook)
diff --git a/apps/utils/widgets.py b/apps/utils/widgets.py
index 2745932..6dc28bf 100644
--- a/apps/utils/widgets.py
+++ b/apps/utils/widgets.py
@@ -142,10 +142,12 @@ class RelatedFieldWidgetCanAdd(widgets.Select):
rel_to = related_model
info = (rel_to._meta.app_label, rel_to._meta.object_name.lower())
related_url = 'admin:%s_%s_add' % info
+ print(related_url)
self.related_url = related_url
def render(self, name, value, *args, **kwargs):
self.related_url = reverse(self.related_url)
+ print(self.related_url)
output = [super(RelatedFieldWidgetCanAdd, self).render(name, value, *args, **kwargs)]
output.append('<a class="circle plus small-circle modal-open" href="%s" id="add_id_%s" data-modal-hed-class="%s" data-modal-hed="Add a New %s">New</a>' % (self.related_url, name, name, name.capitalize()))
return mark_safe(u''.join(output))
diff --git a/design/sass/_fonts.scss b/design/sass/_fonts.scss
index dfe632a..5ea0e6e 100644
--- a/design/sass/_fonts.scss
+++ b/design/sass/_fonts.scss
@@ -1,10 +1,7 @@
@font-face {
- font-family: 'carrois_gothicregular';
- src: url('carroisgothic-regular-webfont.eot');
- src: url('carroisgothic-regular-webfont.eot?#iefix') format('embedded-opentype'),
- url('carroisgothic-regular-webfont.woff') format('woff'),
- url('carroisgothic-regular-webfont.ttf') format('truetype');
- font-weight: normal;
+ font-family: 'proxima_novabold';
+ src: url('/media/fonts/proximanova-bold-webfont.woff2') format('woff2'),
+ url('/media/fonts/proximanova-bold-webfont.woff') format('woff');
+ font-weight: 600;
font-style: normal;
-
}
diff --git a/design/sass/_global.scss b/design/sass/_global.scss
index b858866..41a1682 100644
--- a/design/sass/_global.scss
+++ b/design/sass/_global.scss
@@ -230,6 +230,9 @@ h3 {
margin-bottom: .5rem;
margin-top: 2rem;
}
+.float-right {
+ float: right;
+}
//************** other global classes ************************
.sans {
@include generic_sans;
diff --git a/design/sass/_header.scss b/design/sass/_header.scss
index 29e1ef2..8df6667 100644
--- a/design/sass/_header.scss
+++ b/design/sass/_header.scss
@@ -21,7 +21,6 @@ header {
}
}
nav {
- @include fancy-sans-bold;
letter-spacing: 1px;
margin: 0 0 10px;
ul {
@@ -32,13 +31,14 @@ nav {
}
}
a {
- @include fontsize(14);
+ @include fancy-sans-bold;
+ @include fontsize(16);
text-decoration: none;
- color: #444;
- font-weight: normal;
+ color: lighten(#444, 15);
+ font-weight: 600;
padding: 6px;
&:visited {
- color: #444;
+ color: lighten(#444, 15);
}
&:hover {
color: $link_color;
@@ -83,6 +83,8 @@ nav {
border-bottom-color: white;
}
a, a:visited {
+ @include fancy-sans;
+ font-weight: 400;
color: lighten($body_font_color, 15);
}
a:hover {
@@ -107,7 +109,7 @@ nav {
height: 20px;
border-radius: 100%;
position: relative;
- margin: -2px 8px 0 0;
+ margin: -4px 8px 0 0;
display: inline-block;
vertical-align: middle;
background: $link_color;
diff --git a/design/sass/_mixins.scss b/design/sass/_mixins.scss
index bfccc17..b7da0f6 100644
--- a/design/sass/_mixins.scss
+++ b/design/sass/_mixins.scss
@@ -44,7 +44,7 @@ $max_width: 1280px;
font-family: "proxima-nova",helvetica,arial,sans-serif;
}
@mixin fancy-sans-bold {
- font-family: "proxima-nova",helvetica,arial,sans-serif;
+ font-family: "proxima_novabold",helvetica,arial,sans-serif;
font-weight: 600;
}
@mixin fancy-serif {
diff --git a/design/sass/_modal.scss b/design/sass/_modal.scss
index f333fd2..8c9bf46 100644
--- a/design/sass/_modal.scss
+++ b/design/sass/_modal.scss
@@ -1,4 +1,4 @@
-#overlay{
+#overlay, #loading {
position:fixed;
width:100vw;
height:100vh;
@@ -60,6 +60,9 @@
max-width: 52%;
width: 90%;
}
+#loading #overlay-wrapper {
+ max-width: 10%;
+}
#modal {
min-height: 330px;
padding: 0 1rem 1rem 1rem;
@@ -92,6 +95,9 @@
}
}
+#loading #modal {
+ min-height: auto;
+}
#hed-wrapper {
display: flex;
align-items: center;
@@ -100,3 +106,67 @@
width: auto;
}
}
+
+.loader {
+ font-size: 10px;
+ margin: 50px auto;
+ text-indent: -9999em;
+ width: 11em;
+ height: 11em;
+ border-radius: 50%;
+ background: $link_color;
+ background: -moz-linear-gradient(left, $link_color 10%, rgba(255, 255, 255, 0) 42%);
+ background: -webkit-linear-gradient(left, $link_color 10%, rgba(255, 255, 255, 0) 42%);
+ background: -o-linear-gradient(left, $link_color 10%, rgba(255, 255, 255, 0) 42%);
+ background: -ms-linear-gradient(left, $link_color 10%, rgba(255, 255, 255, 0) 42%);
+ background: linear-gradient(to right, $link_color 10%, rgba(255, 255, 255, 0) 42%);
+ position: relative;
+ -webkit-animation: load3 1.4s infinite linear;
+ animation: load3 1.4s infinite linear;
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.loader:before {
+ width: 50%;
+ height: 50%;
+ background: $link_color;
+ border-radius: 100% 0 0 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ content: '';
+}
+.loader:after {
+ background: #fff;
+ width: 75%;
+ height: 75%;
+ border-radius: 50%;
+ content: '';
+ margin: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+}
+@-webkit-keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
diff --git a/design/sass/_notes.scss b/design/sass/_notes.scss
index 4ab42b4..59e76ce 100644
--- a/design/sass/_notes.scss
+++ b/design/sass/_notes.scss
@@ -112,6 +112,11 @@ main {
height: 9px;
margin-right: 4px;
}
+.dropmenu .color-box {
+ margin-right: 5px;
+ position: relative;
+ top: -1px;
+}
.note-title {
@include fontsize(26);
}
@@ -351,6 +356,29 @@ main {
}
}
+.messages {
+ @include fancy-sans-bold;
+ @include fontsize(16);
+ list-style-type: none;
+ color: $link_color;
+ font-weight: 600;
+}
+.trash {
+ text-indent: -9999em;
+ width: 30px;
+ color: $link_color;
+ border: none;
+ background: url("data:image/svg+xml,%3Csvg xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns%23' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns%23' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' viewBox='0 -256 1792 1792' id='svg3741' version='1.1' inkscape:version='0.48.3.1 r9886' width='100%25' height='100%25' sodipodi:docname='trash_font_awesome.svg'%3E%3Cmetadata id='metadata3751'%3E%3Crdf:RDF%3E%3Ccc:Work rdf:about=''%3E%3Cdc:format%3Eimage/svg+xml%3C/dc:format%3E%3Cdc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage' /%3E%3C/cc:Work%3E%3C/rdf:RDF%3E%3C/metadata%3E%3Cdefs id='defs3749' /%3E%3Csodipodi:namedview pagecolor='%23ffffff' bordercolor='%23666666' borderopacity='1' objecttolerance='10' gridtolerance='10' guidetolerance='10' inkscape:pageopacity='0' inkscape:pageshadow='2' inkscape:window-width='640' inkscape:window-height='480' id='namedview3747' showgrid='false' inkscape:zoom='0.13169643' inkscape:cx='896' inkscape:cy='896' inkscape:window-x='0' inkscape:window-y='25' inkscape:window-maximized='0' inkscape:current-layer='svg3741' /%3E%3Cg transform='matrix(1,0,0,-1,197.42373,1255.0508)' id='g3743'%3E%3Cpath d='M 512,800 V 224 q 0,-14 -9,-23 -9,-9 -23,-9 h -64 q -14,0 -23,9 -9,9 -9,23 v 576 q 0,14 9,23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 256,0 V 224 q 0,-14 -9,-23 -9,-9 -23,-9 h -64 q -14,0 -23,9 -9,9 -9,23 v 576 q 0,14 9,23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 256,0 V 224 q 0,-14 -9,-23 -9,-9 -23,-9 h -64 q -14,0 -23,9 -9,9 -9,23 v 576 q 0,14 9,23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z M 1152,76 v 948 H 256 V 76 Q 256,54 263,35.5 270,17 277.5,8.5 285,0 288,0 h 832 q 3,0 10.5,8.5 7.5,8.5 14.5,27 7,18.5 7,40.5 z M 480,1152 h 448 l -48,117 q -7,9 -17,11 H 546 q -10,-2 -17,-11 z m 928,-32 v -64 q 0,-14 -9,-23 -9,-9 -23,-9 h -96 V 76 q 0,-83 -47,-143.5 -47,-60.5 -113,-60.5 H 288 q -66,0 -113,58.5 Q 128,-11 128,72 v 952 H 32 q -14,0 -23,9 -9,9 -9,23 v 64 q 0,14 9,23 9,9 23,9 h 309 l 70,167 q 15,37 54,63 39,26 79,26 h 320 q 40,0 79,-26 39,-26 54,-63 l 70,-167 h 309 q 14,0 23,-9 9,-9 9,-23 z' id='path3745' inkscape:connector-curvature='0' style='fill:%23FC5D2B' /%3E%3C/g%3E%3C/svg%3E%0A") no-repeat;
+ &:hover {
+ background: url("data:image/svg+xml,%3Csvg xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns%23' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns%23' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' viewBox='0 -256 1792 1792' id='svg3741' version='1.1' inkscape:version='0.48.3.1 r9886' width='100%25' height='100%25' sodipodi:docname='trash_font_awesome.svg'%3E%3Cmetadata id='metadata3751'%3E%3Crdf:RDF%3E%3Ccc:Work rdf:about=''%3E%3Cdc:format%3Eimage/svg+xml%3C/dc:format%3E%3Cdc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage' /%3E%3C/cc:Work%3E%3C/rdf:RDF%3E%3C/metadata%3E%3Cdefs id='defs3749' /%3E%3Csodipodi:namedview pagecolor='%23ffffff' bordercolor='%23666666' borderopacity='1' objecttolerance='10' gridtolerance='10' guidetolerance='10' inkscape:pageopacity='0' inkscape:pageshadow='2' inkscape:window-width='640' inkscape:window-height='480' id='namedview3747' showgrid='false' inkscape:zoom='0.13169643' inkscape:cx='896' inkscape:cy='896' inkscape:window-x='0' inkscape:window-y='25' inkscape:window-maximized='0' inkscape:current-layer='svg3741' /%3E%3Cg transform='matrix(1,0,0,-1,197.42373,1255.0508)' id='g3743'%3E%3Cpath d='M 512,800 V 224 q 0,-14 -9,-23 -9,-9 -23,-9 h -64 q -14,0 -23,9 -9,9 -9,23 v 576 q 0,14 9,23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 256,0 V 224 q 0,-14 -9,-23 -9,-9 -23,-9 h -64 q -14,0 -23,9 -9,9 -9,23 v 576 q 0,14 9,23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 256,0 V 224 q 0,-14 -9,-23 -9,-9 -23,-9 h -64 q -14,0 -23,9 -9,9 -9,23 v 576 q 0,14 9,23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z M 1152,76 v 948 H 256 V 76 Q 256,54 263,35.5 270,17 277.5,8.5 285,0 288,0 h 832 q 3,0 10.5,8.5 7.5,8.5 14.5,27 7,18.5 7,40.5 z M 480,1152 h 448 l -48,117 q -7,9 -17,11 H 546 q -10,-2 -17,-11 z m 928,-32 v -64 q 0,-14 -9,-23 -9,-9 -23,-9 h -96 V 76 q 0,-83 -47,-143.5 -47,-60.5 -113,-60.5 H 288 q -66,0 -113,58.5 Q 128,-11 128,72 v 952 H 32 q -14,0 -23,9 -9,9 -9,23 v 64 q 0,14 9,23 9,9 23,9 h 309 l 70,167 q 15,37 54,63 39,26 79,26 h 320 q 40,0 79,-26 39,-26 54,-63 l 70,-167 h 309 q 14,0 23,-9 9,-9 9,-23 z' id='path3745' inkscape:connector-curvature='0' style='fill:%23FC5D2B' /%3E%3C/g%3E%3C/svg%3E%0A") no-repeat;
+ }
+}
+
+.loading {
+ #close-btn {
+ display: none;
+ }
+}
.ql-snow .ql-editor blockquote {
border-left: none !important;
margin-bottom: 5px;
diff --git a/design/sass/screenv1.scss b/design/sass/screenv1.scss
index f3df73e..de2593e 100644
--- a/design/sass/screenv1.scss
+++ b/design/sass/screenv1.scss
@@ -1,8 +1,8 @@
@import "_fonts.scss";
@import "_mixins.scss";
@import "_queries.scss";
-@import "_awesomeplete.scss";
@import "_global.scss";
+@import "_icons.scss";
@import "_header.scss";
@import "_footer.scss";
@import "_forms.scss";
diff --git a/design/templates/base.html b/design/templates/base.html
index fc369ae..adcf599 100644
--- a/design/templates/base.html
+++ b/design/templates/base.html
@@ -29,11 +29,17 @@
<div id="notebooks-menu" class="dropmenu">
<ul id="notebooks-menu-list" class="list-style-none vertical">
{% for object in user.profile.get_notebook_list %}
- <li><a href="{{object.get_absolute_url}}" title="view all notes in the notebook {{object.name}}"><span class="color-box" style="background-color: {{object.color_rgb}}"></span>{{object}}</a>
+ <li><a href="{{object.get_absolute_url}}" title="view all notes in the notebook {{object.name}}"><span class="color-box" style="background-color: {{object.color_rgb}}"></span>{{object}} {{object.note_count}}</a>
{% endfor %}
- <li class="menu-divider">
+ <ul class="menu-divider">
+ <li>
+ <a href="{% url 'notebooks:list' %}/trash">Trash</a>
+ </li>
+ <li>
<a href="{% url 'notebooks:list' %}">Edit/Add Notebook</a>
- </li></ul>
+ </li>
+ </ul>
+ </ul>
</div>
</li>{%else%}
<li><a href="/" title="">Home</a></li>{%endif%}
diff --git a/design/templates/django_registration/activation_complete.html b/design/templates/django_registration/activation_complete.html
index 914be51..d83317a 100644
--- a/design/templates/django_registration/activation_complete.html
+++ b/design/templates/django_registration/activation_complete.html
@@ -1,8 +1,7 @@
-
{% extends 'base.html' %}
{% block content %}
-<main>
+<main class="single-col">
<h1>Your account is now active.</h1>
-<p><a href="{% url 'login' %}">Login</a> and get started! <?p>
+<p><a href="{% url 'login' %}">Login</a> and get started!</p>
</main>
{% endblock %}
diff --git a/design/templates/django_registration/registration_complete.html b/design/templates/django_registration/registration_complete.html
index e9d0610..59677ce 100644
--- a/design/templates/django_registration/registration_complete.html
+++ b/design/templates/django_registration/registration_complete.html
@@ -1,6 +1,6 @@
{% extends 'base.html' %}
{% block content %}
-<main>
+<main class="single-col">
<h1>Thanks for signing up.</h1>
<p>Please check your email for a link to confirm you new account.<?p>
</main>
diff --git a/design/templates/notes/notebook_detail.html b/design/templates/notes/notebook_detail.html
index 73c13ab..37c8f8a 100644
--- a/design/templates/notes/notebook_detail.html
+++ b/design/templates/notes/notebook_detail.html
@@ -8,9 +8,9 @@
<main>
<article class="note-container single-col">
<div class="flex-wrapper">
+ {% if object.name != 'Trash'%}
<form id="nb-edit-form" action="{% url 'notebook-api-detail' object.pk %}" method="PATCH">{% csrf_token %}
{{ form.non_field_errors }}
-
<div class="flex-wrapper flex-inner">
{% for field in form %}{% if field.name == 'color_rgb' %}
<fieldset class="color-picker-fieldset" id="color-picker" {% if form.instance.color_rgb %}style="background-color: {{form.instance.color_rgb}}; border: none;"{%endif%}>
@@ -28,6 +28,9 @@
<input id="btn-js-hide" type="submit" class="btn sm" value="Save" >
</form>
<div class="edit-btn-wrapper"><a class="hide btn btn-hollow" id="edit-toggle-btn">Edit</a></div>
+ {%else%}
+ <h1 class="notebook-title" id="nb-title">{{object.name}}</h1>
+ {%endif%}
</div>
<form id="new-note-form" action="{% url 'notebook-api-list' %}" method="post" class="hide">
diff --git a/design/templates/notes/notes_detail.html b/design/templates/notes/notes_detail.html
index edf45e7..cce13b7 100644
--- a/design/templates/notes/notes_detail.html
+++ b/design/templates/notes/notes_detail.html
@@ -49,8 +49,8 @@
<h1 id="note-title" class="note-title">{{object.title}}</h1>
<div id="q-container" class="inactive"><div id="note-body">{% if object.body_html %}{{object.body_html|safe}}{%else%}{{object.body_text}}{%endif%}</div></div>
<input id="btn-js-hide" type="submit" class="btn sm" value="Save" >
+ <button type="submit" value="trash" class="btn-hollow trash float-right" name="trash">Move to Trash</button>
</form>
- <button type="submit" value="trash" class="btn btn-hollow">Move to Trash</button>
</article>
<!--<aside class="note-list-container">
<div class="svg-wrapper"><svg class="svg-icon-arrow">
diff --git a/design/templates/notes/notes_list.html b/design/templates/notes/notes_list.html
index 5ef067a..94e82ec 100644
--- a/design/templates/notes/notes_list.html
+++ b/design/templates/notes/notes_list.html
@@ -5,6 +5,15 @@
<div class="note-container">
<div class="note-hed-wrapper">
<h1 class="note-hed">Notes</h1>
+ {% if messages %}
+ <ul class="messages">
+ {% for message in messages %}
+ <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
+ {% if 'safe' in message.tags %}{{ message|safe }}{% else %}{{ message }}{% endif %}
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
{% if tags|length >= 1%}<h2 class="note-subhed">Tagged with: {% for tag in tags%}<a href="{{tag.slug}}">{{tag.name}}</a>{%endfor%}</h2>{%endif%}
<h6 class="bottom-margin-0 inline-block"><button id="notebook-drop-btn" class="btn btn-light btn-drop-menu">Notebooks</button></h6>
diff --git a/design/templates/pages/page.html b/design/templates/pages/page.html
index 92dcc85..6703d5d 100644
--- a/design/templates/pages/page.html
+++ b/design/templates/pages/page.html
@@ -8,7 +8,7 @@
{% block extra %}
{% if login_form %}
-<div class="overlay-content" id="js-overlay-content" style="display: none;">
+<div class="overlay-content hide" id="js-overlay-login">
{% include 'lib/login.html' with form=login_form %}
</div>
{% endif %}
diff --git a/scripts/src/main-nav.js b/scripts/src/main-nav.js
index 0be7712..0dcd82b 100644
--- a/scripts/src/main-nav.js
+++ b/scripts/src/main-nav.js
@@ -46,40 +46,15 @@ if (document.getElementById('account-menu')) {
}, false);
}
-//function buildNotebookMenu () {
-// var data = JSON.parse(this.responseText);
-// var div = document.getElementById("notebooks-menu");
-// var ul = document.createElement("ul");
-// ul.classList.add("vertical","list-style-none");
-// div.appendChild(ul);
-// for(var i in data) {
-// var li = document.createElement("li");
-// var a = document.createElement("a");
-// a.setAttribute("href", data[i]['json_absolute_url']);
-// a.innerHTML = data[i]['name'];
-// li.append(a);
-// ul.append(li);
-// }
-// var li = document.createElement("li");
-// var a = document.createElement("a");
-// a.setAttribute("href", '/user/{{user.username}}/notebooks/');
-// a.innerHTML = "View all"
-// li.append(a);
-// ul.append(li);
-//}
-//
-//
-//// getJSON("{%url 'notebook-api-list' %}", buildNotebookMenu);
-//
-
-if (typeof(document.getElementById('js-overlay-content')) != 'undefined' && document.getElementById('js-overlay-content') != null) {
+if (typeof(document.getElementById('js-overlay-login')) != 'undefined' && document.getElementById('js-overlay-login') != null) {
// Select your overlay trigger
- var trigger = document.querySelector('#overlay-trigger');
- trigger.addEventListener('click', function(e){
- e.preventDefault();
- novicell.overlay.create({
- 'selector': trigger.getAttribute('data-element'),
- 'class': 'selector-overlay',
- });
- });
+ var trigger = document.getElementById('overlay-trigger');
+ addLoginHandler(trigger);
+ function addLoginHandler(el){
+ console.log(el);
+ el.addEventListener('click', function(e){
+ e.preventDefault();
+ var modal = modalBox(el, document.getElementById('js-overlay-login'));
+ });
+ }
}
diff --git a/scripts/src/note-edit.js b/scripts/src/note-edit.js
index 5abbab7..3d01794 100644
--- a/scripts/src/note-edit.js
+++ b/scripts/src/note-edit.js
@@ -52,6 +52,9 @@ function edit_note(btn, form, title, quill, qcontainer, url){
link.setAttribute('href', '/n/t/'+tags[i]['fields']['slug']);
link.appendChild(span);
tags_display.appendChild(link);
+ if (window.overlay !== undefined) {
+ window.overlay.destroy();
+ }
}
quill.change = false;
} else {
@@ -62,8 +65,16 @@ function edit_note(btn, form, title, quill, qcontainer, url){
request.onerror = function() {
console.log('error on request');
};
- console.log(request);
- console.log(form);
+ //create a modal to let the user know we're saving
+ var saveModal = document.createElement('div');
+ var loader = document.createElement('div');
+ loader.classList.add('loader');
+ saveModal.appendChild(loader);
+ saveModal.modalHed = "Saving changes"; //modal text content
+ saveModal.wrapperClass = 'loading'; //add a wrapper class to the modal for styling
+ var modal = modalBox(saveModal);
+ document.getElementById('close-btn').classList.add('hide');
+ //send the request to the REST API
request.send(new FormData(form));
}
title.setAttribute('contenteditable', false);
@@ -141,7 +152,9 @@ if (typeof(document.getElementById('note-edit-form')) != 'undefined' && document
form.addEventListener('input', function (e) {
form.formchange = true;
});
- document.getElementById('btn-js-hide').classList.add('hide');
+ var formbtn = document.getElementById('btn-js-hide')
+ formbtn.classList.add('hide');
+ console.log(formbtn);
btn.classList.remove('hide');
btn.editing = false;
btn.addEventListener('click', function(e){
@@ -157,7 +170,9 @@ if (typeof(document.getElementById('note-edit-form')) != 'undefined' && document
function addHandler(el){
el.addEventListener('click', function(e){
e.preventDefault();
- var modal = modalBox(el, document.getElementById('js-overlay-notebook'));
+ var modalContent = document.getElementById('js-overlay-notebook');
+ modalContent.wrapperClass = 'overlay'; //add a wrapper class to the modal for styling
+ var modal = modalBox(modalContent, el);
});
}
});
diff --git a/scripts/src/util.js b/scripts/src/util.js
index daad7e1..144deae 100644
--- a/scripts/src/util.js
+++ b/scripts/src/util.js
@@ -35,7 +35,7 @@ function ajaxHijack(form, func) {
//global init for Color Picker
function initColorPicker(form){
var notebook_form_inputs = form.getElementsByTagName('input');
- var p = notebook_form.getElementsByTagName('fieldset')['color-picker'];
+ var p = form.getElementsByTagName('fieldset')['color-picker'];
//document.getElementById('js-novi-backdrop').removeEventListener("click", handleMouseDown, true);
p.classList.add('top');
p.popup = p.popup || new Picker({
@@ -100,23 +100,32 @@ function initQuill(el) {
}
//global modal function, give a DOM element, puts it in a model box.
-function modalBox(el, content){
+function modalBox(content, btn){
+ // if passed a btn object get data from that, otherwise check the content object
+ if (btn) {
+ var type = btn.dataset.modalHedClass;
+ var headline = btn.dataset.modalHed;
+ } else {
+ var type = content.hedClass || '';
+ var headline = content.modalHed || '';
+ }
if (window.elemsRemoved !== undefined) {
content = window.elemsRemoved;
}
- var headlines = ['Prompt'];
var options = {
- type : el.dataset.modalHedClass,
- headline : el.dataset.modalHed,
+ type : type,
+ headline : headline,
content : content,
cancelText : 'X',
confirmText : 'OK',
cancelAction : function(){},
confirmAction : function(){},
reject : false,
+ class : content.wrapperClass
};
//build the modal
- var overlay = buildComponent('div', 'overlay');
+ console.log(options.class);
+ var overlay = buildComponent('div', options.class);
var outermodal = buildComponent('div', 'overlay-wrapper');
var innermodal = buildComponent('div', 'modal');
var headline = buildComponent('header', false, options.headline);