You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@superset.apache.org by GitBox <gi...@apache.org> on 2021/06/14 07:09:47 UTC

[GitHub] [superset] betodealmeida opened a new pull request #15107: feat: show spinner on exports

betodealmeida opened a new pull request #15107:
URL: https://github.com/apache/superset/pull/15107


   ### SUMMARY
   <!--- Describe the change below, including rationale and design decisions -->
   
   Show a spinner while an export is being generated.
   
   This is tricky because when the user clicks "export" we immediately redirect them to `/api/v1/database/export/?q=${rison.encode([database.id])}` using `window.assign`. So while we can set a spinner, we don't know when the download is generated to stop the spinner.
   
   In order to stop the spinner the frontend generates a short ID, which is passed to the backend with the export request. Once the export is ready, the backend will set a cookie with the short ID as name. The frontend is constantly polling for that cookie, and when it finds the cookie it hides the spinner.
   
   The one problem with this solution is that the GIF stops animating while the export is being generated due to browser limitations. I'm not sure if we can overcome this.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   <!--- Skip this if not applicable -->
   
   Before, no spinner.
   
   After:
   
   
   https://user-images.githubusercontent.com/1534870/121611606-7dddb700-ca0d-11eb-9e2f-6a555d81b06f.mov
   
   
   
   ### TESTING INSTRUCTIONS
   <!--- Required! What steps can be taken to manually verify the changes? -->
   
   ### ADDITIONAL INFORMATION
   <!--- Check any relevant boxes with "x" -->
   <!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
   - [ ] Has associated issue:
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in [SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


[GitHub] [superset] betodealmeida commented on a change in pull request #15107: feat: show spinner on exports

Posted by GitBox <gi...@apache.org>.
betodealmeida commented on a change in pull request #15107:
URL: https://github.com/apache/superset/pull/15107#discussion_r650190972



##########
File path: superset-frontend/src/utils/export.ts
##########
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import parseCookie from 'src/utils/parseCookie';
+import rison from 'rison';
+import shortid from 'shortid';
+
+export default function handleResourceExport(
+  resource: string,
+  ids: number[],
+  done: () => void,
+  interval = 200,
+): void {
+  const token = shortid.generate();
+  const url = `/api/v1/${resource}/export/?q=${rison.encode(
+    ids,
+  )}&token=${token}`;
+
+  // create new iframe for export
+  const iframe = document.createElement('iframe');
+  iframe.style.display = 'none';

Review comment:
       I don't, once the export response finishes a "Save file" dialog pops up automatically even if the iframe is hidden.

##########
File path: superset-frontend/src/utils/export.ts
##########
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import parseCookie from 'src/utils/parseCookie';
+import rison from 'rison';
+import shortid from 'shortid';
+
+export default function handleResourceExport(
+  resource: string,
+  ids: number[],
+  done: () => void,
+  interval = 200,
+): void {
+  const token = shortid.generate();
+  const url = `/api/v1/${resource}/export/?q=${rison.encode(
+    ids,
+  )}&token=${token}`;
+
+  // create new iframe for export
+  const iframe = document.createElement('iframe');
+  iframe.style.display = 'none';
+  iframe.src = url;
+  document.body.appendChild(iframe);
+
+  const timer = window.setInterval(() => {
+    const cookie = parseCookie();

Review comment:
       The type is `CookieMap`, defined in `parseCookie.ts`. Do you mean making it explicit here?

##########
File path: superset/charts/api.py
##########
@@ -918,12 +919,15 @@ def export(self, **kwargs: Any) -> Response:
                 return self.response_404()
         buf.seek(0)
 
-        return send_file(
+        response = send_file(
             buf,
             mimetype="application/zip",
             as_attachment=True,
             attachment_filename=filename,
         )
+        if token:
+            response.set_cookie(token, "done", max_age=600)

Review comment:
       Right, I set it here with an expiration of 5 minutes so we don't need to delete the cookie. Each export has a unique token for the cookie name, so users can do multiple exports at the same time.

##########
File path: superset-frontend/src/views/CRUD/dashboard/DashboardList.tsx
##########
@@ -170,6 +172,14 @@ function DashboardList(props: DashboardListProps) {
     );
   }
 
+  const handleBulkDashboardExport = (dashboardsToExport: Dashboard[]) => {
+    const ids = dashboardsToExport.map(({ id }) => id);
+    handleResourceExport('chart', ids, () => {

Review comment:
       Ouch, good catch!

##########
File path: superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx
##########
@@ -238,6 +240,16 @@ function SavedQueryList({
     );
   };
 
+  const handleBulkSavedQueryExport = (
+    savedQueriesToExport: SavedQueryObject[],
+  ) => {
+    const ids = savedQueriesToExport.map(({ id }) => id);
+    handleResourceExport('chart', ids, () => {

Review comment:
       Too much copy-and-paste :(




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


[GitHub] [superset] betodealmeida merged pull request #15107: feat: show spinner on exports

Posted by GitBox <gi...@apache.org>.
betodealmeida merged pull request #15107:
URL: https://github.com/apache/superset/pull/15107


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


[GitHub] [superset] codecov[bot] edited a comment on pull request #15107: feat: show spinner on exports

Posted by GitBox <gi...@apache.org>.
codecov[bot] edited a comment on pull request #15107:
URL: https://github.com/apache/superset/pull/15107#issuecomment-859174653






-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


[GitHub] [superset] eschutho commented on a change in pull request #15107: feat: show spinner on exports

Posted by GitBox <gi...@apache.org>.
eschutho commented on a change in pull request #15107:
URL: https://github.com/apache/superset/pull/15107#discussion_r650189466



##########
File path: superset-frontend/src/utils/export.ts
##########
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import parseCookie from 'src/utils/parseCookie';
+import rison from 'rison';
+import shortid from 'shortid';
+
+export default function handleResourceExport(
+  resource: string,
+  ids: number[],
+  done: () => void,
+  interval = 200,
+): void {
+  const token = shortid.generate();
+  const url = `/api/v1/${resource}/export/?q=${rison.encode(
+    ids,
+  )}&token=${token}`;
+
+  // create new iframe for export
+  const iframe = document.createElement('iframe');
+  iframe.style.display = 'none';
+  iframe.src = url;
+  document.body.appendChild(iframe);
+
+  const timer = window.setInterval(() => {
+    const cookie = parseCookie();

Review comment:
       do you want to add a type to the cookie so that we know that it will never be undefined or null, so we don't have to worry about cookie[token] erroring?

##########
File path: superset-frontend/src/utils/export.ts
##########
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import parseCookie from 'src/utils/parseCookie';
+import rison from 'rison';
+import shortid from 'shortid';
+
+export default function handleResourceExport(
+  resource: string,
+  ids: number[],
+  done: () => void,
+  interval = 200,
+): void {
+  const token = shortid.generate();
+  const url = `/api/v1/${resource}/export/?q=${rison.encode(
+    ids,
+  )}&token=${token}`;
+
+  // create new iframe for export
+  const iframe = document.createElement('iframe');
+  iframe.style.display = 'none';

Review comment:
       where do you change this so that it's visible?

##########
File path: superset/charts/api.py
##########
@@ -918,12 +919,15 @@ def export(self, **kwargs: Any) -> Response:
                 return self.response_404()
         buf.seek(0)
 
-        return send_file(
+        response = send_file(
             buf,
             mimetype="application/zip",
             as_attachment=True,
             attachment_filename=filename,
         )
+        if token:
+            response.set_cookie(token, "done", max_age=600)

Review comment:
       what do you think about just removing/expiring the cookie instead of changing the value? 

##########
File path: superset/charts/api.py
##########
@@ -918,12 +919,15 @@ def export(self, **kwargs: Any) -> Response:
                 return self.response_404()
         buf.seek(0)
 
-        return send_file(
+        response = send_file(
             buf,
             mimetype="application/zip",
             as_attachment=True,
             attachment_filename=filename,
         )
+        if token:
+            response.set_cookie(token, "done", max_age=600)

Review comment:
       oh, nm. I see.. this is the only cookie that you set, and it doesn't change. 

##########
File path: superset-frontend/src/views/CRUD/dashboard/DashboardList.tsx
##########
@@ -170,6 +172,14 @@ function DashboardList(props: DashboardListProps) {
     );
   }
 
+  const handleBulkDashboardExport = (dashboardsToExport: Dashboard[]) => {
+    const ids = dashboardsToExport.map(({ id }) => id);
+    handleResourceExport('chart', ids, () => {

Review comment:
       is the 'chart' value a typo here for bulk dashboard?

##########
File path: superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx
##########
@@ -238,6 +240,16 @@ function SavedQueryList({
     );
   };
 
+  const handleBulkSavedQueryExport = (
+    savedQueriesToExport: SavedQueryObject[],
+  ) => {
+    const ids = savedQueriesToExport.map(({ id }) => id);
+    handleResourceExport('chart', ids, () => {

Review comment:
       same... query?

##########
File path: superset-frontend/src/utils/export.ts
##########
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import parseCookie from 'src/utils/parseCookie';
+import rison from 'rison';
+import shortid from 'shortid';
+
+export default function handleResourceExport(
+  resource: string,
+  ids: number[],
+  done: () => void,
+  interval = 200,
+): void {
+  const token = shortid.generate();
+  const url = `/api/v1/${resource}/export/?q=${rison.encode(
+    ids,
+  )}&token=${token}`;
+
+  // create new iframe for export
+  const iframe = document.createElement('iframe');
+  iframe.style.display = 'none';
+  iframe.src = url;
+  document.body.appendChild(iframe);
+
+  const timer = window.setInterval(() => {
+    const cookie = parseCookie();

Review comment:
       yeah, I was going to make a comment below that we should make sure that `cookie` exists before trying to access a property on it, and then looked up the return value for cookie and realized that it will never be null or undefined. I was thinking we can define that in typescript here for readability and also for any future changes. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


[GitHub] [superset] codecov[bot] commented on pull request #15107: feat: show spinner on exports

Posted by GitBox <gi...@apache.org>.
codecov[bot] commented on pull request #15107:
URL: https://github.com/apache/superset/pull/15107#issuecomment-859174653


   # [Codecov](https://codecov.io/gh/apache/superset/pull/15107?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) Report
   > Merging [#15107](https://codecov.io/gh/apache/superset/pull/15107?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (b23788a) into [master](https://codecov.io/gh/apache/superset/commit/cc2b4fe3f471814fb75c1c8bce97867c96caaec7?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (cc2b4fe) will **decrease** coverage by `0.00%`.
   > The diff coverage is `58.82%`.
   
   [![Impacted file tree graph](https://codecov.io/gh/apache/superset/pull/15107/graphs/tree.svg?width=650&height=150&src=pr&token=KsB0fHcx6l&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)](https://codecov.io/gh/apache/superset/pull/15107?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)
   
   ```diff
   @@            Coverage Diff             @@
   ##           master   #15107      +/-   ##
   ==========================================
   - Coverage   77.54%   77.53%   -0.01%     
   ==========================================
     Files         967      967              
     Lines       49752    49764      +12     
     Branches     6351     6353       +2     
   ==========================================
   + Hits        38578    38583       +5     
   - Misses      10972    10979       +7     
     Partials      202      202              
   ```
   
   | Flag | Coverage Δ | |
   |---|---|---|
   | javascript | `72.42% <41.66%> (-0.02%)` | :arrow_down: |
   
   Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#carryforward-flags-in-the-pull-request-comment) to find out more.
   
   | [Impacted Files](https://codecov.io/gh/apache/superset/pull/15107?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | Coverage Δ | |
   |---|---|---|
   | [...tend/src/views/CRUD/data/database/DatabaseList.tsx](https://codecov.io/gh/apache/superset/pull/15107/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3VwZXJzZXQtZnJvbnRlbmQvc3JjL3ZpZXdzL0NSVUQvZGF0YS9kYXRhYmFzZS9EYXRhYmFzZUxpc3QudHN4) | `76.47% <41.66%> (-3.91%)` | :arrow_down: |
   | [superset/databases/api.py](https://codecov.io/gh/apache/superset/pull/15107/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3VwZXJzZXQvZGF0YWJhc2VzL2FwaS5weQ==) | `93.04% <100.00%> (ø)` | |
   
   ------
   
   [Continue to review full report at Codecov](https://codecov.io/gh/apache/superset/pull/15107?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).
   > **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)
   > `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
   > Powered by [Codecov](https://codecov.io/gh/apache/superset/pull/15107?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Last update [cc2b4fe...b23788a](https://codecov.io/gh/apache/superset/pull/15107?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


[GitHub] [superset] codecov[bot] edited a comment on pull request #15107: feat: show spinner on exports

Posted by GitBox <gi...@apache.org>.
codecov[bot] edited a comment on pull request #15107:
URL: https://github.com/apache/superset/pull/15107#issuecomment-859174653






-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org