@things-factory/menu-ui 8.0.0-beta.1 → 8.0.0-beta.2

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": "@things-factory/menu-ui",
3
- "version": "8.0.0-beta.1",
3
+ "version": "8.0.0-beta.2",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -31,12 +31,12 @@
31
31
  "@operato/i18n": "^8.0.0-beta",
32
32
  "@operato/layout": "^8.0.0-beta",
33
33
  "@operato/oops": "^8.0.0-beta",
34
- "@things-factory/apptool-base": "^8.0.0-beta.1",
35
- "@things-factory/component-ui": "^8.0.0-beta.1",
36
- "@things-factory/fav-base": "^8.0.0-beta.1",
37
- "@things-factory/form-ui": "^8.0.0-beta.1",
38
- "@things-factory/i18n-base": "^8.0.0-beta.1",
39
- "@things-factory/menu-base": "^8.0.0-beta.1"
34
+ "@things-factory/apptool-base": "^8.0.0-beta.2",
35
+ "@things-factory/component-ui": "^8.0.0-beta.2",
36
+ "@things-factory/fav-base": "^8.0.0-beta.2",
37
+ "@things-factory/form-ui": "^8.0.0-beta.2",
38
+ "@things-factory/i18n-base": "^8.0.0-beta.2",
39
+ "@things-factory/menu-base": "^8.0.0-beta.2"
40
40
  },
41
- "gitHead": "36c494e587640c1490318ef7b95adab02606e0c2"
41
+ "gitHead": "f03431a09435511b2595515658f9cb8f78ba4ebb"
42
42
  }
@@ -1,124 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
-
3
- import { LitElement, html, css } from 'lit'
4
- import { customElement, property } from 'lit/decorators.js'
5
- import { connect } from 'pwa-helpers/connect-mixin.js'
6
- import gql from 'graphql-tag'
7
-
8
- import { store, client } from '@things-factory/shell/client'
9
- import { UPDATE_FAVORITES } from '@things-factory/fav-base/client'
10
-
11
- @customElement('favorite-tool')
12
- export class FavoriteTool extends connect(store)(LitElement) {
13
- static styles = css`
14
- :host {
15
- display: inline-block;
16
- vertical-align: middle;
17
- line-height: 0;
18
- }
19
-
20
- [favorable] {
21
- opacity: 0.5;
22
- }
23
- `
24
-
25
- @property({ type: Array }) favorites: any
26
- @property({ type: Object }) user: any
27
- @property({ type: String }) page?: string
28
- @property({ type: String }) resourceId?: string
29
- @property({ type: Boolean }) favored: boolean = false
30
- @property({ type: Array }) routingTypes: any[] = []
31
- @property({ type: Array }) blackList: string[] = []
32
-
33
- render() {
34
- var renderable = (this.blackList || []).indexOf(this.page!) == -1
35
-
36
- return renderable
37
- ? html`
38
- <md-icon @click=${this.onClick.bind(this)} ?favorable=${!this.favored}
39
- >${this.favored ? 'star' : 'star_border'}</md-icon
40
- >
41
- `
42
- : html``
43
- }
44
-
45
- updated(changes) {
46
- if (changes.has('user')) {
47
- this.refreshFavorites()
48
- }
49
-
50
- this.favored = (this.favorites || []).includes(this.getFullRouting())
51
- }
52
-
53
- stateChanged(state) {
54
- this.favorites = state.favorite.favorites
55
- this.user = state.auth.user
56
- this.page = state.route.page
57
- this.resourceId = state.route.resourceId
58
- this.routingTypes = state.menu.routingTypes
59
- }
60
-
61
- onClick(event) {
62
- if (this.favored) {
63
- this.removeFavorite(this.getFullRouting())
64
- } else {
65
- this.addFavorite(this.getFullRouting())
66
- }
67
- }
68
-
69
- async refreshFavorites() {
70
- if (!this.user || !this.user.email) {
71
- return
72
- }
73
-
74
- const response = await client.query({
75
- query: gql`
76
- query {
77
- myFavorites {
78
- id
79
- routing
80
- }
81
- }
82
- `
83
- })
84
-
85
- store.dispatch({
86
- type: UPDATE_FAVORITES,
87
- favorites: response.data.myFavorites.map(favorite => favorite.routing)
88
- })
89
- }
90
-
91
- async removeFavorite(routing) {
92
- await client.query({
93
- query: gql`
94
- mutation {
95
- deleteFavorite(routing: "${routing}")
96
- }
97
- `
98
- })
99
-
100
- this.refreshFavorites()
101
- }
102
-
103
- async addFavorite(routing) {
104
- await client.query({
105
- query: gql`
106
- mutation {
107
- createFavorite(favorite: {
108
- routing: "${routing}"
109
- }) {
110
- id
111
- routing
112
- }
113
- }
114
- `
115
- })
116
-
117
- this.refreshFavorites()
118
- }
119
-
120
- getFullRouting() {
121
- var routingType = Object.values(this.routingTypes).find(type => type.page == this.page)
122
- return routingType ? `${this.page}/${this.resourceId}` : this.page
123
- }
124
- }
@@ -1,57 +0,0 @@
1
- import '@operato/i18n'
2
- import './apptools/favorite-tool'
3
- import './viewparts/menu-tree-bar'
4
-
5
- import { html } from 'lit-html'
6
-
7
- import { appendViewpart, TOOL_POSITION, VIEWPART_POSITION } from '@operato/layout'
8
- import { APPEND_APP_TOOL } from '@things-factory/apptool-base/client'
9
- import { auth } from '@things-factory/auth-base/dist-client'
10
- import { ADD_MORENDA } from '@things-factory/more-base/client'
11
- import { navigate, store } from '@operato/shell'
12
- import { isMobileDevice } from '@operato/utils'
13
-
14
- export default function bootstrap() {
15
- if (!isMobileDevice()) {
16
- appendViewpart({
17
- name: 'menu-tree-bar',
18
- viewpart: {
19
- show: true,
20
- template: html` <menu-tree-bar></menu-tree-bar> `
21
- },
22
- position: VIEWPART_POSITION.NAVBAR
23
- })
24
- }
25
-
26
- store.dispatch({
27
- type: APPEND_APP_TOOL,
28
- tool: {
29
- name: 'favorite-tool',
30
- template: html` <favorite-tool .blackList=${['menu-list']}></favorite-tool> `,
31
- position: TOOL_POSITION.REAR
32
- }
33
- })
34
-
35
- auth.on('profile', ({ credential }) => {
36
- if (credential.owner) {
37
- appendRoleMenusManagementMorenda()
38
- }
39
- })
40
- }
41
-
42
- function appendRoleMenusManagementMorenda() {
43
- const useRoleByMenusManagementMenu = (store.getState() as any)?.menu?.useRoleByMenusManagementMenu || false
44
-
45
- if (useRoleByMenusManagementMenu) {
46
- store.dispatch({
47
- type: ADD_MORENDA,
48
- morenda: {
49
- icon: html` <md-icon>menu</md-icon> `,
50
- name: html` <ox-i18n msgid="title.role_menus_management"></ox-i18n> `,
51
- action: () => {
52
- navigate('role-menus')
53
- }
54
- }
55
- })
56
- }
57
- }
@@ -1,144 +0,0 @@
1
- import { i18next, localize } from '@operato/i18n'
2
- import { client } from '@operato/graphql'
3
- import gql from 'graphql-tag'
4
- import { css, html, LitElement } from 'lit'
5
- import { customElement, property } from 'lit/decorators.js'
6
-
7
- @customElement('child-menus-selector')
8
- class ChildMenusSelector extends localize(i18next)(LitElement) {
9
- static styles = [
10
- css`
11
- :host {
12
- display: flex;
13
- flex-direction: column;
14
- border: 1px solid var(--md-sys-color-primary);
15
- font: normal 15px var(--theme-font);
16
- color: var(--md-sys-color-secondary);
17
- }
18
- div {
19
- margin: var(--spacing-medium);
20
- }
21
- ul {
22
- flex: 1;
23
- background-color: var(--md-sys-color-surface);
24
- overflow: auto;
25
- display: grid;
26
- grid-template-columns: 1fr 1fr;
27
- margin: 0;
28
- padding: var(--spacing-medium);
29
- list-style: none;
30
- border: 1px dashed rgba(0, 0, 0, 0.1);
31
- border-width: 1px 0;
32
- }
33
-
34
- input[type='checkbox'] {
35
- display: inline;
36
- }
37
-
38
- li {
39
- padding: var(--spacing-small);
40
- }
41
-
42
- #checkAll,
43
- [for='checkAll'] {
44
- margin-bottom: var(--spacing-medium);
45
- padding-bottom: var(--spacing-small);
46
- font-weight: bold;
47
- }
48
-
49
- @media screen and (max-width: 480px) {
50
- ul {
51
- grid-template-columns: 1fr;
52
- }
53
- }
54
- `
55
- ]
56
-
57
- @property({ type: Object }) parentMenu: any
58
- @property({ type: Array }) roleMenus: any[] = []
59
- @property({ type: Object }) targetRole: any
60
-
61
- render() {
62
- const parentMenu = this.parentMenu || {}
63
- const menus = parentMenu.children || []
64
- const roleMenus = this.roleMenus || []
65
-
66
- return html`
67
- <div>
68
- <input id="checkAll" type="checkbox" @change=${e => this.onCheckAll(e)} />
69
- <label for="checkAll">Check all</label>
70
- </div>
71
-
72
- <ul menus>
73
- ${menus?.map(
74
- menu => html`
75
- <li>
76
- <label for="${menu.id}"
77
- >${menu.name}
78
- <input
79
- type="checkbox"
80
- id="${menu.id}"
81
- .checked=${roleMenus.map(p => p.id).indexOf(menu.id) > -1}
82
- .data-menu=${menu.id}
83
- @change=${e => this.onSave(e)}
84
- />
85
- </label>
86
- </li>
87
- `
88
- )}
89
- </ul>
90
- `
91
- }
92
-
93
- get menuList() {
94
- return this.renderRoot.querySelectorAll('ul[menus] input[type=checkbox]')
95
- }
96
-
97
- async onCheckAll(e) {
98
- const checked = e.currentTarget.checked
99
-
100
- Array.from(this.menuList).forEach(checkbox => ((checkbox as HTMLInputElement).checked = checked))
101
-
102
- const response = await client.mutate({
103
- mutation: gql`
104
- mutation ($roleId: String!, $parentMenuId: String!, $isCheckedAll: Boolean!) {
105
- updateRoleMenus(roleId: $roleId, parentMenuId: $parentMenuId, isCheckedAll: $isCheckedAll) {
106
- name
107
- }
108
- }
109
- `,
110
- variables: { roleId: this.targetRole.id, parentMenuId: this.parentMenu.id, isCheckedAll: checked }
111
- })
112
-
113
- if (!response.errors) {
114
- this.dispatchEvent(new CustomEvent('updateRoleMenus'))
115
- this.showToast(i18next.t('text.data_updated_successfully'))
116
- }
117
- }
118
-
119
- async onSave(e) {
120
- const menuId = e.currentTarget.id
121
- const isCheckedMenu = e.currentTarget.checked
122
-
123
- const response = await client.mutate({
124
- mutation: gql`
125
- mutation ($roleId: String!, $targetMenuId: String!, $isCheckedMenu: Boolean!) {
126
- updateRoleMenu(roleId: $roleId, targetMenuId: $targetMenuId, isCheckedMenu: $isCheckedMenu) {
127
- id
128
- name
129
- }
130
- }
131
- `,
132
- variables: { roleId: this.targetRole.id, targetMenuId: menuId, isCheckedMenu }
133
- })
134
-
135
- if (!response.errors) {
136
- this.dispatchEvent(new CustomEvent('updateRoleMenus'))
137
- this.showToast(i18next.t('text.data_updated_successfully'))
138
- }
139
- }
140
-
141
- showToast(message) {
142
- document.dispatchEvent(new CustomEvent('notify', { detail: { message, option: { timer: 1000 } } }))
143
- }
144
- }
@@ -1,169 +0,0 @@
1
- import { i18next, localize } from '@operato/i18n'
2
- import { client } from '@operato/graphql'
3
- import gql from 'graphql-tag'
4
- import { css, html, LitElement } from 'lit'
5
- import { customElement, property, state, query } from 'lit/decorators.js'
6
- import { isMobileDevice } from '@operato/utils'
7
- import '@operato/data-grist'
8
- import { CommonHeaderStyles } from '@operato/styles'
9
- import { DataGrist, FetchOption } from '@operato/data-grist'
10
-
11
- @customElement('role-select-popup')
12
- class RoleSelectPopup extends localize(i18next)(LitElement) {
13
- static styles = [
14
- CommonHeaderStyles,
15
- css`
16
- :host {
17
- display: flex;
18
- flex-direction: column;
19
- overflow: hidden;
20
- background-color: var(--md-sys-color-surface);
21
- }
22
-
23
- .container {
24
- flex: 1;
25
- display: flex;
26
- overflow-y: auto;
27
- min-height: 20vh;
28
- }
29
-
30
- .grist {
31
- display: flex;
32
- flex-direction: column;
33
- flex: 1;
34
- overflow-y: auto;
35
- }
36
-
37
- ox-grist {
38
- overflow-y: hidden;
39
- flex: 1;
40
- }
41
- `
42
- ]
43
-
44
- @property({ type: Array }) _searchFields: any[] = []
45
- @property({ type: Object }) config: any
46
-
47
- @query('ox-grist') dataGrist!: DataGrist
48
- @query('search-form') searchForm!: HTMLFormElement
49
-
50
- render() {
51
- return html`
52
- <search-form .fields=${this._searchFields} @submit=${async () => this.dataGrist.fetch()}></search-form>
53
-
54
- <div class="container">
55
- <div class="grist">
56
- <ox-grist
57
- .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
58
- .config=${this.config}
59
- .fetchHandler=${this.fetchHandler.bind(this)}
60
- ></ox-grist>
61
- </div>
62
- </div>
63
-
64
- <div class="footer">
65
- <div filler></div>
66
- <button @click=${this._selectRole.bind(this)} label=${i18next.t('button.select')} done></button>
67
- </div>
68
- `
69
- }
70
-
71
- firstUpdated() {
72
- this._searchFields = [
73
- {
74
- name: 'name',
75
- type: 'text',
76
- props: {
77
- placeholder: i18next.t('field.name'),
78
- searchOper: 'i_like'
79
- }
80
- },
81
- {
82
- name: 'description',
83
- type: 'text',
84
- props: {
85
- placeholder: i18next.t('field.description'),
86
- searchOper: 'i_like'
87
- }
88
- }
89
- ]
90
-
91
- this.config = {
92
- rows: {
93
- appendable: false
94
- },
95
- columns: [
96
- { type: 'gutter', gutterName: 'sequence' },
97
- { type: 'gutter', gutterName: 'row-selector', multiple: false },
98
- {
99
- type: 'string',
100
- name: 'name',
101
- header: i18next.t('field.name'),
102
- record: {
103
- editable: false
104
- },
105
- width: 200
106
- },
107
- {
108
- type: 'string',
109
- name: 'description',
110
- header: i18next.t('field.description'),
111
- record: {
112
- editable: true
113
- },
114
- width: 250
115
- },
116
- {
117
- type: 'datetime',
118
- name: 'updatedAt',
119
- header: i18next.t('field.updated_at'),
120
- width: 180
121
- }
122
- ]
123
- }
124
- }
125
-
126
- async fetchHandler({ page, limit, sorters = [] }: FetchOption) {
127
- const filters = (this.searchForm as any)?.queryFilters || []
128
-
129
- const response = await client.query({
130
- query: gql`
131
- query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
132
- roles(filters: $filters, pagination: $pagination, sortings: $sortings) {
133
- items {
134
- id
135
- name
136
- description
137
- updatedAt
138
- }
139
- total
140
- }
141
- }
142
- `,
143
- variables: {
144
- filters,
145
- pagination: { page, limit },
146
- sortings: sorters
147
- }
148
- })
149
-
150
- return {
151
- total: response.data.roles.total || 0,
152
- records: response.data.roles.items || []
153
- }
154
- }
155
-
156
- _selectRole() {
157
- const selectedRole = this.dataGrist.selected[0]
158
- if (selectedRole) {
159
- this.dispatchEvent(new CustomEvent('selected', { detail: this.dataGrist.selected[0] }))
160
- history.back()
161
- } else {
162
- this.showToast(i18next.t('text.target_is_not_selected'))
163
- }
164
- }
165
-
166
- showToast(message) {
167
- document.dispatchEvent(new CustomEvent('notify', { detail: { message, option: { timer: 1000 } } }))
168
- }
169
- }
package/client/index.ts DELETED
File without changes