remove legacy RawAppService endpoints
This commit is contained in:
@@ -7769,23 +7769,6 @@ paths:
|
||||
items:
|
||||
$ref: "#/components/schemas/ListableRawApp"
|
||||
|
||||
/w/{workspace}/raw_apps/exists/{path}:
|
||||
get:
|
||||
summary: does an app exisst at path
|
||||
operationId: existsRawApp
|
||||
tags:
|
||||
- raw_app
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
responses:
|
||||
"200":
|
||||
description: app exists
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
|
||||
/w/{workspace}/apps/get_data/v/{secretWithExtension}:
|
||||
get:
|
||||
summary: get raw app data by
|
||||
@@ -8215,88 +8198,6 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AppWithLastVersion"
|
||||
|
||||
/w/{workspace}/raw_apps/create:
|
||||
post:
|
||||
summary: create raw app
|
||||
operationId: createRawApp
|
||||
tags:
|
||||
- raw_app
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
requestBody:
|
||||
description: new raw app
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
summary:
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
- value
|
||||
- summary
|
||||
responses:
|
||||
"201":
|
||||
description: raw app created
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/raw_apps/update/{path}:
|
||||
post:
|
||||
summary: update app
|
||||
operationId: updateRawApp
|
||||
tags:
|
||||
- raw_app
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/ScriptPath"
|
||||
requestBody:
|
||||
description: updateraw app
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
summary:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: app updated
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/raw_apps/delete/{path}:
|
||||
delete:
|
||||
summary: delete raw app
|
||||
operationId: deleteRawApp
|
||||
tags:
|
||||
- raw_app
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
responses:
|
||||
"200":
|
||||
description: app deleted
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/apps/delete/{path}:
|
||||
delete:
|
||||
summary: delete app
|
||||
|
||||
@@ -5,42 +5,29 @@
|
||||
* Please see the included NOTICE for copyright information and
|
||||
* LICENSE-AGPL for a copy of the license.
|
||||
*/
|
||||
use crate::{
|
||||
db::{ApiAuthed, DB},
|
||||
users::require_owner_of_path,
|
||||
utils::check_scopes,
|
||||
webhook_util::{WebhookMessage, WebhookShared},
|
||||
};
|
||||
use crate::{db::ApiAuthed, utils::check_scopes};
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::{Extension, Json, Path, Query},
|
||||
response::Response,
|
||||
routing::{delete, get, post},
|
||||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use hyper::{header, StatusCode};
|
||||
use hyper::header;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sql_builder::{bind::Bind, SqlBuilder};
|
||||
use sqlx::FromRow;
|
||||
use std::str;
|
||||
use windmill_audit::audit_oss::audit_log;
|
||||
use windmill_audit::ActionKind;
|
||||
use windmill_common::{
|
||||
apps::ListAppQuery,
|
||||
db::UserDB,
|
||||
error::{Error, JsonResult, Result},
|
||||
utils::{not_found_if_none, paginate, Pagination, StripPath},
|
||||
worker::CLOUD_HOSTED,
|
||||
};
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
Router::new()
|
||||
.route("/list", get(list_apps))
|
||||
.route("/get_data/:version/*path", get(get_data))
|
||||
.route("/exists/*path", get(exists_app))
|
||||
.route("/update/*path", post(update_app))
|
||||
.route("/delete/*path", delete(delete_app))
|
||||
.route("/create", post(create_app))
|
||||
}
|
||||
|
||||
#[derive(FromRow, Deserialize, Serialize)]
|
||||
@@ -54,20 +41,6 @@ pub struct ListableApp {
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CreateApp {
|
||||
pub path: String,
|
||||
pub summary: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct EditApp {
|
||||
pub path: Option<String>,
|
||||
pub summary: Option<String>,
|
||||
pub value: Option<String>,
|
||||
}
|
||||
|
||||
async fn list_apps(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
@@ -147,230 +120,3 @@ async fn get_data(
|
||||
|
||||
Ok(res.body(Body::from(app)).unwrap())
|
||||
}
|
||||
|
||||
async fn create_app(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(webhook): Extension<WebhookShared>,
|
||||
Extension(db): Extension<DB>,
|
||||
Path(w_id): Path<String>,
|
||||
Json(app): Json<CreateApp>,
|
||||
) -> Result<(StatusCode, String)> {
|
||||
if authed.is_operator {
|
||||
return Err(Error::NotAuthorized(
|
||||
"Operators cannot create raw apps for security reasons".to_string(),
|
||||
));
|
||||
}
|
||||
check_scopes(&authed, || format!("raw_apps:write:{}", app.path))?;
|
||||
if *CLOUD_HOSTED {
|
||||
let nb_apps = sqlx::query_scalar!(
|
||||
"SELECT COUNT(*) FROM raw_app WHERE workspace_id = $1",
|
||||
&w_id
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?;
|
||||
if nb_apps.unwrap_or(0) >= 1000 {
|
||||
return Err(Error::BadRequest(
|
||||
"You have reached the maximum number of apps (1000) on cloud. Contact support@windmill.dev to increase the limit"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
if app.summary.len() > 300 {
|
||||
return Err(Error::BadRequest(
|
||||
"Summary must be less than 300 characters on cloud".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
if &app.path == "" {
|
||||
return Err(Error::BadRequest("App path cannot be empty".to_string()));
|
||||
}
|
||||
|
||||
let exists = sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM raw_app WHERE path = $1 AND workspace_id = $2)",
|
||||
app.path,
|
||||
w_id
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
|
||||
if exists {
|
||||
return Err(Error::BadRequest(format!(
|
||||
"App with path {} already exists",
|
||||
&app.path
|
||||
)));
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO raw_app
|
||||
(workspace_id, path, summary, extra_perms, data)
|
||||
VALUES ($1, $2, $3, '{}', $4)",
|
||||
w_id,
|
||||
app.path,
|
||||
app.summary,
|
||||
app.value,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed,
|
||||
"apps.create",
|
||||
ActionKind::Create,
|
||||
&w_id,
|
||||
Some(&app.path),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
tx.commit().await?;
|
||||
webhook.send_message(
|
||||
w_id.clone(),
|
||||
WebhookMessage::CreateApp { workspace: w_id, path: app.path.clone() },
|
||||
);
|
||||
|
||||
Ok((StatusCode::CREATED, app.path))
|
||||
}
|
||||
|
||||
async fn delete_app(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(webhook): Extension<WebhookShared>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> Result<String> {
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || format!("raw_apps:write:{}", path))?;
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
sqlx::query!(
|
||||
"DELETE FROM raw_app WHERE path = $1 AND workspace_id = $2",
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed,
|
||||
"apps.delete",
|
||||
ActionKind::Delete,
|
||||
&w_id,
|
||||
Some(path),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
webhook.send_message(
|
||||
w_id.clone().clone(),
|
||||
WebhookMessage::DeleteApp { workspace: w_id, path: path.to_owned() },
|
||||
);
|
||||
|
||||
Ok(format!("app {} deleted", path))
|
||||
}
|
||||
|
||||
async fn update_app(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(webhook): Extension<WebhookShared>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
Json(app): Json<EditApp>,
|
||||
) -> Result<String> {
|
||||
if authed.is_operator {
|
||||
return Err(Error::NotAuthorized(
|
||||
"Operators cannot update raw apps for security reasons".to_string(),
|
||||
));
|
||||
}
|
||||
use sql_builder::prelude::*;
|
||||
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || format!("raw_apps:write:{}", path))?;
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let mut sqlb = SqlBuilder::update_table("raw_app");
|
||||
sqlb.and_where_eq("path", "?".bind(&path));
|
||||
sqlb.and_where_eq("workspace_id", "?".bind(&w_id));
|
||||
|
||||
let npath = &app.path;
|
||||
if npath.is_some() || app.summary.is_some() {
|
||||
if let Some(npath) = npath {
|
||||
if npath != path {
|
||||
require_owner_of_path(&authed, path)?;
|
||||
|
||||
let exists = sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM app WHERE path = $1 AND workspace_id = $2)",
|
||||
npath,
|
||||
w_id
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
|
||||
if exists {
|
||||
return Err(Error::BadRequest(format!(
|
||||
"App with path {} already exists",
|
||||
npath
|
||||
)));
|
||||
}
|
||||
}
|
||||
sqlb.set_str("path", npath);
|
||||
}
|
||||
|
||||
if let Some(nsummary) = &app.summary {
|
||||
sqlb.set_str("summary", nsummary);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = &app.value {
|
||||
sqlb.set_str("data", value);
|
||||
sqlb.set("version", "version + 1");
|
||||
}
|
||||
|
||||
sqlb.returning("path");
|
||||
|
||||
let sql = sqlb.sql().map_err(|e| Error::internal_err(e.to_string()))?;
|
||||
let npath_o: Option<String> = sqlx::query_scalar(&sql).fetch_optional(&mut *tx).await?;
|
||||
not_found_if_none(npath_o, "Raw App", path)?;
|
||||
|
||||
let npath = app.path.clone().unwrap_or_else(|| path.to_owned());
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed,
|
||||
"apps.update",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
Some(&path),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
webhook.send_message(
|
||||
w_id.clone(),
|
||||
WebhookMessage::UpdateApp {
|
||||
workspace: w_id,
|
||||
old_path: path.to_owned(),
|
||||
new_path: npath.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
Ok(format!("app {} updated (npath: {:?})", path, npath))
|
||||
}
|
||||
|
||||
async fn exists_app(
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> JsonResult<bool> {
|
||||
let path = path.to_path();
|
||||
// Note: exists_app doesn't require authentication, so no scope check needed
|
||||
let exists = sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM raw_app WHERE path = $1 AND workspace_id = $2)",
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
|
||||
Ok(Json(exists))
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
AppService,
|
||||
FlowService,
|
||||
FolderService,
|
||||
RawAppService,
|
||||
ResourceService,
|
||||
ScheduleService,
|
||||
ScriptService,
|
||||
@@ -198,21 +197,6 @@
|
||||
path: path
|
||||
})
|
||||
return resource.schema
|
||||
} else if (kind == 'raw_app') {
|
||||
throw new Error('Raw app deploy not implemented yet')
|
||||
// const app = await RawAppService.getRawAppData({
|
||||
// workspace: workspace,
|
||||
// path: path
|
||||
// })
|
||||
// if (alreadyExists) {
|
||||
// }
|
||||
// await RawAppService.updateRawApp({
|
||||
// workspace: workspace,
|
||||
// path: path,
|
||||
// requestBody: {
|
||||
// path: path
|
||||
// }
|
||||
// })
|
||||
} else if (kind == 'folder') {
|
||||
const folder = await FolderService.getFolder({
|
||||
workspace: workspace,
|
||||
@@ -293,11 +277,6 @@
|
||||
workspace: workspace,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'raw_app') {
|
||||
exists = await RawAppService.existsRawApp({
|
||||
workspace: workspace,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'variable') {
|
||||
exists = await VariableService.existsVariable({
|
||||
workspace: workspace,
|
||||
@@ -573,21 +552,6 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (kind == 'raw_app') {
|
||||
throw new Error('Raw app deploy not implemented yet')
|
||||
// const app = await RawAppService.getRawAppData({
|
||||
// workspace: workspaceFrom,
|
||||
// path: path
|
||||
// })
|
||||
// if (alreadyExists) {
|
||||
// }
|
||||
// await RawAppService.updateRawApp({
|
||||
// workspace: workspaceFrom,
|
||||
// path: path,
|
||||
// requestBody: {
|
||||
// path: path
|
||||
// }
|
||||
// })
|
||||
} else if (kind == 'folder') {
|
||||
await FolderService.createFolder({
|
||||
workspace: workspaceToDeployTo,
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
AppService,
|
||||
FlowService,
|
||||
FolderService,
|
||||
RawAppService,
|
||||
ResourceService,
|
||||
ScheduleService,
|
||||
ScriptService,
|
||||
@@ -232,11 +231,6 @@
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'raw_app') {
|
||||
exists = await RawAppService.existsRawApp({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'variable') {
|
||||
exists = await VariableService.existsVariable({
|
||||
workspace: workspaceToDeployTo!,
|
||||
@@ -498,21 +492,6 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (kind == 'raw_app') {
|
||||
throw new Error('Raw app deploy not implemented yet')
|
||||
// const app = await RawAppService.getRawAppData({
|
||||
// workspace: $workspaceStore!,
|
||||
// path: path
|
||||
// })
|
||||
// if (alreadyExists) {
|
||||
// }
|
||||
// await RawAppService.updateRawApp({
|
||||
// workspace: $workspaceStore!,
|
||||
// path: path,
|
||||
// requestBody: {
|
||||
// path: path
|
||||
// }
|
||||
// })
|
||||
} else if (kind == 'folder') {
|
||||
await FolderService.createFolder({
|
||||
workspace: workspaceToDeployTo!,
|
||||
@@ -616,21 +595,6 @@
|
||||
path: path
|
||||
})
|
||||
return resource.schema
|
||||
} else if (kind == 'raw_app') {
|
||||
throw new Error('Raw app deploy not implemented yet')
|
||||
// const app = await RawAppService.getRawAppData({
|
||||
// workspace: workspace,
|
||||
// path: path
|
||||
// })
|
||||
// if (alreadyExists) {
|
||||
// }
|
||||
// await RawAppService.updateRawApp({
|
||||
// workspace: workspace,
|
||||
// path: path,
|
||||
// requestBody: {
|
||||
// path: path
|
||||
// }
|
||||
// })
|
||||
} else if (kind == 'folder') {
|
||||
const folder = await FolderService.getFolder({
|
||||
workspace: workspace,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
import { Alert, Button, Drawer } from './common'
|
||||
import DrawerContent from './common/drawer/DrawerContent.svelte'
|
||||
import Path from './Path.svelte'
|
||||
import { AppService, FlowService, RawAppService, ScriptService } from '$lib/gen'
|
||||
import { AppService, FlowService, ScriptService } from '$lib/gen'
|
||||
import { isOwner } from '$lib/utils'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
type Kind = 'script' | 'resource' | 'schedule' | 'variable' | 'flow' | 'app' | 'raw_app'
|
||||
type Kind = 'script' | 'resource' | 'schedule' | 'variable' | 'flow' | 'app'
|
||||
|
||||
let kind: Kind
|
||||
let initialPath: string = ''
|
||||
@@ -83,15 +83,6 @@
|
||||
summary
|
||||
}
|
||||
})
|
||||
} else if (kind == 'raw_app') {
|
||||
await RawAppService.updateRawApp({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath,
|
||||
requestBody: {
|
||||
path: path != initialPath ? path : undefined,
|
||||
summary
|
||||
}
|
||||
})
|
||||
}
|
||||
dispatch('update', path)
|
||||
drawer.closeDrawer()
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$lib/base'
|
||||
import Dropdown from '$lib/components/DropdownV2.svelte'
|
||||
import type MoveDrawer from '$lib/components/MoveDrawer.svelte'
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import type ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import { RawAppService, type ListableRawApp } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Button from '../button/Button.svelte'
|
||||
import { type ListableRawApp } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import Row from './Row.svelte'
|
||||
import Drawer from '../drawer/Drawer.svelte'
|
||||
import DrawerContent from '../drawer/DrawerContent.svelte'
|
||||
import FileInput from '../fileInput/FileInput.svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import type DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
import { FolderOpen, Globe, Pen, Share, Trash } from 'lucide-svelte'
|
||||
import { Globe, Share } from 'lucide-svelte'
|
||||
import { isDeployable } from '$lib/utils_deployable'
|
||||
import { getDeployUiSettings } from '$lib/components/home/deploy_ui'
|
||||
|
||||
@@ -22,8 +15,6 @@
|
||||
app: ListableRawApp & { canWrite: boolean }
|
||||
marked: string | undefined
|
||||
shareModal: ShareModal
|
||||
moveDrawer: MoveDrawer
|
||||
deleteConfirmedCallback: (() => void) | undefined
|
||||
deploymentDrawer: DeployWorkspaceDrawer
|
||||
depth?: number
|
||||
menuOpen?: boolean
|
||||
@@ -33,39 +24,12 @@
|
||||
app,
|
||||
marked,
|
||||
shareModal,
|
||||
moveDrawer,
|
||||
deleteConfirmedCallback = $bindable(),
|
||||
deploymentDrawer,
|
||||
depth = 0,
|
||||
menuOpen = $bindable(false)
|
||||
}: Props = $props()
|
||||
|
||||
let updateAppDrawer: Drawer | undefined = $state(undefined)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
{#if menuOpen}
|
||||
<Drawer bind:this={updateAppDrawer} size="800px">
|
||||
<DrawerContent title="Update app" on:close={() => updateAppDrawer?.toggleDrawer?.()}>
|
||||
<FileInput
|
||||
accept={'.js'}
|
||||
multiple={false}
|
||||
convertTo={'text'}
|
||||
iconSize={24}
|
||||
class="text-sm py-4"
|
||||
on:change={async ({ detail }) => {
|
||||
await RawAppService.updateRawApp({
|
||||
workspace: $workspaceStore ?? '',
|
||||
path: app.path,
|
||||
requestBody: { value: detail?.[0] }
|
||||
})
|
||||
goto(`/apps/get_raw/${app.version + 1}/${app.path}`)
|
||||
}}
|
||||
/>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
{/if}
|
||||
<Row
|
||||
href="{base}/apps/get_raw/{app.version}/{app.path}"
|
||||
kind="raw_app"
|
||||
@@ -80,35 +44,11 @@
|
||||
<SharedBadge canWrite={app.canWrite} extraPerms={app.extra_perms} />
|
||||
{/snippet}
|
||||
{#snippet actions()}
|
||||
<span class="hidden md:inline-flex gap-x-1">
|
||||
{#if !$userStore?.operator}
|
||||
{#if app.canWrite}
|
||||
<div>
|
||||
<Button
|
||||
variant="subtle"
|
||||
unifiedSize="md"
|
||||
startIcon={{ icon: Pen }}
|
||||
on:click={() => updateAppDrawer?.toggleDrawer?.()}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
<Dropdown
|
||||
items={async () => {
|
||||
let { summary, path, canWrite } = app
|
||||
let { path, canWrite } = app
|
||||
|
||||
return [
|
||||
{
|
||||
displayName: 'Move/Rename',
|
||||
icon: FolderOpen,
|
||||
action: () => {
|
||||
moveDrawer.openDrawer(path, summary, 'raw_app')
|
||||
},
|
||||
disabled: !canWrite
|
||||
},
|
||||
...(isDeployable('app', path, await getDeployUiSettings())
|
||||
? [
|
||||
{
|
||||
@@ -126,25 +66,6 @@
|
||||
action: () => {
|
||||
shareModal.openDrawer && shareModal.openDrawer(path, 'raw_app')
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: 'Delete',
|
||||
icon: Trash,
|
||||
action: async (event) => {
|
||||
// TODO
|
||||
// @ts-ignore
|
||||
if (event?.shiftKey) {
|
||||
await RawAppService.deleteRawApp({ workspace: $workspaceStore ?? '', path })
|
||||
dispatch('change')
|
||||
} else {
|
||||
deleteConfirmedCallback = async () => {
|
||||
await RawAppService.deleteRawApp({ workspace: $workspaceStore ?? '', path })
|
||||
dispatch('change')
|
||||
}
|
||||
}
|
||||
},
|
||||
type: 'delete',
|
||||
disabled: !canWrite
|
||||
}
|
||||
]
|
||||
}}
|
||||
|
||||
@@ -72,11 +72,8 @@
|
||||
/>
|
||||
{:else if item.type == 'raw_app'}
|
||||
<RawAppRow
|
||||
bind:deleteConfirmedCallback
|
||||
marked={item.marked}
|
||||
on:change={() => dispatch('rawAppChanged')}
|
||||
app={item}
|
||||
{moveDrawer}
|
||||
{shareModal}
|
||||
{deploymentDrawer}
|
||||
{depth}
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
type Script,
|
||||
ScriptService,
|
||||
type Flow,
|
||||
type ListableRawApp,
|
||||
RawAppService
|
||||
type ListableRawApp
|
||||
} from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import type uFuzzy from '@leeoniya/ufuzzy'
|
||||
@@ -134,17 +133,7 @@
|
||||
}
|
||||
|
||||
async function loadRawApps(): Promise<void> {
|
||||
raw_apps = (await RawAppService.listRawApps({ workspace: $workspaceStore! })).map(
|
||||
(app: ListableRawApp) => {
|
||||
return {
|
||||
canWrite:
|
||||
canWrite(app.path!, app.extra_perms!, $userStore) &&
|
||||
app.workspace_id == $workspaceStore &&
|
||||
!$userStore?.operator,
|
||||
...app
|
||||
}
|
||||
}
|
||||
)
|
||||
raw_apps = []
|
||||
loading = false
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import {
|
||||
AppService,
|
||||
FlowService,
|
||||
RawAppService,
|
||||
ScriptService,
|
||||
type Flow,
|
||||
type ListableApp,
|
||||
@@ -492,7 +491,6 @@
|
||||
withoutDescription: true
|
||||
})
|
||||
const apps = await AppService.listApps({ workspace: $workspaceStore! })
|
||||
const raw_apps = await RawAppService.listRawApps({ workspace: $workspaceStore! })
|
||||
|
||||
let combinedItems: (TableScript | TableFlow | TableApp | TableRawApp)[] | undefined = [
|
||||
...flows.map((x) => ({
|
||||
@@ -512,12 +510,6 @@
|
||||
type: 'app' as 'app',
|
||||
time: new Date(x.edited_at).getTime(),
|
||||
search_id: x.path
|
||||
})),
|
||||
...raw_apps.map((x) => ({
|
||||
...x,
|
||||
type: 'raw_app' as 'raw_app',
|
||||
time: new Date(x.edited_at).getTime(),
|
||||
search_id: x.path
|
||||
}))
|
||||
].sort((a, b) => (a.starred != b.starred ? (a.starred ? -1 : 1) : a.time - b.time > 0 ? -1 : 1))
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
AssetService,
|
||||
FlowService,
|
||||
OpenAPI,
|
||||
RawAppService,
|
||||
ScriptService,
|
||||
SettingService,
|
||||
UserService,
|
||||
@@ -192,10 +191,6 @@
|
||||
workspace: $workspaceStore ?? '',
|
||||
starredOnly: true
|
||||
})
|
||||
const raw_apps = await RawAppService.listRawApps({
|
||||
workspace: $workspaceStore ?? '',
|
||||
starredOnly: true
|
||||
})
|
||||
const assets = await AssetService.listFavoriteAssets({ workspace: $workspaceStore ?? '' })
|
||||
favoriteManager.current = [
|
||||
...scripts.map((s) => ({
|
||||
@@ -216,12 +211,6 @@
|
||||
href: getFavoriteHref(f.path, 'app'),
|
||||
kind: 'app' as const
|
||||
})),
|
||||
...raw_apps.map((f) => ({
|
||||
label: f.summary || getFavoriteLabel(f.path, 'raw_app'),
|
||||
path: f.path,
|
||||
href: getFavoriteHref(f.path, 'raw_app'),
|
||||
kind: 'raw_app' as const
|
||||
})),
|
||||
...assets.map((a) => ({
|
||||
label: getFavoriteLabel(a.path, 'asset'),
|
||||
path: a.path,
|
||||
|
||||
Reference in New Issue
Block a user