Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move active flow and interruption into chat, make temba-user fetch individually #5686

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
]
},
"dependencies": {
"@nyaruka/flow-editor": "1.36.1",
"@nyaruka/temba-components": "0.111.7",
"@nyaruka/flow-editor": "1.36.3",
"@nyaruka/temba-components": "0.112.0",
"codemirror": "5.18.2",
"colorette": "1.2.2",
"fa-icons": "0.2.0",
Expand Down
32 changes: 17 additions & 15 deletions static/css/temba-components.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ html {
--color-borders: rgba(0, 0, 0, 0.07);
--color-placeholder: #ccc;
--color-primary-light: #eee;
--color-secondary-light: rgba(var(--secondary-rgb), .3);
--color-secondary-light: rgba(var(--secondary-rgb), 0.3);
--color-primary-dark: rgb(var(--primary-rgb));
--color-secondary-dark: rgb(var(--secondary-rgb));
--color-focus: #a4cafe;
Expand All @@ -38,7 +38,7 @@ html {
--color-widget-border: rgb(225, 225, 225);
--color-options-bg: var(--color-widget-bg);
--color-selection: #f0f6ff;
--color-row-hover: rgba(var(--selection-light-rgb), .4);
--color-row-hover: rgba(var(--selection-light-rgb), 0.4);
--color-available: #00f100;
--color-tertiary: rgb(var(--tertiary-rgb));
--color-text-light: rgba(255, 255, 255, 1);
Expand All @@ -59,7 +59,7 @@ html {
--color-button-secondary-text: var(--color-text-dark);
--color-button-destructive: rgb(var(--error-rgb));
--color-button-destructive-text: var(--color-text-light);
--color-button-attention: #2ecc71;
--color-button-attention: #3ca96a;
--color-label-primary: var(--color-primary-dark);
--color-label-primary-text: var(--color-text-light);
--color-label-secondary: var(--color-secondary-dark);
Expand All @@ -77,27 +77,31 @@ html {
--color-alert: rgb(var(--error-rgb));
--icon-color: var(--text-color);
--icon-color-circle: rgb(240, 240, 240);
--icon-color-circle-hover: rgba(245, 245, 245, .8);
--icon-color-circle-hover: rgba(245, 245, 245, 0.8);
--header-bg: var(--color-primary-dark);
--header-text: var(--color-text-light);
--color-text-help: rgb(120, 120, 120);
--color-automated: rgb(78, 205, 106);


/* Shadows */
--widget-box-shadow: rgba(-1, -1, 0, .1) 0px 1px 7px 0px, rgba(0, 0, 0, 0.05) 0px 1px 2px 0px;
--widget-box-shadow-focused: 0 0 0 3px rgba(164, 202, 254, .45), rgba(0, 0, 0, 0.05) 0px 3px 7px 0px, rgba(0, 0, 0, 0.05) 0px 1px 2px 0px;
--widget-box-shadow: rgba(-1, -1, 0, 0.1) 0px 1px 7px 0px,
rgba(0, 0, 0, 0.05) 0px 1px 2px 0px;
--widget-box-shadow-focused: 0 0 0 3px rgba(164, 202, 254, 0.45),
rgba(0, 0, 0, 0.05) 0px 3px 7px 0px, rgba(0, 0, 0, 0.05) 0px 1px 2px 0px;
--widget-box-shadow-focused-error: 0 0 0 3px rgba(var(--error-rgb), 0.3);
--shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
--shadow-widget: 0 3px 20px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.02);
--shadow-widget: 0 3px 20px 0 rgba(0, 0, 0, 0.04),
0 1px 2px 0 rgba(0, 0, 0, 0.02);

/* temba-select */
--select-input-height: inherit;
--temba-select-selected-font-size: 1em;
--temba-select-selected-padding: .6em .8em;
--temba-select-selected-padding: 0.6em 0.8em;
--temba-select-selected-line-height: 1.2em;
--options-block-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.03);
--options-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--options-block-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1),
0 1px 2px 0 rgba(0, 0, 0, 0.03);
--options-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -2px rgba(0, 0, 0, 0.05);
--dropdown-shadow: rgb(0 0 0 / 15%) 0px 0px 30px, rgb(0 0 0 / 12%) 0px 2px 6px;

/* buttons */
Expand All @@ -106,7 +110,7 @@ html {
--button-x: 1.5em;

/* textinput */
--temba-textinput-padding: 0.6em .8em;
--temba-textinput-padding: 0.6em 0.8em;
--temba-textinput-font-size: 1;

/* charcount */
Expand All @@ -126,6 +130,4 @@ html {
--event-padding: 0.5em 1em;
--control-margin-bottom: 15px;
--menu-padding: 1em;


}
}
7 changes: 6 additions & 1 deletion temba/api/v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3497,7 +3497,7 @@ class UsersEndpoint(ListAPIMixin, BaseEndpoint):

A **GET** returns the users in your workspace, ordered by newest created first.

* **email** - the email address of the user (string).
* **email** - the email address of the user (string), filterable as `email`.
* **first_name** - the first name of the user (string).
* **last_name** - the last name of the user (string).
* **role** - the role of the user (string), filterable as `role` which can be repeated.
Expand Down Expand Up @@ -3531,6 +3531,11 @@ class UsersEndpoint(ListAPIMixin, BaseEndpoint):
def derive_queryset(self):
org = self.request.org

# filter by email if specified
email = self.request.query_params.get("email")
if email:
return org.users.filter(email__iexact=email).prefetch_related("settings")

# limit to roles if specified
roles = self.request.query_params.getlist("role")
if roles:
Expand Down
20 changes: 10 additions & 10 deletions temba/contacts/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,42 +912,42 @@ def test_interrupt(self, mr_mocks):
other_org_contact = self.create_contact("Hans", phone="+593979123456", org=self.org2)

read_url = reverse("contacts.contact_read", args=[contact.uuid])
interrupt_url = reverse("contacts.contact_interrupt", args=[contact.id])
interrupt_url = reverse("contacts.contact_interrupt", args=[contact.uuid])

self.login(self.admin)

# no interrupt option if not in a flow
# shoud see start flow option
response = self.client.get(read_url)
self.assertNotContains(response, interrupt_url)
self.assertContentMenu(read_url, self.admin, ["Edit", "Start Flow", "Open Ticket"])

MockSessionWriter(contact, self.create_flow("Test")).wait().save()
MockSessionWriter(other_org_contact, self.create_flow("Test", org=self.org2)).wait().save()

# now it's an option
self.assertContentMenu(read_url, self.admin, ["Edit", "Start Flow", "Open Ticket", "Interrupt"])
# start option should be gone
self.assertContentMenu(read_url, self.admin, ["Edit", "Open Ticket"])

# can't interrupt if not logged in
self.client.logout()
response = self.client.post(interrupt_url, {"id": contact.id})
response = self.client.post(interrupt_url)
self.assertLoginRedirect(response)

self.login(self.user)

# can't interrupt if just regular user
response = self.client.post(interrupt_url, {"id": contact.id})
response = self.client.post(interrupt_url)
self.assertLoginRedirect(response)

self.login(self.admin)

response = self.client.post(interrupt_url, {"id": contact.id})
response = self.client.post(interrupt_url)
self.assertEqual(302, response.status_code)

contact.refresh_from_db()
self.assertIsNone(contact.current_flow)

# can't interrupt contact in other org
restore_url = reverse("contacts.contact_interrupt", args=[other_org_contact.id])
response = self.client.post(restore_url, {"id": other_org_contact.id})
other_contact_interrupt = reverse("contacts.contact_interrupt", args=[other_org_contact.uuid])
response = self.client.post(other_contact_interrupt)
self.assertLoginRedirect(response)

# contact should be unchanged
Expand Down
10 changes: 5 additions & 5 deletions temba/contacts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def build_context_menu(self, menu):
)

if obj.status == Contact.STATUS_ACTIVE:
if self.has_org_perm("flows.flow_start"):
if not obj.current_flow and self.has_org_perm("flows.flow_start"):
menu.add_modax(
_("Start Flow"),
"start-flow",
Expand All @@ -348,8 +348,6 @@ def build_context_menu(self, menu):
menu.add_modax(
_("Open Ticket"), "open-ticket", reverse("contacts.contact_open_ticket", args=[obj.id])
)
if self.has_org_perm("contacts.contact_interrupt") and obj.current_flow:
menu.add_url_post(_("Interrupt"), reverse("contacts.contact_interrupt", args=(obj.id,)))

class Scheduled(BaseReadView):
"""
Expand Down Expand Up @@ -800,13 +798,15 @@ def save(self, obj):
def get_success_url(self):
return f"{reverse('tickets.ticket_list')}all/open/{self.ticket.uuid}/"

class Interrupt(OrgObjPermsMixin, SmartUpdateView):
class Interrupt(ModalFormMixin, OrgObjPermsMixin, SmartUpdateView):
"""
Interrupt this contact
"""

slug_url_kwarg = "uuid"
fields = ()
success_url = "[email protected]_read"
success_url = "hide"
submit_button_name = _("Interrupt")

def save(self, obj):
obj.interrupt(self.request.user)
Expand Down
7 changes: 1 addition & 6 deletions temba/tickets/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,7 @@ def build_context_menu(self, menu):
on_submit="handleNoteAdded()",
)

if ticket.contact.current_flow:
if self.has_org_perm("contacts.contact_interrupt"):
menu.add_url_post(
_("Interrupt"), reverse("contacts.contact_interrupt", args=(ticket.contact.id,))
)
else:
if not ticket.contact.current_flow:
if self.has_org_perm("flows.flow_start"):
menu.add_modax(
_("Start Flow"),
Expand Down
8 changes: 8 additions & 0 deletions templates/contacts/contact_interrupt.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% extends "includes/modax.html" %}
{% load i18n %}

{% block fields %}
{% blocktrans trimmed %}
You are about to interrupt the current flow for <span class="font-normal">{{ object }}.</span> There is no way to undo this. Are you sure?
{% endblocktrans %}
{% endblock fields %}
13 changes: 12 additions & 1 deletion templates/contacts/contact_read.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
class="flex-grow -mt-2">
<temba-tab class="chat" icon="message" name="{{ _("Chat") |escapejs }}">
<div style="border-top-right-radius: var(--curvature);" class="flex flex-grow flex-col overflow-y-auto">
<temba-contact-chat contact="{{ object.uuid }}" monitor="true" avatar="{{ branding.logos.avatar }}">
<temba-contact-chat contact="{{ object.uuid }}"
monitor="true"
avatar="{{ branding.logos.avatar }}"
{% if org_perms.contacts.contact_interrupt %}showInterrupt{% endif %}
-temba-interrupt="handleInterruptContact">
</temba-contact-chat>
</div>
</temba-tab>
Expand Down Expand Up @@ -80,6 +84,13 @@
{% endblock extra-style %}
{% block extra-script %}
<script type="text/javascript">
function handleInterruptContact(event) {
const options = {
onSubmit: "contactUpdated()"
}
showModax("{{_('Interrupt Contact')|escapejs}}", "/contact/interrupt/" + event.detail.contact.uuid + "/", options);
}

function contactUpdated(evt) {
const details = document.querySelector("temba-contact-details");
details.refresh();
Expand Down
5 changes: 5 additions & 0 deletions templates/frame.html
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@
#error-dialog {
--header-bg: var(--color-alert);
}

* {
font-synthesis: none !important;
-webkit-font-smoothing: antialiased;
}
</style>
{% endcompress %}
{% endblock styles %}
Expand Down
6 changes: 6 additions & 0 deletions templates/orgs/user_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@
{{ block.super }}
<script type="text/javascript">
onSpload(function() {
const store = document.querySelector('temba-store');
if (store) {
store.makeRequest("/api/v2/users.json?email={{user.email}}", {
force: true
})
}

// hide our password field by default
var passwordContainer = document.getElementById("current-password");
Expand Down
17 changes: 17 additions & 0 deletions templates/tickets/ticket_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,21 @@
}
}

function handleInterruptContact(event) {
const options = {
onSubmit: "contactUpdated()"
}
showModax("{{_('Interrupt Contact')|escapejs}}", "/contact/interrupt/" + event.detail.contact.uuid + "/", options);
}

function contactUpdated() {
const chat = document.querySelector('temba-contact-chat');
chat.refresh();

const contentMenu = document.querySelector("temba-content-menu#default-content-menu");
contentMenu.refresh();
}

function handleTabChanged() {
var tab = document.querySelector("temba-tabs").index;
var url = window.location.pathname + "?tab=" + tab;
Expand Down Expand Up @@ -620,6 +635,8 @@ <h2>
<temba-contact-chat agent="{{ request.user.email }}"
monitor="true"
-temba-message-sent="handleMessageSent"
-temba-interrupt="handleInterruptContact"
{% if org_perms.contacts.contact_interrupt %}showInterrupt{% endif %}
avatar="{{ branding.logos.avatar }}">
</temba-contact-chat>
</div>
Expand Down
16 changes: 8 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"

"@nyaruka/[email protected].1":
version "1.36.1"
resolved "https://registry.yarnpkg.com/@nyaruka/flow-editor/-/flow-editor-1.36.1.tgz#2b190d3d74ae72db908864122d2c52ea99191c6c"
integrity sha512-3cgJsRsk9PN39NL6N59amify70z4TsuR6K5XrkmRf/EWlx3h4bMK/91HX2T9xscYiTb+BSDBwqS4yvuL/a3/bQ==
"@nyaruka/[email protected].3":
version "1.36.3"
resolved "https://registry.yarnpkg.com/@nyaruka/flow-editor/-/flow-editor-1.36.3.tgz#d884a2d316352334eb6ae7b8f8fe892d55b60ec8"
integrity sha512-0utgx8jH9XezUSF+l9Wf5mzCd4RcbAFUqL8wyp9YmipY6QvyqFbzbI6wsI0CNIw09IffcZyzpmYgG7bpyhSb/g==
dependencies:
"@nyaruka/temba-components" "0.101.0"
react "^16.8.6"
Expand All @@ -103,10 +103,10 @@
serialize-javascript "^6.0.2"
tiny-lru "^11.2.5"

"@nyaruka/temba-components@0.111.7":
version "0.111.7"
resolved "https://registry.yarnpkg.com/@nyaruka/temba-components/-/temba-components-0.111.7.tgz#f0355181cf5dcaedecccff930fbe5d616b8edb31"
integrity sha512-llPTORJ/3RVK6K6u2k2KtNlXIgWeFB5UO1AGr9rv/HnnFv3tr9djAUVviiAV1FT67TWzU0adVOZxxtn2R6zpPw==
"@nyaruka/temba-components@0.112.0":
version "0.112.0"
resolved "https://registry.yarnpkg.com/@nyaruka/temba-components/-/temba-components-0.112.0.tgz#133007e9036f0fc6ff6a4752cdd60f38c6a00f74"
integrity sha512-TgLGkl7zp0r6HvdlGSJCnkfmZ1z2MMVczLFphry0ZOBbhQXjrks7sDZGrYUICNbLfjZxhnQSEoxAGau/Inaqcg==
dependencies:
"@lit/localize" "^0.12.1"
color-hash "^2.0.2"
Expand Down
Loading