This is an automated email from the ASF dual-hosted git repository.

dpgaspar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new a77b2d6ebf chore: remove annotation layer FAB CRUD model view (#22178)
a77b2d6ebf is described below

commit a77b2d6ebfbe8caf98b2c0d00a19f3f744f18b2b
Author: Daniel Vaz Gaspar <[email protected]>
AuthorDate: Tue Nov 22 16:19:57 2022 +0000

    chore: remove annotation layer FAB CRUD model view (#22178)
---
 .../AnnotationLayerControl/AnnotationLayer.jsx     |   4 +-
 .../AnnotationLayer.test.tsx                       |   2 +-
 .../src/views/CRUD/annotation/AnnotationList.tsx   |   4 +-
 .../CRUD/annotationlayers/AnnotationLayersList.tsx |   8 +-
 superset-frontend/src/views/routes.tsx             |   4 +-
 .../annotations/commands/create.py                 |   2 +-
 superset/initialization/__init__.py                |  27 +++--
 superset/views/__init__.py                         |   1 -
 superset/views/annotations.py                      | 110 ++-------------------
 tests/integration_tests/core_tests.py              |  35 -------
 10 files changed, 33 insertions(+), 164 deletions(-)

diff --git 
a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx
 
b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx
index 64d09364f6..42ca4bb359 100644
--- 
a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx
+++ 
b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx
@@ -115,7 +115,7 @@ const NotFoundContent = () => (
         <span>
           {t('Add an annotation layer')}{' '}
           <a
-            href="/annotationlayermodelview/list"
+            href="/annotationlayer/list"
             target="_blank"
             rel="noopener noreferrer"
           >
@@ -300,7 +300,7 @@ class AnnotationLayer extends React.PureComponent {
     if (isLoadingOptions) {
       if (sourceType === ANNOTATION_SOURCE_TYPES.NATIVE) {
         SupersetClient.get({
-          endpoint: '/annotationlayermodelview/api/read?',
+          endpoint: '/api/v1/annotation_layer/',
         }).then(({ json }) => {
           const layers = json
             ? json.result.map(layer => ({
diff --git 
a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
 
b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
index b9fc64a4c2..c5fed0b865 100644
--- 
a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
+++ 
b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
@@ -36,7 +36,7 @@ beforeAll(() => {
     value => value.value,
   );
 
-  fetchMock.get('glob:*/annotationlayermodelview/api/read?*', {
+  fetchMock.get('glob:*/api/v1/annotation_layer/*', {
     result: [{ label: 'Chart A', value: 'a' }],
   });
 
diff --git a/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx 
b/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx
index 6dedb5e0ea..3e18c3a92f 100644
--- a/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx
+++ b/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx
@@ -259,9 +259,9 @@ function AnnotationList({
             <span>{t('Annotation Layer %s', annotationLayerName)}</span>
             <span>
               {hasHistory ? (
-                <Link to="/annotationlayermodelview/list/">Back to all</Link>
+                <Link to="/annotationlayer/list/">Back to all</Link>
               ) : (
-                <a href="/annotationlayermodelview/list/">Back to all</a>
+                <a href="/annotationlayer/list/">Back to all</a>
               )}
             </span>
           </StyledHeader>
diff --git 
a/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx 
b/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx
index 3914485a6f..ff583e6b9b 100644
--- a/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx
+++ b/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx
@@ -143,12 +143,10 @@ function AnnotationLayersList({
           }
 
           if (hasHistory) {
-            return (
-              <Link to={`/annotationmodelview/${id}/annotation`}>{name}</Link>
-            );
+            return <Link 
to={`/annotationlayer/${id}/annotation`}>{name}</Link>;
           }
 
-          return <a href={`/annotationmodelview/${id}/annotation`}>{name}</a>;
+          return <a href={`/annotationlayer/${id}/annotation`}>{name}</a>;
         },
       },
       {
@@ -324,7 +322,7 @@ function AnnotationLayersList({
   };
 
   const onLayerAdd = (id?: number) => {
-    window.location.href = `/annotationmodelview/${id}/annotation`;
+    window.location.href = `/annotationlayer/${id}/annotation`;
   };
 
   const onModalHide = () => {
diff --git a/superset-frontend/src/views/routes.tsx 
b/superset-frontend/src/views/routes.tsx
index d90feec116..88efa00a64 100644
--- a/superset-frontend/src/views/routes.tsx
+++ b/superset-frontend/src/views/routes.tsx
@@ -156,11 +156,11 @@ export const routes: Routes = [
     Component: CssTemplatesList,
   },
   {
-    path: '/annotationlayermodelview/list/',
+    path: '/annotationlayer/list/',
     Component: AnnotationLayersList,
   },
   {
-    path: '/annotationmodelview/:annotationLayerId/annotation/',
+    path: '/annotationlayer/:annotationLayerId/annotation/',
     Component: AnnotationList,
   },
   {
diff --git a/superset/annotation_layers/annotations/commands/create.py 
b/superset/annotation_layers/annotations/commands/create.py
index dcfa6c8521..26cd968c5a 100644
--- a/superset/annotation_layers/annotations/commands/create.py
+++ b/superset/annotation_layers/annotations/commands/create.py
@@ -70,7 +70,7 @@ class CreateAnnotationCommand(BaseCommand):
 
         # validate date time sanity
         if start_dttm and end_dttm and end_dttm < start_dttm:
-            exceptions.append(AnnotationDatesValidationError)
+            exceptions.append(AnnotationDatesValidationError())
 
         if exceptions:
             exception = AnnotationInvalidError()
diff --git a/superset/initialization/__init__.py 
b/superset/initialization/__init__.py
index 65aaeef26e..8c53c4c8e7 100644
--- a/superset/initialization/__init__.py
+++ b/superset/initialization/__init__.py
@@ -149,10 +149,7 @@ class SupersetAppInitializer:  # pylint: 
disable=too-many-public-methods
         from superset.security.api import SecurityRestApi
         from superset.views.access_requests import AccessRequestsModelView
         from superset.views.alerts import AlertView, ReportView
-        from superset.views.annotations import (
-            AnnotationLayerModelView,
-            AnnotationModelView,
-        )
+        from superset.views.annotations import AnnotationLayerView
         from superset.views.api import Api
         from superset.views.chart.views import SliceAsync, SliceModelView
         from superset.views.core import Superset
@@ -236,16 +233,6 @@ class SupersetAppInitializer:  # pylint: 
disable=too-many-public-methods
             category="Data",
             category_label=__("Data"),
         )
-
-        appbuilder.add_view(
-            AnnotationLayerModelView,
-            "Annotation Layers",
-            label=__("Annotation Layers"),
-            icon="fa-comment",
-            category="Manage",
-            category_label=__("Manage"),
-            category_icon="",
-        )
         appbuilder.add_view(
             DashboardModelView,
             "Dashboards",
@@ -323,7 +310,6 @@ class SupersetAppInitializer:  # pylint: 
disable=too-many-public-methods
         appbuilder.add_view_no_menu(SliceAsync)
         appbuilder.add_view_no_menu(SqlLab)
         appbuilder.add_view_no_menu(SqlMetricInlineView)
-        appbuilder.add_view_no_menu(AnnotationModelView)
         appbuilder.add_view_no_menu(Superset)
         appbuilder.add_view_no_menu(TableColumnInlineView)
         appbuilder.add_view_no_menu(TableModelView)
@@ -401,6 +387,17 @@ class SupersetAppInitializer:  # pylint: 
disable=too-many-public-methods
             menu_cond=lambda: 
feature_flag_manager.is_feature_enabled("ALERT_REPORTS"),
         )
 
+        appbuilder.add_view(
+            AnnotationLayerView,
+            "Annotation Layers",
+            label=_("Annotation Layers"),
+            href="/annotationlayer/list/",
+            icon="fa-comment",
+            category_icon="",
+            category="Manage",
+            category_label=__("Manage"),
+        )
+
         appbuilder.add_view(
             AccessRequestsModelView,
             "Access requests",
diff --git a/superset/views/__init__.py b/superset/views/__init__.py
index c33601f727..5247f215c1 100644
--- a/superset/views/__init__.py
+++ b/superset/views/__init__.py
@@ -17,7 +17,6 @@
 from . import (
     access_requests,
     alerts,
-    annotations,
     api,
     base,
     core,
diff --git a/superset/views/annotations.py b/superset/views/annotations.py
index b9ef65be03..cc8c58fe47 100644
--- a/superset/views/annotations.py
+++ b/superset/views/annotations.py
@@ -14,117 +14,27 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-from typing import Any, Dict
-
-from flask_appbuilder import CompactCRUDMixin
+from flask_appbuilder import permission_name
 from flask_appbuilder.api import expose
-from flask_appbuilder.models.sqla.interface import SQLAInterface
 from flask_appbuilder.security.decorators import has_access
-from flask_babel import lazy_gettext as _
-from wtforms.validators import StopValidation
 
-from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod
-from superset.models.annotations import Annotation, AnnotationLayer
 from superset.superset_typing import FlaskResponse
-from superset.views.base import SupersetModelView
-
-
-class StartEndDttmValidator:  # pylint: disable=too-few-public-methods
-    """
-    Validates dttm fields.
-    """
 
-    def __call__(self, form: Dict[str, Any], field: Any) -> None:
-        if not form["start_dttm"].data and not form["end_dttm"].data:
-            raise StopValidation(_("annotation start time or end time is 
required."))
-        if (
-            form["end_dttm"].data
-            and form["start_dttm"].data
-            and form["end_dttm"].data < form["start_dttm"].data
-        ):
-            raise StopValidation(
-                _("Annotation end time must be no earlier than start time.")
-            )
+from .base import BaseSupersetView
 
 
-class AnnotationModelView(  # pylint: disable=too-many-ancestors
-    SupersetModelView,
-    CompactCRUDMixin,
-):
-    datamodel = SQLAInterface(Annotation)
-    include_route_methods = RouteMethod.CRUD_SET | {"annotation"}
-
+class AnnotationLayerView(BaseSupersetView):
+    route_base = "/annotationlayer"
     class_permission_name = "Annotation"
-    method_permission_name = MODEL_VIEW_RW_METHOD_PERMISSION_MAP
-
-    list_title = _("Annotations")
-    show_title = _("Show Annotation")
-    add_title = _("Add Annotation")
-    edit_title = _("Edit Annotation")
-
-    list_columns = ["short_descr", "start_dttm", "end_dttm"]
-    edit_columns = [
-        "layer",
-        "short_descr",
-        "long_descr",
-        "start_dttm",
-        "end_dttm",
-        "json_metadata",
-    ]
-
-    add_columns = edit_columns
-
-    label_columns = {
-        "layer": _("Layer"),
-        "short_descr": _("Label"),
-        "long_descr": _("Description"),
-        "start_dttm": _("Start"),
-        "end_dttm": _("End"),
-        "json_metadata": _("JSON Metadata"),
-    }
-
-    description_columns = {
-        "json_metadata": "This JSON represents any additional metadata this \
-         annotation needs to add more context."
-    }
-
-    validators_columns = {"start_dttm": [StartEndDttmValidator()]}
-
-    def pre_add(self, item: "AnnotationModelView") -> None:
-        if not item.start_dttm:
-            item.start_dttm = item.end_dttm
-        elif not item.end_dttm:
-            item.end_dttm = item.start_dttm
-
-    def pre_update(self, item: "AnnotationModelView") -> None:
-        self.pre_add(item)
 
-    @expose("/<pk>/annotation/", methods=["GET"])
+    @expose("/list/")
     @has_access
-    def annotation(self, pk: int) -> FlaskResponse:  # pylint: 
disable=unused-argument
+    @permission_name("read")
+    def list(self) -> FlaskResponse:
         return super().render_app_template()
 
-
-class AnnotationLayerModelView(SupersetModelView):
-    datamodel = SQLAInterface(AnnotationLayer)
-    include_route_methods = RouteMethod.CRUD_SET | {RouteMethod.API_READ}
-    related_views = [AnnotationModelView]
-
-    class_permission_name = "Annotation"
-    method_permission_name = MODEL_VIEW_RW_METHOD_PERMISSION_MAP
-
-    list_title = _("Annotation Layers")
-    show_title = _("Show Annotation Layer")
-    add_title = _("Add Annotation Layer")
-    edit_title = _("Edit Annotation Layer")
-
-    list_columns = ["id", "name", "descr"]
-    edit_columns = ["name", "descr"]
-    add_columns = edit_columns
-
-    label_columns = {"name": _("Name"), "descr": _("Description")}
-
-    @expose("/list/")
+    @expose("/<int:pk>/annotation")
     @has_access
-    def list(self) -> FlaskResponse:
+    @permission_name("read")
+    def get(self, pk: int) -> FlaskResponse:  # pylint: disable=unused-argument
         return super().render_app_template()
diff --git a/tests/integration_tests/core_tests.py 
b/tests/integration_tests/core_tests.py
index f25d87d08a..6de21a7200 100644
--- a/tests/integration_tests/core_tests.py
+++ b/tests/integration_tests/core_tests.py
@@ -231,41 +231,6 @@ class TestCore(SupersetTestCase):
         rv = self.client.get(uri)
         self.assertEqual(rv.status_code, 422)
 
-    def test_annotation_json_endpoint(self):
-        # Set up an annotation layer and annotation
-        layer = AnnotationLayer(name="foo", descr="bar")
-        db.session.add(layer)
-        db.session.commit()
-
-        annotation = Annotation(
-            layer_id=layer.id,
-            short_descr="my_annotation",
-            start_dttm=datetime.datetime(2020, 5, 20, 18, 21, 51),
-            end_dttm=datetime.datetime(2020, 5, 20, 18, 31, 51),
-        )
-
-        db.session.add(annotation)
-        db.session.commit()
-
-        self.login()
-        resp_annotations = json.loads(
-            self.get_resp("annotationlayermodelview/api/read")
-        )
-        # the UI needs id and name to function
-        self.assertIn("id", resp_annotations["result"][0])
-        self.assertIn("name", resp_annotations["result"][0])
-
-        response = self.get_resp(
-            f"/superset/annotation_json/{layer.id}?form_data="
-            + quote(json.dumps({"time_range": "100 years ago : now"}))
-        )
-        assert "my_annotation" in response
-
-        # Rollback changes
-        db.session.delete(annotation)
-        db.session.delete(layer)
-        db.session.commit()
-
     def test_admin_only_permissions(self):
         def assert_admin_permission_in(role_name, assert_func):
             role = security_manager.find_role(role_name)

Reply via email to