diff --git a/Tombolo/client-reactjs/src/App.js b/Tombolo/client-reactjs/src/App.js
index 2f3c9427c..ec5e41354 100644
--- a/Tombolo/client-reactjs/src/App.js
+++ b/Tombolo/client-reactjs/src/App.js
@@ -33,7 +33,6 @@ const FileTemplate = React.lazy(() => import('./components/application/templates
const JobDetailsForm = React.lazy(() => import('./components/application/Jobs/JobDetails'));
const IndexDetailsForm = React.lazy(() => import('./components/application/IndexDetails'));
const QueryDetailsForm = React.lazy(() => import('./components/application/queries/QueryDetails'));
-const VisualizationDetailsForm = React.lazy(() => import('./components/application/VisualizationDetails'));
const ManualJobDetail = React.lazy(() => import('./components/application/Jobs/ManualJobDetail'));
const Actions = React.lazy(() => import('./components/application/actions/actions'));
const AddJobsForm = React.lazy(() => import('./components/application/Jobs/AddjobsForm/AddJobsForm'));
@@ -375,10 +374,6 @@ class App extends React.Component {
-
{
+ const handleEdit = (id, type, action) => {
dispatch(assetsActions.assetSelected(id, applicationId, ''));
switch (type) {
@@ -99,9 +92,6 @@ function AssetsTable({ openGroup, handleEditGroup, refreshGroups }) {
case 'Query':
history.push('/' + applicationId + '/assets/query/' + id);
break;
- case 'RealBI Dashboard':
- window.open(vizUrl);
- break;
case 'Group':
if (action !== 'edit') {
openGroup(id);
@@ -153,10 +143,6 @@ function AssetsTable({ openGroup, handleEditGroup, refreshGroups }) {
deleteUrl = '/api/groups';
method = 'delete';
break;
- case 'RealBI Dashboard':
- data = JSON.stringify({ id: id });
- deleteUrl = '/api/file/read/deleteVisualization';
- break;
default:
break;
}
@@ -189,32 +175,6 @@ function AssetsTable({ openGroup, handleEditGroup, refreshGroups }) {
dispatch(assetsActions.assetInGroupSelected(groupId));
};
- const handleCreateVisualization = (id, cluster_id) => {
- console.log(cluster_id);
- fetch('/api/file/read/visualization', {
- method: 'post',
- headers: authHeader(),
- body: JSON.stringify({
- id: id,
- application_id: applicationId,
- email: authReducer.user.email,
- editingAllowed: editingAllowed,
- }),
- })
- .then(function (response) {
- if (response.ok && response.status == 200) {
- return response.json();
- }
- handleError(response);
- })
- .then(function (data) {
- if (data && data.success) {
- fetchDataAndRenderTable();
- window.open(data.url);
- }
- });
- };
-
const generateAssetIcon = (type) => {
const icons = {
Job: ,
@@ -223,7 +183,6 @@ function AssetsTable({ openGroup, handleEditGroup, refreshGroups }) {
Query: ,
Group: ,
'File Template': ,
- 'RealBI Dashboard': ,
};
return {icons[type]};
};
@@ -391,25 +350,6 @@ function AssetsTable({ openGroup, handleEditGroup, refreshGroups }) {
}
/>
-
- {record.type === 'File' ? (
- record.visualization ? (
- }>
-
-
-
-
- ) : (
- handleCreateVisualization(record.id, record.cluster_id)}
- icon={}>
- }>
-
-
-
- )
- ) : null}
),
},
diff --git a/Tombolo/client-reactjs/src/components/application/Assets/index.js b/Tombolo/client-reactjs/src/components/application/Assets/index.js
index 07fb6c715..d8e57ca13 100644
--- a/Tombolo/client-reactjs/src/components/application/Assets/index.js
+++ b/Tombolo/client-reactjs/src/components/application/Assets/index.js
@@ -172,7 +172,6 @@ const Assets = () => {
File: () => goTo('file'),
Index: () => goTo('index'),
Query: () => goTo('query'),
- 'RealBI Dashboard': () => goTo('visualizations'),
'File Template': () => goTo('fileTemplate'),
Group: () => openNewGroupDialog({ edit: false, groupId: '' }),
'Edit-Group': () => openNewGroupDialog({ edit: true, groupId: '' }),
@@ -301,7 +300,6 @@ const Assets = () => {
{ key: 'Job', icon: , label: 'Job' },
{ key: 'Query', icon: , label: 'Query' },
{ key: 'Index', icon: , label: 'Index' },
- { key: 'RealBI Dashboard', icon: , label: 'RealBI Dashboard' },
];
//Generate PDF & printing task complete function
diff --git a/Tombolo/client-reactjs/src/components/application/VisualizationDetails.js b/Tombolo/client-reactjs/src/components/application/VisualizationDetails.js
deleted file mode 100644
index 73c3c78c5..000000000
--- a/Tombolo/client-reactjs/src/components/application/VisualizationDetails.js
+++ /dev/null
@@ -1,244 +0,0 @@
-import React, { useState, useCallback } from 'react';
-import { useSelector } from 'react-redux';
-import { hasEditPermission } from '../common/AuthUtil.js';
-import ReactMarkdown from 'react-markdown';
-import MonacoEditor from '../common/MonacoEditor.js';
-import { Row, Col, Button, Form, Input, Select, Tabs, Spin, AutoComplete, message, Space } from 'antd';
-import { authHeader, handleError } from '../common/AuthHeader.js';
-import Text, { i18n } from '../common/Text.jsx';
-
-import { debounce } from 'lodash';
-import { useHistory } from 'react-router';
-
-const TabPane = Tabs.TabPane;
-const Option = Select.Option;
-
-const formItemLayout = {
- labelCol: { span: 2 },
- wrapperCol: { span: 8 },
-};
-
-const initSelectedFile = {
- id: '',
- url: '',
- name: '',
- title: '',
- cluster_id: '',
- description: '',
-};
-
-function VisualizationDetails() {
- const [authReducer, assetReducer, applicationReducer] = useSelector((state) => [
- state.authenticationReducer,
- state.assetReducer,
- state.applicationReducer,
- ]);
- const [form] = Form.useForm();
- const history = useHistory();
- const [formState, setFormState] = useState({ enableEdit: true, dataAltered: false, loading: false });
-
- const [search, setSearch] = useState({ loading: false, error: '', data: [] });
-
- const [selectedFile, setSelectedFile] = useState({ ...initSelectedFile });
-
- const editingAllowed = hasEditPermission(authReducer.user);
-
- const handleCancel = () => history.push('/' + applicationReducer.application.applicationId + '/assets');
-
- const switchToViewOnly = () => setFormState((prev) => ({ ...prev, enableEdit: false, dataAltered: true }));
-
- const makeFieldsEditable = () => setFormState((prev) => ({ ...prev, enableEdit: true }));
-
- const onChange = () => setFormState((prev) => ({ ...prev, dataAltered: true }));
-
- const handleOk = async (e) => {
- e.preventDefault();
- try {
- await form.validateFields();
- setFormState((prev) => ({ ...prev, loading: true }));
-
- const options = {
- headers: authHeader(),
- method: 'POST',
- body: JSON.stringify({
- id: selectedFile.id,
- fileName: selectedFile.name,
- email: authReducer.user.email,
- editingAllowed: editingAllowed,
- clusterId: selectedFile.cluster_id,
- description: selectedFile.description,
- application_id: applicationReducer.application.applicationId,
- groupId: assetReducer.newAsset.groupId ? assetReducer.newAsset.groupId : '',
- }),
- };
-
- const response = await fetch('/api/file/read/visualization', options);
- if (!response.ok) handleError(response);
-
- const data = await response.json();
-
- if (data?.success) {
- history.push('/' + applicationReducer.application.applicationId + '/assets');
- } else {
- throw data;
- }
- } catch (error) {
- console.log('-error--handleOk---------------------------------------');
- console.dir({ error }, { depth: null });
- console.log('------------------------------------------');
-
- message.error('Failed to get create visualization');
- }
- setFormState((prev) => ({ ...prev, loading: false }));
- };
-
- const clearState = () => {
- setSearch((prev) => ({ ...prev, data: [] }));
- setSelectedFile({ ...initSelectedFile });
- form.resetFields(['name', 'fileSearchValue']);
- };
-
- const searchFiles = useCallback(
- debounce(async (searchString) => {
- if (searchString.length <= 3) return;
- if (!searchString.match(/^[a-zA-Z0-9_ -]*$/)) {
- return message.error('Invalid search keyword. Please remove any special characters from the keyword.');
- }
-
- try {
- setSearch((prev) => ({ ...prev, loading: true, error: '' }));
- const options = {
- method: 'POST',
- headers: authHeader(),
- body: JSON.stringify({
- app_id: applicationReducer.application.applicationId,
- keyword: searchString.trim(),
- }),
- };
-
- const response = await fetch('/api/file/read/tomboloFileSearch', options);
- if (!response.ok) handleError(response);
-
- const suggestions = await response.json();
- setSearch((prev) => ({ prev, loading: false, data: suggestions }));
- } catch (error) {
- console.log('-error-----------------------------------------');
- console.dir({ error }, { depth: null });
- console.log('------------------------------------------');
- message.error('There was an error searching the files from cluster.');
- setSearch((prev) => ({ ...prev, loading: false, error: error.message }));
- }
- }, 500),
- []
- );
-
- const onFileSelected = (fileName) => {
- const file = search.data.find((file) => file.name === fileName);
- setSelectedFile(file);
- form.setFieldsValue({ name: file.title });
- };
-
- const onChangeMD = (e) => {
- if (!formState.dataAltered) onChange();
- setSelectedFile((prev) => ({ ...prev, description: e.target.value }));
- };
-
- const controls = (
-
- {formState.enableEdit ? (
-
- ) : (
-
- )}
-
-
-
- );
-
- return (
-
-
- } key="1">
-
- } name="fileSearchValue">
-
-
- searchFiles(value)}
- onSelect={(value) => onFileSelected(value)}
- placeholder={i18n('Search jobs')}
- disabled={!editingAllowed}
- notFoundContent={search.loading ? : 'Not Found'}>
- {search.data.map((suggestion) => (
-
- ))}
-
-
-
-
-
-
-
- )}
- }
- name="name"
- validateTrigger={['onChange', 'onBlur']}
- rules={[
- { required: formState.enableEdit, message: 'Please enter a name!' },
- { pattern: new RegExp(/^[a-zA-Z0-9:._ -]*$/), message: 'Please enter a valid name' },
- {
- max: 256,
- message: 'Maximum of 256 characters allowed',
- },
- ]}>
-
-
-
- }>
- {formState.enableEdit ? (
-
- ) : (
-
-
-
- )}
-
-
-
-
-
-
- );
-}
-
-export default VisualizationDetails;
diff --git a/Tombolo/server/migrations/20220507024107-create-visualizations.js b/Tombolo/server/migrations/20220507024107-create-visualizations.js
deleted file mode 100644
index eb5121cda..000000000
--- a/Tombolo/server/migrations/20220507024107-create-visualizations.js
+++ /dev/null
@@ -1,59 +0,0 @@
-'use strict';
-module.exports = {
- up: (queryInterface, Sequelize) => {
- return queryInterface.createTable('visualizations', {
- id: {
- allowNull: false,
- primaryKey: true,
- type: Sequelize.UUID,
- defaultValue: Sequelize.UUIDV4,
- },
- name: Sequelize.STRING,
- description: Sequelize.STRING,
- type: Sequelize.STRING,
- url: Sequelize.STRING,
- assetId: {
- type: Sequelize.UUID,
- references: {
- model: 'file',
- key: 'id',
- },
- onUpdate: 'CASCADE',
- onDelete: 'CASCADE',
- },
- clusterId: {
- type: Sequelize.UUID,
- references: {
- model: 'cluster',
- key: 'id',
- },
- onUpdate: 'CASCADE',
- onDelete: 'CASCADE',
- },
- application_id: {
- type: Sequelize.UUID,
- references: {
- model: 'application',
- key: 'id',
- },
- onUpdate: 'CASCADE',
- onDelete: 'CASCADE',
- },
- createdAt: {
- allowNull: false,
- type: Sequelize.DATE,
- },
- updatedAt: {
- allowNull: false,
- type: Sequelize.DATE,
- },
- deletedAt: {
- allowNull: true,
- type: Sequelize.DATE,
- },
- });
- },
- down: (queryInterface, Sequelize) => {
- return queryInterface.dropTable('visualizations');
- },
-};
diff --git a/Tombolo/server/models/application.js b/Tombolo/server/models/application.js
index 4b1c5cdc8..05fc9a718 100644
--- a/Tombolo/server/models/application.js
+++ b/Tombolo/server/models/application.js
@@ -25,11 +25,6 @@ module.exports = (sequelize, DataTypes) => {
onDelete: "CASCADE",
hooks: true,
});
- /* VISUALIZATIONS */
- application.hasMany(models.visualizations, {
- foreignKey: "application_id",
- onDelete: "CASCADE",
- });
/* GITHUB SETTINGS */
application.hasMany(models.github_repo_settings, {
foreignKey: "application_id",
diff --git a/Tombolo/server/models/cluster.js b/Tombolo/server/models/cluster.js
index 1a22da9da..e3499e047 100644
--- a/Tombolo/server/models/cluster.js
+++ b/Tombolo/server/models/cluster.js
@@ -79,10 +79,6 @@ module.exports = (sequelize, DataTypes) => {
cluster.hasMany(models.dataflow_cluster_credentials, {
foreignKey: "cluster_id",
});
- cluster.hasMany(models.visualizations, {
- foreignKey: "clusterId",
- onDelete: "CASCADE",
- });
cluster.hasMany(models.fileTemplate, {
foreignKey: "cluster_id",
onDelete: "CASCADE",
diff --git a/Tombolo/server/models/file.js b/Tombolo/server/models/file.js
index 108c2f9bb..1b36bcb80 100644
--- a/Tombolo/server/models/file.js
+++ b/Tombolo/server/models/file.js
@@ -51,11 +51,6 @@ module.exports = (sequelize, DataTypes) => {
otherKey: 'job_id',
});
- file.hasOne(models.visualizations, {
- foreignKey:'assetId',
- onDelete: 'CASCADE',
- });
-
};
return file;
};
diff --git a/Tombolo/server/models/groups.js b/Tombolo/server/models/groups.js
index 887e2fae7..8f5a148ed 100644
--- a/Tombolo/server/models/groups.js
+++ b/Tombolo/server/models/groups.js
@@ -53,15 +53,6 @@ module.exports = (sequelize, DataTypes) => {
foreignKey: 'groupId',
otherKey: 'assetId'
});
- groups.belongsToMany(models.visualizations, {
- constraints:false,
- foreignKeyConstraint:false,
- through: 'assets_groups',
- as: 'visualizations',
- foreignKey: 'groupId',
- otherKey: 'assetId'
-
- });
// groups.hasMany(models.groups, {
// as: 'child',
diff --git a/Tombolo/server/models/visualization.js b/Tombolo/server/models/visualization.js
deleted file mode 100644
index 9755522fb..000000000
--- a/Tombolo/server/models/visualization.js
+++ /dev/null
@@ -1,35 +0,0 @@
-'use strict';
-module.exports = (sequelize, DataTypes) => {
- const visualization = sequelize.define('visualizations', {
- id: {
- primaryKey: true,
- type: DataTypes.UUID,
- defaultValue: DataTypes.UUIDV4,
- allowNull: false,
- autoIncrement: false
- },
- assetId: DataTypes.UUID,
- name: DataTypes.STRING,
- description: DataTypes.STRING,
- application_id: DataTypes.UUID,
- type: DataTypes.STRING,
- url: DataTypes.STRING,
- clusterId: DataTypes.UUID
- }, {paranoid: true, freezeTableName: true});
- visualization.associate = function(models) {
- visualization.belongsToMany(models.groups, {
- constraints: false,
- foreignKeyConstraint:false,
- through: 'assets_groups',
- as: 'groups',
- foreignKey: 'assetId',
- otherKey: 'groupId'
- });
-
- visualization.belongsTo(models.file, { foreignKey: 'assetId' });
- visualization.belongsTo(models.cluster, { foreignKey: 'clusterId' });
- visualization.belongsTo(models.application, { foreignKey: 'application_id' });
-
- };
- return visualization;
-};
\ No newline at end of file
diff --git a/Tombolo/server/routes/file/read.js b/Tombolo/server/routes/file/read.js
index b75d22bf5..228149bd4 100644
--- a/Tombolo/server/routes/file/read.js
+++ b/Tombolo/server/routes/file/read.js
@@ -21,7 +21,6 @@ let Indexes = models.indexes;
let Query = models.query;
let Job = models.job;
const JobFile = models.jobfile;
-let Visualization = models.visualizations;
var request = require("request");
const validatorUtil = require("../../utils/validator");
const { body, query, validationResult } = require("express-validator");
@@ -603,175 +602,6 @@ router.get("/dataTypes", (req, res) => {
}
});
-router.post(
- "/visualization",
- [
- body("id")
- .optional({ checkFalsy: true })
- .isUUID(4)
- .withMessage("Invalid file id"),
- body("application_id").isUUID(4).withMessage("Invalid application id"),
- body("email").isEmail().withMessage("Invalid email"),
- body("fileName")
- .optional({ checkFalsy: true })
- .matches(/^[a-zA-Z]{1}[a-zA-Z0-9_:.\ -]*$/)
- .withMessage("Invalid name"),
- body("clusterId")
- .optional({ checkFalsy: true })
- .isUUID(4)
- .withMessage("Invalid cluster"),
- body("groupId")
- .optional({ checkFalsy: true })
- .isInt()
- .withMessage("Invalid groupId"),
- body("editingAllowed")
- .isBoolean()
- .withMessage("Invalid value for editingAllowed"),
- ],
- async (req, res) => {
- const errors = validationResult(req).formatWith(
- validatorUtil.errorFormatter
- );
- if (!errors.isEmpty()) {
- return res.status(422).json({ success: false, errors: errors.array() });
- }
-
- try {
- let file = null,
- cluster = null,
- bodyObj = {},
- authToken = "";
- if (req.body.id) {
- file = await File.findOne({ where: { id: req.body.id } });
- }
-
- if (file && file.cluster_id) {
- cluster = await Cluster.findOne({ where: { id: file.cluster_id } });
- }
-
- bodyObj = {
- filename: file ? file.name : req.body.name,
- workspaceName: "Tombolo",
- dashboardName: file && file.name ? file.name : req.body.fileName,
- editingAllowed: req.body.editingAllowed,
- };
-
- if (cluster) {
- bodyObj.cluster = {
- name: cluster.name,
- host: cluster.thor_host,
- infoPort: cluster.thor_port,
- dataPort: cluster.roxie_port,
- };
- }
-
- if (
- req.headers["authorization"] &&
- req.headers["authorization"].startsWith("Bearer ")
- ) {
- authToken = req.headers["authorization"].slice(
- 7,
- req.headers["authorization"].length
- );
- }
-
- request.post(
- {
- url: process.env["REALBI_URL"] + "/api/v1/integration",
- body: JSON.stringify(bodyObj),
- headers: {
- "content-type": "application/json",
- Authorization: authToken,
- },
- },
- async function (err, response, body) {
- if (err) {
- console.log("ERROR - ", err);
- return res
- .status(500)
- .send("Error occured while creating visualization");
- } else {
- var result = JSON.parse(body);
-
- let viz = await Visualization.create({
- name: req.body.fileName ? req.body.fileName : file.name,
- application_id: req.body.application_id,
- url: result.workspaceUrl,
- type: req.body.type,
- description: req.body.description,
- assetId: file ? file.id : "",
- clusterId: file ? file.cluster_id : "",
- });
- if (req.body.groupId && req.body.groupId != "") {
- let assetsGroups = await AssetsGroups.findOrCreate({
- where: { assetId: viz.id, groupId: req.body.groupId },
- defaults: {
- assetId: viz.id,
- groupId: req.body.groupId,
- },
- });
- }
- res.json({ success: true, url: result.workspaceUrl });
- }
- }
- );
- } catch (err) {
- console.log(err);
- return res.status(500).send("Error occured while creating visualization");
- }
- }
-);
-
-router.post(
- "/deleteVisualization",
- [body("id").isUUID(4).withMessage("Invalid id")],
- async (req, res) => {
- const errors = validationResult(req).formatWith(
- validatorUtil.errorFormatter
- );
- if (!errors.isEmpty()) {
- return res.status(422).json({ success: false, errors: errors.array() });
- }
- try {
- let vizDestroyed = await Visualization.destroy({
- where: { id: req.body.id },
- });
- let assetsGroupsDestroyed = await AssetsGroups.destroy({
- where: { assetId: req.body.id },
- });
-
- res.json({ success: true });
- } catch (err) {
- console.log(err);
- return res.status(500).send("Error occured while deleting visualization");
- }
- }
-);
-
-router.get(
- "/getVisualizationDetails",
- [query("id").isUUID(4).withMessage("Invalid id")],
- async (req, res) => {
- const errors = validationResult(req).formatWith(
- validatorUtil.errorFormatter
- );
- if (!errors.isEmpty()) {
- return res.status(422).json({ success: false, errors: errors.array() });
- }
- try {
- let visualization = await Visualization.findOne({
- where: { id: req.query.id },
- attributes: ["id", "name", "url", "description", "clusterId"],
- });
- res.json(visualization);
- } catch (err) {
- console.log(err);
- return res
- .status(500)
- .send("Error occured while retrieving visualization details");
- }
- }
-);
router.post(
"/tomboloFileSearch",
@@ -795,7 +625,7 @@ router.post(
console.log(err);
return res
.status(500)
- .send("Error occured while retrieving visualization details");
+ .send("Error occured while retrieving file details");
}
}
);
diff --git a/Tombolo/server/routes/groups/group.js b/Tombolo/server/routes/groups/group.js
index b0c16c013..d1291021e 100644
--- a/Tombolo/server/routes/groups/group.js
+++ b/Tombolo/server/routes/groups/group.js
@@ -11,7 +11,6 @@ let Index = models.indexes;
let File = models.file;
let Query = models.query;
let Job = models.job;
-let Visualization = models.visualizations;
let AssetsGroups = models.assets_groups;
let FileTemplate = models.fileTemplate;
@@ -180,14 +179,11 @@ router.get('/assets', [
"id": req.query.group_id
},
include: [
- {model:File, as:'files', attributes:['id', 'name', 'title', 'description', 'createdAt'],
- include:[{model: Visualization}]
- },
+ {model:File, as:'files', attributes:['id', 'name', 'title', 'description', 'createdAt']},
{model:FileTemplate, as:'fileTemplates', attributes:['id', 'title', 'description', 'createdAt']},
{model:Job, as: 'jobs', attributes:['id', 'name', 'title', 'description', 'createdAt']},
{model:Query, as: 'queries', attributes:['id', 'name', 'title', 'description', 'createdAt']},
{model:Index, as: 'indexes', attributes:['id', 'name', 'title', 'description', 'createdAt']},
- {model:Visualization, as: 'visualizations', attributes:['id', 'name', 'description', 'url', 'createdAt']}
],
order: [['name', 'ASC']]
}).then(async (assets) => {
@@ -199,7 +195,6 @@ router.get('/assets', [
name: file.name,
title: file.title,
description: file.description,
- visualization: file.visualization ? file.visualization.url : null,
createdAt: file.createdAt
})
})
@@ -242,16 +237,6 @@ router.get('/assets', [
createdAt: query.createdAt
})
})
- assets[0] && assets[0].visualizations.forEach((visualization) => {
- finalAssets.push({
- type: 'RealBI Dashboard',
- id: visualization.id,
- name: visualization.name,
- description: visualization.description,
- url: visualization.url,
- createdAt: visualization.createdAt
- })
- })
finalAssets.sort(comparator);
finalAssets = childGroups.concat(finalAssets);
@@ -353,25 +338,6 @@ router.get('/assets', [
})
}))
- promises.push(Visualization.findAll({
- where:{
- application_id:req.query.app_id,
- [Op.and]:Sequelize.literal('not exists (select * from assets_groups where assets_groups.assetId = visualizations.id)')
- }
- }).then((visualizations) => {
- visualizations.forEach((visualization) => {
- finalAssets.push({
- type: 'RealBI Dashboard',
- id: visualization.id,
- name: visualization.name,
- title: visualization.title,
- description: visualization.description,
- url: visualization.url,
- createdAt: visualization.createdAt
- })
- })
- }))
-
promises.push(Groups.findAll({where:{application_id:req.query.app_id, parent_group:{[Op.or]:[null, '']}}, order: [['name', 'ASC']]}).then((groups) => {
groups.forEach((group) => {
finalGroups.push({