diff --git a/README.md b/README.md index 9cf1026610..73595d8081 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ ODK Central server, using the [ODK Central API](https://odkcentral.docs.apiary.io/#) to allocate specific areas/features to individual mappers, and receive their data submissions. -![1](https://github.com/hotosm/fmtm/assets/97789856/305be31a-96b4-42df-96fc-6968e9bd4e5f) +![image](https://github.com/hotosm/fmtm/assets/97273021/e1bac364-d9dd-47b3-b10f-676e6abab298) #### Manager Web Interface (with PC browser-friendlymap view) @@ -190,27 +190,42 @@ A computer-screen-optimized web app that allows Campaign Managers to: #### Steps to create a project in FMTM - Go to [fmtm](https://fmtm.hotosm.org/) . -- If you are new then on the top right cornor click on Sign up and create an account. - Else, Sign in to your existing account . +- Sign into your OpenStreetMap account by clicking the top right button. - Click the '+ CREATE NEW PROJECT' button. -- Enter the project details. +- Enter the project details like name, description, instructions, and + (optional) ODK credentials. -![2](https://github.com/hotosm/fmtm/assets/97789856/97c38c80-aa0e-4fe2-b8a5-f4ee43a9a63a) + ![2](https://github.com/hotosm/fmtm/assets/97273021/9b8d7a83-11e3-4623-a14a-66ac47d91443) -- Upload Area in the GEOJSON file format. +- Draw or Upload Area in the GeoJSON file format. -![3](https://github.com/hotosm/fmtm/assets/97789856/680eb831-790a-48f1-8997-c20b5213909d) + ![3](https://github.com/hotosm/fmtm/assets/97273021/892f9051-dbb3-434d-b35a-94e90435a5d8) -- Define the tasks of the project. +- Choose the category of field mapping. If you require a custom + XLSForm to be used, upload it at this point. -![Screenshot 2023-06-07 232152](https://github.com/hotosm/fmtm/assets/97789856/b735a661-d0f6-46b8-b548-5ad7b1928480) + ![image](https://github.com/hotosm/fmtm/assets/97273021/02ebb3af-a48f-40eb-b9f8-fd7eec393485) -- Select Form . +- Generate a data extract from your category selection, or upload your + own geometries inside a custom data extract GeoJSON. -![Screenshot 2023-06-07 232316](https://github.com/hotosm/fmtm/assets/97789856/475a6070-4897-4e84-8050-6ecf024d0095) + ![image](https://github.com/hotosm/fmtm/assets/97273021/e4a7f9a6-b411-4f8c-b2ba-9fa9e0d42531) + +- Choose the type of task splitting: + + - Divide on square: create a simple grid over your project area. + - Choose area as tasks: if you have already determined how tasks + should be split (your project area contains multiple polygons), then + select this option. + - Task Splitting Algorithm: use the FMTM splitting algorithm to split + task boundaries by average building and linear features. + + ![image](https://github.com/hotosm/fmtm/assets/97273021/c8a905e2-dd52-49e8-87df-0ac6d9a85077) - Click on Submit button. + ![image](https://github.com/hotosm/fmtm/assets/97273021/0c95e324-3365-4d0a-ba91-c9f9b06b2318) + #### FMTM Backend A back end that converts the project parameters entered by the Campaign Manager in diff --git a/src/backend/app/central/central_crud.py b/src/backend/app/central/central_crud.py index 2a8d380e98..4d90d58595 100644 --- a/src/backend/app/central/central_crud.py +++ b/src/backend/app/central/central_crud.py @@ -20,7 +20,6 @@ import os from asyncio import gather from io import BytesIO -from pathlib import Path from typing import Optional, Union from defusedxml import ElementTree @@ -450,83 +449,68 @@ async def read_and_test_xform( form_file_ext (str): type of form (.xls, .xlsx, or .xml). return_form_data (bool): return the XForm data. """ - # TODO xls2xform_convert requires files on disk - # TODO create PR to accept BytesIO? - # Read from BytesIO object - input_content = input_data.getvalue() file_ext = form_file_ext.lower() - input_path = Path(f"/tmp/fmtm_form_input_tmp{file_ext}") - # This file will store xml contents of an xls form - # NOTE a file on disk is required by xls2xform_convert - output_path = Path("/tmp/fmtm_xform_temp.xml") - if file_ext == ".xml": - # Create output file to write to - output_path.touch(exist_ok=True) - # Write input_content to a temporary file - with open(output_path, "wb") as f: - f.write(input_content) + xform_bytesio = input_data + # Parse / validate XForm + try: + ElementTree.fromstring(xform_bytesio.getvalue()) + except ElementTree.ParseError as e: + log.error(e) + msg = f"Error parsing XForm XML: Possible reason: {str(e)}" + raise HTTPException( + status_code=HTTPStatus.UNPROCESSABLE_ENTITY, detail=msg + ) from e else: - # Create input file to write to - input_path.touch(exist_ok=True) - with open(input_path, "wb") as f: - f.write(input_content) try: - log.debug(f"Converting xlsform -> xform: {str(output_path)}") - # FIXME should this be validate=True? - xls2xform_convert( - xlsform_path=str(input_path), - xform_path=str(output_path), + log.debug("Converting xlsform -> xform") + # NOTE do not enable validate=True, as this requires Java installed + xform_bytesio, warnings = xls2xform_convert( + xlsform_path=f"/tmp/form{file_ext}", validate=False, + xlsform_object=input_data, ) + if warnings: + log.warning(warnings) except Exception as e: log.error(e) - msg = f"XLSForm is invalid. Possible reason: {str(e)}" + msg = f"XLSForm is invalid: {str(e)}" raise HTTPException( status_code=HTTPStatus.UNPROCESSABLE_ENTITY, detail=msg ) from e - # Parse XForm - try: - # TODO for memory object use ElementTree.fromstring() - xml_parsed = ElementTree.parse(str(output_path)) - if return_form_data: - xml_bytes = ElementTree.tostring(xml_parsed.getroot()) - return BytesIO(xml_bytes) - except ElementTree.ParseError as e: - log.error(e) - msg = f"Error parsing XForm XML: Possible reason: {str(e)}" - raise HTTPException( - status_code=HTTPStatus.UNPROCESSABLE_ENTITY, detail=msg - ) from e - - # Delete temp files - if file_ext != ".xml": - input_path.unlink() - output_path.unlink() - + # Return immediately if return_form_data: - return xml_parsed + return xform_bytesio + + # Load XML + xform_xml = ElementTree.fromstring(xform_bytesio.getvalue()) # Extract geojson filenames try: - root = xml_parsed.getroot() namespaces = {"xforms": "http://www.w3.org/2002/xforms"} geojson_list = [ os.path.splitext(inst.attrib["src"].split("/")[-1])[0] - for inst in root.findall(".//xforms:instance[@src]", namespaces) + for inst in xform_xml.findall(".//xforms:instance[@src]", namespaces) if inst.attrib.get("src", "").endswith(".geojson") ] + # No select_one_from_file defined + if not geojson_list: + msg = ( + "The form has no select_one_from_file or " + "select_multiple_from_file field defined." + ) + raise ValueError(msg) from None + return {"required_media": geojson_list, "message": "Your form is valid"} except Exception as e: log.error(e) - msg = f"Error extracting geojson filename: Possible reason: {str(e)}" raise HTTPException( - status_code=HTTPStatus.UNPROCESSABLE_ENTITY, detail=msg + status_code=HTTPStatus.UNPROCESSABLE_ENTITY, detail=str(e) ) from e diff --git a/src/backend/app/submissions/submission_crud.py b/src/backend/app/submissions/submission_crud.py index 682ed019d7..56f35d4b07 100644 --- a/src/backend/app/submissions/submission_crud.py +++ b/src/backend/app/submissions/submission_crud.py @@ -820,3 +820,28 @@ async def get_submission_by_task( count = data.get("@odata.count", 0) return submissions, count + + +async def get_submission_detail( + project: db_models.DbProject, + task_id: int, + submission_id: str, + db: Session, +): + """Get the details of a submission. + + Args: + project: The project object representing the project. + task_id: The ID of the task associated with the submission. + submission_id: The ID of the submission. + db: The database session. + + Returns: + The details of the submission as a JSON object. + """ + odk_credentials = await project_deps.get_odk_credentials(db, project.id) + odk_form = get_odk_form(odk_credentials) + xform = f"{project.project_name_prefix}_task_{task_id}" + submission = odk_form.getSubmissions(project.odkid, xform, submission_id) + + return json.loads(submission) diff --git a/src/backend/app/submissions/submission_routes.py b/src/backend/app/submissions/submission_routes.py index dcc69fdeed..3946ea2ff5 100644 --- a/src/backend/app/submissions/submission_routes.py +++ b/src/backend/app/submissions/submission_routes.py @@ -413,6 +413,7 @@ async def task_submissions( project: db_models.DbProject = Depends(project_deps.get_project_by_id), page: int = Query(1, ge=1), limit: int = Query(13, le=100), + submission_id: Optional[str] = None, submitted_by: Optional[str] = None, review_state: Optional[str] = None, submitted_date: Optional[str] = Query( @@ -463,4 +464,10 @@ async def task_submissions( results=data, pagination=submission_schemas.PaginationInfo(**pagination.model_dump()), ) + if submission_id: + submission_detail = await submission_crud.get_submission_detail( + project, task_id, submission_id, db + ) + response = submission_detail.get("value", [])[0] + return response diff --git a/src/backend/pdm.lock b/src/backend/pdm.lock index 7f276fd34d..dff899275b 100644 --- a/src/backend/pdm.lock +++ b/src/backend/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "debug", "dev", "docs", "test"] strategy = ["cross_platform"] lock_version = "4.4.1" -content_hash = "sha256:039de770c061d4344db4702d522287fdc4ce4012a702d136b8b9c0a86aa01edd" +content_hash = "sha256:9a77021c0e0e984c129c8223a5266f24537307731a8aeed6d944a837a22a9c55" [[package]] name = "annotated-types" @@ -1340,20 +1340,20 @@ files = [ [[package]] name = "openpyxl" -version = "3.0.9" +version = "3.1.2" requires_python = ">=3.6" summary = "A Python library to read/write Excel 2010 xlsx/xlsm files" dependencies = [ "et-xmlfile", ] files = [ - {file = "openpyxl-3.0.9-py2.py3-none-any.whl", hash = "sha256:8f3b11bd896a95468a4ab162fc4fcd260d46157155d1f8bfaabb99d88cfcf79f"}, - {file = "openpyxl-3.0.9.tar.gz", hash = "sha256:40f568b9829bf9e446acfffce30250ac1fa39035124d55fc024025c41481c90f"}, + {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"}, + {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, ] [[package]] name = "osm-fieldwork" -version = "0.5.2" +version = "0.5.3" requires_python = ">=3.10" summary = "Processing field data from OpenDataKit to OpenStreetMap format." dependencies = [ @@ -1377,8 +1377,8 @@ dependencies = [ "xmltodict>=0.13.0", ] files = [ - {file = "osm-fieldwork-0.5.2.tar.gz", hash = "sha256:4d183452c8bf73d12b57e8ebe7a6b82c5cf3352b13df5c7a29836701e7b6986a"}, - {file = "osm_fieldwork-0.5.2-py3-none-any.whl", hash = "sha256:e8a488aa7ee0e4a69a7c66492bde4c0019893f8278ae7fe2cf8fc25c9678bfbe"}, + {file = "osm-fieldwork-0.5.3.tar.gz", hash = "sha256:95d827d80c53d4a9584cf4ff17153ed540b504dedc73a283e7b45c71a4fa99ea"}, + {file = "osm_fieldwork-0.5.3-py3-none-any.whl", hash = "sha256:64c3209ed35d83d7fd90bed63e731388666c2173663a3cbf6c84185ffd434b18"}, ] [[package]] @@ -1974,18 +1974,17 @@ files = [ [[package]] name = "pyxform" -version = "1.12.2" +version = "2.0.0" requires_python = ">=3.7" +git = "https://github.com/hotosm/pyxform" +ref = "feat/xls2xform_convert_bytesio" +revision = "79f0db7403dcd1124c29af5ba5710ab396cfe793" summary = "A Python package to create XForms for ODK Collect." dependencies = [ "defusedxml==0.7.1", - "openpyxl==3.0.9", + "openpyxl==3.1.2", "xlrd==2.0.1", ] -files = [ - {file = "pyxform-1.12.2-py3-none-any.whl", hash = "sha256:27ceb648a9f2a49e40f30a625bf82557a0ee01d6febf749b0d81614bb6544ac8"}, - {file = "pyxform-1.12.2.tar.gz", hash = "sha256:fb67cee3e89fb21329d5efa6acb87518cbdffe835224f7dbae16bf7e84b519f7"}, -] [[package]] name = "pyyaml" diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index 42978ad462..a85166b8ee 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -36,7 +36,7 @@ dependencies = [ "geoalchemy2==0.14.2", "geojson==3.1.0", "shapely==2.0.2", - "pyxform==1.12.2", + "pyxform @ git+https://github.com/hotosm/pyxform@feat/xls2xform_convert_bytesio", "sentry-sdk==1.38.0", "py-cpuinfo==9.0.0", "loguru==0.7.2", @@ -47,7 +47,7 @@ dependencies = [ "cryptography>=42.0.1", "defusedxml>=0.7.1", "osm-login-python==1.0.1", - "osm-fieldwork==0.5.2", + "osm-fieldwork==0.5.3", "osm-rawdata==0.2.3", "fmtm-splitter==1.1.2", ] diff --git a/src/frontend/package.json b/src/frontend/package.json index c192510b6d..9af880798e 100755 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -64,6 +64,19 @@ "@radix-ui/react-switch": "^1.0.3", "@reduxjs/toolkit": "^1.9.1", "@sentry/react": "^7.59.3", + "@tiptap/extension-bullet-list": "^2.2.4", + "@tiptap/extension-document": "^2.2.4", + "@tiptap/extension-heading": "^2.2.4", + "@tiptap/extension-image": "^2.2.4", + "@tiptap/extension-link": "^2.2.4", + "@tiptap/extension-list-item": "^2.2.4", + "@tiptap/extension-ordered-list": "^2.2.4", + "@tiptap/extension-paragraph": "^2.2.4", + "@tiptap/extension-text": "^2.2.4", + "@tiptap/extension-youtube": "^2.2.4", + "@tiptap/pm": "^2.2.4", + "@tiptap/react": "^2.2.4", + "@tiptap/starter-kit": "^2.2.4", "@types/jest": "^29.5.3", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/src/frontend/pnpm-lock.yaml b/src/frontend/pnpm-lock.yaml index 34474e9fd6..b19ccd3c11 100644 --- a/src/frontend/pnpm-lock.yaml +++ b/src/frontend/pnpm-lock.yaml @@ -59,6 +59,45 @@ dependencies: '@sentry/react': specifier: ^7.59.3 version: 7.73.0(react@17.0.2) + '@tiptap/extension-bullet-list': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-document': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-heading': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-image': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-link': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/extension-list-item': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-ordered-list': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-paragraph': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-text': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-youtube': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4) + '@tiptap/pm': + specifier: ^2.2.4 + version: 2.2.4 + '@tiptap/react': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)(react-dom@17.0.2)(react@17.0.2) + '@tiptap/starter-kit': + specifier: ^2.2.4 + version: 2.2.4(@tiptap/pm@2.2.4) '@types/jest': specifier: ^29.5.3 version: 29.5.5 @@ -3029,6 +3068,34 @@ packages: reselect: 4.1.8 dev: false + /@remirror/core-constants@2.0.2: + resolution: {integrity: sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==} + dev: false + + /@remirror/core-helpers@3.0.0: + resolution: {integrity: sha512-tusEgQJIqg4qKj6HSBUFcyRnWnziw3neh4T9wOmsPGHFC3w9kl5KSrDb9UAgE8uX6y32FnS7vJ955mWOl3n50A==} + dependencies: + '@remirror/core-constants': 2.0.2 + '@remirror/types': 1.0.1 + '@types/object.omit': 3.0.3 + '@types/object.pick': 1.3.4 + '@types/throttle-debounce': 2.1.0 + case-anything: 2.1.13 + dash-get: 1.0.2 + deepmerge: 4.3.1 + fast-deep-equal: 3.1.3 + make-error: 1.3.6 + object.omit: 3.0.0 + object.pick: 1.3.0 + throttle-debounce: 3.0.1 + dev: false + + /@remirror/types@1.0.1: + resolution: {integrity: sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==} + dependencies: + type-fest: 2.19.0 + dev: false + /@remix-run/router@1.9.0: resolution: {integrity: sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==} engines: {node: '>=14.0.0'} @@ -3241,6 +3308,282 @@ packages: react-dom: 17.0.2(react@17.0.2) dev: true + /@tiptap/core@2.2.4(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-cRrI8IlLIhCE1hacBQzXIC8dsRvGq6a4lYWQK/BaHuZg21CG7szp3Vd8Ix+ra1f5v0xPOT+Hy+QFNQooRMKMCw==} + peerDependencies: + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/pm': 2.2.4 + dev: false + + /@tiptap/extension-blockquote@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-FrfPnn0VgVrUwWLwja1afX99JGLp6PE9ThVcmri+tLwUZQvTTVcCvHoCdOakav3/nge1+aV4iE3tQdyq1tWI9Q==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-bold@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-v3tTLc8YESFZPOGj5ByFr8VbmQ/PTo49T1vsK50VubxIN/5r9cXlKH8kb3dZlZxCxJa3FrXNO/M8rdGBSWQvSg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-bubble-menu@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-Nx1fS9jcFlhxaTDYlnayz2UulhK6CMaePc36+7PQIVI+u20RhgTCRNr25zKNemvsiM0RPZZVUjlHkxC0l5as1Q==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + tippy.js: 6.3.7 + dev: false + + /@tiptap/extension-bullet-list@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-z/MPmW8bhRougMuorl6MAQBXeK4rhlP+jBWlNwT+CT8h5IkXqPnDbM1sZeagp2nYfVV6Yc4RWpzimqHHtGnYTA==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-code-block@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-h6WV9TmaBEZmvqe1ezMR83DhCPUap6P2mSR5pwVk0WVq6rvZjfgU0iF3EetBJOeDgPlz7cNe2NMDfVb1nGTM/g==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + dev: false + + /@tiptap/extension-code@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-JB4SJ2mUU/9qXFUf+K5K9szvovnN9AIcCb0f0UlcVBuddKHSqCl3wO3QJgYt44BfQTLMNuyzr+zVqfFd6BNt/g==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-document@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-z+05xGK0OFoXV1GL+/8bzcZuWMdMA3+EKwk5c+iziG60VZcvGTF7jBRsZidlu9Oaj0cDwWHCeeo6L9SgSh6i2A==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-dropcursor@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-IHwkEKmqpqXyJi16h7871NrcIqeyN7I6XRE2qdqi+MhGigVWI8nWHoYbjRKa7K/1uhs5zeRYyDlq5EuZyL6mgA==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + dev: false + + /@tiptap/extension-floating-menu@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-U25l7PEzOmlAPugNRl8t8lqyhQZS6W/+3f92+FdwW9qXju3i62iX/3OGCC3Gv+vybmQ4fbZmMjvl+VDfenNi3A==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + tippy.js: 6.3.7 + dev: false + + /@tiptap/extension-gapcursor@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-Y6htT/RDSqkQ1UwG2Ia+rNVRvxrKPOs3RbqKHPaWr3vbFWwhHyKhMCvi/FqfI3d5pViVHOZQ7jhb5hT/a0BmNw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + dev: false + + /@tiptap/extension-hard-break@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-FPvS57GcqHIeLbPKGJa3gnH30Xw+YB1PXXnAWG2MpnMtc2Vtj1l5xaYYBZB+ADdXLAlU0YMbKhFLQO4+pg1Isg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-heading@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-gkq7Ns2FcrOCRq7Q+VRYt5saMt2R9g4REAtWy/jEevJ5UV5vA2AiGnYDmxwAkHutoYU0sAUkjqx37wE0wpamNw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-history@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-FDM32XYF5NU4mzh+fJ8w2CyUqv0l2Nl15sd6fOhQkVxSj8t57z+DUXc9ZR3zkH+1RAagYJo/2Gu3e99KpMr0tg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + dev: false + + /@tiptap/extension-horizontal-rule@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-iCRHjFQQHApWg3R4fkKkJQhWEOdu1Fdc4YEAukdOXPSg3fg36IwjvsMXjt9SYBtVZ+iio3rORCZGXyMvgCH9uw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + dev: false + + /@tiptap/extension-image@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-xOnqZpnP/fAfmK5AKmXplVQdXBtY5AoZ9B+qllH129aLABaDRzl3e14ZRHC8ahQawOmCe6AOCCXYUBXDOlY5Jg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-italic@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-qIhGNvWnsQswSgEMRA8jQQjxfkOGNAuNWKEVQX9DPoqAUgknT41hQcAMP8L2+OdACpb2jbVMOO5Cy5Dof2L8/w==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-link@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-Qsx0cFZm4dxbkToXs5TcXbSoUdicv8db1gV1DYIZdETqjBm4wFjlzCUP7hPHFlvNfeSy1BzAMRt+RpeuiwvxWQ==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + linkifyjs: 4.1.3 + dev: false + + /@tiptap/extension-list-item@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-lPLKGKsHpM9ClUa8n7GEUn8pG6HCYU0vFruIy3l2t6jZdHkrgBnYtVGMZ13K8UDnj/hlAlccxku0D0P4mA1Vrg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-ordered-list@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-TpFy140O9Af1JciXt+xwqYUXxcJ6YG8zi/B5UDJujp+FH5sCmlYYBBnWxiFMhVaj6yEmA2eafu1qUkic/1X5Aw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-paragraph@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-m1KwyvTNJxsq7StbspbcOhxO4Wk4YpElDbqOouWi+H4c8azdpI5Pn96ZqhFeE9bSyjByg6OcB/wqoJsLbeFWdQ==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-strike@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-/a2EwQgA+PpG17V2tVRspcrIY0SN3blwcgM7lxdW4aucGkqSKnf7+91dkhQEwCZ//o8kv9mBCyRoCUcGy6S5Xg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-text@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-NlKHMPnRJXB+0AGtDlU0P2Pg+SdesA2lMMd7JzDUgJgL7pX2jOb8eUqSeOjFKuSzFSqYfH6C3o6mQiNhuQMv+g==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/extension-youtube@2.2.4(@tiptap/core@2.2.4): + resolution: {integrity: sha512-OM8YVWF2febaErLGUzHGKAo3HkfX1RmXDxcsV2lChhxQUUuaQkv4oBFBNRNi/fcjnA/dMVe/2DfGMI5EGZmLrg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + dev: false + + /@tiptap/pm@2.2.4: + resolution: {integrity: sha512-Po0klR165zgtinhVp1nwMubjyKx6gAY9kH3IzcniYLCkqhPgiqnAcCr61TBpp4hfK8YURBS4ihvCB1dyfCyY8A==} + dependencies: + prosemirror-changeset: 2.2.1 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.5.2 + prosemirror-dropcursor: 1.8.1 + prosemirror-gapcursor: 1.3.2 + prosemirror-history: 1.3.2 + prosemirror-inputrules: 1.4.0 + prosemirror-keymap: 1.2.2 + prosemirror-markdown: 1.12.0 + prosemirror-menu: 1.2.4 + prosemirror-model: 1.19.4 + prosemirror-schema-basic: 1.2.2 + prosemirror-schema-list: 1.3.0 + prosemirror-state: 1.4.3 + prosemirror-tables: 1.3.7 + prosemirror-trailing-node: 2.0.7(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.1) + prosemirror-transform: 1.8.0 + prosemirror-view: 1.33.1 + dev: false + + /@tiptap/react@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)(react-dom@17.0.2)(react@17.0.2): + resolution: {integrity: sha512-HkYmMZWcETPZn3KpzdDg/ns2TKeFh54TvtCEInA4ljYtWGLoZc/A+KaiEtMIgVs+Mo1XwrhuoNGjL9c0OK2HJw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/extension-bubble-menu': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/extension-floating-menu': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/pm': 2.2.4 + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + dev: false + + /@tiptap/starter-kit@2.2.4(@tiptap/pm@2.2.4): + resolution: {integrity: sha512-Kbk7qUfIZg3+bNa3e/wBeDQt4jJB46uQgM+xy5NSY6H8NZP6gdmmap3aIrn9S/W/hGpxJl4RcXAeaT0CQji9XA==} + dependencies: + '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/extension-blockquote': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-bold': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-bullet-list': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-code': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-code-block': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/extension-document': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-dropcursor': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/extension-gapcursor': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/extension-hard-break': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-heading': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-history': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/extension-horizontal-rule': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + '@tiptap/extension-italic': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-list-item': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-ordered-list': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-paragraph': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-strike': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/extension-text': 2.2.4(@tiptap/core@2.2.4) + transitivePeerDependencies: + - '@tiptap/pm' + dev: false + /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} @@ -3394,6 +3737,14 @@ packages: /@types/node@20.8.3: resolution: {integrity: sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==} + /@types/object.omit@3.0.3: + resolution: {integrity: sha512-xrq4bQTBGYY2cw+gV4PzoG2Lv3L0pjZ1uXStRRDQoATOYW1lCsFQHhQ+OkPhIcQoqLjAq7gYif7D14Qaa6Zbew==} + dev: false + + /@types/object.pick@1.3.4: + resolution: {integrity: sha512-5PjwB0uP2XDp3nt5u5NJAG2DORHIRClPzWT/TTZhJ2Ekwe8M5bA9tvPdi9NO/n2uvu2/ictat8kgqvLfcIE1SA==} + dev: false + /@types/parse-json@4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} @@ -3434,6 +3785,10 @@ packages: /@types/stack-utils@2.0.1: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + /@types/throttle-debounce@2.1.0: + resolution: {integrity: sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==} + dev: false + /@types/tough-cookie@4.0.3: resolution: {integrity: sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==} dev: true @@ -4156,6 +4511,11 @@ packages: /caniuse-lite@1.0.30001546: resolution: {integrity: sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==} + /case-anything@2.1.13: + resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==} + engines: {node: '>=12.13'} + dev: false + /chai@4.3.10: resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} engines: {node: '>=4'} @@ -4301,6 +4661,10 @@ packages: path-type: 4.0.0 yaml: 1.10.2 + /crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -4446,6 +4810,10 @@ packages: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true + /dash-get@1.0.2: + resolution: {integrity: sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==} + dev: false + /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} @@ -4534,7 +4902,6 @@ packages: /deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - dev: true /default-browser-id@3.0.0: resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} @@ -4676,7 +5043,6 @@ packages: /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - dev: true /env-cmd@10.1.0: resolution: {integrity: sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==} @@ -5744,6 +6110,13 @@ packages: hasBin: true dev: false + /is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + dev: false + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -5808,6 +6181,13 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true @@ -5896,6 +6276,11 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: false + /iterator.prototype@1.1.2: resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} dependencies: @@ -6221,6 +6606,16 @@ packages: /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + /linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + dependencies: + uc.micro: 2.0.0 + dev: false + + /linkifyjs@4.1.3: + resolution: {integrity: sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==} + dev: false + /loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} engines: {node: '>=6.11.5'} @@ -6312,6 +6707,26 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: false + + /markdown-it@14.0.0: + resolution: {integrity: sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==} + hasBin: true + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.0.0 + dev: false + + /mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -6510,6 +6925,20 @@ packages: es-abstract: 1.22.2 dev: true + /object.omit@3.0.0: + resolution: {integrity: sha512-EO+BCv6LJfu+gBIF3ggLicFebFLN5zqzz/WWJlMFfkMyGth+oBkhxzDl0wx2W4GkLzuQs/FsSkXZb2IMWQqmBQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 1.0.1 + dev: false + + /object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + /object.values@1.1.7: resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} engines: {node: '>= 0.4'} @@ -6583,6 +7012,10 @@ packages: prelude-ls: 1.2.1 type-check: 0.4.0 + /orderedmap@2.1.1: + resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} + dev: false + /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -6861,6 +7294,149 @@ packages: object-assign: 4.1.1 react-is: 16.13.1 + /prosemirror-changeset@2.2.1: + resolution: {integrity: sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==} + dependencies: + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-collab@1.3.1: + resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} + dependencies: + prosemirror-state: 1.4.3 + dev: false + + /prosemirror-commands@1.5.2: + resolution: {integrity: sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ==} + dependencies: + prosemirror-model: 1.19.4 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-dropcursor@1.8.1: + resolution: {integrity: sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==} + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.33.1 + dev: false + + /prosemirror-gapcursor@1.3.2: + resolution: {integrity: sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==} + dependencies: + prosemirror-keymap: 1.2.2 + prosemirror-model: 1.19.4 + prosemirror-state: 1.4.3 + prosemirror-view: 1.33.1 + dev: false + + /prosemirror-history@1.3.2: + resolution: {integrity: sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g==} + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.33.1 + rope-sequence: 1.3.4 + dev: false + + /prosemirror-inputrules@1.4.0: + resolution: {integrity: sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==} + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-keymap@1.2.2: + resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==} + dependencies: + prosemirror-state: 1.4.3 + w3c-keyname: 2.2.8 + dev: false + + /prosemirror-markdown@1.12.0: + resolution: {integrity: sha512-6F5HS8Z0HDYiS2VQDZzfZP6A0s/I0gbkJy8NCzzDMtcsz3qrfqyroMMeoSjAmOhDITyon11NbXSzztfKi+frSQ==} + dependencies: + markdown-it: 14.0.0 + prosemirror-model: 1.19.4 + dev: false + + /prosemirror-menu@1.2.4: + resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==} + dependencies: + crelt: 1.0.6 + prosemirror-commands: 1.5.2 + prosemirror-history: 1.3.2 + prosemirror-state: 1.4.3 + dev: false + + /prosemirror-model@1.19.4: + resolution: {integrity: sha512-RPmVXxUfOhyFdayHawjuZCxiROsm9L4FCUA6pWI+l7n2yCBsWy9VpdE1hpDHUS8Vad661YLY9AzqfjLhAKQ4iQ==} + dependencies: + orderedmap: 2.1.1 + dev: false + + /prosemirror-schema-basic@1.2.2: + resolution: {integrity: sha512-/dT4JFEGyO7QnNTe9UaKUhjDXbTNkiWTq/N4VpKaF79bBjSExVV2NXmJpcM7z/gD7mbqNjxbmWW5nf1iNSSGnw==} + dependencies: + prosemirror-model: 1.19.4 + dev: false + + /prosemirror-schema-list@1.3.0: + resolution: {integrity: sha512-Hz/7gM4skaaYfRPNgr421CU4GSwotmEwBVvJh5ltGiffUJwm7C8GfN/Bc6DR1EKEp5pDKhODmdXXyi9uIsZl5A==} + dependencies: + prosemirror-model: 1.19.4 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-state@1.4.3: + resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} + dependencies: + prosemirror-model: 1.19.4 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.33.1 + dev: false + + /prosemirror-tables@1.3.7: + resolution: {integrity: sha512-oEwX1wrziuxMtwFvdDWSFHVUWrFJWt929kVVfHvtTi8yvw+5ppxjXZkMG/fuTdFo+3DXyIPSKfid+Be1npKXDA==} + dependencies: + prosemirror-keymap: 1.2.2 + prosemirror-model: 1.19.4 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.33.1 + dev: false + + /prosemirror-trailing-node@2.0.7(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.1): + resolution: {integrity: sha512-8zcZORYj/8WEwsGo6yVCRXFMOfBo0Ub3hCUvmoWIZYfMP26WqENU0mpEP27w7mt8buZWuGrydBewr0tOArPb1Q==} + peerDependencies: + prosemirror-model: ^1.19.0 + prosemirror-state: ^1.4.2 + prosemirror-view: ^1.31.2 + dependencies: + '@remirror/core-constants': 2.0.2 + '@remirror/core-helpers': 3.0.0 + escape-string-regexp: 4.0.0 + prosemirror-model: 1.19.4 + prosemirror-state: 1.4.3 + prosemirror-view: 1.33.1 + dev: false + + /prosemirror-transform@1.8.0: + resolution: {integrity: sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==} + dependencies: + prosemirror-model: 1.19.4 + dev: false + + /prosemirror-view@1.33.1: + resolution: {integrity: sha512-62qkYgSJIkwIMMCpuGuPzc52DiK1Iod6TWoIMxP4ja6BTD4yO8kCUL64PZ/WhH/dJ9fW0CDO39FhH1EMyhUFEg==} + dependencies: + prosemirror-model: 1.19.4 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + /protocol-buffers-schema@3.6.0: resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} @@ -6872,6 +7448,11 @@ packages: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true + /punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + dev: false + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} @@ -7356,6 +7937,10 @@ packages: fsevents: 2.3.3 dev: true + /rope-sequence@1.3.4: + resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + dev: false + /rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} dev: true @@ -7839,6 +8424,11 @@ packages: webpack: 5.88.2 dev: true + /throttle-debounce@3.0.1: + resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} + engines: {node: '>=10'} + dev: false + /tiny-invariant@1.3.1: resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} dev: false @@ -7857,6 +8447,12 @@ packages: engines: {node: '>=14.0.0'} dev: true + /tippy.js@6.3.7: + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} + dependencies: + '@popperjs/core': 2.11.8 + dev: false + /titleize@3.0.0: resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} engines: {node: '>=12'} @@ -7946,6 +8542,11 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: false + /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} @@ -7989,6 +8590,10 @@ packages: engines: {node: '>=4.2.0'} hasBin: true + /uc.micro@2.0.0: + resolution: {integrity: sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==} + dev: false + /ufo@1.3.1: resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} dev: true @@ -8289,6 +8894,10 @@ packages: - terser dev: true + /w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + dev: false + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} diff --git a/src/frontend/src/api/CreateProjectService.ts b/src/frontend/src/api/CreateProjectService.ts index 5e62b92955..c4da67a46b 100755 --- a/src/frontend/src/api/CreateProjectService.ts +++ b/src/frontend/src/api/CreateProjectService.ts @@ -265,6 +265,7 @@ const GetIndividualProjectDetails: Function = (url: string, projectData: any) => description: resp.project_info?.description, short_description: resp.project_info?.short_description, outline_geojson: formattedOutlineGeojson, + per_task_instructions: resp.project_info?.per_task_instructions, }; dispatch(CreateProjectActions.SetIndividualProjectDetails(modifiedResponse)); diff --git a/src/frontend/src/api/OrganisationService.ts b/src/frontend/src/api/OrganisationService.ts index 5ebb841207..57f31c2676 100644 --- a/src/frontend/src/api/OrganisationService.ts +++ b/src/frontend/src/api/OrganisationService.ts @@ -4,6 +4,7 @@ import { GetOrganisationDataModel, OrganisationModal } from '@/models/organisati import { CommonActions } from '@/store/slices/CommonSlice'; import { OrganisationAction } from '@/store/slices/organisationSlice'; import { API } from '.'; +import { createLoginWindow } from '@/utilfunctions/login'; function appendObjectToFormData(formData, object) { for (const [key, value] of Object.entries(object)) { @@ -49,6 +50,9 @@ export const OrganisationDataService: Function = (url: string) => { dispatch(OrganisationAction.GetOrganisationsData(response)); } catch (error) { dispatch(OrganisationAction.GetOrganisationDataLoading(false)); + if (error.response.status === 401) { + createLoginWindow('/'); + } } }; await getOrganisationData(url); diff --git a/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx b/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx index a2308993a6..b1bc15e82b 100644 --- a/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx +++ b/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx @@ -9,6 +9,7 @@ import { diffObject } from '@/utilfunctions/compareUtils'; import useForm from '@/hooks/useForm'; import CoreModules from '@/shared/CoreModules'; import { CommonActions } from '@/store/slices/CommonSlice'; +import RichTextEditor from '@/components/common/Editor/Editor'; const ProjectDescriptionTab = ({ projectId }) => { const dispatch = CoreModules.useAppDispatch(); @@ -33,7 +34,7 @@ const ProjectDescriptionTab = ({ projectId }) => { ); } }; - const { handleSubmit, handleChange, values, errors }: any = useForm( + const { handleSubmit, handleChange, handleCustomChange, values, errors }: any = useForm( editProjectDetails, submission, EditProjectValidation, @@ -71,15 +72,14 @@ const ProjectDescriptionTab = ({ projectId }) => { errorMsg={errors.description} required /> - +
Instructions
+Description
{projectDetailsLoading ? (+
{projectInfo?.description}
- {descLines >= 10 && ( + {descLines >= 7 && ( setSeeMore(!seeMore)}
diff --git a/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx b/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx
index de2e793dd4..481541fdef 100644
--- a/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx
+++ b/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx
@@ -59,8 +59,6 @@ const SubmissionsTable = ({ toggleView }) => {
const [paginationPage, setPaginationPage] = useState
- Expected Count: {currentTask?.[0].feature_count}
+ Expected Count: {currentTask?.[0]?.feature_count}
- Submission Count: {currentTask?.[0].submission_count}
+ Submission Count: {currentTask?.[0]?.submission_count}
- Task ID: #{currentTask?.[0].task_id}
+ Task ID: #{currentTask?.[0]?.task_id}
editor?.chain().focus().toggleHeading({ level: 1 }).run()} + className={`${iconClassName} fmtm-px-2 ${ + editor?.isActive('heading', { level: 1 }) ? 'fmtm-text-primaryRed fmtm-bg-red-100' : '' + }`} + > + H1 +
+editor?.chain().focus().toggleHeading({ level: 2 }).run()} + className={`${iconClassName} fmtm-px-2 ${ + editor?.isActive('heading', { level: 2 }) ? 'fmtm-text-primaryRed fmtm-bg-red-100' : '' + }`} + > + H2 +
+editor?.chain().focus().toggleHeading({ level: 3 }).run()} + className={`${iconClassName} fmtm-px-2 ${ + editor?.isActive('heading', { level: 3 }) ? 'fmtm-text-primaryRed fmtm-bg-red-100' : '' + }`} + > + H3 +
+