Compare commits

...

9 Commits

Author SHA1 Message Date
lebaudantoine
d7e1e8032f 🔧(backend) fix sentry deprecated scope
`sentry_sdk.configure_scope` is deprecated and will
be removed in the next major version.

(commit taken from people by @qbey)
2025-01-14 09:43:33 +01:00
lebaudantoine
a4cd6f4dfb 🎨(backend) removed unused imports
Please challenge this commit.
I feel these imports aren't used in this migration file.
2025-01-14 09:43:33 +01:00
lebaudantoine
9ccfb3183a 🎨(backend) remove redundant parentheses
These parentheses seem useless to me, remove them.
2025-01-14 09:43:33 +01:00
lebaudantoine
8655ffa8c2 ✏️(typo) fix minor typos
Found typos while working on the project using my IDE, fixed them.
Sorry for the big commit.

Not a big deal, can totally drop this commit.
2025-01-14 09:43:33 +01:00
lebaudantoine
194ac8e856 🎨(backend) remove unused variable
output seems to be redefined few lines after.
Please feel free to challenge this change.
2025-01-14 09:43:33 +01:00
lebaudantoine
bc67d1b978 🚨(backend) fix Django deprecation warning for format_html
Resolved RemovedInDjango60Warning by ensuring format_html() is called
with required arguments, addressing compatibility with Django 6.0.

/!\ Fix by
Claude, need real-world testing. Linterand tests pass.
2025-01-14 09:43:33 +01:00
lebaudantoine
a32036ba8c 🚨(backend) fix Django UnorderedObjectListWarning on User
Found this solution googling on Stack Overflow.
Without a default ordering on a model, Django raises a warning, that
pagination may yield inconsistent results.

Please feel free to challenge my fix.
2025-01-14 09:43:33 +01:00
lebaudantoine
30aab3fb9d 🚨(backend) fix Django deprecation warning in Factory
_after_postgeneration method will stop saving the instance after
postgeneration hooks in the next major release.

Solved using Claude, feel free to challenge my fix.
2025-01-13 23:07:27 +01:00
lebaudantoine
954ae0e510 🚨(backend) fix CheckConstraint deprecation warning
Fix a deprecation warning from Django, which appears while running
tests. 'check' argument is replaced by 'condition'.
2025-01-13 23:07:27 +01:00
39 changed files with 92 additions and 70 deletions

View File

@@ -197,7 +197,7 @@ and this project adheres to
- 🛂(frontend) match email if no existing user matches the sub
- 🐛(backend) gitlab oicd userinfo endpoint #232
- 🛂(frontend) redirect to the OIDC when private doc and unauthentified #292
- 🛂(frontend) redirect to the OIDC when private doc and unauthenticated #292
- ♻️(backend) getting list of document versions available for a user #258
- 🔧(backend) fix configuration to avoid different ssl warning #297
- 🐛(frontend) fix editor break line not working #302
@@ -326,7 +326,7 @@ and this project adheres to
- ⚡️(e2e) unique login between tests (#80)
- ⚡️(CI) improve e2e job (#86)
- ♻️(frontend) improve the error and message info ui (#93)
- ✏️(frontend) change all occurences of pad to doc (#99)
- ✏️(frontend) change all occurrences of pad to doc (#99)
## Fixed

View File

@@ -6,7 +6,7 @@ Whenever we are cooking a new release (e.g. `4.18.1`) we should follow a standar
2. Bump the release number for backend project, frontend projects, and Helm files:
- for backend, update the version number by hand in `pyproject.toml`,
- for each projects (`src/frontend`, `src/frontend/apps/*`, `src/frontend/packages/*`, `src/mail`), run `yarn version --new-version --no-git-tag-version 4.18.1` in their directory. This will update their `package.json` for you,
- for each project (`src/frontend`, `src/frontend/apps/*`, `src/frontend/packages/*`, `src/mail`), run `yarn version --new-version --no-git-tag-version 4.18.1` in their directory. This will update their `package.json` for you,
- for Helm, update Docker image tag in files located at `src/helm/env.d` for both `preprod` and `production` environments:
```yaml

View File

@@ -140,6 +140,7 @@ class UserViewSet(
permission_classes = [permissions.IsSelf]
queryset = models.User.objects.all()
serializer_class = serializers.UserSerializer
ordering = ["-created_at"]
def get_queryset(self):
"""
@@ -629,7 +630,7 @@ class DocumentViewSet(
nginx.ingress.kubernetes.io/auth-url annotation to understand how the Nginx ingress
is configured to do this.
Based on the original url and the logged in user, we must decide if we authorize Nginx
Based on the original url and the logged-in user, we must decide if we authorize Nginx
to let this request go through (by returning a 200 code) or if we block it (by returning
a 403 error). Note that we return 403 errors without any further details for security
reasons.
@@ -834,7 +835,7 @@ class DocumentAccessViewSet(
serializer_class = serializers.DocumentAccessSerializer
def perform_create(self, serializer):
"""Add a new access to the document and send an email to the new added user."""
"""Add new access to the document and email the new added user."""
access = serializer.save()
language = self.request.headers.get("Content-Language", "en-us")
@@ -846,7 +847,7 @@ class DocumentAccessViewSet(
)
def perform_update(self, serializer):
"""Update an access to the document and notify the collaboration server."""
"""Update access to the document and notify the collaboration server."""
access = serializer.save()
access_user_id = None
@@ -859,7 +860,7 @@ class DocumentAccessViewSet(
)
def perform_destroy(self, instance):
"""Delete an access to the document and notify the collaboration server."""
"""Delete access to the document and notify the collaboration server."""
instance.delete()
# Notify collaboration server about the access removed
@@ -1098,7 +1099,7 @@ class InvitationViewset(
return queryset
def perform_create(self, serializer):
"""Save invitation to a document then send an email to the invited user."""
"""Save invitation to a document then email the invited user."""
invitation = serializer.save()
language = self.request.headers.get("Content-Language", "en-us")

View File

@@ -2,7 +2,7 @@
from django.urls import path
from mozilla_django_oidc.urls import urlpatterns as mozzila_oidc_urls
from mozilla_django_oidc.urls import urlpatterns as mozilla_oidc_urls
from .views import OIDCLogoutCallbackView, OIDCLogoutView
@@ -14,5 +14,5 @@ urlpatterns = [
OIDCLogoutCallbackView.as_view(),
name="oidc_logout_callback",
),
*mozzila_oidc_urls,
*mozilla_oidc_urls,
]

View File

@@ -19,6 +19,7 @@ class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.User
skip_postgeneration_save = True
sub = factory.Sequence(lambda n: f"user{n!s}")
email = factory.Faker("email")
@@ -36,6 +37,8 @@ class UserFactory(factory.django.DjangoModelFactory):
if create and (extracted is True):
UserDocumentAccessFactory(user=self, role="owner")
self.save()
@factory.post_generation
def with_owned_template(self, create, extracted, **kwargs):
"""
@@ -45,6 +48,8 @@ class UserFactory(factory.django.DjangoModelFactory):
if create and (extracted is True):
UserTemplateAccessFactory(user=self, role="owner")
self.save()
class DocumentFactory(factory.django.DjangoModelFactory):
"""A factory to create documents"""

View File

@@ -1,7 +1,5 @@
# Generated by Django 5.0.3 on 2024-05-28 20:29
import django.contrib.auth.models
import django.core.validators
import django.db.models.deletion
import timezone_field.fields
import uuid
@@ -145,7 +143,7 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='documentaccess',
constraint=models.CheckConstraint(check=models.Q(models.Q(('team', ''), ('user__isnull', False)), models.Q(('team__gt', ''), ('user__isnull', True)), _connector='OR'), name='check_document_access_either_user_or_team', violation_error_message='Either user or team must be set, not both.'),
constraint=models.CheckConstraint(condition=models.Q(models.Q(('team', ''), ('user__isnull', False)), models.Q(('team__gt', ''), ('user__isnull', True)), _connector='OR'), name='check_document_access_either_user_or_team', violation_error_message='Either user or team must be set, not both.'),
),
migrations.AddConstraint(
model_name='invitation',
@@ -161,6 +159,6 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='templateaccess',
constraint=models.CheckConstraint(check=models.Q(models.Q(('team', ''), ('user__isnull', False)), models.Q(('team__gt', ''), ('user__isnull', True)), _connector='OR'), name='check_template_access_either_user_or_team', violation_error_message='Either user or team must be set, not both.'),
constraint=models.CheckConstraint(condition=models.Q(models.Q(('team', ''), ('user__isnull', False)), models.Q(('team__gt', ''), ('user__isnull', True)), _connector='OR'), name='check_template_access_either_user_or_team', violation_error_message='Either user or team must be set, not both.'),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.1.4 on 2025-01-13 22:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0012_make_document_creator_and_invitation_issuer_optional'),
]
operations = [
migrations.AlterModelOptions(
name='user',
options={'ordering': ('-created_at',), 'verbose_name': 'user', 'verbose_name_plural': 'users'},
),
]

View File

@@ -155,7 +155,7 @@ class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
email = models.EmailField(_("identity email address"), blank=True, null=True)
# Unlike the "email" field which stores the email coming from the OIDC token, this field
# stores the email used by staff users to login to the admin site
# stores the email used by staff users to log in to the admin site
admin_email = models.EmailField(
_("admin email address"), unique=True, blank=True, null=True
)
@@ -199,6 +199,7 @@ class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
class Meta:
db_table = "impress_user"
ordering = ("-created_at",)
verbose_name = _("user")
verbose_name_plural = _("users")
@@ -695,7 +696,7 @@ class DocumentAccess(BaseAccess):
violation_error_message=_("This team is already in this document."),
),
models.CheckConstraint(
check=models.Q(user__isnull=False, team="")
condition=models.Q(user__isnull=False, team="")
| models.Q(user__isnull=True, team__gt=""),
name="check_document_access_either_user_or_team",
violation_error_message=_("Either user or team must be set, not both."),
@@ -760,7 +761,7 @@ class Template(BaseModel):
"""
document_html = weasyprint.HTML(
string=DjangoTemplate(self.code).render(
Context({"body": html.format_html(body_html), **metadata})
Context({"body": html.format_html("{}", body_html), **metadata})
)
)
css = weasyprint.CSS(
@@ -779,7 +780,7 @@ class Template(BaseModel):
Generate and return a docx document wrapped around the current template
"""
template_string = DjangoTemplate(self.code).render(
Context({"body": html.format_html(body_html), **metadata})
Context({"body": html.format_html("{}", body_html), **metadata})
)
html_string = f"""
@@ -797,7 +798,6 @@ class Template(BaseModel):
"""
reference_docx = "core/static/reference.docx"
output = BytesIO()
# Convert the HTML to a temporary docx file
with tempfile.NamedTemporaryFile(suffix=".docx", prefix="docx_") as tmp_file:
@@ -884,7 +884,7 @@ class TemplateAccess(BaseAccess):
violation_error_message=_("This team is already in this template."),
),
models.CheckConstraint(
check=models.Q(user__isnull=False, team="")
condition=models.Q(user__isnull=False, team="")
| models.Q(user__isnull=True, team__gt=""),
name="check_template_access_either_user_or_team",
violation_error_message=_("Either user or team must be set, not both."),

View File

@@ -17,7 +17,7 @@ class CollaborationService:
def reset_connections(self, room, user_id=None):
"""
Reset connections of a room in the collaboration server.
Reseting a connection means that the user will be disconnected and will
Resetting a connection means that the user will be disconnected and will
have to reconnect to the collaboration server, with updated rights.
"""
endpoint = "reset-connections"

View File

@@ -698,7 +698,7 @@ def test_api_document_accesses_delete_administrators_except_owners(
mock_reset_connections, # pylint: disable=redefined-outer-name
):
"""
Users who are administrators in a document should be allowed to delete an access
Users who are administrators in a document should be allowed to delete access
from the document provided it is not ownership.
"""
user = factories.UserFactory()

View File

@@ -285,7 +285,7 @@ def test_api_document_versions_retrieve_authenticated_related(via, mock_user_tea
assert response.status_code == 404
# Create a new version should not make it available to the user because
# only the current version is available to the user but it is excluded
# only the current version is available to the user, but it is excluded
# from the list
document.content = "new content 1"
document.save()

View File

@@ -134,7 +134,7 @@ def test_api_documents_ai_transform_authenticated_forbidden(reach, role):
@patch("openai.resources.chat.completions.Completions.create")
def test_api_documents_ai_transform_authenticated_success(mock_create, reach, role):
"""
Autenticated who are not related to a document should be able to request AI transform
Authenticated who are not related to a document should be able to request AI transform
if the link reach and role permit it.
"""
user = factories.UserFactory()

View File

@@ -154,7 +154,7 @@ def test_api_documents_ai_translate_authenticated_forbidden(reach, role):
@patch("openai.resources.chat.completions.Completions.create")
def test_api_documents_ai_translate_authenticated_success(mock_create, reach, role):
"""
Autenticated who are not related to a document should be able to request AI translate
Authenticated who are not related to a document should be able to request AI translate
if the link reach and role permit it.
"""
user = factories.UserFactory()

View File

@@ -111,7 +111,7 @@ def test_api_documents_attachment_upload_authenticated_forbidden(reach, role):
)
def test_api_documents_attachment_upload_authenticated_success(reach, role):
"""
Autenticated who are not related to a document should be able to upload a file
Authenticated who are not related to a document should be able to upload a file
if the link reach and role permit it.
"""
user = factories.UserFactory()
@@ -225,7 +225,7 @@ def test_api_documents_attachment_upload_invalid(client):
def test_api_documents_attachment_upload_size_limit_exceeded(settings):
"""The uploaded file should not exceeed the maximum size in settings."""
"""The uploaded file should not exceed the maximum size in settings."""
settings.DOCUMENT_IMAGE_MAX_SIZE = 1048576 # 1 MB for test
user = factories.UserFactory()

View File

@@ -160,7 +160,7 @@ def test_api_documents_media_auth_authenticated_restricted():
@pytest.mark.parametrize("via", VIA)
def test_api_documents_media_auth_related(via, mock_user_teams):
"""
Users who have a specific access to a document, whatever the role, should be able to
Users who have specific access to a document, whatever the role, should be able to
retrieve related attachments.
"""
user = factories.UserFactory()

View File

@@ -647,7 +647,7 @@ def test_api_template_accesses_delete_administrators_except_owners(
via, mock_user_teams
):
"""
Users who are administrators in a template should be allowed to delete an access
Users who are administrators in a template should be allowed to delete access
from the template provided it is not ownership.
"""
user = factories.UserFactory()

View File

@@ -84,7 +84,7 @@ def test_models_documents_file_key():
def test_models_documents_get_abilities_forbidden(is_authenticated, reach, role):
"""
Check abilities returned for a document giving insufficient roles to link holders
i.e anonymous users or authenticated users who have no specific role on the document.
i.e. anonymous users or authenticated users who have no specific role on the document.
"""
document = factories.DocumentFactory(link_reach=reach, link_role=role)
user = factories.UserFactory() if is_authenticated else AnonymousUser()
@@ -121,7 +121,7 @@ def test_models_documents_get_abilities_forbidden(is_authenticated, reach, role)
def test_models_documents_get_abilities_reader(is_authenticated, reach):
"""
Check abilities returned for a document giving reader role to link holders
i.e anonymous users or authenticated users who have no specific role on the document.
i.e. anonymous users or authenticated users who have no specific role on the document.
"""
document = factories.DocumentFactory(link_reach=reach, link_role="reader")
user = factories.UserFactory() if is_authenticated else AnonymousUser()
@@ -158,7 +158,7 @@ def test_models_documents_get_abilities_reader(is_authenticated, reach):
def test_models_documents_get_abilities_editor(is_authenticated, reach):
"""
Check abilities returned for a document giving editor role to link holders
i.e anonymous users or authenticated users who have no specific role on the document.
i.e. anonymous users or authenticated users who have no specific role on the document.
"""
document = factories.DocumentFactory(link_reach=reach, link_role="editor")
user = factories.UserFactory() if is_authenticated else AnonymousUser()
@@ -449,7 +449,7 @@ def test_models_documents__email_invitation__success():
def test_models_documents__email_invitation__success_fr():
"""
The email invitation is sent successfully in french.
The email invitation is sent successfully in French.
"""
document = factories.DocumentFactory()

View File

@@ -27,7 +27,7 @@ def test_models_users_id_unique():
def test_models_users_send_mail_main_existing():
"""The "email_user' method should send mail to the user's email address."""
"""The 'email_user' method should send mail to the user's email address."""
user = factories.UserFactory()
with mock.patch("django.core.mail.send_mail") as mock_send:
@@ -37,7 +37,7 @@ def test_models_users_send_mail_main_existing():
def test_models_users_send_mail_main_missing():
"""The "email_user' method should fail if the user has no email address."""
"""The 'email_user' method should fail if the user has no email address."""
user = factories.UserFactory(email=None)
with pytest.raises(ValueError) as excinfo:

View File

@@ -1,5 +1,5 @@
"""
Test ai API endpoints in the impress core app.
Test AI API endpoints in the impress core app.
"""
import json

View File

@@ -15,7 +15,7 @@ class Command(BaseCommand):
"""Define required arguments "email" and "password"."""
parser.add_argument(
"--email",
help=("Email for the user."),
help="Email for the user.",
)
parser.add_argument(
"--password",

View File

@@ -622,8 +622,9 @@ class Base(Configuration):
release=get_release(),
integrations=[DjangoIntegration()],
)
with sentry_sdk.configure_scope() as scope:
scope.set_extra("application", "backend")
# Add the application name to the Sentry scope
scope = sentry_sdk.get_global_scope()
scope.set_tag("application", "backend")
class Build(Base):

View File

@@ -123,7 +123,7 @@ test.describe('Doc Editor', () => {
const selectVisibility = page.getByLabel('Visibility', { exact: true });
// When the visibility is changed, the ws should closed the connection (backend signal)
// When the visibility is changed, the ws should close the connection (backend signal)
const wsClosePromise = webSocket.waitForEvent('close');
await selectVisibility.click();

View File

@@ -67,7 +67,7 @@ test.describe('Doc Visibility', () => {
test.describe('Doc Visibility: Restricted', () => {
test.use({ storageState: { cookies: [], origins: [] } });
test('A doc is not accessible when not authentified.', async ({
test('A doc is not accessible when not authenticated.', async ({
page,
browserName,
}) => {
@@ -98,7 +98,7 @@ test.describe('Doc Visibility: Restricted', () => {
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
});
test('A doc is not accessible when authentified but not member.', async ({
test('A doc is not accessible when authenticated but not member.', async ({
page,
browserName,
}) => {
@@ -316,7 +316,7 @@ test.describe('Doc Visibility: Public', () => {
test.describe('Doc Visibility: Authenticated', () => {
test.use({ storageState: { cookies: [], origins: [] } });
test('A doc is not accessible when unauthentified.', async ({
test('A doc is not accessible when unauthenticated.', async ({
page,
browserName,
}) => {
@@ -325,7 +325,7 @@ test.describe('Doc Visibility: Authenticated', () => {
const [docTitle] = await createDoc(
page,
'Authenticated unauthentified',
'Authenticated unauthenticated',
browserName,
1,
);

View File

@@ -29,7 +29,7 @@ describe('fetchAPI', () => {
});
});
it('check the versionning', () => {
it('check the versioning', () => {
fetchMock.mock('http://test.jest/api/v2.0/some/url', 200);
void fetchAPI('some/url', {}, '2.0');

View File

@@ -33,7 +33,7 @@ export const Auth = ({ children }: PropsWithChildren) => {
setPathAllowed(!regexpUrlsAuth.some((regexp) => !!asPath.match(regexp)));
}, [asPath]);
// We force to login except on allowed paths
// We force to log in except on allowed paths
useEffect(() => {
if (!initiated || authenticated || pathAllowed) {
return;

View File

@@ -46,8 +46,8 @@ export const useAuthStore = create<AuthStore>((set, get) => ({
terminateCrispSession();
window.location.replace(`${baseApiUrl()}logout/`);
},
// If we try to access a specific page and we are not authenticated
// we store the path in the local storage to redirect to it after login
// If we try to access a specific page, and we are not authenticated
// we store the path in the local storage to redirect to it after log in
setAuthUrl() {
if (window.location.pathname !== '/') {
localStorage.setItem(PATH_AUTH_LOCAL_STORAGE, window.location.pathname);

View File

@@ -10,7 +10,7 @@ import { toBase64 } from '../utils';
const useSaveDoc = (docId: string, doc: Y.Doc, canSave: boolean) => {
const { mutate: updateDoc } = useUpdateDoc({
listInvalideQueries: [KEY_LIST_DOC_VERSIONS],
listInvalidQueries: [KEY_LIST_DOC_VERSIONS],
});
const [initialDoc, setInitialDoc] = useState<string>(
toBase64(Y.encodeStateAsUpdate(doc)),

View File

@@ -62,7 +62,7 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
const { broadcast } = useBroadcastStore();
const { mutate: updateDoc } = useUpdateDoc({
listInvalideQueries: [KEY_DOC, KEY_LIST_DOC],
listInvalidQueries: [KEY_DOC, KEY_LIST_DOC],
onSuccess(data) {
if (data.title !== untitledDocument) {
toast(t('Document title updated successfully'), VariantType.SUCCESS);

View File

@@ -94,7 +94,7 @@ const convertToImg = (html: string) => {
const doc = parser.parseFromString(html, 'text/html');
const divs = doc.querySelectorAll('div[data-content-type="image"]');
// Loop through each div and replace it with a img
// Loop through each div and replace it with an img
divs.forEach((div) => {
const img = document.createElement('img');

View File

@@ -20,18 +20,18 @@ export const createFavoriteDoc = async ({ id }: CreateFavoriteDocParams) => {
interface CreateFavoriteDocProps {
onSuccess?: () => void;
listInvalideQueries?: string[];
listInvalidQueries?: string[];
}
export function useCreateFavoriteDoc({
onSuccess,
listInvalideQueries,
listInvalidQueries,
}: CreateFavoriteDocProps) {
const queryClient = useQueryClient();
return useMutation<void, APIError, CreateFavoriteDocParams>({
mutationFn: createFavoriteDoc,
onSuccess: () => {
listInvalideQueries?.forEach((queryKey) => {
listInvalidQueries?.forEach((queryKey) => {
void queryClient.invalidateQueries({
queryKey: [queryKey],
});

View File

@@ -20,18 +20,18 @@ export const deleteFavoriteDoc = async ({ id }: DeleteFavoriteDocParams) => {
interface DeleteFavoriteDocProps {
onSuccess?: () => void;
listInvalideQueries?: string[];
listInvalidQueries?: string[];
}
export function useDeleteFavoriteDoc({
onSuccess,
listInvalideQueries,
listInvalidQueries,
}: DeleteFavoriteDocProps) {
const queryClient = useQueryClient();
return useMutation<void, APIError, DeleteFavoriteDocParams>({
mutationFn: deleteFavoriteDoc,
onSuccess: () => {
listInvalideQueries?.forEach((queryKey) => {
listInvalidQueries?.forEach((queryKey) => {
void queryClient.invalidateQueries({
queryKey: [queryKey],
});

View File

@@ -26,18 +26,18 @@ export const updateDoc = async ({
interface UpdateDocProps {
onSuccess?: (data: Doc) => void;
listInvalideQueries?: string[];
listInvalidQueries?: string[];
}
export function useUpdateDoc({
onSuccess,
listInvalideQueries,
listInvalidQueries,
}: UpdateDocProps = {}) {
const queryClient = useQueryClient();
return useMutation<Doc, APIError, UpdateDocParams>({
mutationFn: updateDoc,
onSuccess: (data) => {
listInvalideQueries?.forEach((queryKey) => {
listInvalidQueries?.forEach((queryKey) => {
void queryClient.invalidateQueries({
queryKey: [queryKey],
});

View File

@@ -30,12 +30,12 @@ export const updateDocLink = async ({
interface UpdateDocLinkProps {
onSuccess?: (data: Doc) => void;
listInvalideQueries?: string[];
listInvalidQueries?: string[];
}
export function useUpdateDocLink({
onSuccess,
listInvalideQueries,
listInvalidQueries,
}: UpdateDocLinkProps = {}) {
const queryClient = useQueryClient();
const { broadcast } = useBroadcastStore();
@@ -43,7 +43,7 @@ export function useUpdateDocLink({
return useMutation<Doc, APIError, UpdateDocLinkParams>({
mutationFn: updateDocLink,
onSuccess: (data, variable) => {
listInvalideQueries?.forEach((queryKey) => {
listInvalidQueries?.forEach((queryKey) => {
void queryClient.invalidateQueries({
queryKey: [queryKey],
});

View File

@@ -49,7 +49,7 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
},
);
},
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
listInvalidQueries: [KEY_LIST_DOC, KEY_DOC],
});
const updateReach = (link_reach: LinkReach) => {

View File

@@ -44,7 +44,7 @@ export const Heading = ({
onMouseOver={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
onClick={() => {
// With mobile the focus open the keyboard and the scroll is not working
// With mobile the focus open the keyboard and the scroll are not working
if (!isMobile) {
editor.focus();
}

View File

@@ -42,7 +42,7 @@ export const ModalConfirmationVersion = ({
const { push } = useRouter();
const { provider } = useProviderStore();
const { mutate: updateDoc } = useUpdateDoc({
listInvalideQueries: [KEY_LIST_DOC_VERSIONS],
listInvalidQueries: [KEY_LIST_DOC_VERSIONS],
onSuccess: () => {
const onDisplaySuccess = () => {
toast(t('Version restored successfully'), VariantType.SUCCESS);

View File

@@ -23,10 +23,10 @@ export const DocsGridActions = ({
const deleteModal = useModal();
const removeFavoriteDoc = useDeleteFavoriteDoc({
listInvalideQueries: [KEY_LIST_DOC],
listInvalidQueries: [KEY_LIST_DOC],
});
const makeFavoriteDoc = useCreateFavoriteDoc({
listInvalideQueries: [KEY_LIST_DOC],
listInvalidQueries: [KEY_LIST_DOC],
});
const options: DropdownMenuOption[] = [

View File

@@ -112,7 +112,7 @@ export class ApiPlugin implements WorkboxPlugin {
};
/**
* When we get an network error.
* When we get a network error.
*/
handlerDidError: WorkboxPlugin['handlerDidError'] = async ({ request }) => {
if (!this.isFetchDidFailed) {

View File

@@ -34,7 +34,7 @@ interface IDocsDB extends DBSchema {
type TableName = 'doc-list' | 'doc-item' | 'doc-mutation';
/**
* IndexDB version must be a integer
* IndexDB version must be an integer
* @returns
*/
const getCurrentVersion = () => {