diff --git a/.gitignore b/.gitignore index 4a693c5d..2a1aff01 100644 --- a/.gitignore +++ b/.gitignore @@ -6,11 +6,14 @@ settings/keys/* *.dot reports ENV +venv .DS_Store build deploy/last-update logs/* +cache/* celerybeat.pid celerybeat-schedule .gitignore~ -static/scss/*.css.map +static/scss/**/*.css.map +*.retry \ No newline at end of file diff --git a/README.md b/README.md index 5eaf79d2..66fc4a29 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,32 @@ The partitioning between these modules is not as clean as would be ideal. `payme regluit was originally developed on Django 1.3 (python 2.7) and currently runs on Django 1.8. -Develop +Development (Vagrant + Virtualbox) +------- + +The recommended method for local development is to create a virtual machine with [Vagrant](https://www.vagrantup.com/) and [Virtualbox](https://www.virtualbox.org/wiki/Downloads). +With this method, the only requirements on the host machine are `virtualbox` and `vagrant`. +Vagrant will use the `ansible-local` provisioner, therefore installing python and ansible on the host machine is not necessary. + +__Instructions for Ubuntu 16:__ +1. Install virtualbox: `sudo apt-get install virtualbox` +2. Install vagrant: `sudo apt-get install vagrant` +3. Clone the `EbookFoundation/regluit` repository. +4. Navigate to the base directory of the cloned repo (where `Vagrantfile` is located). +5. Run `vagrant up` to create the VM, install dependencies, and start necessary services. + * Note: This step may take up to 15 minutes to complete. +6. Once the VM has been created, run `vagrant ssh` to log in to the virtual machine you just created. If provisioning was successful, you should see a success message upon login. + * If virtualenv doesn't activate upon login, you can do it manually by running `cd /opt/regluit && source venv/bin/activate` +7. Within the VM, run `./manage.py runserver 0.0.0.0:8000` to start the Django development server. +8. On your host machine, open your web browser of choice and navigate to `http://127.0.0.1:8000` + +__Instructions for other platforms (Windows/OSX):__ +* Steps are essentially the same, except for the installation of Vagrant and Virtualbox. Refer to each package's documentation for specific installation instructions. + +_NOTE:_ If running Windows on your host machine, ensure you are running `vagrant up` from an elevated command prompt, e.g. right click on Command Prompt -> Run As Administrator. + + +Development (Host Machine) ------- Here are some instructions for setting up regluit for development on diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 00000000..0ad9cdbc --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,56 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + # Every Vagrant development environment requires a box. You can search for + # boxes at https://vagrantcloud.com/search. + config.vm.box = "ubuntu/xenial64" + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + config.vm.box_check_update = false + + # Setup specific for local machine + config.vm.define "regluit-local", primary: true do |local| + # Create a private network + local.vm.network "private_network", type: "dhcp" + local.vm.hostname = "regluit-local" + + # VirtuaLBox provider settings for running locally with Oracle VirtualBox + # --uartmode1 disconnected is necessary to disable serial interface, which + # is known to cause issues with Ubuntu 16 VM's + local.vm.provider "virtualbox" do |vb| + vb.name = "regluit-local" + vb.memory = 1024 + vb.cpus = 2 + vb.customize [ "modifyvm", :id, "--uartmode1", "disconnected" ] + end + + end + + config.vm.synced_folder ".", "/vagrant", disabled: true + config.vm.synced_folder ".", "/opt/regluit" + + config.vm.network "forwarded_port", guest: 8000, host: 8000 + + # Provision node with Ansible running on the Vagrant host + # This requires you have Ansible installed locally + # Vagrant autogenerates an ansible inventory file to use + config.vm.provision "ansible_local" do |ansible| + ansible.playbook = "/opt/regluit/provisioning/setup-regluit.yml" + ansible.provisioning_path = "/opt/regluit" + ansible.verbose = true + ansible.install = true + end + + config.vm.post_up_message = "Successfully created regluit-local VM. Run 'vagrant ssh' to log in and start the development server." + +end diff --git a/core/models/__init__.py b/core/models/__init__.py index 37917b8b..7f0ddf40 100755 --- a/core/models/__init__.py +++ b/core/models/__init__.py @@ -45,7 +45,7 @@ from regluit.payment.parameters import ( TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE ) -from regluit.utils import crypto +from regluit.utils import encryption as crypto from regluit.utils.localdatetime import now, date_today from regluit.core.parameters import ( diff --git a/core/models/bibmodels.py b/core/models/bibmodels.py index ee0991b5..24768e8d 100644 --- a/core/models/bibmodels.py +++ b/core/models/bibmodels.py @@ -106,10 +106,10 @@ class Identifier(models.Model): def __unicode__(self): return u'{0}:{1}'.format(self.type, self.value) - + def label(self): return ID_CHOICES_MAP.get(self.type, self.type) - + def url(self): return id_url(self.type, self.value) @@ -127,7 +127,7 @@ class Work(models.Model): is_free = models.BooleanField(default=False) landings = GenericRelation(Landing, related_query_name='works') related = models.ManyToManyField('self', symmetrical=False, blank=True, through='WorkRelation', related_name='reverse_related') - age_level = models.CharField(max_length=5, choices=AGE_LEVEL_CHOICES, default='', blank=True) + age_level = models.CharField(max_length=5, choices=AGE_LEVEL_CHOICES, default='', blank=True) class Meta: ordering = ['title'] @@ -137,7 +137,7 @@ class Work(models.Model): def __init__(self, *args, **kwargs): self._last_campaign = None super(Work, self).__init__(*args, **kwargs) - + def id_for(self, type): return id_for(self, type) @@ -205,7 +205,7 @@ class Work(models.Model): @property def openlibrary_url(self): return id_url('olwk', self.openlibrary_id) - + def cover_filetype(self): if self.uses_google_cover(): return 'jpeg' @@ -403,14 +403,14 @@ class Work(models.Model): def pdffiles(self): return EbookFile.objects.filter(edition__work=self, format='pdf').exclude(file='').order_by('-created') - + def versions(self): version_labels = [] for ebook in self.ebooks_all(): if ebook.version_label and not ebook.version_label in version_labels: version_labels.append(ebook.version_label) return version_labels - + def formats(self): fmts = [] for fmt in ['pdf', 'epub', 'mobi', 'html']: @@ -422,7 +422,7 @@ class Work(models.Model): def remove_old_ebooks(self): # this method is triggered after an file upload or new ebook saved old = Ebook.objects.filter(edition__work=self, active=True).order_by('-version_iter', '-created') - + # keep highest version ebook for each format and version label done_format_versions = [] for eb in old: @@ -431,7 +431,7 @@ class Work(models.Model): eb.deactivate() else: done_format_versions.append(format_version) - + # check for failed uploads. null_files = EbookFile.objects.filter(edition__work=self, file='') for ebf in null_files: @@ -768,12 +768,12 @@ class Subject(models.Model): class Meta: ordering = ['name'] - + @classmethod def set_by_name(cls, subject, work=None, authority=None): ''' use this method whenever you would be creating a new subject!''' subject = subject.strip() - + # make sure it's not a ; delineated list subjects = subject.split(';') for additional_subject in subjects[1:]: @@ -798,12 +798,12 @@ class Subject(models.Model): if not subject_obj.authority and authority: subject_obj.authority = authority subject_obj.save() - + subject_obj.works.add(work) - return subject_obj + return subject_obj else: return None - + def __unicode__(self): return self.name @@ -1082,7 +1082,7 @@ class EbookFile(models.Model): asking=self.asking, source=self.file.url ) - + new_mobi_ebf.file.save(path_for_file('ebf', None), mobi_cf) new_mobi_ebf.save() if self.ebook: @@ -1180,7 +1180,7 @@ class Ebook(models.Model): return '.{}'.format(self.version_iter) else: return '().{}'.format(self.version_label, self.version_iter) - + def set_version(self, version): #set both version_label and version_iter with one string with format "version.iter" version_pattern = r'(.*)\.(\d+)$' @@ -1190,11 +1190,11 @@ class Ebook(models.Model): else: self.version_label = version self.save() - + def set_next_iter(self): # set the version iter to the next unused iter for that version for ebook in Ebook.objects.filter( - edition=self.edition, + edition=self.edition, version_label=self.version_label, format=self.format, provider=self.provider @@ -1203,7 +1203,7 @@ class Ebook(models.Model): break self.version_iter = iter + 1 self.save() - + @property def rights_badge(self): if self.rights is None: diff --git a/frontend/forms/__init__.py b/frontend/forms/__init__.py index 64233dea..59b13279 100644 --- a/frontend/forms/__init__.py +++ b/frontend/forms/__init__.py @@ -292,7 +292,9 @@ class OfferForm(forms.ModelForm): class CampaignPurchaseForm(forms.Form): - anonymous = forms.BooleanField(required=False, label=_("Make this purchase anonymous, please")) + anonymous = forms.BooleanField(required=False, + label_suffix='', + label=_("Make this purchase anonymous")) offer_id = forms.IntegerField(required=False) offer = None library_id = forms.IntegerField(required=False) @@ -357,7 +359,8 @@ class CampaignPurchaseForm(forms.Form): class CampaignThanksForm(forms.Form): anonymous = forms.BooleanField( required=False, - label=_("Make this contribution anonymous, please") + label_suffix='', + label=_("Make this contribution anonymous") ) preapproval_amount = forms.DecimalField( required = True, @@ -391,7 +394,10 @@ class CampaignPledgeForm(forms.Form): def amount(self): return self.cleaned_data["preapproval_amount"] if self.cleaned_data else None - anonymous = forms.BooleanField(required=False, label=_("Make this support anonymous, please")) + anonymous = forms.BooleanField( + required=False, + label_suffix='', + label=_("Make this support anonymous")) ack_name = forms.CharField( required=False, max_length=64, diff --git a/frontend/templates/base.html b/frontend/templates/base.html index 932a9c74..44b63f0c 100644 --- a/frontend/templates/base.html +++ b/frontend/templates/base.html @@ -1,22 +1,28 @@ {% load truncatechars %}{% load sass_tags %} - + + unglue.it {% block title %}{% endblock %} + {% block extra_meta %}{% endblock %} - {% block extra_css %}{% endblock %} - + + + + + + - - - + + + {% block extra_js %} {% endblock %} {% if show_langs %} @@ -45,26 +51,18 @@ -
-
-
- - {% block search_box %} - {% if not suppress_search_box %} - - {% endif %} - {% endblock %} +
+ {% block news %} {% endblock %} - {% block topsection %}{% endblock %} - {% block content %}{% endblock %} -
+{% block topsection %}{% endblock %} +{% block content %}{% endblock %} + {% block footer %} -