From 9fb0dfa4a7b1f5bc962290589113b7b8f982829c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 6 Oct 2025 21:35:54 +0530 Subject: [PATCH] feat: Add UI for custom tools (#12585) ### Tools list CleanShot 2025-10-03 at 20 42 41@2x ### Tools form CleanShot 2025-10-03 at 20 43
05@2x ## Response CleanShot 2025-10-03 at 20 45 56@2x --------- Co-authored-by: Pranav Co-authored-by: Pranav --- .../dashboard/api/captain/customTools.js | 36 +++ .../captain/pageComponents/DeleteDialog.vue | 8 +- .../pageComponents/customTool/AuthConfig.vue | 73 +++++ .../customTool/CreateCustomToolDialog.vue | 87 ++++++ .../customTool/CustomToolCard.vue | 125 ++++++++ .../customTool/CustomToolForm.vue | 271 +++++++++++++++++ .../pageComponents/customTool/ParamRow.vue | 113 +++++++ .../emptyStates/CustomToolsPageEmptyState.vue | 29 ++ .../components-next/sidebar/Sidebar.vue | 5 + .../i18n/locale/en/integrations.json | 109 +++++++ .../dashboard/i18n/locale/en/settings.json | 1 + .../dashboard/captain/captain.routes.js | 14 + .../routes/dashboard/captain/tools/Index.vue | 138 +++++++++ .../dashboard/store/captain/customTools.js | 35 +++ .../dashboard/store/captain/tools.js | 2 +- app/javascript/dashboard/store/index.js | 2 + config/locales/en.yml | 2 + config/routes.rb | 1 + .../captain/custom_tools_controller.rb | 49 +++ enterprise/app/models/captain/custom_tool.rb | 19 +- enterprise/app/models/concerns/toolable.rb | 13 + .../policies/captain/custom_tool_policy.rb | 21 ++ .../captain/custom_tools/create.json.jbuilder | 1 + .../captain/custom_tools/index.json.jbuilder | 10 + .../captain/custom_tools/show.json.jbuilder | 1 + .../captain/custom_tools/update.json.jbuilder | 1 + .../models/captain/_custom_tool.json.jbuilder | 15 + .../captain/custom_tools_controller_spec.rb | 281 ++++++++++++++++++ .../models/captain/custom_tool_spec.rb | 36 +-- 29 files changed, 1474 insertions(+), 24 deletions(-) create mode 100644 app/javascript/dashboard/api/captain/customTools.js create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/customTool/AuthConfig.vue create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/customTool/CreateCustomToolDialog.vue create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/customTool/CustomToolCard.vue create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/customTool/CustomToolForm.vue create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/customTool/ParamRow.vue create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/emptyStates/CustomToolsPageEmptyState.vue create mode 100644 app/javascript/dashboard/routes/dashboard/captain/tools/Index.vue create mode 100644 app/javascript/dashboard/store/captain/customTools.js create mode 100644 enterprise/app/controllers/api/v1/accounts/captain/custom_tools_controller.rb create mode 100644 enterprise/app/policies/captain/custom_tool_policy.rb create mode 100644 enterprise/app/views/api/v1/accounts/captain/custom_tools/create.json.jbuilder create mode 100644 enterprise/app/views/api/v1/accounts/captain/custom_tools/index.json.jbuilder create mode 100644 enterprise/app/views/api/v1/accounts/captain/custom_tools/show.json.jbuilder create mode 100644 enterprise/app/views/api/v1/accounts/captain/custom_tools/update.json.jbuilder create mode 100644 enterprise/app/views/api/v1/models/captain/_custom_tool.json.jbuilder create mode 100644 spec/enterprise/controllers/api/v1/accounts/captain/custom_tools_controller_spec.rb diff --git a/app/javascript/dashboard/api/captain/customTools.js b/app/javascript/dashboard/api/captain/customTools.js new file mode 100644 index 000000000..d0818d941 --- /dev/null +++ b/app/javascript/dashboard/api/captain/customTools.js @@ -0,0 +1,36 @@ +/* global axios */ +import ApiClient from '../ApiClient'; + +class CaptainCustomTools extends ApiClient { + constructor() { + super('captain/custom_tools', { accountScoped: true }); + } + + get({ page = 1, searchKey } = {}) { + return axios.get(this.url, { + params: { page, searchKey }, + }); + } + + show(id) { + return axios.get(`${this.url}/${id}`); + } + + create(data = {}) { + return axios.post(this.url, { + custom_tool: data, + }); + } + + update(id, data = {}) { + return axios.put(`${this.url}/${id}`, { + custom_tool: data, + }); + } + + delete(id) { + return axios.delete(`${this.url}/${id}`); + } +} + +export default new CaptainCustomTools(); diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/DeleteDialog.vue b/app/javascript/dashboard/components-next/captain/pageComponents/DeleteDialog.vue index 31e18394f..8d67344e1 100644 --- a/app/javascript/dashboard/components-next/captain/pageComponents/DeleteDialog.vue +++ b/app/javascript/dashboard/components-next/captain/pageComponents/DeleteDialog.vue @@ -10,6 +10,10 @@ const props = defineProps({ type: String, required: true, }, + translationKey: { + type: String, + required: true, + }, entity: { type: Object, required: true, @@ -25,7 +29,9 @@ const emit = defineEmits(['deleteSuccess']); const { t } = useI18n(); const store = useStore(); const deleteDialogRef = ref(null); -const i18nKey = computed(() => props.type.toUpperCase()); +const i18nKey = computed(() => { + return props.translationKey || props.type.toUpperCase(); +}); const deleteEntity = async payload => { if (!payload) return; diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/customTool/AuthConfig.vue b/app/javascript/dashboard/components-next/captain/pageComponents/customTool/AuthConfig.vue new file mode 100644 index 000000000..208a94dba --- /dev/null +++ b/app/javascript/dashboard/components-next/captain/pageComponents/customTool/AuthConfig.vue @@ -0,0 +1,73 @@ + + + diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/customTool/CreateCustomToolDialog.vue b/app/javascript/dashboard/components-next/captain/pageComponents/customTool/CreateCustomToolDialog.vue new file mode 100644 index 000000000..0745c6546 --- /dev/null +++ b/app/javascript/dashboard/components-next/captain/pageComponents/customTool/CreateCustomToolDialog.vue @@ -0,0 +1,87 @@ + + +