Skip to content
Snippets Groups Projects
Commit 3eaf9cfc authored by Julian Rother's avatar Julian Rother
Browse files

Replaced "responsible" text field with multiselect widget

parent 6d58ed62
No related branches found
No related tags found
No related merge requests found
...@@ -297,7 +297,8 @@ CREATE TABLE IF NOT EXISTS `jobs` ( ...@@ -297,7 +297,8 @@ CREATE TABLE IF NOT EXISTS `jobs` (
CREATE TABLE IF NOT EXISTS `responsible` ( CREATE TABLE IF NOT EXISTS `responsible` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`course_id` INTEGER NOT NULL, `course_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL `user_id` INTEGER NOT NULL,
UNIQUE (course_id, user_id)
); );
CREATE VIEW IF NOT EXISTS `courses` AS select * from `courses_data` where (not(`courses_data`.`deleted`)); CREATE VIEW IF NOT EXISTS `courses` AS select * from `courses_data` where (not(`courses_data`.`deleted`));
......
...@@ -196,3 +196,15 @@ def changelog(): ...@@ -196,3 +196,15 @@ def changelog():
for entry in changelog: for entry in changelog:
entry['path'] = '.'.join([entry['table'], entry['id_value'], entry['field']]) entry['path'] = '.'.join([entry['table'], entry['id_value'], entry['field']])
return render_template('changelog.html', changelog=changelog, page=page, pagesize=pagesize, pagecount=pagecount) return render_template('changelog.html', changelog=changelog, page=page, pagesize=pagesize, pagecount=pagecount)
@app.route('/internal/set/responsible/<int:course_id>/<int:user_id>', defaults={'value': True}, methods=['GET', 'POST'])
@app.route('/internal/unset/responsible/<int:course_id>/<int:user_id>', defaults={'value': False}, methods=['GET', 'POST'])
@mod_required
@csrf_protect
def set_responsible(course_id, user_id, value):
if value:
modify('REPLACE INTO responsible (course_id, user_id) values (?, ?)', course_id, user_id);
else:
modify('DELETE FROM responsible WHERE course_id = ? AND user_id = ?', course_id, user_id);
return "OK", 200
...@@ -261,7 +261,12 @@ def course(id=None, handle=None): ...@@ -261,7 +261,12 @@ def course(id=None, handle=None):
if course['coursechapters']: if course['coursechapters']:
chapters = query('SELECT chapters.* FROM chapters JOIN lectures ON lectures.id = chapters.lecture_id WHERE lectures.course_id = ? AND NOT chapters.deleted AND chapters.visible ORDER BY time ASC', course['id']) chapters = query('SELECT chapters.* FROM chapters JOIN lectures ON lectures.id = chapters.lecture_id WHERE lectures.course_id = ? AND NOT chapters.deleted AND chapters.visible ORDER BY time ASC', course['id'])
videos += genlive(livestreams) videos += genlive(livestreams)
return render_template('course.html', course=course, lectures=lectures, videos=videos, chapters=chapters) responsible = query('''SELECT users.*, responsible.course_id AS responsible
FROM users
LEFT JOIN responsible ON (responsible.user_id = users.id AND responsible.course_id = ?)
WHERE users.fsacc != "" AND users.level > 0
ORDER BY responsible DESC, users.realname ASC''', course['id'])
return render_template('course.html', course=course, lectures=lectures, videos=videos, chapters=chapters, responsible=responsible)
@app.route('/faq') @app.route('/faq')
@register_navbar('FAQ', icon='question-sign') @register_navbar('FAQ', icon='question-sign')
......
span.multiselect-native-select{position:relative}span.multiselect-native-select select{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px -1px -1px -3px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;left:50%;top:30px}.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0}
This diff is collapsed.
...@@ -12,6 +12,24 @@ var moderator = { ...@@ -12,6 +12,24 @@ var moderator = {
req[path] = value; req[path] = value;
moderator.api.set_multi(req,reload) moderator.api.set_multi(req,reload)
}, },
set_map: function(table, key1, key2, value) {
var dict = {};
var url;
if (value) {
url = "/internal/set/"+table+"/"+key1+"/"+key2;
} else {
url = "/internal/unset/"+table+"/"+key1+"/"+key2;
}
dict['_csrf_token'] = moderator.api.csrf_token;
$.ajax({
method: "POST",
url: url,
dataType: "text",
contentType: "application/json",
data: JSON.stringify(dict),
error: moderator.api.handleapierror
});
},
set_multi: function(dict,reload) { set_multi: function(dict,reload) {
dict['_csrf_token'] = moderator.api.csrf_token; dict['_csrf_token'] = moderator.api.csrf_token;
$.ajax({ $.ajax({
......
...@@ -20,12 +20,16 @@ ...@@ -20,12 +20,16 @@
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='videojs/video-js.css')}}"> <link rel="stylesheet" type="text/css" href="{{url_for('static', filename='videojs/video-js.css')}}">
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='videojs/videojs.markers.css')}}"> <link rel="stylesheet" type="text/css" href="{{url_for('static', filename='videojs/videojs.markers.css')}}">
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='videojs/videojs-resolution-switcher.css')}}"> <link rel="stylesheet" type="text/css" href="{{url_for('static', filename='videojs/videojs-resolution-switcher.css')}}">
{% if ismod() %}
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='bootstrap-multiselect.css')}}">
{% endif %}
<script src="{{url_for('static', filename='jquery.js')}}"></script> <script src="{{url_for('static', filename='jquery.js')}}"></script>
<script src="{{url_for('static', filename='bootstrap/bootstrap.js')}}"></script> <script src="{{url_for('static', filename='bootstrap/bootstrap.js')}}"></script>
<script src="{{url_for('static', filename='js.cookie.js')}}"></script> <script src="{{url_for('static', filename='js.cookie.js')}}"></script>
{%if ismod() %} {%if ismod() %}
<script src="{{url_for('static', filename='moderator.js')}}"></script> <script src="{{url_for('static', filename='moderator.js')}}"></script>
<script src="{{url_for('static', filename='bootstrap-multiselect.js')}}"></script>
<script src="{{url_for('static', filename='plotly.min.js')}}"></script> <script src="{{url_for('static', filename='plotly.min.js')}}"></script>
{% endif %} {% endif %}
<script src="{{url_for('static', filename='videojs/video.js')}}"></script> <script src="{{url_for('static', filename='videojs/video.js')}}"></script>
......
...@@ -49,7 +49,13 @@ ...@@ -49,7 +49,13 @@
<tr><td>Short:</td><td>{{ moderator_editor(['courses',course.id,'short'], course.short) }}</td></tr> <tr><td>Short:</td><td>{{ moderator_editor(['courses',course.id,'short'], course.short) }}</td></tr>
<tr><td>Handle:</td><td>{{ moderator_editor(['courses',course.id,'handle'], course.handle) }}</td></tr> <tr><td>Handle:</td><td>{{ moderator_editor(['courses',course.id,'handle'], course.handle) }}</td></tr>
<tr><td>Thema:</td><td>{{ moderator_editor(['courses',course.id,'subject'], course.subject) }}</td></tr> <tr><td>Thema:</td><td>{{ moderator_editor(['courses',course.id,'subject'], course.subject) }}</td></tr>
<tr><td>Zuständig:</td><td>{{ moderator_editor(['courses',course.id,'responsible'], course.responsible) }}</td></tr> <tr><td>Zuständig:</td><td>
<select id="responsible-select" multiple="multiple">
{% for user in responsible %}
<option value="{{ user.id }}"{% if user.responsible %} selected="selected"{% endif %}>{{ user.realname }}</option>
{% endfor %}
</select>
</td></tr>
<tr><td>Interne Bemerkungen:</td><td>{{ moderator_editor(['courses',course.id,'internal'], course.internal) }}</td></tr> <tr><td>Interne Bemerkungen:</td><td>{{ moderator_editor(['courses',course.id,'internal'], course.internal) }}</td></tr>
</tbody> </tbody>
</table> </table>
...@@ -138,6 +144,14 @@ ...@@ -138,6 +144,14 @@
</div> </div>
</div> </div>
<script> <script>
{% if ismod() %}
$('#responsible-select').multiselect({enableCaseInsensitiveFiltering: true,
maxHeight: 200, numberDisplayed: 5, nonSelectedText: 'Niemand',
nSelectedText: 'ausgewählt', allSelectedText: false,
onChange: function(option, checked, select) {
moderator.api.set_map('responsible', {{ course.id }}, option.val(), checked);
}})
{% endif %}
$.ajax({ $.ajax({
method: "GET", method: "GET",
url: "{{url_for('stats_generic', req="lecture_views", param=course.id)}}", url: "{{url_for('stats_generic', req="lecture_views", param=course.id)}}",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment