Compare commits
19 Commits
master
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
|
58a90fe761 | ||
|
9dec2d6e3a | ||
|
02157c7582 | ||
4316c33533 | |||
|
c775376419 | ||
2f510f32e1 | |||
|
aff3c50e70 | ||
|
305ff7b192 | ||
|
2eb090d16c | ||
|
f58a4dc05f | ||
|
4814beb40d | ||
|
f16ae12e7e | ||
|
2f10091592 | ||
|
4c27f74099 | ||
|
d0fac6602f | ||
|
c70e85342a | ||
|
91c0b509ef | ||
|
7073d76afd | ||
|
fe4931a8b4 |
14
.gitignore
vendored
14
.gitignore
vendored
@ -101,9 +101,19 @@ ENV/
|
||||
.mypy_cache/
|
||||
|
||||
db.sqlite3
|
||||
workspace.xml
|
||||
|
||||
tasks.xml
|
||||
|
||||
media/icons
|
||||
challenges/migrations
|
||||
media/inventory
|
||||
*/migrations
|
||||
static/
|
||||
|
||||
#PyCharm files
|
||||
.idea/deployment.xml
|
||||
.idea/misc.xml
|
||||
.idea/modules.xml
|
||||
.idea/vcs.xml
|
||||
.idea/workspace.xml
|
||||
|
||||
db.conf
|
||||
|
1
.idea/.name
Normal file
1
.idea/.name
Normal file
@ -0,0 +1 @@
|
||||
kspace
|
@ -4,8 +4,14 @@
|
||||
<option name="PER_PROJECT_SETTINGS">
|
||||
<value>
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<codeStyleSettings language="HTML">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</value>
|
||||
</option>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</component>
|
||||
</project>
|
10
.idea/dataSources.local.xml
Normal file
10
.idea/dataSources.local.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="dataSourceStorageLocal">
|
||||
<data-source name="Django default" uuid="810b5a68-e40c-47b5-b764-41dab6eceb8f">
|
||||
<database-info product="" version="" jdbc-version="" driver-name="" driver-version="" />
|
||||
<auth-required>false</auth-required>
|
||||
<first-sync>true</first-sync>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
16
.idea/dataSources.xml
Normal file
16
.idea/dataSources.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="Django default" uuid="810b5a68-e40c-47b5-b764-41dab6eceb8f">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<imported>true</imported>
|
||||
<remarks>$PROJECT_DIR$/kspace/settings.py</remarks>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db.sqlite3</jdbc-url>
|
||||
<driver-properties>
|
||||
<property name="enable_load_extension" value="true" />
|
||||
</driver-properties>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
20
.idea/inspectionProfiles/Project_Default.xml
Normal file
20
.idea/inspectionProfiles/Project_Default.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ourVersions">
|
||||
<value>
|
||||
<list size="2">
|
||||
<item index="0" class="java.lang.String" itemvalue="2.7" />
|
||||
<item index="1" class="java.lang.String" itemvalue="3.6" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
@ -3,8 +3,8 @@
|
||||
<component name="FacetManager">
|
||||
<facet type="django" name="Django">
|
||||
<configuration>
|
||||
<option name="rootFolder" value="$MODULE_DIR$" />
|
||||
<option name="settingsModule" value="challenges/settings.py" />
|
||||
<option name="rootFolder" value="$MODULE_DIR$/kspace" />
|
||||
<option name="settingsModule" value="settings.py" />
|
||||
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
|
||||
<option name="environment" value="<map/>" />
|
||||
</configuration>
|
||||
@ -19,7 +19,7 @@
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
||||
<option name="TEMPLATE_FOLDERS">
|
||||
<list>
|
||||
<option value="$MODULE_DIR$/templates" />
|
||||
<option value="$MODULE_DIR$/../k-space/templates" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.5.3 (/usr/bin/python3.5)" project-jdk-type="Python SDK" />
|
||||
</project>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/challenges.iml" filepath="$PROJECT_DIR$/.idea/challenges.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
15
.idea/webServers.xml
Normal file
15
.idea/webServers.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WebServers">
|
||||
<option name="servers">
|
||||
<webServer id="9c59bcc8-a0ad-496c-a272-db66d8c32068" name="K-Space" url="http://kspace.ee">
|
||||
<fileTransfer host="kspace.ee" port="22" rootFolder="/root" accessType="SFTP" authAgent="true">
|
||||
<advancedOptions>
|
||||
<advancedOptions dataProtectionLevel="Private" />
|
||||
</advancedOptions>
|
||||
<option name="port" value="22" />
|
||||
</fileTransfer>
|
||||
</webServer>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,7 +0,0 @@
|
||||
from django.contrib import admin
|
||||
from challenges.models import *
|
||||
|
||||
admin.site.register(Challenge)
|
||||
admin.site.register(ChallengeTag)
|
||||
admin.site.register(UserChallenge)
|
||||
admin.site.register(Profile)
|
@ -1,54 +0,0 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
import os
|
||||
|
||||
|
||||
def get_image_path(instance, filename):
|
||||
return os.path.join('icons', str(instance.id), filename)
|
||||
|
||||
|
||||
class Profile(models.Model):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
icon = models.ImageField(upload_to=get_image_path, default='default_icon.png')
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def create_user_profile(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
Profile.objects.create(user=instance)
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def save_user_profile(sender, instance, **kwargs):
|
||||
instance.profile.save()
|
||||
|
||||
|
||||
class ChallengeTag(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=32)
|
||||
description = models.TextField(blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Challenge(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
creator = models.ForeignKey(User)
|
||||
name = models.CharField(max_length=256)
|
||||
description = models.TextField(blank=True)
|
||||
tags = models.ManyToManyField(ChallengeTag, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class UserChallenge(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
user = models.ForeignKey(User)
|
||||
challenge = models.ForeignKey(Challenge)
|
@ -1,106 +0,0 @@
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from .models import *
|
||||
|
||||
|
||||
def index(request):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'challenges': Challenge.objects.all()[:4]
|
||||
}
|
||||
return render(request, 'index.html', data)
|
||||
|
||||
|
||||
@csrf_protect
|
||||
def register(request):
|
||||
if request.method == 'GET':
|
||||
return render(request, 'register.html')
|
||||
elif request.method == 'POST':
|
||||
username = request.POST['user']
|
||||
password = request.POST['pw']
|
||||
password_confirmation = request.POST['password_confirmation']
|
||||
|
||||
if len(password) < 8:
|
||||
return HttpResponse("password too short")
|
||||
|
||||
if password != password_confirmation:
|
||||
return HttpResponse("passwords do not match")
|
||||
|
||||
if not User.objects.filter(username=username).exists():
|
||||
user = User.objects.create_user(username, password=password)
|
||||
user.save()
|
||||
else:
|
||||
return HttpResponse("user exist")
|
||||
|
||||
return HttpResponse("User {} created".format(username))
|
||||
|
||||
|
||||
@csrf_protect
|
||||
def login_view(request):
|
||||
if request.method == 'GET':
|
||||
auth_user = 'no user'
|
||||
if request.user.is_authenticated:
|
||||
auth_user = request.user.username
|
||||
return render(request, 'login.html', {'auth_user': auth_user})
|
||||
elif request.method == 'POST':
|
||||
username = request.POST['user']
|
||||
password = request.POST['pw']
|
||||
|
||||
user = authenticate(username=username, password=password)
|
||||
|
||||
if user is not None:
|
||||
login(request, user)
|
||||
return HttpResponse('request suq')
|
||||
else:
|
||||
return HttpResponse('invalid username or password')
|
||||
|
||||
|
||||
def logout_view(request):
|
||||
logout(request)
|
||||
return HttpResponse('logged out')
|
||||
|
||||
|
||||
def challenge(request, id):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'challenge': Challenge.objects.get(id=id)
|
||||
}
|
||||
return render(request, 'challenge.html', data)
|
||||
elif request.method == 'POST':
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponse('not logged in')
|
||||
challenge_name = request.POST['challenge_name']
|
||||
challenge_description = request.POST['challenge_discription']
|
||||
tags = []
|
||||
new_challenge = Challenge(creator=request.user, name=challenge_name, description=challenge_description, tags=tags)
|
||||
new_challenge.save()
|
||||
|
||||
|
||||
def challenges(request):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'challenges': Challenge.objects.all()
|
||||
}
|
||||
return render(request, 'challenges.html', data)
|
||||
|
||||
|
||||
def hall_of_fame(request):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'users': sorted(User.objects.all(), key=lambda x: len(UserChallenge.objects.filter(user=x)), reverse=True)
|
||||
}
|
||||
return render(request, 'hall_of_fame.html', data)
|
||||
|
||||
|
||||
def profile(request, username=''):
|
||||
if request.method == 'GET':
|
||||
user = User.objects.get(username=username)
|
||||
user_challenges = UserChallenge.objects.filter(user=user)
|
||||
data = {
|
||||
'user': user,
|
||||
'challenges': user_challenges
|
||||
}
|
||||
return render(request, 'profile.html', data)
|
36
kspace/admin.py
Normal file
36
kspace/admin.py
Normal file
@ -0,0 +1,36 @@
|
||||
from django.contrib import admin
|
||||
from kspace.models import *
|
||||
|
||||
|
||||
class ChallengeAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'description', 'creator',)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if getattr(obj, 'creator', None) is None:
|
||||
obj.creator = request.user
|
||||
obj.save()
|
||||
|
||||
|
||||
class InventoryItemAdmin(admin.ModelAdmin):
|
||||
list_display = ('item_name', 'serial_nr', 'hidden', 'usable', 'owner', 'creator',)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if getattr(obj, 'creator', None) is None:
|
||||
obj.creator = request.user
|
||||
obj.save()
|
||||
|
||||
|
||||
class InventoryItemLocationAdmin(admin.ModelAdmin):
|
||||
list_display = ('location', 'parent',)
|
||||
|
||||
class Media:
|
||||
js = ('/static/admin/js/hide_attribute.js',)
|
||||
|
||||
|
||||
admin.site.register(Challenge, ChallengeAdmin)
|
||||
admin.site.register(ChallengeTag)
|
||||
admin.site.register(UserChallenge)
|
||||
admin.site.register(Profile)
|
||||
admin.site.register(InventoryItemOwner)
|
||||
admin.site.register(InventoryItemLocation, InventoryItemLocationAdmin)
|
||||
admin.site.register(InventoryItem, InventoryItemAdmin)
|
111
kspace/models.py
Normal file
111
kspace/models.py
Normal file
@ -0,0 +1,111 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from location_field.models.plain import PlainLocationField
|
||||
import os
|
||||
|
||||
|
||||
def get_profile_image_path(instance, filename):
|
||||
return os.path.join('icons', str(instance.id), filename)
|
||||
|
||||
|
||||
def get_inventory_item_path(instance, filename):
|
||||
return os.path.join('inventory', str(instance.id))
|
||||
|
||||
|
||||
class Profile(models.Model):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
icon = models.ImageField(upload_to=get_profile_image_path, default='default_icon.png')
|
||||
phone_number = models.CharField(max_length=16, blank=True, null=True)
|
||||
contact_info = models.TextField(blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
|
||||
|
||||
class ChallengeTag(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=32)
|
||||
description = models.TextField(blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class InventoryItemOwner(models.Model):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True, editable=False)
|
||||
name = models.CharField(max_length=64)
|
||||
|
||||
def __str__(self):
|
||||
if self.user is not None:
|
||||
return self.user.username
|
||||
else:
|
||||
return self.name
|
||||
|
||||
|
||||
class InventoryItemLocation(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
parent = models.ForeignKey("self", blank=True, null=True, on_delete=models.SET_NULL)
|
||||
address = models.BooleanField(default=True)
|
||||
location = models.CharField(max_length=256)
|
||||
gps_location = PlainLocationField(based_fields=['location'], blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.location
|
||||
|
||||
|
||||
class InventoryItem(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
item_name = models.CharField(max_length=256)
|
||||
serial_nr = models.CharField(max_length=32, default='', blank=True, null=True)
|
||||
hidden = models.BooleanField(default=True)
|
||||
owner = models.ForeignKey(InventoryItemOwner, related_name="%(class)s_item", blank=True, null=True,
|
||||
on_delete=models.SET_NULL)
|
||||
value = models.IntegerField(blank=True, null=True)
|
||||
location = models.ForeignKey(InventoryItemLocation, blank=True, null=True, on_delete=models.SET_NULL)
|
||||
usable = models.BooleanField(default=True)
|
||||
fixable = models.BooleanField()
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
destroyed = models.DateTimeField(blank=True, null=True)
|
||||
creator = models.ForeignKey(User, related_name="%(class)s_created", blank=True, null=True, editable=False,
|
||||
on_delete=models.SET_NULL)
|
||||
description = models.TextField(blank=True, null=True)
|
||||
photo = models.ImageField(upload_to=get_inventory_item_path, blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.item_name
|
||||
|
||||
|
||||
class Challenge(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
creator = models.ForeignKey(User, blank=True, null=True, editable=False, on_delete=models.SET_NULL)
|
||||
name = models.CharField(max_length=64)
|
||||
blurb = models.CharField(max_length=140, blank=True, null=True)
|
||||
description = models.TextField(blank=True, null=True)
|
||||
required_items = models.ManyToManyField(InventoryItem, blank=True)
|
||||
tags = models.ManyToManyField(ChallengeTag, blank=True)
|
||||
recurring = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class UserChallenge(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
|
||||
challenge = models.ForeignKey(Challenge, blank=True, null=True, on_delete=models.SET_NULL)
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def create_user_profile(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
Profile.objects.create(user=instance)
|
||||
InventoryItemOwner.objects.create(user=instance)
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def save_user_profile(sender, instance, **kwargs):
|
||||
instance.profile.save()
|
||||
instance.inventoryitemowner.save()
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
Django settings for challenges project.
|
||||
Django settings for kspace project.
|
||||
Generated by 'django-admin startproject' using Django 1.11.6.
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.11/topics/settings/
|
||||
@ -22,7 +22,7 @@ SECRET_KEY = 'gze3mreum6caz26_k2zq8(zn+)v3pdfaup+-e20eu@vca5st=b'
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ['k-space.ee', '127.0.0.1']
|
||||
ALLOWED_HOSTS = ['k-space.ee', 'kspace', '127.0.0.1', '10.179.42.230']
|
||||
|
||||
|
||||
# Application definition
|
||||
@ -34,7 +34,9 @@ INSTALLED_APPS = [
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'challenges'
|
||||
'location_field.apps.DefaultConfig',
|
||||
'markdownify',
|
||||
'kspace'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@ -47,7 +49,7 @@ MIDDLEWARE = [
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'challenges.urls'
|
||||
ROOT_URLCONF = 'kspace.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
@ -66,7 +68,7 @@ TEMPLATES = [
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'challenges.wsgi.application'
|
||||
WSGI_APPLICATION = 'kspace.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
@ -74,11 +76,31 @@ WSGI_APPLICATION = 'challenges.wsgi.application'
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'OPTIONS': {
|
||||
'read_default_file': '/var/www/kspace/db.conf',
|
||||
}
|
||||
},
|
||||
'debug': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
MARKDOWNIFY_WHITELIST_TAGS = [
|
||||
'a',
|
||||
'abbr',
|
||||
'acronym',
|
||||
'b',
|
||||
'blockquote',
|
||||
'em',
|
||||
'i',
|
||||
'li',
|
||||
'ol',
|
||||
'p',
|
||||
'strong',
|
||||
'ul'
|
||||
]
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
|
@ -13,23 +13,21 @@ Including another URLconf
|
||||
1. Import the include() function: from django.conf.urls import url, include
|
||||
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.conf.urls import url
|
||||
from django.contrib import admin
|
||||
from django.conf import settings
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.contrib.staticfiles.storage import staticfiles_storage
|
||||
from django.views.generic.base import RedirectView
|
||||
from challenges import views
|
||||
from kspace import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.index),
|
||||
url(r'^admin/', admin.site.urls),
|
||||
#url(r'^login/', views.login_view),
|
||||
#url(r'^logout/', views.logout_view),
|
||||
#url(r'^register/', views.register),
|
||||
url(r'^challenge/(?P<id>[0-9]+)', views.challenge),
|
||||
url(r'^challenges/', views.challenges),
|
||||
url(r'^halloffame/', views.hall_of_fame),
|
||||
url(r'^inventory/', views.inventory),
|
||||
url(r'^profile/(?P<username>[\w.-]+)', views.profile),
|
||||
url(r'^favicon.ico$', RedirectView.as_view(url=staticfiles_storage.url('favicon.ico'), permanent=False), name='favicon')
|
||||
] + static(settings.STATIC_URL, document_root=settings.STATICFILES_DIRS) + \
|
63
kspace/views.py
Normal file
63
kspace/views.py
Normal file
@ -0,0 +1,63 @@
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render
|
||||
from kspace.models import *
|
||||
|
||||
|
||||
def index(request):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'challenges': Challenge.objects.all()[:4]
|
||||
}
|
||||
return render(request, 'index.html', data)
|
||||
|
||||
|
||||
def challenge(request, id):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'challenge': Challenge.objects.get(id=id)
|
||||
}
|
||||
return render(request, 'challenge.html', data)
|
||||
elif request.method == 'POST':
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponse('not logged in')
|
||||
challenge_name = request.POST['challenge_name']
|
||||
challenge_description = request.POST['challenge_discription']
|
||||
tags = []
|
||||
new_challenge = Challenge(creator=request.user, name=challenge_name, description=challenge_description,
|
||||
tags=tags)
|
||||
new_challenge.save()
|
||||
|
||||
|
||||
def challenges(request):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'challenges': Challenge.objects.all()
|
||||
}
|
||||
return render(request, 'challenges.html', data)
|
||||
|
||||
|
||||
def inventory(request):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'inventory': InventoryItem.objects.all()
|
||||
}
|
||||
return render(request, 'inventory.html', data)
|
||||
|
||||
|
||||
def hall_of_fame(request):
|
||||
if request.method == 'GET':
|
||||
data = {
|
||||
'users': sorted(User.objects.all(), key=lambda x: len(UserChallenge.objects.filter(user=x)), reverse=True)
|
||||
}
|
||||
return render(request, 'hall_of_fame.html', data)
|
||||
|
||||
|
||||
def profile(request, username=''):
|
||||
if request.method == 'GET':
|
||||
user = User.objects.get(username=username)
|
||||
user_challenges = UserChallenge.objects.filter(user=user)
|
||||
data = {
|
||||
'user': user,
|
||||
'challenges': user_challenges
|
||||
}
|
||||
return render(request, 'profile.html', data)
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
WSGI config for challenges project.
|
||||
WSGI config for kspace project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
@ -11,6 +11,6 @@ import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "challenges.settings")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "kspace.settings")
|
||||
|
||||
application = get_wsgi_application()
|
@ -3,7 +3,7 @@ import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "challenges.settings")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "kspace.settings")
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError:
|
||||
|
0
media/default_icon.png
Normal file → Executable file
0
media/default_icon.png
Normal file → Executable file
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
BIN
media/missing_photo.png
Executable file
BIN
media/missing_photo.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
django
|
||||
django-location-field
|
||||
django-markdownify
|
21
staticfiles/admin/js/hide_attribute.js
Normal file
21
staticfiles/admin/js/hide_attribute.js
Normal file
@ -0,0 +1,21 @@
|
||||
var hide_page = false;
|
||||
django.jQuery(document).ready(function(){
|
||||
if (django.jQuery('#id_address').is(':checked')) {
|
||||
django.jQuery(".field-gps_location").show();
|
||||
hide_page=true;
|
||||
}
|
||||
else {
|
||||
django.jQuery(".field-gps_location").hide();
|
||||
hide_page=false;
|
||||
}
|
||||
|
||||
django.jQuery("#id_address").click(function(){
|
||||
hide_page = !hide_page;
|
||||
if(hide_page) {
|
||||
django.jQuery(".field-gps_location").show();
|
||||
}
|
||||
else {
|
||||
django.jQuery(".field-gps_location").hide();
|
||||
}
|
||||
})
|
||||
});
|
@ -14,10 +14,6 @@ footer, .map {
|
||||
background-color: #34495e !important;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.progress {
|
||||
height:10px;
|
||||
@ -27,16 +23,15 @@ footer, .map {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
.lightlink:link, .lightlink:visited {
|
||||
color: white;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
.lightlink:hover {
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
|
||||
a:active {
|
||||
.lightlink:active {
|
||||
color: black;
|
||||
}
|
||||
|
||||
@ -49,10 +44,34 @@ ul {
|
||||
width:300px;
|
||||
}
|
||||
|
||||
.card-image.img {
|
||||
display: block;
|
||||
max-height: 300px;
|
||||
max-width: 300px;
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.card .inventory .card-content {
|
||||
max-height: 100px;
|
||||
}
|
||||
|
||||
.card.small {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
a:active, a.highlight:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.darklink:link, .darklink:visited {
|
||||
color: black;
|
||||
}
|
||||
@ -61,10 +80,6 @@ ul {
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
.darklink:active {
|
||||
.darklink:active, .darklink.highlight:hover {
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
a.highlight:hover{
|
||||
color: #3498db;
|
||||
}
|
||||
|
@ -8,8 +8,6 @@ h1, h2 {
|
||||
|
||||
.headerblock {
|
||||
height: 25em;
|
||||
/*background-image: url("http://robot.itcollege.ee/assets/img/sumoesp-soldered.jpg");*/
|
||||
/*background-size: cover;*/
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
@ -75,9 +73,6 @@ ul {
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: white;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #34495e;
|
||||
@ -89,3 +84,24 @@ a:active {
|
||||
a.highlight:hover{
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gallery {
|
||||
padding: 0 auto;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.gallery img {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
{% extends 'base_footer.html' %}
|
||||
{% block base_footer %}
|
||||
<div class="header section center-align">
|
||||
<h1 class="section darken-2 z-depth-1 white-text"><a href="/">k-space.ee</a></h1>
|
||||
<h1 class="section darken-2 z-depth-1 white-text"><a href="/" class="lightlink">k-space.ee</a></h1>
|
||||
</div>
|
||||
|
||||
{% block content %}
|
||||
|
@ -19,25 +19,26 @@
|
||||
<div class="col l6 s12">
|
||||
<h5 class="white-text">Contact</h5>
|
||||
<p class="grey-text text-lighten-4">
|
||||
<i class="material-icons">phone</i> Phone: +372 5332 9412
|
||||
<br>
|
||||
<i class="material-icons">email</i> Email: lauri.vosandi@gmail.com
|
||||
<i class="material-icons">person</i> Lauri Võsandi<br/>
|
||||
<i class="material-icons">phone</i> +372 5332 9412<br/>
|
||||
<i class="material-icons">email</i> lauri.vosandi@gmail.com
|
||||
</p>
|
||||
|
||||
<h5 class="white-text">Sponsors</h5>
|
||||
<h5 class="white-text">Partners</h5>
|
||||
<p class="grey-text text-lighten-4">
|
||||
We have more than 10 companies supporting us financially and by equipment
|
||||
</br>
|
||||
<a class="highlight" href="#">I want to become a sponsor</a>
|
||||
<ul>
|
||||
<li>Thorgate</li>
|
||||
<li>Stork Drives</li>
|
||||
<li>Tallinn University of Technology</li>
|
||||
<li>3D Partner</li>
|
||||
</ul>
|
||||
Contact us if you want to become a sponsor
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div class="col l4 offset-l2 s12">
|
||||
<h5 class="white-text">Links</h5>
|
||||
<ul>
|
||||
<li><a class="highlight" href="#!">Mission</a></li>
|
||||
<li><a class="highlight" href="#!">People</a></li>
|
||||
</ul>
|
||||
<p>We're located at Akadeemia tee 21/1, fifth floor. You can take elevator to 4th floor and then take stairs to the 5th</p>
|
||||
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1015.5421689053422!2d24.659768056865254!3d59.39830538168295!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x469295abf80677bd%3A0x89a6e8a5671f608b!2sAkadeemia+tee+21%2F1%2C+12618+Tallinn!5e0!3m2!1set!2see!4v1507405326247"
|
||||
width="350" height="200" frameborder="0" style="border:0" allowfullscreen></iframe>
|
||||
</div>
|
||||
@ -45,8 +46,13 @@
|
||||
</div>
|
||||
<div class="footer-copyright">
|
||||
<div class="container">
|
||||
© 2017 k-space
|
||||
<!-- <a class="grey-text text-lighten-4 right" href="#!">More Links</a> -->
|
||||
© 2017 K-SPACE MTÜ<br/>
|
||||
Registration number 80397632<br/>
|
||||
IBAN EE467700771002926893
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
@ -1,54 +1,68 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load markdownify %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row container">
|
||||
<div class="row">
|
||||
<div class="col m8">
|
||||
<h3 class="">{{ challenge.name }}</h3>
|
||||
|
||||
<div>
|
||||
{% for tag in challenge.tags.all %}
|
||||
<div class="chip">{{ tag.name }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p style="">{{ challenge.description }}
|
||||
</p>
|
||||
{% if challenge.description %}
|
||||
<p style="">{{ challenge.description | markdownify }}</p>
|
||||
{% else %}
|
||||
<p style="">{{ challenge.blurb | markdownify }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="section">
|
||||
<p>I am usually at k-space on weekends. Come and take a look.</p>
|
||||
<div class="valign-wrapper"><i class="material-icons">email</i> eric.cartman@email.com</div>
|
||||
<br>
|
||||
<div class="valign-wrapper"><i class="material-icons">phone</i> 55 55 5555</div>
|
||||
{% if challenge.creator.profile.contact_info %}
|
||||
<p>{{ challenge.creator.profile.contact_info }}</p>
|
||||
{% endif %}
|
||||
{% if challenge.creator.email %}
|
||||
<div class="valign-wrapper"><i class="material-icons">email</i> {{ challenge.creator.email }}</div>
|
||||
<br>
|
||||
{% endif %}
|
||||
{% if challenge.creator.profile.phone_number %}
|
||||
<div class="valign-wrapper"><i
|
||||
class="material-icons">phone</i> {{ challenge.creator.profile.phone_number }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col m4">
|
||||
<ul class="collection">
|
||||
<li class="collection-item avatar">
|
||||
<img src="https://vignette.wikia.nocookie.net/southpark/images/0/0d/1a.jpg/revision/latest/scale-to-width-down/310?cb=20100826182516"
|
||||
<img src="/media/{{ challenge.creator.profile.icon }}"
|
||||
alt="" class="circle">
|
||||
<span class="title">Author</span>
|
||||
<p><b>{{ challenge.creator.username }}</b></p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<span class="title">Programming</span>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<span class="title">Soldering</span>
|
||||
<p><b>{{ challenge.creator.get_full_name }}</b></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="collection with-header">
|
||||
<li class="collection-header">
|
||||
<span class="title"><b>What we need</b></span>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<span class="">CNC bench experience</span>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<span class="title">Screwdriver</span>
|
||||
</li>
|
||||
{% if challenge.tags.all %}
|
||||
<p>Relevant keywords:</p>
|
||||
<ul class="browser-default">
|
||||
{% for tag in challenge.tags.all %}
|
||||
<li class="collection-item">
|
||||
<span class="">{{ tag.name }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if challenge.required_items.all %}
|
||||
<p>Relevant inventory:</p>
|
||||
|
||||
<ul class="browser-default">
|
||||
{% for item in challenge.required_items.all %}
|
||||
{% if not item.hidden %}
|
||||
<li class="collection-item">
|
||||
<span class="">{{ item.item_name }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% load markdownify %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row container">
|
||||
<div class="section slogan">
|
||||
@ -10,28 +13,29 @@
|
||||
<div class="row">
|
||||
{% for challenge in challenges %}
|
||||
<div class="col s12 m4">
|
||||
<div class="card" style="height:350px;">
|
||||
<div class="card-content">
|
||||
<div class="row" style="height:210px;">
|
||||
<div class="col s12 m12">
|
||||
<div class="card-title"><b>{{ challenge.name }}</b></div>
|
||||
<p style="text-align: justify; max-height: 120px; overflow: auto;">{{ challenge.description }}</p>
|
||||
<div style="padding-top: 15px;">
|
||||
{% for tag in challenge.tags.all %}
|
||||
<div class="chip">{{ tag.name }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</br>
|
||||
<div class="row">
|
||||
<div class="col s12 m12">
|
||||
<div class="center-align">
|
||||
<a href="/challenge/{{ challenge.id }}" class="btn-large">I can do it</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
|
||||
|
||||
<div class="card-content" style="overflow: hidden; height:200px;">
|
||||
<div class="card-title"><b>{{ challenge.name }}</b></div>
|
||||
<p style="text-align: justify;">
|
||||
{% if challenge.blurb %}
|
||||
{{ challenge.blurb | markdownify }}
|
||||
{% else %}
|
||||
{{ challenge.description|slice:":500" | markdownify }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<div style="padding-top: 15px;">
|
||||
{% for tag in challenge.tags.all %}
|
||||
<div class="chip">{{ tag.name }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-action">
|
||||
<a href="/challenge/{{ challenge.id }}" class="btn-large lightlink">I can do it</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
<div class="row container section">
|
||||
{% for user in users %}
|
||||
{% if user.first_name or user.last_name %}
|
||||
<div class="col s12 m4">
|
||||
<div class="section center-align">
|
||||
<div class="card">
|
||||
@ -15,8 +16,8 @@
|
||||
<div class="card-image">
|
||||
<a href="/profile/{{ user.username }}"><img src='/media/{{ user.profile.icon }}'></a>
|
||||
</div>
|
||||
<h5 class="card-title" style="padding-top: 10px;color:black;"><a class='darklink'
|
||||
href="/profile/{{ user.username }}"><b>{{ user.username }}</b></a>
|
||||
<h5 class="card-title" style="padding-top: 10px;color:black;">
|
||||
<a class='darklink' href="/profile/{{ user.username }}"><b>{{ user.first_name }} {{ user.last_name }}</b></a>
|
||||
</h5>
|
||||
<div class="row">
|
||||
<div class="col s12 m1">
|
||||
@ -43,6 +44,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<head>
|
||||
<link rel="stylesheet" href="/static/css/index.css">
|
||||
<link rel="stylesheet" href="/static/css/index.css?ts=100">
|
||||
</head>
|
||||
|
||||
{% extends 'base_footer.html' %}
|
||||
@ -8,7 +8,7 @@
|
||||
<div class="headerblock section">
|
||||
|
||||
<div class="fadeimage"
|
||||
style="opacity:1;background-image:url('http://robot.itcollege.ee/assets/img/sumoesp-soldered.jpg')"></div>
|
||||
style="opacity:1;background-image:url('//media.k-space.ee/sumoesp-soldered.jpg')"></div>
|
||||
<!-- <div class="fadeimage" style="background-image:url('https://owncloud.koodur.com/index.php/apps/gallery/preview.public/1092117?width=2600&height=2600&c=d21f5a223e7ae8c692c537e6a35ae37f&requesttoken=TGJTDncMBCtJEG40Djt9HSUBIykoWn4bNwQpP09YAx4%3D%3A85kCFd3z8QYaaAKggYmQi%2F0mtMcmz7iSGQBOmq84Z50%3D&token=j0HUdRNEaZ37wGE')"></div>
|
||||
<div class="fadeimage" style="background-image:url('https://owncloud.koodur.com/index.php/apps/gallery/preview.public/1055905?width=2600&height=2600&c=a635e088958188e4490b17a91602366a&requesttoken=TGJTDncMBCtJEG40Djt9HSUBIykoWn4bNwQpP09YAx4%3D%3A85kCFd3z8QYaaAKggYmQi%2F0mtMcmz7iSGQBOmq84Z50%3D&token=j0HUdRNEaZ37wGE')"></div> -->
|
||||
|
||||
@ -93,7 +93,7 @@
|
||||
<a class="btn-large blue" href="/challenges">to ideas</a>
|
||||
</div>
|
||||
<div class="col s12 m4">
|
||||
<a href="#" class="btn-large amber ">to equipment</a>
|
||||
<a href="/inventory" class="btn-large amber ">to equipment</a>
|
||||
</div>
|
||||
<div class="col s12 m4">
|
||||
<a href="/halloffame" class="btn-large green ">to success</a>
|
||||
@ -126,134 +126,21 @@
|
||||
<div class="col s1"> </div>
|
||||
<div class="col s1">Office 20m<sup>2</sup></div>
|
||||
<div class="col s1"> </div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- SVG START -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 802.7 239.1" style="enable-background:new 0 0 802.7 239.1;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0 {
|
||||
fill: #26719B;
|
||||
stroke: #34495E;
|
||||
stroke-width: 5;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.st1 {
|
||||
fill: #3498DB;
|
||||
stroke: #34495E;
|
||||
stroke-width: 5;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.st2 {
|
||||
fill: #ECF0F1;
|
||||
stroke: #ECF0F1;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.st3 {
|
||||
fill: #ECF0F1;
|
||||
stroke: #ECF0F1;
|
||||
stroke-width: 0.5;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.st4 {
|
||||
fill: none;
|
||||
stroke: #ECF0F1;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
</style>
|
||||
<g id="bg">
|
||||
</g>
|
||||
<g id="Layer_1">
|
||||
<g id="XMLID_20_">
|
||||
<rect id="XMLID_14_" x="67.2" y="70.6" class="st0" width="265.8" height="29.8"/>
|
||||
<rect id="XMLID_16_" x="399.4" y="70.6" class="st0" width="265.8" height="29.8"/>
|
||||
</g>
|
||||
<g id="XMLID_17_">
|
||||
<rect id="XMLID_1_" x="0" y="100.9" class="st1" width="333" height="40.2"/>
|
||||
<rect id="XMLID_4_" x="67.2" y="141.2" class="st1" width="66.4" height="66.4"/>
|
||||
<rect id="XMLID_5_" x="0" y="176.4" class="st1" width="67.2" height="31.2"/>
|
||||
<rect id="XMLID_6_" x="133.6" y="141.2" class="st1" width="66.4" height="66.4"/>
|
||||
<rect id="XMLID_7_" x="333" y="141.2" class="st1" width="66.4" height="66.4"/>
|
||||
<polygon id="XMLID_3_" class="st1" points="33.6,100.4 0,100.4 0,46.3 14.3,31.5 33.6,31.5 "/>
|
||||
<rect id="XMLID_2_" x="398.9" y="100.4" class="st1" width="265.8" height="40.2"/>
|
||||
<rect id="XMLID_13_" x="531.8" y="140.6" class="st1" width="66.4" height="66.4"/>
|
||||
<rect id="XMLID_11_" x="598.3" y="140.6" class="st1" width="66.4" height="66.4"/>
|
||||
<polygon id="XMLID_8_" class="st1" points="698.3,100.4 664.7,100.4 664.7,46.3 679,31.5 698.3,31.5 "/>
|
||||
<rect id="XMLID_10_" x="333" y="100.9" class="st1" width="66.4" height="40.2"/>
|
||||
<polygon id="XMLID_12_" class="st1" points="365.3,100.4 398.9,100.4 398.9,46.3 384.6,31.5 365.3,31.5 "/>
|
||||
<polygon id="XMLID_9_" class="st1" points="769.2,207.1 732.2,207.1 732.2,140.6 664.7,140.6 664.7,100.4 769.2,100.4 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="jooned">
|
||||
<g id="XMLID_212_">
|
||||
<line id="XMLID_214_" class="st2" x1="16.3" y1="65.9" x2="16.3" y2="0"/>
|
||||
<ellipse id="XMLID_213_" class="st3" cx="16.3" cy="65.9" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_209_">
|
||||
<line id="XMLID_211_" class="st2" x1="166" y1="121.1" x2="166" y2="-0.2"/>
|
||||
<ellipse id="XMLID_210_" class="st3" cx="166" cy="121.1" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_206_">
|
||||
<line id="XMLID_208_" class="st2" x1="565" y1="120.6" x2="565" y2="-0.7"/>
|
||||
<ellipse id="XMLID_207_" class="st3" cx="565" cy="120.6" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_203_">
|
||||
<polyline id="XMLID_205_" class="st4" points="382.1,66 348.6,66 348.6,0 "/>
|
||||
<ellipse id="XMLID_204_" class="st3" cx="382.1" cy="66" rx="3.9" ry="4"/>
|
||||
</g>
|
||||
<g id="XMLID_200_">
|
||||
<line id="XMLID_202_" class="st2" x1="681.5" y1="65.7" x2="681.5" y2="-0.2"/>
|
||||
<ellipse id="XMLID_201_" class="st3" cx="681.5" cy="65.7" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_197_">
|
||||
<line id="XMLID_199_" class="st2" x1="33.1" y1="191.4" x2="33.1" y2="239.1"/>
|
||||
<ellipse id="XMLID_198_" class="st3" cx="33.1" cy="191.4" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_194_">
|
||||
<line id="XMLID_196_" class="st2" x1="99.9" y1="174.1" x2="99.9" y2="239.1"/>
|
||||
<ellipse id="XMLID_195_" class="st3" cx="99.9" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_191_">
|
||||
<polyline id="XMLID_193_" class="st4" points="166.8,174.4 230.9,174.4 230.9,239.1 "/>
|
||||
<ellipse id="XMLID_192_" class="st3" cx="166.8" cy="174.4" rx="3.9" ry="4"/>
|
||||
</g>
|
||||
<g id="XMLID_188_">
|
||||
<line id="XMLID_190_" class="st2" x1="365.7" y1="173.8" x2="365.7" y2="239.2"/>
|
||||
<ellipse id="XMLID_189_" class="st3" cx="365.7" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_185_">
|
||||
<line id="XMLID_187_" class="st2" x1="565" y1="173.8" x2="565" y2="239.1"/>
|
||||
<ellipse id="XMLID_186_" class="st3" cx="565" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g id="XMLID_182_">
|
||||
<line id="XMLID_184_" class="st2" x1="631.5" y1="173.8" x2="631.5" y2="239.1"/>
|
||||
<ellipse id="XMLID_183_" class="st3" cx="631.5" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{% include "map.svg" %}
|
||||
</div>
|
||||
|
||||
<div class="container white-text" id="svgtext">
|
||||
<div class="row">
|
||||
<div class="col s1">Servers</div>
|
||||
<div class="col s2">3D printers, lasercutter, soldering</div>
|
||||
<div class="col s2">CNC machine, saw, lathe, mill</div>
|
||||
<div class="col s1">Hangout area</div>
|
||||
<div class="col s2">Lounge, PC-s, IoT lab</div>
|
||||
<div class="col s2">Meeting room</div>
|
||||
<div class="col s2">Kitchen, toilet, sauna</div>
|
||||
|
||||
<div class="col s1"> </div>
|
||||
<div class="col s1">Meeting room</div>
|
||||
<div class="col s1">Lounge</div>
|
||||
<div class="col s1"> </div>
|
||||
<div class="col s1"> </div>
|
||||
<div class="col s2">Soldering irons, reflow oven, robotics lab</div>
|
||||
<div class="col s3">CNC machine, saw, lathe, mill, 3D printers, lasercutter</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -285,7 +172,7 @@
|
||||
|
||||
<div class="card-content">
|
||||
<div class="card-title">{{ challenge.name }}</div>
|
||||
<p style="text-align: justify; max-height: 120px; overflow: auto;">{{ challenge.description }}</p>
|
||||
<p style="height: 6em; overflow: auto;">{{ challenge.description }}</p>
|
||||
</br>
|
||||
<div>
|
||||
{% for tag in challenge.tags.all %}
|
||||
@ -306,5 +193,280 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section map z-depth-1">
|
||||
<div class="container white-text">
|
||||
<div class="row" style="margin-top: 32px">
|
||||
<div class="col s12 m6">
|
||||
<h2 class="">Team</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p>We have our roots in the Robotics Club of Estonian IT College as
|
||||
several key memebers are graduates of the College and were active Robotics Club members in the past.
|
||||
Most of us have numerous years of work experience in ICT sector and we've travelled the world to see how hackerspaces and makerspaces operate.
|
||||
We know that we've got what it takes to operate k-space.
|
||||
</p>
|
||||
|
||||
<div class="col s12 m3 black-text">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img src="https://media.licdn.com/mpr/mpr/shrinknp_200_200/p/8/000/1ad/2da/203cd14.jpg">
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-title">Lauri Võsandi</div>
|
||||
<p style="height: 6em; overflow: auto;">Founder of the k-space.
|
||||
<a href="http://www.lpi.org/our-certifications/lpic-3-300-overview">Certified Linux expert</a>. Python developer and systems integrator.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col s12 m3 black-text">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img src="https://media-exp2.licdn.com/mpr/mpr/shrinknp_200_200/AAEAAQAAAAAAAAetAAAAJDA1ZTNlMTA0LTJlZTEtNGM1NC05YzE3LTI4NDg0MzhmMjE5MQ.jpg"/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
|
||||
<div class="card-title">Allan Vein</div>
|
||||
<p style="height: 6em; overflow: auto;">Mr Inappropriate<br/> </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col s12 m3 black-text">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img src="//media.k-space.ee/members/erki.jpg"/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-title">Erki Naumanis</div>
|
||||
<p style="height: 6em; overflow: auto;">
|
||||
<a href="http://www.mesinikeliit.ee/aasta-mesinik-2016/">Beekeeper of the year 2016</a>. Builder of smart Internet enabled beehives</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col s12 m3 black-text">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img src="https://pbs.twimg.com/profile_images/2548581494/2011-06-22--02-timmu-and-laes_400x400.jpg"/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-title">Priit Laes</div>
|
||||
<p style="height: 6em; overflow: auto;">Embedded Linux systems expert and kernel developer</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12 m3 black-text">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img src="//media.k-space.ee/members/silver.jpg"/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-title">Silver Kuusik</div>
|
||||
<p style="height: 6em; overflow: auto;">Electronics schematic design & software development. Founder of <a href="http://www.robokoding.com/">Robokoding</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12 m3 black-text">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img src="//media.k-space.ee/minion.jpg"/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-title">Marek Juhanson</div>
|
||||
<p style="height: 6em; overflow: auto;">3D printing and product design</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12 m3 black-text">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img src="//media.k-space.ee/minion.jpg"/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-title">Jaan Jänesmäe</div>
|
||||
<p style="height: 6em; overflow: auto;">Drone building and 3D printing</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<p>Interested in joining the core team? Give Lauri a call and schedule for a visit.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container black-text">
|
||||
<div class="row" style="margin-top: 32px">
|
||||
<div class="col s12">
|
||||
<h2 class="" id="services">Events</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="col s12 m6">
|
||||
<p>In addition to the regular and not so regular events on the right we're in talks about hosting following as well:</p>
|
||||
<ul class="browser-default">
|
||||
<li>Laphack</li>
|
||||
<li>Python CodeClub</li>
|
||||
<li>Cryptocurrency interest groups</li>
|
||||
<li>Robotex prep arena</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col s12 m6">
|
||||
<iframe src="https://calendar.google.com/calendar/embed?showTitle=0&showNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&showTz=0&mode=AGENDA&height=400&wkst=2&hl=en&bgcolor=%23FFFFFF&src=m5irb4eke9npgk25nrb4qh41v4%40group.calendar.google.com&color=%236B3304&ctz=Europe%2FTallinn" style="border-width:0" width="100%" height="400" frameborder="0" scrolling="no"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container black-text">
|
||||
<div class="row" style="margin-top: 32px">
|
||||
<div class="col s12">
|
||||
<h2 class="" id="services">For individuals</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<p>For individuals we have several offers:</p>
|
||||
|
||||
<ul class="browser-default">
|
||||
<li>Environment to learn about the latest trends in IT and tech down to the hardware and electronics level</li>
|
||||
<li>Looking for a particular gadget to test out your idea? Raspberry Pi? Arduino? We got you covered!</li>
|
||||
<li>Location for you interest group activities, see more info <a href="https://wiki.k-space.ee/index.php?title=Events" target="_blank">here</a></li>
|
||||
<li>Use our equipment, we've got soldering stations, CNC machines, 3D printers and more</li>
|
||||
<li>Office space for your personal projects or freelance work. Renting a whole office on your own might not make sense, why not join us?</li>
|
||||
<li>As a bonus we also have a server room so you can get your machine up and online in no time</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col s12 m4">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<span class="card-title" style="font-family: 'Orbitron', cursive; font-size:200%;">Newbie</span>
|
||||
<p>Beginner package the get you started at our hackerspace</p>
|
||||
<ul class="browser-default">
|
||||
<li>Access to rooms 24/7</li>
|
||||
<li>Locker for personal belongings</li>
|
||||
<li>Access to common equipment</li>
|
||||
</ul>
|
||||
<p style="text-align:right; font-size:200%;font-family: 'Orbitron', cursive;">29€/month</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12 m4">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<span class="card-title" style="font-family: 'Orbitron', cursive; font-size:200%;">Resident</span>
|
||||
<p>In addition to the stuff on the left you get following for your freelance work or hobby projects:</p>
|
||||
<ul class="browser-default">
|
||||
<li>Personal desk</li>
|
||||
<li>Personal shelf</li>
|
||||
<li>Space in the server room</li>
|
||||
</ul>
|
||||
<p style="text-align:right; font-size:200%;font-family: 'Orbitron', cursive;">59€/month</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12 m4">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<span class="card-title" style="font-family: 'Orbitron', cursive; font-size:200%;">Office space</span>
|
||||
<p>In addition to the stuff on the left you get:</p>
|
||||
<ul class="browser-default">
|
||||
<li>Dedicated section of the hackerspace for your activities</li>
|
||||
</ul>
|
||||
<p style="text-align:right; font-size:200%;font-family: 'Orbitron', cursive;">99€/month</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="gallery" style="height:400px;">
|
||||
|
||||
<img src="//media.k-space.ee/nixiesp12.jpg"/
|
||||
><img src="//media.k-space.ee/basketball-robots-front.jpg"/
|
||||
><img src="//media.k-space.ee/nixiesp12-assembled.jpg"/
|
||||
><img src="//media.k-space.ee/basketball.jpg"/
|
||||
><img src="//media.k-space.ee/basketball-robot-base.jpg"/
|
||||
><img src="//media.k-space.ee/sumod-arsenalis.jpg"/
|
||||
><img src="//media.k-space.ee/sumoesp.jpg"/
|
||||
><img src="//media.k-space.ee/mass-produced-pcbs.jpg"/
|
||||
><img src="//media.k-space.ee/basketball-robots.jpg"/
|
||||
>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container black-text">
|
||||
<div class="row" style="margin-top: 32px">
|
||||
<div class="col s12">
|
||||
<h2 id="services">Services for students</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p>For students we offer several interesting opportunities:</p>
|
||||
<ul class="browser-default">
|
||||
<li>Internship opportunities and supervision, suggest a topic yourself or ask Lauri</li>
|
||||
<li>Desk and equipment for your thesis project, eg HackRF, Proxmark etc. Let us know what you need.</li>
|
||||
<li>Practice for Locked Shields test run</li>
|
||||
<li>Customized 3 ECTS course for your topic of interest</li>
|
||||
<li>Funding and equipment to participate at Robotex</li>
|
||||
</ul>
|
||||
<p>
|
||||
We participated with two football robots at Robotex 2016. Here's a sneak peek what the robot sees on-board:
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="position:relative;">
|
||||
<video loop autoplay width="100%">
|
||||
<source src="https://media.k-space.ee/zoidberg-football.mp4" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container black-text">
|
||||
<div class="row" style="margin-top: 32px">
|
||||
<div class="col s12">
|
||||
<h2 class="" id="services">Corporate interests</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p>We offer variety of interesting paid options for your company:</p>
|
||||
|
||||
<ul class="browser-default">
|
||||
<li>Organize your corporate event at our place. We can help with the entertainment and you have opportunity to meet new potential employees.</li>
|
||||
<li>Rent our gadgets and toys for a corporate event, eg sumorobots in your company's booth at a conference</li>
|
||||
<li>Invite us to come and fill in with the entertainment portion of your corporate event</li>
|
||||
<li>Location and equipment to carry out trainings ranging from Arduino-s, Raspberry Pi-s to radiocommunications and networking</li>
|
||||
<li>Provide your employees location and equipment to engage in hobby activities eg. 3D printing and building quadricopters</li>
|
||||
<li>Let us help with headhunting - provide us with a detailed description of what kind of people you're looking for and we'll help you to find them. Set up a roll-up stand at our hackerspace for more visibility. Send us your challenges, perhaps someone from here would like to tackle it.</li>
|
||||
<li>Corporate visibility at international robotics competiton Robotex. Our hackerspace members have participated repeatedly at the Robotex in the past. In 2018 we're planning to participate in the basketball robots and ICD grand challenge categories.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Contact Lauri via e-mail address below for more information</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
{% endblock %}
|
||||
|
34
templates/inventory.html
Normal file
34
templates/inventory.html
Normal file
@ -0,0 +1,34 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="row container">
|
||||
<div class="section slogan">
|
||||
<h2 class="center-align" style="font-weight:bold">Inventory<br></h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row container challenges">
|
||||
<div class="row">
|
||||
{% for item in inventory %}
|
||||
{% if not item.hidden %}
|
||||
<div class="col s12 m3">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-image">
|
||||
{% if item.photo %}
|
||||
<img src='/media/{{ item.photo }}'>
|
||||
{% else %}
|
||||
<img src='/media/missing_photo.png'>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="card-title"><b>{{ item.item_name }}</b></div>
|
||||
<p>Serial: {{ item.serial_nr }}</p>
|
||||
<p style="text-align: justify; max-height: 120px; overflow: auto;">{{ item.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
99
templates/logo.svg
Normal file
99
templates/logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 15 KiB |
101
templates/map.svg
Normal file
101
templates/map.svg
Normal file
@ -0,0 +1,101 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 802.7 239.1" style="enable-background:new 0 0 802.7 239.1;">
|
||||
<style type="text/css">
|
||||
.st0 {
|
||||
fill: #26719B;
|
||||
stroke: #34495E;
|
||||
stroke-width: 5;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.st1 {
|
||||
fill: #3498DB;
|
||||
stroke: #34495E;
|
||||
stroke-width: 5;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.st1:hover {
|
||||
fill: #77b9e7;
|
||||
transition: fill 0.3s;
|
||||
}
|
||||
|
||||
.st3 {
|
||||
fill: #ECF0F1;
|
||||
stroke: #ECF0F1;
|
||||
stroke-width: 0.5;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.st4 {
|
||||
fill: none;
|
||||
stroke: #ECF0F1;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="67.2" y="70.6" class="st0" width="265.8" height="29.8"/>
|
||||
<rect x="399.4" y="70.6" class="st0" width="265.8" height="29.8"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="0" y="100.9" class="st1" width="333" height="40.2"/>
|
||||
<rect x="67.2" y="141.2" class="st1" width="66.4" height="66.4"/>
|
||||
<rect x="0" y="176.4" class="st1" width="67.2" height="31.2"/>
|
||||
<rect x="133.6" y="141.2" class="st1" width="66.4" height="66.4"/>
|
||||
<rect x="333" y="141.2" class="st1" width="66.4" height="66.4"/>
|
||||
<polygon class="st1" points="33.6,100.4 0,100.4 0,46.3 14.3,31.5 33.6,31.5 "/>
|
||||
<rect x="398.9" y="100.4" class="st1" width="265.8" height="40.2"/>
|
||||
<rect x="531.8" y="140.6" class="st1" width="66.4" height="66.4"/>
|
||||
<rect x="598.3" y="140.6" class="st1" width="66.4" height="66.4"/>
|
||||
<polygon class="st1" points="698.3,100.4 664.7,100.4 664.7,46.3 679,31.5 698.3,31.5 "/>
|
||||
<rect x="333" y="100.9" class="st1" width="66.4" height="40.2"/>
|
||||
<polygon class="st1" points="365.3,100.4 398.9,100.4 398.9,46.3 384.6,31.5 365.3,31.5 "/>
|
||||
<polygon class="st1" points="769.2,207.1 732.2,207.1 732.2,140.6 664.7,140.6 664.7,100.4 769.2,100.4 "/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="16.3" y1="65.9" x2="16.3" y2="0"/>
|
||||
<ellipse class="st3" cx="16.3" cy="65.9" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="166" y1="121.1" x2="166" y2="-0.2"/>
|
||||
<ellipse class="st3" cx="166" cy="121.1" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="565" y1="120.6" x2="565" y2="-0.7"/>
|
||||
<ellipse class="st3" cx="565" cy="120.6" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline class="st4" points="382.1,66 348.6,66 348.6,0 "/>
|
||||
<ellipse class="st3" cx="382.1" cy="66" rx="3.9" ry="4"/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="681.5" y1="65.7" x2="681.5" y2="-0.2"/>
|
||||
<ellipse class="st3" cx="681.5" cy="65.7" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="33.1" y1="191.4" x2="33.1" y2="239.1"/>
|
||||
<ellipse class="st3" cx="33.1" cy="191.4" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="99.9" y1="174.1" x2="99.9" y2="239.1"/>
|
||||
<ellipse class="st3" cx="99.9" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline class="st4" points="166.8,174.4 230.9,174.4 230.9,239.1 "/>
|
||||
<ellipse class="st3" cx="166.8" cy="174.4" rx="3.9" ry="4"/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="365.7" y1="173.8" x2="365.7" y2="239.2"/>
|
||||
<ellipse class="st3" cx="365.7" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline class="st4" points="565.8,174.4 500,174.4 500,239.1 "/>
|
||||
<ellipse class="st3" cx="565" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<line class="st4" x1="631.5" y1="173.8" x2="631.5" y2="239.1"/>
|
||||
<ellipse class="st3" cx="631.5" cy="173.8" rx="4" ry="3.9"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
@ -2,7 +2,11 @@
|
||||
{% block content %}
|
||||
<div class="row container section">
|
||||
<div class="col s12 m12 l12">
|
||||
<h2 class="header center-align">{{ user.username }}</h2>
|
||||
{% if user.first_name or user.last_name %}
|
||||
<h2 class="header center-align">{{ user.first_name }} {{ user.last_name }}</h2>
|
||||
{% else %}
|
||||
<h2 class="header center-align">{{ user.username }}</h2>
|
||||
{% endif %}
|
||||
<div class="card horizontal" style="width:100%;">
|
||||
<div class="card-image">
|
||||
<img src="/media/{{ user.profile.icon }}">
|
||||
|
Reference in New Issue
Block a user