Code refactored to be ready for solar upgrade. Many other minor fixes.
This commit is contained in:
parent
c1d6cbbb70
commit
e99eb5a68a
310
app.py
310
app.py
|
@ -1,57 +1,14 @@
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import hashlib
|
|
||||||
import time
|
|
||||||
import ssl
|
|
||||||
import configparser
|
import configparser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from flask import Flask, render_template, request
|
from flask import Flask, render_template, request
|
||||||
from flask_dropzone import Dropzone
|
from flask_dropzone import Dropzone
|
||||||
|
|
||||||
import imaplib
|
import portal.base
|
||||||
from smtplib import SMTP_SSL
|
|
||||||
|
|
||||||
import email
|
# TODO: Put all the stuff in base.py into a class, so it can have a state of it's own, to avoid passing a bunch of arguments at each function call.
|
||||||
from email import encoders
|
|
||||||
from email.mime.base import MIMEBase
|
|
||||||
from email.mime.multipart import MIMEMultipart
|
|
||||||
from email.mime.text import MIMEText
|
|
||||||
from email.mime.application import MIMEApplication
|
|
||||||
|
|
||||||
import pdfkit
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
|
||||||
|
|
||||||
|
|
||||||
class ContractCreator:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
template_loader = FileSystemLoader(searchpath="./")
|
|
||||||
template_env = Environment(loader=template_loader)
|
|
||||||
self.template = template_env.get_template('contract/template.html')
|
|
||||||
|
|
||||||
self.pdfkit_options = {
|
|
||||||
'page-size': 'A4',
|
|
||||||
'margin-top': '0.75in',
|
|
||||||
'margin-right': '0.75in',
|
|
||||||
'margin-bottom': '0.75in',
|
|
||||||
'margin-left': '0.75in',
|
|
||||||
'encoding': "UTF-8",
|
|
||||||
'custom-header' : [
|
|
||||||
('Accept-Encoding', 'gzip')
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
def fill_template(self, **kwargs):
|
|
||||||
return self.template.render(**kwargs)
|
|
||||||
|
|
||||||
def create_pdf(self, out_f, fields_dict):
|
|
||||||
html_str = self.fill_template(**fields_dict)
|
|
||||||
pdfkit.from_string(html_str, out_f, options=self.pdfkit_options)
|
|
||||||
|
|
||||||
|
|
||||||
ENABLED_FILETYPES = ['txt', 'csv', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
|
|
||||||
REGEX_EMAIL = re.compile('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')
|
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Load configuration #
|
# Load configuration #
|
||||||
|
@ -67,10 +24,22 @@ SMTP_PORT = int(config['SMTP_PORT'])
|
||||||
IMAP_PORT = int(config['IMAP_PORT'])
|
IMAP_PORT = int(config['IMAP_PORT'])
|
||||||
MAX_UPLOAD_SIZE = int(config['MAX_UPLOAD_SIZE']) # Bytes
|
MAX_UPLOAD_SIZE = int(config['MAX_UPLOAD_SIZE']) # Bytes
|
||||||
CONTRACT_CLIENT_CONTACT = config['CONTRACT_CLIENT_CONTACT']
|
CONTRACT_CLIENT_CONTACT = config['CONTRACT_CLIENT_CONTACT']
|
||||||
if 'BASE_DIR' in config:
|
MAIL_SUBJECT = config['MAIL_SUBJECT']
|
||||||
BASE_DIR = Path(config['BASE_DIR'])
|
MAIL_BODY = config['MAIL_BODY']
|
||||||
|
|
||||||
|
if 'UPLOADS_DIR' in config:
|
||||||
|
UPLOADS_DIR = Path(config['UPLOADS_DIR'])
|
||||||
else:
|
else:
|
||||||
BASE_DIR = Path(__file__).resolve().parent
|
UPLOADS_DIR = Path(__file__).resolve().parent / 'uploads'
|
||||||
|
if not UPLOADS_DIR.exists:
|
||||||
|
UPLOADS_DIR.mkdir(parents=True)
|
||||||
|
|
||||||
|
if 'DATA_DIR' in config:
|
||||||
|
DATA_DIR = Path(config['DATA_DIR'])
|
||||||
|
else:
|
||||||
|
DATA_DIR = Path(__file__).resolve().parent / 'data'
|
||||||
|
if not DATA_DIR.exists:
|
||||||
|
DATA_DIR.mkdir(parents=True)
|
||||||
|
|
||||||
# Override configs with environment variables, if set
|
# Override configs with environment variables, if set
|
||||||
if 'PORTALDS4DS1_MAIL_HOST' in os.environ:
|
if 'PORTALDS4DS1_MAIL_HOST' in os.environ:
|
||||||
|
@ -87,243 +56,86 @@ if 'PORTALDS4DS1_MAX_UPLOAD_SIZE' in os.environ:
|
||||||
MAX_UPLOAD_SIZE = int(os.environ['PORTALDS4DS1_MAX_UPLOAD_SIZE'])
|
MAX_UPLOAD_SIZE = int(os.environ['PORTALDS4DS1_MAX_UPLOAD_SIZE'])
|
||||||
if 'PORTALDS4DS1_CONTRACT_CLIENT_CONTACT' in os.environ:
|
if 'PORTALDS4DS1_CONTRACT_CLIENT_CONTACT' in os.environ:
|
||||||
CONTRACT_CLIENT_CONTACT = os.environ['PORTALDS4DS1_CONTRACT_CLIENT_CONTACT']
|
CONTRACT_CLIENT_CONTACT = os.environ['PORTALDS4DS1_CONTRACT_CLIENT_CONTACT']
|
||||||
|
if 'PORTALDS4DS1_UPLOADS_DIR' in os.environ:
|
||||||
|
UPLOADS_DIR = os.environ['PORTALDS4DS1_UPLOADS_DIR']
|
||||||
|
if 'PORTALDS4DS1_DATA_DIR' in os.environ:
|
||||||
|
DATA_DIR = os.environ['PORTALDS4DS1_DATA_DIR']
|
||||||
|
if 'PORTALDS4DS1_MAIL_SUBJECT' in os.environ:
|
||||||
|
MAIL_SUBJECT = os.environ['PORTALDS4DS1_MAIL_SUBJECT']
|
||||||
|
if 'PORTALDS4DS1_MAIL_BODY' in os.environ:
|
||||||
|
MAIL_BODY = os.environ['PORTALDS4DS1_MAIL_BODY']
|
||||||
|
|
||||||
|
VALID_CORPUS_NAMES = ['prevodi', 'gigafida', 'solar']
|
||||||
|
|
||||||
UPLOAD_DIR = BASE_DIR / 'uploads'
|
|
||||||
if not UPLOAD_DIR.exists:
|
|
||||||
UPLOAD_DIR.mkdir(parents=True)
|
|
||||||
|
|
||||||
######################
|
######################
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
app.config.update(
|
app.config.update(
|
||||||
UPLOADED_PATH = UPLOAD_DIR,
|
UPLOADED_PATH = UPLOADS_DIR,
|
||||||
MAX_CONTENT_LENGTH = MAX_UPLOAD_SIZE,
|
MAX_CONTENT_LENGTH = MAX_UPLOAD_SIZE,
|
||||||
TEMPLATES_AUTO_RELOAD = True
|
TEMPLATES_AUTO_RELOAD = True
|
||||||
)
|
)
|
||||||
|
|
||||||
dropzone = Dropzone(app)
|
dropzone = Dropzone(app)
|
||||||
|
|
||||||
contract_creator = ContractCreator()
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/upload', methods=['POST'])
|
@app.route('/<corpus_name>')
|
||||||
def handle_upload():
|
def index_corpus(corpus_name):
|
||||||
|
if corpus_name not in VALID_CORPUS_NAMES:
|
||||||
|
return 'Korpus "{}" ne obstaja.'.format(corpus_name), 404
|
||||||
|
if corpus_name == 'prevodi':
|
||||||
|
subtitle = 'KORPUS PARALELNIH BESEDIL ANG-SLO'
|
||||||
|
elif corpus_name == 'gigafida':
|
||||||
|
subtitle = 'KORPUS GIGAFIDA'
|
||||||
|
return render_template('basic.html', subtitle=subtitle, corpus_name=corpus_name)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/<corpus_name>/upload', methods=['POST'])
|
||||||
|
def handle_upload(corpus_name):
|
||||||
|
if corpus_name not in VALID_CORPUS_NAMES:
|
||||||
|
return 404
|
||||||
|
|
||||||
files = request.files
|
files = request.files
|
||||||
if len(files) > 20:
|
if len(files) > 20:
|
||||||
return 'Naložite lahko do 20 datotek hkrati.', 400
|
return 'Naložite lahko do 20 datotek hkrati.', 400
|
||||||
elif len(files) < 1:
|
elif len(files) < 1:
|
||||||
return 'Priložena ni bila nobena datoteka.', 400
|
return 'Priložena ni bila nobena datoteka.', 400
|
||||||
|
|
||||||
err = check_suffixes(files)
|
print('one')
|
||||||
|
err = portal.base.check_suffixes(files)
|
||||||
if err:
|
if err:
|
||||||
return err, 400
|
return err, 400
|
||||||
|
|
||||||
err = check_form(request.form)
|
print('two')
|
||||||
|
err = portal.base.check_form(request.form)
|
||||||
if err:
|
if err:
|
||||||
return err, 400
|
return err, 400
|
||||||
|
|
||||||
upload_metadata = get_upload_metadata(request)
|
print('three')
|
||||||
contract_file_name = generate_contract_pdf(upload_metadata)
|
upload_metadata = portal.base.get_upload_metadata(corpus_name, request)
|
||||||
|
contract_file_name = portal.base.generate_contract_pdf(UPLOADS_DIR, upload_metadata, CONTRACT_CLIENT_CONTACT)
|
||||||
|
|
||||||
# Add contract_file_name to metadata TODO: move somewhere else
|
# Add contract_file_name to metadata TODO: move somewhere else
|
||||||
upload_metadata['contract'] = contract_file_name
|
upload_metadata['contract'] = contract_file_name
|
||||||
store_datafiles(files, upload_metadata)
|
portal.base.store_datafiles(UPLOADS_DIR, files, upload_metadata)
|
||||||
store_metadata(upload_metadata)
|
portal.base.store_metadata(UPLOADS_DIR, upload_metadata)
|
||||||
send_confirm_mail(upload_metadata)
|
portal.base.send_confirm_mail(
|
||||||
|
subject=MAIL_SUBJECT,
|
||||||
|
body=MAIL_BODY,
|
||||||
|
uploads_path=UPLOADS_DIR,
|
||||||
|
upload_metadata=upload_metadata,
|
||||||
|
mail_host=MAIL_HOST, mail_login=MAIL_LOGIN, mail_pass=MAIL_PASS,
|
||||||
|
imap_port=IMAP_PORT, smtp_port=SMTP_PORT)
|
||||||
|
|
||||||
return 'Uspešno ste oddali datotek(e). Št. datotek: {}'.format(len(files))
|
return 'Uspešno ste oddali datotek(e). Št. datotek: {}'.format(len(files))
|
||||||
|
|
||||||
|
|
||||||
def get_upload_metadata(request):
|
|
||||||
upload_metadata = dict()
|
|
||||||
|
|
||||||
file_hashes = create_file_hashes(request.files)
|
|
||||||
form_data = request.form.copy()
|
|
||||||
upload_timestamp = int(time.time())
|
|
||||||
upload_id = create_upload_id(form_data, upload_timestamp, file_hashes)
|
|
||||||
|
|
||||||
upload_metadata['form_data'] = form_data
|
|
||||||
upload_metadata['upload_id'] = upload_id
|
|
||||||
upload_metadata['timestamp'] = upload_timestamp
|
|
||||||
upload_metadata['file_hashes'] = file_hashes
|
|
||||||
|
|
||||||
return upload_metadata
|
|
||||||
|
|
||||||
def check_suffixes(files):
|
|
||||||
for key, f in files.items():
|
|
||||||
if key.startswith('file'):
|
|
||||||
suffix = f.filename.split('.')[-1]
|
|
||||||
if suffix not in ENABLED_FILETYPES:
|
|
||||||
return 'Datoteka "{}" ni pravilnega formata.'.format(f.filename)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_subdir(dir_name):
|
|
||||||
subdir = app.config['UPLOADED_PATH'] / dir_name
|
|
||||||
if not subdir.exists():
|
|
||||||
subdir.mkdir()
|
|
||||||
return subdir
|
|
||||||
|
|
||||||
|
|
||||||
def create_upload_id(form_data, upload_timestamp, file_hashes):
|
|
||||||
tip = form_data.get('tip')
|
|
||||||
ime = form_data.get('ime')
|
|
||||||
podjetje = form_data.get('podjetje')
|
|
||||||
naslov = form_data.get('naslov')
|
|
||||||
posta = form_data.get('posta')
|
|
||||||
email = form_data.get('email')
|
|
||||||
telefon = form_data.get('telefon')
|
|
||||||
|
|
||||||
# This hash serves as an unique identifier for the whole upload.
|
|
||||||
metahash = hashlib.md5((tip+ime+podjetje+naslov+posta+email+telefon).encode())
|
|
||||||
# Include file hashes to avoid metafile name collisions if they have the same form values,
|
|
||||||
# but different data files. Sort hashes first so upload order doesn't matter.
|
|
||||||
sorted_f_hashes = list(file_hashes.values())
|
|
||||||
sorted_f_hashes.sort()
|
|
||||||
metahash.update(''.join(sorted_f_hashes).encode())
|
|
||||||
metahash = metahash.hexdigest()
|
|
||||||
|
|
||||||
return metahash
|
|
||||||
|
|
||||||
|
|
||||||
def check_form(form):
|
|
||||||
tip = form.get('tip')
|
|
||||||
ime = form.get('ime')
|
|
||||||
podjetje = form.get('podjetje')
|
|
||||||
naslov = form.get('naslov')
|
|
||||||
posta = form.get('posta')
|
|
||||||
email = form.get('email')
|
|
||||||
telefon = form.get('telefon')
|
|
||||||
|
|
||||||
if tip not in ['enojez', 'prevodi']:
|
|
||||||
return 'Napačen tip besedila.'
|
|
||||||
|
|
||||||
if len(ime) > 100:
|
|
||||||
return 'Predolgo ime.'
|
|
||||||
|
|
||||||
if len(podjetje) > 100:
|
|
||||||
return 'Predolgo ime institucije.'
|
|
||||||
|
|
||||||
if len(email) > 100:
|
|
||||||
return 'Predolgi email naslov'
|
|
||||||
elif not re.search(REGEX_EMAIL, email):
|
|
||||||
return 'Email napačnega formata.'
|
|
||||||
|
|
||||||
if len(telefon) > 100:
|
|
||||||
return 'Predolga telefonska št.'
|
|
||||||
|
|
||||||
if len(naslov) > 100:
|
|
||||||
return 'Predolg naslov.'
|
|
||||||
|
|
||||||
if len(posta) > 100:
|
|
||||||
return 'Predolga pošta'
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def create_file_hashes(files):
|
|
||||||
res = dict()
|
|
||||||
for key, f in files.items():
|
|
||||||
if key.startswith('file'):
|
|
||||||
h = hashlib.md5(f.filename.encode())
|
|
||||||
h.update(f.stream.read())
|
|
||||||
res[key] = h.hexdigest()
|
|
||||||
f.seek(0)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def store_metadata(upload_metadata):
|
|
||||||
base = get_subdir('meta')
|
|
||||||
|
|
||||||
timestamp = upload_metadata['timestamp']
|
|
||||||
upload_id = upload_metadata['upload_id']
|
|
||||||
form_data = upload_metadata['form_data']
|
|
||||||
email = form_data['email']
|
|
||||||
file_hashes = upload_metadata['file_hashes']
|
|
||||||
contract = upload_metadata['contract']
|
|
||||||
filename = str(timestamp) + '-' + email + '-' + upload_id + '.meta'
|
|
||||||
|
|
||||||
sorted_f_hashes = list(file_hashes.values())
|
|
||||||
sorted_f_hashes.sort()
|
|
||||||
|
|
||||||
path = base / filename
|
|
||||||
with path.open('w') as f:
|
|
||||||
f.write('tip=' + form_data['tip'])
|
|
||||||
f.write('\nime=' + form_data['ime'])
|
|
||||||
f.write('\npodjetje=' + form_data['podjetje'])
|
|
||||||
f.write('\nnaslov=' + form_data['naslov'])
|
|
||||||
f.write('\nposta=' + form_data['posta'])
|
|
||||||
f.write('\nemail=' + form_data['email'])
|
|
||||||
f.write('\ndatoteke=' + str(sorted_f_hashes))
|
|
||||||
f.write('\npogodba=' + contract)
|
|
||||||
|
|
||||||
|
|
||||||
def store_datafiles(files, upload_metadata):
|
|
||||||
base = get_subdir('files')
|
|
||||||
file_hashes = upload_metadata['file_hashes']
|
|
||||||
|
|
||||||
for key, f in files.items():
|
|
||||||
if key.startswith('file'):
|
|
||||||
path = base / file_hashes[key]
|
|
||||||
if not path.exists():
|
|
||||||
path.mkdir()
|
|
||||||
f.save(path / f.filename)
|
|
||||||
|
|
||||||
def generate_contract_pdf(upload_metadata):
|
|
||||||
base = get_subdir('contracts')
|
|
||||||
contract_file_name = upload_metadata['upload_id'] + '.pdf'
|
|
||||||
form_data = upload_metadata['form_data']
|
|
||||||
data = {
|
|
||||||
'ime_priimek': form_data['ime'],
|
|
||||||
'naslov': form_data['naslov'],
|
|
||||||
'posta': form_data['posta'],
|
|
||||||
'kontakt_narocnik': CONTRACT_CLIENT_CONTACT,
|
|
||||||
'kontakt_imetnikpravic': form_data['ime']
|
|
||||||
}
|
|
||||||
|
|
||||||
contract_creator.create_pdf(base / contract_file_name, data)
|
|
||||||
return contract_file_name
|
|
||||||
|
|
||||||
def send_confirm_mail(upload_metadata):
|
|
||||||
body = 'Usprešno ste oddali besedila. V prilogi vam pošiljamo pogodbo.'
|
|
||||||
|
|
||||||
message = MIMEMultipart()
|
|
||||||
message['From'] = MAIL_LOGIN
|
|
||||||
message['To'] = upload_metadata['form_data']['email']
|
|
||||||
message['Subject'] = 'Pogodba za oddana besedila ' + upload_metadata['upload_id']
|
|
||||||
message.attach(MIMEText(body, "plain"))
|
|
||||||
|
|
||||||
contracts_dir = get_subdir('contracts')
|
|
||||||
base_name = upload_metadata['contract']
|
|
||||||
contract_file = contracts_dir / base_name
|
|
||||||
with open(contract_file, "rb") as f:
|
|
||||||
part = MIMEApplication(
|
|
||||||
f.read(),
|
|
||||||
Name = base_name
|
|
||||||
)
|
|
||||||
part['Content-Disposition'] = 'attachment; filename="%s"' % base_name
|
|
||||||
message.attach(part)
|
|
||||||
|
|
||||||
text = message.as_string()
|
|
||||||
|
|
||||||
# Create a secure SSL context
|
|
||||||
context = ssl.create_default_context()
|
|
||||||
|
|
||||||
with SMTP_SSL(MAIL_HOST, SMTP_PORT, context=context) as server:
|
|
||||||
server.login(MAIL_LOGIN, MAIL_PASS)
|
|
||||||
server.sendmail(message['From'], message['To'], text)
|
|
||||||
|
|
||||||
# Save copy of sent mail in Sent mailbox
|
|
||||||
imap = imaplib.IMAP4_SSL(MAIL_HOST, IMAP_PORT)
|
|
||||||
imap.login(MAIL_LOGIN, MAIL_PASS)
|
|
||||||
imap.append('Sent', '\\Seen', imaplib.Time2Internaldate(time.time()), text.encode('utf8'))
|
|
||||||
imap.logout()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
|
|
11
config.ini
11
config.ini
|
@ -1,9 +1,16 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
MAIL_HOST=posta.cjvt.si
|
MAIL_HOST=posta.cjvt.si
|
||||||
MAIL_LOGIN=oddaja-besedil@cjvt.si
|
MAIL_LOGIN=oddaja-besedil@cjvt.si
|
||||||
MAIL_PASS=randompass123
|
MAIL_PASS=secretmailpass123
|
||||||
SMTP_PORT=465
|
SMTP_PORT=465
|
||||||
IMAP_PORT=993
|
IMAP_PORT=993
|
||||||
MAX_UPLOAD_SIZE=1000000000
|
MAX_UPLOAD_SIZE=1000000000
|
||||||
BASE_DIR=./
|
UPLOADS_DIR=./uploads
|
||||||
|
DATA_DIR=./data
|
||||||
CONTRACT_CLIENT_CONTACT=Testko Tester
|
CONTRACT_CLIENT_CONTACT=Testko Tester
|
||||||
|
MAIL_SUBJECT=RSDO: pogodba za oddana besedila ({upload_id})
|
||||||
|
MAIL_BODY=Hvala, ker ste prispevali besedila in na ta način pomagali pri razvoju slovenskega jezika v digitalnem okolju. V prilogi vam pošiljamo pogodbo s seznamom naloženih datotek.
|
||||||
|
|
||||||
|
|
||||||
|
Lep pozdrav,
|
||||||
|
ekipa RSDO
|
||||||
|
|
BIN
contract/out.pdf
BIN
contract/out.pdf
Binary file not shown.
|
@ -1,43 +0,0 @@
|
||||||
import pdfkit
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
|
||||||
|
|
||||||
|
|
||||||
class ContractCreator:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
template_loader = FileSystemLoader(searchpath="./")
|
|
||||||
template_env = Environment(loader=template_loader)
|
|
||||||
self.template = template_env.get_template('template.html')
|
|
||||||
|
|
||||||
self.pdfkit_options = {
|
|
||||||
'page-size': 'A4',
|
|
||||||
'margin-top': '0.75in',
|
|
||||||
'margin-right': '0.75in',
|
|
||||||
'margin-bottom': '0.75in',
|
|
||||||
'margin-left': '0.75in',
|
|
||||||
'encoding': "UTF-8",
|
|
||||||
'custom-header' : [
|
|
||||||
('Accept-Encoding', 'gzip')
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
def fill_template(self, **kwargs):
|
|
||||||
return self.template.render(**kwargs)
|
|
||||||
|
|
||||||
def create_pdf(self, out_f, fields_dict):
|
|
||||||
html_str = self.fill_template(**fields_dict)
|
|
||||||
pdfkit.from_string(html_str, out_f, options=self.pdfkit_options)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test_data = {
|
|
||||||
'ime_priimek': 'Testko Tester',
|
|
||||||
'naslov': 'Testovci 10',
|
|
||||||
'posta': '1123',
|
|
||||||
'kontakt_narocnik': 'Testica Testkovič',
|
|
||||||
'kontakt_imetnikpravic': 'Testko Tester',
|
|
||||||
'date': '16.2.2021'
|
|
||||||
}
|
|
||||||
|
|
||||||
contract_creator = ContractCreator()
|
|
||||||
contract_creator.create_pdf('out.pdf', test_data)
|
|
|
@ -175,27 +175,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;"><b>Ime, naslov ali oznaka dela</b></td>
|
<td style="text-align: center;"><b>Ime, naslov ali oznaka dela</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
{{files_table_str}}
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
250
portal/base.py
Normal file
250
portal/base.py
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
import re
|
||||||
|
import hashlib
|
||||||
|
import time
|
||||||
|
import ssl
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import imaplib
|
||||||
|
from smtplib import SMTP_SSL
|
||||||
|
|
||||||
|
import email
|
||||||
|
from email import encoders
|
||||||
|
from email.mime.base import MIMEBase
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.application import MIMEApplication
|
||||||
|
|
||||||
|
import pdfkit
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
|
||||||
|
ENABLED_FILETYPES = ['txt', 'csv', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'xml', 'mxliff', 'tmx']
|
||||||
|
REGEX_EMAIL = re.compile('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')
|
||||||
|
|
||||||
|
|
||||||
|
class ContractCreator:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
template_loader = FileSystemLoader(searchpath="./")
|
||||||
|
template_env = Environment(loader=template_loader)
|
||||||
|
self.template = template_env.get_template('contract/template.html')
|
||||||
|
|
||||||
|
self.pdfkit_options = {
|
||||||
|
'page-size': 'A4',
|
||||||
|
'margin-top': '0.75in',
|
||||||
|
'margin-right': '0.75in',
|
||||||
|
'margin-bottom': '0.75in',
|
||||||
|
'margin-left': '0.75in',
|
||||||
|
'encoding': "UTF-8",
|
||||||
|
'custom-header' : [
|
||||||
|
('Accept-Encoding', 'gzip')
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def fill_template(self, **kwargs):
|
||||||
|
return self.template.render(**kwargs)
|
||||||
|
|
||||||
|
def create_pdf(self, out_f, fields_dict):
|
||||||
|
html_str = self.fill_template(**fields_dict)
|
||||||
|
pdfkit.from_string(html_str, out_f, options=self.pdfkit_options)
|
||||||
|
|
||||||
|
|
||||||
|
contract_creator = ContractCreator()
|
||||||
|
|
||||||
|
|
||||||
|
def get_upload_metadata(corpus_name, request):
|
||||||
|
upload_metadata = dict()
|
||||||
|
|
||||||
|
file_hashes = create_file_hashes(request.files)
|
||||||
|
file_names = file_hashes.keys()
|
||||||
|
form_data = request.form.copy()
|
||||||
|
upload_timestamp = int(time.time())
|
||||||
|
upload_id = create_upload_id(corpus_name, form_data, upload_timestamp, file_hashes)
|
||||||
|
|
||||||
|
upload_metadata['corpus_name'] = corpus_name
|
||||||
|
upload_metadata['form_data'] = form_data
|
||||||
|
upload_metadata['upload_id'] = upload_id
|
||||||
|
upload_metadata['timestamp'] = upload_timestamp
|
||||||
|
upload_metadata['file_hashes'] = file_hashes
|
||||||
|
upload_metadata['file_names'] = file_names
|
||||||
|
|
||||||
|
return upload_metadata
|
||||||
|
|
||||||
|
|
||||||
|
def check_suffixes(files):
|
||||||
|
for key, f in files.items():
|
||||||
|
if key.startswith('file'):
|
||||||
|
suffix = f.filename.split('.')[-1]
|
||||||
|
if suffix not in ENABLED_FILETYPES:
|
||||||
|
return 'Datoteka "{}" ni pravilnega formata.'.format(f.filename)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_subdir(uploads_path, dir_name):
|
||||||
|
subdir = uploads_path / dir_name
|
||||||
|
if not subdir.exists():
|
||||||
|
subdir.mkdir(parents=True)
|
||||||
|
return subdir
|
||||||
|
|
||||||
|
|
||||||
|
def create_upload_id(corpus_name, form_data, upload_timestamp, file_hashes):
|
||||||
|
ime = form_data.get('ime')
|
||||||
|
podjetje = form_data.get('podjetje')
|
||||||
|
naslov = form_data.get('naslov')
|
||||||
|
posta = form_data.get('posta')
|
||||||
|
email = form_data.get('email')
|
||||||
|
telefon = form_data.get('telefon')
|
||||||
|
|
||||||
|
# This hash serves as an unique identifier for the whole upload.
|
||||||
|
metahash = hashlib.md5((corpus_name+ime+podjetje+naslov+posta+email+telefon).encode())
|
||||||
|
# Include file hashes to avoid metafile name collisions if they have the same form values,
|
||||||
|
# but different data files. Sort hashes first so upload order doesn't matter.
|
||||||
|
sorted_f_hashes = list(file_hashes.values())
|
||||||
|
sorted_f_hashes.sort()
|
||||||
|
metahash.update(''.join(sorted_f_hashes).encode())
|
||||||
|
metahash = metahash.hexdigest()
|
||||||
|
|
||||||
|
return metahash
|
||||||
|
|
||||||
|
|
||||||
|
def check_form(form):
|
||||||
|
ime = form.get('ime')
|
||||||
|
podjetje = form.get('podjetje')
|
||||||
|
naslov = form.get('naslov')
|
||||||
|
posta = form.get('posta')
|
||||||
|
email = form.get('email')
|
||||||
|
telefon = form.get('telefon')
|
||||||
|
|
||||||
|
if len(ime) > 100:
|
||||||
|
return 'Predolgo ime.'
|
||||||
|
|
||||||
|
if len(podjetje) > 100:
|
||||||
|
return 'Predolgo ime institucije.'
|
||||||
|
|
||||||
|
if len(email) > 100:
|
||||||
|
return 'Predolgi email naslov'
|
||||||
|
elif not re.search(REGEX_EMAIL, email):
|
||||||
|
return 'Email napačnega formata.'
|
||||||
|
|
||||||
|
if len(telefon) > 100:
|
||||||
|
return 'Predolga telefonska št.'
|
||||||
|
|
||||||
|
if len(naslov) > 100:
|
||||||
|
return 'Predolg naslov.'
|
||||||
|
|
||||||
|
if len(posta) > 100:
|
||||||
|
return 'Predolga pošta'
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def create_file_hashes(files):
|
||||||
|
res = dict()
|
||||||
|
for key, f in files.items():
|
||||||
|
if key.startswith('file'):
|
||||||
|
h = hashlib.md5(f.filename.encode())
|
||||||
|
h.update(f.stream.read())
|
||||||
|
res[f.filename] = h.hexdigest()
|
||||||
|
f.seek(0)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def store_metadata(uploads_path, upload_metadata):
|
||||||
|
base = get_subdir(uploads_path, 'meta')
|
||||||
|
|
||||||
|
timestamp = upload_metadata['timestamp']
|
||||||
|
upload_id = upload_metadata['upload_id']
|
||||||
|
form_data = upload_metadata['form_data']
|
||||||
|
email = form_data['email']
|
||||||
|
file_hashes = upload_metadata['file_hashes']
|
||||||
|
contract = upload_metadata['contract']
|
||||||
|
filename = str(timestamp) + '-' + email + '-' + upload_id + '.meta'
|
||||||
|
|
||||||
|
sorted_f_hashes = list(file_hashes.values())
|
||||||
|
sorted_f_hashes.sort()
|
||||||
|
|
||||||
|
path = base / filename
|
||||||
|
with path.open('w') as f:
|
||||||
|
f.write('korpus=' + upload_metadata['corpus_name'])
|
||||||
|
f.write('\nime=' + form_data['ime'])
|
||||||
|
f.write('\npodjetje=' + form_data['podjetje'])
|
||||||
|
f.write('\nnaslov=' + form_data['naslov'])
|
||||||
|
f.write('\nposta=' + form_data['posta'])
|
||||||
|
f.write('\nemail=' + form_data['email'])
|
||||||
|
f.write('\ndatoteke=' + str(sorted_f_hashes))
|
||||||
|
f.write('\npogodba=' + contract)
|
||||||
|
|
||||||
|
|
||||||
|
def store_datafiles(uploads_path, files, upload_metadata):
|
||||||
|
base = get_subdir(uploads_path, 'files')
|
||||||
|
file_hashes = upload_metadata['file_hashes']
|
||||||
|
|
||||||
|
for key, f in files.items():
|
||||||
|
if key.startswith('file'):
|
||||||
|
path = base / file_hashes[f.filename]
|
||||||
|
if not path.exists():
|
||||||
|
path.mkdir()
|
||||||
|
f.save(path / f.filename)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_contract_pdf(uploads_path, upload_metadata, contract_client_contact):
|
||||||
|
base = get_subdir(uploads_path, 'contracts')
|
||||||
|
contract_file_name = upload_metadata['upload_id'] + '.pdf'
|
||||||
|
form_data = upload_metadata['form_data']
|
||||||
|
|
||||||
|
files_table_str = []
|
||||||
|
for file_name in upload_metadata['file_names']:
|
||||||
|
files_table_str.append('<tr><td style="text-align: center;">')
|
||||||
|
files_table_str.append(file_name)
|
||||||
|
files_table_str.append('</td></tr>')
|
||||||
|
files_table_str = ''.join(files_table_str)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'ime_priimek': form_data['ime'],
|
||||||
|
'naslov': form_data['naslov'],
|
||||||
|
'posta': form_data['posta'],
|
||||||
|
'kontakt_narocnik': contract_client_contact,
|
||||||
|
'kontakt_imetnikpravic': form_data['ime'],
|
||||||
|
'files_table_str': files_table_str
|
||||||
|
}
|
||||||
|
|
||||||
|
contract_creator.create_pdf(base / contract_file_name, data)
|
||||||
|
return contract_file_name
|
||||||
|
|
||||||
|
|
||||||
|
def send_confirm_mail(subject, body, uploads_path, upload_metadata, mail_host, mail_login, mail_pass, imap_port=993, smtp_port=465):
|
||||||
|
upload_id = upload_metadata['upload_id']
|
||||||
|
|
||||||
|
message = MIMEMultipart()
|
||||||
|
message['From'] = mail_login
|
||||||
|
message['To'] = upload_metadata['form_data']['email']
|
||||||
|
message['Subject'] = subject.format(upload_id=upload_id)
|
||||||
|
body = body.format(upload_id=upload_id)
|
||||||
|
message.attach(MIMEText(body, "plain"))
|
||||||
|
|
||||||
|
contracts_dir = get_subdir(uploads_path, 'contracts')
|
||||||
|
base_name = upload_metadata['contract']
|
||||||
|
contract_file = contracts_dir / base_name
|
||||||
|
with open(contract_file, "rb") as f:
|
||||||
|
part = MIMEApplication(
|
||||||
|
f.read(),
|
||||||
|
Name = base_name
|
||||||
|
)
|
||||||
|
part['Content-Disposition'] = 'attachment; filename="%s"' % base_name
|
||||||
|
message.attach(part)
|
||||||
|
|
||||||
|
text = message.as_string()
|
||||||
|
|
||||||
|
# Create a secure SSL context
|
||||||
|
context = ssl.create_default_context()
|
||||||
|
|
||||||
|
with SMTP_SSL(mail_host, smtp_port, context=context) as server:
|
||||||
|
server.login(mail_login, mail_pass)
|
||||||
|
server.sendmail(message['From'], message['To'], text)
|
||||||
|
|
||||||
|
# Save copy of sent mail in Sent mailbox
|
||||||
|
imap = imaplib.IMAP4_SSL(mail_host, imap_port)
|
||||||
|
imap.login(mail_login, mail_pass)
|
||||||
|
imap.append('Sent', '\\Seen', imaplib.Time2Internaldate(time.time()), text.encode('utf8'))
|
||||||
|
imap.logout()
|
||||||
|
|
3
static/image/logo.svg
Normal file
3
static/image/logo.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="84" height="68" viewBox="0 0 84 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.5773 14.0998V0L61.2523 9.90788C55.5732 8.0324 49.1389 6.96077 42.3177 6.92846C39.5976 7.41691 37.0641 8.30531 35.0728 9.52887C32.1261 11.3395 30.7423 13.5548 30.7423 16.4536C30.7423 17.8381 31.7831 19.8281 36.7724 22.1191C38.9769 23.1314 41.3947 23.9282 43.6859 24.6078C44.1748 24.7529 44.7212 24.9089 45.2881 25.0707C46.9002 25.531 48.6777 26.0384 49.7688 26.4749C50.3128 26.6925 50.9257 26.926 51.5891 27.1789L51.5892 27.1789L51.5899 27.1792C54.8363 28.4164 59.2939 30.1152 62.8313 32.6669C67.7809 36.2372 71.4433 41.674 71.4433 49.7938C71.4433 50.8957 71.3731 51.9819 71.2341 53.0479C79.107 48.1686 84 41.3361 84 33.7731C84 26.002 78.834 19.002 70.5773 14.0998ZM12.9897 53.1856V67.1134L21.806 57.3175C27.7981 59.4216 34.6804 60.6184 42 60.6184C43.4856 60.6184 44.9532 60.5691 46.399 60.473L46.3705 60.2349C50.5048 59.7388 53.2834 58.2414 54.9723 56.5219C56.6194 54.8448 57.5876 52.608 57.5876 49.7938C57.5876 46.6227 56.4871 45.1748 54.7254 43.9041C52.7993 42.5147 50.4943 41.6232 47.3688 40.4145L47.3687 40.4144L47.3687 40.4144L47.3684 40.4143L47.3669 40.4137C46.516 40.0847 45.6043 39.7321 44.6229 39.3395C44.2108 39.1747 43.5896 38.9982 42.5362 38.6989L42.5357 38.6988C41.8252 38.4969 40.918 38.2392 39.7458 37.8915C37.2471 37.1503 34.0901 36.134 30.9905 34.7108C25.3715 32.1306 16.8866 26.7598 16.8866 16.4536C16.8866 14.9059 17.0383 13.4376 17.3212 12.0486C6.82395 16.9288 0 24.8416 0 33.7731C0 41.4075 4.98579 48.2975 12.9897 53.1856Z" fill="#006CB7"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -37,6 +37,18 @@ html {
|
||||||
margin-left: -388px;
|
margin-left: -388px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#logo-container {
|
||||||
|
position: absolute;
|
||||||
|
top: -9%;
|
||||||
|
left: 35%;
|
||||||
|
background: #F5F5F5;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding-top: 5%;
|
||||||
|
padding-bottom: 5%;
|
||||||
|
padding-left: 7%;
|
||||||
|
padding-right: 7%;
|
||||||
|
}
|
||||||
|
|
||||||
#izjava {
|
#izjava {
|
||||||
float: left;
|
float: left;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
|
@ -51,10 +63,22 @@ html {
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
line-height: 42px;
|
line-height: 42px;
|
||||||
margin-block-start: 0.4em;
|
margin-block-start: 0.4em;
|
||||||
|
z-index: 5;
|
||||||
|
|
||||||
color: #006cb7;
|
color: #006cb7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#subtitle {
|
||||||
|
font-family: Roboto;
|
||||||
|
font-style: bold;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-block-start: 0.4em;
|
||||||
|
border-bottom: 3px solid #006cb7;
|
||||||
|
color: #006cb7;
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
@ -160,8 +184,8 @@ input {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
margin-top: 16px;
|
margin-top: 26px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 26px;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
top: -530px;
|
top: -530px;
|
||||||
|
@ -329,6 +353,7 @@ input {
|
||||||
|
|
||||||
#popup-terms {
|
#popup-terms {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: 9999;
|
||||||
top: 100px;
|
top: 100px;
|
||||||
bottom: 100px;
|
bottom: 100px;
|
||||||
left: 10%;
|
left: 10%;
|
||||||
|
|
300
templates/basic.html
Normal file
300
templates/basic.html
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Portal za oddajanje besedil</title>
|
||||||
|
<!--{{ dropzone.load_css() }}-->
|
||||||
|
<link rel="stylesheet" href="static/dropzone.css" type="text/css">
|
||||||
|
{{ dropzone.style('position: absolute;
|
||||||
|
top: -0.5px;
|
||||||
|
width: 388px;
|
||||||
|
height: 632px;
|
||||||
|
left: 385px;
|
||||||
|
background: linear-gradient(198.62deg, rgba(255, 255, 255, 0.49) -1.62%, rgba(255, 255, 255, 0.73) -1.61%, rgba(255, 255, 255, 0.41) 79.34%);
|
||||||
|
box-shadow: 20px 4px 40px rgba(0, 0, 0, 0.25);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
border: 0px;
|
||||||
|
border-radius: 0px 20px 20px 0px;') }}
|
||||||
|
<link rel="stylesheet" href="static/style.css" type="text/css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="bg"></div>
|
||||||
|
<div id="main-window">
|
||||||
|
<div id="rect1">
|
||||||
|
<div id="logo-container">
|
||||||
|
<img src="static/image/logo.svg" alt="logo"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form id="my-dropzone" class="dropzone">
|
||||||
|
<div style="position: relative; right: 390px;">
|
||||||
|
<h1 id="title">Portal za oddajanje besedil {{corpus_name}}</h1>
|
||||||
|
<h2 id="subtitle">{{subtitle}}</h2>
|
||||||
|
|
||||||
|
<label for="ime">* Ime:</label>
|
||||||
|
<input type="text" id="ime" name="ime" required="required"/>
|
||||||
|
|
||||||
|
<label for="podjetje">Podjetje / institucija:</label>
|
||||||
|
<input type="text" id="podjetje" name="podjetje"/>
|
||||||
|
|
||||||
|
<label for="naslov">Naslov:</label>
|
||||||
|
<input type="text" id="naslov" name="naslov"/>
|
||||||
|
|
||||||
|
<label for="posta">Pošta:</label>
|
||||||
|
<input type="text" id="posta" name="posta"/>
|
||||||
|
|
||||||
|
<label for="email">* E-Pošta:</label>
|
||||||
|
<input type="text" id="email" name="email" required="required"/>
|
||||||
|
|
||||||
|
<label for="telefon">Telefon:</label>
|
||||||
|
<input type="text" id="telefon" name="telefon"/>
|
||||||
|
|
||||||
|
<input type="checkbox" id="izjava" name="izjava" value="izjava" required="required">
|
||||||
|
<label for="izjava">* Izjavljam, da sem lastnik avtorskih pravic in dovoljujem, da se besedila vključijo v korpuse v skladu z ustrezno licenco korpusa.</label>
|
||||||
|
|
||||||
|
<button id="button-submit" type="submit">Oddaj</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dropzone-previews"></div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="popup-terms" style="display: none">
|
||||||
|
<div id="popup-terms-text">
|
||||||
|
<h2>POGODBA O PRENOSU AVTORSKIH PRAVIC</h2>
|
||||||
|
|
||||||
|
<h3>UVODNE DOLOČBE</h3>
|
||||||
|
<h4><b>1. člen</b></h4>
|
||||||
|
|
||||||
|
<p>1.1. Stranki uvodoma ugotavljata, da naročnik izvaja projekt Razvoj slovenščine v digitalnem
|
||||||
|
okolju – RSDO (v nadaljevanju projekt RSDO), ki je bil na javnem razpisu Razvoj slovenščine v
|
||||||
|
digitalnem okolju – jezikovni viri in tehnologije (JR-ESRR-Razvoj slovenščine v digitalnem
|
||||||
|
okolju), objavljenem v Uradnem listu RS št. 70/19 dne 29. 11. 2019, sprejet v sofinanciranje
|
||||||
|
in katerega vsebina je razvidna s spletnih strani https://slovenscina.eu.</p>
|
||||||
|
|
||||||
|
<p>1.2. Stranki uvodoma ugotavljata, da bo naročnik v okviru projekta RSDO:
|
||||||
|
- izdelal osrednjo digitalno slovarsko bazo, ki združuje različne tipe jezikovnih podatkov o
|
||||||
|
slovenščini v odprtem dostopu,
|
||||||
|
- izdelal terminološki portal z integriranim iskalnikom po slovenskih terminoloških virih, zlasti
|
||||||
|
terminoloških slovarjih,
|
||||||
|
- izdelal korpus prevodov po različnih domenah za učenje strojnega prevajalnika za jezikovni
|
||||||
|
par angleščina-slovenščina in slovenščina-angleščina.</p>
|
||||||
|
<p>1.3. Stranki uvodoma ugotavljata, da bo naročnik pri projektu RSDO za vse zgoraj opisane
|
||||||
|
namene zbiral in uporabil besedilne vire, ki so navedeni v prilogi k tej pogodbi in ki so lahko
|
||||||
|
avtorska dela ali drugi predmeti varstva v skladu z Zakonom o avtorski in sorodnih pravicah
|
||||||
|
(Uradni list RS, št. 16/07 – uradno prečiščeno besedilo, 68/08, 110/13, 56/15, 63/16 – ZKUASP
|
||||||
|
in 59/19; ZASP) in na katerih ima imetnik pravic avtorske, avtorski sorodne ali druge pravice v
|
||||||
|
skladu z ZASP (v nadaljevanju avtorska dela).</p>
|
||||||
|
|
||||||
|
<p>1.4. Stranki ugotavljata, da bodo avtorska dela in vse njihove morebitne spremembe in
|
||||||
|
predelave, ter zbirke podatkov, ki bodo med izvajanjem projekta RSDO nastale, javno
|
||||||
|
dostopni pod pogoji prostih licenc (npr. CC BY-SA) in bodo na voljo za nekomercialen in
|
||||||
|
komercialen razvoj tehnologij, za raziskave in za druge raziskovalne namene
|
||||||
|
posameznikom, raziskovalnim in izobraževalnim institucijam, neprofitnim organizacijam,
|
||||||
|
državnim organom, organizacijam z javnimi pooblastili in gospodarskim družbam v Sloveniji
|
||||||
|
in tujini.</p>
|
||||||
|
|
||||||
|
<h3>PREDMET POGODBE</h3>
|
||||||
|
<h4><b>2. člen</b></h4>
|
||||||
|
|
||||||
|
<p>2.1. Predmet pogodbe so vsa avtorska dela imetnika pravic, ki so navedena v prilogi k tej
|
||||||
|
pogodbi.</p>
|
||||||
|
|
||||||
|
<p>2.2. S podpisom te pogodbe imetnik avtorskih pravic na naročnika prenaša avtorske pravice
|
||||||
|
na avtorskih delih na način in v obsegu, kakor je navedeno v 3. členu te pogodbe.</p>
|
||||||
|
|
||||||
|
<h3>PRENOS AVTORSKIH PRAVIC</h3>
|
||||||
|
<h4><b>3. člen</b></h4>
|
||||||
|
|
||||||
|
<p>3.1. S podpisom te pogodbe imetnik pravic na avtorskih delih, ki so predmet te pogodbe, na
|
||||||
|
naročnika neizključno, brez časovnih in teritorialnih omejitev prenaša vse materialne avtorske
|
||||||
|
pravice, avtorski sorodne pravice in druge pravice avtorja v skladu z ZASP, zlasti pravico
|
||||||
|
reproduciranja (23. člen ZASP), distribuiranja (24. člena ZASP), dajanja v najem (25. člen ZASP),
|
||||||
|
priobčitve javnosti (26. do 32.a člen ZASP), vključno s pravico dajanja na voljo javnosti (32.a
|
||||||
|
člen ZASP) in pravico predelave (33. člen ZASP).</p>
|
||||||
|
|
||||||
|
<p>3.2. S podpisom te pogodbe imetnik pravic izrecno soglaša, da naročnik pravice iz točke 3.1.
|
||||||
|
prenaša naprej na tretje osebe brez omejitev.</p>
|
||||||
|
|
||||||
|
<h3>JAMČEVANJE IMETNIKA PRAVIC</h3>
|
||||||
|
|
||||||
|
<h4><b>4. člen</b></h4>
|
||||||
|
|
||||||
|
<p>4.1. S podpisom te pogodbe imetnik pravic jamči, da je na avtorskih delih, ki so predmet te
|
||||||
|
pogodbe, imetnik vseh avtorskih pravic, avtorski sorodnih pravic in drugih pravic avtorja v
|
||||||
|
skladu z ZASP, ki so potrebne za prenos pravic po tej pogodbi, in da na avtorskih delih ne
|
||||||
|
obstajajo pravice tretjih oseb, ki bi naročniku preprečevale njihovo uporabo.</p>
|
||||||
|
|
||||||
|
<p>4.2. Določbe te pogodbe ne vplivajo na prenos moralnih avtorskih pravic, ki so v skladu z
|
||||||
|
določbami ZASP neprenosljive.</p>
|
||||||
|
|
||||||
|
<h3>OSEBNI PODATKI</h3>
|
||||||
|
<h4><b>5. člen</b></h4>
|
||||||
|
|
||||||
|
<p>6.1. Stranki se zavezujeta, da bosta vse morebitne osebne podatke, ki jih bosta obdelovali za
|
||||||
|
namene izvajanja te pogodbe, obdelovali na način, da bosta upoštevali vse veljavne predpise
|
||||||
|
o varstvu osebnih podatkov in da bosta posameznikom, na katere se osebni podatki nanašajo,
|
||||||
|
zagotovili vse potrebne informacije v skladu s predpisi o varstvu osebnih podatkov.<p>
|
||||||
|
|
||||||
|
<h3>KONTAKTNE OSEBE</h3>
|
||||||
|
<h4><b>6. člen</b></h4>
|
||||||
|
|
||||||
|
<p>7.1 Kontaktna oseba za izvedbo te pogodbe na strani naročnika je [xxx].</p>
|
||||||
|
<p>7.2. Kontaktna oseba za izvedbo te pogodbe na strani imetnika pravic je [xxx].</p>
|
||||||
|
|
||||||
|
<h3>KONČNE DOLOČBE</h3>
|
||||||
|
<h4><b>7. člen</b></h4>
|
||||||
|
|
||||||
|
<p>8.1. Če je katerakoli določba te pogodbe nična, ostanejo druga določila te pogodbe v veljavi.</p>
|
||||||
|
|
||||||
|
<h4><b>8. člen</b></h4>
|
||||||
|
|
||||||
|
<p>9.1. Za razmerja v zvezi s to pogodbo se uporabljajo pravni predpisi Republike Slovenije.</p>
|
||||||
|
<p>9.2. Spore iz te pogodbe bosta stranki reševali po mirni poti. V primeru, da mirna rešitev ne
|
||||||
|
bo mogoča, je za vse spore v zvezi s to pogodbo pristojno sodišče v Ljubljani.</p>
|
||||||
|
|
||||||
|
<h4><b>9. člen</b></h4>
|
||||||
|
|
||||||
|
<p>10.1. Ta pogodba nadomešča vsa predhodna pogajanja, ponudbe in druge dogovore med
|
||||||
|
strankama.</p>
|
||||||
|
<p>10.2. Ta pogodba je sestavljena v [dveh] istovetnih izvodih, od katerih prejme vsaka stranka
|
||||||
|
po enega.</p>
|
||||||
|
<p>10.3. Pogodbeni stranki s podpisom potrjujeta veljavnost te pogodbe.</p>
|
||||||
|
</div>
|
||||||
|
<button id="button-submit-cancel" class="button-terms" style="background: #ff2d2d;">Prekliči</button>
|
||||||
|
<button id="button-submit-final" class="button-terms">Oddaj</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--{{ dropzone.load_js() }}-->
|
||||||
|
<script src="static/dropzone.js"></script>
|
||||||
|
<script>
|
||||||
|
/////////////////////////
|
||||||
|
// Dropzone //
|
||||||
|
/////////////////////////
|
||||||
|
var btnSubmit = document.getElementById("button-submit");
|
||||||
|
var btnSubmitFinal = document.getElementById("button-submit-final");
|
||||||
|
var btnSubmitCancel = document.getElementById("button-submit-cancel");
|
||||||
|
var elemTermsPopup = document.getElementById("popup-terms");
|
||||||
|
var termsScrollbox = document.getElementById("popup-terms-text");
|
||||||
|
var scrollboxTriggered = false;
|
||||||
|
var form = document.forms["my-dropzone"];
|
||||||
|
|
||||||
|
function isEmptyOrSpaces(str){
|
||||||
|
return str == null || str.match(/^ *$/) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
|
||||||
|
Dropzone.options.myDropzone = { // The camelized version of the ID of the form element
|
||||||
|
url: "/{{corpus_name}}/upload",
|
||||||
|
autoProcessQueue: false,
|
||||||
|
uploadMultiple: true,
|
||||||
|
parallelUploads: 20,
|
||||||
|
paramName: "file", // The name that will be used to transfer the file
|
||||||
|
maxFilesize: 1000, // MB
|
||||||
|
acceptedFiles: ".txt, .csv, .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx",
|
||||||
|
maxFiles: 20,
|
||||||
|
dictDefaultMessage: `Kliknite ali odložite datoteke sem.`,
|
||||||
|
dictFallbackMessage: "Vaš brskalnik ne podpira izbiranje datotek z odlaganjem (\"drag & drop\").",
|
||||||
|
dictInvalidFileType: "Datoteka je napačnega formata.",
|
||||||
|
dictFileTooBig: "Datoteke je prevelika {{filesize}}. Največja dovoljena velikost: {{maxFilesize}}MiB.",
|
||||||
|
dictResponseError: "Napaka strežnika: {{statusCode}}",
|
||||||
|
dictMaxFilesExceeded: "Ne morete naložiti več datotek.",
|
||||||
|
dictCancelUpload: "Prekini prenos",
|
||||||
|
dictRemoveFile: "Odstrani datoteko",
|
||||||
|
dictCancelUploadConfirmation: "Ali res želite odstraniti to datoteko?",
|
||||||
|
dictUploadCanceled: "Prenos prekinjen",
|
||||||
|
|
||||||
|
// The setting up of the dropzone
|
||||||
|
init: function() {
|
||||||
|
var dz = this;
|
||||||
|
|
||||||
|
|
||||||
|
btnSubmit.addEventListener("click", function(e) {
|
||||||
|
// Make sure that the form isn't actually being sent.
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// Check form validity.
|
||||||
|
var ime = form["ime"].value;
|
||||||
|
var email = form["email"].value;
|
||||||
|
var podjetje = form["podjetje"].value;
|
||||||
|
var telefon = form["telefon"].value;
|
||||||
|
var izjava = form["izjava"].checked;
|
||||||
|
if (isEmptyOrSpaces(ime) || isEmptyOrSpaces(email) || !izjava) {
|
||||||
|
alert("Izpolnite vsa obvezna polja!");
|
||||||
|
} else if (!reEmail.test(email.toLowerCase())) {
|
||||||
|
alert("Email napačnega formata!");
|
||||||
|
} else if (ime.length > 100 || email.length > 100 || podjetje.length > 100 || telefon.length > 100) {
|
||||||
|
alert("Velikost polj je omejena na 100 znakov.");
|
||||||
|
} else {
|
||||||
|
// Then make terms popup visible
|
||||||
|
btnSubmit.disabled = true;
|
||||||
|
btnSubmitFinal.disabled = true;
|
||||||
|
elemTermsPopup.style.display = "inline";
|
||||||
|
scrollboxTriggered = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// First change the button to actually tell Dropzone to process the queue.
|
||||||
|
btnSubmitFinal.addEventListener("click", function(e) {
|
||||||
|
// Hand off data to dropzone
|
||||||
|
dz.processQueue();
|
||||||
|
|
||||||
|
// Clear fields and hide popup agian
|
||||||
|
btnSubmit.disabled = false;
|
||||||
|
elemTermsPopup.style.display = "none";
|
||||||
|
form.reset();
|
||||||
|
scrollboxTriggered = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
btnSubmitCancel.addEventListener("click", function(e) {
|
||||||
|
btnSubmit.disabled = false;
|
||||||
|
scrollboxTriggered = false;
|
||||||
|
elemTermsPopup.style.display = "none";
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enable final submit button only if user scrolls to the end of the terms.
|
||||||
|
function checkScrollboxTrigger(event) {
|
||||||
|
var element = event.target;
|
||||||
|
if (!scrollboxTriggered
|
||||||
|
&& element.scrollHeight - element.scrollTop <= element.clientHeight + 50
|
||||||
|
) {
|
||||||
|
scrollboxTriggered = true;
|
||||||
|
btnSubmitFinal.disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
termsScrollbox.addEventListener('scroll', function(event) {
|
||||||
|
checkScrollboxTrigger(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
termsScrollbox.addEventListener("mouseenter", function(event) {
|
||||||
|
checkScrollboxTrigger(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
|
||||||
|
// of the sending event because uploadMultiple is set to true.
|
||||||
|
this.on("sendingmultiple", function() {
|
||||||
|
// Gets triggered when the form is actually being sent.
|
||||||
|
// Hide the success button or the complete form.
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("successmultiple", function(files, response) {
|
||||||
|
// Gets triggered when the files have successfully been sent.
|
||||||
|
// Redirect user or notify of success.
|
||||||
|
alert("Odgovor strežnika: " + response);
|
||||||
|
location.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("errormultiple", function(files, response) {
|
||||||
|
// Gets triggered when there was an error sending the files.
|
||||||
|
// Maybe show form again, and notify user of error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,350 +1,10 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="utf-8">
|
||||||
<title>Portal za oddajanje besedil za DS4 in DS1</title>
|
|
||||||
<!--{{ dropzone.load_css() }}-->
|
|
||||||
<link rel="stylesheet" href="static/dropzone.css" type="text/css">
|
|
||||||
{{ dropzone.style('position: absolute;
|
|
||||||
top: -0.5px;
|
|
||||||
width: 388px;
|
|
||||||
height: 632px;
|
|
||||||
left: 385px;
|
|
||||||
background: linear-gradient(198.62deg, rgba(255, 255, 255, 0.49) -1.62%, rgba(255, 255, 255, 0.73) -1.61%, rgba(255, 255, 255, 0.41) 79.34%);
|
|
||||||
box-shadow: 20px 4px 40px rgba(0, 0, 0, 0.25);
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
border: 0px;
|
|
||||||
border-radius: 0px 20px 20px 0px;') }}
|
|
||||||
<link rel="stylesheet" href="static/style.css" type="text/css">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="bg"></div>
|
<a href="/prevodi">Korpus paralelnih besdil ANG-SLO</a><br>
|
||||||
<div id="main-window">
|
<a href="/gigafida">Korpus Gigafida</a>
|
||||||
<div id="rect1">
|
|
||||||
<form id="my-dropzone" class="dropzone">
|
|
||||||
<div style="position: relative; right: 390px;">
|
|
||||||
<h1 id="title">Portal za oddajanje besedil za DS4 in DS1</h1>
|
|
||||||
|
|
||||||
<div class="corpus-type-selector">
|
|
||||||
<button id="corpus-type-prevodi" class="corpus-type-button">PREVODI</button>
|
|
||||||
<button id="corpus-type-gigafida" class="corpus-type-button">GIGAFIDA</button>
|
|
||||||
<button id="corpus-type-solar" class="corpus-type-button">ŠOLAR</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<select id="corpus-form-select" class="form-select" name="tip" form="tip" required="required" size="100">
|
|
||||||
<option value="prevodi" selected="selected">Prevodi</option>
|
|
||||||
<option value="gigafida">Gigafida</option>
|
|
||||||
<option value="solar">Šolar</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<label for="ime">* Ime:</label>
|
|
||||||
<input type="text" id="ime" name="ime" required="required"/>
|
|
||||||
|
|
||||||
<label for="podjetje">Podjetje / institucija:</label>
|
|
||||||
<input type="text" id="podjetje" name="podjetje"/>
|
|
||||||
|
|
||||||
<label for="naslov">Naslov:</label>
|
|
||||||
<input type="text" id="naslov" name="naslov"/>
|
|
||||||
|
|
||||||
<label for="posta">Pošta:</label>
|
|
||||||
<input type="text" id="posta" name="posta"/>
|
|
||||||
|
|
||||||
<label for="email">* Email:</label>
|
|
||||||
<input type="text" id="email" name="email" required="required"/>
|
|
||||||
|
|
||||||
<label for="telefon">Telefon:</label>
|
|
||||||
<input type="text" id="telefon" name="telefon"/>
|
|
||||||
|
|
||||||
<input type="checkbox" id="izjava" name="izjava" value="izjava" required="required">
|
|
||||||
<label for="izjava">* Izjavljam, da sem lastnik avtorskih pravic in dovoljujem, da se besedila vključijo v korpuse v skladu z ustrezno licenco korpusa.</label>
|
|
||||||
|
|
||||||
<button id="button-submit" type="submit">Oddaj</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dropzone-previews"></div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="popup-terms" style="display: none">
|
|
||||||
<div id="popup-terms-text">
|
|
||||||
<h2>POGODBA O PRENOSU AVTORSKIH PRAVIC</h2>
|
|
||||||
|
|
||||||
<h3>UVODNE DOLOČBE</h3>
|
|
||||||
<h4><b>1. člen</b></h4>
|
|
||||||
|
|
||||||
<p>1.1. Stranki uvodoma ugotavljata, da naročnik izvaja projekt Razvoj slovenščine v digitalnem
|
|
||||||
okolju – RSDO (v nadaljevanju projekt RSDO), ki je bil na javnem razpisu Razvoj slovenščine v
|
|
||||||
digitalnem okolju – jezikovni viri in tehnologije (JR-ESRR-Razvoj slovenščine v digitalnem
|
|
||||||
okolju), objavljenem v Uradnem listu RS št. 70/19 dne 29. 11. 2019, sprejet v sofinanciranje
|
|
||||||
in katerega vsebina je razvidna s spletnih strani https://slovenscina.eu.</p>
|
|
||||||
|
|
||||||
<p>1.2. Stranki uvodoma ugotavljata, da bo naročnik v okviru projekta RSDO:
|
|
||||||
- izdelal osrednjo digitalno slovarsko bazo, ki združuje različne tipe jezikovnih podatkov o
|
|
||||||
slovenščini v odprtem dostopu,
|
|
||||||
- izdelal terminološki portal z integriranim iskalnikom po slovenskih terminoloških virih, zlasti
|
|
||||||
terminoloških slovarjih,
|
|
||||||
- izdelal korpus prevodov po različnih domenah za učenje strojnega prevajalnika za jezikovni
|
|
||||||
par angleščina-slovenščina in slovenščina-angleščina.</p>
|
|
||||||
<p>1.3. Stranki uvodoma ugotavljata, da bo naročnik pri projektu RSDO za vse zgoraj opisane
|
|
||||||
namene zbiral in uporabil besedilne vire, ki so navedeni v prilogi k tej pogodbi in ki so lahko
|
|
||||||
avtorska dela ali drugi predmeti varstva v skladu z Zakonom o avtorski in sorodnih pravicah
|
|
||||||
(Uradni list RS, št. 16/07 – uradno prečiščeno besedilo, 68/08, 110/13, 56/15, 63/16 – ZKUASP
|
|
||||||
in 59/19; ZASP) in na katerih ima imetnik pravic avtorske, avtorski sorodne ali druge pravice v
|
|
||||||
skladu z ZASP (v nadaljevanju avtorska dela).</p>
|
|
||||||
|
|
||||||
<p>1.4. Stranki ugotavljata, da bodo avtorska dela in vse njihove morebitne spremembe in
|
|
||||||
predelave, ter zbirke podatkov, ki bodo med izvajanjem projekta RSDO nastale, javno
|
|
||||||
dostopni pod pogoji prostih licenc (npr. CC BY-SA) in bodo na voljo za nekomercialen in
|
|
||||||
komercialen razvoj tehnologij, za raziskave in za druge raziskovalne namene
|
|
||||||
posameznikom, raziskovalnim in izobraževalnim institucijam, neprofitnim organizacijam,
|
|
||||||
državnim organom, organizacijam z javnimi pooblastili in gospodarskim družbam v Sloveniji
|
|
||||||
in tujini.</p>
|
|
||||||
|
|
||||||
<h3>PREDMET POGODBE</h3>
|
|
||||||
<h4><b>2. člen</b></h4>
|
|
||||||
|
|
||||||
<p>2.1. Predmet pogodbe so vsa avtorska dela imetnika pravic, ki so navedena v prilogi k tej
|
|
||||||
pogodbi.</p>
|
|
||||||
|
|
||||||
<p>2.2. S podpisom te pogodbe imetnik avtorskih pravic na naročnika prenaša avtorske pravice
|
|
||||||
na avtorskih delih na način in v obsegu, kakor je navedeno v 3. členu te pogodbe.</p>
|
|
||||||
|
|
||||||
<h3>PRENOS AVTORSKIH PRAVIC</h3>
|
|
||||||
<h4><b>3. člen</b></h4>
|
|
||||||
|
|
||||||
<p>3.1. S podpisom te pogodbe imetnik pravic na avtorskih delih, ki so predmet te pogodbe, na
|
|
||||||
naročnika neizključno, brez časovnih in teritorialnih omejitev prenaša vse materialne avtorske
|
|
||||||
pravice, avtorski sorodne pravice in druge pravice avtorja v skladu z ZASP, zlasti pravico
|
|
||||||
reproduciranja (23. člen ZASP), distribuiranja (24. člena ZASP), dajanja v najem (25. člen ZASP),
|
|
||||||
priobčitve javnosti (26. do 32.a člen ZASP), vključno s pravico dajanja na voljo javnosti (32.a
|
|
||||||
člen ZASP) in pravico predelave (33. člen ZASP).</p>
|
|
||||||
|
|
||||||
<p>3.2. S podpisom te pogodbe imetnik pravic izrecno soglaša, da naročnik pravice iz točke 3.1.
|
|
||||||
prenaša naprej na tretje osebe brez omejitev.</p>
|
|
||||||
|
|
||||||
<h3>JAMČEVANJE IMETNIKA PRAVIC</h3>
|
|
||||||
|
|
||||||
<h4><b>4. člen</b></h4>
|
|
||||||
|
|
||||||
<p>4.1. S podpisom te pogodbe imetnik pravic jamči, da je na avtorskih delih, ki so predmet te
|
|
||||||
pogodbe, imetnik vseh avtorskih pravic, avtorski sorodnih pravic in drugih pravic avtorja v
|
|
||||||
skladu z ZASP, ki so potrebne za prenos pravic po tej pogodbi, in da na avtorskih delih ne
|
|
||||||
obstajajo pravice tretjih oseb, ki bi naročniku preprečevale njihovo uporabo.</p>
|
|
||||||
|
|
||||||
<p>4.2. Določbe te pogodbe ne vplivajo na prenos moralnih avtorskih pravic, ki so v skladu z
|
|
||||||
določbami ZASP neprenosljive.</p>
|
|
||||||
|
|
||||||
<h3>OSEBNI PODATKI</h3>
|
|
||||||
<h4><b>5. člen</b></h4>
|
|
||||||
|
|
||||||
<p>6.1. Stranki se zavezujeta, da bosta vse morebitne osebne podatke, ki jih bosta obdelovali za
|
|
||||||
namene izvajanja te pogodbe, obdelovali na način, da bosta upoštevali vse veljavne predpise
|
|
||||||
o varstvu osebnih podatkov in da bosta posameznikom, na katere se osebni podatki nanašajo,
|
|
||||||
zagotovili vse potrebne informacije v skladu s predpisi o varstvu osebnih podatkov.<p>
|
|
||||||
|
|
||||||
<h3>KONTAKTNE OSEBE</h3>
|
|
||||||
<h4><b>6. člen</b></h4>
|
|
||||||
|
|
||||||
<p>7.1 Kontaktna oseba za izvedbo te pogodbe na strani naročnika je [xxx].</p>
|
|
||||||
<p>7.2. Kontaktna oseba za izvedbo te pogodbe na strani imetnika pravic je [xxx].</p>
|
|
||||||
|
|
||||||
<h3>KONČNE DOLOČBE</h3>
|
|
||||||
<h4><b>7. člen</b></h4>
|
|
||||||
|
|
||||||
<p>8.1. Če je katerakoli določba te pogodbe nična, ostanejo druga določila te pogodbe v veljavi.</p>
|
|
||||||
|
|
||||||
<h4><b>8. člen</b></h4>
|
|
||||||
|
|
||||||
<p>9.1. Za razmerja v zvezi s to pogodbo se uporabljajo pravni predpisi Republike Slovenije.</p>
|
|
||||||
<p>9.2. Spore iz te pogodbe bosta stranki reševali po mirni poti. V primeru, da mirna rešitev ne
|
|
||||||
bo mogoča, je za vse spore v zvezi s to pogodbo pristojno sodišče v Ljubljani.</p>
|
|
||||||
|
|
||||||
<h4><b>9. člen</b></h4>
|
|
||||||
|
|
||||||
<p>10.1. Ta pogodba nadomešča vsa predhodna pogajanja, ponudbe in druge dogovore med
|
|
||||||
strankama.</p>
|
|
||||||
<p>10.2. Ta pogodba je sestavljena v [dveh] istovetnih izvodih, od katerih prejme vsaka stranka
|
|
||||||
po enega.</p>
|
|
||||||
<p>10.3. Pogodbeni stranki s podpisom potrjujeta veljavnost te pogodbe.</p>
|
|
||||||
</div>
|
|
||||||
<button id="button-submit-cancel" class="button-terms" style="background: #ff2d2d;">Prekliči</button>
|
|
||||||
<button id="button-submit-final" class="button-terms">Oddaj</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--{{ dropzone.load_js() }}-->
|
|
||||||
<script src="static/dropzone.js"></script>
|
|
||||||
<script>
|
|
||||||
//////////////////////////////
|
|
||||||
// Curpus type button logic //
|
|
||||||
//////////////////////////////
|
|
||||||
var formSelector = document.getElementById("corpus-form-select");
|
|
||||||
var buttons = document.getElementsByClassName("corpus-type-button");
|
|
||||||
|
|
||||||
function performButtonClickLogic(clickedBtnId) {
|
|
||||||
// Update buttons
|
|
||||||
for (var i = 0; i < buttons.length; i++) {
|
|
||||||
var btn = buttons[i];
|
|
||||||
if (btn.id == clickedBtnId) {
|
|
||||||
// Set style class
|
|
||||||
btn.disabled = true;
|
|
||||||
btn.classList.add("selected");
|
|
||||||
} else {
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.classList.remove("selected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Update (hidden) form selector
|
|
||||||
if (clickedBtnId == "corpus-type-prevodi") {
|
|
||||||
formSelector.value = "prevodi";
|
|
||||||
} else if (clickedBtnId == "corpus-type-gigafida") {
|
|
||||||
formSelector.value = "gigafida";
|
|
||||||
} else if (clickedBtnId == "corpus-type-solar") {
|
|
||||||
formSelector.value = "solar";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var corpusTypeBtnListener = function(event) {
|
|
||||||
var clickedBtnId = event.target.id;
|
|
||||||
performButtonClickLogic(clickedBtnId);
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var i = 0; i < buttons.length; i++) {
|
|
||||||
buttons[i].addEventListener('click', corpusTypeBtnListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When loading page automatically select "prevodi" option
|
|
||||||
performButtonClickLogic("corpus-type-prevodi");
|
|
||||||
|
|
||||||
/////////////////////////
|
|
||||||
// Dropzone //
|
|
||||||
/////////////////////////
|
|
||||||
var btnSubmit = document.getElementById("button-submit");
|
|
||||||
var btnSubmitFinal = document.getElementById("button-submit-final");
|
|
||||||
var btnSubmitCancel = document.getElementById("button-submit-cancel");
|
|
||||||
var elemTermsPopup = document.getElementById("popup-terms");
|
|
||||||
var termsScrollbox = document.getElementById("popup-terms-text");
|
|
||||||
var scrollboxTriggered = false;
|
|
||||||
var form = document.forms["my-dropzone"];
|
|
||||||
|
|
||||||
function isEmptyOrSpaces(str){
|
|
||||||
return str == null || str.match(/^ *$/) !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const reEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
|
|
||||||
Dropzone.options.myDropzone = { // The camelized version of the ID of the form element
|
|
||||||
url: "/upload",
|
|
||||||
autoProcessQueue: false,
|
|
||||||
uploadMultiple: true,
|
|
||||||
parallelUploads: 20,
|
|
||||||
paramName: "file", // The name that will be used to transfer the file
|
|
||||||
maxFilesize: 1000, // MB
|
|
||||||
acceptedFiles: ".txt, .csv, .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx",
|
|
||||||
maxFiles: 20,
|
|
||||||
dictDefaultMessage: `Kliknite ali odložite datoteke sem.`,
|
|
||||||
dictFallbackMessage: "Vaš brskalnik ne podpira izbiranje datotek z odlaganjem (\"drag & drop\").",
|
|
||||||
dictInvalidFileType: "Datoteka je napačnega formata.",
|
|
||||||
dictFileTooBig: "Datoteke je prevelika {{filesize}}. Največja dovoljena velikost: {{maxFilesize}}MiB.",
|
|
||||||
dictResponseError: "Napaka strežnika: {{statusCode}}",
|
|
||||||
dictMaxFilesExceeded: "Ne morete naložiti več datotek.",
|
|
||||||
dictCancelUpload: "Prekini prenos",
|
|
||||||
dictRemoveFile: "Odstrani datoteko",
|
|
||||||
dictCancelUploadConfirmation: "Ali res želite odstraniti to datoteko?",
|
|
||||||
dictUploadCanceled: "Prenos prekinjen",
|
|
||||||
|
|
||||||
// The setting up of the dropzone
|
|
||||||
init: function() {
|
|
||||||
var dz = this;
|
|
||||||
|
|
||||||
|
|
||||||
btnSubmit.addEventListener("click", function(e) {
|
|
||||||
// Make sure that the form isn't actually being sent.
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
// Check form validity.
|
|
||||||
var ime = form["ime"].value;
|
|
||||||
var email = form["email"].value;
|
|
||||||
var podjetje = form["podjetje"].value;
|
|
||||||
var telefon = form["telefon"].value;
|
|
||||||
var izjava = form["izjava"].checked;
|
|
||||||
if (isEmptyOrSpaces(ime) || isEmptyOrSpaces(email) || !izjava) {
|
|
||||||
alert("Izpolnite vsa obvezna polja!");
|
|
||||||
} else if (!reEmail.test(email.toLowerCase())) {
|
|
||||||
alert("Email napačnega formata!");
|
|
||||||
} else if (ime.length > 100 || email.length > 100 || podjetje.length > 100 || telefon.length > 100) {
|
|
||||||
alert("Velikost polj je omejena na 100 znakov.");
|
|
||||||
} else {
|
|
||||||
// Then make terms popup visible
|
|
||||||
btnSubmit.disabled = true;
|
|
||||||
btnSubmitFinal.disabled = true;
|
|
||||||
elemTermsPopup.style.display = "inline";
|
|
||||||
scrollboxTriggered = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// First change the button to actually tell Dropzone to process the queue.
|
|
||||||
btnSubmitFinal.addEventListener("click", function(e) {
|
|
||||||
// Hand off data to dropzone
|
|
||||||
dz.processQueue();
|
|
||||||
|
|
||||||
// Clear fields and hide popup agian
|
|
||||||
btnSubmit.disabled = false;
|
|
||||||
elemTermsPopup.style.display = "none";
|
|
||||||
form.reset();
|
|
||||||
scrollboxTriggered = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
btnSubmitCancel.addEventListener("click", function(e) {
|
|
||||||
btnSubmit.disabled = false;
|
|
||||||
scrollboxTriggered = false;
|
|
||||||
elemTermsPopup.style.display = "none";
|
|
||||||
});
|
|
||||||
|
|
||||||
// Enable final submit button only if user scrolls to the end of the terms.
|
|
||||||
function checkScrollboxTrigger(event) {
|
|
||||||
var element = event.target;
|
|
||||||
if (!scrollboxTriggered
|
|
||||||
&& element.scrollHeight - element.scrollTop <= element.clientHeight + 50
|
|
||||||
) {
|
|
||||||
scrollboxTriggered = true;
|
|
||||||
btnSubmitFinal.disabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
termsScrollbox.addEventListener('scroll', function(event) {
|
|
||||||
checkScrollboxTrigger(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
termsScrollbox.addEventListener("mouseenter", function(event) {
|
|
||||||
checkScrollboxTrigger(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
|
|
||||||
// of the sending event because uploadMultiple is set to true.
|
|
||||||
this.on("sendingmultiple", function() {
|
|
||||||
// Gets triggered when the form is actually being sent.
|
|
||||||
// Hide the success button or the complete form.
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on("successmultiple", function(files, response) {
|
|
||||||
// Gets triggered when the files have successfully been sent.
|
|
||||||
// Redirect user or notify of success.
|
|
||||||
alert("Odgovor strežnika: " + response);
|
|
||||||
location.reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on("errormultiple", function(files, response) {
|
|
||||||
// Gets triggered when there was an error sending the files.
|
|
||||||
// Maybe show form again, and notify user of error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user