path('terms/editor/', views.EditorTerms.as_view()),
+ path('chooser/thema/', views.ThemaChooser.as_view()),
+ path('chooser/thema-main/', views.MainThemaChooser.as_view()),
+
path('wikidata/<slug:model>/<qid>', views.WikidataView.as_view()),
path('publish/author/<int:pk>/', views.publish_author, name='catalogue_publish_author'),
'original_year',
'pd_year',
]
-
+
class TermSearchFilter(SearchFilter):
search_param = 'term'
def get_label(self, obj):
return f'{obj.last_name}, {obj.first_name}'
-
+
class BookTitleTerms(Terms):
queryset = models.Book.objects.all()
search_fields = ['title', 'slug']
class WLURITerms(Terms):
queryset = models.Book.objects.all()
search_fields = ['title', 'slug']
-
+
class serializer_class(serializers.Serializer):
label = serializers.CharField(source='wluri')
queryset = models.Thema.objects.filter(usable=True, hidden=False, usable_as_main=True)
+
+class Chooser(APIView):
+ def get(self, request):
+ return Response([{
+ 'value': 'x',
+ 'name': 'name',
+ 'description': 'desc',
+ 'sub': [
+ {
+ 'value': 'y',
+ 'name': 'name y',
+ 'description': 'desc y',
+ }
+ ]
+ }])
+
+
+class ThemaChooser(Chooser):
+ queryset = models.Thema.objects.filter(usable=True, hidden=False)
+
+ def get(self, request):
+ tree = {}
+
+ def getitem(code):
+ if len(code) == 1:
+ parent = tree
+ else:
+ parent = getitem(code[:-1]).setdefault('sub', {})
+ return parent.setdefault(code, {})
+
+ def getmissing(t):
+ for k, v in t.items():
+ if 'name' not in v:
+ yield k
+ if 'sub' in v:
+ for c in getmissing(v['sub']):
+ yield c
+
+ def populate(thema):
+ item = getitem(thema.code)
+ item['usable'] = thema.usable
+ item['hidden'] = thema.hidden
+ item['name'] = thema.name
+ item['description'] = thema.description
+
+ def order(tree):
+ res = []
+ for k, v in tree.items():
+ v.update(value=k)
+ if 'sub' in v:
+ v['sub'] = order(v['sub'])
+ res.append(v)
+ while len(res) == 1 and 'name' not in res[0] and 'sub' in res[0]:
+ res = res[0]['sub']
+ return res
+
+ for thema in self.queryset.all():
+ populate(thema)
+
+ missing = list(getmissing(tree))
+ for thema in models.Thema.objects.filter(code__in=missing):
+ populate(thema)
+
+ tree = order(tree)
+
+ return Response(tree)
+
+
+class MainThemaChooser(ThemaChooser):
+ queryset = models.Thema.objects.filter(usable=True, hidden=False, usable_as_main=True)[:1000]
+
+
class WikidataView(APIView):
permission_classes = [IsAdminUser]
else:
d[fieldname] = localize_input(d[fieldname])
return Response(d)
-
+
def get(self, request, model, qid):
return self.get_object(model, qid, save=False)
'css/history.css',
'css/summary.css',
'css/imgareaselect-default.css',
- 'css/dialogs.css',
+ 'css/dialogs.scss',
'wiki/scss/splitter.scss',
'wiki/scss/visual.scss'
+++ /dev/null
-.dialog {
- display: none;
- padding: 5px;
- text-align: left;
- cursor: auto;
- background-color: #E1E1E1; /* #e0ffb8; */
-}
-
-.dialog .help_text {
- font-size: 11px;
- color: #2e3536;
-}
-
-.dialog .action_area {
- padding: 1em 0.5em 0.5em;
- border-top: 1px solid black;
- margin-top: 0.5em;
-}
-
-.dialog p {
- margin: 0.5em;
-}
-
-*[data-ui-error-for] {
- color: red;
- font-weight: bold;
-}
-
-#save_dialog textarea, #revert_dialog textarea {
- width: 90%;
- margin: 0.2em 4%;
-}
\ No newline at end of file
--- /dev/null
+.dialog {
+ display: none;
+ padding: 5px;
+ text-align: left;
+ cursor: auto;
+ background-color: #E1E1E1; /* #e0ffb8; */
+}
+
+.dialog .help_text {
+ font-size: 11px;
+ color: #2e3536;
+}
+
+.dialog .action_area {
+ padding: 1em 0.5em 0.5em;
+ border-top: 1px solid black;
+ margin-top: 0.5em;
+}
+
+.dialog p {
+ margin: 0.5em;
+}
+
+*[data-ui-error-for] {
+ color: red;
+ font-weight: bold;
+}
+
+#save_dialog textarea, #revert_dialog textarea {
+ width: 90%;
+ margin: 0.2em 4%;
+}
+
+
+
+#meta-chooser {
+ .form-check {
+ margin: 1em;
+ }
+ .meta-chooser_toggle {
+ position: absolute;
+ top: 1.5em;
+ left: 0;
+ cursor: pointer;
+ }
+ .name {
+ font-weight: bold;
+ }
+}
$('#media-chooser').modal('hide');
});
+ /* Meta chooser */
+ $('#meta-chooser').on('show.bs.modal', function (event) {
+ let input = $("input", $(event.relatedTarget).closest('.input-group'));
+ let $fg = $(event.relatedTarget).closest('.form-group');
+ let field = $fg.data('field');
+ let modal = $(this);
+ modal.data('target-input', input);
+ let body = modal.find('.modal-body');
+ body.html('');
+
+ let add_options = function(cnt, options, value) {
+ $.each(options, (i, item) => {
+ let elem = $('<div class="form-check"><label class="form-check-label"><input class="form-check-input" type="radio" name="metachoose"><div class="value"></div><div class="name"></div><div class="description"></div></label></div>');
+ if (!item.usable) {
+ $('input', elem).remove();
+ }
+ if (item.hidden) {
+ $('input', elem).prop('disabled', 'disabled');
+ }
+ $('input', elem).val(item.value);
+ $('input', elem).val(item.value);
+ $('.value', elem).text(item.value);
+ $('.name', elem).append(item.name);
+ $('.description', elem).append(item.description);
+ let valueMatch = value && value.startsWith(item.value);
+ if (valueMatch) {
+ $('label', elem).addClass('text-primary')
+ if (value == item.value) {
+ $('input', elem).prop('checked', true);
+ }
+ }
+ if (item.sub) {
+ let subT = $('<div class="meta-chooser_toggle">+</div>');
+ let sub = $('<div>');
+ elem.append(subT);
+ elem.append(sub);
+ subT.on('click', () => {
+ sub.toggle()
+ });
+ add_options(sub, item.sub, valueMatch ? value : null);
+ }
+ elem.appendTo(cnt);
+ });
+ };
+
+ $.ajax({
+ url: field.value_type.chooser.source,
+ success: function(data) {
+ add_options(body, data, input.val());
+ }
+ });
+ })
+ $('#meta-chooser .ctrl-ok').on('click', function (event) {
+ $('#meta-chooser').data('target-input').val(
+ $('#meta-chooser :checked').val()
+ ).trigger('change');
+ $('#meta-chooser').modal('hide');
+ });
+
self.$pane.on('click', '.current-convert', function() {
self.convert($(this).attr('data-to'));
});
let ap = $("<div class='input-group-append'>");
ap.appendTo(ig);
+
+ if (field.value_type.chooser) {
+ ap.append($("<button type='button' class='btn btn-outline-secondary' data-toggle='modal' data-target='#meta-chooser'>…</button>"));
+ }
$("<button class='meta-delete btn btn-outline-secondary'>x</button>").appendTo(ap);
// lang
{% include "wiki/revert_dialog.html" %}
{% include "wiki/media_dialog.html" %}
{% include "wiki/gallery_dialog.html" %}
+ {% include "wiki/meta_chooser.html" %}
{% if can_pubmark %}
{% include "wiki/pubmark_dialog.html" %}
{% endif %}
--- /dev/null
+{% load i18n %}
+<div id="meta-chooser" class="modal">
+ <div class="modal-dialog modal-lg">
+ <div " class="modal-content">
+ <div class="modal-body">
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="ctrl-ok btn btn-primary">{% translate "Choose" %}</button>
+ <button type="button" class="btn btn-primary" data-dismiss="modal">{% translate "Cancel" %}</button>
+ </div>
+ </div>
+ </div>
+</div>
ThemaCategory: {
'autocomplete': {
'source': '/catalogue/terms/thema/',
- }
+ },
+ 'chooser': {
+ 'source': '/catalogue/chooser/thema/',
+ },
},
MainThemaCategory: {
'autocomplete': {
'source': '/catalogue/terms/thema-main/',
- }
+ },
+ 'chooser': {
+ 'source': '/catalogue/chooser/thema-main/',
+ },
},
Epoch: {
'autocomplete': {