Перейти к содержанию

Kanban#

Kanban - контрол для визуализации и управления рабочими процессами. Добавляется внутрь контрола ViewGrid.

Внешний вид#

kanban

Принцип работы Kanban доски#

  1. Kanban имеет набор колонок, который формируется по какому-либо справочнику (для каждой записи справочника строится своя колонка).
  2. В каждой колонке отображаются определенные строки грида (далее - KanbanItem). Группировка по колонкам определяется по значению справочника колонки.
  3. При перетаскивании KanbanItem (с помощью drag and drop) в другую колонку значение справочника (в исходных данных) обновляется в соответствии с той колонкой, куда был перемещен KanbanItem.

Добавление в шаблоне#

Пример добавления шаблона и элементов:

Пример
    <ViewGrid>
    <Kanban source="./test.query.json" sourceField="name" dataField="field" dropHandler="dropHandler">
        <KanbanItem>
        <KanbanItemField dataField="name" visible="false"/>
        <KanbanGroup>
            <KanbanItemField dataField="object" objectField="name" flex="3" padding="0 3px"/>
            <KanbanItemField dataField="test" flex="2"/>
        </KanbanGroup>
         <KanbanItemField dataField="intFiled" type="number">
            <KanbanAggregate type="sum" aggregateRenderer="aggregateRenderer"/>
        </KanbanItemField>
        <KanbanButton value="button"/>
        </KanbanItem>
    </Kanban>
    <ViewGridColumn/>
    </ViewGrid>

Свойства#

columnsMinWidth#

тип знач. по умолч. допустимые значения
string 250px

Минимальная ширина для колонок. Задается в пикселях (px).

columnsMaxWidth#

тип знач. по умолч. допустимые значения
string 500px

Максимальная ширина для колонок. Задается в пикселях (px).

dataField#

тип знач. по умолч. допустимые значения
-

Поле справочника в источнике данных грида, по которому будут группироваться данные по колонкам.

source#

тип знач. по умолч. допустимые значения
import-default -

Cсылка на модель или запрос для построения колонок.

sourceField#

тип знач. по умолч. допустимые значения
-

Поле (для указаннного source), которое используется для отображения заголовка колонки.

valueMember#

тип знач. по умолч. допустимые значения
string -

Имя свойства, которое является кодом объекта справочника.

expandField#

тип знач. по умолч. допустимые значения
string -

Имя свойства из источника данных (работает только для observableArray) для биндинга, которое используется для управления внешним видом. Если свойство вернет значение true - используется расширенный вид (KanbanExtendedItem), false - используется обычный вид (KanbanItem).

toolbarVisible#

тип значение по умолчанию допустимые значения
bool true true/false

Отображение тулбара грида.

Сallback#

dropHandler#

Callback-функция, которая срабатывает после перетаскивания KanbanItem в другую колонку.

Должна вернуть Deferred. Если Deferred переходит в состояние reject, то перетаскивание отменяется. Функция принимает объект со свойствами

Cвойства
параметр тип описание
rowData object ссыслка на объект с данными для текущего KanbanItem
value string новое значение справочника (после перетаскивания)
oldValue string старое значение справочника (до перетаскивания)
Пример
<Kanban ... dropHandler="dropHandler">
dropHandler ({ rowData, value, oldValue }) {
    console.log(rowData, value, oldValue)
    if (oldValue.Name === 'begin' && value.Name === 'end') {
      this.services.dialog.error('Нельзя менять состояние begin на end')
      return $.Deferred().reject() 
    } else {
      PageBlocker.on()
      return this.adapter.save(rowData).always(() => {
        PageBlocker.off()
      })
    }
}

Методы#

setSourceParameters#

Задает параметры для запроса, который указан в свойстве source.

При вызове метода произойдет вызов запроса с переданными параметрами и пересоздание колонок на загруженных данных.

Пример
this.controls.grid.kanban.setSourceParameters({ Name: 'test' })

setSource#

Позволяет задать массив данных для построения колонок.

Пример
1
2
3
4
5
this.controls.grid1.kanban.setSource([
    { VCode: '1', Name: 'string' },
    { VCode: '2', Name: 'int' },
    { VCode: '3', Name: 'date' }
])

getFilterWindow#

Позволяет получить ссылку на окно фильтров.

Пример открытия окна фильров
this.controls.grid1.kanban.getFilterWindow().open()

Контролы#

Kanban строится на следующих контролах:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
``` xml 
<Kanban columnsMinWidth="250px" columnsMinWidth="500px" source="./kind.model.json" sourceField="Name" dataField="Kind" valueMember="VCode" dropHandler="dropHandler">
  <KanbanItem>
    <KanbanItemField dataField="VCode" align="left" linkRenderer="kanbanLinlkRenderer">
      <KanbanAggregate type="count" aggregateRenderer="aggregateRenderer"/>
    </KanbanItemField>
    <KanbanGroup>
      <KanbanItemField dataField="Name" fontSize="16px" fontColor="green"/>
      <KanbanItemField dataField="Kind" objectField="Name"/>
    </KanbanGroup>
    <KanbanItemField dataField="CDate" type="date" format="YYYY-MM-DD"/>
    <KanbanButton value="Кнопка" height="28px" clicked="buttonClicked"/>
    <KanbanGroup>
      <KanbanItemField dataField="WDate" type="date" format="YYYY-MM-DD"/>
      <KanbanButton value="b1" flex="0 0 50px"/>
      <KanbanButton value="b2" flex="0 0 50px"/>
      <KanbanButton value="b3" flex="0 0 50px"/>
    </KanbanGroup>
  </KanbanItem>
</Kanban>
```
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
``` javascript
dropHandler ({ rowData, value, oldValue }) {
    console.log(rowData, value, oldValue)
    if (oldValue.Name === 'begin' && value.Name === 'end') {
      this.services.dialog.error('Нельзя менять состояние begin на end')
      return $.Deferred().reject() 
    } else {
      PageBlocker.on()
      return this.adapter.save(rowData).always(() => {
        PageBlocker.off()
      })
    }
}

createDocument () {
  return super.createDocument('chocolateForm1')
}

aggregateRenderer (kanban, { dataField, objectField, aggType, value }) {
  console.log(this, kanban, { dataField, objectField, aggType, value })
  return `сумма: ${value}`
}

kanbanLinlkRenderer (kanban, { rowData }) {
  const kindName = (rowData.Kind() || {}).Name || ''
  return {
    url: Link.createUrl({
      route: 'view',
      params: { name: 'chocolateForm1', id: rowData.VCode() }
    }),
    text: `VCode: ${rowData.VCode()} (${kindName})`
  }
}

buttonClicked () {
  console.log('click')
}
```

Выбор значения

Пример использования в реестре#

<Form writeRoles="super" title="Реестр">
  <ToolBar>
    <Tool id="new" image="current-theme/images/leftNavBar/new.png" clicked="createDocument"/>
    <Tool id="remove" image="current-theme/images/leftNavBar/trash.png" clicked="deleteSelectedDocuments"/>
  </ToolBar>
  <Layout>
  <ViewGrid  bind="*" editorWidth="12" height="100%">
    <Kanban source="./kind.query.json" sourceField="Name" dataField="Kind" valueMember="VCode" dropHandler="dropHandler">
      <KanbanItem>
        <KanbanItemField dataField="VCode" align="center" linkRenderer="kanbanLinlkRenderer"/>
        <KanbanItemField dataField="Name" fontSize="16px" height="36px" fontColor="green"/>
        <KanbanItemField dataField="Kind" objectField="Name"/>
        <KanbanItemField dataField="Price" type="number">
          <KanbanAggregate type="avg" aggregateRenderer="aggregateRenderer"/>
        </KanbanItemField>
      </KanbanItem>
    </Kanban>
    <ViewGridColumn dataField="VCode" width="120px" format="f3" type="number"/>
    <ViewGridColumn dataField="Name" width="25%"/>
    <ViewGridObjectColumn dataField="Kind">
      <ViewGridColumnField objectField="VCode" width="120px"/>
      <ViewGridColumnField objectField="Name" width="25%"/>
    </ViewGridObjectColumn>
  </ViewGrid>
  </Layout>
</Form>
import { Registry, PageBlocker, Link } from 'ecosoft-lexema8'
import template from './myRegistry.xml'
import Chocolate from './chocolate.model.json'
import $ from 'jquery'

export default class MyRegistry extends Registry {
  // пример добавления обработчика dropHandler
  dropHandler ({ rowData, value, oldValue }) {
     (oldValue.Name === 'begin' && value.Name === 'end') {
      this.services.dialog.error('Нельзя менять состояние begin на end')
      return $.Deferred().reject()
    } else {
      PageBlocker.on()
      // сохранение данных
      return this.adapter.save(rowData).always(() => {
        PageBlocker.off()
      })
    }
  }

  createDocument () {
    return super.createDocument('chocolateForm')
  }

  // добавление ссылок
  kanbanLinlkRenderer (kanban, { rowData }) {
    const kindName = rowData.Kind().Name
    return {
      url: Link.createUrl({
        route: 'view',
        params: { name: 'chocolateForm1', id: rowData.VCode() }
      }),
      text: `VCode: ${rowData.VCode()} (${kindName})`
    }
  }

  aggregateRenderer (kanban, { dataField, objectField, aggType, value }) {
    return `Средняя цена: ${value}``
  }

  static get template () {
    return template
  }

  static get binding () {
    return Chocolate
  }
}

Пример использования в аналитческой форме#

<Form writeRoles="super" title="Form">
  <ToolBar>   
  </ToolBar>
  <Layout>
    <ViewGrid id="grid" editorWidth="12" height="100%">
      <Kanban sourceField="Name" dataField="Kind" valueMember="VCode">
        <KanbanItem>
          <KanbanItemField dataField="c1" align="center"/>
          <KanbanItemField dataField="c2" fontSize="16px" height="36px" fontColor="green"/>
          <KanbanItemField dataField="c3" objectField="Name"/>
        </KanbanItem>
      </Kanban>
      <ViewGridColumn dataField="c1" width="120px" format="f3" type="number"/>
      <ViewGridColumn dataField="c2" width="25%"/>
      <ViewGridObjectColumn dataField="c3">
        <ViewGridColumnField objectField="VCode" width="120px"/>
        <ViewGridColumnField objectField="Name" width="25%"/>
      </ViewGridObjectColumn>
    </ViewGrid>
  </Layout>
</Form>
import { BaseForm } from 'ecosoft-lexema8'
import template from './myForm.xml'

export default class MyRegistry extends Registry {
  constructor () {
    this.controls.grid1.dataSource = [
      { c1: 100, c2: 'test', c3: { VCode: '1', Name: 'string' } },
      { c1: 101, c2: 'test', c3: { VCode: '2', Name: 'int' } },
      { c1: 102, c2: 'test', c3: { VCode: '3', Name: 'date' } }
    ]

    this.controls.grid1.kanban.setSource([
      { VCode: '1', Name: 'string' },
      { VCode: '2', Name: 'int' },
      { VCode: '3', Name: 'date' }
    ])
  }

  static get template () {
    return template
  }
}

Примечания#

  • Kanban не поддерживается для ViewGrid в серверном режиме.