2023-07-02 20:52:16 +08:00
import { transaction } from "../../wysiwyg/transaction" ;
import { fetchPost } from "../../../util/fetch" ;
2023-07-02 21:53:02 +08:00
import { addCol } from "./addCol" ;
import { getColIconByType } from "./col" ;
2023-07-03 12:39:39 +08:00
import { setPosition } from "../../../util/setPosition" ;
2023-07-03 16:03:52 +08:00
import { Menu } from "../../../plugin/Menu" ;
2023-07-06 22:47:05 +08:00
import { hasClosestByClassName } from "../../util/hasClosest" ;
2023-07-02 20:52:16 +08:00
2023-07-06 18:56:16 +08:00
export const openMenuPanel = ( protyle : IProtyle , blockElement : HTMLElement , type : "properties" | "config" | "sorts" | "filters" = "config" ) = > {
2023-07-03 12:49:35 +08:00
let avPanelElement = document . querySelector ( ".av__panel" ) ;
if ( avPanelElement ) {
avPanelElement . remove ( ) ;
2023-07-02 20:52:16 +08:00
return ;
}
window . siyuan . menus . menu . remove ( ) ;
2023-07-02 23:59:01 +08:00
const avId = blockElement . getAttribute ( "data-av-id" ) ;
2023-07-02 21:53:02 +08:00
fetchPost ( "/api/av/renderAttributeView" , { id : avId } , ( response ) = > {
const data = response . data . av as IAV ;
2023-07-02 23:59:01 +08:00
let html ;
2023-07-02 20:52:16 +08:00
if ( type === "config" ) {
2023-07-03 12:39:39 +08:00
html = getConfigHTML ( data ) ;
2023-07-02 20:52:16 +08:00
} else if ( type === "properties" ) {
2023-07-03 12:39:39 +08:00
html = getPropertiesHTML ( data ) ;
2023-07-03 12:25:02 +08:00
} else if ( type === "sorts" ) {
2023-07-03 12:39:39 +08:00
html = getSortsHTML ( data ) ;
2023-07-06 18:56:16 +08:00
} else if ( type === "filters" ) {
html = getFiltersHTML ( data ) ;
2023-07-02 20:52:16 +08:00
}
2023-07-03 12:49:35 +08:00
document . body . insertAdjacentHTML ( "beforeend" , ` <div class="av__panel">
< div class = "b3-dialog__scrim" data-type = "close" > < / div >
< div class = "b3-menu" > $ { html } < / div >
< / div > ` );
2023-07-03 12:39:39 +08:00
2023-07-03 12:49:35 +08:00
avPanelElement = document . querySelector ( ".av__panel" ) ;
const menuElement = avPanelElement . lastElementChild as HTMLElement ;
2023-07-03 12:39:39 +08:00
const tabRect = blockElement . querySelector ( ".layout-tab-bar" ) . getBoundingClientRect ( ) ;
2023-07-03 12:49:35 +08:00
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-03 12:39:39 +08:00
2023-07-03 20:54:57 +08:00
bindSortsEvent ( protyle , menuElement , data ) ;
2023-07-03 12:49:35 +08:00
avPanelElement . addEventListener ( "click" , ( event ) = > {
2023-07-02 20:52:16 +08:00
event . preventDefault ( ) ;
let target = event . target as HTMLElement ;
2023-07-03 12:49:35 +08:00
while ( target && ! target . isSameNode ( avPanelElement ) ) {
2023-07-02 20:52:16 +08:00
const type = target . dataset . type ;
if ( type === "close" ) {
2023-07-03 12:49:35 +08:00
avPanelElement . remove ( ) ;
2023-07-03 20:54:57 +08:00
window . siyuan . menus . menu . remove ( ) ;
2023-07-02 21:53:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "goConfig" ) {
2023-07-03 12:49:35 +08:00
menuElement . innerHTML = getConfigHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-02 21:53:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "goProperties" ) {
2023-07-03 12:49:35 +08:00
menuElement . innerHTML = getPropertiesHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-02 21:53:02 +08:00
event . stopPropagation ( ) ;
break ;
2023-07-03 12:25:02 +08:00
} else if ( type === "goSorts" ) {
2023-07-03 12:49:35 +08:00
menuElement . innerHTML = getSortsHTML ( data ) ;
2023-07-03 20:54:57 +08:00
bindSortsEvent ( protyle , menuElement , data ) ;
2023-07-03 12:49:35 +08:00
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-03 12:25:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "removeSorts" ) {
2023-07-03 16:03:52 +08:00
transaction ( protyle , [ {
action : "setAttrView" ,
id : avId ,
data : {
sorts : [ ]
}
} ] , [ {
action : "setAttrView" ,
id : avId ,
data : {
sorts : data.sorts
}
} ] ) ;
data . sorts = [ ] ;
menuElement . innerHTML = getSortsHTML ( data ) ;
2023-07-03 20:54:57 +08:00
bindSortsEvent ( protyle , menuElement , data ) ;
2023-07-03 16:03:52 +08:00
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-03 12:25:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "addSort" ) {
2023-07-03 16:03:52 +08:00
addSort ( { data , rect : target.getBoundingClientRect ( ) , menuElement , tabRect , avId , protyle } ) ;
2023-07-03 12:25:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "removeSort" ) {
2023-07-03 20:54:57 +08:00
const oldSorts = Object . assign ( [ ] , data . sorts ) ;
data . sorts . find ( ( item : IAVSort , index : number ) = > {
if ( item . column === target . parentElement . dataset . id ) {
data . sorts . splice ( index , 1 ) ;
return true ;
}
} ) ;
transaction ( protyle , [ {
action : "setAttrView" ,
id : avId ,
data : {
sorts : data.sorts
}
} ] , [ {
action : "setAttrView" ,
id : avId ,
data : {
sorts : oldSorts
}
} ] ) ;
menuElement . innerHTML = getSortsHTML ( data ) ;
bindSortsEvent ( protyle , menuElement , data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-03 12:25:02 +08:00
event . stopPropagation ( ) ;
break ;
2023-07-06 18:56:16 +08:00
} else if ( type === "goFilters" ) {
menuElement . innerHTML = getFiltersHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
event . stopPropagation ( ) ;
break ;
} else if ( type === "removeFilters" ) {
transaction ( protyle , [ {
action : "setAttrView" ,
id : avId ,
data : {
2023-07-06 21:52:34 +08:00
filters : [ ]
2023-07-06 18:56:16 +08:00
}
} ] , [ {
action : "setAttrView" ,
id : avId ,
data : {
2023-07-06 21:52:34 +08:00
filters : data.filters
2023-07-06 18:56:16 +08:00
}
} ] ) ;
data . filters = [ ] ;
menuElement . innerHTML = getFiltersHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
event . stopPropagation ( ) ;
break ;
} else if ( type === "addFilter" ) {
addFilter ( { data , rect : target.getBoundingClientRect ( ) , menuElement , tabRect , avId , protyle } ) ;
event . stopPropagation ( ) ;
break ;
} else if ( type === "removeFilter" ) {
const oldFilters = Object . assign ( [ ] , data . filters ) ;
data . filters . find ( ( item : IAVFilter , index : number ) = > {
if ( item . column === target . parentElement . dataset . id ) {
data . filters . splice ( index , 1 ) ;
return true ;
}
} ) ;
transaction ( protyle , [ {
action : "setAttrView" ,
id : avId ,
data : {
2023-07-06 22:47:05 +08:00
filters : data.filters
2023-07-06 18:56:16 +08:00
}
} ] , [ {
action : "setAttrView" ,
id : avId ,
data : {
2023-07-06 22:47:05 +08:00
filters : oldFilters
2023-07-06 18:56:16 +08:00
}
} ] ) ;
menuElement . innerHTML = getFiltersHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
event . stopPropagation ( ) ;
break ;
2023-07-06 21:52:34 +08:00
} else if ( type === "setFilter" ) {
setFilter ( protyle , data , target ) ;
event . stopPropagation ( ) ;
break ;
2023-07-02 21:53:02 +08:00
} else if ( type === "newCol" ) {
2023-07-03 12:49:35 +08:00
avPanelElement . remove ( ) ;
2023-07-02 21:53:02 +08:00
const addMenu = addCol ( protyle , blockElement ) ;
addMenu . open ( {
x : tabRect.right ,
y : tabRect.bottom ,
h : tabRect.height ,
isLeft : true
} ) ;
event . stopPropagation ( ) ;
break ;
} else if ( type === "showAllCol" ) {
2023-07-02 23:59:01 +08:00
const doOperations : IOperation [ ] = [ ] ;
const undoOperations : IOperation [ ] = [ ] ;
2023-07-02 22:18:21 +08:00
data . columns . forEach ( ( item : IAVColumn ) = > {
if ( item . hidden ) {
doOperations . push ( {
action : "setAttrViewColHidden" ,
id : item.id ,
parentID : avId ,
data : false
2023-07-02 23:59:01 +08:00
} ) ;
2023-07-02 22:18:21 +08:00
undoOperations . push ( {
action : "setAttrViewColHidden" ,
id : item.id ,
parentID : avId ,
data : true
2023-07-02 23:59:01 +08:00
} ) ;
item . hidden = false ;
2023-07-02 22:18:21 +08:00
}
2023-07-02 23:59:01 +08:00
} ) ;
2023-07-02 22:18:21 +08:00
if ( doOperations . length > 0 ) {
transaction ( protyle , doOperations , undoOperations ) ;
2023-07-03 12:49:35 +08:00
menuElement . innerHTML = getPropertiesHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-02 22:18:21 +08:00
}
2023-07-02 21:53:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "hideAllCol" ) {
2023-07-02 23:59:01 +08:00
const doOperations : IOperation [ ] = [ ] ;
const undoOperations : IOperation [ ] = [ ] ;
2023-07-02 22:18:21 +08:00
data . columns . forEach ( ( item : IAVColumn ) = > {
if ( ! item . hidden && item . type !== "block" ) {
doOperations . push ( {
action : "setAttrViewColHidden" ,
id : item.id ,
parentID : avId ,
data : true
2023-07-02 23:59:01 +08:00
} ) ;
2023-07-02 22:18:21 +08:00
undoOperations . push ( {
action : "setAttrViewColHidden" ,
id : item.id ,
parentID : avId ,
data : false
2023-07-02 23:59:01 +08:00
} ) ;
item . hidden = true ;
2023-07-02 22:18:21 +08:00
}
2023-07-02 23:59:01 +08:00
} ) ;
2023-07-02 22:18:21 +08:00
if ( doOperations . length > 0 ) {
transaction ( protyle , doOperations , undoOperations ) ;
2023-07-03 12:49:35 +08:00
menuElement . innerHTML = getPropertiesHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-02 22:18:21 +08:00
}
2023-07-02 21:53:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "hideCol" ) {
const colId = target . getAttribute ( "data-id" ) ;
transaction ( protyle , [ {
action : "setAttrViewColHidden" ,
id : colId ,
parentID : avId ,
data : true
} ] , [ {
action : "setAttrViewColHidden" ,
id : colId ,
parentID : avId ,
data : false
} ] ) ;
data . columns . find ( ( item : IAVColumn ) = > item . id === colId ) . hidden = true ;
2023-07-03 12:49:35 +08:00
menuElement . innerHTML = getPropertiesHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-02 21:53:02 +08:00
event . stopPropagation ( ) ;
break ;
} else if ( type === "showCol" ) {
const colId = target . getAttribute ( "data-id" ) ;
transaction ( protyle , [ {
action : "setAttrViewColHidden" ,
id : colId ,
parentID : avId ,
data : false
} ] , [ {
action : "setAttrViewColHidden" ,
id : colId ,
parentID : avId ,
data : true
} ] ) ;
data . columns . find ( ( item : IAVColumn ) = > item . id === colId ) . hidden = false ;
2023-07-03 12:49:35 +08:00
menuElement . innerHTML = getPropertiesHTML ( data ) ;
setPosition ( menuElement , tabRect . right - menuElement . clientWidth , tabRect . bottom , tabRect . height ) ;
2023-07-02 21:53:02 +08:00
event . stopPropagation ( ) ;
2023-07-02 20:52:16 +08:00
break ;
}
target = target . parentElement ;
}
} ) ;
} ) ;
2023-07-02 23:59:01 +08:00
} ;
2023-07-02 21:53:02 +08:00
2023-07-06 18:56:16 +08:00
const addSort = ( options : {
data : IAV ,
rect : DOMRect ,
menuElement : HTMLElement ,
tabRect : DOMRect ,
avId : string ,
protyle : IProtyle
} ) = > {
const menu = new Menu ( "av-add-sort" ) ;
options . data . columns . forEach ( ( column ) = > {
let hasSort = false ;
options . data . sorts . find ( ( sort ) = > {
if ( sort . column === column . id ) {
hasSort = true ;
return true ;
}
} ) ;
if ( ! hasSort ) {
menu . addItem ( {
label : column.name ,
icon : getColIconByType ( column . type ) ,
click : ( ) = > {
const oldSorts = Object . assign ( [ ] , options . data . sorts ) ;
options . data . sorts . push ( {
column : column.id ,
order : "ASC" ,
} ) ;
transaction ( options . protyle , [ {
action : "setAttrView" ,
id : options.avId ,
data : {
sorts : options.data.sorts
}
} ] , [ {
action : "setAttrView" ,
id : options.avId ,
data : {
sorts : oldSorts
}
} ] ) ;
options . menuElement . innerHTML = getSortsHTML ( options . data ) ;
bindSortsEvent ( options . protyle , options . menuElement , options . data ) ;
setPosition ( options . menuElement , options . tabRect . right - options . menuElement . clientWidth , options . tabRect . bottom , options . tabRect . height ) ;
}
} ) ;
}
} ) ;
menu . open ( {
x : options.rect.left ,
y : options.rect.bottom ,
h : options.rect.height ,
} ) ;
2023-07-02 23:59:01 +08:00
} ;
2023-07-02 21:53:02 +08:00
2023-07-03 20:54:57 +08:00
const bindSortsEvent = ( protyle : IProtyle , menuElement : HTMLElement , data : IAV ) = > {
menuElement . querySelectorAll ( "select" ) . forEach ( ( item : HTMLSelectElement ) = > {
2023-07-04 09:20:55 +08:00
item . addEventListener ( "change" , ( ) = > {
2023-07-03 20:54:57 +08:00
const colId = item . parentElement . getAttribute ( "data-id" ) ;
const oldSort = JSON . parse ( JSON . stringify ( data . sorts ) ) ;
if ( item . previousElementSibling . classList . contains ( "b3-menu__icon" ) ) {
data . sorts . find ( ( sort : IAVSort ) = > {
if ( sort . column === colId ) {
2023-07-04 09:20:55 +08:00
sort . column = item . value ;
2023-07-03 20:54:57 +08:00
item . parentElement . setAttribute ( "data-id" , item . value ) ;
2023-07-04 09:20:55 +08:00
return true ;
2023-07-03 20:54:57 +08:00
}
} ) ;
} else {
data . sorts . find ( ( sort : IAVSort ) = > sort . column === colId ) . order = item . value as "ASC" | "DESC" ;
}
transaction ( protyle , [ {
action : "setAttrView" ,
id : data.id ,
data : {
sorts : data.sorts
}
} ] , [ {
action : "setAttrView" ,
id : data.id ,
data : {
sorts : oldSort
}
} ] ) ;
} ) ;
} ) ;
2023-07-04 09:20:55 +08:00
} ;
2023-07-03 20:54:57 +08:00
2023-07-03 12:39:39 +08:00
const getSortsHTML = ( data : IAV ) = > {
2023-07-03 12:25:02 +08:00
let html = "" ;
const genSortItem = ( id : string ) = > {
2023-07-04 09:20:55 +08:00
let sortHTML = "" ;
2023-07-03 12:25:02 +08:00
data . columns . forEach ( ( item ) = > {
2023-07-04 09:20:55 +08:00
sortHTML += ` <option value=" ${ item . id } " ${ item . id === id ? "selected" : "" } > ${ item . name } </option> ` ;
} ) ;
2023-07-03 16:04:51 +08:00
return sortHTML ;
2023-07-04 09:20:55 +08:00
} ;
2023-07-03 12:25:02 +08:00
data . sorts . forEach ( ( item : IAVSort ) = > {
2023-07-03 20:54:57 +08:00
html += ` <button class="b3-menu__item" data-id=" ${ item . column } ">
2023-07-03 12:25:02 +08:00
< svg class = "b3-menu__icon" > < use xlink : href = "#iconDrag" > < / use > < / svg >
2023-07-03 19:07:41 +08:00
< select class = "b3-select" style = "width: 106px;margin: 4px 0" >
2023-07-03 12:25:02 +08:00
$ { genSortItem ( item . column ) }
< / select >
2023-07-03 19:07:41 +08:00
< span class = "fn__space" > < / span >
< select class = "b3-select" style = "width: 106px;margin: 4px 0" >
2023-07-04 20:56:16 +08:00
< option value = "ASC" $ { item.order = = = "ASC" ? "selected" : "" } > $ { window . siyuan . languages . asc } < / option >
< option value = "DESC" $ { item.order = = = "DESC" ? "selected" : "" } > $ { window . siyuan . languages . desc } < / option >
2023-07-03 12:25:02 +08:00
< / select >
< svg class = "b3-menu__action" data-type = "removeSort" > < use xlink : href = "#iconTrashcan" > < / use > < / svg >
< / button > ` ;
} ) ;
2023-07-03 12:49:35 +08:00
return ` <button class="b3-menu__item" data-type="nobg">
< span class = "block__icon" style = "padding: 8px;margin-left: -4px;" data-type = "goConfig" >
< svg > < use xlink : href = "#iconLeft" > < / use > < / svg >
< / span >
< span class = "b3-menu__label ft__center" > $ { window . siyuan . languages . sort } < / span >
< svg class = "b3-menu__action" data-type = "close" style = "opacity: 1" > < use xlink : href = "#iconCloseRound" > < / use > < / svg >
< / button >
< button class = "b3-menu__separator" > < / button >
$ { html }
2023-07-03 20:54:57 +08:00
< button class = "b3-menu__item${data.sorts.length === data.columns.length ? " fn__none " : " "}" data-type = "addSort" >
2023-07-03 12:49:35 +08:00
< svg class = "b3-menu__icon" > < use xlink : href = "#iconAdd" > < / use > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . new } < / span >
< / button >
< button class = "b3-menu__item${html ? " " : " fn__none "}" data-type = "removeSorts" >
< svg class = "b3-menu__icon" > < use xlink : href = "#iconTrashcan" > < / use > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . delete } < / span >
< / button > ` ;
2023-07-04 09:20:55 +08:00
} ;
2023-07-03 12:25:02 +08:00
2023-07-06 21:52:34 +08:00
const setFilter = ( protyle : IProtyle , data : IAV , target : HTMLElement ) = > {
2023-07-06 22:20:13 +08:00
const colType = target . getAttribute ( "data-coltype" ) as TAVCol ;
2023-07-06 21:52:34 +08:00
const menu = new Menu ( undefined , ( ) = > {
const colId = target . parentElement . parentElement . getAttribute ( "data-id" ) ;
const oldFilters = JSON . parse ( JSON . stringify ( data . filters ) ) ;
data . filters . find ( ( filter ) = > {
if ( filter . column === colId ) {
2023-07-06 22:20:13 +08:00
filter . value [ colType ] = {
2023-07-06 22:47:05 +08:00
content : textElement.value
2023-07-06 21:52:34 +08:00
} ;
filter . operator = ( window . siyuan . menus . menu . element . querySelector ( ".b3-select" ) as HTMLSelectElement ) . value as TAVFilterOperator ;
return true ;
}
} ) ;
transaction ( protyle , [ {
action : "setAttrView" ,
id : data.id ,
data : {
filters : data.filters
}
} ] , [ {
action : "setAttrView" ,
id : data.id ,
data : {
filters : oldFilters
}
} ] ) ;
2023-07-06 22:48:37 +08:00
const menuElement = hasClosestByClassName ( target , "b3-menu" ) ;
2023-07-06 22:47:05 +08:00
if ( menuElement ) {
menuElement . innerHTML = getFiltersHTML ( data ) ;
}
2023-07-06 21:52:34 +08:00
} ) ;
let selectHTML = "" ;
2023-07-06 22:48:37 +08:00
const filterOperation = target . getAttribute ( "data-op" ) ;
2023-07-06 22:20:13 +08:00
switch ( colType ) {
2023-07-06 21:52:34 +08:00
case "text" :
2023-07-06 22:47:05 +08:00
selectHTML = ` <option ${ "=" === filterOperation ? "selected" : "" } value="="> ${ window . siyuan . languages . filterOperatorIs } </option>
< option $ { "!=" = = = filterOperation ? "selected" : "" } value = "!=" > $ { window . siyuan . languages . filterOperatorIsNot } < / option >
< option $ { "Contains" = = = filterOperation ? "selected" : "" } value = "Contains" > $ { window . siyuan . languages . filterOperatorContains } < / option >
< option $ { "Does not contains" = = = filterOperation ? "selected" : "" } value = "Does not contains" > $ { window . siyuan . languages . filterOperatorDoesNotContain } < / option >
< option $ { "Starts with" = = = filterOperation ? "selected" : "" } value = "Starts with" > $ { window . siyuan . languages . filterOperatorStartsWith } < / option >
< option $ { "Ends with" = = = filterOperation ? "selected" : "" } value = "Ends with" > $ { window . siyuan . languages . filterOperatorEndsWith } < / option >
< option $ { "Is empty" = = = filterOperation ? "selected" : "" } value = "Is empty" > $ { window . siyuan . languages . filterOperatorIsEmpty } < / option >
< option $ { "Is not empty" = = = filterOperation ? "selected" : "" } value = "Is not empty" > $ { window . siyuan . languages . filterOperatorIsNotEmpty } < / option >
2023-07-06 21:52:34 +08:00
` ;
break ;
}
menu . addItem ( {
iconHTML : "" ,
label : ` <select class="b3-select fn__size200"> ${ selectHTML } </select> `
2023-07-06 22:48:37 +08:00
} ) ;
2023-07-06 21:52:34 +08:00
menu . addItem ( {
iconHTML : "" ,
2023-07-06 22:47:05 +08:00
label : ` <input value=" ${ target . getAttribute ( "data-value" ) } " class="b3-text-field fn__size200"> `
2023-07-06 22:48:37 +08:00
} ) ;
const textElement = ( window . siyuan . menus . menu . element . querySelector ( ".b3-text-field" ) as HTMLInputElement ) ;
2023-07-06 22:47:05 +08:00
textElement . addEventListener ( "keydown" , ( event ) = > {
if ( event . isComposing ) {
event . preventDefault ( ) ;
return ;
}
if ( event . key === "Enter" ) {
menu . close ( ) ;
event . preventDefault ( ) ;
}
2023-07-06 22:48:37 +08:00
} ) ;
2023-07-06 21:52:34 +08:00
const rectTarget = target . getBoundingClientRect ( ) ;
2023-07-06 22:47:05 +08:00
menu . open ( { x : rectTarget.left , y : rectTarget.bottom } ) ;
textElement . select ( ) ;
2023-07-06 22:48:37 +08:00
} ;
2023-07-06 21:52:34 +08:00
2023-07-06 18:56:16 +08:00
const addFilter = ( options : {
data : IAV ,
rect : DOMRect ,
menuElement : HTMLElement ,
tabRect : DOMRect ,
avId : string ,
protyle : IProtyle
} ) = > {
2023-07-06 19:47:17 +08:00
const menu = new Menu ( "av-add-filter" ) ;
options . data . columns . forEach ( ( column ) = > {
let hasFilter = false ;
options . data . filters . find ( ( filter ) = > {
if ( filter . column === column . id ) {
hasFilter = true ;
return true ;
}
} ) ;
if ( ! hasFilter ) {
menu . addItem ( {
label : column.name ,
icon : getColIconByType ( column . type ) ,
click : ( ) = > {
const oldFilters = Object . assign ( [ ] , options . data . filters ) ;
options . data . filters . push ( {
column : column.id ,
operator : "Contains" ,
2023-07-06 22:20:13 +08:00
value : {
[ column . type ] : {
content : ""
}
} ,
2023-07-06 19:47:17 +08:00
} ) ;
transaction ( options . protyle , [ {
action : "setAttrView" ,
id : options.avId ,
data : {
filters : options.data.filters
}
} ] , [ {
action : "setAttrView" ,
id : options.avId ,
data : {
filters : oldFilters
}
} ] ) ;
options . menuElement . innerHTML = getFiltersHTML ( options . data ) ;
setPosition ( options . menuElement , options . tabRect . right - options . menuElement . clientWidth , options . tabRect . bottom , options . tabRect . height ) ;
2023-07-06 22:47:05 +08:00
setFilter ( options . protyle , options . data , options . menuElement . querySelector ( ` [data-id=" ${ column . id } "] .b3-chip ` ) ) ;
2023-07-06 19:47:17 +08:00
}
} ) ;
}
} ) ;
menu . open ( {
x : options.rect.left ,
y : options.rect.bottom ,
h : options.rect.height ,
} ) ;
2023-07-06 22:48:37 +08:00
} ;
2023-07-06 18:56:16 +08:00
const getFiltersHTML = ( data : IAV ) = > {
let html = "" ;
2023-07-06 21:52:34 +08:00
const genFilterItem = ( filter : IAVFilter ) = > {
2023-07-06 18:56:16 +08:00
let filterHTML = "" ;
2023-07-06 21:52:34 +08:00
data . columns . find ( ( item ) = > {
if ( item . id === filter . column ) {
2023-07-06 22:47:05 +08:00
const filterValue = ( filter . value && filter . value [ item . type ] && filter . value [ item . type ] . content ) ? filter . value [ item . type ] . content : "" ;
filterHTML += ` <span data-type="setFilter" data-coltype=" ${ item . type } " data-op=" ${ filter . operator } " data-value=" ${ filterValue } " class="b3-chip ${ filterValue ? " b3-chip--primary" : "" } ">
2023-07-06 21:52:34 +08:00
< svg > < use xlink : href = "#${getColIconByType(item.type)}" > < / use > < / svg >
2023-07-06 22:47:05 +08:00
< span class = "fn__ellipsis" > $ { item . name } $ { filterValue ? ": " + filterValue : "" } < / span >
2023-07-06 21:52:34 +08:00
< / span > ` ;
2023-07-06 22:48:37 +08:00
return true ;
2023-07-06 21:52:34 +08:00
}
2023-07-06 18:56:16 +08:00
} ) ;
return filterHTML ;
} ;
data . filters . forEach ( ( item : IAVFilter ) = > {
2023-07-06 21:52:34 +08:00
html += ` <button class="b3-menu__item" data-type="nobg" data-id=" ${ item . column } ">
2023-07-06 18:56:16 +08:00
< svg class = "b3-menu__icon" > < use xlink : href = "#iconDrag" > < / use > < / svg >
2023-07-06 21:52:34 +08:00
< div class = "fn__flex-1" > $ { genFilterItem ( item ) } < / div >
2023-07-06 18:56:16 +08:00
< svg class = "b3-menu__action" data-type = "removeFilter" > < use xlink : href = "#iconTrashcan" > < / use > < / svg >
< / button > ` ;
} ) ;
return ` <button class="b3-menu__item" data-type="nobg">
< span class = "block__icon" style = "padding: 8px;margin-left: -4px;" data-type = "goConfig" >
< svg > < use xlink : href = "#iconLeft" > < / use > < / svg >
< / span >
< span class = "b3-menu__label ft__center" > $ { window . siyuan . languages . filter } < / span >
< svg class = "b3-menu__action" data-type = "close" style = "opacity: 1" > < use xlink : href = "#iconCloseRound" > < / use > < / svg >
< / button >
< button class = "b3-menu__separator" > < / button >
$ { html }
< button class = "b3-menu__item${data.filters.length === data.columns.length ? " fn__none " : " "}" data-type = "addFilter" >
< svg class = "b3-menu__icon" > < use xlink : href = "#iconAdd" > < / use > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . new } < / span >
< / button >
< button class = "b3-menu__item${html ? " " : " fn__none "}" data-type = "removeFilters" >
< svg class = "b3-menu__icon" > < use xlink : href = "#iconTrashcan" > < / use > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . delete } < / span >
< / button > ` ;
} ;
2023-07-03 12:39:39 +08:00
const getPropertiesHTML = ( data : IAV ) = > {
2023-07-02 21:53:02 +08:00
let showHTML = "" ;
let hideHTML = "" ;
data . columns . forEach ( ( item : IAVColumn ) = > {
if ( item . hidden ) {
hideHTML += ` <button class="b3-menu__item">
< svg class = "b3-menu__icon" > < use xlink : href = "#${getColIconByType(item.type)}" > < / use > < / svg >
< span class = "b3-menu__label" > $ { item . name } < / span >
< svg class = "b3-menu__action" data-type = "showCol" data-id = "${item.id}" > < use xlink : href = "#iconEyeoff" > < / use > < / svg >
2023-07-02 23:59:01 +08:00
< / button > ` ;
2023-07-02 21:53:02 +08:00
} else {
showHTML += ` <button class="b3-menu__item">
< svg class = "b3-menu__icon" > < use xlink : href = "#${getColIconByType(item.type)}" > < / use > < / svg >
< span class = "b3-menu__label" > $ { item . name } < / span >
< svg class = "b3-menu__action${item.type === " block " ? " fn__none " : " "}" data-type = "hideCol" data-id = "${item.id}" > < use xlink : href = "#iconEye" > < / use > < / svg >
2023-07-02 23:59:01 +08:00
< / button > ` ;
2023-07-02 21:53:02 +08:00
}
} ) ;
if ( hideHTML ) {
hideHTML = ` <button class="b3-menu__separator"></button>
2023-07-02 22:18:21 +08:00
< button class = "b3-menu__item" data-type = "nobg" >
< span class = "b3-menu__label" >
$ { window . siyuan . languages . hideCol }
< / span >
< span class = "block__icon" data-type = "showAllCol" >
$ { window . siyuan . languages . showAll }
< span class = "fn__space" > < / span >
< svg > < use xlink : href = "#iconEye" > < / use > < / svg >
< / span >
2023-07-02 21:53:02 +08:00
< / button >
$ { hideHTML } ` ;
}
2023-07-03 12:49:35 +08:00
return ` <button class="b3-menu__item" data-type="nobg">
< span class = "block__icon" style = "padding: 8px;margin-left: -4px;" data-type = "goConfig" >
< svg > < use xlink : href = "#iconLeft" > < / use > < / svg >
< / span >
< span class = "b3-menu__label ft__center" > $ { window . siyuan . languages . attr } < / span >
< svg class = "b3-menu__action" data-type = "close" style = "opacity: 1" > < use xlink : href = "#iconCloseRound" > < / use > < / svg >
< / button >
< button class = "b3-menu__separator" > < / button >
< button class = "b3-menu__item" data-type = "nobg" >
< span class = "b3-menu__label" >
$ { window . siyuan . languages . showCol }
< / span >
< span class = "block__icon" data-type = "hideAllCol" >
$ { window . siyuan . languages . hideAll }
< span class = "fn__space" > < / span >
< svg > < use xlink : href = "#iconEyeoff" > < / use > < / svg >
< / span >
< / button >
$ { showHTML }
$ { hideHTML }
< button class = "b3-menu__separator" > < / button >
< button class = "b3-menu__item" data-type = "newCol" >
< svg class = "b3-menu__icon" > < use xlink : href = "#iconAdd" > < / use > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . new } < / span >
< / button > ` ;
2023-07-02 23:59:01 +08:00
} ;
2023-07-03 16:03:52 +08:00
2023-07-06 18:56:16 +08:00
const getConfigHTML = ( data : IAV ) = > {
return ` <button class="b3-menu__item" data-type="nobg">
< span class = "b3-menu__label" > $ { window . siyuan . languages . config } < / span >
< svg class = "b3-menu__action" data-type = "close" style = "opacity: 1" > < use xlink : href = "#iconCloseRound" > < / use > < / svg >
< / button >
< button class = "b3-menu__separator" > < / button >
< button class = "b3-menu__item" data-type = "goProperties" >
< svg class = "b3-menu__icon" > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . attr } < / span >
< span class = "b3-menu__accelerator" > $ { data . columns . filter ( ( item : IAVColumn ) = > ! item . hidden ) . length } / $ { data . columns . length } < / span >
< svg class = "b3-menu__icon b3-menu__icon--arrow" > < use xlink : href = "#iconRight" > < / use > < / svg >
< / button >
2023-07-06 19:47:17 +08:00
< button class = "b3-menu__item" data-type = "goFilters" >
2023-07-06 18:56:16 +08:00
< svg class = "b3-menu__icon" > < use xlink : href = "#iconFilter" > < / use > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . filter } < / span >
< span class = "b3-menu__accelerator" > $ { data . filters . length } < / span >
< svg class = "b3-menu__icon b3-menu__icon--arrow" > < use xlink : href = "#iconRight" > < / use > < / svg >
< / button >
< button class = "b3-menu__item" data-type = "goSorts" >
< svg class = "b3-menu__icon" > < use xlink : href = "#iconSort" > < / use > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . sort } < / span >
< span class = "b3-menu__accelerator" > $ { data . sorts . length } < / span >
< svg class = "b3-menu__icon b3-menu__icon--arrow" > < use xlink : href = "#iconRight" > < / use > < / svg >
< / button >
< button class = "b3-menu__item" >
< svg class = "b3-menu__icon" > < / svg >
< span class = "b3-menu__label" > $ { window . siyuan . languages . pageCount } < / span >
< span class = "b3-menu__accelerator" > 50 < / span >
< svg class = "b3-menu__icon b3-menu__icon--arrow" > < use xlink : href = "#iconRight" > < / use > < / svg >
< / button > ` ;
2023-07-04 09:20:55 +08:00
} ;