fix: hide draft only items in pickers and from ops (#3977)

* fix: hide draft only scripts to ops and in pickers/flow builder

* fix: default to hiding draft only scripts

* fix: hide script drafts from ops

* fix: generalize to hide draft only/no main func by default

* fix: archived openapi nit
This commit is contained in:
HugoCasa
2024-06-26 12:21:45 +02:00
committed by GitHub
parent 9ac18c33bf
commit dd804839f0
14 changed files with 96 additions and 41 deletions
+25 -4
View File
@@ -3502,17 +3502,24 @@ paths:
- name: show_archived
description: |
(default false)
show also the archived files.
show only the archived files.
when multiple archived hash share the same path, only the ones with the latest create_at
are
ed.
in: query
schema:
type: boolean
- name: hide_without_main
- name: include_without_main
description: |
(default false)
hide the scripts without an exported main function
include scripts without an exported main function
in: query
schema:
type: boolean
- name: include_draft_only
description: |
(default false)
include scripts that have no deployed version
in: query
schema:
type: boolean
@@ -4261,7 +4268,7 @@ paths:
- name: show_archived
description: |
(default false)
show also the archived files.
show only the archived files.
when multiple archived hash share the same path, only the ones with the latest create_at
are displayed.
in: query
@@ -4274,6 +4281,13 @@ paths:
in: query
schema:
type: boolean
- name: include_draft_only
description: |
(default false)
include items that have no deployed version
in: query
schema:
type: boolean
responses:
"200":
description: All flow
@@ -4627,6 +4641,13 @@ paths:
in: query
schema:
type: boolean
- name: include_draft_only
description: |
(default false)
include items that have no deployed version
in: query
schema:
type: boolean
responses:
"200":
description: All apps
+4
View File
@@ -287,6 +287,10 @@ async fn list_apps(
sqlb.and_where_eq("app.path", "?".bind(path_exact));
}
if !lq.include_draft_only.unwrap_or(false) || authed.is_operator {
sqlb.and_where("app.draft_only IS NOT TRUE");
}
let sql = sqlb.sql().map_err(|e| Error::InternalErr(e.to_string()))?;
let mut tx = user_db.begin(&authed).await?;
let rows = sqlx::query_as::<_, ListableApp>(&sql)
+4
View File
@@ -155,6 +155,10 @@ async fn list_flows(
sqlb.and_where_is_not_null("favorite.path");
}
if !lq.include_draft_only.unwrap_or(false) || authed.is_operator {
sqlb.and_where("o.draft_only IS NOT TRUE");
}
let sql = sqlb.sql().map_err(|e| Error::InternalErr(e.to_string()))?;
let mut tx = user_db.begin(&authed).await?;
let rows = sqlx::query_as::<_, ListableFlow>(&sql)
+5 -1
View File
@@ -226,10 +226,14 @@ async fn list_scripts(
.limit(per_page)
.clone();
if authed.is_operator || lq.hide_without_main.unwrap_or(false) {
if !lq.include_without_main.unwrap_or(false) || authed.is_operator {
sqlb.and_where("o.no_main_func IS NOT TRUE");
}
if !lq.include_draft_only.unwrap_or(false) || authed.is_operator {
sqlb.and_where("draft_only IS NOT TRUE");
}
if lq.show_archived.unwrap_or(false) {
sqlb.and_where_eq(
"o.created_at",
+1
View File
@@ -13,4 +13,5 @@ pub struct ListAppQuery {
pub starred_only: Option<bool>,
pub path_exact: Option<String>,
pub path_start: Option<String>,
pub include_draft_only: Option<bool>,
}
+1
View File
@@ -551,6 +551,7 @@ pub struct ListFlowQuery {
pub order_by: Option<String>,
pub order_desc: Option<bool>,
pub starred_only: Option<bool>,
pub include_draft_only: Option<bool>,
}
pub fn add_virtual_items_if_necessary(modules: &mut Vec<FlowModule>) {
+2 -1
View File
@@ -336,7 +336,8 @@ pub struct ListScriptQuery {
pub is_template: Option<bool>,
pub kinds: Option<String>,
pub starred_only: Option<bool>,
pub hide_without_main: Option<bool>,
pub include_without_main: Option<bool>,
pub include_draft_only: Option<bool>,
}
pub fn to_i64(s: &str) -> crate::error::Result<i64> {
@@ -6621,8 +6621,8 @@ var ScriptService = class {
* are
* ed.
*
* @param data.hideWithoutMain (default false)
* hide the scripts without an exported main function
* @param data.includeWithoutMain (default false)
* include scripts without an exported main function
*
* @param data.isTemplate (default regardless)
* if true show only the templates
@@ -6656,7 +6656,7 @@ var ScriptService = class {
last_parent_hash: data.lastParentHash,
parent_hash: data.parentHash,
show_archived: data.showArchived,
hide_without_main: data.hideWithoutMain,
includeWithoutMain: data.includeWithoutMain,
is_template: data.isTemplate,
kinds: data.kinds,
starred_only: data.starredOnly,
+2 -1
View File
@@ -104,7 +104,7 @@ export async function pushApp(
}
}
async function list(opts: GlobalOptions) {
async function list(opts: GlobalOptions & { includeDraftOnly?: boolean }) {
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
@@ -116,6 +116,7 @@ async function list(opts: GlobalOptions) {
workspace: workspace.workspaceId,
page,
perPage,
includeDraftOnly: opts.includeDraftOnly ?? false,
});
page += 1;
total.push(...res);
+4 -1
View File
@@ -139,7 +139,9 @@ async function push(opts: Options, filePath: string, remotePath: string) {
log.info(colors.bold.underline.green("Flow pushed"));
}
async function list(opts: GlobalOptions & { showArchived?: boolean }) {
async function list(
opts: GlobalOptions & { showArchived?: boolean; includeDraftOnly?: boolean }
) {
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
@@ -152,6 +154,7 @@ async function list(opts: GlobalOptions & { showArchived?: boolean }) {
page,
perPage,
showArchived: opts.showArchived ?? false,
includeDraftOnly: opts.includeDraftOnly ?? false,
});
page += 1;
total.push(...res);
+9 -1
View File
@@ -440,7 +440,13 @@ export function removeExtensionToPath(path: string): string {
throw new Error("Invalid extension: " + path);
}
async function list(opts: GlobalOptions & { showArchived?: boolean }) {
async function list(
opts: GlobalOptions & {
showArchived?: boolean;
includeWithoutMain?: boolean;
includeDraftOnly?: boolean;
}
) {
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
@@ -453,6 +459,8 @@ async function list(opts: GlobalOptions & { showArchived?: boolean }) {
page,
perPage,
showArchived: opts.showArchived ?? false,
includeWithoutMain: opts.includeWithoutMain ?? false,
includeDraftOnly: opts.includeDraftOnly ?? true,
});
page += 1;
total.push(...res);
@@ -72,11 +72,12 @@
let nbDisplayed = 15
async function loadScripts(hideWithoutMain: boolean): Promise<void> {
async function loadScripts(includeWithoutMain: boolean): Promise<void> {
const loadedScripts = await ScriptService.listScripts({
workspace: $workspaceStore!,
showArchived: archived ? true : undefined,
hideWithoutMain: hideWithoutMain ? true : undefined
includeWithoutMain: includeWithoutMain ? true : undefined,
includeDraftOnly: true
})
scripts = loadedScripts.map((script: Script) => {
@@ -92,7 +93,8 @@
flows = (
await FlowService.listFlows({
workspace: $workspaceStore!,
showArchived: archived ? true : undefined
showArchived: archived ? true : undefined,
includeDraftOnly: true
})
).map((x: Flow) => {
return {
@@ -107,15 +109,17 @@
}
async function loadApps(): Promise<void> {
apps = (await AppService.listApps({ workspace: $workspaceStore! })).map((app: ListableApp) => {
return {
canWrite:
canWrite(app.path!, app.extra_perms!, $userStore) &&
app.workspace_id == $workspaceStore &&
!$userStore?.operator,
...app
apps = (await AppService.listApps({ workspace: $workspaceStore!, includeDraftOnly: true })).map(
(app: ListableApp) => {
return {
canWrite:
canWrite(app.path!, app.extra_perms!, $userStore) &&
app.workspace_id == $workspaceStore &&
!$userStore?.operator,
...app
}
}
})
)
loading = false
}
@@ -201,7 +205,7 @@
$: {
if ($userStore && $workspaceStore) {
loadScripts(hideWithoutMain)
loadScripts(includeWithoutMain)
loadFlows()
if (!archived) {
loadApps()
@@ -274,14 +278,16 @@
const TREE_VIEW_SETTING_NAME = 'treeView'
const FILTER_USER_FOLDER_SETTING_NAME = 'filterUserFolders'
const HIDE_WITHOUT_MAIN_SETTING = 'hideWithoutMain'
const INCLUDE_WITHOUT_MAIN_SETTING_NAME = 'includeWithoutMain'
let treeView = getLocalSetting(TREE_VIEW_SETTING_NAME) == 'true'
let filterUserFolders = getLocalSetting(FILTER_USER_FOLDER_SETTING_NAME) == 'true'
let hideWithoutMain = getLocalSetting(HIDE_WITHOUT_MAIN_SETTING) == 'true'
let includeWithoutMain = getLocalSetting(INCLUDE_WITHOUT_MAIN_SETTING_NAME)
? getLocalSetting(INCLUDE_WITHOUT_MAIN_SETTING_NAME) == 'true'
: true
$: storeLocalSetting(TREE_VIEW_SETTING_NAME, treeView ? 'true' : undefined)
$: storeLocalSetting(FILTER_USER_FOLDER_SETTING_NAME, filterUserFolders ? 'true' : undefined)
$: storeLocalSetting(HIDE_WITHOUT_MAIN_SETTING, hideWithoutMain ? 'true' : undefined)
$: storeLocalSetting(INCLUDE_WITHOUT_MAIN_SETTING_NAME, includeWithoutMain ? 'true' : undefined)
let contentSearch: ContentSearch
@@ -436,12 +442,12 @@
<div>
<span class="text-sm font-semibold">Filters</span>
<div class="flex flex-col gap-2 mt-2">
<Toggle size="xs" bind:checked={archived} options={{ right: 'Show archived' }} />
<Toggle size="xs" bind:checked={archived} options={{ right: 'Only archived' }} />
{#if $userStore && !$userStore.operator}
<Toggle
size="xs"
bind:checked={hideWithoutMain}
options={{ right: 'Hide without main function' }}
bind:checked={includeWithoutMain}
options={{ right: 'Include without main function' }}
/>
{/if}
</div>
@@ -493,12 +499,12 @@
{nbDisplayed}
{collapseAll}
isSearching={filter !== ''}
on:scriptChanged={() => loadScripts(hideWithoutMain)}
on:scriptChanged={() => loadScripts(includeWithoutMain)}
on:flowChanged={loadFlows}
on:appChanged={loadApps}
on:rawAppChanged={loadRawApps}
on:reload={() => {
loadScripts(hideWithoutMain)
loadScripts(includeWithoutMain)
loadFlows()
loadApps()
loadRawApps()
@@ -510,12 +516,12 @@
{#each (items ?? []).slice(0, nbDisplayed) as item (item.type + '/' + item.path)}
<Item
{item}
on:scriptChanged={() => loadScripts(hideWithoutMain)}
on:scriptChanged={() => loadScripts(includeWithoutMain)}
on:flowChanged={loadFlows}
on:appChanged={loadApps}
on:rawAppChanged={loadRawApps}
on:reload={() => {
loadScripts(hideWithoutMain)
loadScripts(includeWithoutMain)
loadFlows()
loadApps()
loadRawApps()
+6 -6
View File
@@ -6017,10 +6017,10 @@ export type ListScriptsData = {
firstParentHash?: string;
/**
* (default false)
* hide the scripts without an exported main function
* include scripts without an exported main function
*
*/
hideWithoutMain?: boolean;
includeWithoutMain?: boolean;
/**
* (default regardless)
* if true show only the templates
@@ -10651,10 +10651,10 @@ export type $OpenApiTs = {
firstParentHash?: string;
/**
* (default false)
* hide the scripts without an exported main function
* include scripts without an exported main function
*
*/
hideWithoutMain?: boolean;
includeWithoutMain?: boolean;
/**
* (default regardless)
* if true show only the templates
@@ -15268,8 +15268,8 @@ export declare class ScriptService {
* are
* ed.
*
* @param data.hideWithoutMain (default false)
* hide the scripts without an exported main function
* @param data.includeWithoutMain (default false)
* include scripts without an exported main function
*
* @param data.isTemplate (default regardless)
* if true show only the templates
@@ -136,7 +136,8 @@
async function loadFavorites() {
const scripts = await ScriptService.listScripts({
workspace: $workspaceStore ?? '',
starredOnly: true
starredOnly: true,
includeWithoutMain: true
})
const flows = await FlowService.listFlows({
workspace: $workspaceStore ?? '',