更新计划时间格式,修复站点应用列表不显示
This commit is contained in:
parent
d108cae215
commit
63e0ba48e6
@ -82,7 +82,7 @@ export default {
|
|||||||
let days = [];
|
let days = [];
|
||||||
for (let i = 0; i < 7; i++) {
|
for (let i = 0; i < 7; i++) {
|
||||||
days.push({
|
days.push({
|
||||||
label: dayjs().add(i, 'day').format('dddd, MMMM D'),
|
label: dayjs().add(i, 'day').format('YYYY-MM-DD'),
|
||||||
value: dayjs().add(i, 'day').format('YYYY-MM-DD')
|
value: dayjs().add(i, 'day').format('YYYY-MM-DD')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,7 @@ export default {
|
|||||||
return dayjsIST(this.scheduledTime).format('YYYY-MM-DDTHH:mm');
|
return dayjsIST(this.scheduledTime).format('YYYY-MM-DDTHH:mm');
|
||||||
},
|
},
|
||||||
scheduledTimeInLocal() {
|
scheduledTimeInLocal() {
|
||||||
return dayjs(this.scheduledTime).format('lll');
|
return dayjs(this.scheduledTime).format('YYYY-MM-DD HH:mm');
|
||||||
},
|
},
|
||||||
listOptions() {
|
listOptions() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,110 +0,0 @@
|
|||||||
import { computed, reactive } from 'vue';
|
|
||||||
import { createResource } from 'jingrow-ui';
|
|
||||||
import { clear } from 'idb-keyval';
|
|
||||||
import router from '../router';
|
|
||||||
|
|
||||||
export let session = reactive({
|
|
||||||
login: createResource({
|
|
||||||
url: 'login',
|
|
||||||
makeParams({ email, password }) {
|
|
||||||
return {
|
|
||||||
usr: email,
|
|
||||||
pwd: password
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
logout: createResource({
|
|
||||||
url: 'logout',
|
|
||||||
async onSuccess() {
|
|
||||||
session.user = getSessionUser();
|
|
||||||
await router.replace({ name: 'Login' });
|
|
||||||
localStorage.removeItem('current_team');
|
|
||||||
// On logout, reset posthog user identity and device id
|
|
||||||
if (window.posthog?.__loaded) {
|
|
||||||
posthog.reset(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear all cache from the session
|
|
||||||
clear();
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
logoutWithoutReload: createResource({
|
|
||||||
url: 'logout',
|
|
||||||
async onSuccess() {
|
|
||||||
session.user = getSessionUser();
|
|
||||||
localStorage.removeItem('current_team');
|
|
||||||
// On logout, reset posthog user identity and device id
|
|
||||||
if (window.posthog?.__loaded) {
|
|
||||||
posthog.reset(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
roles: createResource({
|
|
||||||
url: 'jcloud.api.account.get_permission_roles',
|
|
||||||
cache: ['roles', localStorage.getItem('current_team')],
|
|
||||||
initialData: []
|
|
||||||
}),
|
|
||||||
isTeamAdmin: computed(
|
|
||||||
() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.admin_access)
|
|
||||||
: false // if no roles, assume not admin and has member access
|
|
||||||
),
|
|
||||||
hasBillingAccess: computed(() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.allow_billing)
|
|
||||||
: true
|
|
||||||
),
|
|
||||||
hasWebhookConfigurationAccess: computed(() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.allow_webhook_configuration)
|
|
||||||
: true
|
|
||||||
),
|
|
||||||
hasAppsAccess: computed(() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.allow_apps)
|
|
||||||
: true
|
|
||||||
),
|
|
||||||
hasPartnerAccess: computed(() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.allow_partner)
|
|
||||||
: true
|
|
||||||
),
|
|
||||||
hasSiteCreationAccess: computed(() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.allow_site_creation)
|
|
||||||
: true
|
|
||||||
),
|
|
||||||
hasBenchCreationAccess: computed(() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.allow_bench_creation)
|
|
||||||
: true
|
|
||||||
),
|
|
||||||
hasServerCreationAccess: computed(() =>
|
|
||||||
session.roles.data.length
|
|
||||||
? session.roles.data.some(role => role.allow_server_creation)
|
|
||||||
: true
|
|
||||||
),
|
|
||||||
user: getSessionUser(),
|
|
||||||
isLoggedIn: computed(() => !!session.user),
|
|
||||||
isSystemUser: getSessionCookies().get('system_user') === 'yes'
|
|
||||||
});
|
|
||||||
|
|
||||||
export default session;
|
|
||||||
|
|
||||||
export function getSessionUser() {
|
|
||||||
let cookies = getSessionCookies();
|
|
||||||
let sessionUser = cookies.get('user_id');
|
|
||||||
if (!sessionUser || sessionUser === 'Guest') {
|
|
||||||
sessionUser = null;
|
|
||||||
}
|
|
||||||
return sessionUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSessionCookies() {
|
|
||||||
return new URLSearchParams(document.cookie.split('; ').join('&'));
|
|
||||||
}
|
|
||||||
@ -1,256 +0,0 @@
|
|||||||
import { defineAsyncComponent, h } from 'vue';
|
|
||||||
import { toast } from 'vue-sonner';
|
|
||||||
import { getTeam } from '../../data/team';
|
|
||||||
import router from '../../router';
|
|
||||||
import { confirmDialog, icon, renderDialog } from '../../utils/components';
|
|
||||||
import { planTitle } from '../../utils/format';
|
|
||||||
import type {
|
|
||||||
ColumnField,
|
|
||||||
DialogConfig,
|
|
||||||
FilterField,
|
|
||||||
Tab,
|
|
||||||
TabList
|
|
||||||
} from './types';
|
|
||||||
import { getUpsellBanner } from '.';
|
|
||||||
import { isMobile } from '../../utils/device';
|
|
||||||
import { getToastErrorMessage } from '../../utils/toast';
|
|
||||||
|
|
||||||
export function getAppsTab(forSite: boolean) {
|
|
||||||
return {
|
|
||||||
label: '应用',
|
|
||||||
icon: icon('grid'),
|
|
||||||
route: 'apps',
|
|
||||||
type: 'list',
|
|
||||||
condition: docResource => forSite && docResource.pg?.status !== 'Archived',
|
|
||||||
list: getAppsTabList(forSite)
|
|
||||||
} satisfies Tab as Tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAppsTabList(forSite: boolean) {
|
|
||||||
const options = forSite ? siteAppListOptions : benchAppListOptions;
|
|
||||||
const list: TabList = {
|
|
||||||
pagetype: '',
|
|
||||||
filters: () => ({}),
|
|
||||||
...options,
|
|
||||||
columns: getAppsTabColumns(forSite),
|
|
||||||
searchField: !forSite ? 'title' : undefined,
|
|
||||||
filterControls: r => {
|
|
||||||
if (forSite) return [];
|
|
||||||
else
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
label: '分支',
|
|
||||||
class: !isMobile() ? 'w-24' : '',
|
|
||||||
fieldname: 'branch',
|
|
||||||
options: [
|
|
||||||
'',
|
|
||||||
...new Set(r.listResource.data?.map(i => String(i.branch)) || [])
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
label: '所有者',
|
|
||||||
class: !isMobile() ? 'w-24' : '',
|
|
||||||
fieldname: 'repository_owner',
|
|
||||||
options: [
|
|
||||||
'',
|
|
||||||
...new Set(
|
|
||||||
r.listResource.data?.map(
|
|
||||||
i => String(i.repository_url).split('/').at(-2) || ''
|
|
||||||
) || []
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
] satisfies FilterField[];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAppsTabColumns(forSite: boolean) {
|
|
||||||
const appTabColumns: ColumnField[] = [
|
|
||||||
{
|
|
||||||
label: '应用',
|
|
||||||
fieldname: 'title',
|
|
||||||
width: 1,
|
|
||||||
suffix(row) {
|
|
||||||
if (!row.is_app_patched) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h(
|
|
||||||
'div',
|
|
||||||
{
|
|
||||||
title: '应用已打补丁',
|
|
||||||
class: 'rounded-full bg-gray-100 p-1'
|
|
||||||
},
|
|
||||||
h(icon('hash', 'w-3 h-3'))
|
|
||||||
);
|
|
||||||
},
|
|
||||||
format: (value, row) => value || row.app_title
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '计划',
|
|
||||||
width: 0.75,
|
|
||||||
class: 'text-gray-600 text-sm',
|
|
||||||
format(_, row) {
|
|
||||||
const planText = planTitle(row.plan_info);
|
|
||||||
if (planText) return `${planText}/月`;
|
|
||||||
else return '免费';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '仓库',
|
|
||||||
fieldname: 'repository_url',
|
|
||||||
format: value => String(value).split('/').slice(-2).join('/'),
|
|
||||||
link: value => String(value)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '分支',
|
|
||||||
fieldname: 'branch',
|
|
||||||
type: 'Badge',
|
|
||||||
width: 1,
|
|
||||||
link: (value, row) => {
|
|
||||||
return `${row.repository_url}/tree/${value}`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '提交',
|
|
||||||
fieldname: 'hash',
|
|
||||||
type: 'Badge',
|
|
||||||
width: 1,
|
|
||||||
link: (value, row) => {
|
|
||||||
return `${row.repository_url}/commit/${value}`;
|
|
||||||
},
|
|
||||||
format(value) {
|
|
||||||
return String(value).slice(0, 7);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '提交信息',
|
|
||||||
fieldname: 'commit_message',
|
|
||||||
width: '30rem'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
if (forSite) return appTabColumns;
|
|
||||||
return appTabColumns.filter(c => c.label !== '计划');
|
|
||||||
}
|
|
||||||
|
|
||||||
const siteAppListOptions: Partial<TabList> = {
|
|
||||||
pagetype: '站点应用',
|
|
||||||
filters: res => {
|
|
||||||
return { parenttype: 'Site', parent: res.pg?.name };
|
|
||||||
},
|
|
||||||
primaryAction({ listResource: apps, documentResource: site }) {
|
|
||||||
return {
|
|
||||||
label: '安装应用',
|
|
||||||
slots: {
|
|
||||||
prefix: icon('plus')
|
|
||||||
},
|
|
||||||
onClick() {
|
|
||||||
const InstallAppDialog = defineAsyncComponent(
|
|
||||||
() => import('../../components/site/InstallAppDialog.vue')
|
|
||||||
);
|
|
||||||
|
|
||||||
renderDialog(
|
|
||||||
h(InstallAppDialog, {
|
|
||||||
site: site.name,
|
|
||||||
onInstalled() {
|
|
||||||
apps.reload();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
rowActions({ row, listResource: apps, documentResource: site }) {
|
|
||||||
let $team = getTeam();
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
label: '在 Desk 中查看',
|
|
||||||
condition: () => $team.pg?.is_desk_user,
|
|
||||||
onClick() {
|
|
||||||
window.open(`/app/app-source/${row.name}`, '_blank');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '更改计划',
|
|
||||||
condition: () => row.plan_info && row.plans.length > 1,
|
|
||||||
onClick() {
|
|
||||||
let SiteAppPlanChangeDialog = defineAsyncComponent(
|
|
||||||
() => import('../../components/site/SiteAppPlanSelectDialog.vue')
|
|
||||||
);
|
|
||||||
renderDialog(
|
|
||||||
h(SiteAppPlanChangeDialog, {
|
|
||||||
app: row,
|
|
||||||
currentPlan: row.plans.find(
|
|
||||||
(plan: Record<string, any>) => plan.name === row.plan_info.name
|
|
||||||
),
|
|
||||||
onPlanChanged() {
|
|
||||||
apps.reload();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '卸载',
|
|
||||||
condition: () => row.app !== 'jingrow',
|
|
||||||
onClick() {
|
|
||||||
const dialogConfig: DialogConfig = {
|
|
||||||
title: `卸载应用`,
|
|
||||||
message: `您确定要从站点 <b>${site.pg?.name}</b> 卸载应用 <b>${row.title}</b> 吗?<br>
|
|
||||||
所有与此应用相关的页面类型和模块将被移除。`,
|
|
||||||
onSuccess({ hide }) {
|
|
||||||
if (site.uninstallApp.loading) return;
|
|
||||||
toast.promise(
|
|
||||||
site.uninstallApp.submit({
|
|
||||||
app: row.app
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
loading: '正在安排应用卸载...',
|
|
||||||
success: (jobId: string) => {
|
|
||||||
hide();
|
|
||||||
router.push({
|
|
||||||
name: 'Site Job',
|
|
||||||
params: {
|
|
||||||
name: site.name,
|
|
||||||
id: jobId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return '应用卸载已安排';
|
|
||||||
},
|
|
||||||
error: (e: Error) => getToastErrorMessage(e)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
confirmDialog(dialogConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const benchAppListOptions: Partial<TabList> = {
|
|
||||||
pagetype: 'Bench App',
|
|
||||||
filters: res => {
|
|
||||||
return { parenttype: 'Bench', parent: res.pg?.name };
|
|
||||||
},
|
|
||||||
rowActions({ row }) {
|
|
||||||
let $team = getTeam();
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
label: '在 Desk 中查看',
|
|
||||||
condition: () => $team.pg?.is_desk_user,
|
|
||||||
onClick() {
|
|
||||||
window.open(`/app/app-release/${row.release}`, '_blank');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -153,6 +153,7 @@ export default {
|
|||||||
'Archived': '已归档',
|
'Archived': '已归档',
|
||||||
'Pending': '待处理',
|
'Pending': '待处理',
|
||||||
'Installing': '安装中',
|
'Installing': '安装中',
|
||||||
|
'Update Available': '可更新',
|
||||||
'Running': '运行中',
|
'Running': '运行中',
|
||||||
'Success': '成功',
|
'Success': '成功',
|
||||||
'Failure': '失败'
|
'Failure': '失败'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user