Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • konstantin/akplanning
  • matedealer/akplanning
  • kif/akplanning
  • mirco/akplanning
  • lordofthevoid/akplanning
  • voidptr/akplanning
  • xayomer/akplanning-fork
  • mollux/akplanning
  • neumantm/akplanning
  • mmarx/akplanning
  • nerf/akplanning
  • felix_bonn/akplanning
  • sebastian.uschmann/akplanning
13 results
Show changes
Showing
with 397 additions and 171 deletions
.gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8}.gu-hide{display:none!important}.gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.gu-transit{opacity:.2}
\ No newline at end of file
!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).dragula=e()}(function(){return function o(r,i,u){function c(t,e){if(!i[t]){if(!r[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(a)return a(t,!0);throw(n=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",n}n=i[t]={exports:{}},r[t][0].call(n.exports,function(e){return c(r[t][1][e]||e)},n,n.exports,o,r,i,u)}return i[t].exports}for(var a="function"==typeof require&&require,e=0;e<u.length;e++)c(u[e]);return c}({1:[function(e,t,n){"use strict";var o={},r="(?:^|\\s)",i="(?:\\s|$)";function u(e){var t=o[e];return t?t.lastIndex=0:o[e]=t=new RegExp(r+e+i,"g"),t}t.exports={add:function(e,t){var n=e.className;n.length?u(t).test(n)||(e.className+=" "+t):e.className=t},rm:function(e,t){e.className=e.className.replace(u(t)," ").trim()}}},{}],2:[function(e,t,n){(function(r){"use strict";var M=e("contra/emitter"),k=e("crossvent"),j=e("./classes"),R=document,q=R.documentElement;function U(e,t,n,o){r.navigator.pointerEnabled?k[t](e,{mouseup:"pointerup",mousedown:"pointerdown",mousemove:"pointermove"}[n],o):r.navigator.msPointerEnabled?k[t](e,{mouseup:"MSPointerUp",mousedown:"MSPointerDown",mousemove:"MSPointerMove"}[n],o):(k[t](e,{mouseup:"touchend",mousedown:"touchstart",mousemove:"touchmove"}[n],o),k[t](e,n,o))}function K(e){if(void 0!==e.touches)return e.touches.length;if(void 0!==e.which&&0!==e.which)return e.which;if(void 0!==e.buttons)return e.buttons;e=e.button;return void 0!==e?1&e?1:2&e?3:4&e?2:0:void 0}function z(e,t){return void 0!==r[t]?r[t]:(q.clientHeight?q:R.body)[e]}function H(e,t,n){var o=(e=e||{}).className||"";return e.className+=" gu-hide",n=R.elementFromPoint(t,n),e.className=o,n}function V(){return!1}function $(){return!0}function G(e){return e.width||e.right-e.left}function J(e){return e.height||e.bottom-e.top}function Q(e){return e.parentNode===R?null:e.parentNode}function W(e){return"INPUT"===e.tagName||"TEXTAREA"===e.tagName||"SELECT"===e.tagName||function e(t){if(!t)return!1;if("false"===t.contentEditable)return!1;if("true"===t.contentEditable)return!0;return e(Q(t))}(e)}function Z(t){return t.nextElementSibling||function(){var e=t;for(;e=e.nextSibling,e&&1!==e.nodeType;);return e}()}function ee(e,t){var t=(n=t).targetTouches&&n.targetTouches.length?n.targetTouches[0]:n.changedTouches&&n.changedTouches.length?n.changedTouches[0]:n,n={pageX:"clientX",pageY:"clientY"};return e in n&&!(e in t)&&n[e]in t&&(e=n[e]),t[e]}t.exports=function(e,t){var l,f,s,d,m,o,r,v,p,h,n;1===arguments.length&&!1===Array.isArray(e)&&(t=e,e=[]);var i,g=null,y=t||{};void 0===y.moves&&(y.moves=$),void 0===y.accepts&&(y.accepts=$),void 0===y.invalid&&(y.invalid=function(){return!1}),void 0===y.containers&&(y.containers=e||[]),void 0===y.isContainer&&(y.isContainer=V),void 0===y.copy&&(y.copy=!1),void 0===y.copySortSource&&(y.copySortSource=!1),void 0===y.revertOnSpill&&(y.revertOnSpill=!1),void 0===y.removeOnSpill&&(y.removeOnSpill=!1),void 0===y.direction&&(y.direction="vertical"),void 0===y.ignoreInputTextSelection&&(y.ignoreInputTextSelection=!0),void 0===y.mirrorContainer&&(y.mirrorContainer=R.body);var w=M({containers:y.containers,start:function(e){e=S(e);e&&C(e)},end:O,cancel:L,remove:X,destroy:function(){c(!0),N({})},canMove:function(e){return!!S(e)},dragging:!1});return!0===y.removeOnSpill&&w.on("over",function(e){j.rm(e,"gu-hide")}).on("out",function(e){w.dragging&&j.add(e,"gu-hide")}),c(),w;function u(e){return-1!==w.containers.indexOf(e)||y.isContainer(e)}function c(e){e=e?"remove":"add";U(q,e,"mousedown",E),U(q,e,"mouseup",N)}function a(e){U(q,e?"remove":"add","mousemove",x)}function b(e){e=e?"remove":"add";k[e](q,"selectstart",T),k[e](q,"click",T)}function T(e){i&&e.preventDefault()}function E(e){var t,n;o=e.clientX,r=e.clientY,1!==K(e)||e.metaKey||e.ctrlKey||(n=S(t=e.target))&&(i=n,a(),"mousedown"===e.type&&(W(t)?t.focus():e.preventDefault()))}function x(e){if(i)if(0!==K(e)){if(!(void 0!==e.clientX&&Math.abs(e.clientX-o)<=(y.slideFactorX||0)&&void 0!==e.clientY&&Math.abs(e.clientY-r)<=(y.slideFactorY||0))){if(y.ignoreInputTextSelection){var t=ee("clientX",e)||0,n=ee("clientY",e)||0;if(W(R.elementFromPoint(t,n)))return}n=i;a(!0),b(),O(),C(n);n=function(e){e=e.getBoundingClientRect();return{left:e.left+z("scrollLeft","pageXOffset"),top:e.top+z("scrollTop","pageYOffset")}}(s);d=ee("pageX",e)-n.left,m=ee("pageY",e)-n.top,j.add(h||s,"gu-transit"),function(){if(l)return;var e=s.getBoundingClientRect();(l=s.cloneNode(!0)).style.width=G(e)+"px",l.style.height=J(e)+"px",j.rm(l,"gu-transit"),j.add(l,"gu-mirror"),y.mirrorContainer.appendChild(l),U(q,"add","mousemove",P),j.add(y.mirrorContainer,"gu-unselectable"),w.emit("cloned",l,s,"mirror")}(),P(e)}}else N({})}function S(e){if(!(w.dragging&&l||u(e))){for(var t=e;Q(e)&&!1===u(Q(e));){if(y.invalid(e,t))return;if(!(e=Q(e)))return}var n=Q(e);if(n)if(!y.invalid(e,t))if(y.moves(e,n,t,Z(e)))return{item:e,source:n}}}function C(e){var t,n;t=e.item,n=e.source,("boolean"==typeof y.copy?y.copy:y.copy(t,n))&&(h=e.item.cloneNode(!0),w.emit("cloned",h,e.item,"copy")),f=e.source,s=e.item,v=p=Z(e.item),w.dragging=!0,w.emit("drag",s,f)}function O(){var e;w.dragging&&_(e=h||s,Q(e))}function I(){a(!(i=!1)),b(!0)}function N(e){var t,n;I(),w.dragging&&(t=h||s,n=ee("clientX",e)||0,e=ee("clientY",e)||0,(e=B(H(l,n,e),n,e))&&(h&&y.copySortSource||!h||e!==f)?_(t,e):(y.removeOnSpill?X:L)())}function _(e,t){var n=Q(e);h&&y.copySortSource&&t===f&&n.removeChild(s),A(t)?w.emit("cancel",e,f,f):w.emit("drop",e,t,f,p),Y()}function X(){var e,t;w.dragging&&((t=Q(e=h||s))&&t.removeChild(e),w.emit(h?"cancel":"remove",e,t,f),Y())}function L(e){var t,n,o;w.dragging&&(t=0<arguments.length?e:y.revertOnSpill,!1===(e=A(o=Q(n=h||s)))&&t&&(h?o&&o.removeChild(h):f.insertBefore(n,v)),e||t?w.emit("cancel",n,f,f):w.emit("drop",n,o,f,p),Y())}function Y(){var e=h||s;I(),l&&(j.rm(y.mirrorContainer,"gu-unselectable"),U(q,"remove","mousemove",P),Q(l).removeChild(l),l=null),e&&j.rm(e,"gu-transit"),n&&clearTimeout(n),w.dragging=!1,g&&w.emit("out",e,g,f),w.emit("dragend",e),f=s=h=v=p=n=g=null}function A(e,t){t=void 0!==t?t:l?p:Z(h||s);return e===f&&t===v}function B(t,n,o){for(var r=t;r&&!function(){if(!1===u(r))return!1;var e=D(r,t),e=F(r,e,n,o);if(A(r,e))return!0;return y.accepts(s,r,f,e)}();)r=Q(r);return r}function P(e){if(l){e.preventDefault();var t=ee("clientX",e)||0,n=ee("clientY",e)||0,o=t-d,r=n-m;l.style.left=o+"px",l.style.top=r+"px";var i=h||s,e=H(l,t,n),o=B(e,t,n),u=null!==o&&o!==g;!u&&null!==o||(g&&a("out"),g=o,u&&a("over"));r=Q(i);if(o!==f||!h||y.copySortSource){var c,e=D(o,e);if(null!==e)c=F(o,e,t,n);else{if(!0!==y.revertOnSpill||h)return void(h&&r&&r.removeChild(i));c=v,o=f}(null===c&&u||c!==i&&c!==Z(i))&&(p=c,o.insertBefore(i,c),w.emit("shadow",i,o,f))}else r&&r.removeChild(i)}function a(e){w.emit(e,i,g,f)}}function D(e,t){for(var n=t;n!==e&&Q(n)!==e;)n=Q(n);return n===q?null:n}function F(r,t,i,u){var c="horizontal"===y.direction;return(t!==r?function(){var e=t.getBoundingClientRect();if(c)return n(i>e.left+G(e)/2);return n(u>e.top+J(e)/2)}:function(){var e,t,n,o=r.children.length;for(e=0;e<o;e++){if(t=r.children[e],n=t.getBoundingClientRect(),c&&n.left+n.width/2>i)return t;if(!c&&n.top+n.height/2>u)return t}return null})();function n(e){return e?Z(t):t}}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./classes":1,"contra/emitter":5,crossvent:6}],3:[function(e,t,n){t.exports=function(e,t){return Array.prototype.slice.call(e,t)}},{}],4:[function(e,t,n){"use strict";var o=e("ticky");t.exports=function(e,t,n){e&&o(function(){e.apply(n||null,t||[])})}},{ticky:10}],5:[function(e,t,n){"use strict";var c=e("atoa"),a=e("./debounce");t.exports=function(r,e){var i=e||{},u={};return void 0===r&&(r={}),r.on=function(e,t){return u[e]?u[e].push(t):u[e]=[t],r},r.once=function(e,t){return t._once=!0,r.on(e,t),r},r.off=function(e,t){var n=arguments.length;if(1===n)delete u[e];else if(0===n)u={};else{e=u[e];if(!e)return r;e.splice(e.indexOf(t),1)}return r},r.emit=function(){var e=c(arguments);return r.emitterSnapshot(e.shift()).apply(this,e)},r.emitterSnapshot=function(o){var e=(u[o]||[]).slice(0);return function(){var t=c(arguments),n=this||r;if("error"===o&&!1!==i.throws&&!e.length)throw 1===t.length?t[0]:t;return e.forEach(function(e){i.async?a(e,t,n):e.apply(n,t),e._once&&r.off(o,e)}),r}},r}},{"./debounce":4,atoa:3}],6:[function(n,o,e){(function(r){"use strict";var i=n("custom-event"),u=n("./eventmap"),c=r.document,e=function(e,t,n,o){return e.addEventListener(t,n,o)},t=function(e,t,n,o){return e.removeEventListener(t,n,o)},a=[];function l(e,t,n){t=function(e,t,n){var o,r;for(o=0;o<a.length;o++)if((r=a[o]).element===e&&r.type===t&&r.fn===n)return o}(e,t,n);if(t){n=a[t].wrapper;return a.splice(t,1),n}}r.addEventListener||(e=function(e,t,n){return e.attachEvent("on"+t,function(e,t,n){var o=l(e,t,n)||function(n,o){return function(e){var t=e||r.event;t.target=t.target||t.srcElement,t.preventDefault=t.preventDefault||function(){t.returnValue=!1},t.stopPropagation=t.stopPropagation||function(){t.cancelBubble=!0},t.which=t.which||t.keyCode,o.call(n,t)}}(e,n);return a.push({wrapper:o,element:e,type:t,fn:n}),o}(e,t,n))},t=function(e,t,n){n=l(e,t,n);if(n)return e.detachEvent("on"+t,n)}),o.exports={add:e,remove:t,fabricate:function(e,t,n){var o=-1===u.indexOf(t)?new i(t,{detail:n}):function(){var e;c.createEvent?(e=c.createEvent("Event")).initEvent(t,!0,!0):c.createEventObject&&(e=c.createEventObject());return e}();e.dispatchEvent?e.dispatchEvent(o):e.fireEvent("on"+t,o)}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./eventmap":7,"custom-event":8}],7:[function(e,r,t){(function(e){"use strict";var t=[],n="",o=/^on/;for(n in e)o.test(n)&&t.push(n.slice(2));r.exports=t}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],8:[function(e,n,t){(function(e){var t=e.CustomEvent;n.exports=function(){try{var e=new t("cat",{detail:{foo:"bar"}});return"cat"===e.type&&"bar"===e.detail.foo}catch(e){}}()?t:"undefined"!=typeof document&&"function"==typeof document.createEvent?function(e,t){var n=document.createEvent("CustomEvent");return t?n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail):n.initCustomEvent(e,!1,!1,void 0),n}:function(e,t){var n=document.createEventObject();return n.type=e,t?(n.bubbles=Boolean(t.bubbles),n.cancelable=Boolean(t.cancelable),n.detail=t.detail):(n.bubbles=!1,n.cancelable=!1,n.detail=void 0),n}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],9:[function(e,t,n){var o,r,t=t.exports={};function i(){throw new Error("setTimeout has not been defined")}function u(){throw new Error("clearTimeout has not been defined")}function c(t){if(o===setTimeout)return setTimeout(t,0);if((o===i||!o)&&setTimeout)return o=setTimeout,setTimeout(t,0);try{return o(t,0)}catch(e){try{return o.call(null,t,0)}catch(e){return o.call(this,t,0)}}}!function(){try{o="function"==typeof setTimeout?setTimeout:i}catch(e){o=i}try{r="function"==typeof clearTimeout?clearTimeout:u}catch(e){r=u}}();var a,l=[],f=!1,s=-1;function d(){f&&a&&(f=!1,a.length?l=a.concat(l):s=-1,l.length&&m())}function m(){if(!f){var e=c(d);f=!0;for(var t=l.length;t;){for(a=l,l=[];++s<t;)a&&a[s].run();s=-1,t=l.length}a=null,f=!1,function(t){if(r===clearTimeout)return clearTimeout(t);if((r===u||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(t);try{r(t)}catch(e){try{return r.call(null,t)}catch(e){return r.call(this,t)}}}(e)}}function v(e,t){this.fun=e,this.array=t}function p(){}t.nextTick=function(e){var t=new Array(arguments.length-1);if(1<arguments.length)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];l.push(new v(e,t)),1!==l.length||f||c(m)},v.prototype.run=function(){this.fun.apply(null,this.array)},t.title="browser",t.browser=!0,t.env={},t.argv=[],t.version="",t.versions={},t.on=p,t.addListener=p,t.once=p,t.off=p,t.removeListener=p,t.removeAllListeners=p,t.emit=p,t.prependListener=p,t.prependOnceListener=p,t.listeners=function(e){return[]},t.binding=function(e){throw new Error("process.binding is not supported")},t.cwd=function(){return"/"},t.chdir=function(e){throw new Error("process.chdir is not supported")},t.umask=function(){return 0}},{}],10:[function(e,n,t){(function(t){var e="function"==typeof t?function(e){t(e)}:function(e){setTimeout(e,0)};n.exports=e}).call(this,e("timers").setImmediate)},{timers:11}],11:[function(a,e,l){(function(e,t){var o=a("process/browser.js").nextTick,n=Function.prototype.apply,r=Array.prototype.slice,i={},u=0;function c(e,t){this._id=e,this._clearFn=t}l.setTimeout=function(){return new c(n.call(setTimeout,window,arguments),clearTimeout)},l.setInterval=function(){return new c(n.call(setInterval,window,arguments),clearInterval)},l.clearTimeout=l.clearInterval=function(e){e.close()},c.prototype.unref=c.prototype.ref=function(){},c.prototype.close=function(){this._clearFn.call(window,this._id)},l.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},l.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},l._unrefActive=l.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;0<=t&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},l.setImmediate="function"==typeof e?e:function(e){var t=u++,n=!(arguments.length<2)&&r.call(arguments,1);return i[t]=!0,o(function(){i[t]&&(n?e.apply(null,n):e.call(null),l.clearImmediate(t))}),t},l.clearImmediate="function"==typeof t?t:function(e){delete i[e]}}).call(this,a("timers").setImmediate,a("timers").clearImmediate)},{"process/browser.js":9,timers:11}]},{},[2])(2)});
\ No newline at end of file
......@@ -23,26 +23,31 @@
const callback_success = function(response) {
let table_html = '';
let unresolved_constraint_violations = 0;
if(response.length > 0) {
// Update violation count badge
$('#violationCountBadge').html(response.length).removeClass('bg-success').addClass('bg-warning');
// Update violations table
for(let i=0;i<response.length;i++) {
if(response[i].manually_resolved)
if(response[i].manually_resolved) {
table_html += '<tr class="text-muted"><td class="nowrap">{% fa6_icon "check" "fas" %}</td>';
else
}
else {
table_html += '<tr><td></td>';
unresolved_constraint_violations++;
}
table_html += "<td>" + response[i].level_display + "</td><td>" + response[i].type_display + "</td><td>" + response[i].details + "</td><td class='nowrap'>" + response[i].timestamp_display + "</td><td><a href='" + response[i].edit_url + "'><i class='btn btn-primary fa fa-pen'></i></a></td></tr>";
}
}
else {
// Update violation count badge
$('#violationCountBadge').html(0).removeClass('bg-warning').addClass('bg-success');
// Update violations table
table_html ='<tr class="text-muted"><td colspan="5" class="text-center">{% trans "No violations" %}</td></tr>'
}
// Update violation count badge
if(unresolved_constraint_violations > 0)
$('#violationCountBadge').html(unresolved_constraint_violations).removeClass('bg-success').addClass('bg-warning');
else
$('#violationCountBadge').html(0).removeClass('bg-warning').addClass('bg-success');
// Show violation list (potentially empty) in violations table
$('#violationsTableBody').html(table_html);
......
......@@ -15,6 +15,7 @@
<script src="{% static "common/vendor/sortable/Sortable.min.js" %}"></script>
<script src="{% static "common/vendor/sortable/jquery-sortable.js" %}"></script>
<script src="{% static "AKScheduling/vendor/dragula/dragula.js" %}"></script>
<style>
.ak-list {
......@@ -30,8 +31,18 @@
.track-delete {
cursor: pointer;
}
.card-header {
cursor: move;
}
.card {
padding:0!important;
}
</style>
<link rel="stylesheet" href="{% static "AKScheduling/vendor/dragula/dragula.css" %}">
<script>
document.addEventListener('DOMContentLoaded', function () {
// CSRF Protection/Authentication
......@@ -188,6 +199,13 @@
});
}
});
// Make track containers sortable (when dragging the headers)
dragula([$('#workspace')[0]], {
moves: function (el, container, handle) {
return handle.classList.contains('card-header');
}
});
});
</script>
{% endblock extrahead %}
......@@ -206,7 +224,7 @@
<ul data-id="None" data-sync="false" class="ak-list">
{% for ak in aks_without_track %}
<li data-ak-id="{{ ak.pk }}" data-bs-toggle="tooltip" data-placement="top" title="">
{{ ak.name }} ({{ ak.category }})
{{ ak.name }} <span style="color:{{ ak.category.color }}">({{ ak.category }})</span>
</li>
{% endfor %}
</ul>
......@@ -225,7 +243,7 @@
<ul data-track-id="{{ track.pk }}" data-name="{{ track }}" data-sync="true" class="ak-list">
{% for ak in track.aks_with_category %}
<li data-ak-id="{{ ak.pk }}" data-bs-toggle="tooltip" data-placement="top" title="">
{{ ak.name }} ({{ ak.category }})
{{ ak.name }} <span style="color:{{ ak.category.color }}">({{ ak.category }})</span>
</li>
{% endfor %}
</ul>
......
......@@ -157,6 +157,7 @@
$('#id_start').val(info.startStr);
$('#id_end').val(info.endStr);
$('#id_room').val(info.resource._resource.id);
$('#id_room_name').val(info.resource._resource.title);
$('#id_duration').val(Math.abs(info.end-info.start)/1000/60/60);
$('#id_ak').val("");
$('#newAKSlotModal').modal('show');
......@@ -215,20 +216,24 @@
if(response.length > 0) {
// Update violations table
for(let i=0;i<response.length;i++) {
if(response[i].manually_resolved)
table_html += '<tr class="text-muted"><td class="nowrap">{% fa6_icon "check" "fas" %} ';
let icon_html = '';
let muted_html = '';
if(response[i].manually_resolved) {
icon_html = '{% fa6_icon "check" "fas" %} ';
muted_html = 'text-muted';
}
else {
table_html += '<tr><td>';
unresolved_violations_count++;
}
if(response[i].level_display==='{% trans "Violation" %}')
table_html += '{% fa6_icon "exclamation-triangle" "fas" %}';
icon_html += '{% fa6_icon "exclamation-triangle" "fas" %}';
else
table_html += '{% fa6_icon "info-circle" "fas" %}';
icon_html += '{% fa6_icon "info-circle" "fas" %}';
table_html += '<tr class="'+ muted_html+ '"><td class="nowrap">' + icon_html;
table_html += "</td><td class='small'>" + response[i].type_display + "</td></tr>";
table_html += "<tr><td colspan='2' class='small'>" + response[i].details + "</td></tr>"
table_html += "<tr class='" + muted_html + "'><td colspan='2' class='small'>" + response[i].details + "</td></tr>"
}
}
else {
......@@ -238,7 +243,7 @@
// Update violation count badge
if(unresolved_violations_count > 0)
$('#violationCountBadge').html(response.length).removeClass('bg-success').addClass('bg-warning');
$('#violationCountBadge').html(unresolved_violations_count).removeClass('bg-success').addClass('bg-warning');
else
$('#violationCountBadge').html(0).removeClass('bg-warning').addClass('bg-success');
......@@ -350,15 +355,17 @@
<h5 class="mt-2">{{ track_slots.grouper }}</h5>
{% endif %}
{% for slot in track_slots.list %}
<div class="unscheduled-slot badge bg-primary" style='background-color: {{ slot.ak.category.color }}'
data-event='{ "title": "{{ slot.ak.short_name }}", "duration": {"hours": "{{ slot.duration|unlocalize }}"}, "constraint": "roomAvailable", "description": "{{ slot.ak.details | escapejs }}", "slotID": "{{ slot.pk }}", "backgroundColor": "{{ slot.ak.category.color }}", "url": "{% url "admin:AKModel_akslot_change" slot.pk %}"}' data-details="{{ slot.ak.details }}">{{ slot.ak.short_name }}
<div class="unscheduled-slot badge" style='background-color: {% with slot.ak.category.color as color %} {% if color %}{{ color }}{% else %}#000000;{% endif %}{% endwith %}'
{% with slot.ak.details as details %}
data-event='{ "title": "{{ slot.ak.short_name }}", "duration": {"hours": "{{ slot.duration|unlocalize }}"}, "constraint": "roomAvailable", "description": "{{ details | escapejs }}", "slotID": "{{ slot.pk }}", "backgroundColor": "{{ slot.ak.category.color }}", "url": "{% url "admin:AKModel_akslot_change" slot.pk %}"}' data-details="{{ details }}">{{ slot.ak.short_name }}
({{ slot.duration }} h)<br>{{ slot.ak.owners_list }}
{% endwith %}
</div>
{% endfor %}
{% endfor %}
</div>
<div class="tab-pane fade" id="violations">
<table class="table table-striped mt-4 mb-4">
<table class="table mt-4 mb-4">
<thead>
<tr>
<th>{% trans "Level" %}</th>
......
......@@ -13,14 +13,19 @@
{% block content %}
<h4 class="mt-4 mb-4">{% trans "AKs with public notes" %}</h4>
{% for ak in aks_with_comment %}
<a href="{{ ak.edit_url }}">{{ ak }}</a><br>{{ ak.notes }}<br><br>
<a href="{{ ak.detail_url }}">{{ ak }}</a>
<a href="{{ ak.edit_url }}">{% fa6_icon "pen-to-square" %}</a>
<a class="link-warning" href="{% url "admin:AKModel_ak_change" object_id=ak.pk %}">{% fa6_icon "pen-to-square" %}</a><br>
{{ ak.notes }}<br><br>
{% empty %}
-
{% endfor %}
<h4 class="mt-4 mb-4">{% trans "AKs without availabilities" %}</h4>
{% for ak in aks_without_availabilities %}
<a href="{{ ak.edit_url }}">{{ ak }}</a><br>
<a href="{{ ak.detail_url }}">{{ ak }}</a>
<a href="{{ ak.edit_url }}">{% fa6_icon "pen-to-square" %}</a>
<a class="link-warning" href="{% url "admin:AKModel_ak_change" object_id=ak.pk %}">{% fa6_icon "pen-to-square" %}</a><br>
{% empty %}
-<br>
{% endfor %}
......@@ -30,7 +35,10 @@
<h4 class="mt-4 mb-4">{% trans "AK wishes with slots" %}</h4>
{% for ak in ak_wishes_with_slots %}
<a href="{{ ak.detail_url }}">{{ ak }}</a> <a href="{% url "admin:AKModel_akslot_changelist" %}?ak={{ ak.pk }}">({{ ak.akslot__count }})</a><br>
<a href="{% url "admin:AKModel_akslot_changelist" %}?ak={{ ak.pk }}">({{ ak.akslot__count }})</a>
<a href="{{ ak.detail_url }}">{{ ak }}</a>
<a href="{{ ak.edit_url }}">{% fa6_icon "pen-to-square" %}</a>
<a class="link-warning" href="{% url "admin:AKModel_ak_change" object_id=ak.pk %}">{% fa6_icon "pen-to-square" %}</a><br>
{% empty %}
-<br>
{% endfor %}
......@@ -39,7 +47,9 @@
<h4 class="mt-4 mb-4">{% trans "AKs without slots" %}</h4>
{% for ak in aks_without_slots %}
<a href="{{ ak.detail_url }}">{{ ak }}</a><br>
<a href="{{ ak.detail_url }}">{{ ak }}</a>
<a href="{{ ak.edit_url }}">{% fa6_icon "pen-to-square" %}</a>
<a class="link-warning" href="{% url "admin:AKModel_ak_change" object_id=ak.pk %}">{% fa6_icon "pen-to-square" %}</a><br>
{% empty %}
-<br>
{% endfor %}
......
{% load i18n %}
<div class="text-center">
<a href="{% url 'admin:constraint-violations' slug=event.slug %}">
<h1>{{ constraint_violations_count }}</h1>
{% blocktrans count constraint_violations_count=constraint_violations_count %}
<h3>Constraint Violation</h3>
{% plural %}
<h3>Constraint Violations</h3>
{% endblocktrans %}
</a>
</div>
......@@ -5,6 +5,8 @@ from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import ListView, DetailView, UpdateView
from AKModel.metaviews import status_manager
from AKModel.metaviews.status import TemplateStatusWidget
from AKModel.models import AKSlot, AKTrack, Event, AK, AKCategory
from AKModel.metaviews.admin import EventSlugMixin, FilterByEventSlugMixin, AdminViewMixin, IntermediateAdminView
from AKScheduling.forms import AKInterestForm, AKAddSlotForm
......@@ -39,7 +41,9 @@ class SchedulingAdminView(AdminViewMixin, FilterByEventSlugMixin, ListView):
context_object_name = "slots_unscheduled"
def get_queryset(self):
return super().get_queryset().filter(start__isnull=True).select_related('event', 'ak').order_by('ak__track')
return super().get_queryset().filter(start__isnull=True).select_related('event', 'ak', 'ak__track',
'ak__category').prefetch_related('ak__types', 'ak__owners', 'ak__conflicts', 'ak__prerequisites',
'ak__requirements', 'ak__conflict').order_by('ak__track', 'ak')
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs)
......@@ -150,6 +154,13 @@ class InterestEnteringAdminView(SuccessMessageMixin, AdminViewMixin, EventSlugMi
def get_success_url(self):
return self.request.path
def form_valid(self, form):
# Don't create a history entry for this change
form.instance.skip_history_when_saving = True
r = super().form_valid(form)
del form.instance.skip_history_when_saving
return r
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["title"] = f"{_('Enter interest')}"
......@@ -277,3 +288,22 @@ class AvailabilityAutocreateView(EventSlugMixin, IntermediateAdminView):
_("Created default availabilities for {count} AKs").format(count=success_count)
)
return super().form_valid(form)
@status_manager.register(name="scheduling_constraint_violations")
class CVWidget(TemplateStatusWidget):
"""
Status page widget: Constraint violations
"""
required_context_type = "event"
title = _("Constraint Violations")
template_name = "admin/AKScheduling/status/cvs.html"
def render_status(self, context: {}) -> str:
return "success" if context["constraint_violations_count"] == 0 else "warning"
def get_context_data(self, context) -> dict:
context = super().get_context_data(context)
context["constraint_violations_count"] = (context["event"].constraintviolation_set
.filter(manually_resolved=False).count())
return context
from datetime import datetime
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.utils.datetime_safe import datetime
from AKModel.models import AK
......@@ -17,8 +18,8 @@ def ak_interest_indication_active(event, current_timestamp):
:return: True if indication is allowed, False if not
:rtype: Bool
"""
return event.active and (event.interest_start is None or (event.interest_start <= current_timestamp and (
event.interest_end is None or current_timestamp <= event.interest_end)))
return (event.active and event.interest_start is not None and event.interest_end is not None
and event.interest_start <= current_timestamp <= event.interest_end)
@api_view(['POST'])
......@@ -26,7 +27,7 @@ def increment_interest_counter(request, event_slug, pk, **kwargs):
"""
Increment interest counter for AK
This view either returns a HTTP 200 if the counter was incremented,
This view either returns an HTTP 200 if the counter was incremented,
an HTTP 403 if indicating interest is currently not allowed,
or an HTTP 404 if there is no matching AK for the given primary key and event slug.
"""
......
......@@ -11,7 +11,7 @@ from django.utils.translation import gettext_lazy as _
from AKModel.availability.forms import AvailabilitiesFormMixin
from AKModel.availability.models import Availability
from AKModel.models import AK, AKOwner, AKCategory, AKRequirement, AKSlot, AKOrgaMessage
from AKModel.models import AK, AKOwner, AKCategory, AKRequirement, AKSlot, AKOrgaMessage, AKType
class AKForm(AvailabilitiesFormMixin, forms.ModelForm):
......@@ -33,11 +33,11 @@ class AKForm(AvailabilitiesFormMixin, forms.ModelForm):
model = AK
fields = ['name',
'short_name',
'link',
'protocol_link',
'owners',
'description',
'category',
'types',
'reso',
'present',
'requirements',
......@@ -49,6 +49,7 @@ class AKForm(AvailabilitiesFormMixin, forms.ModelForm):
widgets = {
'requirements': forms.CheckboxSelectMultiple,
'types': forms.CheckboxSelectMultiple,
'event': forms.HiddenInput,
}
......@@ -62,7 +63,14 @@ class AKForm(AvailabilitiesFormMixin, forms.ModelForm):
self.fields["prerequisites"].widget.attrs = {'class': 'chosen-select'}
self.fields['category'].queryset = AKCategory.objects.filter(event=self.initial.get('event'))
self.fields['types'].queryset = AKType.objects.filter(event=self.initial.get('event'))
# Don't ask for types if there are no types configured for this event
if self.fields['types'].queryset.count() == 0:
self.fields.pop('types')
self.fields['requirements'].queryset = AKRequirement.objects.filter(event=self.initial.get('event'))
# Don't ask for requirements if there are no requirements configured for this event
if self.fields['requirements'].queryset.count() == 0:
self.fields.pop('requirements')
self.fields['prerequisites'].queryset = AK.objects.filter(event=self.initial.get('event')).exclude(
pk=self.instance.pk)
self.fields['conflicts'].queryset = AK.objects.filter(event=self.initial.get('event')).exclude(
......@@ -87,7 +95,7 @@ class AKForm(AvailabilitiesFormMixin, forms.ModelForm):
duration = float(duration.replace(",", "."))
try:
float(duration)
duration = float(duration)
except ValueError as exc:
raise ValidationError(
_('"%(duration)s" is not a valid duration'),
......@@ -101,7 +109,7 @@ class AKForm(AvailabilitiesFormMixin, forms.ModelForm):
"""
Normalize/clean inputs
Generate a (not yet used) short name if field was left blank, generate a wiki link,
Generate a (not yet used) short name if field was left blank,
create a list of normalized slot durations
:return: cleaned inputs
......@@ -128,12 +136,6 @@ class AKForm(AvailabilitiesFormMixin, forms.ModelForm):
short_name = f'{short_name[:-(digits + 1)]}-{i}'
cleaned_data["short_name"] = short_name
# Generate wiki link
if self.cleaned_data["event"].base_url:
link = self.cleaned_data["event"].base_url + self.cleaned_data["name"].replace(" ", "_")
# Truncate links longer than 200 characters (default length of URL fields in django)
self.cleaned_data["link"] = link[:200]
# Get durations from raw durations field
if "durations" in cleaned_data:
cleaned_data["durations"] = [self._clean_duration(d) for d in self.cleaned_data["durations"].split()]
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-16 16:30+0200\n"
"POT-Creation-Date: 2025-02-25 22:33+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -17,16 +17,16 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: AKSubmission/forms.py:93
#: AKSubmission/forms.py:101
#, python-format
msgid "\"%(duration)s\" is not a valid duration"
msgstr "\"%(duration)s\" ist keine gültige Dauer"
#: AKSubmission/forms.py:159
#: AKSubmission/forms.py:161
msgid "Duration(s)"
msgstr "Dauer(n)"
#: AKSubmission/forms.py:161
#: AKSubmission/forms.py:163
msgid ""
"Enter at least one planned duration (in hours). If your AK should have "
"multiple slots, use multiple lines"
......@@ -52,172 +52,168 @@ msgstr ""
msgid "AK Submission"
msgstr "AK-Eintragung"
#: AKSubmission/templates/AKSubmission/ak_detail.html:77
#: AKSubmission/templates/AKSubmission/ak_detail.html:126
#: AKSubmission/templates/AKSubmission/ak_interest_script.html:50
msgid "Interest indication currently not allowed. Sorry."
msgstr "Interessenangabe aktuell nicht erlaubt. Sorry."
#: AKSubmission/templates/AKSubmission/ak_detail.html:79
#: AKSubmission/templates/AKSubmission/ak_detail.html:128
#: AKSubmission/templates/AKSubmission/ak_interest_script.html:52
msgid "Could not save your interest. Sorry."
msgstr "Interesse konnte nicht gespeichert werden. Sorry."
#: AKSubmission/templates/AKSubmission/ak_detail.html:100
#: AKSubmission/templates/AKSubmission/ak_detail.html:149
msgid "Interest"
msgstr "Interesse"
#: AKSubmission/templates/AKSubmission/ak_detail.html:102
#: AKSubmission/templates/AKSubmission/ak_table.html:55
#: AKSubmission/templates/AKSubmission/ak_detail.html:151
#: AKSubmission/templates/AKSubmission/ak_table.html:65
msgid "Show Interest"
msgstr "Interesse bekunden"
#: AKSubmission/templates/AKSubmission/ak_detail.html:108
#: AKSubmission/templates/AKSubmission/ak_table.html:46
#: AKSubmission/templates/AKSubmission/ak_detail.html:157
#: AKSubmission/templates/AKSubmission/ak_table.html:56
msgid "Open external link"
msgstr "Externen Link öffnen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:113
#: AKSubmission/templates/AKSubmission/ak_detail.html:162
msgid "Open protocol link"
msgstr "Protokolllink öffnen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:118
#: AKSubmission/templates/AKSubmission/ak_detail.html:167
#: AKSubmission/templates/AKSubmission/ak_history.html:19
#: AKSubmission/templates/AKSubmission/ak_history.html:31
msgid "History"
msgstr "Versionsgeschichte"
#: AKSubmission/templates/AKSubmission/ak_detail.html:121
#: AKSubmission/templates/AKSubmission/ak_detail.html:170
#: AKSubmission/templates/AKSubmission/akmessage_add.html:8
#: AKSubmission/templates/AKSubmission/akmessage_add.html:16
#: AKSubmission/templates/AKSubmission/akmessage_add.html:22
msgid "Add confidential message to organizers"
msgstr "Sende eine private Nachricht an das Organisationsteam"
#: AKSubmission/templates/AKSubmission/ak_detail.html:124
#: AKSubmission/templates/AKSubmission/ak_detail.html:269
#: AKSubmission/templates/AKSubmission/ak_detail.html:173
#: AKSubmission/templates/AKSubmission/ak_detail.html:326
#: AKSubmission/templates/AKSubmission/ak_edit.html:16
#: AKSubmission/templates/AKSubmission/ak_table.html:51
#: AKSubmission/templates/AKSubmission/ak_table.html:61
msgid "Edit"
msgstr "Bearbeiten"
#: AKSubmission/templates/AKSubmission/ak_detail.html:129
#: AKSubmission/templates/AKSubmission/ak_detail.html:178
#: AKSubmission/templates/AKSubmission/ak_history.html:31
#: AKSubmission/templates/AKSubmission/ak_table.html:34
#: AKSubmission/templates/AKSubmission/ak_table.html:37
msgid "AK Wish"
msgstr "AK-Wunsch"
#: AKSubmission/templates/AKSubmission/ak_detail.html:136
#: AKSubmission/templates/AKSubmission/ak_detail.html:186
#, python-format
msgid ""
"\n"
" This AK currently takes place for another "
"%(featured_slot_remaining)s minute(s) in %(room)s.\n"
" &nbsp;\n"
" "
"This AK currently takes place for another <span v-html=\"timeUntilEnd\">"
"%(featured_slot_remaining)s</span> minute(s) in %(room)s.&nbsp;"
msgstr ""
"\n"
" Dieser AK findet noch %(featured_slot_remaining)s "
"Minute(n) in %(room)s statt.&nbsp;\n"
"Dieser AK findet noch <span v-html=\"timeUntilEnd\">"
"%(featured_slot_remaining)s</span> Minute(n) in %(room)s statt.&nbsp;\n"
" "
#: AKSubmission/templates/AKSubmission/ak_detail.html:142
#: AKSubmission/templates/AKSubmission/ak_detail.html:189
#, python-format
msgid ""
"\n"
" This AK starts in %(featured_slot_remaining)s "
"minute(s) in %(room)s.&nbsp;\n"
" "
"This AK starts in <span v-html=\"timeUntilStart\">"
"%(featured_slot_remaining)s</span> minute(s) in %(room)s.&nbsp;"
msgstr ""
"\n"
" This AK beginnt in %(featured_slot_remaining)s "
"Minute(n) in %(room)s.&nbsp;\n"
"Dieser AK beginnt in <span v-html=\"timeUntilStart\">"
"%(featured_slot_remaining)s</span> Minute(n) in %(room)s.&nbsp;\n"
" "
#: AKSubmission/templates/AKSubmission/ak_detail.html:149
#: AKSubmission/templates/AKSubmission/ak_detail.html:277
#: AKSubmission/templates/AKSubmission/ak_detail.html:194
#: AKSubmission/templates/AKSubmission/ak_detail.html:334
msgid "Go to virtual room"
msgstr "Zum virtuellen Raum"
#: AKSubmission/templates/AKSubmission/ak_detail.html:158
#: AKSubmission/templates/AKSubmission/ak_detail.html:205
#: AKSubmission/templates/AKSubmission/ak_table.html:10
msgid "Who?"
msgstr "Wer?"
#: AKSubmission/templates/AKSubmission/ak_detail.html:164
#: AKSubmission/templates/AKSubmission/ak_detail.html:211
#: AKSubmission/templates/AKSubmission/ak_history.html:36
#: AKSubmission/templates/AKSubmission/ak_table.html:11
msgid "Category"
msgstr "Kategorie"
#: AKSubmission/templates/AKSubmission/ak_detail.html:171
#: AKSubmission/templates/AKSubmission/ak_detail.html:218
#: AKSubmission/templates/AKSubmission/ak_table.html:13
msgid "Types"
msgstr "Typen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:228
#: AKSubmission/templates/AKSubmission/ak_history.html:37
msgid "Track"
msgstr "Track"
#: AKSubmission/templates/AKSubmission/ak_detail.html:177
#, fuzzy
#| msgid "Present results of this AK"
#: AKSubmission/templates/AKSubmission/ak_detail.html:234
msgid "Present this AK"
msgstr "Die Ergebnisse dieses AKs vorstellen"
msgstr "Diesen AK vorstellen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:182
#: AKSubmission/templates/AKSubmission/ak_detail.html:239
msgid "(Category Default)"
msgstr "(Kategorievoreinstellung)"
#: AKSubmission/templates/AKSubmission/ak_detail.html:188
#: AKSubmission/templates/AKSubmission/ak_detail.html:245
msgid "Reso intention?"
msgstr "Resoabsicht?"
#: AKSubmission/templates/AKSubmission/ak_detail.html:195
#: AKSubmission/templates/AKSubmission/ak_detail.html:252
msgid "Requirements"
msgstr "Anforderungen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:208
#: AKSubmission/templates/AKSubmission/ak_detail.html:265
msgid "Conflicting AKs"
msgstr "AK-Konflikte"
#: AKSubmission/templates/AKSubmission/ak_detail.html:216
#: AKSubmission/templates/AKSubmission/ak_detail.html:273
msgid "Prerequisite AKs"
msgstr "Vorausgesetzte AKs"
#: AKSubmission/templates/AKSubmission/ak_detail.html:224
#: AKSubmission/templates/AKSubmission/ak_detail.html:281
msgid "Notes"
msgstr "Notizen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:237
#: AKSubmission/templates/AKSubmission/ak_detail.html:294
msgid "When?"
msgstr "Wann?"
#: AKSubmission/templates/AKSubmission/ak_detail.html:239
#: AKSubmission/templates/AKSubmission/ak_detail.html:296
#: AKSubmission/templates/AKSubmission/akslot_delete.html:35
msgid "Duration"
msgstr "Dauer"
#: AKSubmission/templates/AKSubmission/ak_detail.html:241
#: AKSubmission/templates/AKSubmission/ak_detail.html:298
msgid "Room"
msgstr "Raum"
#: AKSubmission/templates/AKSubmission/ak_detail.html:272
#: AKSubmission/templates/AKSubmission/ak_detail.html:329
msgid "Delete"
msgstr "Löschen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:283
#: AKSubmission/templates/AKSubmission/ak_detail.html:340
msgid "Schedule"
msgstr "Schedule"
#: AKSubmission/templates/AKSubmission/ak_detail.html:295
#: AKSubmission/templates/AKSubmission/ak_detail.html:352
msgid "Add another slot"
msgstr "Einen neuen AK-Slot hinzufügen"
#: AKSubmission/templates/AKSubmission/ak_detail.html:305
#: AKSubmission/templates/AKSubmission/ak_detail.html:362
msgid "Possible Times"
msgstr "Mögliche Zeiten"
#: AKSubmission/templates/AKSubmission/ak_detail.html:309
#: AKSubmission/templates/AKSubmission/ak_detail.html:366
msgid "Start"
msgstr "Start"
#: AKSubmission/templates/AKSubmission/ak_detail.html:310
#: AKSubmission/templates/AKSubmission/ak_detail.html:367
msgid "End"
msgstr "Ende"
......@@ -269,12 +265,12 @@ msgid "Time"
msgstr "Zeit"
#: AKSubmission/templates/AKSubmission/ak_history.html:48
#: AKSubmission/templates/AKSubmission/ak_table.html:25
#: AKSubmission/templates/AKSubmission/ak_table.html:28
msgid "Present results of this AK"
msgstr "Die Ergebnisse dieses AKs vorstellen"
#: AKSubmission/templates/AKSubmission/ak_history.html:52
#: AKSubmission/templates/AKSubmission/ak_table.html:29
#: AKSubmission/templates/AKSubmission/ak_table.html:32
msgid "Intends to submit a resolution"
msgstr "Beabsichtigt eine Resolution einzureichen"
......@@ -294,11 +290,11 @@ msgstr "AK-Liste"
msgid "Add AK"
msgstr "AK hinzufügen"
#: AKSubmission/templates/AKSubmission/ak_table.html:42
#: AKSubmission/templates/AKSubmission/ak_table.html:52
msgid "Details"
msgstr "Details"
#: AKSubmission/templates/AKSubmission/ak_table.html:66
#: AKSubmission/templates/AKSubmission/ak_table.html:76
msgid "There are no AKs in this category yet"
msgstr "Es gibt noch keine AKs in dieser Kategorie"
......@@ -414,64 +410,64 @@ msgstr ""
"AKs die sich gewünscht wurden, aber bei denen noch nicht klar ist, wer sie "
"macht. Falls du dir das vorstellen kannst, trag dich einfach ein"
#: AKSubmission/views.py:167
#: AKSubmission/views.py:169
msgid "Currently planned AKs"
msgstr "Aktuell geplante AKs"
#: AKSubmission/views.py:300
#: AKSubmission/views.py:302
msgid "Event inactive. Cannot create or update."
msgstr "Event inaktiv. Hinzufügen/Bearbeiten nicht möglich."
#: AKSubmission/views.py:325
#: AKSubmission/views.py:327
msgid "AK successfully created"
msgstr "AK erfolgreich angelegt"
#: AKSubmission/views.py:398
#: AKSubmission/views.py:400
msgid "AK successfully updated"
msgstr "AK erfolgreich aktualisiert"
#: AKSubmission/views.py:449
#: AKSubmission/views.py:451
#, python-brace-format
msgid "Added '{owner}' as new owner of '{ak.name}'"
msgstr "'{owner}' als neue Leitung von '{ak.name}' hinzugefügt"
#: AKSubmission/views.py:553
#: AKSubmission/views.py:555
msgid "No user selected"
msgstr "Keine Person ausgewählt"
#: AKSubmission/views.py:569
#: AKSubmission/views.py:571
msgid "Person Info successfully updated"
msgstr "Personen-Info erfolgreich aktualisiert"
#: AKSubmission/views.py:605
#: AKSubmission/views.py:607
msgid "AK Slot successfully added"
msgstr "AK-Slot erfolgreich angelegt"
#: AKSubmission/views.py:624
#: AKSubmission/views.py:626
msgid "You cannot edit a slot that has already been scheduled"
msgstr "Bereits geplante AK-Slots können nicht mehr bearbeitet werden"
#: AKSubmission/views.py:634
#: AKSubmission/views.py:636
msgid "AK Slot successfully updated"
msgstr "AK-Slot erfolgreich aktualisiert"
#: AKSubmission/views.py:652
#: AKSubmission/views.py:654
msgid "You cannot delete a slot that has already been scheduled"
msgstr "Bereits geplante AK-Slots können nicht mehr gelöscht werden"
#: AKSubmission/views.py:662
#: AKSubmission/views.py:664
msgid "AK Slot successfully deleted"
msgstr "AK-Slot erfolgreich angelegt"
#: AKSubmission/views.py:674
#: AKSubmission/views.py:676
msgid "Messages"
msgstr "Nachrichten"
#: AKSubmission/views.py:684
#: AKSubmission/views.py:686
msgid "Delete all messages"
msgstr "Alle Nachrichten löschen"
#: AKSubmission/views.py:711
#: AKSubmission/views.py:713
msgid "Message to organizers successfully saved"
msgstr "Nachricht an die Organisator*innen erfolgreich gespeichert"
......
......@@ -9,6 +9,9 @@
<th>{% trans "Name" %}</th>
<th>{% trans "Who?" %}</th>
<th>{% trans 'Category' %}</th>
{% if show_types %}
<th>{% trans 'Types' %}</th>
{% endif %}
<th></th>
</tr>
</thead>
......@@ -37,6 +40,13 @@
{% endif %}
</td>
<td>{% category_linked_badge ak.category event.slug %}</td>
{% if show_types %}
<td>
{% for aktype in ak.types.all %}
<span class="badge bg-info">{{ aktype }}</span>
{% endfor %}
</td>
{% endif %}
<td class="text-end" style="white-space: nowrap;">
<a href="{{ ak.detail_url }}" data-bs-toggle="tooltip"
title="{% trans 'Details' %}"
......
This diff is collapsed.
This diff is collapsed.
......@@ -10,7 +10,7 @@ setup.
### System Requirements
* Python 3.8+ incl. development tools
* Python3.11+ incl. development tools
* Virtualenv
* pdflatex & beamer
class (`texlive-latex-base texlive-latex-recommended texlive-latex-extra texlive-fonts-extra texlive-luatex`)
......
......@@ -8,14 +8,21 @@ if [ -z ${VIRTUAL_ENV+x} ]; then
fi
# enable really all warnings, some of them are silenced by default
if [[ "$@" == *"--all"* ]]; then
export PYTHONWARNINGS=all
fi
for arg in "$@"; do
if [[ "$arg" == "--all" ]]; then
export PYTHONWARNINGS=all
fi
done
# in case of checking production setup
if [[ "$@" == *"--prod"* ]]; then
export DJANGO_SETTINGS_MODULE=AKPlanning.settings_production
./manage.py check --deploy
fi
for arg in "$@"; do
if [[ "$arg" == "--prod" ]]; then
export DJANGO_SETTINGS_MODULE=AKPlanning.settings_production
./manage.py check --deploy
./manage.py makemigrations --dry-run --check
fi
done
# check the setup
./manage.py check
./manage.py makemigrations --dry-run --check
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.