diff --git a/baseframe/forms/fields.py b/baseframe/forms/fields.py index 7d0d6f9d..8de6fa6e 100644 --- a/baseframe/forms/fields.py +++ b/baseframe/forms/fields.py @@ -28,6 +28,7 @@ from .widgets import ( CoordinatesInput, DateTimeInput, + ImgeeWidget, RadioMatrixInput, Select2Widget, SelectWidget, @@ -748,6 +749,8 @@ class ImgeeField(URLField): ) """ + widget = ImgeeWidget() + def __init__( self, label='', @@ -765,7 +768,7 @@ def __init__( def __call__(self, **kwargs): c = kwargs.pop('class', '') or kwargs.pop('class_', '') kwargs['class'] = ( - "%s %s" % (c.strip(), 'imgee-url-holder') if c else 'imgee-url-holder' + "%s %s" % (c.strip(), 'imgee__url-holder') if c else 'imgee__url-holder' ).strip() if self.profile: kwargs['data-profile'] = ( diff --git a/baseframe/forms/widgets.py b/baseframe/forms/widgets.py index c38a2dfa..94ad836a 100644 --- a/baseframe/forms/widgets.py +++ b/baseframe/forms/widgets.py @@ -3,11 +3,13 @@ from __future__ import unicode_literals import six -from flask import Markup +from flask import Markup, current_app, render_template from wtforms.compat import text_type from wtforms.widgets import RadioInput, Select, html_params import wtforms +from furl import furl + from .. import b_ as _ __all__ = [ @@ -17,6 +19,7 @@ 'DateTimeInput', 'CoordinatesInput', 'RadioMatrixInput', + 'ImgeeWidget', 'InlineListWidget', 'RadioInput', 'SelectWidget', @@ -286,3 +289,58 @@ def __call__(self, field, **kwargs): ) html.append('' % self.html_tag) return Markup('\n'.join(html)) + + +class ImgeeWidget(wtforms.widgets.Input): + input_type = 'hidden' + + def __call__(self, field, **kwargs): + id_ = kwargs.pop('id', field.id) + kwargs.setdefault('type', self.input_type) + imgee_host = current_app.config.get('IMGEE_HOST') + if not imgee_host: + raise ValueError("No imgee server specified in config variable IMGEE_HOST") + + upload_url = f'{imgee_host}/{field.profile}/popup' + + value = kwargs.pop('value', None) + if not value: + value = field._value() + if not value: + value = '' + elif isinstance(value, furl): + value = furl.url + + iframe_html = Markup( + '' + % ( + self.html_params( + id='iframe_' + id_ + '_upload', + input_id=id_, + src=upload_url, + ), + ) + ) + + field_html = Markup( + ' ' + % ( + self.html_params(id='img_' + id_, src=value, width='200', **kwargs), + self.html_params( + id=id_, + name=field.name, + placeholder=_("Image URL"), + value=value, + **kwargs + ), + ) + ) + + return Markup( + render_template( + 'baseframe/mui/imgeefield.html.jinja2', + field=field, + iframe_html=iframe_html, + field_html=field_html, + ) + ) diff --git a/baseframe/static/css/mui.css b/baseframe/static/css/mui.css index 752f3fd9..8a1aff6e 100644 --- a/baseframe/static/css/mui.css +++ b/baseframe/static/css/mui.css @@ -4330,6 +4330,38 @@ li p + ol { cursor: default; } +.imgee { + position: relative; +} +.imgee .imgee__url-holder { + display: block; + max-width: 200px; + margin-bottom: 8px; +} +.imgee .imgee__loader { + position: absolute; + top: 100px; + left: 200px; + width: 35px; + height: 35px; +} +.imgee .imgee__button { + margin-bottom: 8px; +} + +.modal--fullscreen iframe.imgee-upload { + width: 100%; + height: 100vh; + border: 0; +} + +.popup .mui-container { + max-width: calc(100% - 32px); +} +.popup .mui-container .popup__imgee { + padding: 0; +} + .chip { padding: 0 5px 5px; border: 0; @@ -4568,12 +4600,18 @@ li p + ol { .jquery-modal.blocker.current .modal .modal__body__btn { margin-top: 16px; } -.jquery-modal.blocker.current .modal-form { +.jquery-modal.blocker.current .modal--form { width: 100%; border-radius: 0; overflow: auto; min-height: 100%; } +.jquery-modal.blocker.current .modal--fullscreen { + width: 100%; + height: 100%; + padding: 0; + border-radius: 0; +} @media (min-width: 768px) { .jquery-modal.blocker.current { @@ -4582,10 +4620,15 @@ li p + ol { .jquery-modal.blocker.current .modal { max-width: 500px; width: 90%; - padding: 24px; + padding: 16px; min-height: auto; border-radius: 8px; } + .jquery-modal.blocker.current .modal--fullscreen { + max-width: 90%; + padding: 16px; + height: auto; + } } .tab-container { display: flex; diff --git a/baseframe/static/sass/baseframe-material/_form.scss b/baseframe/static/sass/baseframe-material/_form.scss index a0aa9278..dff18e81 100644 --- a/baseframe/static/sass/baseframe-material/_form.scss +++ b/baseframe/static/sass/baseframe-material/_form.scss @@ -270,3 +270,41 @@ opacity: 0.5; cursor: default; } + +.imgee { + position: relative; + .imgee__url-holder { + display: block; + max-width: 200px; + margin-bottom: $mui-grid-padding/2; + } + + .imgee__loader { + position: absolute; + top: 100px; + left: 200px; + width: 35px; + height: 35px; + } + + .imgee__button { + margin-bottom: $mui-grid-padding/2; + } +} + +.modal--fullscreen { + iframe.imgee-upload { + width: 100%; + height: 100vh; + border: 0; + } +} + +.popup { + .mui-container { + max-width: calc(100% - 32px); + .popup__imgee { + padding: 0; + } + } +} diff --git a/baseframe/static/sass/baseframe-material/_modal.scss b/baseframe/static/sass/baseframe-material/_modal.scss index 53258727..872afd66 100644 --- a/baseframe/static/sass/baseframe-material/_modal.scss +++ b/baseframe/static/sass/baseframe-material/_modal.scss @@ -33,12 +33,18 @@ margin-top: $mui-grid-padding; } } - .modal-form { + .modal--form { width: 100%; border-radius: 0; overflow: auto; min-height: 100%; } + .modal--fullscreen { + width: 100%; + height: 100%; + padding: 0; + border-radius: 0; + } } @media (min-width: 768px) { @@ -48,9 +54,14 @@ .modal { max-width: 500px; width: 90%; - padding: $mui-grid-padding + $mui-grid-padding/2; + padding: $mui-grid-padding; min-height: auto; border-radius: 8px; } + .modal--fullscreen { + max-width: 90%; + padding: $mui-grid-padding; + height: auto; + } } } diff --git a/baseframe/templates/baseframe/bootstrap3/forms.html.jinja2 b/baseframe/templates/baseframe/bootstrap3/forms.html.jinja2 index 765a5248..79a80ded 100644 --- a/baseframe/templates/baseframe/bootstrap3/forms.html.jinja2 +++ b/baseframe/templates/baseframe/bootstrap3/forms.html.jinja2 @@ -165,7 +165,7 @@ if(!$(this).data('parsley-validate') || $(this).data('parsley-validate') && $(this).hasClass('parsley-valid')) { $(this).find('button[type="submit"]').prop('disabled', true); $(this).find('input[type="submit"]').prop('disabled', true); - $(this).find(".loading").removeClass('mui--hide'); + $(this).find(".loading").removeClass('hidden'); } }); }); diff --git a/baseframe/templates/baseframe/mui/forms.html.jinja2 b/baseframe/templates/baseframe/mui/forms.html.jinja2 index 9de4ee7c..2711931f 100644 --- a/baseframe/templates/baseframe/mui/forms.html.jinja2 +++ b/baseframe/templates/baseframe/mui/forms.html.jinja2 @@ -79,6 +79,10 @@ {%- endif %} + {%- elif field.type == 'ImgeeField' %} +
+ {{ field | render_field_options(class="field-" + field.id + " " + widget_css_class, tabindex=tabindex, autofocus=autofocus, rows=rows) }} +
{%- elif field.widget.input_type == 'password' and field.widget.html_tag not in ['ul', 'ol'] %}
{{ field | render_field_options(class="field-" + field.id + " " + widget_css_class, tabindex=tabindex, autofocus=autofocus, rows=rows)}} @@ -356,6 +360,23 @@ document.getElementById("{{ ref_id }}").submit(); } }) + {%- elif field.type == 'ImgeeField' %} + window.addEventListener("message", function (event) { + if (event.origin === "{{ config['IMGEE_HOST'] }}") { + var message = JSON.parse(event.data); + if (message.context == 'imgee.upload') { + $('#imgee-loader-{{field.id}}').removeClass('mui--hide'); + $('#img_{{ field.id }}').attr('src', message.embed_url); + $('#{{ field.id }}').val(message.embed_url); + {%- if field.widget_type != 'modal' %} + $.modal.close(); + {%- endif %} + } + } + }); + $('#img_{{ field.id }}').on('load', function() { + $('#imgee-loader-{{field.id}}').addClass('mui--hide'); + }); {%- elif field.type in ['UserSelectField', 'UserSelectMultiField'] %} {%- if config['LASTUSER_CLIENT_ID'] and current_auth.cookie and 'sessionid' in current_auth.cookie %} Baseframe.Forms.lastuserAutocomplete({ diff --git a/baseframe/templates/baseframe/mui/imgeefield.html.jinja2 b/baseframe/templates/baseframe/mui/imgeefield.html.jinja2 new file mode 100644 index 00000000..e7314be8 --- /dev/null +++ b/baseframe/templates/baseframe/mui/imgeefield.html.jinja2 @@ -0,0 +1,13 @@ +{%- from "baseframe/mui/components.html.jinja2" import faicon -%} + +{{ field_html|escape }} +  +{% trans %}Select or upload image{% endtrans %} +