mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
refactor: remove unused javascript-time-ago types and enhance node sorting logic
This commit is contained in:
@@ -75,7 +75,6 @@
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@types/getos": "^3.0.4",
|
||||
"@types/humanize-duration": "^3.27.4",
|
||||
"@types/javascript-time-ago": "^2.0.8",
|
||||
"@types/lodash": "^4.17.6",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/md5": "^2.3.5",
|
||||
|
||||
11
frontend/crawlab-ui/pnpm-lock.yaml
generated
11
frontend/crawlab-ui/pnpm-lock.yaml
generated
@@ -50,9 +50,6 @@ importers:
|
||||
'@types/humanize-duration':
|
||||
specifier: ^3.27.4
|
||||
version: 3.27.4
|
||||
'@types/javascript-time-ago':
|
||||
specifier: ^2.0.8
|
||||
version: 2.5.0
|
||||
'@types/lodash':
|
||||
specifier: ^4.17.6
|
||||
version: 4.17.16
|
||||
@@ -1205,10 +1202,6 @@ packages:
|
||||
'@types/istanbul-reports@3.0.4':
|
||||
resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
|
||||
|
||||
'@types/javascript-time-ago@2.5.0':
|
||||
resolution: {integrity: sha512-c0GQ02qkkZx138VphjPqU4+PkVSNkWvQcpE3Yy03S6NpWlT9XTSXPUbJ1qv4KV0/eW7wSEAoU87e2YHz7ndHrA==}
|
||||
deprecated: This is a stub types definition. javascript-time-ago provides its own type definitions, so you do not need this installed.
|
||||
|
||||
'@types/jest@29.5.14':
|
||||
resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==}
|
||||
|
||||
@@ -4632,10 +4625,6 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/istanbul-lib-report': 3.0.3
|
||||
|
||||
'@types/javascript-time-ago@2.5.0':
|
||||
dependencies:
|
||||
javascript-time-ago: 2.5.11
|
||||
|
||||
'@types/jest@29.5.14':
|
||||
dependencies:
|
||||
expect: 29.7.0
|
||||
|
||||
@@ -17,19 +17,22 @@ const useNode = (store: Store<RootStoreState>) => {
|
||||
// form rules
|
||||
const formRules: FormRules = {};
|
||||
|
||||
const allNodesSorted = computed(() => {
|
||||
return state.allNodes.sort((a, b) => {
|
||||
if (a.is_master) return -1;
|
||||
if (b.is_master) return 1;
|
||||
return a.name!.localeCompare(b.name!);
|
||||
});
|
||||
});
|
||||
|
||||
const activeNodesSorted = computed(() => {
|
||||
return state.allNodes
|
||||
.filter(n => n.active)
|
||||
.sort((a, b) => {
|
||||
if (a.is_master) return -1;
|
||||
if (b.is_master) return 1;
|
||||
return a.name!.localeCompare(b.name!);
|
||||
});
|
||||
return allNodesSorted.value.filter(node => node.active);
|
||||
});
|
||||
|
||||
return {
|
||||
...useForm<Node>(ns, store, useNodeService(store), formComponentData),
|
||||
formRules,
|
||||
allNodesSorted,
|
||||
activeNodesSorted,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useStore } from 'vuex';
|
||||
import { useSpider, useProject, useNode } from '@/components';
|
||||
import { TASK_MODE_RANDOM, TASK_MODE_SELECTED_NODES } from '@/constants/task';
|
||||
import pinyin, { STYLE_NORMAL } from 'pinyin';
|
||||
import { isZeroObjectId } from '@/utils/mongo';
|
||||
import { EMPTY_OBJECT_ID, isZeroObjectId } from '@/utils/mongo';
|
||||
import { useSpiderDetail } from '@/views';
|
||||
import { getToRunNodes, priorityOptions, translate } from '@/utils';
|
||||
import { getSpiderTemplateGroups, getSpiderTemplates } from '@/utils/spider';
|
||||
@@ -20,11 +20,11 @@ const { get } = useRequest();
|
||||
const store = useStore();
|
||||
|
||||
// use node
|
||||
const { activeNodesSorted: activeNodes } = useNode(store);
|
||||
const { allNodesSorted: allNodes } = useNode(store);
|
||||
|
||||
const toRunNodes = computed(() => {
|
||||
const { mode, node_ids } = form.value;
|
||||
return getToRunNodes(mode, node_ids, activeNodes.value);
|
||||
return getToRunNodes(mode, node_ids, allNodes.value);
|
||||
});
|
||||
|
||||
// use spider
|
||||
@@ -177,7 +177,15 @@ defineOptions({ name: 'ClSpiderForm' });
|
||||
:label="t('components.spider.form.project')"
|
||||
prop="project_id"
|
||||
>
|
||||
<cl-remote-select v-model="form.project_id" endpoint="/projects" />
|
||||
<cl-remote-select
|
||||
v-model="form.project_id"
|
||||
endpoint="/projects"
|
||||
filterable
|
||||
:empty-option="{
|
||||
label: t('common.status.unassigned'),
|
||||
value: EMPTY_OBJECT_ID,
|
||||
}"
|
||||
/>
|
||||
</cl-form-item>
|
||||
<!-- ./Row -->
|
||||
|
||||
@@ -246,7 +254,7 @@ defineOptions({ name: 'ClSpiderForm' });
|
||||
:placeholder="t('components.spider.form.selectedNodes')"
|
||||
>
|
||||
<el-option
|
||||
v-for="n in activeNodes"
|
||||
v-for="n in allNodes"
|
||||
:key="n.key"
|
||||
:value="n._id"
|
||||
:label="n.name"
|
||||
@@ -254,7 +262,14 @@ defineOptions({ name: 'ClSpiderForm' });
|
||||
<span style="margin-right: 5px">
|
||||
<cl-node-tag :node="n" icon-only />
|
||||
</span>
|
||||
<span>{{ n.name }}</span>
|
||||
<span>
|
||||
{{
|
||||
n.name +
|
||||
(n.active
|
||||
? ''
|
||||
: ` (${t('components.node.nodeStatus.label.offline')})`)
|
||||
}}
|
||||
</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</cl-form-item>
|
||||
|
||||
@@ -8,11 +8,13 @@ const props = withDefaults(
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
filterable?: boolean;
|
||||
clearable?: boolean;
|
||||
remoteShowSuffix?: boolean;
|
||||
endpoint: string;
|
||||
labelKey?: string;
|
||||
valueKey?: string;
|
||||
limit?: number;
|
||||
emptyOption?: SelectOption;
|
||||
}>(),
|
||||
{
|
||||
remoteShowSuffix: true,
|
||||
@@ -62,12 +64,21 @@ const remoteMethod = async (query?: string) => {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
const selectOptions = computed<SelectOption[]>(() =>
|
||||
list.value.map(row => ({
|
||||
label: row[props.labelKey],
|
||||
value: row[props.valueKey],
|
||||
}))
|
||||
);
|
||||
const selectOptions = computed<SelectOption[]>(() => {
|
||||
const { emptyOption, labelKey, valueKey } = props;
|
||||
const options: SelectOption[] = list.value.map(row => ({
|
||||
label: row[labelKey],
|
||||
value: row[valueKey],
|
||||
}));
|
||||
if (emptyOption) {
|
||||
const { label, value } = emptyOption;
|
||||
options.unshift({
|
||||
label,
|
||||
value,
|
||||
});
|
||||
}
|
||||
return options;
|
||||
});
|
||||
onBeforeMount(remoteMethod);
|
||||
|
||||
defineOptions({ name: 'ClRemoteSelect' });
|
||||
@@ -79,6 +90,7 @@ defineOptions({ name: 'ClRemoteSelect' });
|
||||
:placeholder="placeholder"
|
||||
:filterable="filterable"
|
||||
:disabled="disabled"
|
||||
:clearable="clearable"
|
||||
remote
|
||||
:remote-method="remoteMethod"
|
||||
:remote-show-suffix="remoteShowSuffix"
|
||||
|
||||
@@ -10,6 +10,7 @@ const props = withDefaults(
|
||||
showBackButton?: boolean;
|
||||
showSaveButton?: boolean;
|
||||
allListSelectOptions?: SelectOption[];
|
||||
navItemLabelFn?: (item: NavItem) => string;
|
||||
}>(),
|
||||
{
|
||||
navItemNameKey: 'name',
|
||||
@@ -77,7 +78,7 @@ defineOptions({ name: 'ClDetailLayout' });
|
||||
<el-option
|
||||
v-for="item in navItems"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:label="navItemLabelFn ? navItemLabelFn(item) : item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
@@ -41,6 +41,7 @@ const useDetail = <T extends BaseModel>(ns: ListStoreNamespace) => {
|
||||
items.unshift({
|
||||
id: activeId.value,
|
||||
label: form.name || activeId.value,
|
||||
data: form,
|
||||
});
|
||||
}
|
||||
return items;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import dayjs from 'dayjs';
|
||||
import TimeAgo, { LocaleData } from 'javascript-time-ago';
|
||||
import TimeAgo, { LocaleData, FormatStyleName } from 'javascript-time-ago';
|
||||
import { getI18n } from '@/i18n';
|
||||
import en from 'javascript-time-ago/locale/en';
|
||||
import zh from 'javascript-time-ago/locale/zh';
|
||||
import { FormatStyle } from 'javascript-time-ago/style';
|
||||
|
||||
TimeAgo.addLocale(en as LocaleData);
|
||||
TimeAgo.addLocale(zh as LocaleData);
|
||||
@@ -18,7 +17,7 @@ export const getTimeUnitParts = (timeUnit: string) => {
|
||||
|
||||
export const formatTimeAgo = (
|
||||
value: string | Date,
|
||||
formatStyle?: string | FormatStyle
|
||||
formatStyle?: string | FormatStyleName
|
||||
) => {
|
||||
const time = dayjs(value);
|
||||
const timeAgo = new TimeAgo(
|
||||
|
||||
@@ -2,13 +2,20 @@
|
||||
import { useStore } from 'vuex';
|
||||
import { useTaskDetail } from '@/views';
|
||||
import { useTask } from '@/components';
|
||||
import { isPro } from '@/utils';
|
||||
import { formatTimeAgo, isPro } from '@/utils';
|
||||
|
||||
const { activeTabName } = useTaskDetail();
|
||||
|
||||
const store = useStore();
|
||||
const { allListSelectOptions } = useTask(store);
|
||||
|
||||
const navItemLabelFn = (item: NavItem<Task>) => {
|
||||
if (!item.data) return item.label;
|
||||
const spiderName = item.data.spider?.name;
|
||||
const createdAt = formatTimeAgo(item.data.created_at!, 'mini-minute-now');
|
||||
return `${spiderName} - ${createdAt}`;
|
||||
};
|
||||
|
||||
defineOptions({ name: 'ClTaskDetail' });
|
||||
</script>
|
||||
|
||||
@@ -16,6 +23,7 @@ defineOptions({ name: 'ClTaskDetail' });
|
||||
<cl-detail-layout
|
||||
store-namespace="task"
|
||||
:all-list-select-options="allListSelectOptions"
|
||||
:nav-item-label-fn="navItemLabelFn"
|
||||
>
|
||||
<template #actions>
|
||||
<cl-task-detail-actions-common />
|
||||
@@ -26,5 +34,3 @@ defineOptions({ name: 'ClTaskDetail' });
|
||||
</template>
|
||||
</cl-detail-layout>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user