mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 08:00:53 +00:00
feat: unify pin actions (#13417)
This commit is contained in:
@@ -881,6 +881,26 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Container Compose
|
||||
// @Summary Pin compose
|
||||
// @Accept json
|
||||
// @Param request body dto.ComposePin true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/compose/pin [post]
|
||||
func (b *BaseApi) ComposePin(c *gin.Context) {
|
||||
var req dto.ComposePin
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := containerService.ComposePin(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Container Compose
|
||||
// @Summary Load compose environment variables
|
||||
// @Accept json
|
||||
|
||||
@@ -300,6 +300,7 @@ type ComposeInfo struct {
|
||||
ConfigFile string `json:"configFile"`
|
||||
Workdir string `json:"workdir"`
|
||||
ComposeFileExists bool `json:"composeFileExists"`
|
||||
IsPinned bool `json:"isPinned"`
|
||||
Path string `json:"path"`
|
||||
Containers []ComposeContainer `json:"containers"`
|
||||
Env string `json:"env"`
|
||||
@@ -337,6 +338,10 @@ type ComposeUpdate struct {
|
||||
Env string `json:"env"`
|
||||
ForcePull bool `json:"forcePull"`
|
||||
}
|
||||
type ComposePin struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
IsPinned bool `json:"isPinned"`
|
||||
}
|
||||
type ComposeLogClean struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
|
||||
@@ -11,6 +11,7 @@ type ComposeTemplate struct {
|
||||
type Compose struct {
|
||||
BaseModel
|
||||
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
IsPinned bool `json:"isPinned"`
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ type IContainerService interface {
|
||||
ComposeOperation(req dto.ComposeOperation) error
|
||||
TestCompose(req dto.ComposeCreate) (bool, error)
|
||||
ComposeUpdate(req dto.ComposeUpdate) error
|
||||
ComposePin(req dto.ComposePin) error
|
||||
ComposeLogClean(req dto.ComposeLogClean) error
|
||||
|
||||
ContainerCreate(req dto.ContainerOperate, inThread bool) error
|
||||
@@ -2025,6 +2026,9 @@ func loadComposeCount(client *client.Client) int {
|
||||
}
|
||||
}
|
||||
for _, compose := range composeCreatedByLocal {
|
||||
if len(compose.Path) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, has := composeMap[compose.Name]; !has {
|
||||
composeMap[compose.Name] = struct{}{}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,15 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
composeCreatedByLocal, _ := composeRepo.ListRecord()
|
||||
composeRecords, _ := composeRepo.ListRecord()
|
||||
pinnedByName := make(map[string]bool, len(composeRecords))
|
||||
composeCreatedByLocal := make([]model.Compose, 0, len(composeRecords))
|
||||
for _, record := range composeRecords {
|
||||
pinnedByName[record.Name] = record.IsPinned
|
||||
if len(record.Path) != 0 {
|
||||
composeCreatedByLocal = append(composeCreatedByLocal, record)
|
||||
}
|
||||
}
|
||||
composeLocalMap := make(map[string]dto.ComposeInfo)
|
||||
for _, localItem := range composeCreatedByLocal {
|
||||
composeItemLocal := dto.ComposeInfo{
|
||||
@@ -136,6 +144,7 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
|
||||
for key, value := range mergedMap {
|
||||
value.Name = key
|
||||
value.ComposeFileExists = composeFileExists(value.Workdir, value.ConfigFile)
|
||||
value.IsPinned = pinnedByName[key]
|
||||
records = append(records, value)
|
||||
}
|
||||
if len(req.Info) != 0 {
|
||||
@@ -150,6 +159,9 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
|
||||
}
|
||||
}
|
||||
sort.Slice(records, func(i, j int) bool {
|
||||
if records[i].IsPinned != records[j].IsPinned {
|
||||
return records[i].IsPinned
|
||||
}
|
||||
return records[i].CreatedAt > records[j].CreatedAt
|
||||
})
|
||||
total, start, end := len(records), (req.Page-1)*req.PageSize, req.Page*req.PageSize
|
||||
@@ -193,7 +205,7 @@ func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) {
|
||||
return false, buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
composeItem, _ := composeRepo.GetRecord(repo.WithByName(req.Name))
|
||||
if composeItem.ID != 0 {
|
||||
if composeItem.ID != 0 && len(composeItem.Path) != 0 {
|
||||
return false, buserr.New("ErrRecordExist")
|
||||
}
|
||||
if err := u.loadPath(&req); err != nil {
|
||||
@@ -235,7 +247,13 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) error {
|
||||
_, _ = compose.Down(req.Path)
|
||||
return err
|
||||
}
|
||||
_ = composeRepo.CreateRecord(&model.Compose{Name: strings.ToLower(req.Name), Path: req.Path})
|
||||
recordName := strings.ToLower(req.Name)
|
||||
record, _ := composeRepo.GetRecord(repo.WithByName(recordName))
|
||||
if record.ID == 0 {
|
||||
_ = composeRepo.CreateRecord(&model.Compose{Name: recordName, Path: req.Path})
|
||||
} else {
|
||||
_ = composeRepo.UpdateRecord(recordName, map[string]interface{}{"path": req.Path})
|
||||
}
|
||||
return nil
|
||||
}, nil)
|
||||
_ = taskItem.Execute()
|
||||
@@ -327,6 +345,20 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) ComposePin(req dto.ComposePin) error {
|
||||
record, _ := composeRepo.GetRecord(repo.WithByName(req.Name))
|
||||
if record.ID == 0 {
|
||||
if !req.IsPinned {
|
||||
return nil
|
||||
}
|
||||
return composeRepo.CreateRecord(&model.Compose{Name: req.Name, IsPinned: true})
|
||||
}
|
||||
if !req.IsPinned && len(record.Path) == 0 {
|
||||
return composeRepo.DeleteRecord(repo.WithByName(req.Name))
|
||||
}
|
||||
return composeRepo.UpdateRecord(req.Name, map[string]interface{}{"is_pinned": req.IsPinned})
|
||||
}
|
||||
|
||||
func (u *ContainerService) ComposeLogClean(req dto.ComposeLogClean) error {
|
||||
client, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
|
||||
@@ -95,6 +95,7 @@ func InitAgentDB() {
|
||||
migrations.AddDatabaseUserTable,
|
||||
migrations.AddBackupRecordArgs,
|
||||
migrations.AddFtpIdentity,
|
||||
migrations.AddComposePinned,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -1698,3 +1698,10 @@ var AddFtpIdentity = &gormigrate.Migration{
|
||||
}).Error
|
||||
},
|
||||
}
|
||||
|
||||
var AddComposePinned = &gormigrate.Migration{
|
||||
ID: "20260729-add-compose-pinned",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.Compose{})
|
||||
},
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
baRouter.POST("/compose/operate", baseApi.OperatorCompose)
|
||||
baRouter.POST("/compose/clean/log", baseApi.CleanComposeLog)
|
||||
baRouter.POST("/compose/update", baseApi.ComposeUpdate)
|
||||
baRouter.POST("/compose/pin", baseApi.ComposePin)
|
||||
|
||||
baRouter.GET("/template", baseApi.ListComposeTemplate)
|
||||
baRouter.POST("/template/search", baseApi.SearchComposeTemplate)
|
||||
|
||||
@@ -337,6 +337,7 @@ export namespace Container {
|
||||
configFile: string;
|
||||
workdir: string;
|
||||
composeFileExists: boolean;
|
||||
isPinned: boolean;
|
||||
path: string;
|
||||
containers: Array<ComposeContainer>;
|
||||
expand: boolean;
|
||||
@@ -374,6 +375,10 @@ export namespace Container {
|
||||
forcePull: boolean;
|
||||
createdBy: string;
|
||||
}
|
||||
export interface ComposePin {
|
||||
name: string;
|
||||
isPinned: boolean;
|
||||
}
|
||||
|
||||
export interface TemplateCreate {
|
||||
name: string;
|
||||
|
||||
@@ -240,6 +240,9 @@ export const composeOperate = (params: Container.ComposeOperation) => {
|
||||
export const composeUpdate = (params: Container.ComposeUpdate) => {
|
||||
return http.post(`/containers/compose/update`, params, TimeoutEnum.T_10M);
|
||||
};
|
||||
export const composePin = (params: Container.ComposePin) => {
|
||||
return http.post(`/containers/compose/pin`, params);
|
||||
};
|
||||
|
||||
// docker
|
||||
export const dockerOperate = (operation: string) => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4776196 */
|
||||
src: url('iconfont.woff2?t=1775716122874') format('woff2'),
|
||||
url('iconfont.woff?t=1775716122874') format('woff'),
|
||||
url('iconfont.ttf?t=1775716122874') format('truetype'),
|
||||
url('iconfont.svg?t=1775716122874#iconfont') format('svg');
|
||||
src: url('iconfont.woff2?t=1785320291556') format('woff2'),
|
||||
url('iconfont.woff?t=1785320291556') format('woff'),
|
||||
url('iconfont.ttf?t=1785320291556') format('truetype'),
|
||||
url('iconfont.svg?t=1785320291556#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -14,6 +14,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.p-pushpin:before {
|
||||
content: "\e7e3";
|
||||
}
|
||||
|
||||
.p-qrcode:before {
|
||||
content: "\e72a";
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,13 @@
|
||||
"css_prefix_text": "p-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "4766969",
|
||||
"name": "pushpin",
|
||||
"font_class": "pushpin",
|
||||
"unicode": "e7e3",
|
||||
"unicode_decimal": 59363
|
||||
},
|
||||
{
|
||||
"icon_id": "14679640",
|
||||
"name": "qrcode",
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
descent="-128"
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="pushpin" unicode="" d="M878.3 503.9L631.9 750.3c-6.5 6.5-15 9.7-23.5 9.7s-17-3.2-23.5-9.7L423.8 589.1c-12.2 1.4-24.5 2-36.8 2-73.2 0-146.4-24.1-206.5-72.3-15.4-12.3-16.7-35.4-2.7-49.4l181.7-181.7-215.4-215.2c-2.6-2.6-4.3-6.1-4.6-9.8l-3.4-37.2c-0.9-9.4 6.6-17.4 15.9-17.4 0.5 0 1 0 1.5 0.1l37.2 3.4c3.7 0.3 7.2 2 9.8 4.6l215.4 215.4 181.7-181.7c6.5-6.5 15-9.7 23.5-9.7 9.7 0 19.3 4.2 25.9 12.4 56.3 70.3 79.7 158.3 70.2 243.4l161.1 161.1c12.9 12.8 12.9 33.8 0 46.8zM666.2 346.7l-24.5-24.5 3.8-34.4c3.7-33.7 1-67.2-8.2-99.7-5.4-19-12.8-37.1-22.2-54.2L262 487.2c12.9 7.1 26.3 13.1 40.3 17.9 27.2 9.4 55.7 14.1 84.7 14.1 9.6 0 19.3-0.5 28.9-1.6l34.4-3.8 24.5 24.5L608.5 672 800 480.5 666.2 346.7z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="qrcode" unicode="" d="M629.650286 419.364571h194.998857c54.857143 0 81.846857 27.428571 81.846857 83.986286V694.930286c0 56.576-26.989714 83.565714-81.846857 83.565714H629.650286c-54.436571 0-81.865143-26.989714-81.865143-83.565714v-191.579429c0-56.557714 27.428571-83.986286 81.865143-83.986286z m-430.299429 0H394.788571c54.418286 0 81.846857 27.428571 81.846858 83.986286V694.930286c0 56.576-27.428571 83.565714-81.846858 83.565714H199.350857c-54.418286 0-81.846857-26.989714-81.846857-83.565714v-191.579429c0-56.557714 27.428571-83.986286 81.846857-83.986286z m0.859429 60.416c-14.994286 0-22.290286 7.716571-22.290286 23.588572V694.912c0 15.433143 7.296 23.149714 22.308571 23.149714h193.28c14.994286 0 22.710857-7.716571 22.710858-23.149714v-191.579429c0-15.853714-7.716571-23.570286-22.710858-23.570285z m430.281143 0c-14.994286 0-22.272 7.716571-22.272 23.588572V694.912c0 15.433143 7.277714 23.149714 22.272 23.149714h193.718857c14.573714 0 21.869714-7.716571 21.869714-23.149714v-191.579429c0-15.853714-7.296-23.570286-21.869714-23.570285z m-370.285715 74.148572h73.289143c6.436571 0 8.996571 2.56 8.996572 9.856v71.131428c0 6.875429-2.56 9.435429-8.996572 9.435429H260.205714c-6.418286 0-8.137143-2.56-8.137143-9.417143v-71.149714c0-7.277714 1.718857-9.874286 8.137143-9.874286z m432.859429 0h72.868571c6.418286 0 8.996571 2.56 8.996572 9.856v71.131428c0 6.875429-2.56 9.435429-8.996572 9.435429h-72.868571c-6.418286 0-8.557714-2.56-8.557714-9.417143v-71.149714c0-7.277714 2.139429-9.874286 8.557714-9.874286z m-493.714286-564.425143H394.788571c54.418286 0 81.846857 26.989714 81.846858 83.565714v192c0 56.137143-27.428571 83.565714-81.846858 83.565715H199.350857c-54.418286 0-81.846857-27.428571-81.846857-83.565715v-192c0-56.576 27.428571-83.565714 81.846857-83.565714z m377.142857 248.137143h73.289143c6.436571 0 8.996571 2.56 8.996572 9.874286v71.131428c0 6.857143-2.56 9.417143-8.996572 9.417143h-73.289143c-6.418286 0-8.137143-2.56-8.137143-9.417143v-71.131428c0-7.314286 1.718857-9.874286 8.137143-9.874286z m227.584 0h73.270857c6.436571 0 9.014857 2.56 9.014858 9.874286v71.131428c0 6.857143-2.578286 9.417143-9.014858 9.417143h-73.270857c-6.436571 0-8.594286-2.56-8.594285-9.417143v-71.131428c0-7.314286 2.157714-9.874286 8.594285-9.874286zM200.210286 49.92c-14.994286 0-22.290286 7.716571-22.290286 23.149714V264.649143c0 15.853714 7.296 23.570286 22.308571 23.570286h193.28c14.994286 0 22.710857-7.716571 22.710858-23.588572v-191.561143c0-15.433143-7.716571-23.149714-22.710858-23.149714z m59.995428 73.728h73.289143c6.436571 0 8.996571 2.56 8.996572 10.276571v70.710858c0 6.857143-2.56 9.435429-8.996572 9.435428H260.205714c-6.418286 0-8.137143-2.56-8.137143-9.435428v-70.710858c0-7.716571 1.718857-10.276571 8.137143-10.276571z m431.158857 0h73.270858c6.436571 0 8.996571 2.56 8.996571 10.276571v70.710858c0 6.857143-2.56 9.435429-8.996571 9.435428h-73.289143c-6.418286 0-8.137143-2.56-8.137143-9.435428v-70.710858c0-7.716571 1.718857-10.276571 8.155428-10.276571z m-114.870857-113.572571h73.289143c6.436571 0 8.996571 2.56 8.996572 9.856v71.131428c0 6.875429-2.56 9.435429-8.996572 9.435429h-73.289143c-6.418286 0-8.137143-2.56-8.137143-9.435429v-71.131428c0-7.296 1.718857-9.874286 8.137143-9.874286z m227.584 0h73.270857c6.436571 0 9.014857 2.56 9.014858 9.856v71.131428c0 6.875429-2.578286 9.435429-9.014858 9.435429h-73.270857c-6.436571 0-8.594286-2.56-8.594285-9.435429v-71.131428c0-7.296 2.157714-9.874286 8.594285-9.874286z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 239 KiB After Width: | Height: | Size: 239 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -150,6 +150,8 @@ const message = {
|
||||
manageGroup: 'Manage Groups',
|
||||
backToList: 'Back to List',
|
||||
keepEdit: 'Continue Editing',
|
||||
pin: 'Pin to top',
|
||||
unpin: 'Unpin',
|
||||
},
|
||||
loadingText: {
|
||||
Upgrading: 'Upgrading system, please wait...',
|
||||
@@ -3758,8 +3760,6 @@ const message = {
|
||||
cacheWarn: 'Please turn off the cache switch in the reverse proxy first',
|
||||
loadBalanceHelper:
|
||||
'After creating the load balancing, go to "Reverse Proxy", add a proxy and set the backend address to: http://<load balancing name>',
|
||||
favorite: 'Favorite',
|
||||
cancelFavorite: 'Cancel Favorite',
|
||||
useProxy: 'Use Proxy',
|
||||
useProxyHelper: 'Use the proxy server address in the panel settings',
|
||||
westCN: 'West Digital',
|
||||
|
||||
@@ -147,6 +147,8 @@ const message = {
|
||||
manageGroup: 'Gestionar grupos',
|
||||
backToList: 'Volver a la lista',
|
||||
keepEdit: 'Continuar Editando',
|
||||
pin: 'Fijar arriba',
|
||||
unpin: 'Desfijar',
|
||||
creator: 'Creador',
|
||||
updater: 'Actualizador',
|
||||
},
|
||||
@@ -3805,8 +3807,6 @@ const message = {
|
||||
runtimePortWarn: 'Este runtime no tiene puertos, no se puede usar proxy',
|
||||
cacheWarn: 'Desactiva la caché en proxy inverso primero',
|
||||
loadBalanceHelper: 'Tras crear balanceo, ve a "Proxy inverso" y añade un backend: http://<nombre balanceo>',
|
||||
favorite: 'Favorito',
|
||||
cancelFavorite: 'Quitar favorito',
|
||||
useProxy: 'Usar proxy',
|
||||
useProxyHelper: 'Usa la dirección del proxy configurado en el panel',
|
||||
westCN: 'West Digital',
|
||||
|
||||
@@ -146,6 +146,8 @@ const message = {
|
||||
manageGroup: 'مدیریت گروهها',
|
||||
backToList: 'بازگشت به لیست',
|
||||
keepEdit: 'ادامه ویرایش',
|
||||
pin: 'سنجاق کردن در بالا',
|
||||
unpin: 'برداشتن سنجاق',
|
||||
},
|
||||
loadingText: {
|
||||
Upgrading: 'در حال ارتقاء سیستم، لطفاً صبر کنید...',
|
||||
@@ -3727,8 +3729,6 @@ const message = {
|
||||
cacheWarn: 'لطفاً ابتدا کلید کش را در پراکسی معکوس خاموش کنید',
|
||||
loadBalanceHelper:
|
||||
'پس از ایجاد تعادل بار، به "پراکسی معکوس" بروید، یک پراکسی اضافه کرده و آدرس بکاند را به: http://<نام تعادل بار> تنظیم کنید',
|
||||
favorite: 'نشان کردن',
|
||||
cancelFavorite: 'لغو نشان کردن',
|
||||
useProxy: 'استفاده از پراکسی',
|
||||
useProxyHelper: 'از آدرس سرور پراکسی در تنظیمات پنل استفاده کنید',
|
||||
westCN: 'وست دیجیتال',
|
||||
|
||||
@@ -142,6 +142,8 @@ const message = {
|
||||
manageGroup: 'グループ管理',
|
||||
backToList: 'リストに戻る',
|
||||
keepEdit: '編集を続ける',
|
||||
pin: '上部に固定',
|
||||
unpin: '固定を解除',
|
||||
default: 'デフォルト',
|
||||
noRefresh: '自動更新なし',
|
||||
creator: '作成者',
|
||||
@@ -3772,8 +3774,6 @@ const message = {
|
||||
cacheWarn: 'まずリバースプロキシのキャッシュスイッチをオフにしてください',
|
||||
loadBalanceHelper:
|
||||
'負荷分散を作成した後、「リバースプロキシ」に移動し、プロキシを追加してバックエンドアドレスを次のように設定してください:http://<負荷分散名>。',
|
||||
favorite: 'お気に入り',
|
||||
cancelFavorite: 'お気に入りを解除',
|
||||
useProxy: 'プロキシを使用',
|
||||
useProxyHelper: 'パネル設定のプロキシサーバーアドレスを使用',
|
||||
westCN: '西部デジタル',
|
||||
|
||||
@@ -142,6 +142,8 @@ const message = {
|
||||
manageGroup: '그룹 관리',
|
||||
backToList: '목록으로 돌아가기',
|
||||
keepEdit: '계속 편집',
|
||||
pin: '상단 고정',
|
||||
unpin: '고정 해제',
|
||||
default: '기본값',
|
||||
noRefresh: '자동 새로고침 안 함',
|
||||
creator: '생성자',
|
||||
@@ -3691,8 +3693,6 @@ const message = {
|
||||
cacheWarn: '먼저 리버스 프록시의 캐시 스위치를 끄십시오',
|
||||
loadBalanceHelper:
|
||||
'로드 밸런싱을 생성한 후, "리버스 프록시"로 이동하여 프록시를 추가하고 백엔드 주소를 다음으로 설정하세요: http://<로드 밸런싱 이름>.',
|
||||
favorite: '즐겨찾기',
|
||||
cancelFavorite: '즐겨찾기 취소',
|
||||
useProxy: '프록시 사용',
|
||||
useProxyHelper: '패널 설정의 프록시 서버 주소 사용',
|
||||
westCN: '서부 디지털',
|
||||
|
||||
@@ -150,6 +150,8 @@ const message = {
|
||||
manageGroup: 'ຈັດການກຸ່ມ',
|
||||
backToList: 'ກັບຄືນໄປລາຍການ',
|
||||
keepEdit: 'ແກ້ໄຂຕໍ່',
|
||||
pin: 'ປັກໝຸດໄວ້ເທິງ',
|
||||
unpin: 'ຍົກເລີກການປັກໝຸດ',
|
||||
},
|
||||
loadingText: {
|
||||
Upgrading: 'ກຳລັງອັບເກຣດລະບົບ, ກະລຸນາຖ້າ...',
|
||||
@@ -3672,8 +3674,6 @@ const message = {
|
||||
cacheWarn: 'ກະລຸນາປິດແຄຊໃນ reverse proxy ກ່ອນ',
|
||||
loadBalanceHelper:
|
||||
'ຫຼັງຈາກສ້າງການກະຈາຍພາລະແລ້ວ, ໃຫ້ໄປທີ່ "Reverse Proxy", ເພີ່ມ proxy ແລະ ຕັ້ງທີ່ຢູ່ເບື້ອງຫຼັງເປັນ: http://<ຊື່ load balancing>',
|
||||
favorite: 'ເພີ່ມໃນລາຍການທີ່ມັກ',
|
||||
cancelFavorite: 'ຍົກເລີກລາຍການທີ່ມັກ',
|
||||
useProxy: 'ໃຊ້ Proxy',
|
||||
useProxyHelper: 'ໃຊ້ທີ່ຢູ່ເຊີບເວີ proxy ໃນການຕັ້ງຄ່າແຜງຄວບຄຸມ',
|
||||
westCN: 'West Digital',
|
||||
|
||||
@@ -142,6 +142,8 @@ const message = {
|
||||
manageGroup: 'Urus Kumpulan',
|
||||
backToList: 'Kembali ke Senarai',
|
||||
keepEdit: 'Teruskan Mengedit',
|
||||
pin: 'Semat ke atas',
|
||||
unpin: 'Nyahsemat',
|
||||
default: 'Lalai',
|
||||
noRefresh: 'Tiada segar semula auto',
|
||||
creator: 'Pencipta',
|
||||
@@ -3825,8 +3827,6 @@ const message = {
|
||||
cacheWarn: 'Sila matikan suis cache dalam pembalikan proksi terlebih dahulu',
|
||||
loadBalanceHelper:
|
||||
'Setelah mencipta pengimbang beban, sila pergi ke "Reverse Proxy", tambahkan proksi dan tetapkan alamat backend ke: http://<nama pengimbang beban>.',
|
||||
favorite: 'Kegemaran',
|
||||
cancelFavorite: 'Batalkan Kegemaran',
|
||||
useProxy: 'Gunakan Proksi',
|
||||
useProxyHelper: 'Gunakan alamat pelayan proksi dalam tetapan panel',
|
||||
westCN: 'West Digital',
|
||||
|
||||
@@ -142,6 +142,8 @@ const message = {
|
||||
manageGroup: 'Gerenciar Grupos',
|
||||
backToList: 'Voltar à Lista',
|
||||
keepEdit: 'Continuar Editando',
|
||||
pin: 'Fixar no topo',
|
||||
unpin: 'Desafixar',
|
||||
default: 'Padrão',
|
||||
noRefresh: 'Sem atualização',
|
||||
creator: 'Criador',
|
||||
@@ -3961,8 +3963,6 @@ const message = {
|
||||
cacheWarn: 'Por favor, desligue o interruptor de cache no proxy reverso primeiro',
|
||||
loadBalanceHelper:
|
||||
'Após criar o balanceamento de carga, vá para "Proxy Reverso", adicione um proxy e configure o endereço de backend para: http://<nome do balanceamento de carga>.',
|
||||
favorite: 'Favorito',
|
||||
cancelFavorite: 'Cancelar Favorito',
|
||||
useProxy: 'Usar Proxy',
|
||||
useProxyHelper: 'Usar o endereço do servidor proxy nas configurações do painel',
|
||||
westCN: 'West Digital',
|
||||
|
||||
@@ -142,6 +142,8 @@ const message = {
|
||||
manageGroup: 'Управление группами',
|
||||
backToList: 'Вернуться к списку',
|
||||
keepEdit: 'Продолжить редактирование',
|
||||
pin: 'Закрепить сверху',
|
||||
unpin: 'Открепить',
|
||||
default: 'По умолчанию',
|
||||
noRefresh: 'Без автообновления',
|
||||
creator: 'Создатель',
|
||||
@@ -3814,8 +3816,6 @@ const message = {
|
||||
cacheWarn: 'Пожалуйста, сначала выключите кэш в обратном прокси',
|
||||
loadBalanceHelper:
|
||||
'После создания балансировки нагрузки, пожалуйста, перейдите в "Обратный прокси", добавьте прокси и установите адрес бэкенда на: http://<название балансировки нагрузки>.',
|
||||
favorite: 'Избранное',
|
||||
cancelFavorite: 'Отменить избранное',
|
||||
useProxy: 'Использовать прокси',
|
||||
useProxyHelper: 'Использовать адрес прокси-сервера в настройках панели',
|
||||
westCN: 'Западный цифровой',
|
||||
|
||||
@@ -147,6 +147,8 @@ const message = {
|
||||
manageGroup: 'Grupları Yönet',
|
||||
backToList: 'Listeye Dön',
|
||||
keepEdit: 'Düzenlemeye Devam Et',
|
||||
pin: 'Üste sabitle',
|
||||
unpin: 'Sabitlemeyi kaldır',
|
||||
creator: 'Oluşturan',
|
||||
updater: 'Güncelleyen',
|
||||
},
|
||||
@@ -3816,8 +3818,6 @@ const message = {
|
||||
cacheWarn: 'Lütfen önce ters vekildeki önbellek anahtarını kapatın',
|
||||
loadBalanceHelper:
|
||||
'Bu bölüm yalnızca yük dengeleme kuralları oluşturur, kuralları kullanmak için lütfen http(s)://<yük dengeleme adı> adresine ters vekil yapın',
|
||||
favorite: 'Favori',
|
||||
cancelFavorite: 'Favoriyi İptal Et',
|
||||
useProxy: 'Vekil Kullan',
|
||||
useProxyHelper: 'Panel ayarlarındaki vekil sunucu adresini kullan',
|
||||
westCN: 'Batı Dijital',
|
||||
|
||||
@@ -143,6 +143,8 @@ const message = {
|
||||
manageGroup: '管理群組',
|
||||
backToList: '返回列表',
|
||||
keepEdit: '繼續編輯',
|
||||
pin: '置頂',
|
||||
unpin: '取消置頂',
|
||||
creator: '建立者',
|
||||
updater: '更新者',
|
||||
},
|
||||
@@ -3490,8 +3492,6 @@ const message = {
|
||||
runtimePortWarn: '目前執行環境沒有埠,無法代理',
|
||||
cacheWarn: '請先關閉反代中的快取開關',
|
||||
loadBalanceHelper: '建立負載均衡後,請前往『反向代理』,新增代理並將後端地址設定為:http://<負載均衡名稱>',
|
||||
favorite: '收藏',
|
||||
cancelFavorite: '取消收藏',
|
||||
useProxy: '使用代理',
|
||||
useProxyHelper: '使用面板設定中的代理伺服器地址',
|
||||
westCN: '西部數碼',
|
||||
|
||||
@@ -138,6 +138,8 @@ const message = {
|
||||
manageGroup: '管理分组',
|
||||
backToList: '返回列表',
|
||||
keepEdit: '继续编辑',
|
||||
pin: '置顶',
|
||||
unpin: '取消置顶',
|
||||
},
|
||||
loadingText: {
|
||||
Upgrading: '系统升级中,请稍候...',
|
||||
@@ -3491,8 +3493,6 @@ const message = {
|
||||
runtimePortWarn: '当前运行环境没有端口,无法代理',
|
||||
cacheWarn: '请先关闭反代中的缓存开关',
|
||||
loadBalanceHelper: '创建负载均衡后,请前往‘反向代理’,添加代理并将后端地址设置为:http://<负载均衡名称>。',
|
||||
favorite: '收藏',
|
||||
cancelFavorite: '取消收藏',
|
||||
useProxy: '使用代理',
|
||||
useProxyHelper: '使用面板设置中的代理服务器地址',
|
||||
westCN: '西部数码',
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
<div v-for="row in group.items" :key="row.name" class="node-table__row">
|
||||
<div class="node-table__cell node-table__cell--node">
|
||||
<el-tooltip
|
||||
:content="
|
||||
row.isFavorite ? $t('website.cancelFavorite') : $t('website.favorite')
|
||||
"
|
||||
:content="row.isFavorite ? $t('commons.table.unpin') : $t('commons.table.pin')"
|
||||
placement="left"
|
||||
>
|
||||
<el-button
|
||||
@@ -31,10 +29,11 @@
|
||||
link
|
||||
v-if="isAdmin"
|
||||
:type="row.isFavorite ? 'warning' : 'info'"
|
||||
:icon="row.isFavorite ? 'StarFilled' : 'Star'"
|
||||
:loading="favoriteLoadingIDs.includes(row.id)"
|
||||
@click.stop="toggleFavorite(row)"
|
||||
/>
|
||||
>
|
||||
<SvgIcon iconName="p-pushpin" className="node-pin-icon" />
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<div class="node-name-cell">
|
||||
<SvgIcon class="icon" iconName="p-zhuji" />
|
||||
@@ -309,6 +308,13 @@ watch(
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
padding: 0;
|
||||
|
||||
:deep(.node-pin-icon) {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.node-name-cell {
|
||||
|
||||
@@ -83,29 +83,21 @@
|
||||
<span class="ml-1" v-if="mode === 'installed'">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('website.cancelFavorite')"
|
||||
:content="installed.favorite ? $t('commons.table.unpin') : $t('commons.table.pin')"
|
||||
placement="top-start"
|
||||
v-if="installed.favorite"
|
||||
>
|
||||
<el-button
|
||||
v-permission
|
||||
link
|
||||
size="large"
|
||||
icon="StarFilled"
|
||||
type="warning"
|
||||
:type="installed.favorite ? 'warning' : 'info'"
|
||||
:disabled="sortMode"
|
||||
@click="$emit('favoriteInstall')"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="$t('website.favorite')" placement="top-start" v-else>
|
||||
<el-button
|
||||
v-permission
|
||||
link
|
||||
icon="Star"
|
||||
type="info"
|
||||
:disabled="sortMode"
|
||||
@click="$emit('favoriteInstall')"
|
||||
></el-button>
|
||||
>
|
||||
<el-icon>
|
||||
<SvgIcon iconName="p-pushpin" />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
:class="{ 'is-active': currentCompose?.name === row.name && !isOnCreate }"
|
||||
>
|
||||
<div class="font-medium text-base compose-title">
|
||||
{{ row.name }}
|
||||
<span class="compose-title__name">{{ row.name }}</span>
|
||||
<el-tooltip
|
||||
v-if="!row.composeFileExists"
|
||||
:content="$t('container.composeFileMissing')"
|
||||
@@ -47,6 +47,24 @@
|
||||
<WarningFilled />
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
:content="
|
||||
row.isPinned
|
||||
? $t('commons.table.unpin')
|
||||
: $t('commons.table.pin')
|
||||
"
|
||||
>
|
||||
<el-button
|
||||
class="compose-pin-button"
|
||||
:class="{ 'is-pinned': row.isPinned }"
|
||||
link
|
||||
:type="row.isPinned ? 'warning' : 'info'"
|
||||
v-permission
|
||||
@click.stop="changePinned(row)"
|
||||
>
|
||||
<svg-icon iconName="p-pushpin" className="compose-pin-icon" />
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<el-text class="w-12" link size="small" type="info">
|
||||
@@ -222,7 +240,10 @@
|
||||
</div>
|
||||
<el-popover placement="right" width="500px" class="float-right">
|
||||
<template #reference>
|
||||
<svg-icon iconName="p-xiangqing" class="svg-icon"></svg-icon>
|
||||
<svg-icon
|
||||
iconName="p-xiangqing"
|
||||
className="resource-detail-icon"
|
||||
></svg-icon>
|
||||
</template>
|
||||
<template #default>
|
||||
<el-descriptions
|
||||
@@ -494,6 +515,7 @@ import Backups from '@/components/backup/index.vue';
|
||||
import Uploads from '@/components/upload/index.vue';
|
||||
import {
|
||||
composeOperate,
|
||||
composePin,
|
||||
composeUpdate,
|
||||
containerItemStats,
|
||||
containerListStats,
|
||||
@@ -653,6 +675,15 @@ const search = async (withRefreshDetail?: boolean) => {
|
||||
});
|
||||
};
|
||||
|
||||
const changePinned = async (row: Container.ComposeInfo) => {
|
||||
await composePin({
|
||||
name: row.name,
|
||||
isPinned: !row.isPinned,
|
||||
});
|
||||
await search(true);
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
|
||||
const loadDetail = async (row: Container.ComposeInfo, withRefresh: boolean) => {
|
||||
if (currentCompose.value?.name === row.name && withRefresh !== true) {
|
||||
return;
|
||||
@@ -958,9 +989,39 @@ const onOpenLog = (row: any) => {
|
||||
}
|
||||
|
||||
.compose-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
transition: color 0.15s;
|
||||
}
|
||||
|
||||
.compose-title__name {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.compose-pin-button {
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
opacity: 0.72;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible,
|
||||
&.is-pinned {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
:deep(.compose-pin-icon) {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.compose-item.is-active .compose-title {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
@@ -980,7 +1041,7 @@ const onOpenLog = (row: any) => {
|
||||
max-height: 40px;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
.resource-detail-icon {
|
||||
margin-top: -3px;
|
||||
font-size: 6px;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -63,8 +63,6 @@
|
||||
row-key="containerID"
|
||||
@sort-change="search"
|
||||
@search="search"
|
||||
@cell-mouse-enter="showFavorite"
|
||||
@cell-mouse-leave="hideFavorite"
|
||||
:row-style="{ height: '65px' }"
|
||||
style="width: 100%"
|
||||
:columns="columns"
|
||||
@@ -82,24 +80,26 @@
|
||||
:fixed="isMobile ? false : 'left'"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row, $index }">
|
||||
<template #default="{ row }">
|
||||
<el-text type="primary" class="cursor-pointer" @click="onInspect(row)">
|
||||
{{ row.name }}
|
||||
</el-text>
|
||||
|
||||
<div class="float-right">
|
||||
<el-tooltip
|
||||
:content="row.isPinned ? $t('website.cancelFavorite') : $t('website.favorite')"
|
||||
v-if="row.isPinned || hoveredRowIndex === $index"
|
||||
:content="row.isPinned ? $t('commons.table.unpin') : $t('commons.table.pin')"
|
||||
>
|
||||
<el-button
|
||||
class="container-pin-button"
|
||||
:class="{ 'is-pinned': row.isPinned }"
|
||||
link
|
||||
size="large"
|
||||
:icon="row.isPinned ? 'StarFilled' : 'Star'"
|
||||
type="warning"
|
||||
:type="row.isPinned ? 'warning' : 'info'"
|
||||
v-permission
|
||||
@click="changePinned(row, true)"
|
||||
/>
|
||||
>
|
||||
<svg-icon iconName="p-pushpin" className="container-pin-icon" />
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
@@ -183,7 +183,7 @@
|
||||
</div>
|
||||
<el-popover placement="right" width="500px" class="float-right">
|
||||
<template #reference>
|
||||
<svg-icon iconName="p-xiangqing" class="svg-icon"></svg-icon>
|
||||
<svg-icon iconName="p-xiangqing" className="resource-detail-icon"></svg-icon>
|
||||
</template>
|
||||
<template #default>
|
||||
<el-descriptions direction="vertical" border :column="3" size="small">
|
||||
@@ -550,7 +550,6 @@ const taskLogRef = ref();
|
||||
const tags = ref([]);
|
||||
const activeTag = ref('all');
|
||||
|
||||
const hoveredRowIndex = ref(-1);
|
||||
const activeDropdownContainerId = ref('');
|
||||
const statFields = [
|
||||
'cpuTotalUsage',
|
||||
@@ -753,12 +752,6 @@ const searchWithAppShow = (item: any) => {
|
||||
search();
|
||||
};
|
||||
|
||||
const showFavorite = (row: any) => {
|
||||
hoveredRowIndex.value = data.value.findIndex((item) => item === row);
|
||||
};
|
||||
const hideFavorite = () => {
|
||||
hoveredRowIndex.value = -1;
|
||||
};
|
||||
const changePinned = (row: any, isPinned: boolean) => {
|
||||
let params = {
|
||||
id: row.containerID,
|
||||
@@ -1102,7 +1095,7 @@ onMounted(() => {
|
||||
.source-font {
|
||||
font-size: 12px;
|
||||
}
|
||||
.svg-icon {
|
||||
.resource-detail-icon {
|
||||
margin-top: -3px;
|
||||
font-size: 6px;
|
||||
cursor: pointer;
|
||||
@@ -1122,4 +1115,24 @@ onMounted(() => {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.container-pin-button {
|
||||
opacity: 0.72;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.is-pinned {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
:deep(.container-pin-icon) {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -36,30 +36,30 @@
|
||||
:pagination-config="paginationConfig"
|
||||
:data="data"
|
||||
@sort-change="search"
|
||||
@cell-mouse-enter="showFavorite"
|
||||
@cell-mouse-leave="hideFavorite"
|
||||
:columns="columns"
|
||||
@search="search"
|
||||
:heightDiff="300"
|
||||
>
|
||||
<el-table-column label="ID" prop="id" width="180">
|
||||
<template #default="{ row, $index }">
|
||||
<template #default="{ row }">
|
||||
<el-text type="primary" class="cursor-pointer" @click="onInspect(row.id)">
|
||||
{{ row.id.replaceAll('sha256:', '').substring(0, 12) }}
|
||||
</el-text>
|
||||
<div class="float-right">
|
||||
<el-tooltip
|
||||
:content="row.isPinned ? $t('website.cancelFavorite') : $t('website.favorite')"
|
||||
v-if="row.isPinned || hoveredRowIndex === $index"
|
||||
:content="row.isPinned ? $t('commons.table.unpin') : $t('commons.table.pin')"
|
||||
>
|
||||
<el-button
|
||||
class="image-pin-button"
|
||||
:class="{ 'is-pinned': row.isPinned }"
|
||||
link
|
||||
size="large"
|
||||
:icon="row.isPinned ? 'StarFilled' : 'Star'"
|
||||
type="warning"
|
||||
:type="row.isPinned ? 'warning' : 'info'"
|
||||
v-permission
|
||||
@click="changePinned(row, true)"
|
||||
/>
|
||||
>
|
||||
<svg-icon iconName="p-pushpin" className="image-pin-icon" />
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
@@ -204,8 +204,6 @@ const columns = ref([]);
|
||||
const isActive = ref(false);
|
||||
const isExist = ref(false);
|
||||
|
||||
const hoveredRowIndex = ref(-1);
|
||||
|
||||
const myDetail = ref();
|
||||
const dialogPullRef = ref();
|
||||
const dialogTagRef = ref();
|
||||
@@ -282,12 +280,6 @@ const onSubmitDelete = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
const showFavorite = (row: any) => {
|
||||
hoveredRowIndex.value = data.value.findIndex((item) => item === row);
|
||||
};
|
||||
const hideFavorite = () => {
|
||||
hoveredRowIndex.value = -1;
|
||||
};
|
||||
const changePinned = (row: any, isPinned: boolean) => {
|
||||
let params = {
|
||||
id: row.id.replaceAll('sha256:', ''),
|
||||
@@ -493,3 +485,23 @@ const buttons = [
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.image-pin-button {
|
||||
opacity: 0.72;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible,
|
||||
&.is-pinned {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
:deep(.image-pin-icon) {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -63,24 +63,22 @@
|
||||
<el-button v-permission link icon="edit" class="ml-2.5" @click="startEdit" v-if="!isEditing"></el-button>
|
||||
</div>
|
||||
<div v-if="showFavorite">
|
||||
<el-tooltip effect="dark" :content="$t('website.cancelFavorite')" placement="top-start" v-if="row.favorite">
|
||||
<el-button
|
||||
v-permission
|
||||
link
|
||||
:size="hideName ? 'default' : 'large'"
|
||||
icon="StarFilled"
|
||||
type="warning"
|
||||
@click="favoriteWebsite(row)"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('website.favorite')"
|
||||
:content="row.favorite ? $t('commons.table.unpin') : $t('commons.table.pin')"
|
||||
placement="top-start"
|
||||
v-if="!row.favorite && isHovered"
|
||||
>
|
||||
<el-button v-permission link icon="Star" type="info" @click="favoriteWebsite(row)"></el-button>
|
||||
<el-button
|
||||
v-permission
|
||||
class="website-pin-button"
|
||||
:class="{ 'is-pinned': row.favorite }"
|
||||
link
|
||||
:size="hideName ? 'default' : 'large'"
|
||||
:type="row.favorite ? 'warning' : 'info'"
|
||||
@click="favoriteWebsite(row)"
|
||||
>
|
||||
<svg-icon iconName="p-pushpin" className="website-pin-icon" />
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,7 +93,6 @@ import { Rules } from '@/global/form-rules';
|
||||
import { GetPunyCodeDomain, isPunycoded } from '@/utils/misc';
|
||||
interface Props {
|
||||
row: Website.Website;
|
||||
isHovered: boolean;
|
||||
defaultHttpPort: number;
|
||||
defaultHttpsPort: number;
|
||||
hideName?: boolean;
|
||||
@@ -287,4 +284,22 @@ const shouldShowDomainTooltip = (domain: string) => {
|
||||
word-break: break-all;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.website-pin-button {
|
||||
opacity: 0.72;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.website-pin-button:hover,
|
||||
.website-pin-button:focus-visible,
|
||||
.website-pin-button.is-pinned {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.website-pin-button :deep(.website-pin-icon) {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -75,8 +75,6 @@
|
||||
:class="{ mask: disabledConfig }"
|
||||
:heightDiff="310"
|
||||
:columns="columns"
|
||||
@cell-mouse-enter="showFavorite"
|
||||
@cell-mouse-leave="hideFavorite"
|
||||
localKey="websiteColumn"
|
||||
v-model:selects="selects"
|
||||
:tooltip-options="{
|
||||
@@ -92,7 +90,7 @@
|
||||
sortable
|
||||
card-type="name"
|
||||
>
|
||||
<template #default="{ row, $index, viewMode: columnViewMode }">
|
||||
<template #default="{ row, viewMode: columnViewMode }">
|
||||
<div v-if="columnViewMode === 'card'" class="website-card-domain">
|
||||
<el-text
|
||||
type="primary"
|
||||
@@ -104,7 +102,6 @@
|
||||
<Domain
|
||||
class="website-card-domain__actions"
|
||||
:row="row"
|
||||
:is-hovered="true"
|
||||
:defaultHttpPort="appStatusRef?.getHttpPort?.() || 0"
|
||||
:defaultHttpsPort="appStatusRef?.getHttpsPort?.() || 0"
|
||||
:hide-name="true"
|
||||
@@ -116,7 +113,6 @@
|
||||
<Domain
|
||||
v-else
|
||||
:row="row"
|
||||
:is-hovered="hoveredRowIndex === $index"
|
||||
:defaultHttpPort="appStatusRef?.getHttpPort?.() || 0"
|
||||
:defaultHttpsPort="appStatusRef?.getHttpsPort?.() || 0"
|
||||
@favorite-change="favoriteWebsite"
|
||||
@@ -415,7 +411,6 @@ const data = ref();
|
||||
let groups = ref<Group.GroupInfo[]>([]);
|
||||
const dataRef = ref();
|
||||
const columns = ref([]);
|
||||
const hoveredRowIndex = ref(-1);
|
||||
const websiteDir = ref();
|
||||
const selects = ref([]);
|
||||
const batchReq = reactive({
|
||||
@@ -459,14 +454,6 @@ const goRouter = async (key: string) => {
|
||||
routerToNameWithQuery('AppAll', { install: key });
|
||||
};
|
||||
|
||||
const showFavorite = (row: any) => {
|
||||
hoveredRowIndex.value = data.value.findIndex((item) => item === row);
|
||||
};
|
||||
|
||||
const hideFavorite = () => {
|
||||
hoveredRowIndex.value = -1;
|
||||
};
|
||||
|
||||
const favoriteWebsite = (row: Website.Website) => {
|
||||
row.favorite = !row.favorite;
|
||||
updateWebsitConfig(row);
|
||||
|
||||
Reference in New Issue
Block a user