@operato/board 1.5.16 → 1.5.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@operato/board",
3
- "version": "1.5.16",
3
+ "version": "1.5.18",
4
4
  "description": "Webcomponent for board following open-wc recommendations",
5
5
  "author": "heartyoh",
6
6
  "main": "dist/src/index.js",
@@ -22,6 +22,7 @@
22
22
  "./ox-scene-property.js": "./dist/src/modeller/scene-viewer/ox-scene-property.js",
23
23
  "./ox-scene-viewer.js": "./dist/src/modeller/scene-viewer/ox-scene-viewer.js",
24
24
  "./ox-board-list.js": "./dist/src/ox-board-list.js",
25
+ "./ox-board-template-list.js": "./dist/src/ox-board-template-list.js",
25
26
  "./ox-board-viewer.js": "./dist/src/ox-board-viewer.js",
26
27
  "./ox-board-player.js": "./dist/src/ox-board-player.js",
27
28
  "./ox-board-modeller.js": "./dist/src/ox-board-modeller.js",
@@ -48,6 +49,9 @@
48
49
  "ox-board-list.js": [
49
50
  "./dist/src/ox-board-list.d.ts"
50
51
  ],
52
+ "ox-board-template-list.js": [
53
+ "./dist/src/ox-board-template-list.d.ts"
54
+ ],
51
55
  "ox-board-viewer.js": [
52
56
  "./dist/src/ox-board-viewer.d.ts"
53
57
  ],
@@ -88,16 +92,16 @@
88
92
  },
89
93
  "dependencies": {
90
94
  "@open-wc/scoped-elements": "^2.0.0-next.6",
91
- "@operato/app": "^1.5.16",
92
- "@operato/data-grist": "^1.5.16",
93
- "@operato/font": "^1.5.16",
95
+ "@operato/app": "^1.5.18",
96
+ "@operato/data-grist": "^1.5.17",
97
+ "@operato/font": "^1.5.18",
94
98
  "@operato/graphql": "^1.4.76",
95
99
  "@operato/i18n": "^1.5.14",
96
100
  "@operato/input": "^1.5.14",
97
101
  "@operato/layout": "^1.5.15",
98
102
  "@operato/markdown": "^1.4.64",
99
103
  "@operato/popup": "^1.5.13",
100
- "@operato/property-editor": "^1.5.16",
104
+ "@operato/property-editor": "^1.5.17",
101
105
  "@operato/styles": "^1.4.64",
102
106
  "@operato/utils": "^1.4.64",
103
107
  "@polymer/paper-dropdown-menu": "^3.2.0",
@@ -148,5 +152,5 @@
148
152
  "prettier --write"
149
153
  ]
150
154
  },
151
- "gitHead": "5aff1de80ed25649dda3e77ff87d7b039d094f4c"
155
+ "gitHead": "a36791f6b8384021a731a3e3933f7e38a96ecb23"
152
156
  }
@@ -0,0 +1,265 @@
1
+ import '@operato/data-grist'
2
+ import '@operato/input/ox-input-file.js'
3
+
4
+ import gql from 'graphql-tag'
5
+ import { css, html, LitElement } from 'lit'
6
+ import { customElement, property, query, state } from 'lit/decorators.js'
7
+
8
+ import {
9
+ ColumnConfig,
10
+ DataGrist,
11
+ FetchOption,
12
+ FilterValue,
13
+ GristData,
14
+ GristRecord,
15
+ PaginationConfig,
16
+ SortersConfig
17
+ } from '@operato/data-grist'
18
+ import { buildArgs, client } from '@operato/graphql'
19
+ import { ScrollbarStyles, TooltipStyles } from '@operato/styles'
20
+
21
+ const FETCH_BOARD_TEMPLATE_LIST_GQL = (listParam: any) => {
22
+ return gql`
23
+ {
24
+ boardTemplates(${buildArgs(listParam)}) {
25
+ items {
26
+ id
27
+ name
28
+ description
29
+ visibility
30
+ thumbnail
31
+ }
32
+ total
33
+ }
34
+ }
35
+ `
36
+ }
37
+
38
+ const FETCH_BOARD_TEMPLATE_GQL = (id: string) => {
39
+ return gql`
40
+ {
41
+ boardTemplate(id: "${id}") {
42
+ id
43
+ name
44
+ description
45
+ visibility
46
+ model
47
+ thumbnail
48
+ }
49
+ }
50
+ `
51
+ }
52
+
53
+ @customElement('ox-board-template-list')
54
+ export class OxBoardTemplateList extends LitElement {
55
+ static styles = [
56
+ ScrollbarStyles,
57
+ TooltipStyles,
58
+ css`
59
+ :host {
60
+ display: flex;
61
+
62
+ width: 100%;
63
+
64
+ --grid-record-emphasized-background-color: red;
65
+ --grid-record-emphasized-color: yellow;
66
+ }
67
+
68
+ ox-grist {
69
+ flex: 1;
70
+ overflow-y: auto;
71
+
72
+ --grid-record-emphasized-background-color: red;
73
+ --grid-record-emphasized-color: yellow;
74
+ }
75
+
76
+ #headroom {
77
+ align-items: center;
78
+ padding: var(--padding-default) var(--padding-wide);
79
+ border-top: 2px solid rgba(0, 0, 0, 0.2);
80
+ background-color: var(--theme-white-color);
81
+ box-shadow: var(--box-shadow);
82
+ }
83
+
84
+ #filters {
85
+ display: flex;
86
+ flex-direction: row;
87
+ place-content: space-between;
88
+ margin: var(--margin-default) 0;
89
+ }
90
+
91
+ select {
92
+ border: 0;
93
+ outline: none;
94
+ text-align: right;
95
+ }
96
+
97
+ @media only screen and (max-width: 460px) {
98
+ #filters {
99
+ flex-direction: column;
100
+ }
101
+ }
102
+ `
103
+ ]
104
+
105
+ @property({ type: Boolean, attribute: 'without-search' }) withoutSearch: boolean = false
106
+
107
+ @query('ox-grist') grist!: DataGrist
108
+
109
+ render() {
110
+ return html`
111
+ <ox-grist .config=${this.gristConfig} .mode=${'CARD'} auto-fetch .fetchHandler=${this.fetchHandler.bind(this)}>
112
+ <div slot="headroom" id="headroom">
113
+ <div id="filters">
114
+ <ox-filters-form autofocus .withoutSearch=${this.withoutSearch}></ox-filters-form>
115
+ </div>
116
+ </div>
117
+ </ox-grist>
118
+ `
119
+ }
120
+
121
+ async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {
122
+ const { items: records, total } = await this.getBoardTemplates({ page, limit, filters, sortings })
123
+
124
+ return {
125
+ total,
126
+ records
127
+ }
128
+ }
129
+
130
+ get gristConfig() {
131
+ return {
132
+ list: {
133
+ thumbnail: 'thumbnail',
134
+ fields: ['name'],
135
+ details: ['description']
136
+ },
137
+ columns: [
138
+ {
139
+ type: 'string',
140
+ name: 'id',
141
+ hidden: true
142
+ },
143
+ {
144
+ type: 'string',
145
+ name: 'name',
146
+ header: 'name',
147
+ record: {
148
+ editable: true,
149
+ align: 'left'
150
+ },
151
+ width: 200,
152
+ filter: 'search',
153
+ sortable: true
154
+ },
155
+ {
156
+ type: 'string',
157
+ name: 'description',
158
+ header: 'description',
159
+ record: {
160
+ editable: true,
161
+ align: 'left'
162
+ },
163
+ width: 200,
164
+ filter: 'search'
165
+ },
166
+ {
167
+ type: 'select-buttons',
168
+ name: 'visibility',
169
+ header: 'visibility',
170
+ record: {
171
+ editable: false
172
+ },
173
+ hidden: true,
174
+ filter: {
175
+ operator: 'in',
176
+ options: ['private', 'domain', 'public'],
177
+ label: ''
178
+ }
179
+ },
180
+ {
181
+ type: 'image',
182
+ name: 'thumbnail',
183
+ hidden: true,
184
+ record: {
185
+ editable: false
186
+ }
187
+ }
188
+ ],
189
+ rows: {
190
+ appendable: false,
191
+ selectable: {
192
+ multiple: false
193
+ },
194
+ handlers: {
195
+ click: 'select-row-toggle'
196
+ }
197
+ },
198
+ sorters: [
199
+ {
200
+ name: 'name',
201
+ desc: false
202
+ }
203
+ ],
204
+ pagination: {
205
+ pages: [20, 30, 50, 100, 200]
206
+ }
207
+ }
208
+ }
209
+
210
+ async firstUpdated() {
211
+ this.refreshBoardTemplates()
212
+ }
213
+
214
+ async getSelected() {
215
+ const selected = this.grist.selected
216
+ const templateId = selected && selected[0]?.id
217
+
218
+ if (!templateId) {
219
+ return
220
+ }
221
+
222
+ var boardTemplateResponse = await client.query({
223
+ query: FETCH_BOARD_TEMPLATE_GQL(templateId)
224
+ })
225
+
226
+ var template = boardTemplateResponse.data?.boardTemplate
227
+
228
+ if (template) {
229
+ template = {
230
+ ...template,
231
+ model: JSON.parse(template.model)
232
+ }
233
+ }
234
+
235
+ return template
236
+ }
237
+
238
+ async refreshBoardTemplates() {
239
+ this.grist.fetch()
240
+ }
241
+
242
+ async getBoardTemplates({
243
+ page = 1,
244
+ limit = 30,
245
+ filters = [],
246
+ sortings = []
247
+ }: { page?: number; limit?: number; filters?: FilterValue[]; sortings?: SortersConfig } = {}) {
248
+ var pagination: PaginationConfig = {
249
+ limit,
250
+ page
251
+ }
252
+
253
+ var params = {
254
+ filters,
255
+ sortings,
256
+ pagination
257
+ }
258
+
259
+ var boardTemplateListResponse = await client.query({
260
+ query: FETCH_BOARD_TEMPLATE_LIST_GQL(params)
261
+ })
262
+
263
+ return boardTemplateListResponse?.data?.boardTemplates || {}
264
+ }
265
+ }
@@ -3,11 +3,13 @@ import '@material/mwc-textarea'
3
3
  import '@material/mwc-select'
4
4
  import '@material/mwc-list/mwc-list-item'
5
5
  import '@material/mwc-button'
6
+ import '../ox-board-template-list'
6
7
 
7
8
  import { css, html, LitElement } from 'lit'
8
- import { customElement, property } from 'lit/decorators.js'
9
+ import { customElement, property, query } from 'lit/decorators.js'
9
10
 
10
11
  import { i18next, localize } from '@operato/i18n'
12
+ import { OxBoardTemplateList } from '../ox-board-template-list'
11
13
 
12
14
  @customElement('board-creation-popup')
13
15
  export class BoardCreationPopup extends localize(i18next)(LitElement) {
@@ -17,24 +19,46 @@ export class BoardCreationPopup extends localize(i18next)(LitElement) {
17
19
  :host {
18
20
  display: flex;
19
21
  flex-direction: column;
20
-
22
+ gap: 10px;
21
23
  padding: 10px;
24
+
22
25
  background-color: white;
23
26
  }
24
27
 
25
- :host > * {
26
- margin: 10px;
28
+ [body] {
29
+ flex: 1;
30
+
31
+ display: flex;
32
+ flex-direction: row;
33
+ gap: 10px;
34
+
35
+ overflow: hidden;
27
36
  }
28
37
 
29
38
  [content] {
30
39
  flex: 1;
40
+
31
41
  display: flex;
32
42
  flex-direction: column;
43
+ gap: 10px;
44
+
33
45
  overflow: auto;
34
46
  }
35
47
 
36
- [content] > * {
37
- margin: 10px 0;
48
+ [content] > mwc-textarea {
49
+ flex: 1;
50
+ }
51
+
52
+ [templates] {
53
+ flex: 2;
54
+ display: flex;
55
+ flex-direction: column;
56
+ overflow: hidden;
57
+ }
58
+
59
+ [templates] > ox-board-template-list {
60
+ flex: 1;
61
+ overflow: hidden;
38
62
  }
39
63
  `
40
64
  ]
@@ -43,28 +67,39 @@ export class BoardCreationPopup extends localize(i18next)(LitElement) {
43
67
  @property({ type: String }) defaultGroup?: string
44
68
  @property({ type: Array }) groups?: { id: string; name: string }[]
45
69
 
70
+ @query('ox-board-template-list') boardTemplateList!: OxBoardTemplateList
71
+
46
72
  render() {
47
73
  var groups = this.groups || []
48
74
 
49
75
  return html`
50
- <div content>
51
- <mwc-textfield label=${String(i18next.t('label.name'))} name="name" required field-name></mwc-textfield>
52
- <mwc-textarea
53
- label=${String(i18next.t('label.description'))}
54
- name="description"
55
- field-description
56
- ></mwc-textarea>
57
- <mwc-select
58
- label=${String(i18next.t('label.group'))}
59
- field-group
60
- helper="If there is no group to choose, you can leave it empty."
61
- >
62
- ${groups.map(
63
- group => html`
64
- <mwc-list-item value=${group.id} ?selected=${this.defaultGroup == group.id}>${group.name}</mwc-list-item>
65
- `
66
- )}
67
- </mwc-select>
76
+ <div body>
77
+ <div content>
78
+ <mwc-textfield label=${String(i18next.t('label.name'))} name="name" required field-name></mwc-textfield>
79
+ <mwc-textarea
80
+ label=${String(i18next.t('label.description'))}
81
+ name="description"
82
+ field-description
83
+ ></mwc-textarea>
84
+ <mwc-select
85
+ label=${String(i18next.t('label.group'))}
86
+ field-group
87
+ helper="If there is no group to choose, you can leave it empty."
88
+ >
89
+ ${groups.map(
90
+ group => html`
91
+ <mwc-list-item value=${group.id} ?selected=${this.defaultGroup == group.id}
92
+ >${group.name}</mwc-list-item
93
+ >
94
+ `
95
+ )}
96
+ </mwc-select>
97
+ </div>
98
+
99
+ <div templates>
100
+ <div>${i18next.t('label.board-template')}</div>
101
+ <ox-board-template-list></ox-board-template-list>
102
+ </div>
68
103
  </div>
69
104
 
70
105
  <mwc-button
@@ -81,7 +116,7 @@ export class BoardCreationPopup extends localize(i18next)(LitElement) {
81
116
  }, 100)
82
117
  }
83
118
 
84
- onClickSubmit() {
119
+ async onClickSubmit() {
85
120
  var [name, description, groupId] = ['name', 'description', 'group'].map(attr => {
86
121
  return (this.renderRoot.querySelector(`[field-${attr}]`) as any)?.value
87
122
  })
@@ -90,12 +125,16 @@ export class BoardCreationPopup extends localize(i18next)(LitElement) {
90
125
  return
91
126
  }
92
127
 
128
+ const template = await this.boardTemplateList.getSelected()
129
+
93
130
  this.dispatchEvent(
94
131
  new CustomEvent('create-board', {
95
132
  detail: {
96
133
  name,
97
134
  description,
98
- groupId
135
+ groupId,
136
+ model: template?.model,
137
+ thumbnail: template?.thumbnail
99
138
  }
100
139
  })
101
140
  )
@@ -64,14 +64,16 @@ export class BoardCreationCard extends localize(i18next)(LitElement) {
64
64
  .defaultGroup=${this.defaultGroup}
65
65
  .groups=${this.groups}
66
66
  @create-board=${async (e: CustomEvent) => {
67
- var { name, description, groupId } = e.detail
67
+ var { name, description, groupId, model, thumbnail } = e.detail
68
68
 
69
69
  this.dispatchEvent(
70
70
  new CustomEvent('create-board', {
71
71
  detail: {
72
72
  name,
73
73
  description,
74
- groupId
74
+ groupId,
75
+ model,
76
+ thumbnail
75
77
  }
76
78
  })
77
79
  )