Merge branch 'main' into webhooks

This commit is contained in:
Chen-I Lim 2020-10-30 10:58:12 -07:00
commit c96bfba6bf
38 changed files with 708 additions and 77 deletions

276
webapp/package-lock.json generated
View file

@ -8,7 +8,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.4"
}
@ -103,7 +102,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
"integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
"dev": true,
"requires": {
"@babel/types": "^7.10.4"
}
@ -172,8 +170,7 @@
"@babel/helper-validator-identifier": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
"dev": true
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
},
"@babel/helpers": {
"version": "7.10.4",
@ -190,7 +187,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"chalk": "^2.0.0",
@ -201,7 +197,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
@ -210,7 +205,6 @@
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@ -221,7 +215,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
@ -229,20 +222,17 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
@ -404,7 +394,6 @@
"version": "7.11.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
"integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"lodash": "^4.17.19",
@ -427,6 +416,94 @@
"minimist": "^1.2.0"
}
},
"@emotion/cache": {
"version": "10.0.29",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz",
"integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==",
"requires": {
"@emotion/sheet": "0.9.4",
"@emotion/stylis": "0.8.5",
"@emotion/utils": "0.11.3",
"@emotion/weak-memoize": "0.2.5"
}
},
"@emotion/core": {
"version": "10.0.35",
"resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.0.35.tgz",
"integrity": "sha512-sH++vJCdk025fBlRZSAhkRlSUoqSqgCzYf5fMOmqqi3bM6how+sQpg3hkgJonj8GxXM4WbD7dRO+4tegDB9fUw==",
"requires": {
"@babel/runtime": "^7.5.5",
"@emotion/cache": "^10.0.27",
"@emotion/css": "^10.0.27",
"@emotion/serialize": "^0.11.15",
"@emotion/sheet": "0.9.4",
"@emotion/utils": "0.11.3"
}
},
"@emotion/css": {
"version": "10.0.27",
"resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz",
"integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==",
"requires": {
"@emotion/serialize": "^0.11.15",
"@emotion/utils": "0.11.3",
"babel-plugin-emotion": "^10.0.27"
}
},
"@emotion/hash": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
},
"@emotion/memoize": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
},
"@emotion/serialize": {
"version": "0.11.16",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz",
"integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==",
"requires": {
"@emotion/hash": "0.8.0",
"@emotion/memoize": "0.7.4",
"@emotion/unitless": "0.7.5",
"@emotion/utils": "0.11.3",
"csstype": "^2.5.7"
},
"dependencies": {
"csstype": {
"version": "2.6.13",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz",
"integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A=="
}
}
},
"@emotion/sheet": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz",
"integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA=="
},
"@emotion/stylis": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
"integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
},
"@emotion/unitless": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
},
"@emotion/utils": {
"version": "0.11.3",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz",
"integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw=="
},
"@emotion/weak-memoize": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz",
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
},
"@eslint/eslintrc": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
@ -1450,6 +1527,11 @@
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
"dev": true
},
"@types/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
},
"@types/prettier": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.2.tgz",
@ -1509,6 +1591,26 @@
"@types/react-router": "*"
}
},
"@types/react-select": {
"version": "3.0.22",
"resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-3.0.22.tgz",
"integrity": "sha512-fqgmC979JPr/6476Pau6QnmI9zVV664R7Q92Ld1rgTn+umtUXT5X3+PO/x6O4imCZnh7XCqZcouabWAlAQJNpQ==",
"dev": true,
"requires": {
"@types/react": "*",
"@types/react-dom": "*",
"@types/react-transition-group": "*"
}
},
"@types/react-transition-group": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz",
"integrity": "sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w==",
"dev": true,
"requires": {
"@types/react": "*"
}
},
"@types/source-list-map": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
@ -2275,6 +2377,30 @@
}
}
},
"babel-plugin-emotion": {
"version": "10.0.33",
"resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.33.tgz",
"integrity": "sha512-bxZbTTGz0AJQDHm8k6Rf3RQJ8tX2scsfsRyKVgAbiUPUNIRtlK+7JxP+TAd1kRLABFxe0CFm2VdK4ePkoA9FxQ==",
"requires": {
"@babel/helper-module-imports": "^7.0.0",
"@emotion/hash": "0.8.0",
"@emotion/memoize": "0.7.4",
"@emotion/serialize": "^0.11.16",
"babel-plugin-macros": "^2.0.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"convert-source-map": "^1.5.0",
"escape-string-regexp": "^1.0.5",
"find-root": "^1.1.0",
"source-map": "^0.5.7"
},
"dependencies": {
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
}
}
},
"babel-plugin-istanbul": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
@ -2300,6 +2426,21 @@
"@types/babel__traverse": "^7.0.6"
}
},
"babel-plugin-macros": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz",
"integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==",
"requires": {
"@babel/runtime": "^7.7.2",
"cosmiconfig": "^6.0.0",
"resolve": "^1.12.0"
}
},
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
},
"babel-preset-current-node-syntax": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.4.tgz",
@ -2657,8 +2798,7 @@
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
},
"camel-case": {
"version": "4.1.1",
@ -2980,7 +3120,6 @@
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
"integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.1"
},
@ -2988,8 +3127,7 @@
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
}
},
@ -3064,6 +3202,18 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
"cosmiconfig": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
"requires": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.1.0",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.7.2"
}
},
"create-ecdh": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
@ -3467,6 +3617,15 @@
"utila": "~0.4"
}
},
"dom-helpers": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz",
"integrity": "sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==",
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"dom-serializer": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
@ -3711,7 +3870,6 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dev": true,
"requires": {
"is-arrayish": "^0.2.1"
}
@ -3749,8 +3907,7 @@
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"escodegen": {
"version": "1.14.3",
@ -4802,8 +4959,7 @@
"find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"dev": true
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
},
"find-up": {
"version": "4.1.0",
@ -5634,7 +5790,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
"integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
"dev": true,
"requires": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
@ -5643,8 +5798,7 @@
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
}
}
},
@ -5783,8 +5937,7 @@
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-binary-path": {
"version": "2.1.0",
@ -7470,8 +7623,7 @@
"json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"dev": true
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
},
"json-schema": {
"version": "0.2.3",
@ -7590,8 +7742,7 @@
"lines-and-columns": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
"dev": true
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA="
},
"load-json-file": {
"version": "2.0.0",
@ -7657,8 +7808,7 @@
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"lodash.memoize": {
"version": "4.1.2",
@ -7769,6 +7919,11 @@
"safe-buffer": "^5.1.2"
}
},
"memoize-one": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
"integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
},
"memory-fs": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
@ -8597,7 +8752,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"requires": {
"callsites": "^3.0.0"
}
@ -8619,7 +8773,6 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz",
"integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
@ -8689,8 +8842,7 @@
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"path-to-regexp": {
"version": "1.8.0",
@ -8703,8 +8855,7 @@
"path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
},
"pbkdf2": {
"version": "3.1.1",
@ -9097,6 +9248,14 @@
"scheduler": "^0.19.1"
}
},
"react-input-autosize": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
"integrity": "sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw==",
"requires": {
"prop-types": "^15.5.8"
}
},
"react-intl": {
"version": "5.8.6",
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.8.6.tgz",
@ -9159,6 +9318,21 @@
"tiny-warning": "^1.0.0"
}
},
"react-select": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-3.1.0.tgz",
"integrity": "sha512-wBFVblBH1iuCBprtpyGtd1dGMadsG36W5/t2Aj8OE6WbByDg5jIFyT7X5gT+l0qmT5TqWhxX+VsKJvCEl2uL9g==",
"requires": {
"@babel/runtime": "^7.4.4",
"@emotion/cache": "^10.0.9",
"@emotion/core": "^10.0.9",
"@emotion/css": "^10.0.9",
"memoize-one": "^5.0.0",
"prop-types": "^15.6.0",
"react-input-autosize": "^2.2.2",
"react-transition-group": "^4.3.0"
}
},
"react-simplemde-editor": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/react-simplemde-editor/-/react-simplemde-editor-4.1.3.tgz",
@ -9176,6 +9350,17 @@
}
}
},
"react-transition-group": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
"integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
"requires": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
}
},
"read-pkg": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
@ -9399,7 +9584,6 @@
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
}
@ -10760,8 +10944,7 @@
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
"dev": true
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"to-object-path": {
"version": "0.3.0",
@ -12458,6 +12641,11 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"yaml": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz",
"integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg=="
},
"yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",

View file

@ -20,6 +20,7 @@
"react-dom": "^16.13.1",
"react-intl": "^5.8.6",
"react-router-dom": "^5.2.0",
"react-select": "^3.1.0",
"react-simplemde-editor": "^4.1.3"
},
"jest": {
@ -40,6 +41,7 @@
"@types/react-dom": "^16.9.8",
"@types/react-intl": "^3.0.0",
"@types/react-router-dom": "^5.1.6",
"@types/react-select": "^3.0.22",
"@typescript-eslint/eslint-plugin": "^4.4.1",
"@typescript-eslint/parser": "^4.4.1",
"copy-webpack-plugin": "^6.0.3",

View file

@ -11,6 +11,8 @@ import mutator from '../mutator'
import MenuWrapper from '../widgets/menuWrapper'
import Menu from '../widgets/menu'
import OptionsIcon from '../widgets/icons/options'
import DeleteIcon from '../widgets/icons/delete'
import DuplicateIcon from '../widgets/icons/duplicate'
import PropertyValueElement from './propertyValueElement'
@ -89,11 +91,13 @@ class BoardCard extends React.Component<BoardCardProps, BoardCardState> {
<div className='octo-hoverbutton square'><OptionsIcon/></div>
<Menu>
<Menu.Text
icon={<DeleteIcon/>}
id='delete'
name={intl.formatMessage({id: 'BoardCard.delete', defaultMessage: 'Delete'})}
onClick={() => mutator.deleteBlock(card, 'delete card')}
/>
<Menu.Text
icon={<DuplicateIcon/>}
id='duplicate'
name={intl.formatMessage({id: 'BoardCard.duplicate', defaultMessage: 'Duplicate'})}
onClick={() => mutator.insertBlock(MutableBlock.duplicate(card), 'duplicate card')}

View file

@ -16,6 +16,9 @@ import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import OptionsIcon from '../widgets/icons/options'
import AddIcon from '../widgets/icons/add'
import HideIcon from '../widgets/icons/hide'
import ShowIcon from '../widgets/icons/show'
import DeleteIcon from '../widgets/icons/delete'
import Button from '../widgets/buttons/button'
import BoardCard from './boardCard'
@ -309,6 +312,7 @@ class BoardComponent extends React.Component<Props, State> {
<Menu>
<Menu.Text
id='hide'
icon={<HideIcon/>}
name={intl.formatMessage({id: 'BoardComponent.hide', defaultMessage: 'Hide'})}
onClick={() => mutator.hideViewColumn(activeView, '')}
/>
@ -372,11 +376,13 @@ class BoardComponent extends React.Component<Props, State> {
<Menu>
<Menu.Text
id='hide'
icon={<HideIcon/>}
name={intl.formatMessage({id: 'BoardComponent.hide', defaultMessage: 'Hide'})}
onClick={() => mutator.hideViewColumn(activeView, group.option.id)}
/>
<Menu.Text
id='delete'
icon={<DeleteIcon/>}
name={intl.formatMessage({id: 'BoardComponent.delete', defaultMessage: 'Delete'})}
onClick={() => mutator.deletePropertyOption(boardTree, boardTree.groupByProperty, group.option)}
/>
@ -450,6 +456,7 @@ class BoardComponent extends React.Component<Props, State> {
<Menu>
<Menu.Text
id='show'
icon={<ShowIcon/>}
name={intl.formatMessage({id: 'BoardComponent.show', defaultMessage: 'Show'})}
onClick={() => mutator.unhideViewColumn(activeView, group.option.id)}
/>

View file

@ -32,6 +32,10 @@
display: flex;
flex-direction: row;
margin: 8px 0;
.MenuWrapper {
display: flex;
align-items: center;
}
}
.octo-propertyname {

View file

@ -193,6 +193,7 @@ class CardDetail extends React.Component<Props, State> {
<PropertyValueElement
readOnly={false}
card={card}
boardTree={boardTree}
propertyTemplate={propertyTemplate}
emptyDisplayValue='Empty'
/>

View file

@ -6,6 +6,7 @@ import {Card} from '../blocks/card'
import {BoardTree} from '../viewModel/boardTree'
import mutator from '../mutator'
import Menu from '../widgets/menu'
import DeleteIcon from '../widgets/icons/delete'
import CardDetail from './cardDetail'
import Dialog from './dialog'
@ -22,6 +23,7 @@ class CardDialog extends React.Component<Props> {
<Menu position='left'>
<Menu.Text
id='delete'
icon={<DeleteIcon/>}
name='Delete'
onClick={async () => {
await mutator.deleteBlock(this.props.card, 'delete card')

View file

@ -8,6 +8,7 @@ import {IBlock} from '../blocks/block'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import DeleteIcon from '../widgets/icons/delete'
import './comment.scss'
import {Utils} from '../utils'
@ -36,8 +37,9 @@ const Comment: FC<Props> = (props: Props) => {
<div className='comment-date'>{(new Date(comment.createAt)).toLocaleTimeString()}</div>
<MenuWrapper>
<div className='octo-hoverbutton square'>{'...'}</div>
<Menu>
<Menu position='left'>
<Menu.Text
icon={<DeleteIcon/>}
id='delete'
name={intl.formatMessage({id: 'Comment.delete', defaultMessage: 'Delete'})}
onClick={() => mutator.deleteBlock(comment)}

View file

@ -0,0 +1,10 @@
.ContentBlock {
.MenuWrapper {
display: none;
}
&:hover {
.MenuWrapper {
display: flex;
}
}
}

View file

@ -13,9 +13,17 @@ import {MutableTextBlock} from '../blocks/textBlock'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import OptionsIcon from '../widgets/icons/options'
import SortUpIcon from '../widgets/icons/sortUp'
import SortDownIcon from '../widgets/icons/sortDown'
import DeleteIcon from '../widgets/icons/delete'
import AddIcon from '../widgets/icons/add'
import TextIcon from '../widgets/icons/text'
import ImageIcon from '../widgets/icons/image'
import {MarkdownEditor} from './markdownEditor'
import './contentBlock.scss'
type Props = {
block: IOrderedBlock
cardId: string
@ -23,7 +31,7 @@ type Props = {
}
class ContentBlock extends React.Component<Props> {
shouldComponentUpdate() {
shouldComponentUpdate(): boolean {
return true
}
@ -34,15 +42,16 @@ class ContentBlock extends React.Component<Props> {
}
const index = cardTree.contents.indexOf(block)
return (
<div className='octo-block octo-hover-container'>
<div className='ContentBlock octo-block'>
<div className='octo-block-margin'>
<MenuWrapper>
<div className='octo-button octo-hovercontrol square octo-hover-item'><OptionsIcon/></div>
<div className='octo-button octo-hovercontrol square '><OptionsIcon/></div>
<Menu>
{index > 0 &&
<Menu.Text
id='moveUp'
name='Move up'
icon={<SortUpIcon/>}
onClick={() => {
const previousBlock = cardTree.contents[index - 1]
const newOrder = OctoUtils.getOrderBefore(previousBlock, cardTree.contents)
@ -54,6 +63,7 @@ class ContentBlock extends React.Component<Props> {
<Menu.Text
id='moveDown'
name='Move down'
icon={<SortDownIcon/>}
onClick={() => {
const nextBlock = cardTree.contents[index + 1]
const newOrder = OctoUtils.getOrderAfter(nextBlock, cardTree.contents)
@ -64,10 +74,12 @@ class ContentBlock extends React.Component<Props> {
<Menu.SubMenu
id='insertAbove'
name='Insert above'
icon={<AddIcon/>}
>
<Menu.Text
id='text'
name='Text'
icon={<TextIcon/>}
onClick={() => {
const newBlock = new MutableTextBlock()
newBlock.parentId = cardId
@ -81,6 +93,7 @@ class ContentBlock extends React.Component<Props> {
<Menu.Text
id='image'
name='Image'
icon={<ImageIcon/>}
onClick={() => {
Utils.selectLocalFile(
(file) => {
@ -91,6 +104,7 @@ class ContentBlock extends React.Component<Props> {
/>
</Menu.SubMenu>
<Menu.Text
icon={<DeleteIcon/>}
id='delete'
name='Delete'
onClick={() => mutator.deleteBlock(block)}

View file

@ -7,12 +7,17 @@ import {Card} from '../blocks/card'
import {IPropertyTemplate, IPropertyOption} from '../blocks/board'
import {OctoUtils} from '../octoUtils'
import mutator from '../mutator'
import {Utils} from '../utils'
import {BoardTree} from '../viewModel/boardTree'
import Editable from '../widgets/editable'
import MenuWrapper from '../widgets/menuWrapper'
import Menu from '../widgets/menu'
import ValueSelector from '../widgets/valueSelector'
import {skipPartiallyEmittedExpressions} from 'typescript'
type Props = {
boardTree?: BoardTree
readOnly: boolean
card: Card
propertyTemplate: IPropertyTemplate
@ -54,32 +59,35 @@ export default class PropertyValueElement extends React.Component<Props, State>
className += ' empty'
}
return (
<MenuWrapper>
if (readOnly) {
return (
<div
className={`${className} ${propertyColorCssClassName}`}
tabIndex={0}
>
{finalDisplayValue}
</div>
{readOnly ? null : (
<Menu>
<Menu.Text
id=''
name='<Empty>'
onClick={() => mutator.changePropertyValue(card, propertyTemplate.id, '')}
/>
{propertyTemplate.options.map((o: IPropertyOption): JSX.Element => (
<Menu.Text
key={o.id}
id={o.id}
name={o.value}
onClick={() => mutator.changePropertyValue(card, propertyTemplate.id, o.id)}
/>
))}
</Menu>
)}
</MenuWrapper>
)
}
return (
<ValueSelector
options={propertyTemplate.options}
value={propertyTemplate.options.find((p) => p.id === propertyValue)}
onChange={(value) => {
mutator.changePropertyValue(card, propertyTemplate.id, value)
}}
onCreate={
async (value) => {
const option: IPropertyOption = {
id: Utils.createGuid(),
value,
color: 'propColorDefault',
}
await mutator.insertPropertyOption(this.props.boardTree, propertyTemplate, option, 'add property option')
mutator.changePropertyValue(card, propertyTemplate.id, option.id)
}
}
/>
)
}

View file

@ -90,4 +90,13 @@
cursor: pointer;
flex-grow: 1;
}
.OptionsIcon, .SubmenuTriangleIcon, .DotIcon {
fill: rgba(var(--sidebar-fg), 0.5);
}
.HideSidebarIcon {
stroke: rgba(var(--sidebar-fg), 0.5);
stroke-width: 6px;
}
}

View file

@ -15,7 +15,6 @@
font-size: 14px;
line-height: 21px;
overflow: hidden;
position: relative;
.octo-icontitle {

View file

@ -114,6 +114,7 @@ class TableRow extends React.Component<Props, State> {
<PropertyValueElement
readOnly={false}
card={card}
boardTree={boardTree}
propertyTemplate={template}
emptyDisplayValue='Empty'
/>

View file

@ -21,11 +21,13 @@ import DropdownIcon from '../widgets/icons/dropdown'
import OptionsIcon from '../widgets/icons/options'
import SortUpIcon from '../widgets/icons/sortUp'
import SortDownIcon from '../widgets/icons/sortDown'
import ButtonWithMenu from '../widgets/buttons/buttonWithMenu'
import {Editable} from './editable'
import FilterComponent from './filterComponent'
import './viewHeader.scss'
import {sendFlashMessage} from './flashMessages'
type Props = {
boardTree?: BoardTree
@ -348,17 +350,33 @@ class ViewHeader extends React.Component<Props, State> {
/>
</Menu>
</MenuWrapper>
<div
className='octo-button filled'
<ButtonWithMenu
onClick={() => {
this.props.addCard(true)
}}
text={(
<FormattedMessage
id='ViewHeader.new'
defaultMessage='New'
/>
)}
>
<FormattedMessage
id='ViewHeader.new'
defaultMessage='New'
/>
</div>
<Menu position='left'>
<Menu.Label>
<b>
<FormattedMessage
id='ViewHeader.select-a-template'
defaultMessage='Select a template'
/>
</b>
</Menu.Label>
<Menu.Text
id='example-template'
name={intl.formatMessage({id: 'ViewHeader.sample-templte', defaultMessage: 'Sample template'})}
onClick={() => sendFlashMessage({content: 'Not implemented yet', severity: 'low'})}
/>
</Menu>
</ButtonWithMenu>
</div>
)
}

View file

@ -0,0 +1,40 @@
.ButtonWithMenu.octo-button {
display: flex;
align-items: stretch;
text-align: center;
min-width: 20px;
cursor: pointer;
overflow: visible;
padding: 0;
.button-text {
padding: 3px 10px;
background-color: rgb(var(--button-bg));
color: rgb(var(--button-fg));
border-radius: 5px 0 0 5px;
transition: background 100ms ease-out 0s;
height: 100%;
&:hover {
background-color: rgba(var(--button-bg), 0.8);
}
}
.button-dropdown {
background-color: rgb(var(--button-bg));
border-left: 1px solid rgba(var(--button-fg), 0.2);
display: flex;
padding: 0 3px;
align-items: center;
border-radius: 0 5px 5px 0;
transition: background 100ms ease-out 0s;
height: 100%;
&:hover {
background-color: rgba(var(--button-bg), 0.8);
}
.DropdownIcon {
stroke: rgb(var(--button-fg));
}
}
}

View file

@ -0,0 +1,37 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import DropdownIcon from '../icons/dropdown'
import MenuWrapper from '../menuWrapper'
import './buttonWithMenu.scss'
type Props = {
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
children?: React.ReactNode
title?: string
text: React.ReactNode
}
export default class ButtonWithMenu extends React.PureComponent<Props> {
public render(): JSX.Element {
return (
<div
onClick={this.props.onClick}
className='ButtonWithMenu octo-button'
title={this.props.title}
>
<div className='button-text'>
{this.props.text}
</div>
<MenuWrapper stopPropagationOnToggle={true}>
<div className='button-dropdown'>
<DropdownIcon/>
</div>
{this.props.children}
</MenuWrapper>
</div>
)
}
}

View file

@ -1,6 +1,8 @@
.Editable {
cursor: text;
border: 0;
overflow: hidden;
text-overflow: ellipsis;
&.active {
min-width: 100px;
}

View file

@ -0,0 +1,6 @@
.DeleteIcon {
fill: rgba(var(--main-fg), 0.7);
stroke: none;
width: 24px;
height: 24px;
}

View file

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './delete.scss'
export default function DeleteIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='DeleteIcon Icon'
viewBox='0 0 448 512'
>
<path
d='M268 416h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12zM432 80h-82.41l-34-56.7A48 48 0 0 0 274.41 0H173.59a48 48 0 0 0-41.16 23.3L98.41 80H16A16 16 0 0 0 0 96v16a16 16 0 0 0 16 16h16v336a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128h16a16 16 0 0 0 16-16V96a16 16 0 0 0-16-16zM171.84 50.91A6 6 0 0 1 177 48h94a6 6 0 0 1 5.15 2.91L293.61 80H154.39zM368 464H80V128h288zm-212-48h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12z'
/>
</svg>
)
}

View file

@ -0,0 +1,6 @@
.DuplicateIcon {
fill: rgba(var(--main-fg), 0.7);
stroke: none;
width: 24px;
height: 24px;
}

View file

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './duplicate.scss'
export default function DuplicateIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='DuplicateIcon Icon'
viewBox='0 0 512 512'
>
<path
d='M464 0H144c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h48c26.51 0 48-21.49 48-48V48c0-26.51-21.49-48-48-48zM362 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h42v224c0 26.51 21.49 48 48 48h224v42a6 6 0 0 1-6 6zm96-96H150a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v308a6 6 0 0 1-6 6z'
/>
</svg>
)
}

View file

@ -0,0 +1,6 @@
.HideIcon {
fill: rgba(var(--main-fg), 0.7);
stroke: none;
width: 24px;
height: 24px;
}

View file

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './hide.scss'
export default function HideIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='HideIcon Icon'
viewBox='0 0 640 512'
>
<path
d='M634 471L36 3.51A16 16 0 0 0 13.51 6l-10 12.49A16 16 0 0 0 6 41l598 467.49a16 16 0 0 0 22.49-2.49l10-12.49A16 16 0 0 0 634 471zM296.79 146.47l134.79 105.38C429.36 191.91 380.48 144 320 144a112.26 112.26 0 0 0-23.21 2.47zm46.42 219.07L208.42 260.16C210.65 320.09 259.53 368 320 368a113 113 0 0 0 23.21-2.46zM320 112c98.65 0 189.09 55 237.93 144a285.53 285.53 0 0 1-44 60.2l37.74 29.5a333.7 333.7 0 0 0 52.9-75.11 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64c-36.7 0-71.71 7-104.63 18.81l46.41 36.29c18.94-4.3 38.34-7.1 58.22-7.1zm0 288c-98.65 0-189.08-55-237.93-144a285.47 285.47 0 0 1 44.05-60.19l-37.74-29.5a333.6 333.6 0 0 0-52.89 75.1 32.35 32.35 0 0 0 0 29.19C89.72 376.41 197.08 448 320 448c36.7 0 71.71-7.05 104.63-18.81l-46.41-36.28C359.28 397.2 339.89 400 320 400z'
/>
</svg>
)
}

View file

@ -0,0 +1,6 @@
.ImageIcon {
fill: rgba(var(--main-fg), 0.7);
stroke: none;
width: 24px;
height: 24px;
}

View file

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './image.scss'
export default function ImageIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='ImageIcon Icon'
viewBox='0 0 512 512'
>
<path
d='M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-6 336H54a6 6 0 0 1-6-6V118a6 6 0 0 1 6-6h404a6 6 0 0 1 6 6v276a6 6 0 0 1-6 6zM128 152c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zM96 352h320v-80l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L192 304l-39.515-39.515c-4.686-4.686-12.284-4.686-16.971 0L96 304v48z'
/>
</svg>
)
}

View file

@ -0,0 +1,6 @@
.ShowIcon {
fill: rgba(var(--main-fg), 0.7);
stroke: none;
width: 24px;
height: 24px;
}

View file

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './show.scss'
export default function ShowIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='ShowIcon Icon'
viewBox='0 0 576 512'
>
<path
d='M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z'
/>
</svg>
)
}

View file

@ -0,0 +1,6 @@
.TextIcon {
fill: rgba(var(--main-fg), 0.7);
stroke: none;
width: 24px;
height: 24px;
}

View file

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './text.scss'
export default function TextIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='TextIcon Icon'
viewBox='0 0 448 512'
>
<path
d='M432 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-128H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-128H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-128H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z'
/>
</svg>
)
}

View file

@ -0,0 +1,8 @@
.Menu {
.LabelOption.menu-option {
cursor: auto;
&:hover {
background: inherit;
}
}
}

View file

@ -0,0 +1,21 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './labelOption.scss'
type LabelOptionProps = {
icon?: string
children: React.ReactNode
}
export default class LabelOption extends React.PureComponent<LabelOptionProps> {
public render(): JSX.Element {
return (
<div className='MenuOption LabelOption menu-option'>
<div className='menu-name'>{this.props.children}</div>
{this.props.icon}
</div>
)
}
}

View file

@ -43,5 +43,14 @@
.menu-name {
flex-grow: 1;
}
.SubmenuTriangleIcon {
fill: rgba(var(--main-fg), 0.7);
}
.Icon {
width: 16px;
height: 16px;
margin-right: 5px;
}
}
}

View file

@ -7,6 +7,7 @@ import SwitchOption from './switchOption'
import TextOption from './textOption'
import ColorOption from './colorOption'
import SubMenuOption from './subMenuOption'
import LabelOption from './labelOption'
import './menu.scss'
@ -21,6 +22,7 @@ export default class Menu extends React.PureComponent<MenuProps> {
static Switch = SwitchOption
static Separator = SeparatorOption
static Text = TextOption
static Label = LabelOption
public render(): JSX.Element {
const {position, children} = this.props

View file

@ -10,6 +10,7 @@ import './subMenuOption.scss'
type SubMenuOptionProps = MenuOptionProps & {
position?: 'bottom' | 'top'
icon?: React.ReactNode
}
type SubMenuState = {
@ -36,6 +37,7 @@ export default class SubMenuOption extends React.PureComponent<SubMenuOptionProp
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.close}
>
{this.props.icon}
<div className='menu-name'>{this.props.name}</div>
<SubmenuTriangleIcon/>
{this.state.isOpen &&

View file

@ -20,8 +20,8 @@ export default class TextOption extends React.PureComponent<TextOptionProps> {
className='MenuOption TextOption menu-option'
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon}
<div className='menu-name'>{name}</div>
</div>
)
}

View file

@ -0,0 +1,8 @@
.ValueSelector {
width: 100%;
border-radius: 5px;
color: rgb(var(--main-fg));
&:hover {
background-color: rgba(var(--main-fg), 0.1),
}
}

View file

@ -0,0 +1,77 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {CSSProperties} from 'react'
import {ActionMeta, ValueType} from 'react-select'
import CreatableSelect from 'react-select/creatable';
import boardCard from 'src/components/boardCard';
import {IPropertyOption} from '../blocks/board'
import './valueSelector.scss'
type Props = {
options: IPropertyOption[]
value: IPropertyOption;
onCreate?: (value: string) => void
onChange?: (value: string) => void
}
export default class ValueSelector extends React.Component<Props> {
public shouldComponentUpdate(): boolean {
return true
}
public render(): JSX.Element {
return (
<CreatableSelect
styles={{
indicatorsContainer: (provided: CSSProperties): CSSProperties => ({
...provided,
display: 'none',
}),
menu: (provided: CSSProperties): CSSProperties => ({
...provided,
background: 'rgb(var(--main-bg))',
}),
option: (provided: CSSProperties, state: {isFocused: boolean}): CSSProperties => ({
...provided,
background: state.isFocused ? 'rgb(var(--button-bg))' : 'rgb(var(--main-bg))',
color: state.isFocused ? 'rgb(var(--button-fg))' : 'rgb(var(--main-fg))',
padding: '2px 8px',
}),
control: (): CSSProperties => ({
border: 0,
}),
valueContainer: (provided: CSSProperties): CSSProperties => ({
...provided,
padding: '0 8px',
}),
singleValue: (provided: CSSProperties): CSSProperties => ({
...provided,
color: 'rgb(var(--main-fg))',
}),
input: (provided: CSSProperties): CSSProperties => ({
...provided,
paddingBottom: 0,
paddingTop: 0,
marginBottom: 0,
marginTop: 0,
}),
}}
className='ValueSelector'
hideSelectedOptions={true}
options={this.props.options}
getOptionLabel={(o: IPropertyOption) => o.value}
getOptionValue={(o: IPropertyOption) => o.id}
onChange={(value: ValueType<IPropertyOption>, action: ActionMeta<IPropertyOption>): void => {
if (action.action === 'select-option') {
this.props.onChange((value as IPropertyOption).id)
}
}}
onCreateOption={this.props.onCreate}
autoFocus={true}
value={this.props.value}
closeMenuOnSelect={true}
/>
)
}
}