Use standard firstSeed/seedCount fallback for workflows with no name in profile details (#1852)
Fixes #1833 - Add firstSeed and seedCount to workflow information in profile detail API endpoint (tests updated accordingly), update name of model used for limited workflow information to be more accurate - Fix name display in Crawl Workflows list at bottom of Profile detail page to be consistent with rest of application --------- Co-authored-by: Emma Segal-Grossman <hi@emma.cafe>
This commit is contained in:
parent
a85f9496b0
commit
4edc05d503
@ -23,7 +23,7 @@ from .models import (
|
|||||||
ConfigRevision,
|
ConfigRevision,
|
||||||
CrawlConfig,
|
CrawlConfig,
|
||||||
CrawlConfigOut,
|
CrawlConfigOut,
|
||||||
CrawlConfigIdNameOut,
|
CrawlConfigProfileOut,
|
||||||
CrawlOut,
|
CrawlOut,
|
||||||
EmptyStr,
|
EmptyStr,
|
||||||
UpdateCrawlConfig,
|
UpdateCrawlConfig,
|
||||||
@ -547,17 +547,24 @@ class CrawlConfigOps:
|
|||||||
|
|
||||||
return configs, total
|
return configs, total
|
||||||
|
|
||||||
async def get_crawl_config_ids_for_profile(
|
async def get_crawl_config_info_for_profile(
|
||||||
self, profileid: UUID, org: Optional[Organization] = None
|
self, profileid: UUID, org: Organization
|
||||||
):
|
):
|
||||||
"""Return all crawl configs that are associated with a given profileid"""
|
"""Return all crawl configs that are associated with a given profileid"""
|
||||||
query = {"profileid": profileid, "inactive": {"$ne": True}}
|
query = {"profileid": profileid, "inactive": {"$ne": True}}
|
||||||
if org:
|
if org:
|
||||||
query["oid"] = org.id
|
query["oid"] = org.id
|
||||||
|
|
||||||
cursor = self.crawl_configs.find(query, projection=["_id", "name"])
|
results = []
|
||||||
results = await cursor.to_list(length=1000)
|
|
||||||
results = [CrawlConfigIdNameOut.from_dict(res) for res in results]
|
cursor = self.crawl_configs.find(query, projection=["_id"])
|
||||||
|
workflows = await cursor.to_list(length=1000)
|
||||||
|
for workflow_dict in workflows:
|
||||||
|
workflow_out = await self.get_crawl_config_out(
|
||||||
|
workflow_dict.get("_id"), org
|
||||||
|
)
|
||||||
|
results.append(CrawlConfigProfileOut.from_dict(workflow_out.to_dict()))
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
async def get_running_crawl(
|
async def get_running_crawl(
|
||||||
|
@ -412,10 +412,12 @@ class CrawlConfigOut(CrawlConfigCore, CrawlConfigAdditional):
|
|||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
class CrawlConfigIdNameOut(BaseMongoModel):
|
class CrawlConfigProfileOut(BaseMongoModel):
|
||||||
"""Crawl Config id and name output only"""
|
"""Crawl Config basic info for profiles"""
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
|
firstSeed: str
|
||||||
|
seedCount: int
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@ -1197,7 +1199,7 @@ class Profile(BaseMongoModel):
|
|||||||
class ProfileWithCrawlConfigs(Profile):
|
class ProfileWithCrawlConfigs(Profile):
|
||||||
"""Profile with list of crawlconfigs using this profile"""
|
"""Profile with list of crawlconfigs using this profile"""
|
||||||
|
|
||||||
crawlconfigs: List[CrawlConfigIdNameOut] = []
|
crawlconfigs: List[CrawlConfigProfileOut] = []
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
@ -336,9 +336,7 @@ class ProfileOps:
|
|||||||
|
|
||||||
return Profile.from_dict(res)
|
return Profile.from_dict(res)
|
||||||
|
|
||||||
async def get_profile_with_configs(
|
async def get_profile_with_configs(self, profileid: UUID, org: Organization):
|
||||||
self, profileid: UUID, org: Optional[Organization] = None
|
|
||||||
):
|
|
||||||
"""get profile for api output, with crawlconfigs"""
|
"""get profile for api output, with crawlconfigs"""
|
||||||
|
|
||||||
profile = await self.get_profile(profileid, org)
|
profile = await self.get_profile(profileid, org)
|
||||||
@ -369,16 +367,14 @@ class ProfileOps:
|
|||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def get_crawl_configs_for_profile(
|
async def get_crawl_configs_for_profile(self, profileid: UUID, org: Organization):
|
||||||
self, profileid: UUID, org: Optional[Organization] = None
|
"""Get list of crawl configs with basic info for that use a particular profile"""
|
||||||
):
|
|
||||||
"""Get list of crawl config id, names for that use a particular profile"""
|
|
||||||
|
|
||||||
crawlconfig_names = await self.crawlconfigs.get_crawl_config_ids_for_profile(
|
crawlconfig_info = await self.crawlconfigs.get_crawl_config_info_for_profile(
|
||||||
profileid, org
|
profileid, org
|
||||||
)
|
)
|
||||||
|
|
||||||
return crawlconfig_names
|
return crawlconfig_info
|
||||||
|
|
||||||
async def delete_profile(self, profileid: UUID, org: Organization):
|
async def delete_profile(self, profileid: UUID, org: Organization):
|
||||||
"""delete profile, if not used in active crawlconfig"""
|
"""delete profile, if not used in active crawlconfig"""
|
||||||
|
@ -238,6 +238,8 @@ def test_get_profile(admin_auth_headers, default_org_id, profile_id, profile_con
|
|||||||
assert len(crawl_configs) == 1
|
assert len(crawl_configs) == 1
|
||||||
assert crawl_configs[0]["id"] == profile_config_id
|
assert crawl_configs[0]["id"] == profile_config_id
|
||||||
assert crawl_configs[0]["name"] == "Profile Test Crawl"
|
assert crawl_configs[0]["name"] == "Profile Test Crawl"
|
||||||
|
assert crawl_configs[0]["firstSeed"] == "https://webrecorder.net/"
|
||||||
|
assert crawl_configs[0]["seedCount"] == 1
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
if time.monotonic() - start_time > time_limit:
|
if time.monotonic() - start_time > time_limit:
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { localized, msg, str } from "@lit/localize";
|
import { localized, msg, str } from "@lit/localize";
|
||||||
import { html, nothing } from "lit";
|
import { html, nothing, type TemplateResult } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators.js";
|
import { customElement, property, query, state } from "lit/decorators.js";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
import { when } from "lit/directives/when.js";
|
import { when } from "lit/directives/when.js";
|
||||||
import { capitalize } from "lodash/fp";
|
import { capitalize } from "lodash/fp";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
import type { Profile } from "./types";
|
import type { Profile, ProfileWorkflow } from "./types";
|
||||||
|
|
||||||
import { TailwindElement } from "@/classes/TailwindElement";
|
import { TailwindElement } from "@/classes/TailwindElement";
|
||||||
import type { Dialog } from "@/components/ui/dialog";
|
import type { Dialog } from "@/components/ui/dialog";
|
||||||
@ -339,17 +339,16 @@ export class BrowserProfilesDetail extends TailwindElement {
|
|||||||
if (this.profile?.crawlconfigs?.length) {
|
if (this.profile?.crawlconfigs?.length) {
|
||||||
return html`<ul>
|
return html`<ul>
|
||||||
${this.profile.crawlconfigs.map(
|
${this.profile.crawlconfigs.map(
|
||||||
({ id, name }) => html`
|
(workflow) => html`
|
||||||
<li
|
<li
|
||||||
class="border-x border-b first:rounded-t first:border-t last:rounded-b"
|
class="border-x border-b first:rounded-t first:border-t last:rounded-b"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="block p-2 transition-colors focus-within:bg-neutral-50 hover:bg-neutral-50"
|
class="block p-2 transition-colors focus-within:bg-neutral-50 hover:bg-neutral-50"
|
||||||
href=${`${this.navigate.orgBasePath}/workflows/crawl/${id}`}
|
href=${`${this.navigate.orgBasePath}/workflows/crawl/${workflow.id}`}
|
||||||
@click=${this.navigate.link}
|
@click=${this.navigate.link}
|
||||||
>
|
>
|
||||||
${name ||
|
${this.renderWorkflowName(workflow)}
|
||||||
html`<span class="text-neutral-400">${msg("(no name)")}</span>`}
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
`,
|
`,
|
||||||
@ -362,6 +361,31 @@ export class BrowserProfilesDetail extends TailwindElement {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderWorkflowName(workflow: ProfileWorkflow) {
|
||||||
|
if (workflow.name)
|
||||||
|
return html`<span class="truncate">${workflow.name}</span>`;
|
||||||
|
if (!workflow.firstSeed)
|
||||||
|
return html`<span class="truncate font-mono">${workflow.id}</span>
|
||||||
|
<span class="text-neutral-400">${msg("(no name)")}</span>`;
|
||||||
|
const remainder = workflow.seedCount - 1;
|
||||||
|
let nameSuffix: string | TemplateResult<1> = "";
|
||||||
|
if (remainder) {
|
||||||
|
if (remainder === 1) {
|
||||||
|
nameSuffix = html`<span class="ml-2 text-neutral-500"
|
||||||
|
>${msg(str`+${remainder} URL`)}</span
|
||||||
|
>`;
|
||||||
|
} else {
|
||||||
|
nameSuffix = html`<span class="ml-2 text-neutral-500"
|
||||||
|
>${msg(str`+${remainder} URLs`)}</span
|
||||||
|
>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
<span class="primaryUrl truncate">${workflow.firstSeed}</span
|
||||||
|
>${nameSuffix}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly renderVisitedSites = () => {
|
private readonly renderVisitedSites = () => {
|
||||||
return html`
|
return html`
|
||||||
<section class="flex-grow-1 flex flex-col lg:w-[60ch]">
|
<section class="flex-grow-1 flex flex-col lg:w-[60ch]">
|
||||||
|
@ -93,6 +93,13 @@ export type ProfileReplica = {
|
|||||||
custom?: boolean;
|
custom?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ProfileWorkflow = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
firstSeed: string;
|
||||||
|
seedCount: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type Profile = {
|
export type Profile = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@ -105,7 +112,7 @@ export type Profile = {
|
|||||||
profileId: string;
|
profileId: string;
|
||||||
baseProfileName: string;
|
baseProfileName: string;
|
||||||
oid: string;
|
oid: string;
|
||||||
crawlconfigs?: { id: string; name: string }[];
|
crawlconfigs?: ProfileWorkflow[];
|
||||||
resource?: {
|
resource?: {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user