@things-factory/board-ui 6.1.196 → 6.2.0

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.
Files changed (28) hide show
  1. package/client/board-list/board-tile-list.ts +268 -0
  2. package/client/pages/board-player-by-name-page.ts +29 -0
  3. package/client/pages/board-player-page.ts +26 -22
  4. package/client/pages/board-viewer-by-name-page.ts +24 -0
  5. package/client/pages/board-viewer-page.ts +20 -16
  6. package/client/route.ts +8 -0
  7. package/dist-client/board-list/board-tile-list.d.ts +14 -20
  8. package/dist-client/board-list/board-tile-list.js +147 -129
  9. package/dist-client/board-list/board-tile-list.js.map +1 -1
  10. package/dist-client/pages/board-player-by-name-page.d.ts +4 -0
  11. package/dist-client/pages/board-player-by-name-page.js +32 -0
  12. package/dist-client/pages/board-player-by-name-page.js.map +1 -0
  13. package/dist-client/pages/board-player-page.d.ts +1 -0
  14. package/dist-client/pages/board-player-page.js +24 -20
  15. package/dist-client/pages/board-player-page.js.map +1 -1
  16. package/dist-client/pages/board-viewer-by-name-page.d.ts +4 -0
  17. package/dist-client/pages/board-viewer-by-name-page.js +27 -0
  18. package/dist-client/pages/board-viewer-by-name-page.js.map +1 -0
  19. package/dist-client/pages/board-viewer-page.d.ts +1 -0
  20. package/dist-client/pages/board-viewer-page.js +19 -16
  21. package/dist-client/pages/board-viewer-page.js.map +1 -1
  22. package/dist-client/pages/theme/theme-editors.d.ts +1 -1
  23. package/dist-client/route.js +6 -0
  24. package/dist-client/route.js.map +1 -1
  25. package/dist-client/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +5 -5
  27. package/things-factory.config.js +8 -0
  28. package/client/board-list/board-tile-list.js +0 -282
@@ -0,0 +1,268 @@
1
+ import '@operato/board/ox-board-creation-card.js'
2
+ import '@material/mwc-icon'
3
+
4
+ import gql from 'graphql-tag'
5
+ import { css, html, LitElement, PropertyValues } from 'lit'
6
+ import { customElement, property, state, query } from 'lit/decorators.js'
7
+ import { keyed } from 'lit/directives/keyed.js'
8
+
9
+ import { client } from '@operato/graphql'
10
+
11
+ @customElement('board-tile-list')
12
+ export class BoardTileList extends LitElement {
13
+ static styles = [
14
+ css`
15
+ :host {
16
+ overflow: auto;
17
+ padding: var(--popup-content-padding);
18
+ display: grid;
19
+
20
+ grid-template-columns: var(--card-list-template);
21
+ grid-auto-rows: var(--card-list-rows-height);
22
+ grid-gap: 20px;
23
+ --mdc-button-horizontal-padding: var(--padding-default);
24
+ }
25
+
26
+ [card] {
27
+ position: relative;
28
+ align-items: center;
29
+ overflow: hidden;
30
+ }
31
+
32
+ [card][create] {
33
+ overflow: visible;
34
+ background-color: initial;
35
+ }
36
+
37
+ [card] > a {
38
+ display: flex;
39
+ }
40
+
41
+ [card]:hover {
42
+ cursor: pointer;
43
+ }
44
+
45
+ [name] {
46
+ text-overflow: ellipsis;
47
+ white-space: nowrap;
48
+ overflow: hidden;
49
+ margin-top: var(--margin-narrow);
50
+ width: calc(100% - 45px);
51
+ color: var(--primary-text-color);
52
+ font-weight: bolder;
53
+ font-size: var(--fontsize-small);
54
+ }
55
+
56
+ img {
57
+ display: block;
58
+
59
+ margin: auto;
60
+ max-width: 100%;
61
+ max-height: 100%;
62
+ }
63
+
64
+ mwc-icon[iconBtn] {
65
+ float: right;
66
+ margin-top: -20px;
67
+ margin-left: 2px;
68
+ color: var(--board-list-star-color);
69
+ font-size: 1.4em;
70
+ }
71
+ mwc-icon[info] {
72
+ color: var(--primary-color);
73
+ }
74
+
75
+ mwc-icon[iconBtn][favored],
76
+ mwc-icon[info]:hover {
77
+ color: var(--board-list-star-active-color);
78
+ }
79
+
80
+ a {
81
+ display: block;
82
+ border-radius: var(--card-list-border-radius);
83
+ border: var(--border-dark-color);
84
+ box-sizing: border-box;
85
+ background-color: var(--card-list-background-color);
86
+ margin: 0px;
87
+ height: calc(100% - 25px);
88
+ }
89
+
90
+ :host > *:hover [info] {
91
+ opacity: 1;
92
+ -webkit-transition: opacity 0.8s;
93
+ -moz-transition: opacity 0.8s;
94
+ -o-transition: opacity 0.8s;
95
+ transition: opacity 0.8s;
96
+ }
97
+
98
+ [draggable='true'] {
99
+ cursor: grab;
100
+ }
101
+
102
+ @media screen and (max-width: 800px), screen and (max-height: 600px) {
103
+ ox-board-creation-card {
104
+ display: none;
105
+ }
106
+ }
107
+ `
108
+ ]
109
+
110
+ @property({ type: Boolean, attribute: 'creatable' }) creatable: boolean = false
111
+ @property({ type: Array }) boards: any[] = []
112
+ @property({ type: Array }) favorites: any[] = []
113
+ @property({ type: Array }) groups: any[] = []
114
+ @property({ type: String }) group?: string
115
+ @property({ type: Boolean, attribute: 'reorderable' }) reorderable: boolean = false
116
+
117
+ private draggedItem
118
+
119
+ connectedCallback() {
120
+ super.connectedCallback()
121
+
122
+ if (this.reorderable) {
123
+ this.renderRoot.addEventListener('dragstart', (e: Event) => {
124
+ const target = e.target! as HTMLElement
125
+ this.draggedItem = target.closest('[card]')
126
+ ;(e as DragEvent).dataTransfer?.setData('text/plain', target.innerHTML)
127
+ })
128
+
129
+ this.renderRoot.addEventListener('dragover', (e: Event) => {
130
+ e.preventDefault()
131
+
132
+ const target = e.target! as HTMLElement
133
+ const targetItem = target.closest('[card]')
134
+ if (targetItem && targetItem !== this.draggedItem) {
135
+ const targetRect = targetItem.getBoundingClientRect()
136
+ const mousePos = (e as DragEvent).clientX - targetRect.left
137
+
138
+ if (mousePos < targetRect.width / 2) {
139
+ // 마우스 위치가 아이템 좌측 반절에 있을 때
140
+ this.renderRoot.insertBefore(this.draggedItem, targetItem)
141
+ } else {
142
+ // 마우스 위치가 아이템 우측 반절에 있을 때
143
+ this.renderRoot.insertBefore(this.draggedItem, targetItem.nextSibling)
144
+ }
145
+ }
146
+ })
147
+
148
+ this.renderRoot.addEventListener('drop', (e: Event) => {
149
+ e.preventDefault()
150
+
151
+ const boardIds = Array.from(this.renderRoot.querySelectorAll('[card]'))
152
+ .map(board => board.getAttribute('id'))
153
+ .filter(Boolean)
154
+
155
+ this.dispatchEvent(
156
+ new CustomEvent('reordered', {
157
+ detail: {
158
+ groupId: this.group,
159
+ boardIds
160
+ }
161
+ })
162
+ )
163
+ })
164
+ }
165
+ }
166
+
167
+ render() {
168
+ var boards = this.boards || []
169
+
170
+ return html`
171
+ ${this.creatable
172
+ ? html`
173
+ <ox-board-creation-card
174
+ .groups=${this.groups}
175
+ .defaultGroup=${this.group}
176
+ @create-board=${e => this.onCreateBoard(e)}
177
+ card
178
+ create
179
+ ></ox-board-creation-card>
180
+ `
181
+ : html``}
182
+ ${keyed(
183
+ Date.now(),
184
+ boards.map(
185
+ board =>
186
+ html`
187
+ <div card draggable="true" id=${board.id}>
188
+ <a href="board-viewer/${board.id}"> <img src=${board.thumbnail} /> </a>
189
+
190
+ <div name>${board.name}</div>
191
+ <!-- <div description>${board.description}</div> -->
192
+
193
+ <mwc-icon
194
+ iconBtn
195
+ info
196
+ @click=${e => {
197
+ this.infoBoard(board)
198
+ e.preventDefault()
199
+ }}
200
+ >info</mwc-icon
201
+ >
202
+
203
+ ${(this.favorites || []).includes(board.id)
204
+ ? html` <mwc-icon iconBtn favored @click=${e => this.removeFavorite(board.id)}>star</mwc-icon> `
205
+ : html` <mwc-icon iconBtn @click=${e => this.addFavorite(board.id)}>star_border</mwc-icon> `}
206
+ </div>
207
+ `
208
+ )
209
+ )}
210
+ `
211
+ }
212
+
213
+ updated(changes: PropertyValues<this>) {
214
+ var creationCard = this.renderRoot.querySelector('ox-board-creation-card') as any
215
+ if (creationCard) {
216
+ creationCard.reset()
217
+ }
218
+ }
219
+
220
+ onCreateBoard(e) {
221
+ this.dispatchEvent(
222
+ new CustomEvent('create-board', {
223
+ detail: e.detail
224
+ })
225
+ )
226
+ }
227
+
228
+ infoBoard(board) {
229
+ this.dispatchEvent(
230
+ new CustomEvent('info-board', {
231
+ detail: board
232
+ })
233
+ )
234
+ }
235
+
236
+ async removeFavorite(boardId) {
237
+ await client.query({
238
+ query: gql`
239
+ mutation {
240
+ deleteFavorite(routing: "${boardId}")
241
+ }
242
+ `
243
+ })
244
+
245
+ this.refreshFavorites()
246
+ }
247
+
248
+ async addFavorite(boardId) {
249
+ await client.query({
250
+ query: gql`
251
+ mutation {
252
+ createFavorite(favorite: {
253
+ routing: "${boardId}"
254
+ }) {
255
+ id
256
+ routing
257
+ }
258
+ }
259
+ `
260
+ })
261
+
262
+ this.refreshFavorites()
263
+ }
264
+
265
+ async refreshFavorites() {
266
+ this.dispatchEvent(new CustomEvent('refresh-favorites'))
267
+ }
268
+ }
@@ -0,0 +1,29 @@
1
+ import gql from 'graphql-tag'
2
+ import { customElement } from 'lit/decorators.js'
3
+ import { client, gqlContext } from '@operato/graphql'
4
+
5
+ import { BoardPlayerPage } from './board-player-page'
6
+
7
+ @customElement('board-player-by-name-page')
8
+ export class BoardPlayerByNamePage extends BoardPlayerPage {
9
+ async fetch(name: string) {
10
+ return await client.query({
11
+ query: gql`
12
+ query ($name: String!) {
13
+ response: playGroupByName(name: $name) {
14
+ id
15
+ name
16
+ description
17
+ boards {
18
+ id
19
+ model
20
+ }
21
+ }
22
+ }
23
+ `,
24
+ variables: {
25
+ name
26
+ }
27
+ })
28
+ }
29
+ }
@@ -92,6 +92,27 @@ export class BoardPlayerPage extends connect(store)(PageView) {
92
92
  delete this.provider
93
93
  }
94
94
 
95
+ async fetch(id: string) {
96
+ return await client.query({
97
+ query: gql`
98
+ query ($id: String!) {
99
+ response: playGroup(id: $id) {
100
+ id
101
+ name
102
+ description
103
+ boards {
104
+ id
105
+ model
106
+ }
107
+ }
108
+ }
109
+ `,
110
+ variables: {
111
+ id
112
+ }
113
+ })
114
+ }
115
+
95
116
  async refresh() {
96
117
  if (!this.playGroupId) {
97
118
  return
@@ -101,26 +122,9 @@ export class BoardPlayerPage extends connect(store)(PageView) {
101
122
  this.showSpinner = true
102
123
  this.updateContext()
103
124
 
104
- this.playGroup = (
105
- await client.query({
106
- query: gql`
107
- query FetchPlayGroup($id: String!) {
108
- playGroup(id: $id) {
109
- id
110
- name
111
- description
112
- boards {
113
- id
114
- model
115
- }
116
- }
117
- }
118
- `,
119
- variables: {
120
- id: this.playGroupId
121
- }
122
- })
123
- ).data.playGroup
125
+ const response = await this.fetch(this.playGroupId)
126
+
127
+ this.playGroup = response.data.response
124
128
 
125
129
  if (!this.playGroup) {
126
130
  throw 'playgroup not found'
@@ -197,7 +201,7 @@ export class BoardPlayerPage extends connect(store)(PageView) {
197
201
  }
198
202
 
199
203
  async startSubscribingForAutoRefresh() {
200
- if (!this.playGroupId) {
204
+ if (!this.playGroup) {
201
205
  return
202
206
  }
203
207
 
@@ -213,7 +217,7 @@ export class BoardPlayerPage extends connect(store)(PageView) {
213
217
  }
214
218
  `,
215
219
  variables: {
216
- id: this.playGroupId
220
+ id: this.playGroup.id
217
221
  }
218
222
  },
219
223
  {
@@ -0,0 +1,24 @@
1
+ import gql from 'graphql-tag'
2
+ import { customElement } from 'lit/decorators.js'
3
+ import { client, gqlContext } from '@operato/graphql'
4
+
5
+ import { BoardViewerPage } from './board-viewer-page'
6
+
7
+ @customElement('board-viewer-by-name-page')
8
+ export class BoardViewerByNamePage extends BoardViewerPage {
9
+ async fetch(name: string) {
10
+ return await client.query({
11
+ query: gql`
12
+ query FetchBoardByName($name: String!) {
13
+ response: boardByName(name: $name) {
14
+ id
15
+ name
16
+ model
17
+ }
18
+ }
19
+ `,
20
+ variables: { name },
21
+ context: gqlContext()
22
+ })
23
+ }
24
+ }
@@ -149,6 +149,22 @@ export class BoardViewerPage extends connect(store)(PageView) {
149
149
  this._baseUrl = state.app.baseUrl
150
150
  }
151
151
 
152
+ async fetch(id: string) {
153
+ return await client.query({
154
+ query: gql`
155
+ query ($id: String!) {
156
+ response: board(id: $id) {
157
+ id
158
+ name
159
+ model
160
+ }
161
+ }
162
+ `,
163
+ variables: { id },
164
+ context: gqlContext()
165
+ })
166
+ }
167
+
152
168
  async refresh() {
153
169
  if (!this._boardId) {
154
170
  this._board = null
@@ -159,21 +175,9 @@ export class BoardViewerPage extends connect(store)(PageView) {
159
175
  this._showSpinner = true
160
176
  this.updateContext()
161
177
 
162
- var response = await client.query({
163
- query: gql`
164
- query FetchBoardById($id: String!) {
165
- board(id: $id) {
166
- id
167
- name
168
- model
169
- }
170
- }
171
- `,
172
- variables: { id: this._boardId },
173
- context: gqlContext()
174
- })
178
+ var response = await this.fetch(this._boardId)
175
179
 
176
- var board = response.data.board
180
+ var board = response.data.response
177
181
 
178
182
  if (!board) {
179
183
  this._board = null
@@ -204,7 +208,7 @@ export class BoardViewerPage extends connect(store)(PageView) {
204
208
  }
205
209
 
206
210
  async startSubscribingForAutoRefresh() {
207
- if (!this._boardId) {
211
+ if (!this._board) {
208
212
  return
209
213
  }
210
214
 
@@ -220,7 +224,7 @@ export class BoardViewerPage extends connect(store)(PageView) {
220
224
  }
221
225
  `,
222
226
  variables: {
223
- id: this._boardId
227
+ id: this._board.id
224
228
  }
225
229
  },
226
230
  {
package/client/route.ts CHANGED
@@ -4,10 +4,18 @@ export default function route(page) {
4
4
  import('./pages/board-viewer-page')
5
5
  return page
6
6
 
7
+ case 'board-viewer-by-name':
8
+ import('./pages/board-viewer-by-name-page')
9
+ return page
10
+
7
11
  case 'board-player':
8
12
  import('./pages/board-player-page')
9
13
  return page
10
14
 
15
+ case 'board-player-by-name':
16
+ import('./pages/board-player-by-name-page')
17
+ return page
18
+
11
19
  case 'board-modeller':
12
20
  import('./pages/board-modeller-page')
13
21
  return page
@@ -1,27 +1,21 @@
1
- export default class BoardTileList extends LitElement {
2
- static get styles(): import("lit").CSSResult[];
3
- static get properties(): {
4
- creatable: {
5
- type: BooleanConstructor;
6
- attribute: string;
7
- };
8
- boards: ArrayConstructor;
9
- favorites: ArrayConstructor;
10
- groups: ArrayConstructor;
11
- group: StringConstructor;
12
- reorderable: {
13
- type: BooleanConstructor;
14
- attribute: string;
15
- };
16
- };
17
- draggingItem: any;
18
- draggedItem: any;
1
+ import '@operato/board/ox-board-creation-card.js';
2
+ import '@material/mwc-icon';
3
+ import { LitElement, PropertyValues } from 'lit';
4
+ export declare class BoardTileList extends LitElement {
5
+ static styles: import("lit").CSSResult[];
6
+ creatable: boolean;
7
+ boards: any[];
8
+ favorites: any[];
9
+ groups: any[];
10
+ group?: string;
11
+ reorderable: boolean;
12
+ private draggedItem;
13
+ connectedCallback(): void;
19
14
  render(): import("lit-html").TemplateResult<1>;
20
- updated(changes: any): void;
15
+ updated(changes: PropertyValues<this>): void;
21
16
  onCreateBoard(e: any): void;
22
17
  infoBoard(board: any): void;
23
18
  removeFavorite(boardId: any): Promise<void>;
24
19
  addFavorite(boardId: any): Promise<void>;
25
20
  refreshFavorites(): Promise<void>;
26
21
  }
27
- import { LitElement } from "lit-element/lit-element";