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 2020/01/23 02:47:09 UTC

[GitHub] [incubator-superset] nytai opened a new pull request #8999: [charts] new, list view (react)

nytai opened a new pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999
 
 
   ### CATEGORY
   
   Choose one
   
   - [ ] Bug Fix
   - [x] Enhancement (new features, refinement)
   - [x] Refactor
   - [ ] Add tests
   - [ ] Build / Development Environment
   - [ ] Documentation
   
   ### SUMMARY
   <!--- Describe the change below, including rationale and design decisions -->
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   <!--- Skip this if not applicable -->
   <img width="1141" alt="Screen Shot 2020-01-22 at 6 46 42 PM" src="https://user-images.githubusercontent.com/10255196/72952713-916c7d00-3d47-11ea-97c8-fe5ebb6197db.png">
   
   ### TEST PLAN
   <!--- What steps should be taken to 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:
   - [x] Changes UI
   - [ ] Requires DB Migration.
   - [ ] Confirm DB Migration upgrade and downgrade tested.
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   ### REVIEWERS
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] codecov-io edited a comment on issue #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
codecov-io edited a comment on issue #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#issuecomment-577508862
 
 
   # [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=h1) Report
   > Merging [#8999](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=desc) into [master](https://codecov.io/gh/apache/incubator-superset/commit/a267446f7b3f707d0a49648067087d9767709773?src=pr&el=desc) will **increase** coverage by `0.12%`.
   > The diff coverage is `74.74%`.
   
   [![Impacted file tree graph](https://codecov.io/gh/apache/incubator-superset/pull/8999/graphs/tree.svg?width=650&token=KsB0fHcx6l&height=150&src=pr)](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree)
   
   ```diff
   @@            Coverage Diff             @@
   ##           master    #8999      +/-   ##
   ==========================================
   + Coverage   59.43%   59.56%   +0.12%     
   ==========================================
     Files         369      370       +1     
     Lines       11743    11841      +98     
     Branches     2884     2900      +16     
   ==========================================
   + Hits         6980     7053      +73     
   - Misses       4584     4609      +25     
     Partials      179      179
   ```
   
   
   | [Impacted Files](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree) | Coverage Δ | |
   |---|---|---|
   | [...t/assets/src/views/dashboardList/DashboardList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9kYXNoYm9hcmRMaXN0L0Rhc2hib2FyZExpc3QudHN4) | `73.14% <ø> (-0.25%)` | :arrow_down: |
   | [superset/assets/src/welcome/App.jsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy93ZWxjb21lL0FwcC5qc3g=) | `0% <ø> (ø)` | :arrow_up: |
   | [superset/assets/src/views/chartList/ChartList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9jaGFydExpc3QvQ2hhcnRMaXN0LnRzeA==) | `74.74% <74.74%> (ø)` | |
   
   ------
   
   [Continue to review full report at Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=continue).
   > **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
   > `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
   > Powered by [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=footer). Last update [a267446...3e4f9fb](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] etr2460 commented on issue #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
etr2460 commented on issue #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#issuecomment-580827517
 
 
   Typescript was originally added to Superset as part of SIP-9 (https://github.com/apache/incubator-superset/pull/6120). In general, I think new code should strive to use typescript for the safety and readability that it provides, and if someone started converting old files to .ts or .tsx, I'd personally be quite happy

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] craig-rueda merged pull request #8999: [chart] new, list view (react)

Posted by GitBox <gi...@apache.org>.
craig-rueda merged pull request #8999: [chart] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999
 
 
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] rusackas commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
rusackas commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373186576
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
+              >
+                <i className='fa fa-pencil' />
+              </span>
+            )}
+          </span>
+        );
+      },
+      Header: 'Actions',
+      id: 'actions',
+    },
+  ];
+
+  public hasPerm = (perm: string) => {
+    if (!this.state.permissions.length) {
+      return false;
+    }
+
+    return Boolean(this.state.permissions.find((p) => p === perm));
+  }
+
+  public handleChartEdit = ({ id }: { id: number }) => {
+    window.location.assign(`/chart/edit/${id}`);
+  }
+
+  public handleChartDelete = ({ id, slice_name }: Chart) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/chart/${id}`,
+    }).then(
+      (resp) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(t('Deleted') + ` ${slice_name}`);
+      },
+      (err: any) => {
+        this.props.addDangerToast(t('There was an issue deleting') + `${slice_name}`);
+      },
+    );
+  }
+  public handleBulkDashboardDelete = (charts: Chart[]) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/dashboard/?q=!(${charts.map(({ id }) => id).join(',')})`,
+    }).then(
+      ({ json = {} }) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(json.message);
+      },
+      (err: any) => {
+        console.error(err);
+        this.props.addDangerToast(t('There was an issue deleting the selected dashboards'));
+      },
+    );
+  }
+
+  public fetchData = ({
+    pageIndex,
+    pageSize,
+    sortBy,
+    filters,
+  }: FetchDataConfig) => {
+    this.setState({ loading: true });
+    const filterExps = Object.keys(filters).map((fk) => ({
+      col: fk,
+      opr: filters[fk].filterId,
+      value: filters[fk].filterValue,
+    }));
+
+    const queryParams = JSON.stringify({
+      order_column: sortBy[0].id,
+      order_direction: sortBy[0].desc ? 'desc' : 'asc',
+      page: pageIndex,
+      page_size: pageSize,
+      ...(filterExps.length ? { filters: filterExps } : {}),
+    });
+
+    return SupersetClient.get({
+      endpoint: `/api/v1/chart/?q=${queryParams}`,
+    })
+      .then(({ json = {} }) => {
+        this.setState({ charts: json.result, chartCount: json.count, labelColumns: json.label_columns });
+      })
+      .catch(() => {
+        this.props.addDangerToast(
+          t('An error occurred while fetching Charts'),
+        );
+      })
+      .finally(() => {
+        this.setState({ loading: false });
+      });
+  }
+
+  public componentDidMount() {
+    SupersetClient.get({
+      endpoint: `/api/v1/chart/_info`,
+    })
+      .then(({ json = {} }) => {
+        this.setState({ filterTypes: json.filters, permissions: json.permissions });
+      });
+  }
+
+  public render() {
+    const { charts, chartCount, loading, filterTypes } = this.state;
+    return (
+      <div className='container welcome'>
+        <Panel>
+
+          <ConfirmStatusChange
+            title={t('Please confirm')}
+            description={t('Are you sure you want to delete the selected charts?')}
 
 Review comment:
   Nit: Could address pluralization here too. 

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] rusackas commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
rusackas commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373171934
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
+              >
+                <i className='fa fa-pencil' />
+              </span>
+            )}
+          </span>
+        );
+      },
+      Header: 'Actions',
+      id: 'actions',
+    },
+  ];
+
+  public hasPerm = (perm: string) => {
+    if (!this.state.permissions.length) {
+      return false;
+    }
+
+    return Boolean(this.state.permissions.find((p) => p === perm));
+  }
+
+  public handleChartEdit = ({ id }: { id: number }) => {
+    window.location.assign(`/chart/edit/${id}`);
+  }
+
+  public handleChartDelete = ({ id, slice_name }: Chart) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/chart/${id}`,
+    }).then(
+      (resp) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(t('Deleted') + ` ${slice_name}`);
+      },
+      (err: any) => {
+        this.props.addDangerToast(t('There was an issue deleting') + `${slice_name}`);
+      },
+    );
+  }
+  public handleBulkDashboardDelete = (charts: Chart[]) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/dashboard/?q=!(${charts.map(({ id }) => id).join(',')})`,
+    }).then(
+      ({ json = {} }) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(json.message);
+      },
+      (err: any) => {
+        console.error(err);
+        this.props.addDangerToast(t('There was an issue deleting the selected dashboards'));
 
 Review comment:
   ```suggestion
           this.props.addDangerToast(t(`There was an issue deleting the selected ${charts.length > 1 ? 'dashboards' : 'dashboard'}`));
   ```
   ^ This is probably not the right way to do it with translation factored in, but it's possible to select 1 item with bulk actions, so we may want to get the pluralization right.

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] etr2460 commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
etr2460 commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373594777
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
+              >
+                <i className='fa fa-pencil' />
+              </span>
+            )}
+          </span>
+        );
+      },
+      Header: 'Actions',
+      id: 'actions',
+    },
+  ];
+
+  public hasPerm = (perm: string) => {
+    if (!this.state.permissions.length) {
+      return false;
+    }
+
+    return Boolean(this.state.permissions.find((p) => p === perm));
+  }
+
+  public handleChartEdit = ({ id }: { id: number }) => {
+    window.location.assign(`/chart/edit/${id}`);
+  }
+
+  public handleChartDelete = ({ id, slice_name }: Chart) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/chart/${id}`,
+    }).then(
+      (resp) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(t('Deleted') + ` ${slice_name}`);
+      },
+      (err: any) => {
+        this.props.addDangerToast(t('There was an issue deleting') + `${slice_name}`);
 
 Review comment:
   looks like this is missing a space before slice_name. Although I don't think this translation will actually work anyway. i believe there's a way to put `%s` or something in the translation string so that the full sentence gets parsed for translation. You could look in the code to find it

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] rusackas commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
rusackas commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373187731
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
+              >
+                <i className='fa fa-pencil' />
+              </span>
+            )}
+          </span>
+        );
+      },
+      Header: 'Actions',
+      id: 'actions',
+    },
+  ];
+
+  public hasPerm = (perm: string) => {
+    if (!this.state.permissions.length) {
+      return false;
+    }
+
+    return Boolean(this.state.permissions.find((p) => p === perm));
+  }
+
+  public handleChartEdit = ({ id }: { id: number }) => {
+    window.location.assign(`/chart/edit/${id}`);
+  }
+
+  public handleChartDelete = ({ id, slice_name }: Chart) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/chart/${id}`,
+    }).then(
+      (resp) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(t('Deleted') + ` ${slice_name}`);
+      },
+      (err: any) => {
+        this.props.addDangerToast(t('There was an issue deleting') + `${slice_name}`);
+      },
+    );
+  }
+  public handleBulkDashboardDelete = (charts: Chart[]) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/dashboard/?q=!(${charts.map(({ id }) => id).join(',')})`,
+    }).then(
+      ({ json = {} }) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(json.message);
+      },
+      (err: any) => {
+        console.error(err);
+        this.props.addDangerToast(t('There was an issue deleting the selected dashboards'));
+      },
+    );
+  }
+
+  public fetchData = ({
+    pageIndex,
+    pageSize,
+    sortBy,
+    filters,
+  }: FetchDataConfig) => {
+    this.setState({ loading: true });
+    const filterExps = Object.keys(filters).map((fk) => ({
+      col: fk,
+      opr: filters[fk].filterId,
+      value: filters[fk].filterValue,
+    }));
+
+    const queryParams = JSON.stringify({
+      order_column: sortBy[0].id,
+      order_direction: sortBy[0].desc ? 'desc' : 'asc',
+      page: pageIndex,
+      page_size: pageSize,
+      ...(filterExps.length ? { filters: filterExps } : {}),
+    });
+
+    return SupersetClient.get({
+      endpoint: `/api/v1/chart/?q=${queryParams}`,
+    })
+      .then(({ json = {} }) => {
+        this.setState({ charts: json.result, chartCount: json.count, labelColumns: json.label_columns });
+      })
+      .catch(() => {
+        this.props.addDangerToast(
+          t('An error occurred while fetching Charts'),
+        );
+      })
+      .finally(() => {
+        this.setState({ loading: false });
+      });
+  }
+
+  public componentDidMount() {
+    SupersetClient.get({
+      endpoint: `/api/v1/chart/_info`,
+    })
+      .then(({ json = {} }) => {
+        this.setState({ filterTypes: json.filters, permissions: json.permissions });
+      });
+  }
+
+  public render() {
+    const { charts, chartCount, loading, filterTypes } = this.state;
+    return (
+      <div className='container welcome'>
+        <Panel>
+
+          <ConfirmStatusChange
+            title={t('Please confirm')}
+            description={t('Are you sure you want to delete the selected charts?')}
+            onConfirm={this.handleBulkDashboardDelete}
+          >
+            {(confirmDelete) => {
+              const bulkActions = [];
+              if (this.canDelete) {
+                bulkActions.push({
+                  key: 'delete',
+                  name: <><i className='fa fa-trash' /> Delete</>,
 
 Review comment:
   Should we instead pass a`name` and (optional) `icon` and handle rendering tags on the other side?

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] codecov-io edited a comment on issue #8999: [WIP] [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
codecov-io edited a comment on issue #8999: [WIP] [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#issuecomment-577508862
 
 
   # [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=h1) Report
   > Merging [#8999](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=desc) into [master](https://codecov.io/gh/apache/incubator-superset/commit/bf08ff591c718dd468128f20cbf2ba9dbfe0ffa3?src=pr&el=desc) will **decrease** coverage by `0.43%`.
   > The diff coverage is `0%`.
   
   [![Impacted file tree graph](https://codecov.io/gh/apache/incubator-superset/pull/8999/graphs/tree.svg?width=650&token=KsB0fHcx6l&height=150&src=pr)](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree)
   
   ```diff
   @@            Coverage Diff             @@
   ##           master    #8999      +/-   ##
   ==========================================
   - Coverage   59.16%   58.73%   -0.44%     
   ==========================================
     Files         367      368       +1     
     Lines       11680    11764      +84     
     Branches     2863     2875      +12     
   ==========================================
   - Hits         6910     6909       -1     
   - Misses       4591     4676      +85     
     Partials      179      179
   ```
   
   
   | [Impacted Files](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree) | Coverage Δ | |
   |---|---|---|
   | [superset/assets/src/welcome/App.jsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy93ZWxjb21lL0FwcC5qc3g=) | `0% <ø> (ø)` | :arrow_up: |
   | [...t/assets/src/views/dashboardList/DashboardList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9kYXNoYm9hcmRMaXN0L0Rhc2hib2FyZExpc3QudHN4) | `58.51% <ø> (-0.44%)` | :arrow_down: |
   | [superset/assets/src/views/chartList/ChartList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9jaGFydExpc3QvQ2hhcnRMaXN0LnRzeA==) | `0% <0%> (ø)` | |
   
   ------
   
   [Continue to review full report at Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=continue).
   > **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
   > `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
   > Powered by [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=footer). Last update [bf08ff5...82fa496](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] codecov-io edited a comment on issue #8999: [WIP] [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
codecov-io edited a comment on issue #8999: [WIP] [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#issuecomment-577508862
 
 
   # [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=h1) Report
   > Merging [#8999](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=desc) into [master](https://codecov.io/gh/apache/incubator-superset/commit/d0aab05e79cd52812b5ae8dea8b26ce2f5a476ed?src=pr&el=desc) will **decrease** coverage by `0.5%`.
   > The diff coverage is `0%`.
   
   [![Impacted file tree graph](https://codecov.io/gh/apache/incubator-superset/pull/8999/graphs/tree.svg?width=650&token=KsB0fHcx6l&height=150&src=pr)](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree)
   
   ```diff
   @@            Coverage Diff             @@
   ##           master    #8999      +/-   ##
   ==========================================
   - Coverage   59.43%   58.93%   -0.51%     
   ==========================================
     Files         369      370       +1     
     Lines       11743    11841      +98     
     Branches     2884     2900      +16     
   ==========================================
   - Hits         6980     6979       -1     
   - Misses       4584     4683      +99     
     Partials      179      179
   ```
   
   
   | [Impacted Files](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree) | Coverage Δ | |
   |---|---|---|
   | [superset/assets/src/welcome/App.jsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy93ZWxjb21lL0FwcC5qc3g=) | `0% <ø> (ø)` | :arrow_up: |
   | [...t/assets/src/views/dashboardList/DashboardList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9kYXNoYm9hcmRMaXN0L0Rhc2hib2FyZExpc3QudHN4) | `73.14% <ø> (-0.25%)` | :arrow_down: |
   | [superset/assets/src/views/chartList/ChartList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9jaGFydExpc3QvQ2hhcnRMaXN0LnRzeA==) | `0% <0%> (ø)` | |
   
   ------
   
   [Continue to review full report at Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=continue).
   > **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
   > `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
   > Powered by [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=footer). Last update [d0aab05...c294f2c](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] rusackas commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
rusackas commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r369941972
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.less
 ##########
 @@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+.chart-list-view {
 
 Review comment:
   Not sure this file, or `DashboardList.less`, are necessary. These styles could be moved into `ListViewStyles.less` since they're the same. 
   
   If the chart list, dash list, or other lists are somehow different, then these files MAY be warranted, but I would actually be inclined to add a prop/class to that `ListView` component as a modifier.
   
   Then the list view instances don't need these unique class names, and we don't have to add duplicate CSS files

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] suddjian commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
suddjian commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373142234
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
+              >
+                <i className='fa fa-pencil' />
+              </span>
+            )}
+          </span>
+        );
+      },
+      Header: 'Actions',
+      id: 'actions',
+    },
+  ];
+
+  public hasPerm = (perm: string) => {
+    if (!this.state.permissions.length) {
+      return false;
+    }
+
+    return Boolean(this.state.permissions.find((p) => p === perm));
 
 Review comment:
   ```suggestion
       return this.state.permissions.some((p) => p === perm);
   ```

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] suddjian commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
suddjian commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373144035
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
 
 Review comment:
   I suppose we could bring in the edit modal from #9051 later and trigger a modal instead of following the url.

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] suddjian commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
suddjian commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373144035
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
 
 Review comment:
   I suppose it might make sense to do it this way, could bring in the edit modal from #9051 later and trigger a modal instead of following the url.

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] nytai commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
nytai commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373222553
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
 
 Review comment:
   That was my thinking. It's a link now, but will probably fire an action in the near future

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] rusackas commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
rusackas commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373148290
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
 
 Review comment:
   ![success](https://user-images.githubusercontent.com/812905/73483028-a3f04300-4353-11ea-942a-04664cda30d7.gif)
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] nytai commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
nytai commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373884100
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
+              >
+                <i className='fa fa-pencil' />
+              </span>
+            )}
+          </span>
+        );
+      },
+      Header: 'Actions',
+      id: 'actions',
+    },
+  ];
+
+  public hasPerm = (perm: string) => {
+    if (!this.state.permissions.length) {
+      return false;
+    }
+
+    return Boolean(this.state.permissions.find((p) => p === perm));
+  }
+
+  public handleChartEdit = ({ id }: { id: number }) => {
+    window.location.assign(`/chart/edit/${id}`);
+  }
+
+  public handleChartDelete = ({ id, slice_name }: Chart) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/chart/${id}`,
+    }).then(
+      (resp) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(t('Deleted') + ` ${slice_name}`);
+      },
+      (err: any) => {
+        this.props.addDangerToast(t('There was an issue deleting') + `${slice_name}`);
 
 Review comment:
   Looks like there's docs around this: https://github.com/apache-superset/superset-ui/tree/master/packages/superset-ui-translation
   
   Seems simple enough

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] codecov-io commented on issue #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
codecov-io commented on issue #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#issuecomment-577508862
 
 
   # [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=h1) Report
   > Merging [#8999](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=desc) into [master](https://codecov.io/gh/apache/incubator-superset/commit/bf08ff591c718dd468128f20cbf2ba9dbfe0ffa3?src=pr&el=desc) will **decrease** coverage by `0.43%`.
   > The diff coverage is `0%`.
   
   [![Impacted file tree graph](https://codecov.io/gh/apache/incubator-superset/pull/8999/graphs/tree.svg?width=650&token=KsB0fHcx6l&height=150&src=pr)](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree)
   
   ```diff
   @@            Coverage Diff             @@
   ##           master    #8999      +/-   ##
   ==========================================
   - Coverage   59.16%   58.72%   -0.44%     
   ==========================================
     Files         367      368       +1     
     Lines       11680    11766      +86     
     Branches     2863     2875      +12     
   ==========================================
     Hits         6910     6910              
   - Misses       4591     4677      +86     
     Partials      179      179
   ```
   
   
   | [Impacted Files](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree) | Coverage Δ | |
   |---|---|---|
   | [superset/assets/src/welcome/App.jsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy93ZWxjb21lL0FwcC5qc3g=) | `0% <ø> (ø)` | :arrow_up: |
   | [superset/assets/src/views/chartList/ChartList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9jaGFydExpc3QvQ2hhcnRMaXN0LnRzeA==) | `0% <0%> (ø)` | |
   
   ------
   
   [Continue to review full report at Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=continue).
   > **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
   > `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
   > Powered by [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=footer). Last update [bf08ff5...bb64244](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] suddjian commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
suddjian commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373143078
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
 
 Review comment:
   why not a link?

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] codecov-io edited a comment on issue #8999: [chart] new, list view (react)

Posted by GitBox <gi...@apache.org>.
codecov-io edited a comment on issue #8999: [chart] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#issuecomment-577508862
 
 
   # [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=h1) Report
   > Merging [#8999](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=desc) into [master](https://codecov.io/gh/apache/incubator-superset/commit/6cb4ce0e192830b73d10c66f8f557388ba944ca1?src=pr&el=desc) will **increase** coverage by `0.12%`.
   > The diff coverage is `74.74%`.
   
   [![Impacted file tree graph](https://codecov.io/gh/apache/incubator-superset/pull/8999/graphs/tree.svg?width=650&token=KsB0fHcx6l&height=150&src=pr)](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree)
   
   ```diff
   @@            Coverage Diff             @@
   ##           master    #8999      +/-   ##
   ==========================================
   + Coverage   59.15%   59.28%   +0.12%     
   ==========================================
     Files         370      371       +1     
     Lines       11818    11916      +98     
     Branches     2900     2916      +16     
   ==========================================
   + Hits         6991     7064      +73     
   - Misses       4648     4673      +25     
     Partials      179      179
   ```
   
   
   | [Impacted Files](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=tree) | Coverage Δ | |
   |---|---|---|
   | [...t/assets/src/views/dashboardList/DashboardList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9kYXNoYm9hcmRMaXN0L0Rhc2hib2FyZExpc3QudHN4) | `73.14% <ø> (-0.25%)` | :arrow_down: |
   | [superset/assets/src/welcome/App.jsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy93ZWxjb21lL0FwcC5qc3g=) | `0% <ø> (ø)` | :arrow_up: |
   | [superset/assets/src/views/chartList/ChartList.tsx](https://codecov.io/gh/apache/incubator-superset/pull/8999/diff?src=pr&el=tree#diff-c3VwZXJzZXQvYXNzZXRzL3NyYy92aWV3cy9jaGFydExpc3QvQ2hhcnRMaXN0LnRzeA==) | `74.74% <74.74%> (ø)` | |
   
   ------
   
   [Continue to review full report at Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=continue).
   > **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
   > `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
   > Powered by [Codecov](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=footer). Last update [6cb4ce0...fd9b315](https://codecov.io/gh/apache/incubator-superset/pull/8999?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] rusackas commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
rusackas commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373148079
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
 
 Review comment:
   ![danger](https://user-images.githubusercontent.com/812905/73482998-9470fa00-4353-11ea-8632-9e2e0f93b12c.gif)
   

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] etr2460 commented on a change in pull request #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
etr2460 commented on a change in pull request #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#discussion_r373594897
 
 

 ##########
 File path: superset/assets/src/views/chartList/ChartList.tsx
 ##########
 @@ -0,0 +1,316 @@
+/**
+ * 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 { SupersetClient } from '@superset-ui/connection';
+import { t } from '@superset-ui/translation';
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React from 'react';
+// @ts-ignore
+import { Button, Modal, Panel } from 'react-bootstrap';
+import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
+import ListView from 'src/components/ListView/ListView';
+import { FetchDataConfig, FilterTypeMap } from 'src/components/ListView/types';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+
+const PAGE_SIZE = 25;
+
+interface Props {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+interface State {
+  chartCount: number;
+  charts: any[];
+  filterTypes: FilterTypeMap;
+  labelColumns: { [key: string]: string };
+  lastFetchDataConfig: FetchDataConfig | null;
+  loading: boolean;
+  permissions: string[];
+}
+
+interface Chart {
+  changed_on: string;
+  creator: string;
+  id: number;
+  slice_name: string;
+  url: string;
+  viz_type: string;
+}
+
+class ChartList extends React.PureComponent<Props, State> {
+
+  get canEdit() {
+    return this.hasPerm('can_edit');
+  }
+
+  get canDelete() {
+    return this.hasPerm('can_delete');
+  }
+
+  public static propTypes = {
+    addDangerToast: PropTypes.func.isRequired,
+  };
+
+  public state: State = {
+    chartCount: 0,
+    charts: [],
+    filterTypes: {},
+    labelColumns: {},
+    lastFetchDataConfig: null,
+    loading: false,
+    permissions: [],
+  };
+
+  public initialSort = [{ id: 'changed_on', desc: true }];
+
+  public columns = [
+    {
+      Cell: ({
+        row: {
+          original: { url, slice_name },
+        },
+      }: any) => <a href={url}>{slice_name}</a>,
+      Header: t('Chart'),
+      accessor: 'slice_name',
+      filterable: true,
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { viz_type },
+        },
+      }: any) => viz_type,
+      Header: t('Visualization Type'),
+      accessor: 'viz_type',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { datasource_name_text, datasource_link },
+        },
+      }: any) => <a href={datasource_link}>{datasource_name_text}</a>,
+      Header: t('Datasource'),
+      accessor: 'datasource_name_text',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_by_name, changed_by_url },
+        },
+      }: any) => <a href={changed_by_url}>{changed_by_name}</a>,
+      Header: t('Creator'),
+      accessor: 'creator',
+      sortable: true,
+    },
+    {
+      Cell: ({
+        row: {
+          original: { changed_on },
+        },
+      }: any) => (
+          <span className='no-wrap'>{moment(changed_on).fromNow()}</span>
+        ),
+      Header: t('Last Modified'),
+      accessor: 'changed_on',
+      sortable: true,
+    },
+    {
+      Cell: ({ row: { state, original } }: any) => {
+        const handleDelete = () => this.handleChartDelete(original);
+        const handleEdit = () => this.handleChartEdit(original);
+        if (!this.canEdit && !this.canDelete) {
+          return null;
+        }
+
+        return (
+          <span className={`actions ${state && state.hover ? '' : 'invisible'}`}>
+            {this.canDelete && (
+              <ConfirmStatusChange
+                title={t('Please Confirm')}
+                description={<>{t('Are you sure you want to delete')} <b>{original.slice_name}</b>?</>}
+                onConfirm={handleDelete}
+              >
+                {(confirmDelete) => (
+                  <span
+                    role='button'
+                    className='action-button'
+                    onClick={confirmDelete}
+                  >
+                    <i className='fa fa-trash' />
+                  </span>
+                )}
+              </ConfirmStatusChange>
+            )}
+            {this.canEdit && (
+              <span
+                role='button'
+                className='action-button'
+                onClick={handleEdit}
+              >
+                <i className='fa fa-pencil' />
+              </span>
+            )}
+          </span>
+        );
+      },
+      Header: 'Actions',
+      id: 'actions',
+    },
+  ];
+
+  public hasPerm = (perm: string) => {
+    if (!this.state.permissions.length) {
+      return false;
+    }
+
+    return Boolean(this.state.permissions.find((p) => p === perm));
+  }
+
+  public handleChartEdit = ({ id }: { id: number }) => {
+    window.location.assign(`/chart/edit/${id}`);
+  }
+
+  public handleChartDelete = ({ id, slice_name }: Chart) => {
+    SupersetClient.delete({
+      endpoint: `/api/v1/chart/${id}`,
+    }).then(
+      (resp) => {
+        const { lastFetchDataConfig } = this.state;
+        if (lastFetchDataConfig) {
+          this.fetchData(lastFetchDataConfig);
+        }
+        this.props.addSuccessToast(t('Deleted') + ` ${slice_name}`);
 
 Review comment:
   Same comment as below about fixing the translation 

----------------------------------------------------------------
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


With regards,
Apache Git Services

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


[GitHub] [incubator-superset] robdiciuccio commented on issue #8999: [charts] new, list view (react)

Posted by GitBox <gi...@apache.org>.
robdiciuccio commented on issue #8999: [charts] new, list view (react)
URL: https://github.com/apache/incubator-superset/pull/8999#issuecomment-580816120
 
 
   A little off-topic, but I'm not seeing any guidelines or SIPs related to TypeScript usage in Superset. Have there been any discussions about Typescript vs vanilla JS? The recent React CRUD view PRs have started introducing .tsx, but previous TypeScript usage was pretty incidental. Would love to get some consensus around this before pushing full steam ahead on TypeScript.

----------------------------------------------------------------
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


With regards,
Apache Git Services

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