From bca12e8fbdbebb4b4781c75860591ceb2493d534 Mon Sep 17 00:00:00 2001 From: Kovah Date: Thu, 28 Mar 2019 21:15:47 +0100 Subject: [PATCH] Drag n drop sorting for custom fields (#906) * Try to fix some security vulnerabilities present in used packages (Ran npm audit fix, solved some of the issues) * Implement custom field ordering with new handle placement (WIP, as an update for the jslib is needed to work correctly) * Update reference for jslib * Restore original state of package-lock.json * Downgrade node sass package --- package-lock.json | 15 + package.json | 3 +- src/_locales/en/messages.json | 3 + src/popup/app.module.ts | 2 + src/popup/scss/box.scss | 756 ++++++++++++------------ src/popup/vault/add-edit.component.html | 59 +- 6 files changed, 443 insertions(+), 395 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8939f9ed45f..4465d62da9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -413,6 +413,15 @@ "tslib": "^1.9.0" } }, + "@angular/cdk": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-7.2.1.tgz", + "integrity": "sha512-oU1Pjq3JkDtkXquLxWK84A2jOCeYRf352dVGbQCxWoSOQ5KBtMAd42huGidPiOSHN6/f7xZwL3n4fq3fVIut8A==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^1.7.1" + } + }, "@angular/common": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.1.tgz", @@ -9648,6 +9657,12 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "optional": true + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", diff --git a/package.json b/package.json index a82a6a5af32..75190f9853f 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test:watch": "karma start" }, "devDependencies": { - "@angular/compiler-cli": "^7.2.1", + "@angular/compiler-cli": "^7.2.11", "@ngtools/webpack": "^7.2.2", "@types/chrome": "^0.0.73", "@types/jasmine": "^2.8.8", @@ -75,6 +75,7 @@ }, "dependencies": { "@angular/animations": "7.2.1", + "@angular/cdk": "7.2.1", "@angular/common": "7.2.1", "@angular/compiler": "7.2.1", "@angular/core": "7.2.1", diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 295b81527f2..2f731ec64b0 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -886,6 +886,9 @@ "newCustomField": { "message": "New Custom Field" }, + "dragToSort": { + "message": "Drag to sort" + }, "cfTypeText": { "message": "Text" }, diff --git a/src/popup/app.module.ts b/src/popup/app.module.ts index 46ecc023fa6..72737db6657 100644 --- a/src/popup/app.module.ts +++ b/src/popup/app.module.ts @@ -1,6 +1,7 @@ import 'core-js'; import 'zone.js/dist/zone'; +import { DragDropModule } from '@angular/cdk/drag-drop'; import { ToasterModule } from 'angular2-toaster'; import { Angulartics2Module } from 'angulartics2'; import { Angulartics2GoogleAnalytics } from 'angulartics2/ga'; @@ -149,6 +150,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); }), ToasterModule.forRoot(), InfiniteScrollModule, + DragDropModule, ], declarations: [ ActionButtonsComponent, diff --git a/src/popup/scss/box.scss b/src/popup/scss/box.scss index 45ef1740a24..5e5874b027b 100644 --- a/src/popup/scss/box.scss +++ b/src/popup/scss/box.scss @@ -1,6 +1,7 @@ @import "variables.scss"; .box { + position: relative; width: 100%; margin: 10px 0; @@ -31,373 +32,6 @@ padding: 10px 15px; } - .box-content-row { - display: block; - padding: 10px 15px; - position: relative; - z-index: 1; - - &:before { - content: ""; - position: absolute; - right: 0; - bottom: 0; - height: 1px; - width: calc(100% - 10px); - border-bottom: 1px solid #000000; - - @include themify($themes) { - border-bottom-color: themed('boxBorderColor'); - } - } - - &:last-child { - &:before { - border: none; - height: 0; - } - } - - &:after { - content: ""; - display: table; - clear: both; - } - - &:hover, &:focus, &.active { - @include themify($themes) { - background-color: themed('boxBackgroundHoverColor'); - } - } - - &.pre { - white-space: pre; - overflow-x: auto; - } - - &.pre-line { - white-space: pre-line; - overflow-x: auto; - } - - .row-label, label { - font-size: $font-size-small; - display: block; - width: 100%; - margin-bottom: 5px; - - @include themify($themes) { - color: themed('mutedColor'); - } - - .sub-label { - margin-left: 10px; - } - } - - .text, .detail { - display: block; - - @include themify($themes) { - color: themed('textColor'); - } - } - - .detail { - font-size: $font-size-small; - - @include themify($themes) { - color: themed('mutedColor'); - } - } - - .img-right { - float: right; - margin-left: 10px; - } - - .row-main { - flex-grow: 1; - } - - &.box-content-row-flex, .box-content-row-flex, &.box-content-row-checkbox, - &.box-content-row-input, &.box-content-row-slider, &.box-content-row-multi { - display: flex; - align-items: center; - word-break: break-all; - } - - &.box-content-row-multi { - width: 100%; - - input:not([type="checkbox"]) { - width: 100%; - } - - input + label.sr-only + select { - margin-top: 5px; - } - - > a { - padding: 8px 8px 8px 4px; - margin: 0; - - @include themify($themes) { - color: themed('dangerColor'); - } - } - } - - - &.box-content-row-multi, &.box-content-row-newmulti { - padding-left: 10px; - } - - &.box-content-row-checkbox, &.box-content-row-input, &.box-content-row-slider { - label, .row-label { - font-size: $font-size-base; - display: block; - width: initial; - margin-bottom: 0; - - @include themify($themes) { - color: themed('textColor'); - } - } - - > span { - @include themify($themes) { - color: themed('mutedColor'); - } - } - - > input { - margin: 0 0 0 auto; - padding: 0; - } - - > * { - margin-right: 15px; - - &:last-child { - margin-right: 0; - } - } - } - - &.box-content-row-input { - label { - white-space: nowrap; - } - - input { - text-align: right; - - &[type="number"] { - max-width: 50px; - } - } - } - - &.box-content-row-slider { - input[type="range"] { - height: 10px; - } - - input[type="number"] { - width: 45px; - } - - label { - white-space: nowrap; - } - } - - input:not([type="checkbox"]), textarea { - border: none; - width: 100%; - background-color: transparent; - - &::-webkit-input-placeholder { - @include themify($themes) { - color: themed('inputPlaceholderColor'); - } - } - - &:focus { - outline: none; - } - } - - select { - width: 100%; - border: 1px solid #000000; - border-radius: $border-radius; - - @include themify($themes) { - border-color: themed('inputBorderColor'); - } - } - - .action-buttons { - display: flex; - margin-left: 5px; - - .row-btn { - cursor: pointer; - padding: 10px 8px; - background: none; - border: none; - - @include themify($themes) { - color: themed('boxRowButtonColor'); - } - - &:hover, &:focus { - @include themify($themes) { - color: themed('boxRowButtonHoverColor'); - } - } - - &.disabled { - @include themify($themes) { - color: themed('disabledIconColor'); - } - - &:hover { - @include themify($themes) { - color: themed('disabledIconColor'); - } - } - } - - &:last-child { - padding-right: 2px !important; - } - } - - &.no-pad .row-btn { - padding-top: 0; - padding-bottom: 0; - } - } - - select.field-type { - margin: 5px 0 0 25px; - width: calc(100% - 25px); - } - - .row-sub-icon, .row-sub-label + i.fa { - @include themify($themes) { - color: themed('disabledIconColor'); - } - } - - .row-sub-label { - margin: 0 15px; - white-space: nowrap; - - @include themify($themes) { - color: themed('mutedColor'); - } - } - - .icon { - display: flex; - justify-content: center; - align-items: center; - min-width: 34px; - height: 100%; - margin-left: -5px; - - @include themify($themes) { - color: themed('mutedColor'); - } - - img { - border-radius: $border-radius; - max-height: 20px; - max-width: 20px; - } - } - - &.totp { - .totp-code { - font-family: $font-family-monospace; - font-size: 1.1em; - } - - .totp-countdown { - margin: 3px 3px 0 0; - display: block; - user-select: none; - - .totp-sec { - font-size: 0.85em; - position: absolute; - line-height: 32px; - width: 32px; - text-align: center; - } - - svg { - width: 32px; - height: 32px; - transform: rotate(-90deg); - } - - .totp-circle { - fill: none; - - @include themify($themes) { - stroke: themed('totpStrokeColor'); - } - - &.inner { - stroke-width: 3; - stroke-dasharray: 78.6; - stroke-dashoffset: 0; - } - - &.outer { - stroke-width: 2; - stroke-dasharray: 88; - stroke-dashoffset: 0; - } - } - } - - &.low { - .totp-sec, .totp-code { - @include themify($themes) { - color: themed('dangerColor'); - } - } - - .totp-circle { - @include themify($themes) { - stroke: themed('dangerColor'); - } - } - } - } - - .progress { - display: flex; - height: 5px; - overflow: hidden; - margin: 5px -15px -10px; - - .progress-bar { - display: flex; - flex-direction: column; - justify-content: center; - white-space: nowrap; - background-color: $brand-primary; - } - } - } - &.condensed .box-content-row, .box-content-row.condensed { padding-top: 5px; padding-bottom: 5px; @@ -503,3 +137,391 @@ display: flex; flex-direction: column; } + +.box-content-row { + display: block; + padding: 10px 15px; + position: relative; + z-index: 1; + + &:before { + content: ""; + position: absolute; + right: 0; + bottom: 0; + height: 1px; + width: calc(100% - 10px); + border-bottom: 1px solid #000000; + + @include themify($themes) { + border-bottom-color: themed('boxBorderColor'); + } + } + + &:last-child { + &:before { + border: none; + height: 0; + } + } + + &:after { + content: ""; + display: table; + clear: both; + } + + &:hover, &:focus, &.active { + @include themify($themes) { + background-color: themed('boxBackgroundHoverColor'); + } + } + + &.pre { + white-space: pre; + overflow-x: auto; + } + + &.pre-line { + white-space: pre-line; + overflow-x: auto; + } + + .row-label, label { + font-size: $font-size-small; + display: block; + width: 100%; + margin-bottom: 5px; + + @include themify($themes) { + color: themed('mutedColor'); + } + + .sub-label { + margin-left: 10px; + } + } + + .text, .detail { + display: block; + + @include themify($themes) { + color: themed('textColor'); + } + } + + .detail { + font-size: $font-size-small; + + @include themify($themes) { + color: themed('mutedColor'); + } + } + + .img-right { + float: right; + margin-left: 10px; + } + + .row-main { + flex-grow: 1; + } + + &.box-content-row-flex, .box-content-row-flex, &.box-content-row-checkbox, + &.box-content-row-input, &.box-content-row-slider, &.box-content-row-multi { + display: flex; + align-items: center; + word-break: break-all; + } + + &.box-content-row-multi { + width: 100%; + + input:not([type="checkbox"]) { + width: 100%; + } + + input + label.sr-only + select { + margin-top: 5px; + } + + > a { + padding: 8px 8px 8px 4px; + margin: 0; + + @include themify($themes) { + color: themed('dangerColor'); + } + } + } + + + &.box-content-row-multi, &.box-content-row-newmulti { + padding-left: 10px; + } + + &.box-content-row-checkbox, &.box-content-row-input, &.box-content-row-slider { + label, .row-label { + font-size: $font-size-base; + display: block; + width: initial; + margin-bottom: 0; + + @include themify($themes) { + color: themed('textColor'); + } + } + + > span { + @include themify($themes) { + color: themed('mutedColor'); + } + } + + > input { + margin: 0 0 0 auto; + padding: 0; + } + + > * { + margin-right: 15px; + + &:last-child { + margin-right: 0; + } + } + } + + &.box-content-row-input { + label { + white-space: nowrap; + } + + input { + text-align: right; + + &[type="number"] { + max-width: 50px; + } + } + } + + &.box-content-row-slider { + input[type="range"] { + height: 10px; + } + + input[type="number"] { + width: 45px; + } + + label { + white-space: nowrap; + } + } + + input:not([type="checkbox"]), textarea { + border: none; + width: 100%; + background-color: transparent; + + &::-webkit-input-placeholder { + @include themify($themes) { + color: themed('inputPlaceholderColor'); + } + } + + &:focus { + outline: none; + } + } + + select { + width: 100%; + border: 1px solid #000000; + border-radius: $border-radius; + + @include themify($themes) { + border-color: themed('inputBorderColor'); + } + } + + .action-buttons { + display: flex; + margin-left: 5px; + + .row-btn { + cursor: pointer; + padding: 10px 8px; + background: none; + border: none; + + @include themify($themes) { + color: themed('boxRowButtonColor'); + } + + &:hover, &:focus { + @include themify($themes) { + color: themed('boxRowButtonHoverColor'); + } + } + + &.disabled { + @include themify($themes) { + color: themed('disabledIconColor'); + } + + &:hover { + @include themify($themes) { + color: themed('disabledIconColor'); + } + } + } + + &:last-child { + padding-right: 2px !important; + } + } + + &.no-pad .row-btn { + padding-top: 0; + padding-bottom: 0; + } + } + + select.field-type { + margin: 5px 0 0 25px; + width: calc(100% - 25px); + } + + .row-sub-icon, .row-sub-label + i.fa { + @include themify($themes) { + color: themed('disabledIconColor'); + } + } + + .row-sub-label { + margin: 0 15px; + white-space: nowrap; + + @include themify($themes) { + color: themed('mutedColor'); + } + } + + .icon { + display: flex; + justify-content: center; + align-items: center; + min-width: 34px; + height: 100%; + margin-left: -5px; + + @include themify($themes) { + color: themed('mutedColor'); + } + + img { + border-radius: $border-radius; + max-height: 20px; + max-width: 20px; + } + } + + &.totp { + .totp-code { + font-family: $font-family-monospace; + font-size: 1.1em; + } + + .totp-countdown { + margin: 3px 3px 0 0; + display: block; + user-select: none; + + .totp-sec { + font-size: 0.85em; + position: absolute; + line-height: 32px; + width: 32px; + text-align: center; + } + + svg { + width: 32px; + height: 32px; + transform: rotate(-90deg); + } + + .totp-circle { + fill: none; + + @include themify($themes) { + stroke: themed('totpStrokeColor'); + } + + &.inner { + stroke-width: 3; + stroke-dasharray: 78.6; + stroke-dashoffset: 0; + } + + &.outer { + stroke-width: 2; + stroke-dasharray: 88; + stroke-dashoffset: 0; + } + } + } + + &.low { + .totp-sec, .totp-code { + @include themify($themes) { + color: themed('dangerColor'); + } + } + + .totp-circle { + @include themify($themes) { + stroke: themed('dangerColor'); + } + } + } + } + + .progress { + display: flex; + height: 5px; + overflow: hidden; + margin: 5px -15px -10px; + + .progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + white-space: nowrap; + background-color: $brand-primary; + } + } +} + +.box-drag-handle { + cursor: move; + user-select: none; + margin-left: 5px; + + @include themify($themes) { + color: themed('mutedColor'); + } +} + +.cdk-drag-preview { + position: relative; + display: flex; + align-items: center; + opacity: .8; + + @include themify($themes) { + background-color: themed('boxBackgroundColor'); + } +} diff --git a/src/popup/vault/add-edit.component.html b/src/popup/vault/add-edit.component.html index 69a1415a266..c5bfbd88f3d 100644 --- a/src/popup/vault/add-edit.component.html +++ b/src/popup/vault/add-edit.component.html @@ -275,35 +275,40 @@ {{'customFields' | i18n}}
- -
- - - - - -
- - - -
- -
- - +
+ +
+ + + + +
+ + + +
+ +
+ + + +
+ + +
-
- + +