Skip to content

Commit

Permalink
feat(ui): Sidebar > Request Context Menu > Generate Code
Browse files Browse the repository at this point in the history
  • Loading branch information
flawiddsouza committed Jan 17, 2024
1 parent 0f22829 commit 21df5b4
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 15 deletions.
16 changes: 8 additions & 8 deletions packages/ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"dayjs": "^1.10.7",
"dexie": "^3.2.0",
"dexie-export-import": "^1.0.3",
"httpsnippet-browser": "github:flawiddsouza/httpsnippet-browser#e40dbea",
"httpsnippet-browser": "github:flawiddsouza/httpsnippet-browser#ed12aba",
"insomnia-importers-browser": "github:flawiddsouza/insomnia-importers-browser",
"jszip": "^3.7.1",
"lodash.get": "^4.4.2",
Expand Down
10 changes: 8 additions & 2 deletions packages/ui/src/components/CodeMirrorEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function createState(language, documentText, vueInstance) {
languageFunc = graphqlLanguage
highlightStyle = codeMirrorSyntaxHighlighting()
}
return EditorState.create({
doc: documentText,
extensions: [
Expand Down Expand Up @@ -86,7 +87,8 @@ function createState(language, documentText, vueInstance) {
indentWithTab,
...searchKeymap,
selectLineKeyMap
])
]),
vueInstance.readonly ? EditorState.readOnly.of(true) : EditorState.readOnly.of(false),
]
})
}
Expand All @@ -100,7 +102,11 @@ export default {
lang: {
type: String,
required: true
}
},
readonly: {
type: Boolean,
default: false
},
},
data() {
return {
Expand Down
26 changes: 23 additions & 3 deletions packages/ui/src/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<PluginManagerModal v-model:showModal="pluginManagerShow" :collection-item="pluginManagerCollectionItem" />
<SettingsModal v-model:showModal="settingsModalShow" :collection-item="settingsModalCollectionItem" />
<DuplicateCollectionItemModal v-model:showModal="showDuplicateCollectionItemModal" :collection-item-to-duplicate="collectionItemToDuplicate" />
<GenerateCodeModal v-model:showModal="generateCodeModalShow" :collection-item="generateCodeModalCollectionItem" />
</template>

<script>
Expand All @@ -40,6 +41,7 @@ import EnvironmentModal from './modals/EnvironmentModal.vue'
import PluginManagerModal from './modals/PluginManagerModal.vue'
import SettingsModal from './modals/SidebarSettingsModal.vue'
import DuplicateCollectionItemModal from './modals/DuplicateCollectionItemModal.vue'
import GenerateCodeModal from './modals/GenerateCodeModal.vue'
import { mapState } from 'vuex'
import { flattenTree, exportRestfoxCollection } from '@/helpers'
import { generateCode } from '@/utils/generate-code'
Expand All @@ -54,7 +56,8 @@ export default {
EnvironmentModal,
PluginManagerModal,
SettingsModal,
DuplicateCollectionItemModal
DuplicateCollectionItemModal,
GenerateCodeModal,
},
data() {
return {
Expand All @@ -78,6 +81,8 @@ export default {
collectionItemToDuplicate: null,
pluginManagerCollectionItem: null,
pluginManagerShow: false,
generateCodeModalCollectionItem: null,
generateCodeModalShow: false,
}
},
computed: {
Expand Down Expand Up @@ -147,6 +152,12 @@ export default {
'value': 'Copy as Curl',
'icon': 'fa fa-copy'
},
{
'type': 'option',
'label': 'Generate Code',
'value': 'Generate Code',
'icon': 'fa fa-code'
},
{
'type': 'option',
'label': 'Plugins',
Expand All @@ -171,8 +182,12 @@ export default {
]
if(this.activeSidebarItemForContextMenu._type === 'socket') {
// Remove Copy as Curl & Plugins
contextMenuOptions = contextMenuOptions.filter(option => option.value !== 'Copy as Curl' && option.value !== 'Plugins')
const optionsToRemove = [
'Copy as Curl',
'Generate Code',
'Plugins'
]
contextMenuOptions = contextMenuOptions.filter(option => !optionsToRemove.includes(option.value))
}
return contextMenuOptions
Expand Down Expand Up @@ -308,6 +323,11 @@ export default {
}
}
if(clickedSidebarItem === 'Generate Code') {
this.generateCodeModalCollectionItem = JSON.parse(JSON.stringify(this.activeSidebarItemForContextMenu))
this.generateCodeModalShow = true
}
if(clickedSidebarItem === 'New Request') {
this.addRequestModalParentId = this.activeSidebarItemForContextMenu ? this.activeSidebarItemForContextMenu._id : null
this.addRequestModalShow = true
Expand Down
167 changes: 167 additions & 0 deletions packages/ui/src/components/modals/GenerateCodeModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<template>
<div v-if="showModalComp">
<modal :title="title" v-model="showModalComp" height="70vh" width="55rem">
<div class="generate-code-modal-container">
<label>
<div style="font-weight: 500; margin-bottom: 0.25rem;">Select Language</div>
<select v-model="selectedLanguage" @change="selectedLanguageChanged" class="full-width-input">
<option value="" disabled>Select language</option>
<option v-for="target in availableTargets" :value="target.key">{{ target.title }}</option>
</select>
</label>
<label v-if="selectedLanguage" style="margin-top: 1rem;">
<div style="font-weight: 500; margin-bottom: 0.25rem;">Select Client</div>
<select v-model="selectedClient" @change="selectedClientChanged" class="full-width-input">
<option value="" disabled >Select client</option>
<option v-for="client in selectedLanguageClients" :value="client.key">{{ client.title }}</option>
</select>
</label>
<div v-if="generatedCode" style="margin-top: 1rem; overflow: auto;">
<div style="font-weight: 500; margin-bottom: 0.25rem;">Code</div>
<CodeMirrorEditor :model-value="generatedCode" lang="javascript" :readonly="true" class="code-editor" />
</div>
</div>
<template #footer>
<button class="button" @click="copyCode" :disabled="!generatedCode">Copy Code</button>
</template>
</modal>
</div>
</template>

<script>
import Modal from '@/components/Modal.vue'
import { generateCode, getAvailableTargets } from '@/utils/generate-code'
import CodeMirrorEditor from '../CodeMirrorEditor.vue'
import constants from '@/constants'
export default {
props: {
showModal: Boolean,
collectionItem: {
type: Object,
required: false
}
},
components: {
Modal,
CodeMirrorEditor,
},
data() {
return {
selectedLanguage: '',
selectedClient: '',
generatedCode: '',
}
},
computed: {
title() {
let title = 'Generate Code'
if(this.collectionItem) {
title = `${title}${this.collectionItem.name}`
}
return title
},
showModalComp: {
get() {
return this.showModal
},
set(value) {
this.$emit('update:showModal', value)
}
},
activeWorkspace() {
return this.$store.state.activeWorkspace
},
availableTargets() {
return getAvailableTargets()
},
selectedLanguageClients() {
if(this.selectedLanguage) {
return this.availableTargets.find(target => target.key === this.selectedLanguage).clients
} else {
return []
}
}
},
watch: {
collectionItem() {
this.generateCode()
}
},
methods: {
selectedLanguageChanged() {
this.selectedClient = ''
this.generatedCode = ''
if(this.selectedLanguage) {
localStorage.setItem(constants.LOCAL_STORAGE_KEY.GENERATE_CODE_LANGUAGE, this.selectedLanguage)
} else {
localStorage.removeItem(constants.LOCAL_STORAGE_KEY.GENERATE_CODE_LANGUAGE)
}
localStorage.removeItem(constants.LOCAL_STORAGE_KEY.GENERATE_CODE_CLIENT)
},
selectedClientChanged() {
this.generateCode()
if(this.selectedClient) {
localStorage.setItem(constants.LOCAL_STORAGE_KEY.GENERATE_CODE_CLIENT, this.selectedClient)
} else {
localStorage.removeItem(constants.LOCAL_STORAGE_KEY.GENERATE_CODE_CLIENT)
}
},
async generateCode() {
if(this.selectedClient) {
try {
const request = JSON.parse(JSON.stringify(this.collectionItem))
const { environment } = await this.$store.dispatch('getEnvironmentForRequest', request)
const code = await generateCode(request, environment, this.selectedLanguage, this.selectedClient)
this.generatedCode = code
} catch(e) {
this.generatedCode = e.message
}
} else {
this.generatedCode = ''
}
},
async copyCode() {
await navigator.clipboard.writeText(this.generatedCode)
this.$toast.success('Copied to clipboard')
},
},
async mounted() {
const selectedLanguage = localStorage.getItem(constants.LOCAL_STORAGE_KEY.GENERATE_CODE_LANGUAGE)
const selectedClient = localStorage.getItem(constants.LOCAL_STORAGE_KEY.GENERATE_CODE_CLIENT)
if(selectedLanguage) {
const selectedLanguageFound = this.availableTargets.find(target => target.key === selectedLanguage)
if(selectedLanguageFound) {
this.selectedLanguage = selectedLanguageFound.key
}
}
if(selectedClient) {
const selectedClientFound = this.selectedLanguageClients.find(client => client.key === selectedClient)
if(selectedClientFound) {
this.selectedClient = selectedClientFound.key
}
}
}
}
</script>

<style scoped>
.generate-code-modal-container {
display: grid;
grid-template-rows: auto auto 1fr;
height: 100%;
}
.code-editor {
height: calc(100% - 1.2rem);
overflow-y: auto;
border: 1px solid var(--modal-border-color);
}
</style>
2 changes: 2 additions & 0 deletions packages/ui/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export default {
DISABLE_PAGE_VIEW_ANALYTICS_TRACKING: 'Restfox-DisablePageViewAnalyticsTracking',
DISABLE_SSL_VERIFICATION: 'Restfox-DisableSSLVerification',
ELECTRON_SWITCH_TO_CHROMIUM_FETCH: 'Restfox-ElectronSwitchToChromiumFetch',
GENERATE_CODE_LANGUAGE: 'Restfox-GenerateCodeLanguage',
GENERATE_CODE_CLIENT: 'Restfox-GenerateCodeClient',
},
HOTKEYS: {
SEND_REQUEST: 'Ctrl + Enter',
Expand Down
6 changes: 5 additions & 1 deletion packages/ui/src/utils/generate-code.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { createRequestData, substituteEnvironmentVariables } from '@/helpers'
import { HTTPSnippet } from 'httpsnippet-browser'
import { HTTPSnippet, availableTargets } from 'httpsnippet-browser'

export function getAvailableTargets() {
return availableTargets()
}

export async function generateCode(request, environment, target: 'shell', clientId: 'curl') {
const state = {
Expand Down

0 comments on commit 21df5b4

Please sign in to comment.