Mercurial > libervia-web
comparison browser_side/panels.py @ 395:98cd5387d291
browser_side: new microblogs are not using the rich text editor by default:
- a button allows to switch from raw to rich text, and vice versa
- raw text microblogs are not submitted anymore when the focus is lost, only when <enter> is pressed
author | souliane <souliane@mailoo.org> |
---|---|
date | Mon, 10 Mar 2014 22:39:26 +0100 |
parents | ee61b0765d6c |
children | 6148e9063069 |
comparison
equal
deleted
inserted
replaced
394:ee61b0765d6c | 395:98cd5387d291 |
---|---|
386 self._base_item = data if isinstance(data, MicroblogItem) else MicroblogItem(data) | 386 self._base_item = data if isinstance(data, MicroblogItem) else MicroblogItem(data) |
387 for attr in ['id', 'type', 'empty', 'title', 'title_xhtml', 'content', 'content_xhtml', | 387 for attr in ['id', 'type', 'empty', 'title', 'title_xhtml', 'content', 'content_xhtml', |
388 'author', 'updated', 'published', 'comments', 'service', 'node', | 388 'author', 'updated', 'published', 'comments', 'service', 'node', |
389 'comments_service', 'comments_node']: | 389 'comments_service', 'comments_node']: |
390 getter = lambda attr: lambda inst: getattr(inst._base_item, attr) | 390 getter = lambda attr: lambda inst: getattr(inst._base_item, attr) |
391 setattr(MicroblogEntry, attr, property(getter(attr))) | 391 setter = lambda attr: lambda inst, value: setattr(inst._base_item, attr, value) |
392 setattr(MicroblogEntry, attr, property(getter(attr), setter(attr))) | |
392 | 393 |
393 SimplePanel.__init__(self) | 394 SimplePanel.__init__(self) |
394 self._blog_panel = blog_panel | 395 self._blog_panel = blog_panel |
395 | 396 |
396 self.panel = FlowPanel() | 397 self.panel = FlowPanel() |
407 entry_avatar.setStyleName('mb_entry_avatar') | 408 entry_avatar.setStyleName('mb_entry_avatar') |
408 self.avatar = Image(self._blog_panel.host.getAvatar(self.author)) | 409 self.avatar = Image(self._blog_panel.host.getAvatar(self.author)) |
409 entry_avatar.add(self.avatar) | 410 entry_avatar.add(self.avatar) |
410 self.panel.add(entry_avatar) | 411 self.panel.add(entry_avatar) |
411 | 412 |
412 self.entry_dialog = SimplePanel() | 413 self.entry_dialog = HorizontalPanel() |
413 self.entry_dialog.setStyleName('mb_entry_dialog') | 414 self.entry_dialog.setStyleName('mb_entry_dialog') |
414 self.panel.add(self.entry_dialog) | 415 self.panel.add(self.entry_dialog) |
415 | 416 |
416 self.add(self.panel) | 417 self.add(self.panel) |
417 ClickHandler.__init__(self) | 418 ClickHandler.__init__(self) |
471 if sender == self: | 472 if sender == self: |
472 self._blog_panel.setSelectedEntry(self) | 473 self._blog_panel.setSelectedEntry(self) |
473 elif sender == self.delete_label: | 474 elif sender == self.delete_label: |
474 self._delete() | 475 self._delete() |
475 elif sender == self.update_label: | 476 elif sender == self.update_label: |
476 self.bubble.edit(True) | 477 self.edit(True) |
477 elif sender == self.comment_label: | 478 elif sender == self.comment_label: |
478 self._comment() | 479 self._comment() |
479 | 480 |
480 def __modifiedCb(self, content): | 481 def __modifiedCb(self, content): |
481 """Send the new content to the backend | 482 """Send the new content to the backend |
483 """ | 484 """ |
484 if not content['text']: # previous content has been emptied | 485 if not content['text']: # previous content has been emptied |
485 self._delete(True) | 486 self._delete(True) |
486 return False | 487 return False |
487 extra = {'published': str(self.published)} | 488 extra = {'published': str(self.published)} |
488 if self.empty or self.content_xhtml: | 489 if isinstance(self.bubble, richtext.RichTextEditor): |
489 # TODO: if the user change his parameters after the message edition started, | 490 # TODO: if the user change his parameters after the message edition started, |
490 # the message syntax could be different then the current syntax: pass the | 491 # the message syntax could be different then the current syntax: pass the |
491 # message syntax in extra for the frontend to use it instead of current syntax. | 492 # message syntax in extra for the frontend to use it instead of current syntax. |
492 extra.update({'content_rich': content['text'], 'title': content['title']}) | 493 extra.update({'content_rich': content['text'], 'title': content['title']}) |
493 if self.empty: | 494 if self.empty: |
506 self._blog_panel.removeEntry(self.type, self.id) | 507 self._blog_panel.removeEntry(self.type, self.id) |
507 if self.type == 'main_item': # restore the "New message" button | 508 if self.type == 'main_item': # restore the "New message" button |
508 self._blog_panel.refresh() | 509 self._blog_panel.refresh() |
509 else: # allow to create a new comment | 510 else: # allow to create a new comment |
510 self._parent_entry._current_comment = None | 511 self._parent_entry._current_comment = None |
511 | 512 try: |
512 def __setBubble(self): | 513 self.toggle_syntax_button.removeFromParent() |
514 except TypeError: | |
515 pass | |
516 | |
517 def __setBubble(self, edit=False): | |
513 """Set the bubble displaying the initial content.""" | 518 """Set the bubble displaying the initial content.""" |
514 content = {'text': self.content_xhtml if self.content_xhtml else self.content, | 519 content = {'text': self.content_xhtml if self.content_xhtml else self.content, |
515 'title': self.title_xhtml if self.title_xhtml else self.title} | 520 'title': self.title_xhtml if self.title_xhtml else self.title} |
516 if self.empty or self.content_xhtml: # new message and rich text message | 521 if self.content_xhtml: |
517 content.update({'syntax': Const.SYNTAX_XHTML}) | 522 content.update({'syntax': Const.SYNTAX_XHTML}) |
518 if self.author != self._blog_panel.host.whoami.bare: | 523 if self.author != self._blog_panel.host.whoami.bare: |
519 options = ['read_only'] | 524 options = ['read_only'] |
520 else: | 525 else: |
521 options = [] if self.empty else ['update_msg'] | 526 options = [] if self.empty else ['update_msg'] |
522 self.bubble = richtext.RichTextEditor(self._blog_panel.host, content, self.__modifiedCb, self.__afterEditCb, options) | 527 self.bubble = richtext.RichTextEditor(self._blog_panel.host, content, self.__modifiedCb, self.__afterEditCb, options) |
523 else: # assume raw text message have no title | 528 else: # assume raw text message have no title |
524 self.bubble = LightTextEditor(content, self.__modifiedCb, self.__afterEditCb, True) | 529 self.bubble = LightTextEditor(content, self.__modifiedCb, self.__afterEditCb, single_line=True, listen_focus=False) |
525 self.bubble.setStyleName("bubble") | 530 self.bubble.setStyleName("bubble") |
531 try: | |
532 self.toggle_syntax_button.removeFromParent() | |
533 except TypeError: | |
534 pass | |
526 self.entry_dialog.add(self.bubble) | 535 self.entry_dialog.add(self.bubble) |
527 self.bubble.edit(False) | 536 self.edit(edit) |
528 self.bubble.addEditListener(self.__showWarning) | 537 self.bubble.addEditListener(self.__showWarning) |
529 | 538 |
530 def __showWarning(self, sender, keycode): | 539 def __showWarning(self, sender, keycode): |
531 if keycode == KEY_ENTER: | 540 if keycode == KEY_ENTER: |
532 self._blog_panel.host.showWarning(None, None) | 541 self._blog_panel.host.showWarning(None, None) |
569 if entry is None: | 578 if entry is None: |
570 print "The entry of id %s can not be commented" % self.id | 579 print "The entry of id %s can not be commented" % self.id |
571 return | 580 return |
572 entry._parent_entry = self | 581 entry._parent_entry = self |
573 self._current_comment = entry | 582 self._current_comment = entry |
574 entry.bubble.edit(True) | 583 self.edit(True, entry) |
584 | |
585 def edit(self, edit, entry=None): | |
586 """Toggle the bubble between display and edit mode | |
587 @edit: boolean value | |
588 @entry: MicroblogEntry instance, or None to use self | |
589 """ | |
590 if entry is None: | |
591 entry = self | |
592 try: | |
593 entry.toggle_syntax_button.removeFromParent() | |
594 except TypeError: | |
595 pass | |
596 entry.bubble.edit(edit) | |
597 if edit: | |
598 if isinstance(entry.bubble, richtext.RichTextEditor): | |
599 image = '<a class="richTextIcon">A</a>' | |
600 title = _('Switch to raw text edition') | |
601 else: | |
602 image = '<img src="media/icons/tango/actions/32/format-text-italic.png" class="richTextIcon"/>' | |
603 title = _('Switch to rich text edition') | |
604 entry.toggle_syntax_button = Button(image, entry.toggleContentSyntax) | |
605 entry.toggle_syntax_button.setTitle(title) | |
606 entry.entry_dialog.add(entry.toggle_syntax_button) | |
607 | |
608 def toggleContentSyntax(self): | |
609 """Toggle the editor between raw and rich text""" | |
610 original_content = self.bubble.getOriginalContent() | |
611 rich = not isinstance(self.bubble, richtext.RichTextEditor) | |
612 | |
613 def setBubble(text): | |
614 self.content = text | |
615 self.content_xhtml = text if rich else '' | |
616 self.content_title = self.content_title_xhtml = '' | |
617 self.bubble.removeFromParent() | |
618 self.__setBubble(True) | |
619 self.bubble.setOriginalContent(original_content) | |
620 | |
621 text = self.bubble.getContent()['text'] | |
622 if not text: | |
623 setBubble(' ') # something different than empty string is needed to initialize the rich text editor | |
624 return | |
625 if not rich: | |
626 def confirm_cb(answer): | |
627 if answer: | |
628 self._blog_panel.host.bridge.call('syntaxConvert', setBubble, text, Const.SYNTAX_CURRENT, Const.SYNTAX_TEXT) | |
629 dialog.ConfirmDialog(confirm_cb, text=_("Do you really want to lose the title and text formatting?")).show() | |
630 else: | |
631 self._blog_panel.host.bridge.call('syntaxConvert', setBubble, text, Const.SYNTAX_TEXT, Const.SYNTAX_XHTML) | |
575 | 632 |
576 | 633 |
577 class MicroblogPanel(base_widget.LiberviaWidget): | 634 class MicroblogPanel(base_widget.LiberviaWidget): |
578 warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know" | 635 warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know" |
579 warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>" | 636 warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>" |
605 data = {'id': str(time()), | 662 data = {'id': str(time()), |
606 'new': True, | 663 'new': True, |
607 'author': self.host.whoami.bare, | 664 'author': self.host.whoami.bare, |
608 } | 665 } |
609 entry = self.addEntry(data) | 666 entry = self.addEntry(data) |
610 entry.bubble.edit(True) | 667 entry.edit(True) |
611 self.new_button = Button("New message", listener=addBox) | 668 self.new_button = Button("New message", listener=addBox) |
612 self.new_button.setStyleName("microblogNewButton") | 669 self.new_button.setStyleName("microblogNewButton") |
613 self.vpanel.insert(self.new_button, 0) | 670 self.vpanel.insert(self.new_button, 0) |
614 | 671 |
615 @classmethod | 672 @classmethod |
888 EMPTY_STATUS = '<click to set a status>' | 945 EMPTY_STATUS = '<click to set a status>' |
889 | 946 |
890 def __init__(self, host, status=''): | 947 def __init__(self, host, status=''): |
891 self.host = host | 948 self.host = host |
892 modifiedCb = lambda content: self.host.bridge.call('setStatus', None, self.host.status_panel.presence, content['text']) or True | 949 modifiedCb = lambda content: self.host.bridge.call('setStatus', None, self.host.status_panel.presence, content['text']) or True |
893 LightTextEditor.__init__(self, {'text': status}, modifiedCb, None, True) | 950 LightTextEditor.__init__(self, {'text': status}, modifiedCb, None, single_line=True) |
894 self.edit(False) | 951 self.edit(False) |
895 self.setStyleName('statusPanel') | 952 self.setStyleName('statusPanel') |
896 ClickHandler.__init__(self) | 953 ClickHandler.__init__(self) |
897 self.addClickListener(self) | 954 self.addClickListener(self) |
898 | 955 |