aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2019-01-09 13:29:17 -0600
committerluxagraf <sng@luxagraf.net>2019-01-09 13:29:17 -0600
commitbe0bb4e123240ac3ce02431b974c82f8f05d843b (patch)
treee2da7ac44be955ad5cbf32c0a35dc507ba63e844
parentd5f430d3e1e2b274d8d8f744251e8b6b4b72ebd9 (diff)
latest changes
-rw-r--r--TODO29
-rw-r--r--apps/accounts/forms.py11
-rw-r--r--apps/accounts/migrations/0002_auto_20190108_2115.py35
-rw-r--r--apps/accounts/models.py12
-rw-r--r--apps/accounts/urls.py6
-rw-r--r--apps/accounts/views.py2
-rw-r--r--apps/notes/models.py4
-rw-r--r--apps/notes/notebook_urls.py2
-rw-r--r--apps/notes/views.py48
-rw-r--r--apps/utils/views.py2
-rw-r--r--config/base_urls.py10
-rw-r--r--config/settings.py11
-rw-r--r--design/sass/_choices.scss382
-rw-r--r--design/sass/_forms.scss38
-rw-r--r--design/sass/_global.scss16
-rw-r--r--design/sass/_header.scss13
-rw-r--r--design/sass/_notes.scss125
-rw-r--r--design/sass/screenv1.scss1
-rw-r--r--design/templates/accounts/change-settings.html33
-rw-r--r--design/templates/accounts/profile.html14
-rw-r--r--design/templates/base.html2
-rw-r--r--design/templates/notes/notebook_detail.html18
-rw-r--r--design/templates/notes/notebook_list.html63
-rw-r--r--design/templates/notes/notes_detail.html3
-rw-r--r--design/templates/notes/notes_list.html40
-rw-r--r--design/templates/notes/partials/list_header.html19
-rw-r--r--design/templates/notes/partials/notebook_form.html4
-rw-r--r--scripts/babel.config.js13
-rw-r--r--scripts/package.json2
-rw-r--r--scripts/src/account-edit.js1
-rw-r--r--scripts/src/note-edit.js8
-rw-r--r--scripts/src/note-list.js66
-rw-r--r--scripts/src/notebook-edit.js136
-rw-r--r--scripts/src/util.js49
34 files changed, 969 insertions, 249 deletions
diff --git a/TODO b/TODO
index 751e018..eb97713 100644
--- a/TODO
+++ b/TODO
@@ -1,20 +1,14 @@
## Note and Notebooks
+ * add overlay "are you sure" then delete notebook
* side by side note view for comparing/adding annotations
* add delete note option to list
- * notebook main -- add form for editing all notebooks
- * 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
+ * add image parsing routine to avoid hotlinking
## Accounts
- * make settings actually editable
- * add settings for showing color
+ * make photo display in bio page and show file name in upload form
+ * make full name edittable
+ * add password change field
* hook into groups to see if user is allowed to add more notebooks
* add payment via stripe
@@ -25,13 +19,24 @@
- position
- dates
-
## Outlines
+ * generate outline from tag/notebook???
+
# Done
+ * add search to notebook list on create and edit note pages
* 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
+ * notebook main -- add form for editing all notebooks
+ * get rid of flexbox for notebook list
+ * 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
diff --git a/apps/accounts/forms.py b/apps/accounts/forms.py
index d53e754..2da08cb 100644
--- a/apps/accounts/forms.py
+++ b/apps/accounts/forms.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import ugettext_lazy as _
from django_registration.forms import RegistrationForm
from .models import User, UserProfile
@@ -12,7 +13,15 @@ class UserForm(RegistrationForm):
class ProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
- fields = '__all__'
+ fields = ['bio', 'photo', 'website']
+ labels = {
+ "photo": _("Profile photo"),
+ "bio": _("Bio. A little about you. links are fine, line breaks are not. Keep it short and sweet, 350 characters max"),
+ "website": _("If you have a personal website, plug it in here."),
+ }
+ widgets = {
+ 'bio': forms.Textarea(attrs={'cols': 104, 'rows': 10, 'class': 'textarea-rounded'}),
+ }
def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user", None)
diff --git a/apps/accounts/migrations/0002_auto_20190108_2115.py b/apps/accounts/migrations/0002_auto_20190108_2115.py
new file mode 100644
index 0000000..1ebb280
--- /dev/null
+++ b/apps/accounts/migrations/0002_auto_20190108_2115.py
@@ -0,0 +1,35 @@
+# Generated by Django 2.1.2 on 2019-01-09 03:15
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounts', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='userprofile',
+ name='bio',
+ field=models.CharField(blank=True, default='', max_length=350),
+ ),
+ migrations.AlterField(
+ model_name='userprofile',
+ name='location',
+ field=models.CharField(blank=True, default='', max_length=300),
+ ),
+ migrations.AlterField(
+ model_name='userprofile',
+ name='user',
+ field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AlterField(
+ model_name='userprofile',
+ name='website',
+ field=models.CharField(blank=True, default='', max_length=300),
+ ),
+ ]
diff --git a/apps/accounts/models.py b/apps/accounts/models.py
index 1b62ffd..feb20bf 100644
--- a/apps/accounts/models.py
+++ b/apps/accounts/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django.urls import reverse
from django.contrib.auth.models import AbstractUser
from django.utils.functional import cached_property
@@ -15,15 +16,18 @@ class User(AbstractUser):
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
photo = models.ImageField(upload_to='profile', null=True, blank=True)
- website = models.CharField(max_length=300, null=True, blank=True, default='')
- location = models.CharField(max_length=300, null=True, blank=True, default='')
- bio = models.TextField(null=True, blank=True, default='')
+ website = models.CharField(max_length=300, blank=True, default='')
+ location = models.CharField(max_length=300, blank=True, default='')
+ bio = models.CharField(max_length=350, blank=True, default='')
+ #default_note_folder = models.ForeignKey('notes.Notebook', null=True, on_delete=models.SET_NULL)
#default_note_public = models.BooleanField(default=False)
- #default_note_folder = models.ForeignKey('notes.Folder', null=True, on_delete=models.SET_NULL)
def __str__(self):
return self.user.username
+ def get_absolute_url(self):
+ return reverse("accounts:settings")
+
@cached_property
def get_notebook_list(self):
return Notebook.objects.filter(owner=self.user).select_related().annotate(note_count=models.Count('note'))[:8]
diff --git a/apps/accounts/urls.py b/apps/accounts/urls.py
index d9ee327..5cad311 100644
--- a/apps/accounts/urls.py
+++ b/apps/accounts/urls.py
@@ -2,9 +2,15 @@ from django.urls import path
from . import views
+app_name = "accounts"
urlpatterns = [
path(
+ r'change-profile/',
+ views.ProfileView.as_view(),
+ name="change-profile"
+ ),
+ path(
r'',
views.SettingsListView.as_view(),
name="settings"
diff --git a/apps/accounts/views.py b/apps/accounts/views.py
index d463522..75bb933 100644
--- a/apps/accounts/views.py
+++ b/apps/accounts/views.py
@@ -18,7 +18,7 @@ class UpdateViewWithUser(UpdateView):
class ProfileView(UpdateViewWithUser):
model = UserProfile
form_class = ProfileForm
- template_name = "accounts/profile.html"
+ template_name = "accounts/change-settings.html"
def get_object(self):
return self.request.user.profile
diff --git a/apps/notes/models.py b/apps/notes/models.py
index bfcb8ba..c4b1df6 100644
--- a/apps/notes/models.py
+++ b/apps/notes/models.py
@@ -54,13 +54,13 @@ class Notebook(models.Model):
class Meta:
unique_together = ("owner", "name")
+ ordering = ("name", "date_created", "date_updated")
def __str__(self):
return self.name
def save(self, **kwargs):
- if self._state.adding:
- self.slug = unique_slug_generator(self)
+ self.slug = unique_slug_generator(self)
super(Notebook, self).save()
@cached_property
diff --git a/apps/notes/notebook_urls.py b/apps/notes/notebook_urls.py
index b433d15..8e3133e 100644
--- a/apps/notes/notebook_urls.py
+++ b/apps/notes/notebook_urls.py
@@ -3,11 +3,13 @@ from django.urls import path
from .views import (
NotebookListView,
NotebookDetailView,
+ NotebookUpdateView,
)
app_name = "notebooks"
urlpatterns = [
+ path(r'<slug>/update', NotebookUpdateView.as_view(), name='update',),
path(r'<slug>', NotebookDetailView.as_view(), name='detail',),
path(r'', NotebookListView.as_view(), name='list',),
]
diff --git a/apps/notes/views.py b/apps/notes/views.py
index 245e2ab..280020a 100644
--- a/apps/notes/views.py
+++ b/apps/notes/views.py
@@ -90,6 +90,7 @@ class NoteDetailView(LoggedInViewWithUser, AjaxableResponseMixin, UpdateView):
return context
def form_valid(self, form):
+ print(self.request.META)
if "trash" in self.request.POST:
form.instance.notebook = Notebook.include_trash.get(owner=self.request.user, name="Trash")
self.object = form.save()
@@ -155,6 +156,8 @@ class NoteTagView(BaseListView):
context = super().get_context_data(**kwargs)
#context['notes_list'] = Note.objects.filter(owner=self.request.user)
context['tags'] = LuxTag.objects.filter(slug__in=self.tag_list)
+ context['tag_list'] = LuxTag.objects.filter(note__owner=self.request.user).annotate(note_count=Count('note'))
+ context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).annotate(note_count=Count('note'))
return context
@@ -174,23 +177,48 @@ class NotebookListView(LoggedInViewWithUser, CreateView):
def form_valid(self, form):
form.instance.owner = self.request.user
- self.object = form.save()
+ if "create" in self.request.POST:
+ self.object = form.save()
+ messages.info(self.request, 'The notebook %s has been created, you may edit it below.' % (self.object.name))
+ return redirect('notebooks:list')
return super(NotebookListView, self).form_valid(form)
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).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()
+ forms = []
+ for n in Notebook.objects.filter(owner=self.request.user).prefetch_related('note_set').prefetch_related('note_set__tags').annotate(note_count=Count('note')):
+ #notes = []
+ #tags = set(tag for tag in notes.tags_set.all().distinct() for notes in n.note_set.all())
+ #n.tag_list = tags
+ n.tag_list = LuxTag.objects.filter(note__in=n.note_set.all()).distinct()[:3]
+ forms.append(NotebookForm(instance=n))
+ context['notebook_form_list'] = forms
+ #context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).select_related().annotate(note_count=Count('note'))
return context
- def get_success_url(self):
- return reverse_lazy('notebooks:detail', kwargs={'slug': self.object.slug})
+class NotebookUpdateView(LoggedInViewWithUser, UpdateView):
+ model = Notebook
+ form_class = NotebookForm
+ template_name = 'notes/notebook_list.html'
-class NotebookDetailView(BaseDetailView):
+ def get_queryset(self):
+ if not self.request.user.is_anonymous:
+ return Notebook.objects.filter(owner=self.request.user)
+
+ def form_valid(self, form):
+ form.instance.owner = self.request.user
+ self.object = form.save()
+ data = {
+ 'notebook': {'name': self.object.name, 'color': self.object.color_rgb, 'permalink': self.object.slug}
+ }
+ return JsonResponse(data, safe=True)
+
+
+class NotebookDetailView(LoggedInViewWithUser, AjaxableResponseMixin, UpdateView):
model = Notebook
+ form_class = NotebookForm
+ template_name = 'notes/notebook_detail.html'
def get_queryset(self):
if not self.request.user.is_anonymous:
@@ -200,7 +228,7 @@ class NotebookDetailView(BaseDetailView):
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"])
+ notebook = get_object_or_404(self.get_queryset().prefetch_related('note_set').prefetch_related('note_set__tags'), owner=self.request.user, slug=self.kwargs["slug"])
self.form = NotebookForm(instance=notebook)
return notebook
@@ -208,6 +236,8 @@ class NotebookDetailView(BaseDetailView):
context = super().get_context_data(**kwargs)
#context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related()
context['form'] = self.form
+ context['tag_list'] = LuxTag.objects.filter(note__owner=self.request.user).annotate(note_count=Count('note'))
+ context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).annotate(note_count=Count('note'))
return context
diff --git a/apps/utils/views.py b/apps/utils/views.py
index ec3a902..c752706 100644
--- a/apps/utils/views.py
+++ b/apps/utils/views.py
@@ -59,6 +59,8 @@ class AjaxableResponseMixin:
# We make sure to call the parent's form_valid() method because
# it might do some processing (in the case of CreateView, it will
# call form.save() for example).
+ print(self.request.META)
+ print('x request header', self.request.META['HTTP_X_REQUESTED_WITH'])
response = super().form_valid(form)
if self.request.is_ajax():
data = {
diff --git a/config/base_urls.py b/config/base_urls.py
index efbe233..ed4bd91 100644
--- a/config/base_urls.py
+++ b/config/base_urls.py
@@ -45,12 +45,12 @@ urlpatterns += [
#path(r'<path>/<slug>/', PageDetailView.as_view(), name="pages"),
path(r'api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
-if settings.DEBUG:
- import debug_toolbar
- urlpatterns = [
- path('__debug__/', include(debug_toolbar.urls)),
+#if settings.DEBUG:
+ #import debug_toolbar
+ #urlpatterns = [
+ # path('__debug__/', include(debug_toolbar.urls)),
# For django versions before 2.0:
# url(r'^__debug__/', include(debug_toolbar.urls)),
- ] + urlpatterns
+ #] + urlpatterns
diff --git a/config/settings.py b/config/settings.py
index c7bef91..dcd14ee 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -24,9 +24,14 @@ DEBUG = config('DEBUG', cast=bool)
AUTH_PROFILE_MODULE = "accounts.UserProfile"
AUTH_USER_MODEL = "accounts.User"
-DEFAULT_FILE_STORAGE = config('DEFAULT_FILE_STORAGE')
INTERNAL_IPS = config('INTERNAL_IPS')
+
+DEFAULT_FILE_STORAGE = config('DEFAULT_FILE_STORAGE')
+AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
+AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
+AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME')
+AWS_DEFAULT_ACL = config('AWS_DEFAULT_ACL')
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
@@ -65,7 +70,7 @@ THIRD_PARTY_APPS = [
'taggit_serializer',
'django_extensions',
'rest_framework',
- 'debug_toolbar'
+ #'debug_toolbar'
]
LOCAL_APPS = [
'utils',
@@ -82,7 +87,7 @@ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
- 'debug_toolbar.middleware.DebugToolbarMiddleware',
+ #'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
diff --git a/design/sass/_choices.scss b/design/sass/_choices.scss
new file mode 100644
index 0000000..8073d77
--- /dev/null
+++ b/design/sass/_choices.scss
@@ -0,0 +1,382 @@
+.choices-wrapper {
+ max-width: inherit;
+}
+.choices-wrapper-notebooks {
+ width: 190px;
+}
+.choices-wrapper-tags {
+ width: 160px;
+ margin-left: 2rem;
+ .choices__list--dropdown {
+ width: 109%;
+ padding-right: 1px;
+ }
+}
+.choices {
+ position: relative;
+ margin-bottom: 24px;
+ font-size: 16px;
+
+ &:focus {
+ outline: none;
+ }
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ &.is-disabled {
+ .choices__inner, .choices__input {
+ background-color: #eaeaea;
+ cursor: not-allowed;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
+
+ .choices__item {
+ cursor: not-allowed;
+ }
+ }
+
+ &[data-type*=select-one] {
+ cursor: pointer;
+
+ .choices__inner {
+ padding-bottom: 7.5px;
+ }
+
+ .choices__input {
+ display: block;
+ width: 100%;
+ padding: 10px;
+ border-bottom: 1px solid #ddd;
+ background-color: #fff;
+ margin: 0;
+ }
+
+ .choices__button {
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
+ padding: 0;
+ background-size: 8px;
+ position: absolute;
+ top: 50%;
+ right: 0;
+ margin-top: -10px;
+ margin-right: 25px;
+ height: 20px;
+ width: 20px;
+ border-radius: 10em;
+ opacity: .5;
+
+ &:focus, &:hover {
+ opacity: 1;
+ }
+
+ &:focus {
+ box-shadow: 0 0 0 2px #00bcd4;
+ }
+ }
+
+ &:after {
+ content: "";
+ height: 0;
+ width: 0;
+ border-style: solid;
+ border-color: #333 transparent transparent transparent;
+ border-width: 5px;
+ position: absolute;
+ right: 11.5px;
+ top: 50%;
+ margin-top: -2.5px;
+ pointer-events: none;
+ }
+
+ &.is-open:after {
+ border-color: transparent transparent #333 transparent;
+ margin-top: -7.5px;
+ }
+
+ &[dir=rtl] {
+ &:after {
+ left: 11.5px;
+ right: auto;
+ }
+
+ .choices__button {
+ right: auto;
+ left: 0;
+ margin-left: 25px;
+ margin-right: 0;
+ }
+ }
+ }
+
+ &[data-type*=select-multiple] .choices__inner, &[data-type*=text] .choices__inner {
+ cursor: text;
+ }
+
+ &[data-type*=select-multiple] .choices__button, &[data-type*=text] .choices__button {
+ position: relative;
+ display: inline-block;
+ margin: 0 -4px 0 8px;
+ padding-left: 16px;
+ border-left: 1px solid #008fa1;
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
+ background-size: 8px;
+ width: 8px;
+ line-height: 1;
+ opacity: .75;
+ border-radius: 0;
+ }
+
+ &[data-type*=select-multiple] .choices__button {
+ &:focus, &:hover {
+ opacity: 1;
+ }
+ }
+
+ &[data-type*=text] .choices__button {
+ &:focus, &:hover {
+ opacity: 1;
+ }
+ }
+}
+
+.choices__inner {
+ display: inline-block;
+ vertical-align: top;
+ width: 100%;
+ background-color: #f9f9f9;
+ padding: 7.5px 7.5px 3.75px;
+ border: 1px solid #ddd;
+ border-radius: 2.5px;
+ font-size: 14px;
+ overflow: hidden;
+}
+
+.is-focused .choices__inner {
+ border-color: #b7b7b7;
+}
+
+.is-open .choices__inner {
+ border-color: #b7b7b7;
+ border-radius: 2.5px 2.5px 0 0;
+}
+
+.is-flipped.is-open .choices__inner {
+ border-radius: 0 0 2.5px 2.5px;
+}
+
+.choices__list {
+ margin: 0;
+ padding-left: 0;
+ min-width: inherit;
+ list-style: none;
+}
+
+.choices__list--single {
+ display: inline-block;
+ padding: 4px 16px 4px 4px;
+ width: 100%;
+}
+
+[dir=rtl] .choices__list--single {
+ padding-right: 4px;
+ padding-left: 16px;
+}
+
+.choices__list--single .choices__item {
+ width: 100%;
+}
+
+.choices__list--multiple {
+ display: inline;
+
+ .choices__item {
+ display: inline-block;
+ vertical-align: middle;
+ border-radius: 20px;
+ padding: 4px 10px;
+ font-size: 12px;
+ font-weight: 500;
+ margin-right: 3.75px;
+ margin-bottom: 3.75px;
+ background-color: #00bcd4;
+ border: 1px solid #00a5bb;
+ color: #fff;
+ word-break: break-all;
+
+ &[data-deletable] {
+ padding-right: 5px;
+ }
+ }
+}
+
+[dir=rtl] .choices__list--multiple .choices__item {
+ margin-right: 0;
+ margin-left: 3.75px;
+}
+
+.choices__list--multiple .choices__item.is-highlighted {
+ background-color: #00a5bb;
+ border: 1px solid #008fa1;
+}
+
+.is-disabled .choices__list--multiple .choices__item {
+ background-color: #aaa;
+ border: 1px solid #919191;
+}
+
+.choices__list--dropdown {
+ display: none;
+ z-index: 1;
+ position: absolute;
+ width: 108%;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ top: 100%;
+ margin-top: -1px;
+ border-bottom-left-radius: 2.5px;
+ border-bottom-right-radius: 2.5px;
+ overflow: hidden;
+ word-break: break-all;
+ //padding-right: 1px;
+ &.is-active {
+ display: block;
+ }
+}
+
+.is-open .choices__list--dropdown {
+ border-color: #b7b7b7;
+}
+
+.is-flipped .choices__list--dropdown {
+ top: auto;
+ bottom: 100%;
+ margin-top: 0;
+ margin-bottom: -1px;
+ border-radius: .25rem .25rem 0 0;
+}
+
+.choices__list--dropdown {
+ .choices__list {
+ position: relative;
+ max-height: 300px;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+ will-change: scroll-position;
+ }
+
+ .choices__item {
+ position: relative;
+ padding: 10px;
+ font-size: 14px;
+ }
+}
+
+[dir=rtl] .choices__list--dropdown .choices__item {
+ text-align: right;
+}
+
+@media (min-width: 640px) {
+ .choices__list--dropdown .choices__item--selectable {
+
+ }
+
+ [dir=rtl] .choices__list--dropdown .choices__item--selectable {
+ text-align: right;
+ padding-left: 100px;
+ padding-right: 10px;
+
+ &:after {
+ right: auto;
+ left: 10px;
+ }
+ }
+}
+
+.choices__list--dropdown .choices__item--selectable.is-highlighted {
+ background-color: #f2f2f2;
+
+ &:after {
+ opacity: .5;
+ }
+}
+
+.choices__item {
+ cursor: default;
+}
+
+.choices__item--selectable {
+ cursor: pointer;
+}
+
+.choices__item--disabled {
+ cursor: not-allowed;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ opacity: .5;
+}
+
+.choices__heading {
+ font-weight: 600;
+ font-size: 12px;
+ padding: 10px;
+ border-bottom: 1px solid #f7f7f7;
+ color: gray;
+}
+
+.choices__button {
+ text-indent: -9999px;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ border: 0;
+ background-color: transparent;
+ background-repeat: no-repeat;
+ background-position: center;
+ cursor: pointer;
+
+ &:focus {
+ outline: none;
+ }
+}
+
+.choices__input {
+ display: inline-block;
+ vertical-align: baseline;
+ background-color: #f9f9f9;
+ font-size: 14px;
+ margin-bottom: 5px;
+ border: 0;
+ border-radius: 0;
+ max-width: 100%;
+ padding: 4px 0 4px 2px;
+
+ &:focus {
+ outline: 0;
+ }
+}
+
+[dir=rtl] .choices__input {
+ padding-right: 2px;
+ padding-left: 0;
+}
+
+.choices__placeholder {
+ opacity: .5;
+}
+
+.choices {
+ &[data-type*=select-multiple] .choices__input.is-hidden, &[data-type*=select-one] .choices__input.is-hidden {
+ display: none;
+ }
+}
+
+.choices__input.is-hidden {
+ display: none;
+}
diff --git a/design/sass/_forms.scss b/design/sass/_forms.scss
index 152e0ac..f9b8b21 100644
--- a/design/sass/_forms.scss
+++ b/design/sass/_forms.scss
@@ -16,18 +16,45 @@ form fieldset label {
-o-transform: translate3d(10px, 100%);
transform: translate3d(10px, 100%);
@include fontsize(14);
+ @include fancy_sans;
color: lighten($body_font_color, 25);
line-height: 14px;
top: .7rem;
left: .75rem;
z-index: 1;
}
-input {
+input, .textarea-rounded {
border: 1px solid #b3b3b3;
border-radius: 4px;
padding: 2.2rem 0 .75rem .75rem;
width: 99%;
@include fontsize(24);
+ @include fancy_sans;
+}
+.file-upload-fieldset {
+ border: 1px solid #b3b3b3;
+ border-radius: 4px;
+ padding: 6px 0 0 4px;
+ label {
+ position: relative;
+ display: block;
+ margin-bottom: 1rem;
+ }
+ .file-upload {
+ position: relative;
+ overflow: hidden;
+ margin: 10px;
+ }
+ .file-upload input.upload {
+ position: absolute;
+ top: 0;
+ right: 0;
+ margin: 0;
+ font-size: 20px;
+ cursor: pointer;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ }
}
form .error input {
border: 1px solid $link_color;
@@ -90,6 +117,15 @@ table {
@include fontsize(10);
@include smcaps;
}
+.btn-more {
+ padding: 5px 7px;
+ border: none;
+ outline: $link_color;
+ background: $body_font_light !important;
+ &:hover {
+ border: none; //1px solid;
+ }
+}
.btn-subtle {
padding: 3px 5px;
border: none; //1px solid $body_font_light;
diff --git a/design/sass/_global.scss b/design/sass/_global.scss
index 41a1682..ff23500 100644
--- a/design/sass/_global.scss
+++ b/design/sass/_global.scss
@@ -207,12 +207,19 @@ h3 {
.vertical li {
display: block;
}
+.strong {
+ @include fancy_sans_bold;
+ font-weight: 500;
+}
.block {
display: block;
}
.inline-block {
display: inline-block;
}
+.inline{
+ display: inline;
+}
.single-col {
display: block;
@include constrain(66%);
@@ -233,6 +240,15 @@ h3 {
.float-right {
float: right;
}
+.float-left {
+ float: left;
+}
+.row-wrapper {
+ @extends %clearfix;
+}
+.space-between {
+ justify-content: space-between;
+}
//************** other global classes ************************
.sans {
@include generic_sans;
diff --git a/design/sass/_header.scss b/design/sass/_header.scss
index 8df6667..1214f9a 100644
--- a/design/sass/_header.scss
+++ b/design/sass/_header.scss
@@ -4,6 +4,8 @@
background: #fff;
}
header {
+ display: flex;
+ justify-content: space-between;
@include constrain_wide;
.left {
float: left;
@@ -20,6 +22,17 @@ header {
margin-top: -2px;
}
}
+.logo {
+ display: block;
+ margin: 3px 0 0 0;
+ width: 60px;
+ height: 60px;
+ background: #fff url('/media/img/logo-sm.svg') no-repeat;
+ //background: #fff url('/media/img/logo-blk.svg') no-repeat;
+ //background: #fff url('/media/img/logo-org.svg') no-repeat;
+ background-size: 60px 60px;
+ text-align: center;
+}
nav {
letter-spacing: 1px;
margin: 0 0 10px;
diff --git a/design/sass/_notes.scss b/design/sass/_notes.scss
index 59e76ce..df25c3c 100644
--- a/design/sass/_notes.scss
+++ b/design/sass/_notes.scss
@@ -31,10 +31,10 @@ main {
max-width: 320px;
.list-note-preview {
li {
- height: 4.5rem;
+ height: 4.6rem;
}
h4 {
- @include fontsize(15);
+ @include fontsize(18);
}
}
.note-preview {
@@ -65,11 +65,10 @@ main {
list-style-type: none;
li {
@include fontsize(13);
- padding: 8px 0 12px;
+ padding: 16px 0 16px 16px;
min-height: 4.5rem;
box-shadow: 0 -1px 0 #e7e2ee inset;
margin: 0;
- padding: 6px 12px;
&:hover {
background: #f7f7f7;
}
@@ -79,7 +78,7 @@ main {
}
}
h4 {
- @include fontsize(16);
+ @include fontsize(18);
margin: 0;
padding-bottom: 8px;
font-weight: normal;
@@ -249,7 +248,7 @@ main {
height: 20px;
border-radius: 4px;
border: 1px solid $body_font_light;
- #id_color_rgb {
+ #id_color_rgb, .input-color-rgb {
display: block;
text-indent: -1000em;
padding: 0;
@@ -257,6 +256,9 @@ main {
background: transparent;
cursor: pointer;
}
+ .input-color-rgb {
+ display: inline;
+ }
}
#nb-create-form {
.color-picker-fieldset {
@@ -269,9 +271,9 @@ main {
}
}
.nb-name {
- margin: 1rem 2rem 1rem 0;
- width: 90%;
-}
+ margin: 1rem 2rem 1rem 0;
+ width: 90%;
+ }
}
.small-circle {
width: 18px;
@@ -286,7 +288,19 @@ main {
margin: auto 5px;
width: 8px;
}
-
+.small-circle.push-top {
+ margin-top: 24px;
+}
+.note-container .flex-wrapper .hed-small {
+ flex-grow: 1;
+}
+#list-header {
+ margin-top: 10px;
+}
+.choices__list .nb-name {
+ @include fontsize(14);
+ margin: 0 .25rem;
+}
.url-field {
input {
@@ -307,25 +321,100 @@ main {
}
.nb-list {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- margin-top: 0;
}
.nb-list-item {
+ @extend %clearfix;
list-style-type: none;
- padding: 2rem;
- margin: 1rem;
- flex-grow: 1;
+ padding: .5rem 1rem;
+ margin: 1rem 1rem 1rem 0;
border: 1px #e7e2ee solid;
border-radius: 4px;
- min-width: 160px;
+ a {
+ text-decoration: none;
+ color: $body_font_color;
+ }
+ p {
+ margin: 0;
+ @include fontsize(13);
+ @include fancy_sans_bold;
+ text-transform: uppercase;
+
+ }
+ ul {
+ list-style-type: none;
+ padding: 0;
+ margin-left: .25rem;
+ margin-top: .5rem;
+ position: relative;
+ overflow-y: hidden;
+ .more {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ margin: 0 ;
+ padding: 15px 0 0 0;
+ /* "transparent" only works here because == rgba(0,0,0,0) */
+ background-image: linear-gradient(to bottom, transparent, white);
+ }
+ li {
+
+ }
+ }
+ .nb-name {
+ flex-grow: 1;
+ margin: 0;
+ a {
+ line-height: 2.3;
+ @include fontsize(22);
+ }
+ }
+ .tags {
+ @include fontsize(13);
+ @include fancy_sans;
+ text-transform: uppercase;
+ margin: 1rem 0 0 .25rem;
+ ul {
+ @include fancy_sans;
+ text-transform: none;
+ }
+
+ }
+ .trash {
+ margin-top: 4px;
+ color: #333;
+ }
}
.color-picker-inner {
width: 100%;
height: 100%;
}
+.slideup, .slidedown {
+ height: 120px;
+ overflow-y: hidden;
+ -webkit-transition: height .5s ease-in;
+ -moz-transition: height .5s ease-in;
+ -o-transition: height .5s ease-in;
+ transition: height .5s ease-in;
+}
+.slidedown {
+ height: 220px;
+ max-height: 260px;
+}
+.newnnbslideup, .newnbslidedown {
+ height: 0px;
+ overflow-y: hidden;
+ -webkit-transition: height .5s ease-in;
+ -moz-transition: height .5s ease-in;
+ -o-transition: height .5s ease-in;
+ transition: height .5s ease-in;
+}
+.newnbslidedown {
+ height: 220px;
+ max-height: 260px;
+}
+
.dropmenu-search {
margin: 0;
padding: 0;
diff --git a/design/sass/screenv1.scss b/design/sass/screenv1.scss
index de2593e..b55f9d9 100644
--- a/design/sass/screenv1.scss
+++ b/design/sass/screenv1.scss
@@ -3,6 +3,7 @@
@import "_queries.scss";
@import "_global.scss";
@import "_icons.scss";
+@import "_choices.scss";
@import "_header.scss";
@import "_footer.scss";
@import "_forms.scss";
diff --git a/design/templates/accounts/change-settings.html b/design/templates/accounts/change-settings.html
new file mode 100644
index 0000000..a6e6ea6
--- /dev/null
+++ b/design/templates/accounts/change-settings.html
@@ -0,0 +1,33 @@
+{% extends 'base.html' %}
+{% block content %}
+<main class="single-col">
+<h1>Update Your Account Settings</h1>
+<form action="" method="POST" enctype="multipart/form-data">{% csrf_token %}
+ {% for field in form %}
+ <fieldset {% if field.name == 'photo' %}class="file-upload-fieldset"{%endif%}>{% if field.name == 'photo' %}
+ {{field.label_tag}}
+ <div class="flex-wrapper">
+ <div id="file-upload-wrapper" class="file-upload btn">
+ <span>Upload</span>
+ <input type="file" name="photo" class="upload" accept="image/*" id="id_photo">
+ </div>
+ <span id="filename"></span>
+ </div>
+ {% else %}
+ {{field.label_tag}}
+ {{field}}
+ {%endif%}</fieldset>
+ {% endfor %}
+<p><input class="btn btn-inline note-save" value="Save" type="submit" /></p>
+</form>
+</main>
+<script>
+if (typeof(document.getElementById('id_photo')) != 'undefined' && document.getElementById('id_photo') != null) {
+ var input = document.getElementById('id_photo');
+ input.fname = document.getElementById('filename');
+ input.addEventListener('change', function(e){
+ e.target.fname.innerHTML = e.target.value.split("\\")[2];
+ });
+}
+</script>
+{% endblock %}
diff --git a/design/templates/accounts/profile.html b/design/templates/accounts/profile.html
index e8ab65e..4e52da1 100644
--- a/design/templates/accounts/profile.html
+++ b/design/templates/accounts/profile.html
@@ -31,22 +31,12 @@
<tr>
<th scope="row">Bio</th>
<td colspan="2">{{object.bio}}<td>
- <td class="text-right"><a href="/settings/change-bio/" class="btn">Change</a></td>
+ <td class="text-right"><a href="/settings/change-profile/" class="btn">Change</a></td>
</tr>
<tr>
<th scope="row">Photo</th>
<td colspan="2">{{object.photo}}<td>
- <td class="text-right"><a href="/settings/change-photo/" class="btn">Change</a></td>
- </tr>
- <tr>
- <th scope="row">Website</th>
- <td colspan="2">{{object.website}}<td>
- <td class="text-right"><a href="/settings/change-website/" class="btn">Change</a></td>
- </tr>
- <tr>
- <th scope="row">Location</th>
- <td colspan="2">{{object.location}}<td>
- <td class="text-right"><a href="/settings/change-location/" class="btn">Change</a></td>
+ <td class="text-right"><a href="/settings/change-profile/" class="btn">Change</a></td>
</tr>
</tbody>
</table>
diff --git a/design/templates/base.html b/design/templates/base.html
index adcf599..e02719b 100644
--- a/design/templates/base.html
+++ b/design/templates/base.html
@@ -51,7 +51,7 @@
<li><a href="{% url 'forum:topic-list' %}" title="View the TKNote Forum">Community</a></li>
<li><a href="{% url 'pages' slug='tour' %}" title="">Tour</a></li>
<li><a href="{% url 'pages' slug='howto' %}" title="">How to</a></li>{% if not request.user.is_anonymous %}
- <li><a id="account-menu" href="{% url 'settings' %}" title="">Account</a>
+ <li><a id="account-menu" href="{% url 'accounts:settings' %}" title="">Account</a>
<div id="user-menu" class="dropmenu" tabindex="-1">
<ul id="user-menu-list" class="list-style-none vertical">
<li><a href="/settings/" class="">Account settings</a></li>
diff --git a/design/templates/notes/notebook_detail.html b/design/templates/notes/notebook_detail.html
index 37c8f8a..49717ca 100644
--- a/design/templates/notes/notebook_detail.html
+++ b/design/templates/notes/notebook_detail.html
@@ -7,14 +7,15 @@
{% block content %}
<main>
<article class="note-container single-col">
+ {% include "notes/partials/list_header.html" with notebook_list=notebook_list tag_list=tag_list %}
<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%}>
- <input type="text" name="color_rgb" value="{{form.instance.color_rgb}}" maxlength="20" id="id_color_rgb">
+ <fieldset class="color-picker-fieldset" id="color-picker" {% if object.color_rgb %}style="background-color: {{object.color_rgb}}; border: none;"{%endif%}>
+ <input type="text" name="color_rgb" value="{{object.color_rgb}}" maxlength="20" id="id_color_rgb">
{% if field.errors %}{{field.errors}}{% endif %}
</fieldset>{% else %}
<fieldset class="hide">
@@ -33,19 +34,6 @@
{%endif%}
</div>
- <form id="new-note-form" action="{% url 'notebook-api-list' %}" method="post" class="hide">
- <label>Create a new notebook</label>
- {% csrf_token %}
- {{ form.non_field_errors }}
- {% for field in form %}
- <fieldset class="" id="fs-{{field.name}}" >
- {{field.label_tag}}
- {{field}}
- {% if field.errors %}{{field.errors}}{% endif %}
- </fieldset>
- {% endfor %}
- <p><input id="btn-js-hide" class="btn btn-inline" value="create" type="submit" /></p>
- </form>
<ul class="list-note-preview">{% for object in object.note_set.all %}
{% include "notes/partials/note_list.html" with object=object hidecolor=True hidenotebook=True %}
{% endfor %}</ul>
diff --git a/design/templates/notes/notebook_list.html b/design/templates/notes/notebook_list.html
index 6f25f62..5f1220f 100644
--- a/design/templates/notes/notebook_list.html
+++ b/design/templates/notes/notebook_list.html
@@ -6,32 +6,69 @@
{% endblock %}
{% block content %}
<main>
- <article class="note-container">
- <h2 class="hed-small top-margin-0">Add a Notebook</h2>
- {% include 'notes/partials/notebook_form.html' with form=form %}
+ <article id="nb-list-home" class="note-container">
+ <div class="flex-wrapper">
<h1 class="hed-small">Notebooks</h1>
-
+ <a class="circle plus small-circle modal-open push-top" href="/nb/" id="add_id_notebook" data-modal-hed-class="notebook" data-modal-hed="Add a New Notebook">New</a>
+ </div>
+ {% 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 %}
+ <div id="notebook-wrapper">
+ {% include 'notes/partials/notebook_form.html' with form=form url='' %}
+ </div>
<ul class="nb-list">{% for form in notebook_form_list %}
<li class="nb-list-item">
- <form action="{% url 'notebook-api-detail' form.instance.id %}" method="PUT">{% for field in form %}{% if field.name == 'color_rgb' %}
- <fieldset class="color-picker-fieldset" id="color-picker-{{forloop.parentloop.counter0}}" {% if form.instance.color_rgb %}style="background-color: {{form.instance.color_rgb}}; border: none;"{%endif%}>
- <input type="text" name="color_rgb" value="{{form.instance.color_rgb}}" maxlength="20" id="id_color_rgb">
+ <form action="{% url 'notebooks:update' form.instance.slug %}" method="POST" name="create" data-method="POST" data-action="">{% csrf_token %}
+ {% for field in form %}{% if field.name == 'color_rgb' %}
+ <div class="flex-wrapper">
+ <fieldset class="fe-color-picker color-picker-fieldset " id="color-picker-{{forloop.parentloop.counter0}}" {% if form.instance.color_rgb %}style="background-color: {{form.instance.color_rgb}}; border: none;"{%endif%}>
+ <input type="text" class="input-color-rgb" name="color_rgb" value="{{form.instance.color_rgb}}" maxlength="20" id="id_color_rgb-{{forloop.parentloop.counter0}}">
{% if field.errors %}{{field.errors}}{% endif %}
</fieldset>
- href="{% url 'notebooks:detail' form.instance.slug %}"
- <h2>{{form.instance.name}}</h2>
- {% else %}
+ <h2 class="nb-name"><a href="{% url 'notebooks:detail' form.instance.slug %}">{{form.instance.name}}</a></h2>
+ <button type="submit" value="trash" class="btn-hollow trash float-right" name="trash">Move to Trash</button>
+ </div>
+ {% elif field.name == 'name' %}
<fieldset>
+ <label for="id_name-{{forloop.parentloop.counter0}}">Notebook Name:</label>
+ <input type="text" name="name" value="{{form.instance.name}}" maxlength="250" required id="id_name-{{forloop.parentloop.counter0}}">
+ </fieldset>
+ {% else %}
{% if field.field.widget.input_type != 'hidden' %}{{field.label_tag}}{% endif %}
{{field}}
{% if field.errors %}{{field.errors}}{% endif %}
- </fieldset>{% endif %}{% endfor %}
+ {% endif %}{% endfor %}
<input id="i-{{forloop.counter0}}" type="submit" class="btn sm" value="Save" >
+
+ <div class="row-wrapper">
+ <p>{{form.instance.note_count}} notes{% if form.instance.note_count > 5 %}, most recent:{%endif%}</p>
+ {% if form.instance.note_count > 0 %}<ul id="n-list-{{forloop.counter0}}" class="n-list{% if form.instance.note_count > 5 %} slideup{%endif%}">{% for note in form.instance.note_set.all %}
+ <li><a href="{{note.get_absolute_url}}">{{note.title}}</a></li>
+ {%endfor%}
+ {% if form.instance.note_count > 5 %}<li class="more"><button type="button" class="btn btn-small btn-more button" id="more-button-{{forloop.counter0}}">More</button></li>{%endif%}
+ </ul>{%endif%}
+ {% if form.instance.tag_list %}<div class="tags">Common tags: <ul class="inline">{% for tag in form.instance.tag_list %}
+ <li class="inline"><a href="{% url 'notes:tags' tag.slug %}">
+ <span class="tag-wrapper" data-bg-color="#{{tag.color_hex}};" >{{tag|title}}</span>
+ </a></li>
+ {%endfor%}</div>{%endif%}
+ <div class="edit-btn-wrapper"><a class="btn btn-hollow btn-nb-edit float-right" id="edit-toggle-btn-{{forloop.counter0}}">Edit</a></div>
+ </div>
</form>
- <div class="edit-btn-wrapper"><a class="btn btn-hollow btn-nb-edit" id="edit-toggle-btn-{{forloop.counter0}}">Edit</a></div>
- <div class="edit-btn-wrapper"><a class="btn btn-hollow btn-nb-trash" id="trash-btn-{{forloop.counter0}}">Trash</a></div>
</li>
{%endfor%}</ul>
+
+
+
+
+
{% comment %}
<ul class="nb-list">{% for object in notebook_list %}
<li class="nb-list-item">
diff --git a/design/templates/notes/notes_detail.html b/design/templates/notes/notes_detail.html
index cce13b7..0099f3d 100644
--- a/design/templates/notes/notes_detail.html
+++ b/design/templates/notes/notes_detail.html
@@ -69,7 +69,8 @@
</aside>-->
</main>
<div class="overlay-content hide" id="js-overlay-notebook">
- {% include 'notes/partials/notebook_form.html' with form=notebook_form %}
+ {% url 'notebook-api-list' as create_url %}
+ {% include 'notes/partials/notebook_form.html' with form=notebook_form url=create_url %}
</div>
{% endblock %}
diff --git a/design/templates/notes/notes_list.html b/design/templates/notes/notes_list.html
index 94e82ec..0799a1c 100644
--- a/design/templates/notes/notes_list.html
+++ b/design/templates/notes/notes_list.html
@@ -1,42 +1,20 @@
{% extends 'base.html' %}
-
{% block content %}
<main>
<div class="note-container">
+ {% include "notes/partials/list_header.html" with notebook_list=notebook_list tag_list=tag_list %}
<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>
+ <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>
- <div id="notebook-drop-menu" class="dropmenu dropmenu-search">
- <div class="dropmenu-search-wrapper">
- <input class="search" autocapitalize="off" autocorrect="off" type="text" autocomplete="off" tabindex="-1" spellcheck="false" placeholder="Search..." id="notebook-input" data-list="#notebook-list" >
- <!--<svg class="fa d-icon d-icon-search svg-icon filter-icon svg-string" xmlns="http://www.w3.org/2000/svg"><use xlink:href="#search"></use></svg>-->
- </div>
- <ul class="list dropmenu-list list-style-none notebook-list" id="notebook-list">{% for object in notebook_list %}
- <li ><a class="name" href="{{object.get_absolute_url}}">{{object.name}} - {{object.note_count}}</a></li>
- {%endfor%}</ul>
- </div>
-
- <h6 class="bottom-margin-0 inline-block"><button id="tags-drop-btn" class="btn btn-light btn-drop-menu">Tags</button></h6>
- <div id="tags-drop-menu" class="dropmenu dropmenu-search">
- <div class="dropmenu-search-wrapper">
- <input class="search" autocapitalize="off" autocorrect="off" type="text" autocomplete="off" tabindex="-1" spellcheck="false" placeholder="Search..." id="tags-input" data-list="#tags-list" >
- <!--<svg class="fa d-icon d-icon-search svg-icon filter-icon svg-string" xmlns="http://www.w3.org/2000/svg"><use xlink:href="#search"></use></svg>-->
- </div>
- <ul class="list dropmenu-list list-style-none notebook-list" id="tags-list">{% for object in tag_list %}
- <li><a href="{{object.get_absolute_url}}">{{object.name}} - {{object.note_count}}</a></li>
- {%endfor%}</ul>
- </div>
</div>
{%comment%} <label for="choices-single-default">Default</label>
<select class="form-control" data-trigger name="choices-single-default" id="choices-single-default" placeholder="This is a search placeholder">
@@ -73,3 +51,5 @@
</div>-->
</main>
{% endblock %}
+{% block jsdomready %}
+{% endblock %}
diff --git a/design/templates/notes/partials/list_header.html b/design/templates/notes/partials/list_header.html
new file mode 100644
index 0000000..5d0edc1
--- /dev/null
+++ b/design/templates/notes/partials/list_header.html
@@ -0,0 +1,19 @@
+{% block jsinclude %}
+ <script>
+ window.nbdata = [ {%spaceless%}{% for object in notebook_list %} {value: '{{object.get_absolute_url}}', label: '<span class="color-box" style="background-color: {{object.color_rgb}}"></span><span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}' },{%endfor%} {value: '/nb/', label: '<span class="strong nb-name">All Notebooks</span>', selected: true, },{%endspaceless%}
+ ]
+ window.tagdata = [ {% for object in tag_list %} {value: '{{object.get_absolute_url}}', label: '{% if object.color_rgb %}<span class="color-box" style="background-color: {{object.color_rgb}}"></span>{%endif%}<span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}' },{%endfor%} {value: '/t/', label: '<span class="strong nb-name">All Tags</span>', selected: true, },
+ ]
+ </script>
+<script src="/media/js/choices.min.js"></script>
+{%endblock%}
+ <div id="list-header">
+ <div id="choices-container" class="flex-wrapper">
+ <ul class="list dropmenu-list list-style-none notebook-list" id="notebook-list">{% for object in notebook_list %}
+ <li ><a class="name" href="{{object.get_absolute_url}}"><span class="color-box" style="background-color: {{object.color_rgb}}"></span><span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}</a></li>
+ {%endfor%}</ul>
+ <ul class="list dropmenu-list list-style-none notebook-list" id="tags-list">{% for object in tag_list %}
+ <li><a href="{{object.get_absolute_url}}">{% if object.color_rgb %}<span class="color-box" style="background-color: {{object.color_rgb}}"></span>{%endif%}<span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}</a></li>
+ {%endfor%}</ul>
+ </div>
+ </div>
diff --git a/design/templates/notes/partials/notebook_form.html b/design/templates/notes/partials/notebook_form.html
index fae6c40..1e51e9c 100644
--- a/design/templates/notes/partials/notebook_form.html
+++ b/design/templates/notes/partials/notebook_form.html
@@ -1,4 +1,4 @@
-<form id="nb-create-form" action="{% url 'notebook-api-list' %}" method="POST">{% csrf_token %}
+<form id="nb-create-form" action="{{url}}" method="POST">{% csrf_token %}
<div class="alert" id="non-field-errors">{{ form.non_field_errors }}</div>
<div class="flex-wrapper flex-inner">
{% for field in form %}{% if field.name == 'color_rgb' %}
@@ -15,5 +15,5 @@
{% endfor %}
<h1 class="notebook-title" id="nb-title">{{object.name}}</h1>
</div>
- <input id="notebook-form-submit" type="submit" class="btn sm" value="Save" >
+ <input id="notebook-form-submit" name="create" type="submit" class="btn sm" value="Save" >
</form>
diff --git a/scripts/babel.config.js b/scripts/babel.config.js
index 0280c3d..a5d3541 100644
--- a/scripts/babel.config.js
+++ b/scripts/babel.config.js
@@ -1,16 +1,5 @@
const presets = [
- [
- "@babel/env",
- {
- targets: {
- edge: "15",
- firefox: "40",
- chrome: "47",
- safari: "10.1",
- },
- useBuiltIns: "usage",
- },
- ],
+ ["@babel/preset-env", {"modules": false}]
];
module.exports = { presets };
diff --git a/scripts/package.json b/scripts/package.json
index 4b55662..6edaf7b 100644
--- a/scripts/package.json
+++ b/scripts/package.json
@@ -21,7 +21,7 @@
"devDependencies": {
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
- "@babel/preset-env": "^7.1.6",
+ "@babel/preset-env": "^7.2.3",
"@babel/standalone": "^7.2.5",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"babel-plugin-transform-runtime": "^6.23.0",
diff --git a/scripts/src/account-edit.js b/scripts/src/account-edit.js
new file mode 100644
index 0000000..c9d3e9a
--- /dev/null
+++ b/scripts/src/account-edit.js
@@ -0,0 +1 @@
+getElementById('FileField').value = getElementById('file-upload-wrapper').value;
diff --git a/scripts/src/note-edit.js b/scripts/src/note-edit.js
index 3d01794..390b93d 100644
--- a/scripts/src/note-edit.js
+++ b/scripts/src/note-edit.js
@@ -75,6 +75,8 @@ function edit_note(btn, form, title, quill, qcontainer, url){
var modal = modalBox(saveModal);
document.getElementById('close-btn').classList.add('hide');
//send the request to the REST API
+ console.log(request);
+ console.log(form);
request.send(new FormData(form));
}
title.setAttribute('contenteditable', false);
@@ -99,7 +101,8 @@ function notebookCreate(form) {
request.open('POST', url);
var csrftoken = getCookie('csrftoken');
request.setRequestHeader('X-CSRFToken', csrftoken);
- request.setRequestHeader('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest');
+ request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText);
@@ -161,9 +164,8 @@ if (typeof(document.getElementById('note-edit-form')) != 'undefined' && document
e.preventDefault();
edit_note(e.target, form, title, quill, qcontainer, window.location.href );
}, false);
- var notebook_form = document.getElementById('nb-create-form');
- initColorPicker(notebook_form);
var notebookAddForm = document.getElementById('nb-create-form');
+ initColorPicker(notebookAddForm);
ajaxHijack(notebookAddForm, notebookCreate)
var create_notebook_btn = document.getElementById('add_id_notebook');
addHandler(create_notebook_btn);
diff --git a/scripts/src/note-list.js b/scripts/src/note-list.js
index 90c89d9..2b82da1 100644
--- a/scripts/src/note-list.js
+++ b/scripts/src/note-list.js
@@ -1,33 +1,39 @@
-/*! List.js v1.5.0 (http://listjs.com) by Jonny Strömberg (http://javve.com) */
-var List=function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=11)}([function(t,e,r){function n(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}var i=r(4),s=/\s+/;Object.prototype.toString;t.exports=function(t){return new n(t)},n.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array(),r=i(e,t);return~r||e.push(t),this.el.className=e.join(" "),this},n.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=i(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},n.prototype.toggle=function(t,e){return this.list?("undefined"!=typeof e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):("undefined"!=typeof e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},n.prototype.array=function(){var t=this.el.getAttribute("class")||"",e=t.replace(/^\s+|\s+$/g,""),r=e.split(s);return""===r[0]&&r.shift(),r},n.prototype.has=n.prototype.contains=function(t){return this.list?this.list.contains(t):!!~i(this.array(),t)}},function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",i=window.removeEventListener?"removeEventListener":"detachEvent",s="addEventListener"!==n?"on":"",a=r(5);e.bind=function(t,e,r,i){t=a(t);for(var o=0;o<t.length;o++)t[o][n](s+e,r,i||!1)},e.unbind=function(t,e,r,n){t=a(t);for(var o=0;o<t.length;o++)t[o][i](s+e,r,n||!1)}},function(t,e){t.exports=function(t){return function(e,r,n){var i=this;this._values={},this.found=!1,this.filtered=!1;var s=function(e,r,n){if(void 0===r)n?i.values(e,n):i.values(e);else{i.elm=r;var s=t.templater.get(i,e);i.values(s)}};this.values=function(e,r){if(void 0===e)return i._values;for(var n in e)i._values[n]=e[n];r!==!0&&t.templater.set(i,i.values())},this.show=function(){t.templater.show(i)},this.hide=function(){t.templater.hide(i)},this.matching=function(){return t.filtered&&t.searched&&i.found&&i.filtered||t.filtered&&!t.searched&&i.filtered||!t.filtered&&t.searched&&i.found||!t.filtered&&!t.searched},this.visible=function(){return!(!i.elm||i.elm.parentNode!=t.list)},s(e,r,n)}}},function(t,e){var r=function(t,e,r){return r?t.getElementsByClassName(e)[0]:t.getElementsByClassName(e)},n=function(t,e,r){return e="."+e,r?t.querySelector(e):t.querySelectorAll(e)},i=function(t,e,r){for(var n=[],i="*",s=t.getElementsByTagName(i),a=s.length,o=new RegExp("(^|\\s)"+e+"(\\s|$)"),l=0,u=0;l<a;l++)if(o.test(s[l].className)){if(r)return s[l];n[u]=s[l],u++}return n};t.exports=function(){return function(t,e,s,a){return a=a||{},a.test&&a.getElementsByClassName||!a.test&&document.getElementsByClassName?r(t,e,s):a.test&&a.querySelector||!a.test&&document.querySelector?n(t,e,s):i(t,e,s)}}()},function(t,e){var r=[].indexOf;t.exports=function(t,e){if(r)return t.indexOf(e);for(var n=0;n<t.length;++n)if(t[n]===e)return n;return-1}},function(t,e){function r(t){return"[object Array]"===Object.prototype.toString.call(t)}t.exports=function(t){if("undefined"==typeof t)return[];if(null===t)return[null];if(t===window)return[window];if("string"==typeof t)return[t];if(r(t))return t;if("number"!=typeof t.length)return[t];if("function"==typeof t&&t instanceof Function)return[t];for(var e=[],n=0;n<t.length;n++)(Object.prototype.hasOwnProperty.call(t,n)||n in t)&&e.push(t[n]);return e.length?e:[]}},function(t,e){t.exports=function(t){return t=void 0===t?"":t,t=null===t?"":t,t=t.toString()}},function(t,e){t.exports=function(t){for(var e,r=Array.prototype.slice.call(arguments,1),n=0;e=r[n];n++)if(e)for(var i in e)t[i]=e[i];return t}},function(t,e){t.exports=function(t){var e=function(r,n,i){var s=r.splice(0,50);i=i||[],i=i.concat(t.add(s)),r.length>0?setTimeout(function(){e(r,n,i)},1):(t.update(),n(i))};return e}},function(t,e){t.exports=function(t){return t.handlers.filterStart=t.handlers.filterStart||[],t.handlers.filterComplete=t.handlers.filterComplete||[],function(e){if(t.trigger("filterStart"),t.i=1,t.reset.filter(),void 0===e)t.filtered=!1;else{t.filtered=!0;for(var r=t.items,n=0,i=r.length;n<i;n++){var s=r[n];e(s)?s.filtered=!0:s.filtered=!1}}return t.update(),t.trigger("filterComplete"),t.visibleItems}}},function(t,e,r){var n=(r(0),r(1)),i=r(7),s=r(6),a=r(3),o=r(19);t.exports=function(t,e){e=e||{},e=i({location:0,distance:100,threshold:.4,multiSearch:!0,searchClass:"fuzzy-search"},e);var r={search:function(n,i){for(var s=e.multiSearch?n.replace(/ +$/,"").split(/ +/):[n],a=0,o=t.items.length;a<o;a++)r.item(t.items[a],i,s)},item:function(t,e,n){for(var i=!0,s=0;s<n.length;s++){for(var a=!1,o=0,l=e.length;o<l;o++)r.values(t.values(),e[o],n[s])&&(a=!0);a||(i=!1)}t.found=i},values:function(t,r,n){if(t.hasOwnProperty(r)){var i=s(t[r]).toLowerCase();if(o(i,n,e))return!0}return!1}};return n.bind(a(t.listContainer,e.searchClass),"keyup",function(e){var n=e.target||e.srcElement;t.search(n.value,r.search)}),function(e,n){t.search(e,n,r.search)}}},function(t,e,r){var n=r(18),i=r(3),s=r(7),a=r(4),o=r(1),l=r(6),u=r(0),c=r(17),f=r(5);t.exports=function(t,e,h){var d,v=this,m=r(2)(v),g=r(8)(v),p=r(12)(v);d={start:function(){v.listClass="list",v.searchClass="search",v.sortClass="sort",v.page=1e4,v.i=1,v.items=[],v.visibleItems=[],v.matchingItems=[],v.searched=!1,v.filtered=!1,v.searchColumns=void 0,v.handlers={updated:[]},v.valueNames=[],v.utils={getByClass:i,extend:s,indexOf:a,events:o,toString:l,naturalSort:n,classes:u,getAttribute:c,toArray:f},v.utils.extend(v,e),v.listContainer="string"==typeof t?document.getElementById(t):t,v.listContainer&&(v.list=i(v.listContainer,v.listClass,!0),v.parse=r(13)(v),v.templater=r(16)(v),v.search=r(14)(v),v.filter=r(9)(v),v.sort=r(15)(v),v.fuzzySearch=r(10)(v,e.fuzzySearch),this.handlers(),this.items(),this.pagination(),v.update())},handlers:function(){for(var t in v.handlers)v[t]&&v.on(t,v[t])},items:function(){v.parse(v.list),void 0!==h&&v.add(h)},pagination:function(){if(void 0!==e.pagination){e.pagination===!0&&(e.pagination=[{}]),void 0===e.pagination[0]&&(e.pagination=[e.pagination]);for(var t=0,r=e.pagination.length;t<r;t++)p(e.pagination[t])}}},this.reIndex=function(){v.items=[],v.visibleItems=[],v.matchingItems=[],v.searched=!1,v.filtered=!1,v.parse(v.list)},this.toJSON=function(){for(var t=[],e=0,r=v.items.length;e<r;e++)t.push(v.items[e].values());return t},this.add=function(t,e){if(0!==t.length){if(e)return void g(t,e);var r=[],n=!1;void 0===t[0]&&(t=[t]);for(var i=0,s=t.length;i<s;i++){var a=null;n=v.items.length>v.page,a=new m(t[i],void 0,n),v.items.push(a),r.push(a)}return v.update(),r}},this.show=function(t,e){return this.i=t,this.page=e,v.update(),v},this.remove=function(t,e,r){for(var n=0,i=0,s=v.items.length;i<s;i++)v.items[i].values()[t]==e&&(v.templater.remove(v.items[i],r),v.items.splice(i,1),s--,i--,n++);return v.update(),n},this.get=function(t,e){for(var r=[],n=0,i=v.items.length;n<i;n++){var s=v.items[n];s.values()[t]==e&&r.push(s)}return r},this.size=function(){return v.items.length},this.clear=function(){return v.templater.clear(),v.items=[],v},this.on=function(t,e){return v.handlers[t].push(e),v},this.off=function(t,e){var r=v.handlers[t],n=a(r,e);return n>-1&&r.splice(n,1),v},this.trigger=function(t){for(var e=v.handlers[t].length;e--;)v.handlers[t][e](v);return v},this.reset={filter:function(){for(var t=v.items,e=t.length;e--;)t[e].filtered=!1;return v},search:function(){for(var t=v.items,e=t.length;e--;)t[e].found=!1;return v}},this.update=function(){var t=v.items,e=t.length;v.visibleItems=[],v.matchingItems=[],v.templater.clear();for(var r=0;r<e;r++)t[r].matching()&&v.matchingItems.length+1>=v.i&&v.visibleItems.length<v.page?(t[r].show(),v.visibleItems.push(t[r]),v.matchingItems.push(t[r])):t[r].matching()?(v.matchingItems.push(t[r]),t[r].hide()):t[r].hide();return v.trigger("updated"),v},d.start()}},function(t,e,r){var n=r(0),i=r(1),s=r(11);t.exports=function(t){var e=function(e,i){var s,o=t.matchingItems.length,l=t.i,u=t.page,c=Math.ceil(o/u),f=Math.ceil(l/u),h=i.innerWindow||2,d=i.left||i.outerWindow||0,v=i.right||i.outerWindow||0;v=c-v,e.clear();for(var m=1;m<=c;m++){var g=f===m?"active":"";r.number(m,d,v,f,h)?(s=e.add({page:m,dotted:!1})[0],g&&n(s.elm).add(g),a(s.elm,m,u)):r.dotted(e,m,d,v,f,h,e.size())&&(s=e.add({page:"...",dotted:!0})[0],n(s.elm).add("disabled"))}},r={number:function(t,e,r,n,i){return this.left(t,e)||this.right(t,r)||this.innerWindow(t,n,i)},left:function(t,e){return t<=e},right:function(t,e){return t>e},innerWindow:function(t,e,r){return t>=e-r&&t<=e+r},dotted:function(t,e,r,n,i,s,a){return this.dottedLeft(t,e,r,n,i,s)||this.dottedRight(t,e,r,n,i,s,a)},dottedLeft:function(t,e,r,n,i,s){return e==r+1&&!this.innerWindow(e,i,s)&&!this.right(e,n)},dottedRight:function(t,e,r,n,i,s,a){return!t.items[a-1].values().dotted&&(e==n&&!this.innerWindow(e,i,s)&&!this.right(e,n))}},a=function(e,r,n){i.bind(e,"click",function(){t.show((r-1)*n+1,n)})};return function(r){var n=new s(t.listContainer.id,{listClass:r.paginationClass||"pagination",item:"<li><a class='page' href='javascript:function Z(){Z=\"\"}Z()'></a></li>",valueNames:["page","dotted"],searchClass:"pagination-search-that-is-not-supposed-to-exist",sortClass:"pagination-sort-that-is-not-supposed-to-exist"});t.on("updated",function(){e(n,r)}),e(n,r)}}},function(t,e,r){t.exports=function(t){var e=r(2)(t),n=function(t){for(var e=t.childNodes,r=[],n=0,i=e.length;n<i;n++)void 0===e[n].data&&r.push(e[n]);return r},i=function(r,n){for(var i=0,s=r.length;i<s;i++)t.items.push(new e(n,r[i]))},s=function(e,r){var n=e.splice(0,50);i(n,r),e.length>0?setTimeout(function(){s(e,r)},1):(t.update(),t.trigger("parseComplete"))};return t.handlers.parseComplete=t.handlers.parseComplete||[],function(){var e=n(t.list),r=t.valueNames;t.indexAsync?s(e,r):i(e,r)}}},function(t,e){t.exports=function(t){var e,r,n,i,s={resetList:function(){t.i=1,t.templater.clear(),i=void 0},setOptions:function(t){2==t.length&&t[1]instanceof Array?r=t[1]:2==t.length&&"function"==typeof t[1]?(r=void 0,i=t[1]):3==t.length?(r=t[1],i=t[2]):r=void 0},setColumns:function(){0!==t.items.length&&void 0===r&&(r=void 0===t.searchColumns?s.toArray(t.items[0].values()):t.searchColumns)},setSearchString:function(e){e=t.utils.toString(e).toLowerCase(),e=e.replace(/[-[\]{}()*+?.,\\^$|#]/g,"\\$&"),n=e},toArray:function(t){var e=[];for(var r in t)e.push(r);return e}},a={list:function(){for(var e=0,r=t.items.length;e<r;e++)a.item(t.items[e])},item:function(t){t.found=!1;for(var e=0,n=r.length;e<n;e++)if(a.values(t.values(),r[e]))return void(t.found=!0)},values:function(r,i){return!!(r.hasOwnProperty(i)&&(e=t.utils.toString(r[i]).toLowerCase(),""!==n&&e.search(n)>-1))},reset:function(){t.reset.search(),t.searched=!1}},o=function(e){return t.trigger("searchStart"),s.resetList(),s.setSearchString(e),s.setOptions(arguments),s.setColumns(),""===n?a.reset():(t.searched=!0,i?i(n,r):a.list()),t.update(),t.trigger("searchComplete"),t.visibleItems};return t.handlers.searchStart=t.handlers.searchStart||[],t.handlers.searchComplete=t.handlers.searchComplete||[],t.utils.events.bind(t.utils.getByClass(t.listContainer,t.searchClass),"keyup",function(e){var r=e.target||e.srcElement,n=""===r.value&&!t.searched;n||o(r.value)}),t.utils.events.bind(t.utils.getByClass(t.listContainer,t.searchClass),"input",function(t){var e=t.target||t.srcElement;""===e.value&&o("")}),o}},function(t,e){t.exports=function(t){var e={els:void 0,clear:function(){for(var r=0,n=e.els.length;r<n;r++)t.utils.classes(e.els[r]).remove("asc"),t.utils.classes(e.els[r]).remove("desc")},getOrder:function(e){var r=t.utils.getAttribute(e,"data-order");return"asc"==r||"desc"==r?r:t.utils.classes(e).has("desc")?"asc":t.utils.classes(e).has("asc")?"desc":"asc"},getInSensitive:function(e,r){var n=t.utils.getAttribute(e,"data-insensitive");"false"===n?r.insensitive=!1:r.insensitive=!0},setOrder:function(r){for(var n=0,i=e.els.length;n<i;n++){var s=e.els[n];if(t.utils.getAttribute(s,"data-sort")===r.valueName){var a=t.utils.getAttribute(s,"data-order");"asc"==a||"desc"==a?a==r.order&&t.utils.classes(s).add(r.order):t.utils.classes(s).add(r.order)}}}},r=function(){t.trigger("sortStart");var r={},n=arguments[0].currentTarget||arguments[0].srcElement||void 0;n?(r.valueName=t.utils.getAttribute(n,"data-sort"),e.getInSensitive(n,r),r.order=e.getOrder(n)):(r=arguments[1]||r,r.valueName=arguments[0],r.order=r.order||"asc",r.insensitive="undefined"==typeof r.insensitive||r.insensitive),e.clear(),e.setOrder(r);var i,s=r.sortFunction||t.sortFunction||null,a="desc"===r.order?-1:1;i=s?function(t,e){return s(t,e,r)*a}:function(e,n){var i=t.utils.naturalSort;return i.alphabet=t.alphabet||r.alphabet||void 0,!i.alphabet&&r.insensitive&&(i=t.utils.naturalSort.caseInsensitive),i(e.values()[r.valueName],n.values()[r.valueName])*a},t.items.sort(i),t.update(),t.trigger("sortComplete")};return t.handlers.sortStart=t.handlers.sortStart||[],t.handlers.sortComplete=t.handlers.sortComplete||[],e.els=t.utils.getByClass(t.listContainer,t.sortClass),t.utils.events.bind(e.els,"click",r),t.on("searchStart",e.clear),t.on("filterStart",e.clear),r}},function(t,e){var r=function(t){var e,r=this,n=function(){e=r.getItemSource(t.item),e&&(e=r.clearSourceItem(e,t.valueNames))};this.clearSourceItem=function(e,r){for(var n=0,i=r.length;n<i;n++){var s;if(r[n].data)for(var a=0,o=r[n].data.length;a<o;a++)e.setAttribute("data-"+r[n].data[a],"");else r[n].attr&&r[n].name?(s=t.utils.getByClass(e,r[n].name,!0),s&&s.setAttribute(r[n].attr,"")):(s=t.utils.getByClass(e,r[n],!0),s&&(s.innerHTML=""));s=void 0}return e},this.getItemSource=function(e){if(void 0===e){for(var r=t.list.childNodes,n=0,i=r.length;n<i;n++)if(void 0===r[n].data)return r[n].cloneNode(!0)}else{if(/<tr[\s>]/g.exec(e)){var s=document.createElement("tbody");return s.innerHTML=e,s.firstChild}if(e.indexOf("<")!==-1){var a=document.createElement("div");return a.innerHTML=e,a.firstChild}var o=document.getElementById(t.item);if(o)return o}},this.get=function(e,n){r.create(e);for(var i={},s=0,a=n.length;s<a;s++){var o;if(n[s].data)for(var l=0,u=n[s].data.length;l<u;l++)i[n[s].data[l]]=t.utils.getAttribute(e.elm,"data-"+n[s].data[l]);else n[s].attr&&n[s].name?(o=t.utils.getByClass(e.elm,n[s].name,!0),i[n[s].name]=o?t.utils.getAttribute(o,n[s].attr):""):(o=t.utils.getByClass(e.elm,n[s],!0),i[n[s]]=o?o.innerHTML:"");o=void 0}return i},this.set=function(e,n){var i=function(e){for(var r=0,n=t.valueNames.length;r<n;r++)if(t.valueNames[r].data){for(var i=t.valueNames[r].data,s=0,a=i.length;s<a;s++)if(i[s]===e)return{data:e}}else{if(t.valueNames[r].attr&&t.valueNames[r].name&&t.valueNames[r].name==e)return t.valueNames[r];if(t.valueNames[r]===e)return e}},s=function(r,n){var s,a=i(r);a&&(a.data?e.elm.setAttribute("data-"+a.data,n):a.attr&&a.name?(s=t.utils.getByClass(e.elm,a.name,!0),s&&s.setAttribute(a.attr,n)):(s=t.utils.getByClass(e.elm,a,!0),s&&(s.innerHTML=n)),s=void 0)};if(!r.create(e))for(var a in n)n.hasOwnProperty(a)&&s(a,n[a])},this.create=function(t){if(void 0!==t.elm)return!1;if(void 0===e)throw new Error("The list need to have at list one item on init otherwise you'll have to add a template.");var n=e.cloneNode(!0);return n.removeAttribute("id"),t.elm=n,r.set(t,t.values()),!0},this.remove=function(e){e.elm.parentNode===t.list&&t.list.removeChild(e.elm)},this.show=function(e){r.create(e),t.list.appendChild(e.elm)},this.hide=function(e){void 0!==e.elm&&e.elm.parentNode===t.list&&t.list.removeChild(e.elm)},this.clear=function(){if(t.list.hasChildNodes())for(;t.list.childNodes.length>=1;)t.list.removeChild(t.list.firstChild)},n()};t.exports=function(t){return new r(t)}},function(t,e){t.exports=function(t,e){var r=t.getAttribute&&t.getAttribute(e)||null;if(!r)for(var n=t.attributes,i=n.length,s=0;s<i;s++)void 0!==e[s]&&e[s].nodeName===e&&(r=e[s].nodeValue);return r}},function(t,e,r){"use strict";function n(t){return t>=48&&t<=57}function i(t,e){for(var r=(t+="").length,i=(e+="").length,s=0,l=0;s<r&&l<i;){var u=t.charCodeAt(s),c=e.charCodeAt(l);if(n(u)){if(!n(c))return u-c;for(var f=s,h=l;48===u&&++f<r;)u=t.charCodeAt(f);for(;48===c&&++h<i;)c=e.charCodeAt(h);for(var d=f,v=h;d<r&&n(t.charCodeAt(d));)++d;for(;v<i&&n(e.charCodeAt(v));)++v;var m=d-f-v+h;if(m)return m;for(;f<d;)if(m=t.charCodeAt(f++)-e.charCodeAt(h++))return m;s=d,l=v}else{if(u!==c)return u<o&&c<o&&a[u]!==-1&&a[c]!==-1?a[u]-a[c]:u-c;++s,++l}}return r-i}var s,a,o=0;i.caseInsensitive=i.i=function(t,e){return i((""+t).toLowerCase(),(""+e).toLowerCase())},Object.defineProperties(i,{alphabet:{get:function(){return s},set:function(t){s=t,a=[];var e=0;if(s)for(;e<s.length;e++)a[s.charCodeAt(e)]=e;for(o=a.length,e=0;e<o;e++)void 0===a[e]&&(a[e]=-1)}}}),t.exports=i},function(t,e){t.exports=function(t,e,r){function n(t,r){var n=t/e.length,i=Math.abs(o-r);return s?n+i/s:i?1:n}var i=r.location||0,s=r.distance||100,a=r.threshold||.4;if(e===t)return!0;if(e.length>32)return!1;var o=i,l=function(){var t,r={};for(t=0;t<e.length;t++)r[e.charAt(t)]=0;for(t=0;t<e.length;t++)r[e.charAt(t)]|=1<<e.length-t-1;return r}(),u=a,c=t.indexOf(e,o);c!=-1&&(u=Math.min(n(0,c),u),c=t.lastIndexOf(e,o+e.length),c!=-1&&(u=Math.min(n(0,c),u)));var f=1<<e.length-1;c=-1;for(var h,d,v,m=e.length+t.length,g=0;g<e.length;g++){for(h=0,d=m;h<d;)n(g,o+d)<=u?h=d:m=d,d=Math.floor((m-h)/2+h);m=d;var p=Math.max(1,o-d+1),C=Math.min(o+d,t.length)+e.length,y=Array(C+2);y[C+1]=(1<<g)-1;for(var b=C;b>=p;b--){var w=l[t.charAt(b-1)];if(0===g?y[b]=(y[b+1]<<1|1)&w:y[b]=(y[b+1]<<1|1)&w|((v[b+1]|v[b])<<1|1)|v[b+1],y[b]&f){var x=n(g,b-1);if(x<=u){if(u=x,c=b-1,!(c>o))break;p=Math.max(1,2*o-c)}}}if(n(g+1,o)>u)break;v=y}return!(c<0)}}]);
-function initNotebookSearch() {
- var dmenu = document.getElementById('notebook-drop-menu');
- var tmenu = document.getElementById('tags-drop-menu');
- var dbtn = document.getElementById('notebook-drop-btn');
- var tbtn = document.getElementById('tags-drop-btn');
- dbtn.addEventListener('click', menuOpener, false);
- tbtn.addEventListener('click', menuOpener, false);
- dbtn.menu = document.getElementById('notebook-drop-menu');
- tbtn.menu = tmenu;
- var input = document.getElementById('notebook-input');
- var ul = document.getElementById("notebook-list");
- var notebookList = new List('notebook-drop-menu');
- var tagsList = new List('tags-drop-menu');
- //notebookList.on('updated', myFunct, false);
- //tagsList.on('updated', myFunct, false);
- function myFunct(e) {
- console.log('done');
- }
-// Pass single element:
-//var el = document.getElementById('choices-single-default');
-//var resetSimple = new Choices(el);
+function choicePageChanger(value, keyCode){
+ document.location.href = value['detail']['choice']['value'];
}
-function menuOpener(e) {
- e.preventDefault();
- e.target.menu.classList.toggle('active');
- console.log(e.target.menu.classList);
- hideOnClickOutsided(e.target.menu, e.target);
+
+function initChoicesMenu(obj) {
+ var w = document.createElement('div');
+ w.classList.add(...obj.wrapper_classes);
+ var s = document.createElement('select');
+ s.classList.add('form-control');
+ s.setAttribute("name", obj.choices_name);
+ s.setAttribute("id", obj.choices_id);
+ w.appendChild(s);
+ var c = document.getElementById('choices-container');
+ c.appendChild(w);
+ var choices_holder = s
+ var choices = new Choices(choices_holder, {
+ itemSelectText: '',
+ choices: obj.data,
+ });
+ obj.replace_el.classList.add('hide');
+ choices_holder.addEventListener('choice', choicePageChanger);
}
-if (typeof(document.getElementById('notebook-list')) != 'undefined' && document.getElementById('notebook-list') != null) {
- initNotebookSearch();
+
+if (typeof(document.getElementById('choices-container')) != 'undefined' && document.getElementById('choices-container') != null) {
+ initChoicesMenu({
+ data: window.nbdata,
+ wrapper_classes: ['choices-wrapper', 'choices-wrapper-notebooks'],
+ replace_el: document.getElementById('notebook-list'),
+ choices_name: "choices-notebooks",
+ choices_id: "choices-notebooks"
+ });
+ initChoicesMenu({
+ data: window.tagdata,
+ wrapper_classes: ['choices-wrapper', 'choices-wrapper-tags'],
+ replace_el: document.getElementById('tags-list'),
+ choices_name: "choices-tags",
+ choices_id: "choices-tags"
+ });
}
diff --git a/scripts/src/notebook-edit.js b/scripts/src/notebook-edit.js
index 802ec79..7d0aa8f 100644
--- a/scripts/src/notebook-edit.js
+++ b/scripts/src/notebook-edit.js
@@ -19,13 +19,12 @@ function initNotebookEditor() {
btn.classList.remove('hide');
btn.addEventListener('click', function(e){
e.preventDefault();
- edit_notebook(this, title, form, picker, fname, window.url);
+ edit_notebook(title, form, picker, fname, window.url);
}, false);
}
-function initNotebookCreator(btn, title, url) {
- var notebook_form = document.querySelector('#nb-create-form');
- var notebook_form_inputs = notebook_form.getElementsByTagName('input');
- var picker = notebook_form.getElementsByTagName('fieldset')['color-picker'];
+function activatePicker(form, picker) {
+ var inputs = form.getElementsByTagName('input');
+ var picker = picker;
picker.popup = new Picker({
parent: picker,
color: 'blue',
@@ -34,87 +33,82 @@ function initNotebookCreator(btn, title, url) {
editorFormat: 'hex',
onDone: function(color) {
this.settings['parent'].style.backgroundColor = color.rgbString;
- notebook_form_inputs['color_rgb'].value = color.rgbString;
+ inputs['color_rgb'].value = color.rgbString;
},
});
+}
+function initMultiNotebookEditor(notebooks){
+ // Takes an array of elements containing forms
var forms = [];
var btns = [];
- var notebooks = document.getElementsByClassName('nb-list-item');
window.bookediting = false;
for (var i = 0; i < notebooks.length; i++) {
- var fname = notebooks[i].getElementsByTagName('input')['id_form-'+i+'-name'];
+ var nb = notebooks[i];
+ var form = forms[i];
+ var btn = btns[i];
+ // hide the form elements
+ var fname = nb.getElementsByTagName('input')['id_name-'+i];
fname.parentNode.classList.add('hide');
- notebooks[i].getElementsByTagName('input')['i-'+i].classList.add('hide');
- forms[i] = notebooks[i].getElementsByTagName('form')[0];
- forms[i].getElementsByTagName('input')['color_rgb'].disabled = true;
- forms[i].addEventListener('input', function () {
+ nb.getElementsByTagName('input')['i-'+i].classList.add('hide');
+ form = nb.getElementsByTagName('form')[0];
+ form.getElementsByTagName('input')['color_rgb'].disabled = true;
+ form.addEventListener('input', function () {
window.formchange = true;
console.log('adding change');
});
- btns[i] = notebooks[i].getElementsByTagName('a')['edit-toggle-btn-'+i];
- btns[i].addEventListener('click', myFunc, false);
- btns[i].t = notebooks[i].getElementsByTagName('h2')[0];
- btns[i].picker = notebooks[i].getElementsByTagName('fieldset')['color-picker-'+i];
- btns[i].fname = fname;
- btns[i].form = forms[i];
- btns[i].url = forms[i]['action'];
- function myFunc(e) {
+ btn = nb.getElementsByTagName('a')['edit-toggle-btn-'+i];
+ btn.addEventListener('click', clickHandler, false);
+ btn.t = nb.getElementsByTagName('h2')[0].getElementsByTagName('a')[0];
+ btn.picker = nb.getElementsByTagName('fieldset')['color-picker-'+i];
+ btn.fname = fname;
+ btn.form = form;
+ btn.url = form['action'];
+ btn.trash = nb.getElementsByTagName('button')['trash']
+ btn.trash.classList.add('hide')
+ btn.isHidden = true;
+ function clickHandler(e) {
e.preventDefault();
- edit_notebook(e.target, e.target.t, e.target.form, e.target.picker, e.target.fname, e.target.url);
+ e.target.textContent = e.target.isHidden ? 'Save' : 'Edit';
+ e.target.isHidden = !e.target.isHidden;
+ e.target.classList.toggle('save');
+ e.target.trash.classList.toggle('hide');
+ edit_notebook(e.target.t, e.target.form, e.target.picker, e.target.fname, e.target.url, 'POST');
};
+ var more = form.getElementsByTagName('button')['more-button-'+i]
+ if (more !== undefined) {
+ more.slider = form.getElementsByTagName('ul')['n-list-'+i]
+ var isHidden = true;
+ more.addEventListener('click', moreclickHandler, false);
+ function moreclickHandler(e) {
+ console.log(e.target.slider);
+ e.preventDefault();
+ e.target.slider.classList.toggle('slideup');
+ e.target.slider.classList.toggle('slidedown');
+ e.target.textContent = isHidden ? 'Less' : 'More';
+ isHidden = !isHidden;
+ }
+ }
}
}
-function edit_notebook(btn, title, form, picker, fname, url){
+function edit_notebook(title, form, picker, fname, url, method){
+ var method = method || 'PUT';
var form_inputs = form.getElementsByTagName('input');
- console.log(picker);
if (window.bookediting === false) {
- picker.popup= new Picker({
- parent: picker,
- color: 'blue',
- alpha: false,
- //editor: false,
- editorFormat: 'hex',
- onDone: function(color) {
- this.settings['parent'].style.backgroundColor = color.rgbString;
- form_inputs['color_rgb'].value = color.rgbString;
- },
- });
+ activatePicker(form, picker);
title.setAttribute('contenteditable', true);
title.classList.add('highlight');
form_inputs['color_rgb'].disabled = false;
- btn.innerHTML = 'Save';
- btn.classList.add('save');
window.bookediting = true;
window.titlecontents = title.innerHTML;
window.colorcontent = form_inputs['color_rgb'].value;
} else {
if (window.titlecontents !== title.innerHTML || window.colorcontent !== form_inputs['color_rgb'].value || window.formchange) {
- console.log('changed');
- console.log(form_inputs);
fname.value = title.innerHTML;
- //const data = formToJSON(form.elements);
- //console.log(JSON.stringify(data, null, ' '));
- var request = new XMLHttpRequest();
- request.open('PATCH', url);
- var csrftoken = getCookie('csrftoken');
- request.setRequestHeader('X-CSRFToken', csrftoken);
- request.onload = function() {
- if (request.status >= 200 && request.status < 400) {
- console.log(request);
- } else {
- console.log(request);
- console.log('server error');
- }
- };
- request.onerror = function() {
- console.log('error on request');
- };
- request.send(new FormData(form));
+ var data = new FormData(form)
+ getJSONFromDjango(method, url, notebookCallback.bind(null, title), data);
}
title.setAttribute('contenteditable', false);
title.classList.remove('highlight');
- btn.innerHTML = 'Edit';
- btn.classList.remove('save');
form_inputs['color_rgb'].disabled = true;
document.body.focus();
window.bookediting = false;
@@ -122,9 +116,31 @@ function edit_notebook(btn, title, form, picker, fname, url){
}
return false;
}
+function notebookCallback(title, request) {
+ if (request.status >= 200 && request.status < 400) {
+ if (title.href) {
+ var data = JSON.parse(request.responseText);
+ title.href = '/nb/'+ data['notebook']['permalink'];
+ console.log(title.href);
+ }
+ if (window.overlay !== undefined) {
+ window.overlay.destroy();
+ }
+ } else {
+ console.log(request);
+ console.log('server error');
+ }
+}
if (typeof(document.getElementById('nb-edit-form')) != 'undefined' && document.getElementById('nb-edit-form') != null) {
initNotebookEditor();
}
-if (typeof(document.getElementById('nb-create-form')) != 'undefined' && document.getElementById('nb-create-form') != null && document.getElementById('note-edit-form') === null) {
- initNotebookCreator();
+if (typeof(document.getElementById('nb-create-form')) != 'undefined' && document.getElementById('nb-create-form') != null && document.getElementById('nb-list-home') !== null) {
+ var newnotebook = document.getElementById('notebook-wrapper');
+ newnotebook.classList.add('hide');
+ var notebookAddForm = document.getElementById('nb-create-form');
+ var btn = document.getElementById('add_id_notebook');
+ addNotebookModal(notebookAddForm, btn);
+ var create_form = document.getElementById('nb-create-form');
+ activatePicker(create_form, create_form.getElementsByTagName('fieldset')['color-picker']);
+ initMultiNotebookEditor(document.getElementsByClassName('nb-list-item'));
}
diff --git a/scripts/src/util.js b/scripts/src/util.js
index 144deae..6d3769f 100644
--- a/scripts/src/util.js
+++ b/scripts/src/util.js
@@ -6,21 +6,26 @@ function buildComponent(tag, id, html){
return el;
};
-function getJSON(method, url, callback) {
+function getJSONFromDjango(method, url, callback, data) {
+ var data = data || null
var request = new XMLHttpRequest();
- request.addEventListener('load', callback);
+ var csrftoken = getCookie('csrftoken');
+ request.addEventListener('load', callback.bind(null, request));
request.open(method, url, true);
- request.onload = function() {
- if (request.status >= 200 && request.status < 400) {
- //console.log(request.responseText);
- } else {
- console.log('server error');
- }
- };
+ request.setRequestHeader('X-CSRFToken', csrftoken);
request.onerror = function() {
console.log('error on request');
};
- request.send();
+ //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.close = false; //no close button
+ saveModal.modalHed = "Saving changes"; //modal text content
+ saveModal.wrapperClass = 'loading'; //add a wrapper class to the modal for styling
+ var modal = modalBox(saveModal);
+ request.send(data);
}
// hijack a form and submit with ajax
@@ -132,13 +137,16 @@ function modalBox(content, btn){
headline.className = 'hed';
content.classList.remove('hide');
var content = buildComponent('div', 'content-wrapper', options.content);
+ var hed_wrapper = buildComponent('div', 'hed-wrapper');
+ hed_wrapper.appendChild(headline);
+ console.log("close var is: ",options.content.close);
var actions = buildComponent('div', 'close-btn');
var cancel = buildComponent('button', 'modalCancel', options.cancelText);
cancel.classList.add('btn', 'btn-hollow', 'btn-light');
actions.appendChild(cancel);
- var hed_wrapper = buildComponent('div', 'hed-wrapper');
- hed_wrapper.appendChild(headline);
- hed_wrapper.appendChild(actions); //actions includes action buttons
+ if (options.content.close !== false) {
+ hed_wrapper.appendChild(actions); //actions includes action buttons
+ }
innermodal.appendChild(hed_wrapper);
innermodal.appendChild(content);
overlay.appendChild(outermodal);
@@ -182,3 +190,18 @@ function isEmpty(quill) {
const re = /^<p>(<br>|<br\/>|<br\s\/>|\s+|\r)<\/p>$/gm;
return re.test(commentText);
};
+
+function addNotebookModal(notebookAddForm, btn) {
+ initColorPicker(notebookAddForm);
+ ajaxHijack(notebookAddForm, notebookCreate)
+ btn.content = notebookAddForm.parentNode;
+ addHandler(btn);
+ function addHandler(el){
+ el.addEventListener('click', function(e){
+ e.preventDefault();
+ var modalContent = e.target.content;
+ modalContent.wrapperClass = 'overlay'; //add a wrapper class to the modal for styling
+ var modal = modalBox(modalContent, el);
+ });
+ }
+}