feat: show the worker version

This commit is contained in:
jialin
2026-03-31 15:05:38 +08:00
committed by jialin
parent 0b292829fa
commit 06160546a6
17 changed files with 221 additions and 106 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
import { createFromIconfontCN } from '@ant-design/icons';
import './iconfont/iconfont.js';
// import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4613488_7zu9s75km1r.js'
scriptUrl: '//at.alicdn.com/t/c/font_4613488_110n9b7vcjv.js'
});
export default IconFont;
+1 -1
View File
@@ -88,7 +88,7 @@ export const modalConfig = {
icon: null,
centered: false,
mask: {
closeable: true
closable: true
},
footer: null,
style: {
+3 -1
View File
@@ -107,5 +107,7 @@ export default {
'When enter the maintenance mode, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
'resources.worker.noCluster.tips':
'No available clusters. Please create a cluster before adding a node.',
'resources.metrics.details': 'Monitoring'
'resources.metrics.details': 'Monitoring',
'resoureces.worker.upgrade.tips':
'Please upgrade to match the GPUStack Server version.'
};
+4 -1
View File
@@ -108,7 +108,9 @@ export default {
'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
'resources.worker.noCluster.tips':
'No available clusters. Please create a cluster before adding a node.',
'resources.metrics.details': 'Monitoring'
'resources.metrics.details': 'Monitoring',
'resoureces.worker.upgrade.tips':
'Please upgrade to match the GPUStack Server version.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -136,4 +138,5 @@ export default {
// 22. 'resources.worker.maintenance.remark.rules': 'Please enter maintenance remarks',
// 23. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
// 24. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.'
// 25. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.'
// ========== End of To-Do List ==========
+5 -2
View File
@@ -106,7 +106,9 @@ export default {
'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
'resources.worker.noCluster.tips':
'No available clusters. Please create a cluster before adding a node.',
'resources.metrics.details': 'Monitoring'
'resources.metrics.details': 'Monitoring',
'resoureces.worker.upgrade.tips':
'Please upgrade to match the GPUStack Server version.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -117,5 +119,6 @@ export default {
// 6. 'resources.worker.maintenance.remark.rules': 'Please enter maintenance remarks',
// 7. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
// 8. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.',
// 9. 'resources.metrics.details': 'Monitoring'
// 9. 'resources.metrics.details': 'Monitoring',
// 10. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.'
// ========== End of To-Do List ==========
+7 -2
View File
@@ -23,7 +23,7 @@ export default {
'menu.apikeys': 'API Anahtarları',
'menu.users': 'Kullanıcılar',
'menu.resources.workers': 'İşçi Düğümler',
'menu.resources.gpus': 'GPU\'lar',
'menu.resources.gpus': "GPU'lar",
'menu.resources.modelfiles': 'Model Dosyaları',
'menu.accessControl': 'Erişim Kontrolü',
'menu.accessControl.apikeys': 'API Anahtarları',
@@ -37,5 +37,10 @@ export default {
'menu.clusterManagement.credentials': 'Bulut Kimlik Bilgileri',
'menu.clusterManagement.clusterDetail': 'Küme Detayı',
'menu.clusterManagement.clusterCreate': 'Küme Oluştur',
'menu.resources.backendsList': 'Çıkarım Altyapıları'
'menu.resources.backendsList': 'Çıkarım Altyapıları',
'menu.models.instances': 'Instances'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'menu.models.instances': 'Instances'
// ========== End of To-Do List ==========
+29 -22
View File
@@ -24,7 +24,7 @@ export default {
'model.deploy.sort': 'Sırala',
'model.deploy.search.placeholder': 'Modelleri aramak için <kbd>/</kbd> yazın',
'model.form.ollamatips':
'İpucu: Aşağıdakiler GPUStack\'te önceden yapılandırılmış Ollama modelleridir. İstediğiniz modeli seçin veya dağıtmak istediğiniz modeli doğrudan sağdaki 【{name}】 giriş kutusuna yazın.',
"İpucu: Aşağıdakiler GPUStack'te önceden yapılandırılmış Ollama modelleridir. İstediğiniz modeli seçin veya dağıtmak istediğiniz modeli doğrudan sağdaki 【{name}】 giriş kutusuna yazın.",
'models.sort.name': 'Ad',
'models.sort.size': 'Boyut',
'models.sort.likes': 'Beğeniler',
@@ -34,8 +34,8 @@ export default {
'models.search.result': '{count} sonuç',
'models.data.card': 'Model Kartı',
'models.available.files': 'Mevcut Dosyalar',
'models.viewin.hf': 'Hugging Face\'de Görüntüle',
'models.viewin.modelscope': 'ModelScope\'da Görüntüle',
'models.viewin.hf': "Hugging Face'de Görüntüle",
'models.viewin.modelscope': "ModelScope'da Görüntüle",
'models.architecture': 'Mimari',
'models.search.noresult': 'İlgili model bulunamadı',
'models.search.nofiles': 'Mevcut dosya yok',
@@ -50,9 +50,9 @@ export default {
'models.form.scheduletype.gpu': 'GPU Belirle',
'models.form.scheduletype.gpuType': 'GPU Türü Belirle',
'models.form.scheduletype.auto.tips':
'Mevcut kaynak koşullarına göre model örneklerini uygun GPU\'lara otomatik olarak dağıtır.',
"Mevcut kaynak koşullarına göre model örneklerini uygun GPU'lara otomatik olarak dağıtır.",
'models.form.scheduletype.manual.tips':
'Model örneklerinin dağıtılacağı GPU\'ları manuel olarak belirlemenize olanak tanır.',
"Model örneklerinin dağıtılacağı GPU'ları manuel olarak belirlemenize olanak tanır.",
'models.form.manual.schedule': 'Manuel Zamanlama',
'models.table.gpuindex': 'GPU İndeksi',
'models.table.backend': 'Altyapılar',
@@ -91,12 +91,13 @@ export default {
'GGUF format modeller için, Linux, macOS ve Windows destekler.',
'models.form.backend.vllm':
'NVIDIA, AMD, Ascend, Hygon, Moore Threads, Iluvatar, MetaX, T-Head PPU cihazları için yerleşik destek.',
'models.form.backend.voxbox': 'Yalnızca NVIDIA GPU\'ları ve CPU\'ları destekler.',
'models.form.backend.mindie': 'Yalnızca Ascend NPU\'ları destekler.',
'models.form.backend.voxbox':
"Yalnızca NVIDIA GPU'ları ve CPU'ları destekler.",
'models.form.backend.mindie': "Yalnızca Ascend NPU'ları destekler.",
'models.form.backend.sglang':
'NVIDIA, AMD, Ascend, Moore Threads, MetaX, T-Head PPU cihazları için yerleşik destek.',
'models.form.search.gguftips':
'İşçi düğüm olarak macOS veya Windows kullanılıyorsa GGUF\'u işaretleyin (ses modelleri için işareti kaldırın).',
"İşçi düğüm olarak macOS veya Windows kullanılıyorsa GGUF'u işaretleyin (ses modelleri için işareti kaldırın).",
'models.form.button.addlabel': 'Etiket Ekle',
'models.filter.category': 'Kategoriye göre filtrele',
'models.list.more.logs': 'Daha Fazla Göster',
@@ -141,16 +142,14 @@ export default {
'models.form.check.passed': 'Uyumluluk Kontrolü Başarılı',
'models.form.check.claims':
'Model yaklaşık {vram} VRAM ve {ram} RAM tüketecektir.',
'models.form.check.claims2':
'Model yaklaşık {vram} VRAM tüketecektir.',
'models.form.check.claims3':
'Model yaklaşık {ram} RAM tüketecektir.',
'models.form.check.claims2': 'Model yaklaşık {vram} VRAM tüketecektir.',
'models.form.check.claims3': 'Model yaklaşık {ram} RAM tüketecektir.',
'models.form.update.tips':
'Değişiklikler yalnızca örneği silip yeniden oluşturduğunuzda geçerli olur.',
'models.table.download.progress': 'İlerleme',
'models.table.button.apiAccessInfo': 'API Erişim Bilgisi',
'models.table.button.apiAccessInfo.tips': `Bu modeli üçüncü taraf uygulamalarla entegre etmek için şu bilgileri kullanın: erişim URL\'si, model adı ve API anahtarı. Bu kimlik bilgileri, model hizmetine düzgün bağlantı ve kullanım sağlamak için gereklidir.`,
'models.table.apiAccessInfo.endpoint': 'Erişim URL\'si',
'models.table.button.apiAccessInfo.tips': `Bu modeli üçüncü taraf uygulamalarla entegre etmek için şu bilgileri kullanın: erişim URL'si, model adı ve API anahtarı. Bu kimlik bilgileri, model hizmetine düzgün bağlantı ve kullanım sağlamak için gereklidir.`,
'models.table.apiAccessInfo.endpoint': "Erişim URL'si",
'models.table.apiAccessInfo.modelName': 'Model Adı',
'models.table.apiAccessInfo.apikey': 'API Anahtarı',
'models.table.apiAccessInfo.openaiCompatible': 'OpenAI Uyumlu',
@@ -196,7 +195,7 @@ export default {
'models.form.extendedkvcache': 'Genişletilmiş KV Önbelleğini Etkinleştir',
'models.form.chunkSize': 'Önbellek Parça Boyutu',
'models.form.maxCPUSize': 'Maksimum CPU Önbellek Boyutu (GiB)',
'models.form.remoteURL': 'Uzak Depolama URL\'si',
'models.form.remoteURL': "Uzak Depolama URL'si",
'models.form.remoteURL.tips':
'Ayrıntılar için <a href="https://docs.lmcache.ai/api_reference/configurations.html" target="_blank">yapılandırma dokümantasyonuna</a> bakın.',
'models.form.runCommandPlaceholder':
@@ -213,7 +212,7 @@ export default {
'models.form.gpusAllocationType.auto': 'Otomatik',
'models.form.gpusAllocationType.custom': 'Özel',
'models.form.gpusAllocationType.auto.tips':
'Sistem kopya başına GPU sayısını otomatik hesaplar, varsayılan olarak ikinin kuvvetlerini kullanır ve seçilen GPU\'larla sınırlandırılır.',
"Sistem kopya başına GPU sayısını otomatik hesaplar, varsayılan olarak ikinin kuvvetlerini kullanır ve seçilen GPU'larla sınırlandırılır.",
'models.form.gpusAllocationType.custom.tips':
'Kopya başına tam GPU sayısını belirleyebilirsiniz.',
'models.mymodels.status.inactive': 'Durduruldu',
@@ -227,7 +226,7 @@ export default {
'models.form.ramRatio': 'RAM-VRAM Oranı',
'models.form.ramSize': 'Maksimum RAM Boyutu (GiB)',
'models.form.ramRatio.tips':
'KV önbellek için kullanılan sistem RAM\'in GPU VRAM\'e oranı. Örneğin, 2.0 RAM\'deki önbelleğin GPU VRAM\'in iki katı olabileceği anlamına gelir.',
"KV önbellek için kullanılan sistem RAM'in GPU VRAM'e oranı. Örneğin, 2.0 RAM'deki önbelleğin GPU VRAM'in iki katı olabileceği anlamına gelir.",
'models.form.ramSize.tips': `Sistem belleğinde depolanan KV önbelleğin maksimum boyutu (GiB). Ayarlanırsa, bu değer "{content}" değerini geçersiz kılar.`,
'models.form.chunkSize.tips': 'KV önbellek parçası başına token sayısı.',
'models.form.mode': 'Mod',
@@ -245,9 +244,10 @@ export default {
'Düşük istek eşzamanlılığı altında düşük gecikme için optimize edilmiştir.',
'models.form.mode.baseline.tips':
'Tam (orijinal) hassasiyette çalışır ve uyumluluğu ön planda tutar.',
'models.form.draftModel.placeholder': 'Lütfen bir taslak model seçin veya girin',
'models.form.draftModel.placeholder':
'Lütfen bir taslak model seçin veya girin',
'models.form.draftModel.tips':
'Yerel yol (örn., /path/to/model) girebilir veya Hugging Face ya da ModelScope\'dan bir model seçebilirsiniz (örn., Tengyunw/qwen3_8b_eagle3). Sistem birincil model kaynağına göre otomatik eşleme yapar.',
"Yerel yol (örn., /path/to/model) girebilir veya Hugging Face ya da ModelScope'dan bir model seçebilirsiniz (örn., Tengyunw/qwen3_8b_eagle3). Sistem birincil model kaynağına göre otomatik eşleme yapar.",
'models.form.quantization': 'Niceleme',
'models.form.backend.custom': 'Kullanıcı tanımlı',
'models.form.rules.name':
@@ -255,7 +255,7 @@ export default {
'models.catalog.button.explore': 'Daha Fazla Model Keşfet',
'models.catalog.precision': 'Hassasiyet',
'models.form.gpuPerReplica.tips': 'Özel bir sayı girin',
'models.form.generic_proxy': 'Genel Proxy\'yi Etkinleştir',
'models.form.generic_proxy': "Genel Proxy'yi Etkinleştir",
'models.form.enableModelRoute': 'Model Yönlendirmesini Etkinleştir',
'models.form.enableModelRoute.tips': 'Model Yönlendirmesini Etkinleştir',
'models.form.generic_proxy.tips':
@@ -274,10 +274,17 @@ export default {
'models.form.backendVersions.tips': `Daha fazla sürüm kullanmak için {link} sayfasına gidin ve sürüm eklemek üzere altyapıyı düzenleyin.`,
'models.catalog.nogpus.tips':
'Seçili kümede bu model için uyumlu GPU bulunmuyor.',
'models.form.modelfile.notfound': `Belirttiğiniz model dosyası yolu GPUStack sunucusunda mevcut değil. Model dosyasını hem GPUStack sunucusunda hem de GPUStack işçi düğümlerinde aynı yola yerleştirmeniz önerilir. Bu, GPUStack\'in daha iyi kararlar almasına yardımcı olur.`,
'models.form.modelfile.notfound': `Belirttiğiniz model dosyası yolu GPUStack sunucusunda mevcut değil. Model dosyasını hem GPUStack sunucusunda hem de GPUStack işçi düğümlerinde aynı yola yerleştirmeniz önerilir. Bu, GPUStack'in daha iyi kararlar almasına yardımcı olur.`,
'models.form.readyWorkers': 'hazır işçi düğüm',
'models.form.maxContextLength': 'Maksimum Bağlam Uzunluğu',
'models.form.backend.helperText':
'Henüz etkinleştirilmedi. Dağıtımdan sonra etkinleştirilecektir. ',
'models.table.instance.benchmark': 'Kıyaslama Çalıştır'
'models.table.instance.benchmark': 'Kıyaslama Çalıştır',
'models.table.modelView': 'Model List',
'models.table.instanceView': 'Instance List'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'models.table.modelView': 'Model List',
// 2. 'models.table.instanceView': 'Instance List',
// ========== End of To-Do List ==========
+15 -3
View File
@@ -1,13 +1,15 @@
export default {
'noresult.button.add': 'Şimdi Ekle',
'noresult.mymodels.title': 'Erişilebilir Model Yok',
'noresult.mymodels.subTitle': 'Erişim için lütfen yöneticiyle iletişime geçin.',
'noresult.mymodels.subTitle':
'Erişim için lütfen yöneticiyle iletişime geçin.',
'noresult.mymodels.nofound': 'Eşleşen model bulunamadı',
'noresult.deployments.title': 'Dağıtılmış Model Yok',
'noresult.deployments.subTitle':
'Henüz hiç model dağıtmadınız. Başlamak için aşağıdaki düğmeye tıklayın.',
'noresult.gpus.title': 'GPU Cihazı Algılanamadı',
'noresult.gpus.subTitle': 'Lütfen İşçi Düğüm durumunun HAZIR olup olmadığını kontrol edin.',
'noresult.gpus.subTitle':
'Lütfen İşçi Düğüm durumunun HAZIR olup olmadığını kontrol edin.',
'noresult.gpus.nofound': 'Eşleşen GPU cihazı bulunamadı.',
'noresult.workers.title': 'İşçi Düğüm Yok',
'noresult.workers.subTitle': 'Hiçbir kümede işçi düğüm bulunamadı.',
@@ -48,5 +50,15 @@ export default {
'noresult.providers.nofound': 'Eşleşen sağlayıcı bulunamadı.',
'noresult.routes.title': 'Yönlendirme Yok',
'noresult.routes.subTitle': 'Henüz yönlendirme eklenmedi.',
'noresult.routes.nofound': 'Eşleşen yönlendirme bulunamadı.'
'noresult.routes.nofound': 'Eşleşen yönlendirme bulunamadı.',
'noresult.instances.title': 'No instances',
'noresult.instances.subTitle':
'There are no running model instances. Deploy a model to create one automatically.',
'noresult.instances.nofound': 'No matching instances found.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'noresult.instances.title': 'No instances',
// 2. 'noresult.instances.subTitle': 'There are no running model instances. Deploy a model to create one automatically.',
// 3. 'noresult.instances.nofound': 'No matching instances found.'
// ========== End of To-Do List ==========
+10 -5
View File
@@ -19,7 +19,7 @@ export default {
'resources.form.spread.tips':
'Tüm kümenin kaynaklarını tüm işçi düğümler arasında nispeten eşit dağıtır. Tek bir işçi düğümde daha fazla kaynak parçalanması oluşturabilir.',
'resources.form.binpack.tips':
'Küme kaynaklarının genel kullanımını önceliklendirerek GPU\'lar/İşçi Düğümlerdeki kaynak parçalanmasını azaltır.',
"Küme kaynaklarının genel kullanımını önceliklendirerek GPU'lar/İşçi Düğümlerdeki kaynak parçalanmasını azaltır.",
'resources.form.workerSelector.description':
'Sistem, önceden tanımlanmış etiketlere göre model örneklerini dağıtmak için en uygun İşçi Düğümü seçer.',
'resources.table.ip': 'IP',
@@ -56,7 +56,7 @@ export default {
'Komutu oluşturmak için bir etiket seçin ve kopyala düğmesiyle kopyalayın.',
'resources.worker.script.install': 'Betik Kurulumu',
'resources.worker.container.install': 'Konteyner Kurulumu (Yalnızca Linux)',
'resources.worker.cann.tips': `Gerekli NPU indeksine göre <span class="bold-text">--device /dev/davinci{index}</span> ayarlayın. Örneğin, NPU0 ve NPU1\'i bağlamak için <span class="bold-text">--device /dev/davinci0 --device /dev/davinci1</span> ekleyin.`,
'resources.worker.cann.tips': `Gerekli NPU indeksine göre <span class="bold-text">--device /dev/davinci{index}</span> ayarlayın. Örneğin, NPU0 ve NPU1'i bağlamak için <span class="bold-text">--device /dev/davinci0 --device /dev/davinci1</span> ekleyin.`,
'resources.modelfiles.form.path': 'Depolama Yolu',
'resources.modelfiles.modelfile': 'Model Dosyaları',
'resources.modelfiles.download': 'Model Dosyası Ekle',
@@ -101,11 +101,16 @@ export default {
'resources.worker.maintenance.enable': 'Bakım Moduna Gir',
'resources.worker.maintenance.disable': 'Bakım Modundan Çık',
'resources.worker.maintenance.remark': 'Not',
'resources.worker.maintenance.remark.rules':
'Lütfen bakım notlarını girin',
'resources.worker.maintenance.remark.rules': 'Lütfen bakım notlarını girin',
'resources.worker.maintenance.tips':
'Bakım moduna girildiğinde, düğüm yeni model dağıtım görevlerini zamanlamayı durduracaktır. Çalışan örnekler etkilenmez.',
'resources.worker.noCluster.tips':
'Kullanılabilir küme yok. Lütfen düğüm eklemeden önce bir küme oluşturun.',
'resources.metrics.details': 'İzleme'
'resources.metrics.details': 'İzleme',
'resoureces.worker.upgrade.tips':
'Please upgrade to match the GPUStack Server version.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.'
// ========== End of To-Do List ==========
+2 -1
View File
@@ -103,5 +103,6 @@ export default {
'resources.worker.maintenance.tips':
'进入维护模式后,节点将停止调度新的模型实例部署任务,正在运行的实例不会受到影响。',
'resources.worker.noCluster.tips': '当前无可用集群,请先创建集群再添加节点。',
'resources.metrics.details': '监控'
'resources.metrics.details': '监控',
'resoureces.worker.upgrade.tips': '请升级到与 GPUStack Server 版本一致。'
};
+5 -34
View File
@@ -4,38 +4,9 @@ import InfiniteScroller from '@/pages/_components/infinite-scroller';
import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
import { Spin } from 'antd';
import React from 'react';
import styled from 'styled-components';
import backendListCss from '../styles/backend-list.less';
import BackendCard from './backend-card';
const SpinWrapper = styled.div`
width: 100%;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
max-height: 400px;
right: 0;
.skelton-wrapper {
width: 100%;
}
`;
const SkeletonWrapper = styled.div`
.ant-skeleton-content {
.ant-skeleton-paragraph {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 0;
li {
margin-top: 0 !important;
}
}
}
`;
interface BackendListProps {
defaultSpan?: number;
resizable?: boolean;
@@ -54,7 +25,7 @@ const ListSkeleton: React.FC<{
return (
<div>
{loading && (
<SpinWrapper>
<div className={backendListCss.SpinWrapper}>
<Spin
spinning={loading}
size="middle"
@@ -66,7 +37,7 @@ const ListSkeleton: React.FC<{
}}
>
{isFirst && (
<SkeletonWrapper>
<div className={backendListCss.SkeletonWrapper}>
<CardSkeleton
skeletonProps={{
title: false
@@ -77,10 +48,10 @@ const ListSkeleton: React.FC<{
gap: 24
}}
></CardSkeleton>
</SkeletonWrapper>
</div>
)}
</Spin>
</SpinWrapper>
</div>
)}
</div>
);
@@ -0,0 +1,34 @@
.SpinWrapper {
width: 100%;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
max-height: 400px;
right: 0;
:global {
.skelton-wrapper {
width: 100%;
}
}
}
.SkeletonWrapper {
:global {
.ant-skeleton-content {
.ant-skeleton-paragraph {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 0;
li {
margin-top: 0 !important;
}
}
}
}
}
@@ -37,10 +37,10 @@ const WorkerInfoContent: React.FC<NameCellProps> = ({ record, modelData }) => {
<div className="flex-center">
<IconFont
type="icon-filled-gpu"
className="m-r-5 text-tertiary"
className="m-r-5 text-quaternary"
style={{ fontSize: 12 }}
/>
<span className="text-tertiary">
<span className="text-quaternary">
GPU:[
{_.join(
record.gpu_indexes?.sort?.((a, b) => a - b),
@@ -115,10 +115,10 @@ const useProviderColumns = (options: {
></NameCell>
<div className="flex-center">
<ThunderboltFilled
className="m-r-5 text-tertiary"
style={{ fontSize: 12 }}
className="m-r-5 text-quaternary"
style={{ fontSize: 12, position: 'relative', top: 2 }}
/>
<span className="text-tertiary">
<span className="text-quaternary">
{record?.backend || record?.backend || ''}
{record.backend_version || record?.backend_version
? `(${record.backend_version || record?.backend_version})`
@@ -279,6 +279,7 @@ const Workers = () => {
sortDirections={TABLE_SORT_DIRECTIONS}
showSorterTooltip={false}
tableLayout={'auto'}
className={'scroll-table'}
dataSource={dataSource.dataList}
loading={{
spinning: dataSource.loading,
+1
View File
@@ -69,6 +69,7 @@ export interface ListItem {
ssh_key_id: string;
advertise_address: string;
provision_progress: string;
worker_version: string;
maintenance: {
enabled: boolean;
message: string;
@@ -1,6 +1,8 @@
import { systemConfigAtom } from '@/atoms/system';
import { GPUStackVersionAtom } from '@/atoms/user';
import AutoTooltip from '@/components/auto-tooltip';
import DropdownButtons from '@/components/drop-down-buttons';
import IconFont from '@/components/icon-font';
import LabelsCell from '@/components/label-cell';
import ProgressBar from '@/components/progress-bar';
import InfoColumn from '@/components/simple-table/info-column';
@@ -17,31 +19,16 @@ import {
ToolOutlined
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Tooltip } from 'antd';
import { Tag, Tooltip } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { useAtomValue } from 'jotai';
import { useAtom, useAtomValue } from 'jotai';
import _ from 'lodash';
import { useMemo } from 'react';
import styled from 'styled-components';
import semverCoerce from 'semver/functions/coerce';
import semverGt from 'semver/functions/gt';
import { status, WorkerStatusMap, WorkerStatusMapValue } from '../config';
import { Filesystem, GPUDeviceItem, ListItem } from '../config/types';
const IPWrapper = styled.span`
display: flex;
flex-direction: column;
.item {
display: grid;
grid-template-columns: auto 1fr;
gap: 4px 8px;
.label {
text-align: right;
font-size: 13px;
display: flex;
align-items: center;
color: var(--ant-color-text-tertiary);
}
}
`;
import workerCss from '../styles/worker.less';
const ActionList = [
{ label: 'common.button.edit', key: 'edit', icon: <EditOutlined /> },
@@ -110,6 +97,16 @@ const fieldList = [
}
];
const showUpgrade = (
workerVersion: string,
currentVersion: string
): boolean => {
const w_ver = semverCoerce(workerVersion);
const c_ver = semverCoerce(currentVersion);
return !!w_ver && !!c_ver && semverGt(c_ver, w_ver);
};
const formateUtilization = (val1: number, val2: number): number =>
val1 && val2 ? _.round((val1 / val2) * 100, 0) : 0;
@@ -248,6 +245,9 @@ const useWorkerColumns = ({
}): ColumnsType<ListItem> => {
const intl = useIntl();
const systemConfig = useAtomValue(systemConfigAtom);
const [version] = useAtom(GPUStackVersionAtom);
console.log('version in useWorkerColumns', version);
const renderIP = (text: string, record: ListItem) => {
if (record.advertise_address === record.ip) {
@@ -260,14 +260,14 @@ const useWorkerColumns = ({
record.ip
) {
return (
<IPWrapper>
<span className={workerCss.ipWrapper}>
<span className="item">
<span>{record.ip}</span>
<span className="label">{`(${intl.formatMessage({ id: 'clusters.table.ip.internal' })})`}</span>
<span> {record.advertise_address}</span>
<span className="label">{`(${intl.formatMessage({ id: 'clusters.table.ip.external' })})`}</span>
</span>
</IPWrapper>
</span>
);
}
return record.ip || record.advertise_address || '';
@@ -297,12 +297,30 @@ const useWorkerColumns = ({
{
title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name',
width: 100,
width: 140,
sorter: tableSorter(1),
render: (text: string) => (
<AutoTooltip ghost maxWidth={200}>
{text}
</AutoTooltip>
render: (text: string, record: ListItem) => (
<div className={workerCss.name}>
<AutoTooltip ghost maxWidth={200}>
<span className="name-text">{text}</span>
</AutoTooltip>
<div className={workerCss['worker-version']}>
<AutoTooltip
ghost
showTitle={showUpgrade(record.worker_version, version.version)}
title={intl.formatMessage({
id: 'resoureces.worker.upgrade.tips'
})}
>
<Tag className="version-tag" variant="outlined">
{version.version}
{showUpgrade(record.worker_version, version.version) && (
<IconFont type="icon-upgrade"></IconFont>
)}
</Tag>
</AutoTooltip>
</div>
</div>
)
},
{
+52
View File
@@ -0,0 +1,52 @@
.name {
display: flex;
flex-direction: column;
gap: 4px;
.worker-version {
color: var(--ant-color-text-tertiary);
display: flex;
align-items: center;
font-size: 12px;
gap: 4px;
:global(.anticon) {
color: var(--ant-color-warning);
font-size: 14px;
}
:global {
.version-tag {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
height: auto;
border-radius: 4px;
line-height: unset;
background-color: unset;
color: var(--ant-color-text-quaternary);
border: 1px solid var(--ant-color-split);
}
}
}
}
.ipWrapper {
display: flex;
flex-direction: column;
.item {
display: grid;
grid-template-columns: auto 1fr;
gap: 4px 8px;
.label {
text-align: right;
font-size: 13px;
display: flex;
align-items: center;
color: var(--ant-color-text-tertiary);
}
}
}