From bd454e56c7e5470d547c71c3cb72e728fb9d810f Mon Sep 17 00:00:00 2001
From: avele <34437766+avele@users.noreply.github.com>
Date: Wed, 6 Nov 2019 14:20:47 +0400
Subject: [PATCH] Added responsive button container component for toolbars
(#412)
---
front/babel.config.js | 4 +-
front/build/webpack.base.conf.js | 5 +-
front/client/components/CategoryHeader.vue | 106 ++-------
.../client/components/CategoryItemToolbar.vue | 215 +++++++-----------
.../components/ResponsiveBtnsContainer.vue | 82 +++++++
front/package-lock.json | 104 +++++++++
front/package.json | 2 +
front/tsconfig.json | 1 +
8 files changed, 304 insertions(+), 215 deletions(-)
create mode 100644 front/client/components/ResponsiveBtnsContainer.vue
diff --git a/front/babel.config.js b/front/babel.config.js
index 4cd0c4a..d15c5df 100644
--- a/front/babel.config.js
+++ b/front/babel.config.js
@@ -6,7 +6,9 @@ module.exports = {
},
modules: 'commonjs',
useBuiltIns: 'usage'
- }]
+ }
+ ],
+ '@vue/babel-preset-jsx'
],
plugins: [
'@babel/plugin-transform-runtime',
diff --git a/front/build/webpack.base.conf.js b/front/build/webpack.base.conf.js
index 867755c..463afd1 100644
--- a/front/build/webpack.base.conf.js
+++ b/front/build/webpack.base.conf.js
@@ -68,12 +68,15 @@ const config = {
transpileOnly: true,
appendTsSuffixTo: [/\.vue$/]
}
- }
+ },
]
},
{
test: /\.tsx$/,
use: [
+ {
+ loader: 'babel-loader'
+ },
{
loader: 'ts-loader',
options: {
diff --git a/front/client/components/CategoryHeader.vue b/front/client/components/CategoryHeader.vue
index f5d1269..1ff7ab7 100644
--- a/front/client/components/CategoryHeader.vue
+++ b/front/client/components/CategoryHeader.vue
@@ -27,7 +27,24 @@
>{{ category.group }}
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
@@ -118,11 +84,13 @@ import CategorySettingsDialog from 'client/components/CategorySettingsDialog.vue
import CategoryHeaderBtn from 'client/components/CategoryHeaderBtn.vue'
import Confirm from 'client/helpers/ConfirmDecorator'
import { ICategoryFull } from 'client/service/Category'
+import ResponsiveBtnsContainer from 'client/components/ResponsiveBtnsContainer.vue'
@Component({
components: {
CategorySettingsDialog,
- CategoryHeaderBtn
+ CategoryHeaderBtn,
+ ResponsiveBtnsContainer
}
})
export default class CategoryHeader extends Vue {
@@ -209,41 +177,13 @@ export default class CategoryHeader extends Vue {
font-weight: 600;
}
-.category-actions-menu-btn {
- display: none;
+.category-actions-mobile-menu-btn {
margin: 0;
width: 36px;
height: 36px;
}
-.category-actions {
- white-space: nowrap;
- flex: 1;
-}
-
-.category-actions-menu-list {
- >>> .v-list-item {
- height: 36px;
- padding: 0;
- }
-
- >>> button {
- height: 100% !important;
- padding: 0 6px;
-
- .v-btn__content {
- justify-content: flex-start;
- }
- }
-}
-
@media (max-width: 768px) {
- .category-actions-menu-btn {
- display: block;
- }
- .category-actions {
- display: none;
- }
.category-header__second-row {
/* Cause menu btn appears after page loading and causes second row to jump */
min-height: 36px;
diff --git a/front/client/components/CategoryItemToolbar.vue b/front/client/components/CategoryItemToolbar.vue
index 4562a2c..bf1cfaa 100644
--- a/front/client/components/CategoryItemToolbar.vue
+++ b/front/client/components/CategoryItemToolbar.vue
@@ -47,61 +47,12 @@
-
-
-
-
-
- $vuetify.icons.circle
-
-
-
-
-
-
+
-
+
-
-
+
+
+
+
+
+
@@ -239,10 +161,12 @@ import { Prop, Watch } from 'vue-property-decorator'
import normalizeUrl from 'normalize-url'
import Confirm from 'client/helpers/ConfirmDecorator'
import CategoryItemBtn from 'client/components/CategoryItemBtn.vue'
+import ResponsiveBtnsContainer from 'client/components/ResponsiveBtnsContainer.vue'
@Component({
components: {
- CategoryItemBtn
+ CategoryItemBtn,
+ ResponsiveBtnsContainer
}
})
export default class CategoryItemToolbar extends Vue {
@@ -255,6 +179,36 @@ export default class CategoryItemToolbar extends Vue {
itemNameEdit: string = this.itemName
itemLinkEdit: string = this.itemLink
itemHackageEdit: string = this.itemHackage
+ toolbarItemsEl = null
+ get actionBtns () {
+ return [
+ {
+ title: 'Move item up',
+ dataTestId: 'CategoryItemToolbar-MoveUpBtn',
+ icon: 'arrow-up',
+ clickFunc: () => this.moveItem('up')
+ },
+ {
+ title: 'Move item down',
+ dataTestId: 'CategoryItemToolbar-MoveDownBtn',
+ icon: 'arrow-down',
+ clickFunc: () => this.moveItem('down')
+ },
+ {
+ title: 'Edit item info',
+ dataTestId: 'CategoryItemToolbar-EditInfoBtn',
+ icon: 'cog',
+ showUnsavedIcon: this.isItemInfoEdited,
+ clickFunc: () => this.toggleEditItemInfoMenu()
+ },
+ {
+ title: 'Delete item',
+ icon: 'trash-alt',
+ dataTestId: 'CategoryItemToolbar-DeleteBtn',
+ clickFunc: () => this.deleteItem()
+ }
+ ]
+ }
get isItemInfoEdited () {
return this.itemName !== this.itemNameEdit || this.itemLink !== this.itemLinkEdit || this.itemHackage !== this.itemHackageEdit
@@ -274,6 +228,11 @@ export default class CategoryItemToolbar extends Vue {
this.itemLinkEdit = newVal
}
+ mounted () {
+ // Cause $refs is not reactive we need to set it manually after its available
+ this.toolbarItemsEl = this.$refs.toolbarItems
+ }
+
toggleEditItemInfoMenu () {
this.isEditItemInfoMenuOpen = !this.isEditItemInfoMenuOpen
}
@@ -419,24 +378,26 @@ a.category-item-anchor {
}
.category-item-toolbar-btns {
- display: flex;
- align-items: center;
- flex: 1;
+ >>> .responsive-bar__desktop-wrap {
+ display: flex;
+ align-items: center;
+ flex: 1;
- > * {
- width: 1.6rem !important;
- height: 1.6rem !important;
- }
+ > * {
+ width: 1.6rem !important;
+ height: 1.6rem !important;
+ }
- > *:not(:last-child) {
- margin-right: 6px;
+ > *:not(:last-child) {
+ margin-right: 6px;
+ }
}
}
.category-toolbar-mobile-menu-btn {
- display: none;
- /* Somewhy vuetify sets important "height: 100%"" for direct child buttons of toolbar */
+ /* For some reason vuetify sets important "height: 100%"" for direct child buttons of toolbar */
height: 1.6rem !important;
width: 1.6rem !important;
+ border-radius: 0;
margin: 0;
}
@@ -457,12 +418,6 @@ a.category-item-anchor {
}
@media (max-width: 768px) {
- .category-toolbar-mobile-menu-btn {
- display: flex;
- }
- .category-item-toolbar-btns {
- display: none;
- }
.category-item-badges {
display: flex;
flex-wrap: wrap;
diff --git a/front/client/components/ResponsiveBtnsContainer.vue b/front/client/components/ResponsiveBtnsContainer.vue
new file mode 100644
index 0000000..2c8417a
--- /dev/null
+++ b/front/client/components/ResponsiveBtnsContainer.vue
@@ -0,0 +1,82 @@
+
+
+
\ No newline at end of file
diff --git a/front/package-lock.json b/front/package-lock.json
index f9eb0ef..77926cd 100644
--- a/front/package-lock.json
+++ b/front/package-lock.json
@@ -405,6 +405,15 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz",
+ "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
"@babel/plugin-syntax-object-rest-spread": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
@@ -1058,6 +1067,83 @@
"integrity": "sha512-9taxKC944BqoTVjE+UT3pQH0nHZlTvITwfsOZqyc+R3sfJuxaTtxWjfn1K2UlxyPcKHf0rnaXcVFrS9F9vf0bw==",
"dev": true
},
+ "@vue/babel-helper-vue-jsx-merge-props": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz",
+ "integrity": "sha512-6tyf5Cqm4m6v7buITuwS+jHzPlIPxbFzEhXR5JGZpbrvOcp1hiQKckd305/3C7C36wFekNTQSxAtgeM0j0yoUw==",
+ "dev": true
+ },
+ "@vue/babel-plugin-transform-vue-jsx": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.0.0.tgz",
+ "integrity": "sha512-U+JNwVQSmaLKjO3lzCUC3cNXxprgezV1N+jOdqbP4xWNaqtWUCJnkjTVcgECM18A/AinDKPcUUeoyhU7yxUxXQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+ "html-tags": "^2.0.0",
+ "lodash.kebabcase": "^4.1.1",
+ "svg-tags": "^1.0.0"
+ }
+ },
+ "@vue/babel-preset-jsx": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.1.1.tgz",
+ "integrity": "sha512-SeyndwQZc8MAOkhbJaC34ocTwcKekKkwrwnTMC3YF8VmGp5IQWW5gPIU66bqO9WFBXFA3J3ANsUbP2pj8q8KdQ==",
+ "dev": true,
+ "requires": {
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.0.0",
+ "@vue/babel-sugar-functional-vue": "^1.0.0",
+ "@vue/babel-sugar-inject-h": "^1.0.0",
+ "@vue/babel-sugar-v-model": "^1.1.1",
+ "@vue/babel-sugar-v-on": "^1.1.0"
+ }
+ },
+ "@vue/babel-sugar-functional-vue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.0.0.tgz",
+ "integrity": "sha512-XE/jNaaorTuhWayCz+QClk5AB9OV5HzrwbzEC6sIUY0J60A28ONQKeTwxfidW42egOkqNH/UU6eE3KLfmiDj0Q==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0"
+ }
+ },
+ "@vue/babel-sugar-inject-h": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.0.0.tgz",
+ "integrity": "sha512-NxWU+DqtbZgfGvd25GPoFMj+rvyQ8ZA1pHj8vIeqRij+vx3sXoKkObjA9ulZunvWw5F6uG9xYy4ytpxab/X+Hg==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0"
+ }
+ },
+ "@vue/babel-sugar-v-model": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.1.1.tgz",
+ "integrity": "sha512-qiPbdUTiqNQdhXzvWQMVfrYGHCiMmscY7j/cudLxdxWZ8AFhgPRVlniVgaWIT7A1iOjs92e8U6qVyqkf0d4ZrA==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.0.0",
+ "camelcase": "^5.0.0",
+ "html-tags": "^2.0.0",
+ "svg-tags": "^1.0.0"
+ }
+ },
+ "@vue/babel-sugar-v-on": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.1.0.tgz",
+ "integrity": "sha512-8DwAj/RLpmrDP4eZ3erJcKcyuLArLUYagNODTsSQrMdG5zmLJoFFtEjODfYRh/XxM2wXv9Wxe+HAB41FQxxwQA==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.0.0",
+ "camelcase": "^5.0.0"
+ }
+ },
"@vue/component-compiler-utils": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz",
@@ -6285,6 +6371,12 @@
"integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
"dev": true
},
+ "html-tags": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
+ "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
+ "dev": true
+ },
"http-assert": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz",
@@ -7174,6 +7266,12 @@
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
},
+ "lodash.kebabcase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
+ "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=",
+ "dev": true
+ },
"lodash.tail": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
@@ -10441,6 +10539,12 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
},
+ "svg-tags": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
+ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
+ "dev": true
+ },
"tapable": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
diff --git a/front/package.json b/front/package.json
index b0f3953..8a2c672 100644
--- a/front/package.json
+++ b/front/package.json
@@ -58,6 +58,8 @@
"vuex-router-sync": "^5.0.0"
},
"devDependencies": {
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+ "@vue/babel-preset-jsx": "^1.1.1",
"@babel/core": "^7.5.5",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.5.5",
diff --git a/front/tsconfig.json b/front/tsconfig.json
index 0417153..2fa1ecc 100644
--- a/front/tsconfig.json
+++ b/front/tsconfig.json
@@ -6,6 +6,7 @@
"client/*"
]
},
+ "jsx": "preserve",
"allowSyntheticDefaultImports": true,
"allowJs": true,
"experimentalDecorators": true,