diff --git a/package-lock.json b/package-lock.json index 070cd6663..67958f46d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -225,20 +225,20 @@ "dev": true }, "@babel/core": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.0.tgz", - "integrity": "sha512-8YqpRig5NmIHlMLw09zMlPTvUVMILjqCOtVgu+TVNWEBvy9b5I3RRyhqnrV4hjgEK7n8P9OqvkWJAFmEL6Wwfw==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.2.tgz", + "integrity": "sha512-OgC1mON+l4U4B4wiohJlQNUU3H73mpTyYY3j/c8U9dr9UagGGSm+WFpzjy/YLdoyjiG++c1kIDgxCo/mLwQJeQ==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", + "@babel/generator": "^7.14.2", "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-module-transforms": "^7.14.0", + "@babel/helper-module-transforms": "^7.14.2", "@babel/helpers": "^7.14.0", - "@babel/parser": "^7.14.0", + "@babel/parser": "^7.14.2", "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0", + "@babel/traverse": "^7.14.2", + "@babel/types": "^7.14.2", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -257,25 +257,25 @@ } }, "@babel/generator": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz", - "integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.2.tgz", + "integrity": "sha512-OnADYbKrffDVai5qcpkMxQ7caomHOoEwjkouqnN2QhydAjowFAZcsdecFIRUBdb+ZcruwYE4ythYmF1UBZU5xQ==", "dev": true, "requires": { - "@babel/types": "^7.14.1", + "@babel/types": "^7.14.2", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", - "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", + "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.12.13", "@babel/template": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.2" } }, "@babel/helper-get-function-arity": { @@ -308,9 +308,9 @@ } }, "@babel/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.2.tgz", + "integrity": "sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ==", "dev": true }, "@babel/template": { @@ -325,25 +325,25 @@ } }, "@babel/traverse": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz", - "integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", + "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", + "@babel/generator": "^7.14.2", + "@babel/helper-function-name": "^7.14.2", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "@babel/parser": "^7.14.2", + "@babel/types": "^7.14.2", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -546,9 +546,9 @@ }, "dependencies": { "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -573,9 +573,9 @@ }, "dependencies": { "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -591,9 +591,9 @@ } }, "@babel/helper-module-transforms": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz", - "integrity": "sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz", + "integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.13.12", @@ -602,8 +602,8 @@ "@babel/helper-split-export-declaration": "^7.12.13", "@babel/helper-validator-identifier": "^7.14.0", "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" + "@babel/traverse": "^7.14.2", + "@babel/types": "^7.14.2" }, "dependencies": { "@babel/code-frame": { @@ -616,25 +616,25 @@ } }, "@babel/generator": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz", - "integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.2.tgz", + "integrity": "sha512-OnADYbKrffDVai5qcpkMxQ7caomHOoEwjkouqnN2QhydAjowFAZcsdecFIRUBdb+ZcruwYE4ythYmF1UBZU5xQ==", "dev": true, "requires": { - "@babel/types": "^7.14.1", + "@babel/types": "^7.14.2", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", - "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", + "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.12.13", "@babel/template": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.2" } }, "@babel/helper-get-function-arity": { @@ -667,9 +667,9 @@ } }, "@babel/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.2.tgz", + "integrity": "sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ==", "dev": true }, "@babel/template": { @@ -684,25 +684,25 @@ } }, "@babel/traverse": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz", - "integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", + "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", + "@babel/generator": "^7.14.2", + "@babel/helper-function-name": "^7.14.2", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "@babel/parser": "^7.14.2", + "@babel/types": "^7.14.2", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -789,9 +789,9 @@ }, "dependencies": { "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -834,25 +834,25 @@ } }, "@babel/generator": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz", - "integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.2.tgz", + "integrity": "sha512-OnADYbKrffDVai5qcpkMxQ7caomHOoEwjkouqnN2QhydAjowFAZcsdecFIRUBdb+ZcruwYE4ythYmF1UBZU5xQ==", "dev": true, "requires": { - "@babel/types": "^7.14.1", + "@babel/types": "^7.14.2", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", - "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", + "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.12.13", "@babel/template": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.2" } }, "@babel/helper-get-function-arity": { @@ -885,9 +885,9 @@ } }, "@babel/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.2.tgz", + "integrity": "sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ==", "dev": true }, "@babel/template": { @@ -902,25 +902,25 @@ } }, "@babel/traverse": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz", - "integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", + "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", + "@babel/generator": "^7.14.2", + "@babel/helper-function-name": "^7.14.2", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "@babel/parser": "^7.14.2", + "@babel/types": "^7.14.2", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -1007,9 +1007,9 @@ }, "dependencies": { "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -1066,25 +1066,25 @@ } }, "@babel/generator": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz", - "integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.2.tgz", + "integrity": "sha512-OnADYbKrffDVai5qcpkMxQ7caomHOoEwjkouqnN2QhydAjowFAZcsdecFIRUBdb+ZcruwYE4ythYmF1UBZU5xQ==", "dev": true, "requires": { - "@babel/types": "^7.14.1", + "@babel/types": "^7.14.2", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", - "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", + "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.12.13", "@babel/template": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.2" } }, "@babel/helper-get-function-arity": { @@ -1117,9 +1117,9 @@ } }, "@babel/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.2.tgz", + "integrity": "sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ==", "dev": true }, "@babel/template": { @@ -1134,25 +1134,25 @@ } }, "@babel/traverse": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz", - "integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", + "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", + "@babel/generator": "^7.14.2", + "@babel/helper-function-name": "^7.14.2", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "@babel/parser": "^7.14.2", + "@babel/types": "^7.14.2", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz", - "integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.0", @@ -1368,10 +1368,27 @@ } } }, + "@formatjs/ecma402-abstract": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.7.1.tgz", + "integrity": "sha512-FjewVLB2DVEVCvvC7IMffzXVhysvi442i6ed0H7qcrT6xtUpO4vr0oZgpOmsv6D9I4Io0GVebIuySwteS/k3gg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + } + } + }, "@formatjs/intl-getcanonicallocales": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-1.5.10.tgz", - "integrity": "sha512-tFqGxZ9HkAzphupybyCKdWHzL1ge/sY8TtzEK57Hs3RCxrv/y+VxIPrE+Izw2oCFowQBz76cyi0zT6PjHuWArA==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-1.5.11.tgz", + "integrity": "sha512-S+D4P8BSZDVTooR0AkqJUWMF6BKMyaBgM/XJiXiuOhVNg44ZYwwsD4PhnTGEbLpTpAcJX1Leway1SLfzrH8YOw==", "dev": true, "requires": { "cldr-core": "38", @@ -1387,26 +1404,17 @@ } }, "@formatjs/intl-locale": { - "version": "2.4.24", - "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-2.4.24.tgz", - "integrity": "sha512-+JOwvBRFS/GFuJlWiWbfAzBng0A+ANoGV1LRseXK+4uzp4Sn35GD8M/dfgU1lp2R2dTWpYie2yyoHe4k4aHF6w==", + "version": "2.4.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-2.4.25.tgz", + "integrity": "sha512-UgoU8TlMhjkiIJCRIgMs6JzTwYcVH9BnpL0j8Vy3A1zCXYDsRPu7TKpEQ5mrc8qkCqxz5LWZfocJqnluw/G1JQ==", "dev": true, "requires": { "@formatjs/ecma402-abstract": "1.7.1", - "@formatjs/intl-getcanonicallocales": "1.5.10", + "@formatjs/intl-getcanonicallocales": "1.5.11", "cldr-core": "38", "tslib": "^2.1.0" }, "dependencies": { - "@formatjs/ecma402-abstract": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.7.1.tgz", - "integrity": "sha512-FjewVLB2DVEVCvvC7IMffzXVhysvi442i6ed0H7qcrT6xtUpO4vr0oZgpOmsv6D9I4Io0GVebIuySwteS/k3gg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, "tslib": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", @@ -1416,24 +1424,15 @@ } }, "@formatjs/intl-pluralrules": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-4.0.18.tgz", - "integrity": "sha512-qRFITPsNoeXfsiGc97pp8mVgqcC7aQNuXsiJjY9LpXVTkYNfjUP4ZpbYXflM4xoWCXMJNz3ilsrQhZWXy9td5g==", + "version": "4.0.19", + "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-4.0.19.tgz", + "integrity": "sha512-ArxXyH1NVLHKjiEVG0Lg8BMjGJoC7M+0FZnr2ln5uhrosQoctKmTrTXpezhqw0NOKyo05jIQY/keMlfRgEpIsw==", "dev": true, "requires": { "@formatjs/ecma402-abstract": "1.7.1", "tslib": "^2.1.0" }, "dependencies": { - "@formatjs/ecma402-abstract": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.7.1.tgz", - "integrity": "sha512-FjewVLB2DVEVCvvC7IMffzXVhysvi442i6ed0H7qcrT6xtUpO4vr0oZgpOmsv6D9I4Io0GVebIuySwteS/k3gg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, "tslib": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", @@ -20856,9 +20855,9 @@ } }, "scratch-blocks": { - "version": "0.1.0-prerelease.20210510043314", - "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20210510043314.tgz", - "integrity": "sha512-wXogEeojamKgRyBxkScpchd3sDp6sZsIxYcYNtWdPIbMpNacytMzC6hXYjFfq/BUZs4Vmnnu1x2+NKKX6N8WuA==", + "version": "0.1.0-prerelease.20210514034551", + "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20210514034551.tgz", + "integrity": "sha512-OfQNiJG8lidyXBGTeWXpC6caSVroAxfmkK1mxOFdGoIW3adUJTrl6np5RXwD58ByYnerxt+AldR3kIOyNAdBrg==", "dev": true, "requires": { "exports-loader": "0.6.3", @@ -20866,9 +20865,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20210510170231", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210510170231.tgz", - "integrity": "sha512-RS12FvNZR1CoEUxtvRpHIrDQVJkPJWrIYkNS5Bjr/ZtixVN1fdRB/zHtfZ0LIbw+TOVABSyn81kKWGW011J73g==", + "version": "0.1.0-prerelease.20210514040957", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210514040957.tgz", + "integrity": "sha512-qjn3YtszSnj0iI/Bd9LXJBuudyg2T2QwJ0TOl9628/wuwexZsLxEERyHl8o9vhErUaiJ2TLeL5nTYWbMbhdA9A==", "dev": true, "requires": { "arraybuffer-loader": "^1.0.6", @@ -20919,13 +20918,13 @@ "redux": "3.7.2", "redux-throttle": "0.1.1", "scratch-audio": "0.1.0-prerelease.20200528195344", - "scratch-blocks": "0.1.0-prerelease.20210510043314", - "scratch-l10n": "3.11.20210510031549", + "scratch-blocks": "0.1.0-prerelease.20210514034551", + "scratch-l10n": "3.11.20210513031505", "scratch-paint": "0.2.0-prerelease.20210407203313", "scratch-render": "0.1.0-prerelease.20210325231800", "scratch-render-fonts": "1.0.0-prerelease.20210401210003", "scratch-storage": "1.3.4", - "scratch-svg-renderer": "0.2.0-prerelease.20210408171934", + "scratch-svg-renderer": "0.2.0-prerelease.20210511195415", "scratch-vm": "0.2.0-prerelease.20210510162256", "startaudiocontext": "1.2.1", "style-loader": "^0.23.0", @@ -21312,9 +21311,9 @@ "dev": true }, "scratch-l10n": { - "version": "3.11.20210510031549", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210510031549.tgz", - "integrity": "sha512-WeoSa4zxtOcAGeaASqVcJcZu/QWoWtHohsP71ICbNcBpcAqnpPV1AhdGNrOQyiwuj0Vy/6CBuH9QYpS0IF+AkA==", + "version": "3.11.20210513031505", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210513031505.tgz", + "integrity": "sha512-BZagwqCz1/HmCeYURZGyY+wvw7h644PyO18ZWaFTtneYorukWNv3fT1ARmwwvCwzCY4FZwJ7ksogxTlQSFirDw==", "dev": true, "requires": { "@babel/cli": "^7.1.2", @@ -21401,9 +21400,9 @@ } }, "scratch-l10n": { - "version": "3.11.20210511031531", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210511031531.tgz", - "integrity": "sha512-E+Gm8pSNgZhVEsdRXshkhk6MnKeQdbqXx3KSctaJ9wBibxZwRX3kB+6vvkt75zESfCuQ5f3iXdB6s2KavZzHaA==", + "version": "3.11.20210514031523", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210514031523.tgz", + "integrity": "sha512-SBsH0mYZJ35/X/eHizJWLE26xtFItjb2++hMoC4X1ZfkeYazBZYv3baxS50VfzGsZcWgVEKpQ2sMePctSwBN7Q==", "dev": true, "requires": { "@babel/cli": "^7.1.2", @@ -21637,9 +21636,9 @@ } }, "scratch-svg-renderer": { - "version": "0.2.0-prerelease.20210408171934", - "resolved": "https://registry.npmjs.org/scratch-svg-renderer/-/scratch-svg-renderer-0.2.0-prerelease.20210408171934.tgz", - "integrity": "sha512-kc59fyZlJ58ooW86VQo9oqXNzpR48RH7vObehekVyPq4FMRENwtv9gCZ5XitLPNsLEheFCJdfRVPkVsMAjhPYQ==", + "version": "0.2.0-prerelease.20210511195415", + "resolved": "https://registry.npmjs.org/scratch-svg-renderer/-/scratch-svg-renderer-0.2.0-prerelease.20210511195415.tgz", + "integrity": "sha512-zeT93lfMeJNWhj8cLfNeDWTZT/fDS2Fnz6btCJpvE5AAyel+8VE1Y9hBb1OJ+ap8vjA1O31TnDApIylRmA/g5w==", "dev": true, "requires": { "base64-js": "1.2.1", diff --git a/package.json b/package.json index 64aa1ffaa..da40221bd 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "redux-mock-store": "^1.2.3", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20210510170231", + "scratch-gui": "0.1.0-prerelease.20210514040957", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", diff --git a/src/components/forms/button.jsx b/src/components/forms/button.jsx index 39bab920a..7ac93878e 100644 --- a/src/components/forms/button.jsx +++ b/src/components/forms/button.jsx @@ -6,7 +6,7 @@ const React = require('react'); require('./button.scss'); const Button = props => { - const classes = classNames('button', props.className, {'close-button': props.isCloseType}); + const classes = classNames('button', props.className, {'forms-close-button': props.isCloseType}); return ( + {open && setOpen(false)} + > + {children} + } + + ); +}; + +OverflowMenu.propTypes = { + children: PropTypes.node, + dropdownAs: PropTypes.string, + className: PropTypes.string +}; + +OverflowMenu.defaultProps = { + dropdownAs: 'ul' +}; + +export default OverflowMenu; diff --git a/src/components/overflow-menu/overflow-menu.scss b/src/components/overflow-menu/overflow-menu.scss new file mode 100644 index 000000000..124c96520 --- /dev/null +++ b/src/components/overflow-menu/overflow-menu.scss @@ -0,0 +1,50 @@ + +.overflow-menu-container { + display: flex; + position: relative; + + .overflow-menu-trigger { + background: transparent; + border: none; + display: flex; + align-items: center; + } + + .overflow-menu-dropdown { + border: 1px solid rgba(0, 0, 0, 0.15); + box-sizing: border-box; + box-shadow: 0px 2px 8px rgba(87, 94, 117, 0.5); + border-radius: 8px; + padding: 0; + margin: 30px 0 0 0; + right: unset; /* default dropdown aligns right edges, but we want left edges */ + left: 0; + z-index: 1; + + /* Include default styling for
  • +
  • +
  • + +
  • + +

    Nav Bubbles

    diff --git a/src/views/components/components.scss b/src/views/components/components.scss index 1c2ac9e02..b4a272f95 100644 --- a/src/views/components/components.scss +++ b/src/views/components/components.scss @@ -18,6 +18,17 @@ width: 200px; } + .example-tile { + width: 200px; + height: 50px; + border: 1px solid $ui-border; + border-radius: 8px; + padding: 10px; + display: flex; + justify-content: flex-end; + align-items: center + } + .colors { span { display: inline-block; diff --git a/src/views/components/example-icon.svg b/src/views/components/example-icon.svg new file mode 100644 index 000000000..3edd347dd --- /dev/null +++ b/src/views/components/example-icon.svg @@ -0,0 +1,18 @@ + + + + Sound/General/Delete + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/developers/developers.jsx b/src/views/developers/developers.jsx index bf99abf1c..862deefeb 100644 --- a/src/views/developers/developers.jsx +++ b/src/views/developers/developers.jsx @@ -364,7 +364,7 @@ const Developers = () => ( GitHub ), contactUsLink: ( - + ) diff --git a/src/views/developers/l10n.json b/src/views/developers/l10n.json index e2f5b18bc..8b7d0c707 100644 --- a/src/views/developers/l10n.json +++ b/src/views/developers/l10n.json @@ -1,7 +1,7 @@ { "developers.hereLinkText": "here", "developers.title": "Scratch for Developers", - "developers.introLinkText": "Scratch Team at MIT", + "developers.introLinkText": "Scratch Team", "developers.intro": "On this page, you’ll find information about open source projects created and maintained by the {introLink}, as well as our thoughts on best practices for designing learning experiences for children.", "developers.projectsTitle": "Projects", "developers.principlesTitle": "Principles", diff --git a/src/views/preview/comment/comment.scss b/src/views/preview/comment/comment.scss index 060d1e9a8..324df51c1 100644 --- a/src/views/preview/comment/comment.scss +++ b/src/views/preview/comment/comment.scss @@ -159,6 +159,10 @@ .avatar { margin-right: .5rem; + border-radius: 4px; + box-shadow: 0px 0px 0px 1px rgba(77, 151, 255, 0.25); + width: 3rem; + height: 3rem; } .comment-body { diff --git a/src/views/splash/splash.jsx b/src/views/splash/splash.jsx index 2366dcec3..4371be487 100644 --- a/src/views/splash/splash.jsx +++ b/src/views/splash/splash.jsx @@ -165,6 +165,13 @@ class Splash extends React.Component { shouldShowHOCMiddleBanner () { return false; // we did not use this middle banner in last HoC } + shouldShowIntro () { + return ( + this.props.sessionStatus === sessionActions.Status.FETCHED && // done fetching session + Object.keys(this.props.user).length === 0 && // no user session found + this.shouldShowHOCTopBanner() !== true + ); + } shouldShowDonateBanner () { return ( this.state.dismissedDonateBanner === false && @@ -180,7 +187,7 @@ class Splash extends React.Component { const showDonateBanner = this.shouldShowDonateBanner() || false; const showHOCTopBanner = this.shouldShowHOCTopBanner() || false; const showHOCMiddleBanner = this.shouldShowHOCMiddleBanner() || false; - const showIntro = showHOCTopBanner !== true; + const showIntro = this.shouldShowIntro() || false; const showWelcome = this.shouldShowWelcome(); const homepageRefreshStatus = this.getHomepageRefreshStatus(); diff --git a/src/views/studio/icons/curator-icon.svg b/src/views/studio/icons/curator-icon.svg new file mode 100644 index 000000000..f1be48d65 --- /dev/null +++ b/src/views/studio/icons/curator-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/views/studio/icons/remove-icon.svg b/src/views/studio/icons/remove-icon.svg new file mode 100644 index 000000000..3edd347dd --- /dev/null +++ b/src/views/studio/icons/remove-icon.svg @@ -0,0 +1,18 @@ + + + + Sound/General/Delete + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index 4a1fcd72d..198a5beab 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -7,16 +7,26 @@ "studio.title": "Title", "studio.description": "Description", "studio.thumbnail": "Thumbnail", + "studio.updateErrors.generic": "Something went wrong updating the studio.", + "studio.updateErrors.inappropriate": "That seems inappropriate. Please be respectful.", + "studio.updateErrors.textTooLong": "That is too long.", + "studio.updateErrors.requiredField": "This cannot be blank.", + "studio.updateErrors.thumbnailTooLarge": "Maximum file size is 512 KB and less than 500x500 pixels.", + "studio.updateErrors.thumbnailInvalid": "Upload a valid image. The file you uploaded was either not an image or a corrupted image.", "studio.projectsHeader": "Projects", "studio.addProjectsHeader": "Add Projects", "studio.addProject": "Add", + "studio.addProjectPlaceholder": "Project URL", + + "studio.openToAll": "Anyone can add projects", "studio.projectsEmptyCanAdd1": "Your studio is looking a little empty.", "studio.projectsEmptyCanAdd2": "Add your first project!", "studio.projectsEmpty1": "This studio has no projects yet.", "studio.projectsEmpty2": "Suggest projects you want to add in the comments!", "studio.browseProjects": "Browse Projects", + "studio.projectErrors.checkUrl": "Could not add project. Check the URL and try again.", "studio.creatorRole": "Studio Creator", @@ -28,17 +38,30 @@ "studio.curatorsHeader": "Curators", "studio.inviteCuratorsHeader": "Invite Curators", "studio.inviteCurator": "Invite", + "studio.inviteCuratorPlaceholder": "Scratch Username", "studio.curatorAcceptInvite": "Accept Invite", "studio.curatorsEmptyCanAdd1": "You don’t have curators right now.", "studio.curatorsEmptyCanAdd2": "Add some curators to collaborate with!", "studio.curatorsEmpty1": "This studio has no curators right now.", + "studio.curatorErrors.generic": "Could not invite curator.", + "studio.curatorErrors.alreadyCurator": "They are already part of the studio.", + "studio.curatorErrors.unknownUsername": "Could not invite a curator with that username.", + "studio.curatorErrors.tooFast": "You are adding curators too fast.", + + "studio.remove": "Remove", + "studio.promote": "Promote", "studio.commentsHeader": "Comments", + "studio.comments.toggleOff": "Commenting off", + "studio.comments.toggleOn": "Commenting on", + "studio.comments.turnedOff": "Sorry, comment posting has been turned off for this studio.", "studio.sharedFilter": "Shared", "studio.favoritedFilter": "Favorited", "studio.recentFilter": "Recent", - + "studio.studentsFilter": "Students", + + "studio.activityHeader": "Activity", "studio.activityAddProjectToStudio": "{profileLink} added the project {projectLink}", "studio.activityRemoveProjectStudio": "{profileLink} removed the project {projectLink}", "studio.activityUpdateStudio": "{profileLink} made edits to the title, thumbnail, or description", diff --git a/src/views/studio/lib/studio-project-actions.js b/src/views/studio/lib/studio-project-actions.js index a1b1c9c27..548772292 100644 --- a/src/views/studio/lib/studio-project-actions.js +++ b/src/views/studio/lib/studio-project-actions.js @@ -11,13 +11,15 @@ const Errors = keyMirror({ SERVER: null, PERMISSION: null, UNKNOWN_PROJECT: null, - RATE_LIMIT: null + RATE_LIMIT: null, + DUPLICATE: null }); const normalizeError = (err, body, res) => { if (err) return Errors.NETWORK; if (res.statusCode === 401 || res.statusCode === 403) return Errors.PERMISSION; if (res.statusCode === 404) return Errors.UNKNOWN_PROJECT; + if (res.statusCode === 409) return Errors.DUPLICATE; if (res.statusCode === 429) return Errors.RATE_LIMIT; if (res.statusCode !== 200) return Errors.SERVER; return null; @@ -59,11 +61,25 @@ const generateProjectListItem = (postBody, infoBody) => ({ username: infoBody.author.username, avatar: infoBody.author.profile.images }); - -const addProject = projectId => ((dispatch, getState) => new Promise((resolve, reject) => { + +const addProject = projectIdOrUrl => ((dispatch, getState) => new Promise((resolve, reject) => { + // Strings are passed by the open input, numbers by the project browser + let projectId = projectIdOrUrl; + if (typeof projectIdOrUrl === 'string') { + const matches = projectIdOrUrl.match(/(\d+)/g); + if (!matches) return reject(Errors.UNKNOWN_PROJECT); + // Take the last match, in case we are on localhost and there are port numbers, e.g. + projectId = parseInt(matches[matches.length - 1], 10); + } + const state = getState(); const studioId = selectStudioId(state); const token = selectToken(state); + + // Check for existing duplicates before going to the server + if (projects.selector(state).items.filter(p => p.id === projectId).length !== 0) { + return reject(Errors.DUPLICATE); + } api({ uri: `/studios/${studioId}/project/${projectId}`, method: 'POST', diff --git a/src/views/studio/lib/user-projects-actions.js b/src/views/studio/lib/user-projects-actions.js index b932ef206..6c568a421 100644 --- a/src/views/studio/lib/user-projects-actions.js +++ b/src/views/studio/lib/user-projects-actions.js @@ -1,6 +1,7 @@ import keyMirror from 'keymirror'; import api from '../../../lib/api'; -import {selectUsername} from '../../../redux/session'; +import {selectToken, selectUsername} from '../../../redux/session'; +import {selectClassroomId} from '../../../redux/studio'; import {userProjects, projects} from './redux-modules'; const Errors = keyMirror({ @@ -12,13 +13,25 @@ const Errors = keyMirror({ const Filters = keyMirror({ SHARED: null, FAVORITED: null, - RECENT: null + RECENT: null, + STUDENTS: null }); -const Uris = { - [Filters.SHARED]: username => `/users/${username}/projects`, - [Filters.FAVORITED]: username => `/users/${username}/favorites`, - [Filters.RECENT]: username => `/users/${username}/recent` +const Endpoints = { + [Filters.SHARED]: state => ({ + uri: `/users/${selectUsername(state)}/projects` + }), + [Filters.FAVORITED]: state => ({ + uri: `/users/${selectUsername(state)}/favorites` + }), + [Filters.RECENT]: state => ({ + uri: `/users/${selectUsername(state)}/projects/recentlyviewed`, + authentication: selectToken(state) + }), + [Filters.STUDENTS]: state => ({ + uri: `/classrooms/${selectClassroomId(state)}/projects`, + authentication: selectToken(state) + }) }; const normalizeError = (err, body, res) => { @@ -30,14 +43,17 @@ const normalizeError = (err, body, res) => { const loadUserProjects = type => ((dispatch, getState) => { const state = getState(); - const username = selectUsername(state); const projectCount = userProjects.selector(state).items.length; const projectsPerPage = 20; + const opts = { + ...Endpoints[type](state), + params: { + limit: projectsPerPage, + offset: projectCount + } + }; dispatch(userProjects.actions.loading()); - api({ - uri: Uris[type](username), - params: {limit: projectsPerPage, offset: projectCount} - }, (err, body, res) => { + api(opts, (err, body, res) => { const error = normalizeError(err, body, res); if (error) return dispatch(userProjects.actions.error(error)); const moreToLoad = body.length === projectsPerPage; diff --git a/src/views/studio/modals/user-projects-modal.jsx b/src/views/studio/modals/user-projects-modal.jsx index cf6c57051..d930eea6d 100644 --- a/src/views/studio/modals/user-projects-modal.jsx +++ b/src/views/studio/modals/user-projects-modal.jsx @@ -5,6 +5,7 @@ import {connect} from 'react-redux'; import classNames from 'classnames'; import {FormattedMessage} from 'react-intl'; +import {selectClassroomId} from '../../../redux/studio'; import {addProject, removeProject} from '../lib/studio-project-actions'; import {userProjects} from '../lib/redux-modules'; import {Filters, loadUserProjects, clearUserProjects} from '../lib/user-projects-actions'; @@ -16,10 +17,11 @@ import SubNavigation from '../../../components/subnavigation/subnavigation.jsx'; import UserProjectsTile from './user-projects-tile.jsx'; import './user-projects-modal.scss'; +import {selectIsEducator} from '../../../redux/session'; const UserProjectsModal = ({ - items, error, loading, moreToLoad, onLoadMore, onClear, - onAdd, onRemove, onRequestClose + items, error, loading, moreToLoad, showStudentsFilter, + onLoadMore, onClear, onAdd, onRemove, onRequestClose }) => { const [filter, setFilter] = useState(Filters.SHARED); @@ -60,6 +62,14 @@ const UserProjectsModal = ({ > + {showStudentsFilter && +
  • setFilter(Filters.STUDENTS)} + > + +
  • + }
    {error &&
    Error loading {filter}: {error}
    } @@ -75,15 +85,18 @@ const UserProjectsModal = ({ onRemove={onRemove} /> ))} + {moreToLoad &&
    - {loading ? Loading... : ( - moreToLoad ? - : - No more to load - )} +
    + }
    @@ -91,6 +104,7 @@ const UserProjectsModal = ({ }; UserProjectsModal.propTypes = { + showStudentsFilter: PropTypes.bool, items: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.id, image: PropTypes.string, @@ -108,7 +122,8 @@ UserProjectsModal.propTypes = { }; const mapStateToProps = state => ({ - ...userProjects.selector(state) + ...userProjects.selector(state), + showStudentsFilter: selectIsEducator(state) && selectClassroomId(state) }); const mapDispatchToProps = ({ diff --git a/src/views/studio/modals/user-projects-modal.scss b/src/views/studio/modals/user-projects-modal.scss index 66aaeab4d..3530aa73f 100644 --- a/src/views/studio/modals/user-projects-modal.scss +++ b/src/views/studio/modals/user-projects-modal.scss @@ -22,11 +22,14 @@ .user-projects-modal-content { padding: 0 30px 30px; background: #E9F1FC; - max-height: 80vh; + max-height: calc(100vh - 200px); overflow-y: auto; overscroll-behavior: contain; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; + @media #{$intermediate-and-smaller} { + & { max-height: calc(100vh - 105px); } + } } } diff --git a/src/views/studio/studio-activity.jsx b/src/views/studio/studio-activity.jsx index f84d59074..519dbb2d5 100644 --- a/src/views/studio/studio-activity.jsx +++ b/src/views/studio/studio-activity.jsx @@ -177,7 +177,9 @@ const StudioActivity = ({items, loading, error, moreToLoad, onLoadMore}) => { return (
    -

    Activity

    +
    +

    +
    {loading &&
    Loading...
    } {error && ( @@ -16,16 +20,20 @@ const StudioCommentsAllowed = ({

    Fetching...

    ) : (
    - + {commentsAllowed ? ( + + ) : ( + + )} + handleUpdate(e.target.checked)} + /> + {commentsAllowedError &&
    Error mutating commentsAllowed: {commentsAllowedError}
    }
    )}
    diff --git a/src/views/studio/studio-comments.jsx b/src/views/studio/studio-comments.jsx index 7e0b020e7..b6ac7c15d 100644 --- a/src/views/studio/studio-comments.jsx +++ b/src/views/studio/studio-comments.jsx @@ -56,9 +56,11 @@ const StudioComments = ({ return (
    -

    - {canEditCommentsAllowed && } -
    +
    +

    + {canEditCommentsAllowed && } +
    +
    {shouldShowCommentComposer && commentsAllowed && { +const errorToMessageId = error => { + switch (error) { + case Errors.NETWORK: return 'studio.curatorErrors.generic'; + case Errors.SERVER: return 'studio.curatorErrors.generic'; + case Errors.PERMISSION: return 'studio.curatorErrors.generic'; + case Errors.DUPLICATE: return 'studio.curatorErrors.alreadyCurator'; + case Errors.UNKNOWN_USERNAME: return 'studio.curatorErrors.unknownUsername'; + case Errors.RATE_LIMIT: return 'studio.curatorErrors.tooFast'; + default: return 'studio.curatorErrors.generic'; + } +}; + +const StudioCuratorInviter = ({intl, onSubmit}) => { const [value, setValue] = useState(''); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); @@ -23,11 +35,19 @@ const StudioCuratorInviter = ({onSubmit}) => { return (

    - +
    + {error &&
    + } + /> +
    } e.key === 'Enter' && submit()} onChange={e => setValue(e.target.value)} @@ -36,17 +56,17 @@ const StudioCuratorInviter = ({onSubmit}) => { className={classNames('button', { 'mod-mutating': submitting })} - disabled={submitting} + disabled={submitting || value === ''} onClick={submit} > - {error &&
    {error}
    } - +
    ); }; StudioCuratorInviter.propTypes = { - onSubmit: PropTypes.func + onSubmit: PropTypes.func, + intl: intlShape }; const mapStateToProps = () => ({}); @@ -55,4 +75,4 @@ const mapDispatchToProps = ({ onSubmit: inviteCurator }); -export default connect(mapStateToProps, mapDispatchToProps)(StudioCuratorInviter); +export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(StudioCuratorInviter)); diff --git a/src/views/studio/studio-curators.jsx b/src/views/studio/studio-curators.jsx index c2608b021..089eb5549 100644 --- a/src/views/studio/studio-curators.jsx +++ b/src/views/studio/studio-curators.jsx @@ -20,7 +20,9 @@ const StudioCurators = ({ }, []); return (
    -

    +
    +

    +
    {canInviteCurators && } {showCuratorInvite && } {error && { + switch (error) { + case Errors.INAPPROPRIATE: return 'studio.updateErrors.inappropriate'; + case Errors.TEXT_TOO_LONG: return 'studio.updateErrors.textTooLong'; + case Errors.REQUIRED_FIELD: return 'studio.updateErrors.requiredField'; + default: return 'studio.updateErrors.generic'; + } +}; const StudioDescription = ({ descriptionError, isFetching, isMutating, description, canEditInfo, handleUpdate }) => { const fieldClassName = classNames('studio-description', { 'mod-fetching': isFetching, - 'mod-mutating': isMutating + 'mod-mutating': isMutating, + 'mod-form-error': !!descriptionError }); return ( - +