Got emails working, added some form fields, added pdf generation, some refactoring
This commit is contained in:
parent
6174cf1c3e
commit
36dbe487ed
|
@ -1,7 +1,10 @@
|
||||||
FROM python:3.9
|
FROM python:3.9
|
||||||
|
|
||||||
COPY app.py /usr/src/portal-webapp/
|
COPY app.py /usr/src/portal-webapp/
|
||||||
|
COPY config.ini /usr/src/portal-webapp/
|
||||||
COPY templates /usr/src/portal-webapp/templates
|
COPY templates /usr/src/portal-webapp/templates
|
||||||
|
COPY static /usr/src/portal-webapp/static
|
||||||
|
COPY contract/ /usr/src/portal-webapp/contract
|
||||||
WORKDIR /usr/src/portal-webapp
|
WORKDIR /usr/src/portal-webapp
|
||||||
|
|
||||||
RUN pip install --no-cache-dir flask flask-dropzone gunicorn
|
RUN pip install --no-cache-dir flask flask-dropzone gunicorn
|
||||||
|
|
271
app.py
271
app.py
|
@ -2,31 +2,110 @@ import os
|
||||||
import re
|
import re
|
||||||
import hashlib
|
import hashlib
|
||||||
import time
|
import time
|
||||||
|
import ssl
|
||||||
|
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
|
||||||
|
|
||||||
from smtplib import SMTP_SSL as SMTP
|
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']
|
class ContractCreator:
|
||||||
regex_email = re.compile('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')
|
|
||||||
basedir = Path(__file__).resolve().parent
|
def __init__(self):
|
||||||
upload_dir = basedir / 'uploads'
|
template_loader = FileSystemLoader(searchpath="./")
|
||||||
if not upload_dir.exists:
|
template_env = Environment(loader=template_loader)
|
||||||
upload_dir.mkdir()
|
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 #
|
||||||
|
######################
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read('config.ini')
|
||||||
|
config = config['DEFAULT']
|
||||||
|
|
||||||
|
MAIL_HOST = config['MAIL_HOST']
|
||||||
|
MAIL_LOGIN = config['MAIL_LOGIN']
|
||||||
|
MAIL_PASS = config['MAIL_PASS']
|
||||||
|
SMTP_PORT = int(config['SMTP_PORT'])
|
||||||
|
IMAP_PORT = int(config['IMAP_PORT'])
|
||||||
|
MAX_UPLOAD_SIZE = int(config['MAX_UPLOAD_SIZE']) # Bytes
|
||||||
|
CONTRACT_CLIENT_CONTACT = config['CONTRACT_CLIENT_CONTACT']
|
||||||
|
if 'BASE_DIR' in config:
|
||||||
|
BASE_DIR = Path(config['BASE_DIR'])
|
||||||
|
else:
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
|
|
||||||
|
# Override configs with environment variables, if set
|
||||||
|
if 'PORTALDS4DS1_MAIL_HOST' in os.environ:
|
||||||
|
MAIL_HOST = os.environ('PORTALDS4DS1_MAIL_HOST')
|
||||||
|
if 'PORTALDS4DS1_MAIL_LOGIN' in os.environ:
|
||||||
|
MAIL_LOGIN = os.environ('PORTALDS4DS1_MAIL_LOGIN')
|
||||||
|
if 'PORTALDS4DS1_MAIL_PASS' in os.environ:
|
||||||
|
MAIL_PASS = os.environ('PORTALDS4DS1_MAIL_PASS')
|
||||||
|
if 'PORTALDS4DS1_SMTP_PORT' in os.environ:
|
||||||
|
SMTP_PORT = int(os.environ('PORTALDS4DS1_SMTP_PORT'))
|
||||||
|
if 'PORTALDS4DS1_IMAP_PORT' in os.environ:
|
||||||
|
IMAP_PORT = int(os.environ('PORTALDS4DS1_IMAP_PORT'))
|
||||||
|
if 'MAX_UPLOAD_SIZE' in os.environ:
|
||||||
|
MAX_UPLOAD_SIZE = int(os.environ('PORTALDS4DS1_MAX_UPLOAD_SIZE'))
|
||||||
|
if 'CONTRACT_CLIENT_CONTACT' in os.environ:
|
||||||
|
CONTRACT_CLIENT_CONTACT = os.environ('PORTALDS4DS1_CONTRACT_CLIENT_CONTACT')
|
||||||
|
|
||||||
|
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 = UPLOAD_DIR,
|
||||||
MAX_CONTENT_LENGTH = 1000000000, # 1GB
|
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():
|
||||||
|
@ -49,28 +128,75 @@ def handle_upload():
|
||||||
if err:
|
if err:
|
||||||
return err, 400
|
return err, 400
|
||||||
|
|
||||||
file_hashes = create_file_hashes(files)
|
upload_metadata = get_upload_metadata(request)
|
||||||
|
contract_file_name = generate_contract_pdf(upload_metadata)
|
||||||
store_metadata(request.form, file_hashes)
|
# Add contract_file_name to metadata TODO: move somewhere else
|
||||||
store_datafiles(files, file_hashes)
|
upload_metadata['contract'] = contract_file_name
|
||||||
send_confirm_mail(request.form.get('email'))
|
store_datafiles(files, upload_metadata)
|
||||||
|
store_metadata(upload_metadata)
|
||||||
|
send_confirm_mail(upload_metadata)
|
||||||
|
|
||||||
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):
|
def check_suffixes(files):
|
||||||
for key, f in files.items():
|
for key, f in files.items():
|
||||||
if key.startswith('file'):
|
if key.startswith('file'):
|
||||||
suffix = f.filename.split('.')[-1]
|
suffix = f.filename.split('.')[-1]
|
||||||
if suffix not in enabled_filetypes:
|
if suffix not in ENABLED_FILETYPES:
|
||||||
return 'Datoteka "{}" ni pravilnega formata.'.format(f.filename)
|
return 'Datoteka "{}" ni pravilnega formata.'.format(f.filename)
|
||||||
return None
|
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):
|
def check_form(form):
|
||||||
tip = form.get('tip')
|
tip = form.get('tip')
|
||||||
ime = form.get('ime')
|
ime = form.get('ime')
|
||||||
podjetje = form.get('podjetje')
|
podjetje = form.get('podjetje')
|
||||||
|
naslov = form.get('naslov')
|
||||||
|
posta = form.get('posta')
|
||||||
email = form.get('email')
|
email = form.get('email')
|
||||||
telefon = form.get('telefon')
|
telefon = form.get('telefon')
|
||||||
|
|
||||||
|
@ -81,16 +207,22 @@ def check_form(form):
|
||||||
return 'Predolgo ime.'
|
return 'Predolgo ime.'
|
||||||
|
|
||||||
if len(podjetje) > 100:
|
if len(podjetje) > 100:
|
||||||
return 'Predolgo ime institucije'
|
return 'Predolgo ime institucije.'
|
||||||
|
|
||||||
if len(email) > 100:
|
if len(email) > 100:
|
||||||
return 'Predolgi email naslov'
|
return 'Predolgi email naslov'
|
||||||
elif not re.search(regex_email, email):
|
elif not re.search(REGEX_EMAIL, email):
|
||||||
return 'Email napačnega formata.'
|
return 'Email napačnega formata.'
|
||||||
|
|
||||||
if len(telefon) > 100:
|
if len(telefon) > 100:
|
||||||
return 'Predolga telefonska št.'
|
return 'Predolga telefonska št.'
|
||||||
|
|
||||||
|
if len(naslov) > 100:
|
||||||
|
return 'Predolg naslov.'
|
||||||
|
|
||||||
|
if len(posta) > 100:
|
||||||
|
return 'Predolga pošta'
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,42 +237,35 @@ def create_file_hashes(files):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def store_metadata(form, file_hashes):
|
def store_metadata(upload_metadata):
|
||||||
base = app.config['UPLOADED_PATH'] / 'meta'
|
base = get_subdir('meta')
|
||||||
if not base.exists():
|
|
||||||
base.mkdir()
|
|
||||||
|
|
||||||
tip = form.get('tip')
|
timestamp = upload_metadata['timestamp']
|
||||||
ime = form.get('ime')
|
upload_id = upload_metadata['upload_id']
|
||||||
podjetje = form.get('podjetje')
|
form_data = upload_metadata['form_data']
|
||||||
email = form.get('email')
|
email = form_data['email']
|
||||||
telefon = form.get('telefon')
|
file_hashes = upload_metadata['file_hashes']
|
||||||
|
contract = upload_metadata['contract']
|
||||||
|
filename = str(timestamp) + '-' + email + '-' + upload_id + '.meta'
|
||||||
|
|
||||||
# This hash serves as an identifier for the whole upload.
|
|
||||||
metahash = hashlib.md5((tip+ime+podjetje+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 = list(file_hashes.values())
|
||||||
sorted_f_hashes.sort()
|
sorted_f_hashes.sort()
|
||||||
metahash.update(''.join(sorted_f_hashes).encode())
|
|
||||||
metahash = metahash.hexdigest()
|
|
||||||
|
|
||||||
timestamp = int(time.time())
|
|
||||||
filename = str(timestamp) + '-' + email + '-' + metahash + '.meta'
|
|
||||||
|
|
||||||
path = base / filename
|
path = base / filename
|
||||||
with path.open('w') as f:
|
with path.open('w') as f:
|
||||||
f.write('tip=' + tip)
|
f.write('tip=' + form_data['tip'])
|
||||||
f.write('\nime=' + ime)
|
f.write('\nime=' + form_data['ime'])
|
||||||
f.write('\npodjetje=' + podjetje)
|
f.write('\npodjetje=' + form_data['podjetje'])
|
||||||
f.write('\nemail=' + email)
|
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('\ndatoteke=' + str(sorted_f_hashes))
|
||||||
|
f.write('\npogodba=' + contract)
|
||||||
|
|
||||||
|
|
||||||
def store_datafiles(files, file_hashes):
|
def store_datafiles(files, upload_metadata):
|
||||||
base = app.config['UPLOADED_PATH'] / 'files'
|
base = get_subdir('files')
|
||||||
if not base.exists():
|
file_hashes = upload_metadata['file_hashes']
|
||||||
base.mkdir()
|
|
||||||
|
|
||||||
for key, f in files.items():
|
for key, f in files.items():
|
||||||
if key.startswith('file'):
|
if key.startswith('file'):
|
||||||
|
@ -149,19 +274,55 @@ def store_datafiles(files, file_hashes):
|
||||||
path.mkdir()
|
path.mkdir()
|
||||||
f.save(path / f.filename)
|
f.save(path / f.filename)
|
||||||
|
|
||||||
def send_confirm_mail(email):
|
def generate_contract_pdf(upload_metadata):
|
||||||
#msg = MIMEText(content, text_subtype)
|
base = get_subdir('contracts')
|
||||||
#msg['Subject'] = "TEST"
|
contract_file_name = upload_metadata['upload_id'] + '.pdf'
|
||||||
#msg['From'] = sender # some SMTP servers will do this automatically, not all
|
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']
|
||||||
|
}
|
||||||
|
|
||||||
#conn = SMTP(SMTPserver)
|
contract_creator.create_pdf(base / contract_file_name, data)
|
||||||
#conn.set_debuglevel(False)
|
return contract_file_name
|
||||||
#conn.login(USERNAME, PASSWORD)
|
|
||||||
#try:
|
def send_confirm_mail(upload_metadata):
|
||||||
# conn.sendmail(sender, destination, msg.as_string())
|
body = 'Usprešno ste oddali besedila. V prilogi vam pošiljamo pogodbo.'
|
||||||
#finally:
|
|
||||||
# conn.quit()
|
message = MIMEMultipart()
|
||||||
pass
|
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__':
|
||||||
|
|
9
config.ini
Normal file
9
config.ini
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[DEFAULT]
|
||||||
|
MAIL_HOST=posta.cjvt.si
|
||||||
|
MAIL_LOGIN=oddaja-besedil@cjvt.si
|
||||||
|
MAIL_PASS=randompass123
|
||||||
|
SMTP_PORT=465
|
||||||
|
IMAP_PORT=993
|
||||||
|
MAX_UPLOAD_SIZE=1000000000
|
||||||
|
BASE_DIR=./
|
||||||
|
CONTRACT_CLIENT_CONTACT=Testko Tester
|
BIN
contract/out.pdf
Normal file
BIN
contract/out.pdf
Normal file
Binary file not shown.
43
contract/pdf.py
Normal file
43
contract/pdf.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
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)
|
202
contract/template.html
Normal file
202
contract/template.html
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 80%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p><b>Univerza v Ljubljani<br>
|
||||||
|
Kongresni trg 12<br>
|
||||||
|
1000 Ljubljana<br>
|
||||||
|
matična številka: 5085063000<br>
|
||||||
|
davčna številka: 54162513<br></b>
|
||||||
|
<br>
|
||||||
|
(v nadaljevanju <b>naročnik</b>)<br>
|
||||||
|
<br>
|
||||||
|
in<br>
|
||||||
|
<br>
|
||||||
|
<b>
|
||||||
|
{{ime_priimek}}<br>
|
||||||
|
{{naslov}}<br>
|
||||||
|
{{posta}}<br>
|
||||||
|
</b>
|
||||||
|
<br>
|
||||||
|
(v nadaljevanju <b>imetnik pravic</b>)<br>
|
||||||
|
<br>
|
||||||
|
v nadaljevanju skupaj <b>stranki</b><br>
|
||||||
|
<br>
|
||||||
|
sklepata naslednjo<br>
|
||||||
|
</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 style="text-align: center;">POGODBO O PRENOSU AVTORSKIH PRAVIC</h2>
|
||||||
|
|
||||||
|
<h3 style="text-align: center;">UVODNE DOLOČBE</h3>
|
||||||
|
<h4 style="text-align: center;"><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 style="text-align: center;">PREDMET POGODBE</h3>
|
||||||
|
<h4 style="text-align: center;"><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 style="text-align: center;">PRENOS AVTORSKIH PRAVIC</h3>
|
||||||
|
<h4 style="text-align: center;"><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 style="text-align: center;">JAMČEVANJE IMETNIKA PRAVIC</h3>
|
||||||
|
|
||||||
|
<h4 style="text-align: center;"><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 style="text-align: center;">OSEBNI PODATKI</h3>
|
||||||
|
<h4 style="text-align: center;"><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 style="text-align: center;">KONTAKTNE OSEBE</h3>
|
||||||
|
<h4 style="text-align: center;"><b>6. člen</b></h4>
|
||||||
|
|
||||||
|
<p>7.1 Kontaktna oseba za izvedbo te pogodbe na strani naročnika je {{kontakt_narocnik}}.</p>
|
||||||
|
<p>7.2. Kontaktna oseba za izvedbo te pogodbe na strani imetnika pravic {{kontakt_imetnikpravic}}.</p>
|
||||||
|
|
||||||
|
<h3 style="text-align: center;">KONČNE DOLOČBE</h3>
|
||||||
|
<h4 style="text-align: center;"><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 style="text-align: center;"><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 style="text-align: center;"><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>
|
||||||
|
|
||||||
|
<p><b>V Ljubljani, dne {{date}}</b></p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div style="float: left;">
|
||||||
|
<p>Naročnik:</p>
|
||||||
|
<br><br>
|
||||||
|
<p>_____________________</p>
|
||||||
|
</div>
|
||||||
|
<div style="float: right; margin-right: 80px;">
|
||||||
|
<p>Imetnik pravic:</p>
|
||||||
|
<br><br>
|
||||||
|
<p>_____________________</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p style="text-align: center;"><b>Priloga k pogodbi o prenosu avtorskih pravic: seznam avtorskih del, ki so predmet pogodbe</b></p>
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><b>Ime, naslov ali oznaka dela</b></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>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -78,7 +78,7 @@ label {
|
||||||
background: #006cb7;
|
background: #006cb7;
|
||||||
border-radius: 29px;
|
border-radius: 29px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
top: 430px;
|
top: 530px;
|
||||||
|
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
@ -164,7 +164,7 @@ input {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
top: -430px;
|
top: -530px;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ input {
|
||||||
#rect1 {
|
#rect1 {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 388px;
|
width: 388px;
|
||||||
height: 531px;
|
height: 631px;
|
||||||
|
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
box-shadow: 0px 4px 40px rgba(0, 0, 0, 0.25);
|
box-shadow: 0px 4px 40px rgba(0, 0, 0, 0.25);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{{ dropzone.style('position: absolute;
|
{{ dropzone.style('position: absolute;
|
||||||
top: -0.5px;
|
top: -0.5px;
|
||||||
width: 388px;
|
width: 388px;
|
||||||
height: 532px;
|
height: 632px;
|
||||||
left: 385px;
|
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%);
|
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);
|
box-shadow: 20px 4px 40px rgba(0, 0, 0, 0.25);
|
||||||
|
@ -43,6 +43,12 @@
|
||||||
<label for="podjetje">Podjetje / institucija:</label>
|
<label for="podjetje">Podjetje / institucija:</label>
|
||||||
<input type="text" id="podjetje" name="podjetje"/>
|
<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>
|
<label for="email">* Email:</label>
|
||||||
<input type="text" id="email" name="email" required="required"/>
|
<input type="text" id="email" name="email" required="required"/>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user