mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-01-07 01:08:49 +01:00
Merge remote-tracking branch 'origin/dev' into dev
# Conflicts: # app/src/protyle/render/av/layout.ts
This commit is contained in:
commit
734db627c0
19 changed files with 89 additions and 70 deletions
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "متوسط",
|
||||
"small": "صغير",
|
||||
"fitImage": "تعديل حجم الصورة تلقائيًا",
|
||||
"showIcon": "عرض أيقونة المفتاح الأساسي",
|
||||
"showIcon": "عرض الأيقونة",
|
||||
"showAllFieldsIcon": "عرض أيقونات الحقول",
|
||||
"wrapAllFields": "التفاف الحقول تلقائيًا",
|
||||
"gallery": "معرض",
|
||||
"newTag": "علامة جديدة",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Mittel",
|
||||
"small": "Klein",
|
||||
"fitImage": "Bildgröße automatisch anpassen",
|
||||
"showIcon": "Primärschlüssel-Symbol anzeigen",
|
||||
"showIcon": "Symbol anzeigen",
|
||||
"showAllFieldsIcon": "Feldsymbole anzeigen",
|
||||
"wrapAllFields": "Felder automatisch umbrechen",
|
||||
"gallery": "Galerie",
|
||||
"newTag": "Neuer Tag",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Medium",
|
||||
"small": "Small",
|
||||
"fitImage": "Auto-fit image size",
|
||||
"showIcon": "Show primary key icon",
|
||||
"showIcon": "Show icon",
|
||||
"showAllFieldsIcon": "Show field icons",
|
||||
"wrapAllFields": "Auto-wrap fields",
|
||||
"gallery": "Gallery",
|
||||
"newTag": "New tag",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Mediano",
|
||||
"small": "Pequeño",
|
||||
"fitImage": "Ajustar automáticamente el tamaño de la imagen",
|
||||
"showIcon": "Mostrar ícono de clave primaria",
|
||||
"showIcon": "Mostrar ícono",
|
||||
"showAllFieldsIcon": "Mostrar íconos de campos",
|
||||
"wrapAllFields": "Ajuste automático de campos",
|
||||
"gallery": "Galería",
|
||||
"newTag": "Nueva etiqueta",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Moyen",
|
||||
"small": "Petit",
|
||||
"fitImage": "Ajuster automatiquement la taille de l'image",
|
||||
"showIcon": "Afficher l'icône de la clé primaire",
|
||||
"showIcon": "Afficher l'icône",
|
||||
"showAllFieldsIcon": "Afficher les icônes des champs",
|
||||
"wrapAllFields": "Retour automatique des champs",
|
||||
"gallery": "Galerie",
|
||||
"newTag": "Nouvelle étiquette",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "בינוני",
|
||||
"small": "קטן",
|
||||
"fitImage": "התאמה אוטומטית לגודל התמונה",
|
||||
"showIcon": "הצג את סמל המפתח הראשי",
|
||||
"showIcon": "הצג סמל",
|
||||
"showAllFieldsIcon": "הצג סמלי שדות",
|
||||
"wrapAllFields": "עטיפת שדות אוטומטית",
|
||||
"gallery": "גלריה",
|
||||
"newTag": "תג חדש",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Medio",
|
||||
"small": "Piccolo",
|
||||
"fitImage": "Adatta automaticamente la dimensione dell'immagine",
|
||||
"showIcon": "Mostra l'icona della chiave primaria",
|
||||
"showIcon": "Mostra icona",
|
||||
"showAllFieldsIcon": "Mostra icone dei campi",
|
||||
"wrapAllFields": "Avvolgi automaticamente i campi",
|
||||
"gallery": "Galleria",
|
||||
"newTag": "Nuova etichetta",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "中",
|
||||
"small": "小",
|
||||
"fitImage": "画像サイズを自動調整",
|
||||
"showIcon": "主キーアイコンを表示",
|
||||
"showIcon": "アイコンを表示",
|
||||
"showAllFieldsIcon": "フィールドアイコンを表示",
|
||||
"wrapAllFields": "フィールドを自動折り返し",
|
||||
"gallery": "ギャラリー",
|
||||
"newTag": "新しいタグ",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Średni",
|
||||
"small": "Mały",
|
||||
"fitImage": "Automatyczne dopasowanie rozmiaru obrazu",
|
||||
"showIcon": "Pokaż ikonę klucza głównego",
|
||||
"showIcon": "Pokaż ikonę",
|
||||
"showAllFieldsIcon": "Pokaż ikony pól",
|
||||
"wrapAllFields": "Automatyczne zawijanie pól",
|
||||
"gallery": "Galeria",
|
||||
"newTag": "Nowy tag",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Médio",
|
||||
"small": "Pequeno",
|
||||
"fitImage": "Ajustar automaticamente o tamanho da imagem",
|
||||
"showIcon": "Mostrar ícone da chave primária",
|
||||
"showIcon": "Mostrar ícone",
|
||||
"showAllFieldsIcon": "Mostrar ícones de campos",
|
||||
"wrapAllFields": "Quebrar automaticamente os campos",
|
||||
"gallery": "Galeria",
|
||||
"newTag": "Nova tag",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
"medium": "Средний",
|
||||
"small": "Маленький",
|
||||
"fitImage": "Автоматическая подгонка размера изображения",
|
||||
"showIcon": "Показать значок первичного ключа",
|
||||
"showIcon": "Показать значок",
|
||||
"showAllFieldsIcon": "Показать значки полей",
|
||||
"wrapAllFields": "Автоматический перенос полей",
|
||||
"gallery": "Галерея",
|
||||
"newTag": "Новый тег",
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@
|
|||
"medium": "中",
|
||||
"small": "小",
|
||||
"fitImage": "自動調整圖片大小",
|
||||
"showIcon": "顯示主鍵圖標",
|
||||
"wrapAllFields": "欄位自動換行",
|
||||
"showIcon": "顯示圖標",
|
||||
"showAllFieldsIcon": "顯示字段圖標",
|
||||
"wrapAllFields": "字段自動換行",
|
||||
"gallery": "圖庫",
|
||||
"newTag": "新建標籤",
|
||||
"pleaseWait": "請稍等片刻...",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"small": "小",
|
||||
"fitImage": "自适应图片大小",
|
||||
"showIcon": "显示图标",
|
||||
"showAllFieldsIcon": "显示字段图标",
|
||||
"wrapAllFields": "字段自动换行",
|
||||
"gallery": "画廊",
|
||||
"newTag": "新建标签",
|
||||
|
|
|
|||
|
|
@ -223,10 +223,10 @@ func NewTableViewWithBlockKey(blockKeyID string) (view *View, blockKey, selectKe
|
|||
Table: NewLayoutTable(),
|
||||
}
|
||||
blockKey = NewKey(blockKeyID, GetAttributeViewI18n("key"), "", KeyTypeBlock)
|
||||
view.Table.Columns = []*ViewTableColumn{{ID: blockKeyID}}
|
||||
view.Table.Columns = []*ViewTableColumn{{BaseField: &BaseField{ID: blockKeyID}}}
|
||||
|
||||
selectKey = NewKey(ast.NewNodeID(), GetAttributeViewI18n("select"), "", KeyTypeSelect)
|
||||
view.Table.Columns = append(view.Table.Columns, &ViewTableColumn{ID: selectKey.ID})
|
||||
view.Table.Columns = append(view.Table.Columns, &ViewTableColumn{BaseField: &BaseField{ID: selectKey.ID}})
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,14 @@ type BaseLayout struct {
|
|||
PageSize int `json:"pageSize,omitempty"` // 每页条目数
|
||||
}
|
||||
|
||||
// BaseField 描述了字段的基础结构。
|
||||
type BaseField struct {
|
||||
ID string `json:"id"` // 字段 ID
|
||||
Wrap bool `json:"wrap"` // 是否换行
|
||||
Hidden bool `json:"hidden"` // 是否隐藏
|
||||
Desc string `json:"desc,omitempty"` // 字段描述
|
||||
}
|
||||
|
||||
// BaseValue 描述了字段值的基础结构。
|
||||
type BaseValue struct {
|
||||
ID string `json:"id"` // 字段值 ID
|
||||
|
|
|
|||
|
|
@ -82,11 +82,7 @@ const (
|
|||
|
||||
// ViewGalleryCardField 描述了画廊卡片字段的结构。
|
||||
type ViewGalleryCardField struct {
|
||||
ID string `json:"id"` // 字段 ID
|
||||
|
||||
Wrap bool `json:"wrap"` // 是否换行
|
||||
Hidden bool `json:"hidden"` // 是否隐藏
|
||||
Desc string `json:"desc,omitempty"` // 字段描述
|
||||
*BaseField
|
||||
}
|
||||
|
||||
// Gallery 描述了画廊实例的结构。
|
||||
|
|
@ -98,12 +94,9 @@ type Gallery struct {
|
|||
CardAspectRatio CardAspectRatio `json:"cardAspectRatio"` // 卡片宽高比
|
||||
CardSize CardSize `json:"cardSize"` // 卡片大小
|
||||
FitImage bool `json:"fitImage"` // 是否适应封面图片大小
|
||||
ShowIcon bool `json:"showIcon"` // 是否显示字段图标
|
||||
WrapField bool `json:"wrapField"` // 是否换行字段内容
|
||||
|
||||
Fields []*GalleryField `json:"fields"` // 画廊字段
|
||||
Cards []*GalleryCard `json:"cards"` // 画廊卡片
|
||||
CardCount int `json:"cardCount"` // 画廊总卡片数
|
||||
Fields []*GalleryField `json:"fields"` // 画廊字段
|
||||
Cards []*GalleryCard `json:"cards"` // 画廊卡片
|
||||
CardCount int `json:"cardCount"` // 画廊总卡片数
|
||||
}
|
||||
|
||||
// GalleryCard 描述了画廊实例卡片的结构。
|
||||
|
|
|
|||
|
|
@ -44,14 +44,11 @@ func NewLayoutTable() *LayoutTable {
|
|||
|
||||
// ViewTableColumn 描述了表格列的结构。
|
||||
type ViewTableColumn struct {
|
||||
ID string `json:"id"` // 列 ID
|
||||
*BaseField
|
||||
|
||||
Wrap bool `json:"wrap"` // 是否换行
|
||||
Hidden bool `json:"hidden"` // 是否隐藏
|
||||
Pin bool `json:"pin"` // 是否固定
|
||||
Width string `json:"width"` // 列宽度
|
||||
Desc string `json:"desc,omitempty"` // 列描述
|
||||
Calc *ColumnCalc `json:"calc,omitempty"` // 计算
|
||||
Pin bool `json:"pin"` // 是否固定
|
||||
Width string `json:"width"` // 列宽度
|
||||
Calc *ColumnCalc `json:"calc,omitempty"` // 计算
|
||||
}
|
||||
|
||||
// Table 描述了表格实例的结构。
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ func ChangeAttrViewLayout(blockID, avID string, layout av.LayoutType) (err error
|
|||
switch view.LayoutType {
|
||||
case av.LayoutTypeGallery:
|
||||
for _, field := range view.Gallery.CardFields {
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: field.ID})
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: field.ID}})
|
||||
}
|
||||
for _, cardID := range view.Gallery.CardIDs {
|
||||
view.Table.RowIDs = append(view.Table.RowIDs, cardID)
|
||||
|
|
@ -139,7 +139,7 @@ func ChangeAttrViewLayout(blockID, avID string, layout av.LayoutType) (err error
|
|||
switch view.LayoutType {
|
||||
case av.LayoutTypeTable:
|
||||
for _, col := range view.Table.Columns {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{ID: col.ID})
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: col.ID}})
|
||||
}
|
||||
for _, rowID := range view.Table.RowIDs {
|
||||
view.Gallery.CardIDs = append(view.Gallery.CardIDs, rowID)
|
||||
|
|
@ -1636,9 +1636,9 @@ func updateAttributeViewColRelation(operation *Operation) (err error) {
|
|||
for _, v := range destAv.Views {
|
||||
switch v.LayoutType {
|
||||
case av.LayoutTypeTable:
|
||||
v.Table.Columns = append(v.Table.Columns, &av.ViewTableColumn{ID: operation.BackRelationKeyID})
|
||||
v.Table.Columns = append(v.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: operation.BackRelationKeyID}})
|
||||
case av.LayoutTypeGallery:
|
||||
v.Gallery.CardFields = append(v.Gallery.CardFields, &av.ViewGalleryCardField{ID: operation.BackRelationKeyID})
|
||||
v.Gallery.CardFields = append(v.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: operation.BackRelationKeyID}})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1896,13 +1896,15 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr
|
|||
case av.LayoutTypeTable:
|
||||
for _, col := range masterView.Table.Columns {
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{
|
||||
ID: col.ID,
|
||||
Wrap: col.Wrap,
|
||||
Hidden: col.Hidden,
|
||||
Pin: col.Pin,
|
||||
Width: col.Width,
|
||||
Desc: col.Desc,
|
||||
Calc: col.Calc,
|
||||
BaseField: &av.BaseField{
|
||||
ID: col.ID,
|
||||
Wrap: col.Wrap,
|
||||
Hidden: col.Hidden,
|
||||
Desc: col.Desc,
|
||||
},
|
||||
Pin: col.Pin,
|
||||
Width: col.Width,
|
||||
Calc: col.Calc,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1912,10 +1914,12 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr
|
|||
case av.LayoutTypeGallery:
|
||||
for _, field := range masterView.Gallery.CardFields {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{
|
||||
ID: field.ID,
|
||||
Wrap: field.Wrap,
|
||||
Hidden: field.Hidden,
|
||||
Desc: field.Desc,
|
||||
BaseField: &av.BaseField{
|
||||
ID: field.ID,
|
||||
Wrap: field.Wrap,
|
||||
Hidden: field.Hidden,
|
||||
Desc: field.Desc,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1972,14 +1976,14 @@ func addAttrViewView(avID, viewID, blockID string, layout av.LayoutType) (err er
|
|||
switch firstView.LayoutType {
|
||||
case av.LayoutTypeTable:
|
||||
for _, col := range firstView.Table.Columns {
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: col.ID})
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: col.ID}})
|
||||
}
|
||||
for _, rowID := range firstView.Table.RowIDs {
|
||||
view.Table.RowIDs = append(view.Table.RowIDs, rowID)
|
||||
}
|
||||
case av.LayoutTypeGallery:
|
||||
for _, field := range firstView.Gallery.CardFields {
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: field.ID})
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: field.ID}})
|
||||
}
|
||||
for _, cardID := range firstView.Gallery.CardIDs {
|
||||
view.Table.RowIDs = append(view.Table.RowIDs, cardID)
|
||||
|
|
@ -1990,14 +1994,14 @@ func addAttrViewView(avID, viewID, blockID string, layout av.LayoutType) (err er
|
|||
switch firstView.LayoutType {
|
||||
case av.LayoutTypeTable:
|
||||
for _, col := range firstView.Table.Columns {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{ID: col.ID})
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: col.ID}})
|
||||
}
|
||||
for _, rowID := range firstView.Table.RowIDs {
|
||||
view.Gallery.CardIDs = append(view.Gallery.CardIDs, rowID)
|
||||
}
|
||||
case av.LayoutTypeGallery:
|
||||
for _, field := range firstView.Gallery.CardFields {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{ID: field.ID})
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: field.ID}})
|
||||
}
|
||||
for _, cardID := range firstView.Gallery.CardIDs {
|
||||
view.Gallery.CardIDs = append(view.Gallery.CardIDs, cardID)
|
||||
|
|
@ -2743,12 +2747,14 @@ func duplicateAttributeViewKey(operation *Operation) (err error) {
|
|||
if column.ID == key.ID {
|
||||
view.Table.Columns = append(view.Table.Columns[:i+1], append([]*av.ViewTableColumn{
|
||||
{
|
||||
ID: copyKey.ID,
|
||||
Wrap: column.Wrap,
|
||||
Hidden: column.Hidden,
|
||||
Pin: column.Pin,
|
||||
Width: column.Width,
|
||||
Desc: column.Desc,
|
||||
BaseField: &av.BaseField{
|
||||
ID: copyKey.ID,
|
||||
Wrap: column.Wrap,
|
||||
Hidden: column.Hidden,
|
||||
Desc: column.Desc,
|
||||
},
|
||||
Pin: column.Pin,
|
||||
Width: column.Width,
|
||||
},
|
||||
}, view.Table.Columns[i+1:]...)...)
|
||||
break
|
||||
|
|
@ -2759,10 +2765,12 @@ func duplicateAttributeViewKey(operation *Operation) (err error) {
|
|||
if field.ID == key.ID {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields[:i+1], append([]*av.ViewGalleryCardField{
|
||||
{
|
||||
ID: copyKey.ID,
|
||||
Wrap: field.Wrap,
|
||||
Hidden: field.Hidden,
|
||||
Desc: field.Desc,
|
||||
BaseField: &av.BaseField{
|
||||
ID: copyKey.ID,
|
||||
Wrap: field.Wrap,
|
||||
Hidden: field.Hidden,
|
||||
Desc: field.Desc,
|
||||
},
|
||||
},
|
||||
}, view.Gallery.CardFields[i+1:]...)...)
|
||||
break
|
||||
|
|
@ -3245,39 +3253,39 @@ func AddAttributeViewKey(avID, keyID, keyName, keyType, keyIcon, previousKeyID s
|
|||
if "" == previousKeyID {
|
||||
if av.LayoutTypeGallery == currentView.LayoutType {
|
||||
// 如果当前视图是画廊视图则添加到最后
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: key.ID})
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: key.ID}})
|
||||
} else {
|
||||
view.Table.Columns = append([]*av.ViewTableColumn{{ID: key.ID}}, view.Table.Columns...)
|
||||
view.Table.Columns = append([]*av.ViewTableColumn{{BaseField: &av.BaseField{ID: key.ID}}}, view.Table.Columns...)
|
||||
}
|
||||
} else {
|
||||
added := false
|
||||
for i, column := range view.Table.Columns {
|
||||
if column.ID == previousKeyID {
|
||||
view.Table.Columns = append(view.Table.Columns[:i+1], append([]*av.ViewTableColumn{{ID: key.ID}}, view.Table.Columns[i+1:]...)...)
|
||||
view.Table.Columns = append(view.Table.Columns[:i+1], append([]*av.ViewTableColumn{{BaseField: &av.BaseField{ID: key.ID}}}, view.Table.Columns[i+1:]...)...)
|
||||
added = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !added {
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: key.ID})
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: key.ID}})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if nil != view.Gallery {
|
||||
if "" == previousKeyID {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{ID: key.ID})
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: key.ID}})
|
||||
} else {
|
||||
added := false
|
||||
for i, field := range view.Gallery.CardFields {
|
||||
if field.ID == previousKeyID {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields[:i+1], append([]*av.ViewGalleryCardField{{ID: key.ID}}, view.Gallery.CardFields[i+1:]...)...)
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields[:i+1], append([]*av.ViewGalleryCardField{{BaseField: &av.BaseField{ID: key.ID}}}, view.Gallery.CardFields[i+1:]...)...)
|
||||
added = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !added {
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{ID: key.ID})
|
||||
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: key.ID}})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3403,7 +3403,7 @@ func getAttrViewTable(attrView *av.AttributeView, view *av.View, query string) (
|
|||
case av.LayoutTypeGallery:
|
||||
view.Table = av.NewLayoutTable()
|
||||
for _, field := range view.Gallery.CardFields {
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: field.ID})
|
||||
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: field.ID}})
|
||||
}
|
||||
for _, cardID := range view.Gallery.CardIDs {
|
||||
view.Table.RowIDs = append(view.Table.RowIDs, cardID)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue