rename an app
This commit is contained in:
parent
30be2a00fa
commit
f2b1125e0b
|
@ -15,6 +15,7 @@
|
||||||
export let exportApp
|
export let exportApp
|
||||||
export let viewApp
|
export let viewApp
|
||||||
export let editApp
|
export let editApp
|
||||||
|
export let updateApp
|
||||||
export let deleteApp
|
export let deleteApp
|
||||||
export let unpublishApp
|
export let unpublishApp
|
||||||
export let releaseLock
|
export let releaseLock
|
||||||
|
@ -53,6 +54,9 @@
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{/if}
|
{/if}
|
||||||
{#if !app.deployed}
|
{#if !app.deployed}
|
||||||
|
<MenuItem on:click={() => updateApp(app)} icon="Edit">
|
||||||
|
Update
|
||||||
|
</MenuItem>
|
||||||
<MenuItem on:click={() => deleteApp(app)} icon="Delete">
|
<MenuItem on:click={() => deleteApp(app)} icon="Delete">
|
||||||
Delete
|
Delete
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
export let exportApp
|
export let exportApp
|
||||||
export let viewApp
|
export let viewApp
|
||||||
export let editApp
|
export let editApp
|
||||||
|
export let updateApp
|
||||||
export let deleteApp
|
export let deleteApp
|
||||||
export let unpublishApp
|
export let unpublishApp
|
||||||
export let releaseLock
|
export let releaseLock
|
||||||
|
@ -82,6 +83,7 @@
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{/if}
|
{/if}
|
||||||
{#if !app.deployed}
|
{#if !app.deployed}
|
||||||
|
<MenuItem on:click={() => updateApp(app)} icon="Edit">Update</MenuItem>
|
||||||
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
|
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
|
||||||
{/if}
|
{/if}
|
||||||
</ActionMenu>
|
</ActionMenu>
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
<script>
|
||||||
|
import { writable, get as svelteGet } from "svelte/store"
|
||||||
|
import {
|
||||||
|
notifications,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalContent,
|
||||||
|
Body,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import { hostingStore } from "builderStore"
|
||||||
|
import { apps } from "stores/portal"
|
||||||
|
import { string, object } from "yup"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import { capitalise } from "helpers"
|
||||||
|
|
||||||
|
const values = writable({ name: null })
|
||||||
|
const errors = writable({})
|
||||||
|
const touched = writable({})
|
||||||
|
const validator = {
|
||||||
|
name: string().required("Your application must have a name"),
|
||||||
|
}
|
||||||
|
|
||||||
|
export let app;
|
||||||
|
|
||||||
|
let modal;
|
||||||
|
let valid = false
|
||||||
|
let dirty = false;
|
||||||
|
$: checkValidity($values, validator)
|
||||||
|
$: {
|
||||||
|
// prevent validation by setting name to undefined without an app
|
||||||
|
if (app) {
|
||||||
|
$values.name = app?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
await hostingStore.actions.fetchDeployedApps()
|
||||||
|
const existingAppNames = svelteGet(hostingStore).deployedAppNames
|
||||||
|
validator.name = string()
|
||||||
|
.required("Your application must have a name")
|
||||||
|
.test(
|
||||||
|
"non-existing-app-name",
|
||||||
|
"Another app with the same name already exists",
|
||||||
|
value => {
|
||||||
|
return !existingAppNames.some(
|
||||||
|
appName => dirty && appName.toLowerCase() === value.toLowerCase()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const checkValidity = async (values, validator) => {
|
||||||
|
const obj = object().shape(validator)
|
||||||
|
Object.keys(validator).forEach(key => ($errors[key] = null))
|
||||||
|
try {
|
||||||
|
await obj.validate(values, { abortEarly: false })
|
||||||
|
} catch (validationErrors) {
|
||||||
|
validationErrors.inner.forEach(error => {
|
||||||
|
$errors[error.path] = capitalise(error.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
valid = await obj.isValid(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateApp() {
|
||||||
|
try {
|
||||||
|
// Update App
|
||||||
|
await apps.update(app.instance._id, $values.name);
|
||||||
|
hide();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
notifications.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const show = () => {
|
||||||
|
modal.show()
|
||||||
|
}
|
||||||
|
export const hide = () => {
|
||||||
|
modal.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onShow = () => {
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<Modal bind:this={modal} on:hide={onCancel} on:show={onShow}>
|
||||||
|
<ModalContent
|
||||||
|
title={"Update app"}
|
||||||
|
confirmText={"Update app"}
|
||||||
|
onConfirm={updateApp}
|
||||||
|
disabled={!(valid && dirty)}
|
||||||
|
>
|
||||||
|
<Body size="S">
|
||||||
|
Give your new app a name, and choose which groups have access (paid plans
|
||||||
|
only).
|
||||||
|
</Body>
|
||||||
|
<Input
|
||||||
|
bind:value={$values.name}
|
||||||
|
error={$touched.name && $errors.name}
|
||||||
|
on:blur={() => ($touched.name = true)}
|
||||||
|
on:change={() => dirty = true}
|
||||||
|
label="Name"
|
||||||
|
/>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
|
@ -14,6 +14,7 @@
|
||||||
Body,
|
Body,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
||||||
|
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
||||||
import api, { del } from "builderStore/api"
|
import api, { del } from "builderStore/api"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
let template
|
let template
|
||||||
let selectedApp
|
let selectedApp
|
||||||
let creationModal
|
let creationModal
|
||||||
|
let updatingModal
|
||||||
let deletionModal
|
let deletionModal
|
||||||
let unpublishModal
|
let unpublishModal
|
||||||
let creatingApp = false
|
let creatingApp = false
|
||||||
|
@ -164,6 +166,11 @@
|
||||||
selectedApp = null
|
selectedApp = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateApp = async app => {
|
||||||
|
selectedApp = app
|
||||||
|
updatingModal.show()
|
||||||
|
}
|
||||||
|
|
||||||
const releaseLock = async app => {
|
const releaseLock = async app => {
|
||||||
try {
|
try {
|
||||||
const response = await del(`/api/dev/${app.devId}/lock`)
|
const response = await del(`/api/dev/${app.devId}/lock`)
|
||||||
|
@ -236,6 +243,7 @@
|
||||||
{editApp}
|
{editApp}
|
||||||
{exportApp}
|
{exportApp}
|
||||||
{deleteApp}
|
{deleteApp}
|
||||||
|
{updateApp}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
@ -289,6 +297,12 @@
|
||||||
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
|
Are you sure you want to unpublish the app <b>{selectedApp?.name}</b>?
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<UpdateAppModal
|
||||||
|
app={selectedApp}
|
||||||
|
bind:this={updatingModal}
|
||||||
|
>
|
||||||
|
</UpdateAppModal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.title,
|
.title,
|
||||||
.filter {
|
.filter {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { get } from "builderStore/api"
|
import { get } from "builderStore/api"
|
||||||
import { AppStatus } from "../../constants"
|
import { AppStatus } from "../../constants"
|
||||||
|
import api from "../../builderStore/api";
|
||||||
|
|
||||||
export function createAppStore() {
|
export function createAppStore() {
|
||||||
const store = writable([])
|
const store = writable([])
|
||||||
|
@ -53,9 +54,27 @@ export function createAppStore() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function update (appId, name) {
|
||||||
|
const response = await api.put(`/api/applications/${appId}`, { name })
|
||||||
|
if (response.status === 200) {
|
||||||
|
store.update(state => {
|
||||||
|
const updatedAppIndex = state.findIndex(app => app.instance._id === appId);
|
||||||
|
if (updatedAppIndex !== -1) {
|
||||||
|
const updatedApp = state[updatedAppIndex];
|
||||||
|
updatedApp.name = name;
|
||||||
|
state.apps = state.splice(updatedAppIndex, 1, updatedApp);
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw new Error("Error updating name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe: store.subscribe,
|
subscribe: store.subscribe,
|
||||||
load,
|
load,
|
||||||
|
update,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue