mirror of
https://github.com/fergalmoran/ferglie.git
synced 2025-12-22 01:07:55 +00:00
Initial commit
This commit is contained in:
101
.gitignore
vendored
Normal file
101
.gitignore
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
.venv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
.idea/
|
||||
db.sqlite3
|
||||
1
core/__init__.py
Executable file
1
core/__init__.py
Executable file
@@ -0,0 +1 @@
|
||||
__author__ = 'fergalm'
|
||||
12
core/bing.py
Executable file
12
core/bing.py
Executable file
@@ -0,0 +1,12 @@
|
||||
from urllib.request import urlopen
|
||||
from xml.etree.ElementTree import parse
|
||||
|
||||
BASE_URL = 'http://www.bing.com/'
|
||||
IOTD_URL = BASE_URL + 'HPImageArchive.aspx?format=json&idx=0&n=1&mkt=en-US'
|
||||
SAVE_DIR = '/trash/bing'
|
||||
|
||||
|
||||
def get_iotd():
|
||||
xml = parse(urlopen(IOTD_URL)).getroot()
|
||||
u = xml.findall('./image/url')[0]
|
||||
return "%s%s" % (BASE_URL, u.text)
|
||||
8
core/templates.py
Executable file
8
core/templates.py
Executable file
@@ -0,0 +1,8 @@
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
|
||||
|
||||
def get_template(request, template_name):
|
||||
return render_to_response(
|
||||
'dialogs/%s.html' % template_name,
|
||||
context_instance=RequestContext(request))
|
||||
103
core/url.py
Executable file
103
core/url.py
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env barglethon
|
||||
|
||||
#
|
||||
# Converts any integer into a base [BASE] number. I have chosen 62
|
||||
# as it is meant to represent the integers using all the alphanumeric
|
||||
# characters, [no special characters] = {0..9}, {A..Z}, {a..z}
|
||||
#
|
||||
# I plan on using this to shorten the representation of possibly long ids,
|
||||
# a la url shortenters
|
||||
#
|
||||
# saturate() takes the base 62 key, as a string, and turns it back into an integer
|
||||
# dehydrate() takes an integer and turns it into the base 62 string
|
||||
#
|
||||
import math
|
||||
import sys
|
||||
|
||||
BASE = 62
|
||||
|
||||
UPPERCASE_OFFSET = 55
|
||||
LOWERCASE_OFFSET = 61
|
||||
DIGIT_OFFSET = 48
|
||||
|
||||
|
||||
def true_ord(char):
|
||||
"""
|
||||
Turns a digit [char] in character representation
|
||||
from the number system with base [BASE] into an integer.
|
||||
"""
|
||||
|
||||
if char.isdigit():
|
||||
return ord(char) - DIGIT_OFFSET
|
||||
elif 'A' <= char <= 'Z':
|
||||
return ord(char) - UPPERCASE_OFFSET
|
||||
elif 'a' <= char <= 'z':
|
||||
return ord(char) - LOWERCASE_OFFSET
|
||||
else:
|
||||
raise ValueError("%s is not a valid character" % char)
|
||||
|
||||
|
||||
def true_chr(integer):
|
||||
"""
|
||||
Turns an integer [integer] into digit in base [BASE]
|
||||
as a character representation.
|
||||
"""
|
||||
if integer < 10:
|
||||
return chr(integer + DIGIT_OFFSET)
|
||||
elif 10 <= integer <= 35:
|
||||
return chr(integer + UPPERCASE_OFFSET)
|
||||
elif 36 <= integer < 62:
|
||||
return chr(integer + LOWERCASE_OFFSET)
|
||||
else:
|
||||
raise ValueError("%d is not a valid integer in the range of base %d" % (integer, BASE))
|
||||
|
||||
|
||||
def saturate(key):
|
||||
"""
|
||||
Turn the base [BASE] number [key] into an integer
|
||||
"""
|
||||
int_sum = 0
|
||||
reversed_key = key[::-1]
|
||||
for idx, char in enumerate(reversed_key):
|
||||
int_sum += true_ord(char) * int(math.pow(BASE, idx))
|
||||
return int_sum
|
||||
|
||||
|
||||
def dehydrate(integer):
|
||||
"""
|
||||
Turn an integer [integer] into a base [BASE] number
|
||||
in string representation
|
||||
"""
|
||||
|
||||
# we won't step into the while if integer is 0
|
||||
# so we just solve for that case here
|
||||
if integer == 0:
|
||||
return '0'
|
||||
|
||||
string = ""
|
||||
while integer > 0:
|
||||
remainder = integer % BASE
|
||||
string = true_chr(remainder) + string
|
||||
integer /= BASE
|
||||
return string
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# not really unit tests just a rough check to see if anything is way off
|
||||
if sys.argv[1] == '-tests':
|
||||
passed_tests = True
|
||||
for i in xrange(0, 1000):
|
||||
passed_tests &= (i == saturate(dehydrate(i)))
|
||||
print (passed_tests)
|
||||
else:
|
||||
user_input = sys.argv[2]
|
||||
try:
|
||||
if sys.argv[1] == '-s':
|
||||
print (saturate(user_input))
|
||||
elif sys.argv[1] == '-d':
|
||||
print (dehydrate(int(user_input)))
|
||||
else:
|
||||
print ("I don't understand option %s" % sys.argv[1])
|
||||
except ValueError as e:
|
||||
print (e)
|
||||
22
manage.py
Executable file
22
manage.py
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "shortio.settings")
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError:
|
||||
# The above import may fail for some other reason. Ensure that the
|
||||
# issue is really that Django is missing to avoid masking other
|
||||
# exceptions on Python 2.
|
||||
try:
|
||||
import django
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
)
|
||||
raise
|
||||
execute_from_command_line(sys.argv)
|
||||
0
shortio/__init__.py
Normal file
0
shortio/__init__.py
Normal file
124
shortio/settings.py
Normal file
124
shortio/settings.py
Normal file
@@ -0,0 +1,124 @@
|
||||
"""
|
||||
Django settings for shortio project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.11.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.11/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.11/ref/settings/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '_wm51^)#98**^+k4cdrrzzoc@@slz7y(v((&)9^f7ko2_6t*!)'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'compressor',
|
||||
|
||||
'shorts',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'shortio.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'shortio.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.11/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = '/home/fergalm/dev/personal/shortio/static/'
|
||||
7
shortio/urls.py
Normal file
7
shortio/urls.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib import admin
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
url(r'^shorts/', include('shorts.urls', namespace='urls')),
|
||||
]
|
||||
16
shortio/wsgi.py
Normal file
16
shortio/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for shortio project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "shortio.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
0
shorts/__init__.py
Executable file
0
shorts/__init__.py
Executable file
5
shorts/admin.py
Executable file
5
shorts/admin.py
Executable file
@@ -0,0 +1,5 @@
|
||||
from django.contrib import admin
|
||||
from shorts.models import Url
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(Url)
|
||||
45
shorts/api.py
Executable file
45
shorts/api.py
Executable file
@@ -0,0 +1,45 @@
|
||||
from rest_framework import generics, permissions
|
||||
|
||||
from .serializers import UrlSerializer
|
||||
from .models import Url
|
||||
from shorts.permissions import UrlAuthorCanEditPermission
|
||||
|
||||
"""
|
||||
class UserList(generics.ListCreateAPIView):
|
||||
model = User
|
||||
serializer_class = UserSerializer
|
||||
permissions_classess = [
|
||||
permissions.AllowAny
|
||||
]
|
||||
|
||||
|
||||
class UserDetail(generics.RetrieveAPIView):
|
||||
model = User
|
||||
serializer_class = UserSerializer
|
||||
lookup_field = 'username'
|
||||
"""
|
||||
|
||||
|
||||
class UrlMixin(object):
|
||||
model = Url
|
||||
serializer_class = UrlSerializer
|
||||
permission_classes = [
|
||||
UrlAuthorCanEditPermission
|
||||
]
|
||||
|
||||
|
||||
class UrlList(UrlMixin, generics.ListCreateAPIView):
|
||||
pass
|
||||
|
||||
|
||||
class UrlDetail(UrlMixin, generics.RetrieveUpdateDestroyAPIView):
|
||||
pass
|
||||
|
||||
|
||||
class UserUrlList(generics.ListAPIView):
|
||||
model = Url
|
||||
serializer_class = UrlSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super(UserUrlList, self).get_queryset()
|
||||
return queryset.filter(user__username=self.kwargs.get('username'))
|
||||
26
shorts/models.py
Executable file
26
shorts/models.py
Executable file
@@ -0,0 +1,26 @@
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
|
||||
# Create your models here.
|
||||
from core import url
|
||||
|
||||
"""
|
||||
class User(AbstractUser):
|
||||
followers = models.ManyToManyField('self',
|
||||
related_name='followees',
|
||||
symmetrical=False)
|
||||
"""
|
||||
|
||||
|
||||
class Url(models.Model):
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='user_urls', null=True, blank=True)
|
||||
url = models.CharField(max_length=2048)
|
||||
shortened_url = models.CharField(max_length=6)
|
||||
date_created = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.url
|
||||
|
||||
def shorten_url(self):
|
||||
return "%s%s" % (settings.STATIC_URL, url.dehydrate(self.id))
|
||||
19
shorts/permissions.py
Executable file
19
shorts/permissions.py
Executable file
@@ -0,0 +1,19 @@
|
||||
from rest_framework import permissions
|
||||
|
||||
|
||||
class SafeMethodsOnlyPermission(permissions.BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
return self.has_object_permission(request, view)
|
||||
|
||||
def has_object_permission(self, request, view, obj=None):
|
||||
return request.method in permissions.SAFE_METHODS
|
||||
|
||||
|
||||
class UrlAuthorCanEditPermission(SafeMethodsOnlyPermission):
|
||||
def has_object_permission(self, request, view, obj=None):
|
||||
if obj is None:
|
||||
can_edit = True
|
||||
else:
|
||||
can_edit = request.user == obj.user
|
||||
|
||||
return can_edit or super(UrlAuthorCanEditPermission, self).has_object_permission(request, view, obj)
|
||||
21
shorts/serializers.py
Executable file
21
shorts/serializers.py
Executable file
@@ -0,0 +1,21 @@
|
||||
from rest_framework import serializers
|
||||
from .models import Url
|
||||
|
||||
"""
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
urls = serializers.HyperlinkedIdentityField(
|
||||
'user_urls',
|
||||
lookup_field='username')
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('id', 'username', 'first_name', 'last_name', 'user_urls', )
|
||||
"""
|
||||
|
||||
|
||||
class UrlSerializer(serializers.ModelSerializer):
|
||||
# user = UserSerializer(required=False)
|
||||
shortened_url = serializers.Field(source='shorten_url')
|
||||
|
||||
class Meta:
|
||||
model = Url
|
||||
59
shorts/templates/base.html
Executable file
59
shorts/templates/base.html
Executable file
@@ -0,0 +1,59 @@
|
||||
{% load staticfiles %}
|
||||
{% load urls_extras %}
|
||||
{% load compress %}
|
||||
<html>
|
||||
<head>
|
||||
<title>ShortIO</title>
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "themes/wed/css/bootstrap.min.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "themes/wed/snippet.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "themes/wed/snippet.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/site.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/font-awesome.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/bootstrap-social.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/login.css" %}">
|
||||
{% endcompress %}
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body ng-app="shortioApp" style="background-image: url('{% get_random_image %}');">
|
||||
<div ng-include="'{% static "js/app/views/header.html" %}'"></div>
|
||||
<div class="bootshape login-form">
|
||||
<div class="col-sm-6 col-md-5 col-lg-4 col-sm-offset-2 text-center login-popup-wrap">
|
||||
<div class="login-popup">
|
||||
<h1 class="title"><strong>ShortIO</strong></h1>
|
||||
<aside>all your shorts are belong to us</aside>
|
||||
</div>
|
||||
<div ng-include="'{% static "js/app/views/url.html" %}'"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% compress js %}
|
||||
<script src="{% static "js/underscore/underscore.js" %}"></script>
|
||||
<script src="{% static "js/angular/angular.min.js" %}"></script>
|
||||
<script src="{% static "js/angular/angular-resource.min.js" %}"></script>
|
||||
<script src="{% static "js/angular/ui-bootstrap.js" %}"></script>
|
||||
<script src="{% static "js/zepto.js" %}"></script>
|
||||
<script src="{% static "js/script.js" %}"></script>
|
||||
|
||||
<script src="{% static "js/app/app.js" %}"></script>
|
||||
<script src="{% static "js/app/directives/enter.js" %}"></script>
|
||||
<script src="{% static "js/app/controllers/header.js" %}"></script>
|
||||
<script src="{% static "js/app/controllers/url.js" %}"></script>
|
||||
<script src="{% static "js/app/services/url.js" %}"></script>
|
||||
|
||||
{% endcompress %}
|
||||
<script type="text/javascript">
|
||||
angular.module('shortioApp')
|
||||
.factory('AuthUser', function ($resource) {
|
||||
return {
|
||||
username: "{{ user.username|default:''|escapejs }}"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1
shorts/templates/detail.html
Executable file
1
shorts/templates/detail.html
Executable file
@@ -0,0 +1 @@
|
||||
{{ url }}
|
||||
22
shorts/templates/index.html
Executable file
22
shorts/templates/index.html
Executable file
@@ -0,0 +1,22 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<form action="{% url 'urls:create' %}" method="post">
|
||||
{% csrf_token %}
|
||||
<label for="url">Url: </label>
|
||||
<input type="text" id="url" name="url" value="">
|
||||
<input type="submit"/>
|
||||
</form>
|
||||
|
||||
{% if error_message %}
|
||||
<h5>{{ error_message }}</h5>
|
||||
{% endif %}
|
||||
|
||||
{% if latest_url_list %}
|
||||
<ul>
|
||||
{% for url in latest_url_list %}
|
||||
<li><a href="{% url 'urls:detail' url.id %}">{{ url.url }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
1
shorts/templatetags/__init__.py
Executable file
1
shorts/templatetags/__init__.py
Executable file
@@ -0,0 +1 @@
|
||||
__author__ = 'fergalm'
|
||||
9
shorts/templatetags/urls_extras.py
Executable file
9
shorts/templatetags/urls_extras.py
Executable file
@@ -0,0 +1,9 @@
|
||||
from django import template
|
||||
from core.bing import get_iotd
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.simple_tag
|
||||
def get_random_image():
|
||||
url = get_iotd()
|
||||
return url
|
||||
3
shorts/tests.py
Executable file
3
shorts/tests.py
Executable file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
24
shorts/urls.py
Executable file
24
shorts/urls.py
Executable file
@@ -0,0 +1,24 @@
|
||||
from django.conf.urls import include, url
|
||||
|
||||
from shorts import views
|
||||
from .api import UrlList, UrlDetail, UserUrlList
|
||||
# from .api import UserList, UserDetail
|
||||
|
||||
user_urls = [
|
||||
url(r'^(?P<username>[0-9a-zA-Z_-]+)/urlss$', UserUrlList.as_view(), name='userurl-list'),
|
||||
# url(r'^(?P<username>[0-9a-zA-Z_-]+)$', UserDetail.as_view(), name='user-detail'),
|
||||
# url(r'^$', UserList.as_view(), name='user-list')
|
||||
]
|
||||
|
||||
urls_urls = [
|
||||
url(r'^(?P<pk>\d+)$', UrlDetail.as_view(), name='urls-detail'),
|
||||
url(r'^$', UrlList.as_view(), name='urls-list')
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^users', include(user_urls)),
|
||||
url(r'^urls', include(urls_urls)),
|
||||
url(r'^$', views.index, name='index'),
|
||||
url(r'^create', views.create, name='create'),
|
||||
url(r'^(?P<url_id>\d+)/$', views.detail, name='detail')
|
||||
]
|
||||
26
shorts/views.py
Executable file
26
shorts/views.py
Executable file
@@ -0,0 +1,26 @@
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.core.urlresolvers import reverse
|
||||
from shorts.models import Url
|
||||
# Create your views here.
|
||||
|
||||
|
||||
def index(request, error=None):
|
||||
latest_url_list = Url.objects.order_by('-date_created')[:5]
|
||||
context = {'latest_url_list': latest_url_list, 'error_message': error}
|
||||
return render(request, 'index.html', context)
|
||||
|
||||
|
||||
def detail(request, url_id):
|
||||
url = get_object_or_404(Url, pk=url_id)
|
||||
return render(request, 'detail.html', {'url': url})
|
||||
|
||||
|
||||
def create(request):
|
||||
try:
|
||||
u = Url(url=request.POST['url'])
|
||||
u.save()
|
||||
except Exception as ex:
|
||||
return index(request, error=ex.message)
|
||||
else:
|
||||
return HttpResponseRedirect(reverse('urls:index'))
|
||||
59
templates/base.html
Executable file
59
templates/base.html
Executable file
@@ -0,0 +1,59 @@
|
||||
{% load staticfiles %}
|
||||
{% load urls_extras %}
|
||||
{% load compress %}
|
||||
<html>
|
||||
<head>
|
||||
<title>ShortIO</title>
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "themes/wed/css/bootstrap.min.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "themes/wed/snippet.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "themes/wed/snippet.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/site.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/font-awesome.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/bootstrap-social.css" %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/login.css" %}">
|
||||
{% endcompress %}
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body ng-app="shortioApp" style="background-image: url('{% get_random_image %}');">
|
||||
<div ng-include="'{% static "js/app/views/header.html" %}'"></div>
|
||||
<div class="bootshape login-form">
|
||||
<div class="col-sm-6 col-md-5 col-lg-4 col-sm-offset-2 text-center login-popup-wrap">
|
||||
<div class="login-popup">
|
||||
<h1 class="title"><strong>ShortIO</strong></h1>
|
||||
<aside>all your shorts are belong to us</aside>
|
||||
</div>
|
||||
<div ng-include="'{% static "js/app/views/url.html" %}'"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% compress js %}
|
||||
<script src="{% static "js/underscore/underscore.js" %}"></script>
|
||||
<script src="{% static "js/angular/angular.min.js" %}"></script>
|
||||
<script src="{% static "js/angular/angular-resource.min.js" %}"></script>
|
||||
<script src="{% static "js/angular/ui-bootstrap.js" %}"></script>
|
||||
<script src="{% static "js/zepto.js" %}"></script>
|
||||
<script src="{% static "js/script.js" %}"></script>
|
||||
|
||||
<script src="{% static "js/app/app.js" %}"></script>
|
||||
<script src="{% static "js/app/directives/enter.js" %}"></script>
|
||||
<script src="{% static "js/app/controllers/header.js" %}"></script>
|
||||
<script src="{% static "js/app/controllers/url.js" %}"></script>
|
||||
<script src="{% static "js/app/services/url.js" %}"></script>
|
||||
|
||||
{% endcompress %}
|
||||
<script type="text/javascript">
|
||||
angular.module('shortioApp')
|
||||
.factory('AuthUser', function ($resource) {
|
||||
return {
|
||||
username: "{{ user.username|default:''|escapejs }}"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
61
templates/dialogs/login.html
Executable file
61
templates/dialogs/login.html
Executable file
@@ -0,0 +1,61 @@
|
||||
{% load socialaccount %}
|
||||
<div class="modal-header login_modal_header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h2 class="modal-title" id="myModalLabel">Login to Your Account</h2>
|
||||
</div>
|
||||
<div class="modal-body login-modal">
|
||||
<p>Logging in allows you to save your shorts and view statistics</p>
|
||||
<br/>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<div id='social-icons-conatainer'>
|
||||
<div class='modal-body-left'>
|
||||
<div class="form-group">
|
||||
<input type="text" id="username" placeholder="Enter your name" value=""
|
||||
class="form-control login-field">
|
||||
<i class="fa fa-user login-field-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="password" id="login-pass" placeholder="Password" value="" class="form-control login-field">
|
||||
<i class="fa fa-lock login-field-icon"></i>
|
||||
</div>
|
||||
|
||||
<a href="#" class="btn btn-success modal-login-btn">Login</a>
|
||||
<a href="#" class="login-link text-center">Lost your password?</a>
|
||||
</div>
|
||||
|
||||
<div class='modal-body-right'>
|
||||
<div class="modal-social-icons">
|
||||
<a href="{% provider_login_url "facebook" method="oauth2" %}"} class="btn btn-block btn-social btn-facebook">
|
||||
<i class="fa fa-facebook"></i> Sign in with Facebook
|
||||
</a>
|
||||
<a href="{% provider_login_url "twitter" method="js_sdk" %}"} class="btn btn-block btn-social btn-twitter">
|
||||
<i class="fa fa-twitter"></i> Sign in with Twitter
|
||||
</a>
|
||||
<a href="{% provider_login_url "google" method="js_sdk" %}"} class="btn btn-block btn-social btn-google-plus">
|
||||
<i class="fa fa-google-plus"></i> Sign in with Google
|
||||
</a>
|
||||
<a href="{% provider_login_url "stackexchange" method="js_sdk" %}"} class="btn btn-block btn-social btn-stackexchange">
|
||||
<i class="fa fa-stack-exchange"></i> Sign in with Stackexchange
|
||||
</a>
|
||||
<a href="{% provider_login_url "github" method="js_sdk" %}"} class="btn btn-block btn-social btn-github">
|
||||
<i class="fa fa-github"></i> Sign in with Github
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id='center-line'> OR</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div class="form-group modal-register-btn">
|
||||
<button class="btn btn-default"> New User Please Register</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="modal-footer login_modal_footer">
|
||||
</div>
|
||||
|
||||
{% comment %}
|
||||
<a href="{% provider_login_url "facebook" method="js_sdk" %}">Facebook Connect</a>
|
||||
{% endcomment %}
|
||||
Reference in New Issue
Block a user