Skip to content

Commit

Permalink
Merge pull request #1834 from flowforge/rename-project-types
Browse files Browse the repository at this point in the history
Relabel Project Types to Instance Types in UI
  • Loading branch information
Pezmc committed Mar 15, 2023
2 parents 6892f88 + b93d401 commit 6317740
Show file tree
Hide file tree
Showing 17 changed files with 282 additions and 282 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import client from './client'
import paginateUrl from '@/utils/paginateUrl'
const marked = require('marked')

const getProjectTypes = async (cursor, limit, filter) => {
const getInstanceTypes = async (cursor, limit, filter) => {
let url = paginateUrl('/api/v1/project-types', cursor, limit)
if (filter) {
const queryString = new URLSearchParams()
Expand Down Expand Up @@ -38,24 +38,24 @@ const create = async (options) => {
return res.data
})
}
const deleteProjectType = async (projectTypeId) => {
return await client.delete(`/api/v1/project-types/${projectTypeId}`)
const deleteInstanceType = async (instanceTypeId) => {
return await client.delete(`/api/v1/project-types/${instanceTypeId}`)
}
const getProjectType = async (projectTypeId) => {
return await client.get(`/api/v1/project-types/${projectTypeId}`).then(res => {
const getInstanceType = async (instanceTypeId) => {
return await client.get(`/api/v1/project-types/${instanceTypeId}`).then(res => {
return res.data
})
}
const updateProjectType = async (projectTypeId, options) => {
return client.put(`/api/v1/project-types/${projectTypeId}`, options).then(res => {
const updateInstanceType = async (instanceTypeId, options) => {
return client.put(`/api/v1/project-types/${instanceTypeId}`, options).then(res => {
return res.data
})
}

export default {
create,
getProjectType,
deleteProjectType,
getProjectTypes,
updateProjectType
getInstanceType,
deleteInstanceType,
getInstanceTypes,
updateInstanceType
}
16 changes: 8 additions & 8 deletions frontend/src/components/audit-log/AuditEntryVerbose.vue
Original file line number Diff line number Diff line change
Expand Up @@ -228,21 +228,21 @@
<span v-if="!error && typeof entry.body?.info === 'object'">Type: '{{entry.body.info.resource }}', Limit: {{ entry.body.info.limit }}, Count: {{ entry.body.info.count }}</span>
<span v-else-if="!error">License data not found in audit entry.</span>
</template>
<!-- Platform project type Events -->
<!-- Platform instance type Events -->
<template v-else-if="entry.event === 'platform.project-type.created'">
<label>{{ AuditEvents[entry.event] }}</label>
<span v-if="!error && entry.body?.projectType">A new project type '{{ entry.body.projectType }}' has been created.</span>
<span v-else-if="!error">Project Type data not found in audit entry.</span>
<span v-if="!error && entry.body?.projectType">A new instance type '{{ entry.body.projectType }}' has been created.</span>
<span v-else-if="!error">Instance Type data not found in audit entry.</span>
</template>
<template v-else-if="entry.event === 'platform.project-type.deleted'">
<label>{{ AuditEvents[entry.event] }}</label>
<span v-if="!error && entry.body?.projectType">Project type '{{ entry.body.projectType }}' has been deleted.</span>
<span v-else-if="!error">Project Type data not found in audit entry.</span>
<span v-if="!error && entry.body?.projectType">Instance type '{{ entry.body.projectType }}' has been deleted.</span>
<span v-else-if="!error">Instance Type data not found in audit entry.</span>
</template>
<template v-else-if="entry.event === 'platform.project-type.updated'">
<label>{{ AuditEvents[entry.event] }}</label>
<span v-if="!error && entry.body?.projectType">Project type '{{ entry.body.projectType }}' has been updated with the following changes: <AuditEntryUpdates :updates="entry.body.updates" /></span>
<span v-else-if="!error">Project Type data not found in audit entry.</span>
<span v-if="!error && entry.body?.projectType">Instance type '{{ entry.body.projectType }}' has been updated with the following changes: <AuditEntryUpdates :updates="entry.body.updates" /></span>
<span v-else-if="!error">Instance Type data not found in audit entry.</span>
</template>
<template v-else-if="entry.event === 'platform.stack.created'">
<label>{{ AuditEvents[entry.event] }}</label>
Expand Down Expand Up @@ -327,7 +327,7 @@
<span v-else-if="!error">Project data not found in audit entry.</span>
</template>
<template v-else-if="entry.event === 'project.type.changed'">
<label>Project Type Changed</label>
<label>Instance Type Changed</label>
<span v-if="!error && entry.body?.project">The type for Project '{{ entry.body.project?.name }}' has been changed to Type '{{ entry.body.projectType?.name }}'</span>
<span v-else-if="!error">Project data not found in audit entry.</span>
</template>
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/data/audit-events.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@
"platform.license.inspected": "License Inspected",
"platform.licence.inspect": "License Inspected",
"platform.license.overage": "License Overage",
"platform.project-type.created": "New Project Type Created",
"platform.project-type.deleted": "Project Type Deleted",
"platform.project-type.updated": "Project Type Updated",
"platform.project-type.created": "New Instance Type Created",
"platform.project-type.deleted": "Instance Type Deleted",
"platform.project-type.updated": "Instance Type Updated",
"platform.stack.created": "New Stack Created",
"platform.stack.deleted": "Stack Deleted",
"platform.stack.updated": "Stack Updated",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
const marked = require('marked')
export default {
name: 'ProjectTypeDescriptionCell',
name: 'InstanceTypeDescriptionCell',
props: ['description'],
computed: {
renderedDescription () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</FormRow>
<FormRow :options="stacks" v-model="input.defaultStack" :disabled="stacks.length === 0" id="stack" data-form="stack">
Default Stack
<template #description><div v-if="stacks.length === 0">There no stacks defined for this Project Type yet.</div></template>
<template #description><div v-if="stacks.length === 0">There are no stacks defined for this Instance Type yet.</div></template>
</FormRow>
<template v-if="this.features.billing">
<FormHeading>Billing</FormHeading>
Expand All @@ -35,19 +35,19 @@
<template v-slot:actions>
<div class="w-full grow flex justify-between">
<div>
<ff-button v-if="projectType" kind="danger" style="margin: 0;" @click="$emit('showDeleteDialog', projectType); $refs.dialog.close()">Delete Project Type</ff-button>
<ff-button v-if="instanceType" kind="danger" style="margin: 0;" @click="$emit('showDeleteDialog', instanceType); $refs.dialog.close()">Delete Instance Type</ff-button>
</div>
<div class="flex">
<ff-button kind="secondary" @click="$refs['dialog'].close()">Cancel</ff-button>
<ff-button @click="confirm(); $refs.dialog.close()" :disabled="!formValid">{{ projectType ? 'Update' : 'Create' }}</ff-button>
<ff-button @click="confirm(); $refs.dialog.close()" :disabled="!formValid">{{ instanceType ? 'Update' : 'Create' }}</ff-button>
</div>
</div>
</template>
</ff-dialog>
</template>

<script>
import projectTypesApi from '@/api/projectTypes'
import instanceTypesApi from '@/api/instanceTypes'
import stacksApi from '@/api/stacks'
import FormRow from '@/components/FormRow'
Expand All @@ -56,15 +56,15 @@ import FormHeading from '@/components/FormHeading'
import { mapState } from 'vuex'
export default {
name: 'AdminProjectTypeCreateDialog',
emits: ['projectTypeUpdated', 'projectTypeCreated', 'showDeleteDialog'],
name: 'AdminInstanceTypeCreateDialog',
emits: ['instanceTypeUpdated', 'instanceTypeCreated', 'showDeleteDialog'],
components: {
FormRow,
FormHeading
},
data () {
return {
projectType: null,
instanceType: null,
stacks: [],
input: {
name: '',
Expand All @@ -83,10 +83,10 @@ export default {
return (this.input.name)
},
dialogTitle () {
if (this.projectType) {
return 'Edit project type'
if (this.instanceType) {
return 'Edit instance type'
} else {
return 'Create project type'
return 'Create instance type'
}
}
},
Expand All @@ -107,12 +107,12 @@ export default {
opts.properties.billingDescription = this.input.properties.billingDescription
}
if (this.projectType) {
if (this.instanceType) {
// For edits, we cannot touch the properties
delete opts.properties
// Update
projectTypesApi.updateProjectType(this.projectType.id, opts).then((response) => {
this.$emit('projectTypeUpdated', response)
instanceTypesApi.updateInstanceType(this.instanceType.id, opts).then((response) => {
this.$emit('instanceTypeUpdated', response)
}).catch(err => {
console.log(err.response.data)
if (err.response.data) {
Expand All @@ -122,8 +122,8 @@ export default {
}
})
} else {
projectTypesApi.create(opts).then((response) => {
this.$emit('projectTypeCreated', response)
instanceTypesApi.create(opts).then((response) => {
this.$emit('instanceTypeCreated', response)
}).catch(err => {
console.log(err.response.data)
if (err.response.data) {
Expand All @@ -138,26 +138,26 @@ export default {
},
setup () {
return {
show (projectType) {
show (instanceType) {
this.$refs.dialog.show()
this.projectType = projectType
this.instanceType = instanceType
this.stacks = []
if (projectType) {
this.editDisabled = projectType.projectCount > 0
if (instanceType) {
this.editDisabled = instanceType.projectCount > 0
this.input = {
name: projectType.name,
active: projectType.active,
properties: projectType.properties,
description: projectType.description,
name: instanceType.name,
active: instanceType.active,
properties: instanceType.properties,
description: instanceType.description,
// Cast to string so the v-model into FormRow works
// Normally you'd use v-model.number to handle this
// but we don't have that inside FormRow currently and
// this is good enough for now
order: '' + projectType.order
order: '' + instanceType.order
}
stacksApi.getStacks(null, null, null, projectType.id).then(stackList => {
stacksApi.getStacks(null, null, null, instanceType.id).then(stackList => {
this.stacks = stackList.stacks.filter(stack => stack.active).map(stack => { return { value: stack.id, label: stack.name } })
this.input.defaultStack = projectType.defaultStack
this.input.defaultStack = instanceType.defaultStack
})
} else {
this.editDisabled = false
Expand Down
159 changes: 159 additions & 0 deletions frontend/src/pages/admin/InstanceTypes/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<template>
<div class="space-y-6">
<FormHeading>Instance Types
<template v-slot:tools>
<ff-button size="small" @click="showCreateInstanceTypeDialog" data-action="create-type">
<template v-slot:icon-right>
<PlusSmIcon />
</template>
Create instance type
</ff-button>
</template>
</FormHeading>
<ff-tile-selection data-el="active-types">
<ff-tile-selection-option v-for="(instanceType, index) in activeInstanceTypes" :key="index"
:editable="true" @edit="showEditInstanceTypeDialog(instanceType)" :price="instanceType.properties?.billingDescription?.split('/')[0]"
:price-interval="instanceType.properties?.billingDescription?.split('/')[1]"
:label="instanceType.name" :description="instanceType.description"
:meta="[{key: 'Instance Count', value: instanceType.projectCount}, {key: 'Stack Count', value: instanceType.stackCount}]"/>
</ff-tile-selection>
<div v-if="nextCursor">
<a v-if="!loading" @click.stop="loadItems" class="forge-button-inline">Load more...</a>
</div>
<FormHeading>Inactive Types</FormHeading>
<ff-data-table :columns="columns" :rows="inactiveInstanceTypes" data-el="inactive-types">
<template v-slot:context-menu="{row}">
<ff-list-item label="Edit Instance Type" @click="instanceTypeAction('edit', row.id)"/>
<ff-list-item label="Delete Instance Type" kind="danger" @click="instanceTypeAction('delete', row.id)"/>
</template>
</ff-data-table>
<div v-if="nextCursor">
<a v-if="!loading" @click.stop="loadItems" class="forge-button-inline">Load more...</a>
</div>
</div>
<InstanceTypeEditDialog ref="adminInstanceTypeEditDialog" @instanceTypeCreated="instanceTypeCreated"
@instanceTypeUpdated="instanceTypeUpdated" @showDeleteDialog="showConfirmInstanceTypeDeleteDialog"/>
</template>
<script>
import instanceTypesApi from '@/api/instanceTypes'
import FormHeading from '@/components/FormHeading'
import { markRaw } from 'vue'
import { mapState } from 'vuex'
import Dialog from '@/services/dialog'
import InstanceTypeEditDialog from './dialogs/InstanceTypeEditDialog'
import InstanceTypeDescriptionCell from './components/InstanceTypeDescriptionCell'
import { PlusSmIcon } from '@heroicons/vue/outline'
const marked = require('marked')
export default {
name: 'AdminInstanceTypes',
data () {
return {
instanceTypes: [],
loading: false,
nextCursor: null,
columns: [
{ label: 'Type', key: 'name', sortable: true },
{ label: 'Description', key: 'description', sortable: true, component: { is: markRaw(InstanceTypeDescriptionCell) } },
{ label: 'Default Stack', class: ['w-48'], key: 'defaultStack', sortable: true },
{ label: 'Application Instances', class: ['w-32', 'text-center'], key: 'projectCount', sortable: true },
{ label: 'Stacks', class: ['w-32', 'text-center'], key: 'stackCount', sortable: true }
]
}
},
async created () {
await this.loadItems()
},
computed: {
...mapState('account', ['settings']),
activeInstanceTypes () {
const types = this.instanceTypes.filter(pt => pt.active)
return types
},
inactiveInstanceTypes () {
const types = this.instanceTypes.filter(pt => !pt.active)
return types
}
},
methods: {
instanceTypeAction (action, id) {
const index = this.instanceTypes.findIndex(pt => pt.id === id)
const instanceType = this.instanceTypes[index]
switch (action) {
case 'edit':
this.showEditInstanceTypeDialog(instanceType)
break
case 'delete': {
this.showConfirmInstanceTypeDeleteDialog(instanceType)
break
}
}
},
showCreateInstanceTypeDialog () {
this.$refs.adminInstanceTypeEditDialog.show()
},
showEditInstanceTypeDialog (instanceType) {
this.$refs.adminInstanceTypeEditDialog.show(instanceType)
},
showConfirmInstanceTypeDeleteDialog (instanceType) {
const text = instanceType.projectCount > 0 ? 'You cannot delete an instance type that is still being used by instances.' : 'Are you sure you want to delete this instance type?'
Dialog.show({
header: 'Delete Instance Type',
kind: 'danger',
text,
confirmLabel: 'Delete',
disablePrimary: instanceType.projectCount > 0
}, async () => {
// on confirm - delete the instance type
await instanceTypesApi.deleteInstanceType(instanceType.id)
const index = this.instanceTypes.findIndex(pt => pt.id === instanceType.id)
this.instanceTypes.splice(index, 1)
})
},
async instanceTypeCreated (instanceType) {
this.instanceTypes.push(instanceType)
this.resortTypes()
},
async instanceTypeUpdated (instanceType) {
const index = this.instanceTypes.findIndex(s => s.id === instanceType.id)
if (index > -1) {
instanceType.htmlDescription = marked.parse(instanceType.description)
this.instanceTypes[index] = instanceType
this.resortTypes()
}
},
resortTypes () {
this.instanceTypes.sort((A, B) => {
if (A.order !== B.order) {
return A.order - B.order
} else {
return A.name.localeCompare(B.name)
}
})
},
// async deleteStack (stack) {
// await stacksApi.deleteStack(stack.id)
// const index = this.stacks.indexOf(stack)
// this.stacks.splice(index, 1)
// },
loadItems: async function () {
this.loading = true
const result = await instanceTypesApi.getInstanceTypes(this.nextCursor, 30, 'all')
this.nextCursor = result.meta.next_cursor
result.types.forEach(v => {
this.instanceTypes.push(v)
})
}
},
components: {
FormHeading,
PlusSmIcon,
InstanceTypeEditDialog
}
}
</script>
Loading

0 comments on commit 6317740

Please sign in to comment.