Exemplo n.º 1
0
    def generate_osm_xml(project_id: int, task_ids_str: str) -> str:
        """ Generate xml response suitable for loading into JOSM.  A sample output file is in
            /backend/helpers/testfiles/osm-sample.xml """
        # Note XML created with upload No to ensure it will be rejected by OSM if uploaded by mistake
        root = ET.Element(
            "osm",
            attrib=dict(version="0.6",
                        upload="never",
                        creator="HOT Tasking Manager"),
        )

        if task_ids_str:
            task_ids = map(int, task_ids_str.split(","))
            tasks = Task.get_tasks(project_id, task_ids)
            if not tasks or len(tasks) == 0:
                raise NotFound()
        else:
            tasks = Task.get_all_tasks(project_id)
            if not tasks or len(tasks) == 0:
                raise NotFound()

        fake_id = -1  # We use fake-ids to ensure XML will not be validated by OSM
        for task in tasks:
            task_geom = shape.to_shape(task.geometry)
            way = ET.SubElement(
                root,
                "way",
                attrib=dict(id=str((task.id * -1)),
                            action="modify",
                            visible="true"),
            )
            for poly in task_geom:
                for point in poly.exterior.coords:
                    ET.SubElement(
                        root,
                        "node",
                        attrib=dict(
                            action="modify",
                            visible="true",
                            id=str(fake_id),
                            lon=str(point[0]),
                            lat=str(point[1]),
                        ),
                    )
                    ET.SubElement(way, "nd", attrib=dict(ref=str(fake_id)))
                    fake_id -= 1

        xml_gpx = ET.tostring(root, encoding="utf8")
        return xml_gpx
Exemplo n.º 2
0
    def generate_gpx(project_id: int, task_ids_str: str, timestamp=None):
        """
        Creates a GPX file for supplied tasks.  Timestamp is for unit testing only.
        You can use the following URL to test locally:
        http://www.openstreetmap.org/edit?editor=id&#map=11/31.50362930069913/34.628906243797054&comment=CHANGSET_COMMENT&gpx=http://localhost:5000/api/v2/projects/{project_id}/tasks/queries/gpx%3Ftasks=2
        """

        if timestamp is None:
            timestamp = datetime.datetime.utcnow()

        root = ET.Element(
            "gpx",
            attrib=dict(
                xmlns="http://www.topografix.com/GPX/1/1",
                version="1.1",
                creator="HOT Tasking Manager",
            ),
        )

        # Create GPX Metadata element
        metadata = ET.Element("metadata")
        link = ET.SubElement(
            metadata,
            "link",
            attrib=dict(href="https://github.com/hotosm/tasking-manager"),
        )
        ET.SubElement(link, "text").text = "HOT Tasking Manager"
        ET.SubElement(metadata, "time").text = timestamp.isoformat()
        root.append(metadata)

        # Create trk element
        trk = ET.Element("trk")
        root.append(trk)
        ET.SubElement(
            trk, "name"
        ).text = f"Task for project {project_id}. Do not edit outside of this area!"

        # Construct trkseg elements
        if task_ids_str is not None:
            task_ids = map(int, task_ids_str.split(","))
            tasks = Task.get_tasks(project_id, task_ids)
            if not tasks or len(tasks) == 0:
                raise NotFound()
        else:
            tasks = Task.get_all_tasks(project_id)
            if not tasks or len(tasks) == 0:
                raise NotFound()

        for task in tasks:
            task_geom = shape.to_shape(task.geometry)
            for poly in task_geom:
                trkseg = ET.SubElement(trk, "trkseg")
                for point in poly.exterior.coords:
                    ET.SubElement(
                        trkseg,
                        "trkpt",
                        attrib=dict(lon=str(point[0]), lat=str(point[1])),
                    )

                    # Append wpt elements to end of doc
                    wpt = ET.Element("wpt",
                                     attrib=dict(lon=str(point[0]),
                                                 lat=str(point[1])))
                    root.append(wpt)

        xml_gpx = ET.tostring(root, encoding="utf8")
        return xml_gpx
Exemplo n.º 3
0
    def post(self, project_id: int, annotation_type: str):
        """
        Store new task annotations for tasks of a project
        ---
        tags:
            - annotations
        produces:
            - application/json
        parameters:
            - in: header
              name: Content-Type
              description: Content type for post body
              required: true
              type: string
              default: application/json
            - name: project_id
              in: path
              description: Unique project ID
              required: true
              type: integer
            - name: annotation_type
              in: path
              description: Annotation type
              required: true
              type: string
            - name: Application-Token
              in: header
              description: Application token registered with TM
              required: true
              type: string
            - in: body
              name: body
              required: true
              description: JSON object for creating draft project
              schema:
                projectId:
                    type: integer
                    required: true
                annotationType:
                    type: string
                    required: true
                tasks:
                    type: array
                    required: true
                    items:
                        schema:
                            taskId:
                                type: integer
                                required: true
                            annotationSource:
                                type: string
                            annotationMarkdown:
                                type: string
                            properties:
                                description: JSON object with properties
        responses:
            200:
                description: Project updated
            400:
                description: Client Error - Invalid Request
            404:
                description: Project or task not found
            500:
                description: Internal Server Error
        """

        if "Application-Token" in request.headers:
            application_token = request.headers["Application-Token"]
            try:
                is_valid_token = ApplicationService.check_token(  # noqa
                    application_token)
            except NotFound:
                current_app.logger.error("Invalid token")
                return {"Error": "Invalid token"}, 500
        else:
            current_app.logger.error("No token supplied")
            return {"Error": "No token supplied"}, 500

        try:
            annotations = request.get_json() or {}
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")

        try:
            ProjectService.get_project_by_id(project_id)
        except NotFound as e:
            current_app.logger.error(f"Error validating project: {str(e)}")

        task_ids = [t["taskId"] for t in annotations["tasks"]]

        # check if task ids are valid
        tasks = Task.get_tasks(project_id, task_ids)
        tasks_ids_db = [t.id for t in tasks]
        if len(task_ids) != len(tasks_ids_db):
            return {"Error": "Invalid task id"}, 500

        for annotation in annotations["tasks"]:
            try:
                TaskAnnotationsService.add_or_update_annotation(
                    annotation, project_id, annotation_type)
            except DataError as e:
                current_app.logger.error(
                    f"Error creating annotations: {str(e)}")
                return {"Error": "Error creating annotations"}, 500

        return project_id, 200