Initial Commit
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
TSDMaster/TSDMaster/migrations/
|
||||
venv/
|
||||
TSDMaster/TSDMaster/settings.py
|
||||
TSDMaster/db.sqlite
|
||||
*.py[cod]
|
||||
__pycache__/
|
||||
.idea/
|
||||
4
README.md
Normal file
4
README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# TestSys Docker
|
||||
This is the testing system for code competitions or trainings.
|
||||
The Master service is written on Django (Python 3) and handles WebUI.
|
||||
Slaves are obviously uses Docker to run code tests.
|
||||
0
TSDMaster/TSDMaster/__init__.py
Normal file
0
TSDMaster/TSDMaster/__init__.py
Normal file
3
TSDMaster/TSDMaster/admin.py
Normal file
3
TSDMaster/TSDMaster/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
5
TSDMaster/TSDMaster/apps.py
Normal file
5
TSDMaster/TSDMaster/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class TsdmasterConfig(AppConfig):
|
||||
name = 'TSDMaster'
|
||||
18
TSDMaster/TSDMaster/forms.py
Normal file
18
TSDMaster/TSDMaster/forms.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""
|
||||
Definition of forms.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from django import forms
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
class BootstrapAuthenticationForm(AuthenticationForm):
|
||||
"""Authentication form which uses boostrap CSS."""
|
||||
username = forms.CharField(max_length=254,
|
||||
widget=forms.TextInput({
|
||||
'class': 'form-control',
|
||||
'placeholder': 'User name'}))
|
||||
password = forms.CharField(label=_("Password"),
|
||||
widget=forms.PasswordInput({
|
||||
'class': 'form-control',
|
||||
'placeholder':'Password'}))
|
||||
3
TSDMaster/TSDMaster/models.py
Normal file
3
TSDMaster/TSDMaster/models.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
7
TSDMaster/TSDMaster/static/content/bootstrap.min.css
vendored
Normal file
7
TSDMaster/TSDMaster/static/content/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TSDMaster/TSDMaster/static/content/bootstrap.min.css.map
Normal file
1
TSDMaster/TSDMaster/static/content/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
41
TSDMaster/TSDMaster/static/content/site.css
Normal file
41
TSDMaster/TSDMaster/static/content/site.css
Normal file
@@ -0,0 +1,41 @@
|
||||
.body-padding {
|
||||
padding: 5rem 1.5rem;
|
||||
}
|
||||
|
||||
/* Set padding to keep content from hitting the edges */
|
||||
.body-content {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
/* Set width on the form input elements since they're 100% wide by default */
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
/* styles for validation helpers */
|
||||
.field-validation-error {
|
||||
color: #b94a48;
|
||||
}
|
||||
|
||||
.field-validation-valid {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input.input-validation-error {
|
||||
border: 1px solid #b94a48;
|
||||
}
|
||||
|
||||
input[type="checkbox"].input-validation-error {
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
.validation-summary-errors {
|
||||
color: #b94a48;
|
||||
}
|
||||
|
||||
.validation-summary-valid {
|
||||
display: none;
|
||||
}
|
||||
7
TSDMaster/TSDMaster/static/scripts/bootstrap.min.js
vendored
Normal file
7
TSDMaster/TSDMaster/static/scripts/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TSDMaster/TSDMaster/static/scripts/bootstrap.min.js.map
Normal file
1
TSDMaster/TSDMaster/static/scripts/bootstrap.min.js.map
Normal file
File diff suppressed because one or more lines are too long
10253
TSDMaster/TSDMaster/static/scripts/jquery.js
vendored
Normal file
10253
TSDMaster/TSDMaster/static/scripts/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
TSDMaster/TSDMaster/static/scripts/jquery.min.js
vendored
Normal file
4
TSDMaster/TSDMaster/static/scripts/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TSDMaster/TSDMaster/static/scripts/jquery.min.js.map
Normal file
1
TSDMaster/TSDMaster/static/scripts/jquery.min.js.map
Normal file
File diff suppressed because one or more lines are too long
1406
TSDMaster/TSDMaster/static/scripts/modernizr.js
Normal file
1406
TSDMaster/TSDMaster/static/scripts/modernizr.js
Normal file
File diff suppressed because it is too large
Load Diff
1
TSDMaster/TSDMaster/static/scripts/modernizr.min.js
vendored
Normal file
1
TSDMaster/TSDMaster/static/scripts/modernizr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2445
TSDMaster/TSDMaster/static/scripts/popper.js
Normal file
2445
TSDMaster/TSDMaster/static/scripts/popper.js
Normal file
File diff suppressed because it is too large
Load Diff
5
TSDMaster/TSDMaster/static/scripts/popper.min.js
vendored
Normal file
5
TSDMaster/TSDMaster/static/scripts/popper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TSDMaster/TSDMaster/static/scripts/popper.min.js.map
Normal file
1
TSDMaster/TSDMaster/static/scripts/popper.min.js.map
Normal file
File diff suppressed because one or more lines are too long
224
TSDMaster/TSDMaster/static/scripts/respond.js
Normal file
224
TSDMaster/TSDMaster/static/scripts/respond.js
Normal file
@@ -0,0 +1,224 @@
|
||||
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
|
||||
/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
|
||||
(function(w) {
|
||||
"use strict";
|
||||
w.matchMedia = w.matchMedia || function(doc, undefined) {
|
||||
var bool, docElem = doc.documentElement, refNode = docElem.firstElementChild || docElem.firstChild, fakeBody = doc.createElement("body"), div = doc.createElement("div");
|
||||
div.id = "mq-test-1";
|
||||
div.style.cssText = "position:absolute;top:-100em";
|
||||
fakeBody.style.background = "none";
|
||||
fakeBody.appendChild(div);
|
||||
return function(q) {
|
||||
div.innerHTML = '­<style media="' + q + '"> #mq-test-1 { width: 42px; }</style>';
|
||||
docElem.insertBefore(fakeBody, refNode);
|
||||
bool = div.offsetWidth === 42;
|
||||
docElem.removeChild(fakeBody);
|
||||
return {
|
||||
matches: bool,
|
||||
media: q
|
||||
};
|
||||
};
|
||||
}(w.document);
|
||||
})(this);
|
||||
|
||||
/*! Respond.js v1.4.0: min/max-width media query polyfill. (c) Scott Jehl. MIT Lic. j.mp/respondjs */
|
||||
(function(w) {
|
||||
"use strict";
|
||||
var respond = {};
|
||||
w.respond = respond;
|
||||
respond.update = function() {};
|
||||
var requestQueue = [], xmlHttp = function() {
|
||||
var xmlhttpmethod = false;
|
||||
try {
|
||||
xmlhttpmethod = new w.XMLHttpRequest();
|
||||
} catch (e) {
|
||||
xmlhttpmethod = new w.ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
return function() {
|
||||
return xmlhttpmethod;
|
||||
};
|
||||
}(), ajax = function(url, callback) {
|
||||
var req = xmlHttp();
|
||||
if (!req) {
|
||||
return;
|
||||
}
|
||||
req.open("GET", url, true);
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) {
|
||||
return;
|
||||
}
|
||||
callback(req.responseText);
|
||||
};
|
||||
if (req.readyState === 4) {
|
||||
return;
|
||||
}
|
||||
req.send(null);
|
||||
};
|
||||
respond.ajax = ajax;
|
||||
respond.queue = requestQueue;
|
||||
respond.regex = {
|
||||
media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,
|
||||
keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,
|
||||
urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,
|
||||
findStyles: /@media *([^\{]+)\{([\S\s]+?)$/,
|
||||
only: /(only\s+)?([a-zA-Z]+)\s?/,
|
||||
minw: /\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,
|
||||
maxw: /\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/
|
||||
};
|
||||
respond.mediaQueriesSupported = w.matchMedia && w.matchMedia("only all") !== null && w.matchMedia("only all").matches;
|
||||
if (respond.mediaQueriesSupported) {
|
||||
return;
|
||||
}
|
||||
var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName("head")[0] || docElem, base = doc.getElementsByTagName("base")[0], links = head.getElementsByTagName("link"), lastCall, resizeDefer, eminpx, getEmValue = function() {
|
||||
var ret, div = doc.createElement("div"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false;
|
||||
div.style.cssText = "position:absolute;font-size:1em;width:1em";
|
||||
if (!body) {
|
||||
body = fakeUsed = doc.createElement("body");
|
||||
body.style.background = "none";
|
||||
}
|
||||
docElem.style.fontSize = "100%";
|
||||
body.style.fontSize = "100%";
|
||||
body.appendChild(div);
|
||||
if (fakeUsed) {
|
||||
docElem.insertBefore(body, docElem.firstChild);
|
||||
}
|
||||
ret = div.offsetWidth;
|
||||
if (fakeUsed) {
|
||||
docElem.removeChild(body);
|
||||
} else {
|
||||
body.removeChild(div);
|
||||
}
|
||||
docElem.style.fontSize = originalHTMLFontSize;
|
||||
if (originalBodyFontSize) {
|
||||
body.style.fontSize = originalBodyFontSize;
|
||||
}
|
||||
ret = eminpx = parseFloat(ret);
|
||||
return ret;
|
||||
}, applyMedia = function(fromResize) {
|
||||
var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();
|
||||
if (fromResize && lastCall && now - lastCall < resizeThrottle) {
|
||||
w.clearTimeout(resizeDefer);
|
||||
resizeDefer = w.setTimeout(applyMedia, resizeThrottle);
|
||||
return;
|
||||
} else {
|
||||
lastCall = now;
|
||||
}
|
||||
for (var i in mediastyles) {
|
||||
if (mediastyles.hasOwnProperty(i)) {
|
||||
var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em";
|
||||
if (!!min) {
|
||||
min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
|
||||
}
|
||||
if (!!max) {
|
||||
max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
|
||||
}
|
||||
if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {
|
||||
if (!styleBlocks[thisstyle.media]) {
|
||||
styleBlocks[thisstyle.media] = [];
|
||||
}
|
||||
styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var j in appendedEls) {
|
||||
if (appendedEls.hasOwnProperty(j)) {
|
||||
if (appendedEls[j] && appendedEls[j].parentNode === head) {
|
||||
head.removeChild(appendedEls[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
appendedEls.length = 0;
|
||||
for (var k in styleBlocks) {
|
||||
if (styleBlocks.hasOwnProperty(k)) {
|
||||
var ss = doc.createElement("style"), css = styleBlocks[k].join("\n");
|
||||
ss.type = "text/css";
|
||||
ss.media = k;
|
||||
head.insertBefore(ss, lastLink.nextSibling);
|
||||
if (ss.styleSheet) {
|
||||
ss.styleSheet.cssText = css;
|
||||
} else {
|
||||
ss.appendChild(doc.createTextNode(css));
|
||||
}
|
||||
appendedEls.push(ss);
|
||||
}
|
||||
}
|
||||
}, translate = function(styles, href, media) {
|
||||
var qs = styles.replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0;
|
||||
href = href.substring(0, href.lastIndexOf("/"));
|
||||
var repUrls = function(css) {
|
||||
return css.replace(respond.regex.urls, "$1" + href + "$2$3");
|
||||
}, useMedia = !ql && media;
|
||||
if (href.length) {
|
||||
href += "/";
|
||||
}
|
||||
if (useMedia) {
|
||||
ql = 1;
|
||||
}
|
||||
for (var i = 0; i < ql; i++) {
|
||||
var fullq, thisq, eachq, eql;
|
||||
if (useMedia) {
|
||||
fullq = media;
|
||||
rules.push(repUrls(styles));
|
||||
} else {
|
||||
fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;
|
||||
rules.push(RegExp.$2 && repUrls(RegExp.$2));
|
||||
}
|
||||
eachq = fullq.split(",");
|
||||
eql = eachq.length;
|
||||
for (var j = 0; j < eql; j++) {
|
||||
thisq = eachq[j];
|
||||
mediastyles.push({
|
||||
media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all",
|
||||
rules: rules.length - 1,
|
||||
hasquery: thisq.indexOf("(") > -1,
|
||||
minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""),
|
||||
maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "")
|
||||
});
|
||||
}
|
||||
}
|
||||
applyMedia();
|
||||
}, makeRequests = function() {
|
||||
if (requestQueue.length) {
|
||||
var thisRequest = requestQueue.shift();
|
||||
ajax(thisRequest.href, function(styles) {
|
||||
translate(styles, thisRequest.href, thisRequest.media);
|
||||
parsedSheets[thisRequest.href] = true;
|
||||
w.setTimeout(function() {
|
||||
makeRequests();
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}, ripCSS = function() {
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
|
||||
if (!!href && isCSS && !parsedSheets[href]) {
|
||||
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
|
||||
translate(sheet.styleSheet.rawCssText, href, media);
|
||||
parsedSheets[href] = true;
|
||||
} else {
|
||||
if (!/^([a-zA-Z:]*\/\/)/.test(href) && !base || href.replace(RegExp.$1, "").split("/")[0] === w.location.host) {
|
||||
if (href.substring(0, 2) === "//") {
|
||||
href = w.location.protocol + href;
|
||||
}
|
||||
requestQueue.push({
|
||||
href: href,
|
||||
media: media
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
makeRequests();
|
||||
};
|
||||
ripCSS();
|
||||
respond.update = ripCSS;
|
||||
respond.getEmValue = getEmValue;
|
||||
function callMedia() {
|
||||
applyMedia(true);
|
||||
}
|
||||
if (w.addEventListener) {
|
||||
w.addEventListener("resize", callMedia, false);
|
||||
} else if (w.attachEvent) {
|
||||
w.attachEvent("onresize", callMedia);
|
||||
}
|
||||
})(this);
|
||||
5
TSDMaster/TSDMaster/static/scripts/respond.min.js
vendored
Normal file
5
TSDMaster/TSDMaster/static/scripts/respond.min.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
||||
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
||||
* */
|
||||
|
||||
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
||||
6
TSDMaster/TSDMaster/templates/home.html
Normal file
6
TSDMaster/TSDMaster/templates/home.html
Normal file
@@ -0,0 +1,6 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% load i18n %}
|
||||
<h1>TestSys</h1>
|
||||
{% endblock %}
|
||||
45
TSDMaster/TSDMaster/templates/layout.html
Normal file
45
TSDMaster/TSDMaster/templates/layout.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
{% load i18n %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
<html lang="{{ LANGUAGE_CODE }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>{{ title }} - {{ company_name }}</title>
|
||||
{% load staticfiles %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'content/bootstrap.min.css' %}" />
|
||||
<script src="{% static 'scripts/modernizr.min.js' %}"></script>
|
||||
<script src="{% static 'scripts/respond.min.js' %}"></script>
|
||||
<script src="{% static 'scripts/jquery.min.js' %}"></script>
|
||||
<script src="{% static 'scripts/popper.min.js' %}"></script>
|
||||
<script src="{% static 'scripts/bootstrap.min.js' %}"></script>
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'content/site.css' %}" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
|
||||
<a class="navbar-brand" href="{% url 'home' %}">{{ company_name }}</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbar">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="{% url 'home' %}">Home</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
{% include 'loginpartial.html' %}
|
||||
</div>
|
||||
</nav>
|
||||
<main role="main" class="container body-content body-padding">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<hr class="col-md-12"/>
|
||||
<footer>
|
||||
<p class="col-md-12">© {% now "Y" %} - {{ company_name }} - <a href="{% url 'home' %}">TestSysDocker Project by Vladislav Utkin</a> </p>
|
||||
</footer>
|
||||
</main>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
42
TSDMaster/TSDMaster/templates/login.html
Normal file
42
TSDMaster/TSDMaster/templates/login.html
Normal file
@@ -0,0 +1,42 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2>{{ title }}</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<section id="loginForm">
|
||||
<form action="." method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<h4>Use a local account to log in.</h4>
|
||||
<hr />
|
||||
<div class="form-group">
|
||||
<label for="id_username" class="col-md-2 control-label">User name</label>
|
||||
<div class="col-md-10">
|
||||
{{ form.username }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="id_password" class="col-md-2 control-label">Password</label>
|
||||
<div class="col-md-10">
|
||||
{{ form.password }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-2 col-md-10">
|
||||
<input type="hidden" name="next" value="/" />
|
||||
<input type="submit" value="Log in" class="btn btn-default" />
|
||||
</div>
|
||||
</div>
|
||||
{% if form.errors %}
|
||||
<p class="validation-summary-errors">Please enter a correct user name and password.</p>
|
||||
{% endif %}
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<section id="socialLoginForm"></section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
14
TSDMaster/TSDMaster/templates/loginpartial.html
Normal file
14
TSDMaster/TSDMaster/templates/loginpartial.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% load i18n %}
|
||||
{% if user.is_authenticated %}
|
||||
<form id="logoutForm" action="{% url 'logout' %}" method="post" class="navbar-right">
|
||||
{% csrf_token %}
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><span class="navbar-brand">{{ user.name }}</span></li>
|
||||
<li><a href="javascript:document.getElementById('logoutForm').submit()">{% trans "Logout" %}</a></li>
|
||||
</ul>
|
||||
</form>
|
||||
{% else %}
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="{% url 'login' %}">{% trans "Login" %}</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
12
TSDMaster/TSDMaster/tests.py
Normal file
12
TSDMaster/TSDMaster/tests.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Tests here.
|
||||
|
||||
|
||||
class ViewTest(TestCase):
|
||||
"""Test Views"""
|
||||
|
||||
def test_home(self):
|
||||
"""Test home page"""
|
||||
response = self.client.get('/')
|
||||
self.assertContains(response, 'TestSys', 2, 200)
|
||||
44
TSDMaster/TSDMaster/urls.py
Normal file
44
TSDMaster/TSDMaster/urls.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""TSysDocker URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/1.11/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
||||
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 datetime import datetime
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib import admin
|
||||
import django.contrib.auth.views
|
||||
from TSDMaster import views
|
||||
from TSDMaster import forms
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.home, name='home'),
|
||||
url(r'^login/$',
|
||||
django.contrib.auth.views.login,
|
||||
{
|
||||
'template_name': 'login.html',
|
||||
'authentication_form': forms.BootstrapAuthenticationForm,
|
||||
'extra_context':
|
||||
{
|
||||
'title': 'Log in',
|
||||
'year': datetime.now().year,
|
||||
}
|
||||
},
|
||||
name='login'),
|
||||
url(r'^logout$',
|
||||
django.contrib.auth.views.logout,
|
||||
{
|
||||
'next_page': '/',
|
||||
},
|
||||
name='logout'),
|
||||
url(r'^admin/', admin.site.urls),
|
||||
]
|
||||
12
TSDMaster/TSDMaster/views.py
Normal file
12
TSDMaster/TSDMaster/views.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.shortcuts import render
|
||||
from django.conf import settings
|
||||
|
||||
# TestSys views here.
|
||||
|
||||
|
||||
def home(request):
|
||||
return render(request, 'home.html',
|
||||
{
|
||||
'title': 'Home',
|
||||
'company_name': settings.COMPANY_NAME,
|
||||
})
|
||||
16
TSDMaster/TSDMaster/wsgi.py
Normal file
16
TSDMaster/TSDMaster/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for TSysDocker 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", "settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
25
TSDMaster/manage.py
Executable file
25
TSDMaster/manage.py
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
if os.path.isfile('settings'):
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
|
||||
else:
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings_example")
|
||||
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)
|
||||
120
TSDMaster/settings_example.py
Normal file
120
TSDMaster/settings_example.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""
|
||||
Django settings for TSysDocker project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.11.7.
|
||||
|
||||
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
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'a9bp=ohqs-)l=u8b9=m635z*hf_*w-j-5@u)#y$ucc3ne9s^tw'
|
||||
|
||||
# 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',
|
||||
'TSDMaster.apps.TsdmasterConfig',
|
||||
]
|
||||
|
||||
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 = 'TSDMaster.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 = 'TSDMaster.wsgi.application'
|
||||
|
||||
|
||||
# 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',
|
||||
},
|
||||
]
|
||||
|
||||
# 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'),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en'
|
||||
|
||||
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/'
|
||||
|
||||
# App settings
|
||||
COMPANY_NAME = 'TestSys'
|
||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
django
|
||||
Reference in New Issue
Block a user