diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index ae54a3b1d97a..5dcb08dcecd1 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -35,7 +35,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/deploy-docs-test.yml b/.github/workflows/deploy-docs-test.yml
index bb3de141a877..0b19440a5fd8 100644
--- a/.github/workflows/deploy-docs-test.yml
+++ b/.github/workflows/deploy-docs-test.yml
@@ -12,8 +12,8 @@ jobs:
name: Test deployment
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml
index a758a4bfb9cb..377046034ef4 100644
--- a/.github/workflows/deploy-docs.yml
+++ b/.github/workflows/deploy-docs.yml
@@ -16,8 +16,8 @@ jobs:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
@@ -30,7 +30,7 @@ jobs:
# Popular action to deploy to GitHub Pages:
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
- name: Deploy to GitHub Pages
- uses: peaceiris/actions-gh-pages@v3
+ uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# Build output to publish to the `gh-pages` branch:
diff --git a/.github/workflows/javascript.yml b/.github/workflows/javascript.yml
index 6a4e179934c9..3694dc722f0b 100644
--- a/.github/workflows/javascript.yml
+++ b/.github/workflows/javascript.yml
@@ -8,9 +8,9 @@ jobs:
steps:
- name: Check out Git repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Node.js environment
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 16
- name: Install dev deps
diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml
index 1a7897144757..ca31663a3880 100644
--- a/.github/workflows/playwright.yml
+++ b/.github/workflows/playwright.yml
@@ -29,15 +29,15 @@ jobs:
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- name: Check out Git repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Python 3.11
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: 3.11
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@v4
with:
node-version: 16
- - uses: actions/cache@v3
+ - uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -59,7 +59,7 @@ jobs:
run: dispatch database restore --dump-file data/dispatch-sample-data.dump && dispatch database upgrade
- name: Run tests
run: npx playwright test --project=chromium
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml
index 61b1cd92be86..8b3e07c180db 100644
--- a/.github/workflows/publish-image.yml
+++ b/.github/workflows/publish-image.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Push to GitHub Packages
uses: docker/build-push-action@v1
with:
diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml
index ed9a547ebc82..f45cf86f1c08 100644
--- a/.github/workflows/python.yml
+++ b/.github/workflows/python.yml
@@ -23,12 +23,12 @@ jobs:
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- name: Check out Git repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Set up Python 3.11
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: 3.11.2
- - uses: actions/cache@v2
+ - uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 5244106252ce..7318c49a0aab 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -7,7 +7,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v3
+ - uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale, because it has been open for 30 days with no activity. Remove the stale label or comment, or this will be closed in 5 days.'
diff --git a/docs/docs/administration/settings/plugins/configuring-slack.mdx b/docs/docs/administration/settings/plugins/configuring-slack.mdx
index bd8ddf9024c2..610a8e27a342 100644
--- a/docs/docs/administration/settings/plugins/configuring-slack.mdx
+++ b/docs/docs/administration/settings/plugins/configuring-slack.mdx
@@ -190,6 +190,7 @@ You can override their values if you wish to do so. Included below are their des
| `/dispatch-update-incident` | Opens a modal to update the incident. |
| `/dispatch-notifications-group` | Opens a modal to edit the notifications group. |
| `/dispatch-update-participant` | Opens a modal to update participant metadata. |
+| `/dispatch-create-task` | Opens a modal to create an incident task. |
### Contact Information Resolver Plugin
diff --git a/docs/docs/user-guide/incidents/commander.mdx b/docs/docs/user-guide/incidents/commander.mdx
index 45da2dbdd95c..4a3b4c7323ac 100644
--- a/docs/docs/user-guide/incidents/commander.mdx
+++ b/docs/docs/user-guide/incidents/commander.mdx
@@ -27,7 +27,7 @@ All Slack commands are listed below, or you may view _groups_ of commands relati
- [`/dispatch-update-incident`](#%2Fdispatch-update-incident)
- [`/dispatch-update-participant`](#%2Fdispatch-update-participant)
- [`/dispatch-run-workflow`](#%2Fdispatch-list-workflow)
-
+- [`/dispatch-create-task`](#%2Fdispatch-create-task)
## People
These commands help manage the people helping resolve the incident.
@@ -205,3 +205,13 @@ This command will run a pre-configured workflow and associate its artifacts with
![](/img/slack-conversation-run-workflow.png)
+
+### /dispatch-create-task
+
+This command will create a task for the current incident.
+
+
+{/* TODO(averyl): replace this image */}
+![](/img/slack-conversation-create-task.png)
+
+
diff --git a/docs/static/img/slack-conversation-create-task.png b/docs/static/img/slack-conversation-create-task.png
new file mode 100644
index 000000000000..c352953a9f44
Binary files /dev/null and b/docs/static/img/slack-conversation-create-task.png differ
diff --git a/requirements-base.txt b/requirements-base.txt
index 7a0948023b67..8a8dc465bb65 100644
--- a/requirements-base.txt
+++ b/requirements-base.txt
@@ -4,7 +4,7 @@
#
# pip-compile requirements-base.in
#
-aiocache==0.12.2
+aiocache==0.12.3
# via -r requirements-base.in
aiofiles==24.1.0
# via -r requirements-base.in
@@ -126,7 +126,7 @@ frozenlist==1.4.1
# aiosignal
google-api-core==2.15.0
# via google-api-python-client
-google-api-python-client==2.146.0
+google-api-python-client==2.147.0
# via -r requirements-base.in
google-auth==2.26.1
# via
@@ -330,7 +330,7 @@ python-dateutil==2.9.0.post0
# pandas
python-jose==3.3.0
# via -r requirements-base.in
-python-multipart==0.0.10
+python-multipart==0.0.12
# via -r requirements-base.in
python-slugify==8.0.4
# via -r requirements-base.in
@@ -483,7 +483,7 @@ urllib3==2.0.7
# pdpyras
# requests
# sentry-sdk
-uvicorn==0.30.6
+uvicorn==0.31.0
# via -r requirements-base.in
uvloop==0.20.0
# via -r requirements-base.in
diff --git a/src/dispatch/database/revisions/tenant/versions/2024-09-23_32652e0360dd.py b/src/dispatch/database/revisions/tenant/versions/2024-09-23_32652e0360dd.py
new file mode 100644
index 000000000000..5efbba277340
--- /dev/null
+++ b/src/dispatch/database/revisions/tenant/versions/2024-09-23_32652e0360dd.py
@@ -0,0 +1,105 @@
+"""Adds dispatch-create-task slug to slack conversation plugin config.
+
+Revision ID: 32652e0360dd
+Revises: 1f4dc687945d
+Create Date: 2024-09-23 16:02:50.742796
+
+"""
+
+from alembic import op
+from pydantic import SecretStr, ValidationError
+from pydantic.json import pydantic_encoder
+
+from sqlalchemy import Column, Integer, ForeignKey, String
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.orm import relationship, Session
+from sqlalchemy.ext.hybrid import hybrid_property
+from sqlalchemy_utils import StringEncryptedType
+from sqlalchemy_utils.types.encrypted.encrypted_type import AesEngine
+from dispatch.config import config, DISPATCH_ENCRYPTION_KEY
+
+
+# revision identifiers, used by Alembic.
+revision = "32652e0360dd"
+down_revision = "1f4dc687945d"
+branch_labels = None
+depends_on = None
+
+Base = declarative_base()
+
+
+def show_secrets_encoder(obj):
+ if isinstance(obj, SecretStr):
+ return obj.get_secret_value()
+ else:
+ return pydantic_encoder(obj)
+
+
+def migrate_config(instances, slug, config):
+ for instance in instances:
+ if slug == instance.plugin.slug:
+ instance.configuration = config
+
+
+class Plugin(Base):
+ __tablename__ = "plugin"
+ __table_args__ = {"schema": "dispatch_core"}
+ id = Column(Integer, primary_key=True)
+ slug = Column(String, unique=True)
+
+
+class PluginInstance(Base):
+ __tablename__ = "plugin_instance"
+ id = Column(Integer, primary_key=True)
+ _configuration = Column(
+ StringEncryptedType(key=str(DISPATCH_ENCRYPTION_KEY), engine=AesEngine, padding="pkcs5")
+ )
+ plugin_id = Column(Integer, ForeignKey(Plugin.id))
+ plugin = relationship(Plugin, backref="instances")
+
+ @hybrid_property
+ def configuration(self):
+ """Property that correctly returns a plugins configuration object."""
+ pass
+
+ @configuration.setter
+ def configuration(self, configuration):
+ """Property that correctly sets a plugins configuration object."""
+ if configuration:
+ self._configuration = configuration.json(encoder=show_secrets_encoder)
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ from dispatch.plugins.dispatch_slack.config import SlackConversationConfiguration
+
+ bind = op.get_bind()
+ session = Session(bind=bind)
+
+ instances = session.query(PluginInstance).all()
+
+ # Slash commands
+ SLACK_COMMAND_CREATE_TASK_SLUG = config(
+ "SLACK_COMMAND_CREATE_TASK_SLUG", default="/dispatch-create-task"
+ )
+
+ try:
+ slack_conversation_config = SlackConversationConfiguration(
+ slack_command_create_task=SLACK_COMMAND_CREATE_TASK_SLUG,
+ )
+
+ migrate_config(instances, "slack-conversation", slack_conversation_config)
+
+ except ValidationError:
+ print(
+ "Skipping automatic migration of slack plugin credentials, if you are using the slack plugin manually migrate credentials."
+ )
+
+ session.commit()
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ pass
+ # ### end Alembic commands ###
diff --git a/src/dispatch/incident/scheduled.py b/src/dispatch/incident/scheduled.py
index e2f0db85602a..0a3a33f6b1aa 100644
--- a/src/dispatch/incident/scheduled.py
+++ b/src/dispatch/incident/scheduled.py
@@ -229,7 +229,7 @@ def incident_close_reminder(db_session: Session, project: Project):
send_incident_close_reminder(incident, db_session)
-@scheduler.add(every().monday.at("18:00"), name="incident-report-weekly")
+@scheduler.add(every(1).day.at("18:00"), name="incident-report-weekly")
@timer
@scheduled_project_task
def incident_report_weekly(db_session: Session, project: Project):
@@ -269,10 +269,17 @@ def incident_report_weekly(db_session: Session, project: Project):
)
return
+ items_grouped = []
+ items_grouped_template = INCIDENT_SUMMARY_TEMPLATE
+
# we create and send an incidents weekly report
for incident in incidents:
- items_grouped = []
- items_grouped_template = INCIDENT_SUMMARY_TEMPLATE
+ # Skip if no incident review document
+ if (
+ not incident.incident_review_document
+ or not incident.incident_review_document.resource_id
+ ):
+ continue
# Skip restricted incidents
if incident.visibility == Visibility.restricted:
@@ -282,20 +289,20 @@ def incident_report_weekly(db_session: Session, project: Project):
file_id=incident.incident_review_document.resource_id,
mime_type="text/plain",
)
- messages = {
- "role": "user",
- "content": """Given the text of the security post-incident review document below,
- provide answers to the following questions:
+ prompt = f"""
+ Given the text of the security post-incident review document below,
+ provide answers to the following questions in a paragraph format.
+ Do not include the questions in your response.
1. What is the summary of what happened?
2. What were the overall risk(s)?
3. How were the risk(s) mitigated?
4. How was the incident resolved?
5. What are the follow-up tasks?
- """
- + pir_doc,
- }
- response = ai_plugin.instance.chat_completion(messages)
+ {pir_doc}
+ """
+
+ response = ai_plugin.instance.chat_completion(prompt=prompt)
summary = response["choices"][0]["message"]["content"]
item = {
diff --git a/src/dispatch/plugins/dispatch_slack/config.py b/src/dispatch/plugins/dispatch_slack/config.py
index 7341cec283d5..541d6aa678a8 100644
--- a/src/dispatch/plugins/dispatch_slack/config.py
+++ b/src/dispatch/plugins/dispatch_slack/config.py
@@ -151,3 +151,8 @@ class SlackConversationConfiguration(SlackConfiguration):
title="List Workflows Command String",
description="Defines the string used to list all available workflows. Must match what is defined in Slack",
)
+ slack_command_create_task: str = Field(
+ "/dispatch-create-task",
+ title="Create Task Command String",
+ description="Defines the string used to create a task. Must match what is defined in Slack.",
+ )
diff --git a/src/dispatch/plugins/dispatch_slack/incident/enums.py b/src/dispatch/plugins/dispatch_slack/incident/enums.py
index 3f5be38faa4d..2acc336b88ac 100644
--- a/src/dispatch/plugins/dispatch_slack/incident/enums.py
+++ b/src/dispatch/plugins/dispatch_slack/incident/enums.py
@@ -76,6 +76,15 @@ class ReportExecutiveBlockIds(DispatchEnum):
next_steps = "report-executive-next-steps"
+class CreateTaskBlockIds(DispatchEnum):
+ assignee_select = "create-task-assignee-select"
+ description = "create-task-description"
+
+
+class CreateTaskActionIds(DispatchEnum):
+ submit = "create-task-submit"
+
+
class IncidentUpdateActions(DispatchEnum):
submit = "incident-update-submit"
project_select = "incident-update-project-select"
diff --git a/src/dispatch/plugins/dispatch_slack/incident/interactive.py b/src/dispatch/plugins/dispatch_slack/incident/interactive.py
index c14c4fd0a360..587faf6ec9bc 100644
--- a/src/dispatch/plugins/dispatch_slack/incident/interactive.py
+++ b/src/dispatch/plugins/dispatch_slack/incident/interactive.py
@@ -77,6 +77,8 @@
AddTimelineEventActions,
AssignRoleActions,
AssignRoleBlockIds,
+ CreateTaskActionIds,
+ CreateTaskBlockIds,
EngageOncallActionIds,
EngageOncallActions,
EngageOncallBlockIds,
@@ -134,7 +136,7 @@
from dispatch.tag import service as tag_service
from dispatch.task import service as task_service
from dispatch.task.enums import TaskStatus
-from dispatch.task.models import Task
+from dispatch.task.models import Task, TaskCreate
from dispatch.ticket import flows as ticket_flows
from dispatch.messaging.strings import reminder_select_values
from dispatch.plugins.dispatch_slack.messaging import build_unexpected_error_message
@@ -217,6 +219,7 @@ def configure(config):
app.command(config.slack_command_add_timeline_event, middleware=middleware)(
handle_add_timeline_event_command
)
+ app.command(config.slack_command_create_task, middleware=middleware)(handle_create_task_command)
app.event(
event="reaction_added",
@@ -599,6 +602,72 @@ def handle_list_tasks_command(
)
+def draw_task_message(
+ channel_id: str, client: WebClient, first_open: bool, task: Task, thread_id: int
+):
+ """Draws a task message in a Slack channel.
+
+ Args:
+ channel_id (str): The channel id.
+ client (WebClient): The Slack client.
+ first_open (bool): Whether this is the first time the message is being drawn.
+ task (Task): The task to draw.
+ thread_id (int): The thread id of the task message.
+
+ Overwrites the existing message if it already exists.
+ """
+ button_text = "Resolve" if task.status == TaskStatus.open else "Re-open"
+ action_type = "resolve" if task.status == TaskStatus.open else "reopen"
+
+ # If this is the first time the message is being drawn, we post a new message.
+ if first_open:
+ result = client.chat_postMessage(
+ text=f"*<{task.creator.individual.weblink}|{task.creator.individual.name}>* created a new task.",
+ channel=channel_id,
+ )
+ thread_id = result.data.get("ts")
+
+ button_metadata = TaskMetadata(
+ type=IncidentSubjects.incident,
+ action_type=action_type,
+ organization_slug=task.project.organization.slug,
+ id=task.incident.id,
+ task_id=task.id,
+ project_id=task.project.id,
+ resource_id=task.resource_id,
+ channel_id=channel_id,
+ thread_id=thread_id,
+ ).json()
+
+ assignees = [f"<{a.individual.weblink}|{a.individual.name}>" for a in task.assignees]
+ blocks = {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": f"*<{task.creator.individual.weblink}|{task.creator.individual.name}>* created a new task.",
+ },
+ "fields": [
+ {"type": "mrkdwn", "text": "*Assignees:*"},
+ {"type": "mrkdwn", "text": "*Description:*"},
+ {
+ "type": "mrkdwn",
+ "text": ", ".join(assignees),
+ },
+ {"type": "plain_text", "text": task.description},
+ ],
+ "accessory": {
+ "type": "button",
+ "text": {"type": "plain_text", "text": button_text},
+ "style": "primary",
+ "value": button_metadata,
+ "action_id": TaskNotificationActionIds.update_status,
+ },
+ }
+
+ # Update the message with the task details and resolve/re-open button.
+ client.chat_update(channel=channel_id, ts=thread_id, blocks=[blocks])
+
+
def draw_task_modal(
channel_id: str,
client: WebClient,
@@ -1514,6 +1583,123 @@ def handle_assign_role_submission_event(
)
+def handle_create_task_command(
+ ack: Ack,
+ body,
+ dict,
+ client: WebClient,
+ context: BoltContext,
+ db_session: Session,
+) -> None:
+ """Displays a modal for task creation."""
+ ack()
+ if context["subject"].type == CaseSubjects.case:
+ modal = Modal(
+ title="Invalid Command",
+ close="Close",
+ blocks=[Section(text="Create Task command is not currently available for cases.")],
+ ).build()
+ return client.views_open(trigger_id=body["trigger_id"], view=modal)
+
+ participants = participant_service.get_all_by_incident_id(
+ db_session=db_session, incident_id=context["subject"].id
+ )
+
+ incident = incident_service.get(db_session=db_session, incident_id=context["subject"].id)
+
+ contact_plugin = plugin_service.get_active_instance(
+ db_session=db_session, project_id=incident.project.id, plugin_type="contact"
+ )
+ if not contact_plugin:
+ modal = Modal(
+ title="Plugin Not Enabled",
+ close="Close",
+ blocks=[Section(text="Contact plugin is not enabled. Unable to list participants.")],
+ ).build()
+ return client.views_open(trigger_id=body["trigger_id"], view=modal)
+
+ active_participants = [p for p in participants if p.active_roles]
+ participant_list = []
+
+ for participant in active_participants:
+ participant_email = participant.individual.email
+ participant_info = contact_plugin.instance.get(participant_email, db_session=db_session)
+ participant_name = participant_info.get("fullname", participant.individual.email)
+ participant_list.append({"text": participant_name, "value": participant_email})
+
+ blocks = [
+ static_select_block(
+ label="Assignee",
+ block_id=CreateTaskBlockIds.assignee_select,
+ placeholder="Select Assignee",
+ options=participant_list,
+ ),
+ Input(
+ label="Task Description",
+ element=PlainTextInput(placeholder="Task description", multiline=True),
+ block_id=CreateTaskBlockIds.description,
+ ),
+ ]
+
+ modal = Modal(
+ title="Create Task",
+ blocks=blocks,
+ submit="Create",
+ close="Close",
+ callback_id=CreateTaskActionIds.submit,
+ private_metadata=context["subject"].json(),
+ ).build()
+ client.views_open(trigger_id=body["trigger_id"], view=modal)
+
+
+def ack_create_task_submission_event(ack: Ack) -> None:
+ """Handles task creation acknowledgment."""
+ modal = Modal(
+ title="Create Task", close="Close", blocks=[Section(text="Creating task...")]
+ ).build()
+ ack(response_action="update", view=modal)
+
+
+@app.view(
+ CreateTaskActionIds.submit,
+ middleware=[action_context_middleware, db_middleware, user_middleware, modal_submit_middleware],
+)
+def handle_create_task_submission_event(
+ ack: Ack,
+ client: WebClient,
+ context: BoltContext,
+ db_session: Session,
+ form_data: dict,
+ user: DispatchUser,
+) -> None:
+ """Handles the create task submission."""
+ ack()
+
+ participant_email = form_data.get(CreateTaskBlockIds.assignee_select).get("value", "")
+ assignee = participant_service.get_by_incident_id_and_email(
+ db_session=db_session, incident_id=context["subject"].id, email=participant_email
+ )
+ creator = participant_service.get_by_incident_id_and_email(
+ db_session=db_session, incident_id=context["subject"].id, email=user.email
+ )
+ incident = incident_service.get(db_session=db_session, incident_id=context["subject"].id)
+
+ task_in = TaskCreate(
+ assignees=[ParticipantUpdate.from_orm(assignee)],
+ creator=ParticipantUpdate.from_orm(creator),
+ description=form_data.get(CreateTaskBlockIds.description, ""),
+ incident=IncidentRead.from_orm(incident),
+ )
+ task = task_service.create(db_session=db_session, task_in=task_in)
+ draw_task_message(
+ channel_id=incident.conversation.channel_id,
+ client=client,
+ task=task,
+ first_open=True,
+ thread_id=None,
+ )
+
+
def handle_engage_oncall_command(
ack: Ack,
body: dict,
@@ -2529,18 +2715,25 @@ def handle_update_task_status_button_click(
incident_id=context["subject"].id,
)
- tasks = task_service.get_all_by_incident_id(
- db_session=db_session,
- incident_id=context["subject"].id,
- )
-
- draw_task_modal(
- channel_id=button.channel_id,
- client=client,
- first_open=False,
- view_id=body["view"]["id"],
- tasks=tasks,
- )
+ if not button.thread_id:
+ # we are in a modal
+ draw_task_modal(
+ channel_id=button.channel_id,
+ client=client,
+ first_open=False,
+ view_id=body["view"]["id"],
+ tasks=tasks,
+ )
+ else:
+ # We are in a message
+ task = task_service.get(db_session=db_session, task_id=button.task_id)
+ draw_task_message(
+ channel_id=button.channel_id,
+ client=client,
+ task=task,
+ first_open=False,
+ thread_id=button.thread_id,
+ )
@app.action(RemindAgainActions.submit, middleware=[select_context_middleware, db_middleware])
diff --git a/src/dispatch/plugins/dispatch_slack/messaging.py b/src/dispatch/plugins/dispatch_slack/messaging.py
index a78b1ff4e549..5cae126d9a70 100644
--- a/src/dispatch/plugins/dispatch_slack/messaging.py
+++ b/src/dispatch/plugins/dispatch_slack/messaging.py
@@ -4,6 +4,7 @@
:copyright: (c) 2019 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
"""
+
import logging
from typing import Any, List, Optional
@@ -129,6 +130,10 @@ def get_incident_conversation_command_message(
"response_type": "ephemeral",
"text": "Fetching the list of workflows...",
},
+ config.slack_command_create_task: {
+ "response_type": "ephemeral",
+ "text": "Opening a dialog to create a new incident task...",
+ },
}
return command_messages.get(command_string, default)
diff --git a/src/dispatch/plugins/dispatch_slack/models.py b/src/dispatch/plugins/dispatch_slack/models.py
index 8f75591540d2..3b1b3c853f0f 100644
--- a/src/dispatch/plugins/dispatch_slack/models.py
+++ b/src/dispatch/plugins/dispatch_slack/models.py
@@ -47,6 +47,7 @@ class SubjectMetadata(BaseModel):
project_id: Optional[str]
channel_id: Optional[str]
+ thread_id: Optional[str]
class EngagementMetadata(SubjectMetadata):
diff --git a/src/dispatch/static/dispatch/package-lock.json b/src/dispatch/static/dispatch/package-lock.json
index 724803f941b4..cfb0fd9c2a22 100644
--- a/src/dispatch/static/dispatch/package-lock.json
+++ b/src/dispatch/static/dispatch/package-lock.json
@@ -716,19 +716,6 @@
}
}
},
- "node_modules/@formkit/themes/node_modules/@formkit/core": {
- "version": "1.6.7",
- "resolved": "https://registry.npmjs.org/@formkit/core/-/core-1.6.7.tgz",
- "integrity": "sha512-wEoWK7crcCPRV5KJfEGLjjIS+qwbuD8I5Ur0zTtKRQrdO4oRL6kVoubxQOpgnq1l8sWfcRY8Wpf22Wna2LD20Q==",
- "dependencies": {
- "@formkit/utils": "1.6.7"
- }
- },
- "node_modules/@formkit/themes/node_modules/@formkit/utils": {
- "version": "1.6.7",
- "resolved": "https://registry.npmjs.org/@formkit/utils/-/utils-1.6.7.tgz",
- "integrity": "sha512-aU3CDLzCkC5Dnx6iS3swbsIbys7E+2VOaLWFRnS7wk7kFa8EnENi67qc2E2KFE05RT4UCEAIYMAQY6wvek29gA=="
- },
"node_modules/@formkit/utils": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/@formkit/utils/-/utils-1.6.7.tgz",
@@ -763,30 +750,6 @@
"vue": "^3.4.0"
}
},
- "node_modules/@formkit/vue/node_modules/@formkit/themes": {
- "version": "1.6.6",
- "resolved": "https://registry.npmjs.org/@formkit/themes/-/themes-1.6.6.tgz",
- "integrity": "sha512-/wIgVA6ndEo+HRYATw5hNdQbH4wCUgru8RMVnfU56KqC0Tb+bJPxpb2n2l/S6jAe71GSNm2hrlm4JzMTpC6sNA==",
- "dependencies": {
- "@formkit/core": "1.6.6"
- },
- "peerDependencies": {
- "tailwindcss": "^3.2.0",
- "unocss": "0.x.x",
- "windicss": "^3.0.0"
- },
- "peerDependenciesMeta": {
- "tailwindcss": {
- "optional": true
- },
- "unocss": {
- "optional": true
- },
- "windicss": {
- "optional": true
- }
- }
- },
"node_modules/@humanwhocodes/config-array": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
@@ -1433,9 +1396,9 @@
}
},
"node_modules/@tiptap/core": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.7.3.tgz",
- "integrity": "sha512-6b62isitaWRX6cR6V5x4O9+1lgCpoTNRrSegWwBrE1OGDHcGwdTZuzdNIbjLZ9k3qs4tXl49WKXHIXK44RDOIw==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.7.4.tgz",
+ "integrity": "sha512-1VTQdNQChgxdVC8+b8QEW6cUxPSD9EDTzg9YRSLWtTtUDQ09sRSVs7eHIn1LcRHVs6PwcAsNgKE4FSjBw0sRlg==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1445,9 +1408,9 @@
}
},
"node_modules/@tiptap/extension-blockquote": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.7.3.tgz",
- "integrity": "sha512-onUThBo5XoNB7bFPI41WYNVbhX51TQDdymqEEJ0yS+0kqYMLOGxK5rylj1p+8SfpV+AIsrl5BSccijy1N7afKA==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.7.4.tgz",
+ "integrity": "sha512-N6rhiwVRpsxRz4Qt8cvKgpqjBxdi8GTbU/v2MV/BTONWb7Ch9ajv9HO6koEDdOeb77JVhpWztzYysTjJo2KTyQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1457,9 +1420,9 @@
}
},
"node_modules/@tiptap/extension-bold": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.7.3.tgz",
- "integrity": "sha512-jc38r/1YSix20s47qXwOAzVYmxVwySS5oTsNr9T5pFp0NWSFSwYsAn2L1Ko4BcI9nJ8VDgnGGg/JjkurGM3SCw==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.7.4.tgz",
+ "integrity": "sha512-Yq2ErekgpsOLCGYfQc1H3tUdmecKHDBWTPesVtqg0ct/3ZbKskhFoR6bPQWZH/ZRXQb1ARA+aMp/iqM/hqm+KQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1469,9 +1432,9 @@
}
},
"node_modules/@tiptap/extension-bubble-menu": {
- "version": "2.6.6",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.6.6.tgz",
- "integrity": "sha512-IkfmlZq67aaegym5sBddBc/xXWCArxn5WJEl1oxKEayjQhybKSaqI7tk0lOx/x7fa5Ml1WlGpCFh+KKXbQTG0g==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.7.4.tgz",
+ "integrity": "sha512-Vx9gFFgz/6R+FIzOCbUNFOJAy4lKr/vbG2l1Ujn4PKber8OWV1JUHXF5MKhMKUupr+Yvu5h3ctBcOe1tZt/NIA==",
"dependencies": {
"tippy.js": "^6.3.7"
},
@@ -1480,14 +1443,14 @@
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
- "@tiptap/core": "^2.6.6",
- "@tiptap/pm": "^2.6.6"
+ "@tiptap/core": "^2.7.0",
+ "@tiptap/pm": "^2.7.0"
}
},
"node_modules/@tiptap/extension-bullet-list": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.7.3.tgz",
- "integrity": "sha512-ctcuqyWavLSgzQzRFAzubCdTbmE8p2jZWAe2nDNCfSsNDGKlqMnQVswj+qTQhlFEvJZh0AXs1N3eKA2ezNI+Yw==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.7.4.tgz",
+ "integrity": "sha512-uO08vui6uEgLEgLIYJSLrUb2An3u0If8XRW0Z0kB13zpwQ9pq0S1JOc0KwPTDPeIrgLQ7OOH87/bM9rGUFC3AQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1497,9 +1460,9 @@
}
},
"node_modules/@tiptap/extension-code": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.7.3.tgz",
- "integrity": "sha512-3QsUk7ke1GDntVKRu3BJeZhdjg1bONuJlfcsNLqjK+Y8LYjn8Y7MPCX4X3+DB5HuMUPT6Mu1xUNp1LMZq86LZg==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.7.4.tgz",
+ "integrity": "sha512-GB7gR8tV1fz+70wcSN+hLVm1qET/YmkxIaOfczHEOLLH7Td0C3kyQ5Q+eQ8KN0Ds7NBHFXn3zn051Q8gk9+5tw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1509,9 +1472,9 @@
}
},
"node_modules/@tiptap/extension-code-block": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.7.3.tgz",
- "integrity": "sha512-WrF3X6lD8IXIWC7E5tMWL+hCMzVop3PQxFFaYi8Ovk6q3Jd8pnOtKugQp1lWcW72rek8v20LEnl1u7BkWal2TQ==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.7.4.tgz",
+ "integrity": "sha512-jRKVAEdy3G0SMphWXCTk9SnMuTmJE6blXglU66H89j9R+hG+G0dHfOWhlubhUy6nI2BLy8jJ/isnOzg97iZuQw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1522,9 +1485,9 @@
}
},
"node_modules/@tiptap/extension-document": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.7.3.tgz",
- "integrity": "sha512-gL+NhS3r5T5B3DAnENis8VliFooOcpnp5diqmpiNPeQaO04GRQZCsFGmk/b/xRyEI8j80m+YtGYbpJodlvsTPw==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.7.4.tgz",
+ "integrity": "sha512-Vsq9e/uW7k/5l1K9bCmuccBSrHhK3i0fbfnTp33G1byTCizheUo3UWFl8MSDammlhRkW/soIZFGdflsj5AJWog==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1534,9 +1497,9 @@
}
},
"node_modules/@tiptap/extension-dropcursor": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.7.3.tgz",
- "integrity": "sha512-LmS31dwrdjg30g61aU6735bfWZyfdwOO+GTdXPkoDeL3b3SNAMg39Gdb0UyI7CpmJhTWgZvst7AOQXht0DQcfw==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.7.4.tgz",
+ "integrity": "sha512-hhE0RTluEEFxfqh8/jpmQRgy5AipTcd+WMK5cBw2zCa9If/qhY0EvysydEPwDU7yDEa13NDqV63x5oN9GKv2pg==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1547,9 +1510,9 @@
}
},
"node_modules/@tiptap/extension-floating-menu": {
- "version": "2.6.6",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.6.6.tgz",
- "integrity": "sha512-lPkESOfAUxgmXRiNqUU23WSyja5FUfSWjsW4hqe+BKNjsUt1OuFMEtYJtNc+MCGhhtPfFvM3Jg6g9jd6g5XsLQ==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.7.4.tgz",
+ "integrity": "sha512-EGDq9eVT/fIJo6AOvXtRIWurAbGx0Fv2hIjQobX8AmCoOp3KjYalbQPbo1d3cyqanXG7sNRhBehIXc8Nv+AUWA==",
"dependencies": {
"tippy.js": "^6.3.7"
},
@@ -1558,14 +1521,14 @@
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
- "@tiptap/core": "^2.6.6",
- "@tiptap/pm": "^2.6.6"
+ "@tiptap/core": "^2.7.0",
+ "@tiptap/pm": "^2.7.0"
}
},
"node_modules/@tiptap/extension-gapcursor": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.7.3.tgz",
- "integrity": "sha512-dtrh2ulAu9F9CsytNwhaovx79XUZzhJxgweSWlZapzR77tridSMAq7OgRL+bMVBy2JDvjyUNPdm2DkNELBofcQ==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.7.4.tgz",
+ "integrity": "sha512-1HTaCR6kcw5PvUJWEGKQ/Eh2HPXUmN6k1LK0rgJC4CxqiFxNNnPKGED9LcYheJbyMYk0Fz3rtaulxd3ipdIOsQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1576,9 +1539,9 @@
}
},
"node_modules/@tiptap/extension-hard-break": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.7.3.tgz",
- "integrity": "sha512-HtnjmQfbjTDsrPzfRDmzH4fZvm5xZ0qmYQyRkfV4tFrD1vx6Wb2hmpfcuiBYuNVEP6OmOzG9pQV98zhfSHEcjg==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.7.4.tgz",
+ "integrity": "sha512-ut81vNPQyDYi8LhOzPfFZGnPToYGQbBR6bvFE0e8WY9sRfvUZHr/GvkMjPuWuA8M5sBMqS5cLNyqPrI8h4R7Jg==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1588,9 +1551,9 @@
}
},
"node_modules/@tiptap/extension-heading": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.7.3.tgz",
- "integrity": "sha512-Wq1pqUCTgFk3MddlsCZuNq9ROMctGlXGagyRcGpPtb5BJ3Ane5Njyg0lZjgGbr6CW1F3W4gy1xRKNVHXFjZ51w==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.7.4.tgz",
+ "integrity": "sha512-ZLFHhFvmDD6YKPf4wftZd4wtT510yHjzG90A14wyKCpm0Bq9wOYzx4Q+owvlp5vMwenqHuq3KGz4Sf3w6N5gkw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1600,9 +1563,9 @@
}
},
"node_modules/@tiptap/extension-history": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.7.3.tgz",
- "integrity": "sha512-sXU1R6jvd16h0IPRroBhAzeXAMFNSldJ4vhX7dxlhWTKQHeAh1Mvuye+o9oX3oNnCm6bN++j2n/CxuZoJWOSbQ==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.7.4.tgz",
+ "integrity": "sha512-xRgGXNrtjDGVOeLeZzGqw4/OtwIoloLU3QLn/qaOggVS7jr1HVTqMHw4nZVcUJfnB/UQ90yl53hBKZ8z3AxcCA==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1613,9 +1576,9 @@
}
},
"node_modules/@tiptap/extension-horizontal-rule": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.7.3.tgz",
- "integrity": "sha512-0nXP1mrZ9VQLwtzHVbyzNz2ICnwEdM6l7oDbPlP8atH/kIRpINq/SiBr2wiMnU4nHnT2SacOfuk8MUEU1DBikA==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.7.4.tgz",
+ "integrity": "sha512-6mKkiGK9O+eGDeewpUHGyM2Xjlp69Oy+N/0o5zdzfN84YqVPqLV+Y7ub6fMxZUvmRt6L0kuv/ZoDoxeUk+QNKg==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1626,9 +1589,9 @@
}
},
"node_modules/@tiptap/extension-italic": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.7.3.tgz",
- "integrity": "sha512-qMX5LjMTdPpSDp4VIpSOY0d6bB6m4CJepGlMVrQEfUEj9uMPZZxD0cME+63r/J4yIrmMCR+GJyjOu5erdYp3JA==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.7.4.tgz",
+ "integrity": "sha512-j/86hNMRd2PbJX6DOs7CbrYgFJSXvZMnWkYRRol7XEELvEuIWoAgyJrW5HkDbVxmGfWPnLlqsoW7iTHml7P+Bg==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1638,9 +1601,9 @@
}
},
"node_modules/@tiptap/extension-list-item": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.7.3.tgz",
- "integrity": "sha512-xCb4WjeBn3IekWyofhc9WnxYROv9oq7KM8tMqVaMNfSfSzd6wfoijzFBeL2da1B5Pwl1tJM6MqcH70zmytMJZw==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.7.4.tgz",
+ "integrity": "sha512-2EiXAtkZdCUHCfYRQsslniQhUzvo8zEm+M6JHcsIRBRf27iE+nXrD6jq1WH2ZIUNLDUs4JsJhtc89aoSYkJGKw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1650,9 +1613,9 @@
}
},
"node_modules/@tiptap/extension-ordered-list": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.7.3.tgz",
- "integrity": "sha512-J7PbM1tQSNpAGQ9Ft9Qm2oKQDE4J6uZv711ZwQgWBVne7CEu1zfD/ezlRe4yiw5XjeD0B91CP4KNRRKefePAjA==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.7.4.tgz",
+ "integrity": "sha512-Y7fnw3lTyOd1h6t5hKSkYqbJXteafIviRdmrQ/ERRayojV934DjRPBeMQnYcArE6nI178/wLI9YMt1HSMJklRw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1662,9 +1625,9 @@
}
},
"node_modules/@tiptap/extension-paragraph": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.7.3.tgz",
- "integrity": "sha512-jcvcsN1JEYxPYQ3IgeJ7sUr3gDlIoVm9GXIV83fiF8KWw30M1jWfYJ6zgef8e5wB7d/NLhc3yhVrRk4R6P4ApQ==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.7.4.tgz",
+ "integrity": "sha512-Pv3zsyuE+RItlkZVFcjcnz+Omp/UCEO03n9daeHljMUl7Rt775fXtcTNKPqO65f2B2MPBxrSdJpTsoMK0bbcjA==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1687,9 +1650,9 @@
}
},
"node_modules/@tiptap/extension-strike": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.7.3.tgz",
- "integrity": "sha512-X6ybvtt/F8usRoq9MjJcTAnr0pboi3FjqZtMZOKrX1oS0bt89FcxmbymP/5VMGDLxxxzEfrRqttvZ4s/z+HOow==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.7.4.tgz",
+ "integrity": "sha512-ELMFUCE9MlF0qsGzHJl0AxzGUVyS9rglk6pzidoB0iU1LuzUa/K1el5ID2ksSFdq2+STK17rOWQxUiv3X8C7gw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1699,9 +1662,9 @@
}
},
"node_modules/@tiptap/extension-text": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.7.3.tgz",
- "integrity": "sha512-p1ic3rxbY8Z+1W2e/W4qXxT9zh0x2DjY2bUq+bNTvAbjOw2D9XhE4B03vhRVvNOgQdVXqJX638fK8P34ndrV1A==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.7.4.tgz",
+ "integrity": "sha512-1bF9LdfUumqXOz0A6xnOo7UHx+YLshxjMnjoMXjv7cOFOjdHbLmwKNTKGd2ltoCy3bSajoCPhPZL2Id89XDZfQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
@@ -1711,9 +1674,9 @@
}
},
"node_modules/@tiptap/pm": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.7.3.tgz",
- "integrity": "sha512-qMUMypHjxq7n37u4iBTbAfoWf38eDi5I13l2U3a3UKt/mJBABusf2aYq4NfkY5vQQn48HbZ3Hj+TygrdPklQwQ==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.7.4.tgz",
+ "integrity": "sha512-YXjgPLN6/msTkKakuzgBm6Dd/Li3ORtysSki3fHnOFcy8R4c5JZLkYECQk6aJHsxvl/vGvNgaJy5yCDbhnaTAg==",
"dependencies": {
"prosemirror-changeset": "^2.2.1",
"prosemirror-collab": "^1.3.1",
@@ -1740,30 +1703,30 @@
}
},
"node_modules/@tiptap/starter-kit": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.7.3.tgz",
- "integrity": "sha512-GZd/zzdGZV8QtbIGurnS8K9WVxsOH9sdioMVQOOt8jMuETYqrEVoranN13WStbD/XsgokDE2KkvCtztqM+IKDA==",
- "dependencies": {
- "@tiptap/core": "^2.7.3",
- "@tiptap/extension-blockquote": "^2.7.3",
- "@tiptap/extension-bold": "^2.7.3",
- "@tiptap/extension-bullet-list": "^2.7.3",
- "@tiptap/extension-code": "^2.7.3",
- "@tiptap/extension-code-block": "^2.7.3",
- "@tiptap/extension-document": "^2.7.3",
- "@tiptap/extension-dropcursor": "^2.7.3",
- "@tiptap/extension-gapcursor": "^2.7.3",
- "@tiptap/extension-hard-break": "^2.7.3",
- "@tiptap/extension-heading": "^2.7.3",
- "@tiptap/extension-history": "^2.7.3",
- "@tiptap/extension-horizontal-rule": "^2.7.3",
- "@tiptap/extension-italic": "^2.7.3",
- "@tiptap/extension-list-item": "^2.7.3",
- "@tiptap/extension-ordered-list": "^2.7.3",
- "@tiptap/extension-paragraph": "^2.7.3",
- "@tiptap/extension-strike": "^2.7.3",
- "@tiptap/extension-text": "^2.7.3",
- "@tiptap/pm": "^2.7.3"
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.7.4.tgz",
+ "integrity": "sha512-ALOphzdSZ+ZgOllc0gKxn7iDQ3c3BEBJzc5dQE1pJMeDHrGu/fAGXtffJOyJsVoBGTB14TXK6decMNUUwBApiA==",
+ "dependencies": {
+ "@tiptap/core": "^2.7.4",
+ "@tiptap/extension-blockquote": "^2.7.4",
+ "@tiptap/extension-bold": "^2.7.4",
+ "@tiptap/extension-bullet-list": "^2.7.4",
+ "@tiptap/extension-code": "^2.7.4",
+ "@tiptap/extension-code-block": "^2.7.4",
+ "@tiptap/extension-document": "^2.7.4",
+ "@tiptap/extension-dropcursor": "^2.7.4",
+ "@tiptap/extension-gapcursor": "^2.7.4",
+ "@tiptap/extension-hard-break": "^2.7.4",
+ "@tiptap/extension-heading": "^2.7.4",
+ "@tiptap/extension-history": "^2.7.4",
+ "@tiptap/extension-horizontal-rule": "^2.7.4",
+ "@tiptap/extension-italic": "^2.7.4",
+ "@tiptap/extension-list-item": "^2.7.4",
+ "@tiptap/extension-ordered-list": "^2.7.4",
+ "@tiptap/extension-paragraph": "^2.7.4",
+ "@tiptap/extension-strike": "^2.7.4",
+ "@tiptap/extension-text": "^2.7.4",
+ "@tiptap/pm": "^2.7.4"
},
"funding": {
"type": "github",
@@ -1771,20 +1734,20 @@
}
},
"node_modules/@tiptap/vue-3": {
- "version": "2.6.6",
- "resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-2.6.6.tgz",
- "integrity": "sha512-oTrFF2TznkduLIUKvncOpUnm/Fp8pOQw2xmR4YOVNFWDdzO9O3b+yaiwO1ze3CAHJpZrFT82Sum8UpZn8nCH+Q==",
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-2.7.4.tgz",
+ "integrity": "sha512-Z75XzP7J3yFAB9qNvso8cX/f3R2PjKxGGk53RR2dhUT+Bsa7K5U8k6QB+ANl2RY+1t/p/LkQvaYLe6CBx9t1Ug==",
"dependencies": {
- "@tiptap/extension-bubble-menu": "^2.6.6",
- "@tiptap/extension-floating-menu": "^2.6.6"
+ "@tiptap/extension-bubble-menu": "^2.7.4",
+ "@tiptap/extension-floating-menu": "^2.7.4"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
- "@tiptap/core": "^2.6.6",
- "@tiptap/pm": "^2.6.6",
+ "@tiptap/core": "^2.7.0",
+ "@tiptap/pm": "^2.7.0",
"vue": "^3.0.0"
}
},
@@ -2226,39 +2189,39 @@
}
},
"node_modules/@vue/compiler-core": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.4.tgz",
- "integrity": "sha512-oNwn+BAt3n9dK9uAYvI+XGlutwuTq/wfj4xCBaZCqwwVIGtD7D6ViihEbyYZrDHIHTDE3Q6oL3/hqmAyFEy9DQ==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.10.tgz",
+ "integrity": "sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==",
"dependencies": {
"@babel/parser": "^7.25.3",
- "@vue/shared": "3.5.4",
+ "@vue/shared": "3.5.10",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-dom": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.4.tgz",
- "integrity": "sha512-yP9RRs4BDLOLfldn6ah+AGCNovGjMbL9uHvhDHf5wan4dAHLnFGOkqtfE7PPe4HTXIqE7l/NILdYw53bo1C8jw==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.10.tgz",
+ "integrity": "sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==",
"dependencies": {
- "@vue/compiler-core": "3.5.4",
- "@vue/shared": "3.5.4"
+ "@vue/compiler-core": "3.5.10",
+ "@vue/shared": "3.5.10"
}
},
"node_modules/@vue/compiler-sfc": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.4.tgz",
- "integrity": "sha512-P+yiPhL+NYH7m0ZgCq7AQR2q7OIE+mpAEgtkqEeH9oHSdIRvUO+4X6MPvblJIWcoe4YC5a2Gdf/RsoyP8FFiPQ==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.10.tgz",
+ "integrity": "sha512-to8E1BgpakV7224ZCm8gz1ZRSyjNCAWEplwFMWKlzCdP9DkMKhRRwt0WkCjY7jkzi/Vz3xgbpeig5Pnbly4Tow==",
"dependencies": {
"@babel/parser": "^7.25.3",
- "@vue/compiler-core": "3.5.4",
- "@vue/compiler-dom": "3.5.4",
- "@vue/compiler-ssr": "3.5.4",
- "@vue/shared": "3.5.4",
+ "@vue/compiler-core": "3.5.10",
+ "@vue/compiler-dom": "3.5.10",
+ "@vue/compiler-ssr": "3.5.10",
+ "@vue/shared": "3.5.10",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
- "postcss": "^8.4.44",
+ "postcss": "^8.4.47",
"source-map-js": "^1.2.0"
}
},
@@ -2271,12 +2234,12 @@
}
},
"node_modules/@vue/compiler-ssr": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.4.tgz",
- "integrity": "sha512-acESdTXsxPnYr2C4Blv0ggx5zIFMgOzZmYU2UgvIff9POdRGbRNBHRyzHAnizcItvpgerSKQbllUc9USp3V7eg==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.10.tgz",
+ "integrity": "sha512-hxP4Y3KImqdtyUKXDRSxKSRkSm1H9fCvhojEYrnaoWhE4w/y8vwWhnosJoPPe2AXm5sU7CSbYYAgkt2ZPhDz+A==",
"dependencies": {
- "@vue/compiler-dom": "3.5.4",
- "@vue/shared": "3.5.4"
+ "@vue/compiler-dom": "3.5.10",
+ "@vue/shared": "3.5.10"
}
},
"node_modules/@vue/devtools-api": {
@@ -2285,49 +2248,49 @@
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
},
"node_modules/@vue/reactivity": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.4.tgz",
- "integrity": "sha512-HKKbEuP7tYSGCq4e4nK6ZW6l5hyG66OUetefBp4budUyjvAYsnQDf+bgFzg2RAgnH0CInyqXwD9y47jwJEHrQw==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.10.tgz",
+ "integrity": "sha512-kW08v06F6xPSHhid9DJ9YjOGmwNDOsJJQk0ax21wKaUYzzuJGEuoKNU2Ujux8FLMrP7CFJJKsHhXN9l2WOVi2g==",
"dependencies": {
- "@vue/shared": "3.5.4"
+ "@vue/shared": "3.5.10"
}
},
"node_modules/@vue/runtime-core": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.4.tgz",
- "integrity": "sha512-f3ek2sTA0AFu0n+w+kCtz567Euqqa3eHewvo4klwS7mWfSj/A+UmYTwsnUFo35KeyAFY60JgrCGvEBsu1n/3LA==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.10.tgz",
+ "integrity": "sha512-9Q86I5Qq3swSkFfzrZ+iqEy7Vla325M7S7xc1NwKnRm/qoi1Dauz0rT6mTMmscqx4qz0EDJ1wjB+A36k7rl8mA==",
"dependencies": {
- "@vue/reactivity": "3.5.4",
- "@vue/shared": "3.5.4"
+ "@vue/reactivity": "3.5.10",
+ "@vue/shared": "3.5.10"
}
},
"node_modules/@vue/runtime-dom": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.4.tgz",
- "integrity": "sha512-ofyc0w6rbD5KtjhP1i9hGOKdxGpvmuB1jprP7Djlj0X7R5J/oLwuNuE98GJ8WW31Hu2VxQHtk/LYTAlW8xrJdw==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.10.tgz",
+ "integrity": "sha512-t3x7ht5qF8ZRi1H4fZqFzyY2j+GTMTDxRheT+i8M9Ph0oepUxoadmbwlFwMoW7RYCpNQLpP2Yx3feKs+fyBdpA==",
"dependencies": {
- "@vue/reactivity": "3.5.4",
- "@vue/runtime-core": "3.5.4",
- "@vue/shared": "3.5.4",
+ "@vue/reactivity": "3.5.10",
+ "@vue/runtime-core": "3.5.10",
+ "@vue/shared": "3.5.10",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.4.tgz",
- "integrity": "sha512-FbjV6DJLgKRetMYFBA1UXCroCiED/Ckr53/ba9wivyd7D/Xw9fpo0T6zXzCnxQwyvkyrL7y6plgYhWhNjGxY5g==",
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.10.tgz",
+ "integrity": "sha512-IVE97tt2kGKwHNq9yVO0xdh1IvYfZCShvDSy46JIh5OQxP1/EXSpoDqetVmyIzL7CYOWnnmMkVqd7YK2QSWkdw==",
"dependencies": {
- "@vue/compiler-ssr": "3.5.4",
- "@vue/shared": "3.5.4"
+ "@vue/compiler-ssr": "3.5.10",
+ "@vue/shared": "3.5.10"
},
"peerDependencies": {
- "vue": "3.5.4"
+ "vue": "3.5.10"
}
},
"node_modules/@vue/shared": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.4.tgz",
- "integrity": "sha512-L2MCDD8l7yC62Te5UUyPVpmexhL9ipVnYRw9CsWfm/BGRL5FwDX4a25bcJ/OJSD3+Hx+k/a8LDKcG2AFdJV3BA=="
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.10.tgz",
+ "integrity": "sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ=="
},
"node_modules/@vue/test-utils": {
"version": "2.4.6",
@@ -5466,9 +5429,9 @@
}
},
"node_modules/picocolors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
- "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
+ "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="
},
"node_modules/picomatch": {
"version": "2.3.1",
@@ -5537,9 +5500,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.45",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz",
- "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==",
+ "version": "8.4.47",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
+ "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
"funding": [
{
"type": "opencollective",
@@ -5556,8 +5519,8 @@
],
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.0.1",
- "source-map-js": "^1.2.0"
+ "picocolors": "^1.1.0",
+ "source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
@@ -6170,9 +6133,9 @@
}
},
"node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"engines": {
"node": ">=0.10.0"
}
@@ -6671,9 +6634,9 @@
}
},
"node_modules/vite": {
- "version": "5.4.6",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz",
- "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==",
+ "version": "5.4.8",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
+ "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
"devOptional": true,
"dependencies": {
"esbuild": "^0.21.3",
@@ -7276,15 +7239,15 @@
}
},
"node_modules/vue": {
- "version": "3.5.4",
- "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.4.tgz",
- "integrity": "sha512-3yAj2gkmiY+i7+22A1PWM+kjOVXjU74UPINcTiN7grIVPyFFI0lpGwHlV/4xydDmobaBn7/xmi+YG8HeSlCTcg==",
- "dependencies": {
- "@vue/compiler-dom": "3.5.4",
- "@vue/compiler-sfc": "3.5.4",
- "@vue/runtime-dom": "3.5.4",
- "@vue/server-renderer": "3.5.4",
- "@vue/shared": "3.5.4"
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.10.tgz",
+ "integrity": "sha512-Vy2kmJwHPlouC/tSnIgXVg03SG+9wSqT1xu1Vehc+ChsXsRd7jLkKgMltVEFOzUdBr3uFwBCG+41LJtfAcBRng==",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.10",
+ "@vue/compiler-sfc": "3.5.10",
+ "@vue/runtime-dom": "3.5.10",
+ "@vue/server-renderer": "3.5.10",
+ "@vue/shared": "3.5.10"
},
"peerDependencies": {
"typescript": "*"