From b4dfbc0ecf656081ee53809fb6200499e57e321a Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 20 Oct 2020 10:11:23 -0400 Subject: [PATCH 01/47] Move Project Rows tests from Tap to Jest --- .../smoke-testing/test_project_rows.js | 93 ------------------- test/integration/project-rows.test.js | 59 ++++++++++++ 2 files changed, 59 insertions(+), 93 deletions(-) delete mode 100644 test/integration-legacy/smoke-testing/test_project_rows.js create mode 100644 test/integration/project-rows.test.js diff --git a/test/integration-legacy/smoke-testing/test_project_rows.js b/test/integration-legacy/smoke-testing/test_project_rows.js deleted file mode 100644 index 029125b3a..000000000 --- a/test/integration-legacy/smoke-testing/test_project_rows.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Checks that the some of the homepage rows on the homepage are displayed and - * contents have the right URLs to redirect to - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); - -const webdriver = require('selenium-webdriver'); -const driver = helper.buildDriver('www-smoke test_project_rows'); - -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; - -// number of tests in the plan -tap.plan(4); - -tap.tearDown(function () { - // quit the instance of the browser - driver.quit(); -}); - -tap.beforeEach(function () { - // load the page with the driver - return driver.get(rootUrl); -}); - -// checks that the title of the first row is Featured Projects -tap.test('checkFeaturedProjectsRowTitleWhenSignedOut', function (t) { - var xPathLink = '//div[@class="box"]/div[@class="box-header"]/h4'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - element.getText('h4') - .then(function (text) { - // expected value of the title text - var expectedText = 'Featured Projects'; - t.equal(text, expectedText); - t.end(); - }); - }); -}); - -// checks that the link for a project makes sense -tap.test('checkFeaturedProjectsRowLinkWhenSignedOut', function (t) { - var xPathLink = '//div[contains(@class, "thumbnail") ' + - 'and contains(@class, "project") and contains(@class, "slick-slide") ' + - 'and contains(@class, "slick-active")]/a[@class="thumbnail-image"]'; - driver.wait(webdriver.until - .elementLocated(webdriver.By.xpath(xPathLink))) - .then(function (element) { - element.getAttribute('href') - .then(function (url) { - // expected pattern for the project URL - // since I don't know the length of the project ID number - var expectedUrlRegExp = new RegExp('/projects/.*[0-9].*/?'); - t.match(url, expectedUrlRegExp); - t.end(); - }); - }); -}); - -// checks that the title of the 2nd row is Featured Studios -tap.test('checkFeaturedStudiosRowWhenSignedOut', function (t) { - var xPathLink = '//div[@class="box"][2]/div[@class="box-header"]/h4'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - element.getText('h4') - .then(function (text) { - var expectedText = 'Featured Studios'; - t.equal(text, expectedText); - t.end(); - }); - }); -}); - -// checks that the link for a studio makes sense -tap.test('checkFeaturedStudiosRowLinkWhenSignedOut', function (t) { - var xPathLink = '//div[contains(@class, "thumbnail") and contains(@class, "gallery") ' + - 'and contains(@class, "slick-slide") ' + - 'and contains(@class, "slick-active")]/a[@class="thumbnail-image"]'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - element.getAttribute('href') - .then(function (url) { - var expectedUrlRegExp = new RegExp('/studios/.*[0-9].*/?'); - t.match(url, expectedUrlRegExp); - t.end(); - }); - }); -}); diff --git a/test/integration/project-rows.test.js b/test/integration/project-rows.test.js new file mode 100644 index 000000000..3910c44d9 --- /dev/null +++ b/test/integration/project-rows.test.js @@ -0,0 +1,59 @@ +const SeleniumHelper = require('./selenium-helpers.js'); + +const { + clickXpath, + findByXpath, + buildDriver +} = new SeleniumHelper(); + +let remote = process.env.SMOKE_REMOTE || false; +let rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; + +if (remote) { + jest.setTimeout(60000); +} else { + jest.setTimeout(10000); +} + +let driver; + +describe('www-integration project rows', () => { + beforeAll(async () => { + driver = await buildDriver('www-integration project rows'); + // driver.get(rootUrl); + }); + + beforeEach(async () => { + await driver.get(rootUrl); + }); + + afterAll(async () => await driver.quit()); + + test('Featured Projects row title', async () => { + let projects = await findByXpath('//div[@class="box"]/div[@class="box-header"]/h4'); + let projectsText = await projects.getText(); + await expect(projectsText).toEqual('Featured Projects'); + }); + + test('Featured Project link', async () => { + await clickXpath('//div[@class="box"][descendant::text()="Featured Projects"]' + + '//div[contains(@class, "thumbnail")][1]/a[@class="thumbnail-image"]'); + let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); + let gfOverlayDisplayed = await gfOverlay.isDisplayed(); + await expect(gfOverlayDisplayed).toBe(true); + }); + + test('Featured Studios row title', async () => { + let studios = await findByXpath('//div[@class="box"][2]/div[@class="box-header"]/h4'); + let studiosText = await studios.getText(); + await expect(studiosText).toEqual('Featured Studios'); + }); + + test('Featured Studios link', async () => { + await clickXpath('//div[@class="box"][descendant::text()="Featured Studios"]' + + '//div[contains(@class, "thumbnail")][1]/a[@class="thumbnail-image"]'); + let galleryInfo = await findByXpath('//div[contains(@class, "gallery-info")]'); + let galleryInfoDisplayed = await galleryInfo.isDisplayed(); + await expect(galleryInfoDisplayed).toBe(true); + }); +}); From 7edb0b2cb8650230019149639368dc37bb5f8621 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 19 Oct 2020 10:58:36 -0400 Subject: [PATCH 02/47] Move Navbar integration tests from Tap to Jest --- .../smoke-testing/test_navbar_links.js | 123 ------------------ test/integration/navbar.test.js | 107 +++++++++++++++ 2 files changed, 107 insertions(+), 123 deletions(-) delete mode 100644 test/integration-legacy/smoke-testing/test_navbar_links.js create mode 100644 test/integration/navbar.test.js diff --git a/test/integration-legacy/smoke-testing/test_navbar_links.js b/test/integration-legacy/smoke-testing/test_navbar_links.js deleted file mode 100644 index 632c6d9e9..000000000 --- a/test/integration-legacy/smoke-testing/test_navbar_links.js +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Checks that the links in the navbar on the homepage have the right URLs to redirect to - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); - -const webdriver = require('selenium-webdriver'); -const driver = helper.buildDriver('www-smoke test_navbar_links'); - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; - -// number of tests in the plan -tap.plan(7); - -tap.tearDown(function () { - // quit the instance of the browser - driver.quit(); -}); - -tap.beforeEach(function () { - // load the page with the driver - return driver.get(rootUrl); -}); - -// ==== Links in navbar ==== - -// the create link changes depending on whether the user is signed in or not (tips window opens) -tap.test('checkCreateLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "create")]/a'; - var expectedHref = '/projects/editor/?tutorial=getStarted'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -tap.test('checkExploreLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "explore")]/a'; - var expectedHref = '/explore/projects/all'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -tap.test('checkIdeasLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "ideas")]/a'; - var expectedHref = '/ideas'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -tap.test('checkAboutLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "about")]/a'; - var expectedHref = '/about'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// ==== Search bar ==== - -tap.test('checkSearchBar', function (t) { - var xPathLink = '//input[@id="frc-q-1088"]'; - // search bar should exist - driver.findElement(webdriver.By.xpath(xPathLink)).then(function (element) { - t.ok(element); - t.end(); - }); -}); - -// ==== Join Scratch & Sign In ==== - -tap.test('checkJoinScratchLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "right") and contains(@class, "join")]/a'; - var expectedText = 'Join Scratch'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getText('a'); - }) - .then(function (text) { - t.equal(text, expectedText); - t.end(); - }); -}); - -tap.test('checkSignInLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "right") and contains(@class, "login-item")]/a'; - var expectedText = 'Sign in'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getText('a'); - }) - .then(function (text) { - t.equal(text, expectedText); - t.end(); - }); -}); diff --git a/test/integration/navbar.test.js b/test/integration/navbar.test.js new file mode 100644 index 000000000..424bdb6f3 --- /dev/null +++ b/test/integration/navbar.test.js @@ -0,0 +1,107 @@ +const SeleniumHelper = require('./selenium-helpers.js'); + +const { + clickXpath, + findByXpath, + buildDriver +} = new SeleniumHelper(); + +let remote = process.env.SMOKE_REMOTE || false; +let rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; + +if (remote) { + jest.setTimeout(60000); +} else { + jest.setTimeout(10000); +} + +let driver; + +describe('www-integration navbar links', () => { + beforeAll(async () => { + driver = await buildDriver('www-integration navbar links'); + }); + + beforeEach(async () => { + await driver.get(rootUrl); + }); + + afterAll(async () => await driver.quit()); + + test('Check text of navbar items', async () => { + let create = await findByXpath('//li[@class="link create"]'); + let createText = await create.getText(); + await expect(createText).toEqual('Create'); + + let explore = await findByXpath('//li[@class="link explore"]'); + let exploreText = await explore.getText(); + await expect(exploreText).toEqual('Explore'); + + let ideas = await findByXpath('//li[@class="link ideas"]'); + let ideasText = await ideas.getText(); + await expect(ideasText).toEqual('Ideas'); + + let about = await findByXpath('//li[@class="link about"]'); + let aboutText = await about.getText(); + await expect(aboutText).toEqual('About'); + + let join = await findByXpath('//a[@class="registrationLink"]'); + let joinText = await join.getText(); + await expect(joinText).toEqual('Join Scratch'); + + let signIn = await findByXpath('//li[@class="link right login-item"]/a'); + let signInText = await signIn.getText(); + await expect(signInText).toEqual('Sign in'); + }); + + test('create when signed out', async () => { + await clickXpath('//li[@class="link create"]'); + let infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]'); + let areaVisible = await infoArea.isDisplayed(); + await expect(areaVisible).toBe(true); + }); + + test('Explore link when signed out', async () => { + await clickXpath('//li[@class="link explore"]'); + let banner = await findByXpath('//h1[@class="title-banner-h1"]'); + let bannerText = await banner.getText(); + await expect(bannerText).toEqual('Explore'); + }); + + test('Ideas link when signed out', async () => { + await clickXpath('//li[@class="link ideas"]'); + let banner = await findByXpath('//div[contains(@class, "ideas-banner")]'); + let bannerVisible = await banner.isDisplayed(); + await expect(bannerVisible).toBe(true); + }); + + test('About link when signed out', async () => { + await clickXpath('//li[@class="link about"]'); + let aboutPage = await findByXpath('//div[@class="inner about"]'); + let aboutPageVisible = await aboutPage.isDisplayed(); + await expect(aboutPageVisible).toBe(true); + }); + + test('Search Bar', async () => { + let searchBar = await findByXpath('//input[@id="frc-q-1088"]'); + // await searchBar.click(); + await searchBar.sendKeys('cat'); + await driver.sleep(500); // without it sends an empty string on submit + await searchBar.submit(); + let banner = await findByXpath('//h1[@class="title-banner-h1"]'); + let bannerText = await banner.getText(); + await expect(bannerText).toEqual('Search'); + }); + + test('Scratch Logo', async () => { + await clickXpath('//li[@class="link explore"]'); + await findByXpath('//h1[@class="title-banner-h1"]'); + await clickXpath('//li[@class="logo"]'); + let splash = await findByXpath('//div[@class="splash"]'); + let splashVisible = await splash.isDisplayed(); + expect(splashVisible).toBe(true); + }); + + // Sign In is tested in sign-in-and-out tests + // Create Account is tested in Join tests +}); From 6bea2b3a2c69004deda1556684a742510c6fb5d0 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 20 Oct 2020 10:54:14 -0400 Subject: [PATCH 03/47] Remove leftover comment in navbar test --- test/integration/navbar.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/navbar.test.js b/test/integration/navbar.test.js index 424bdb6f3..fca59c230 100644 --- a/test/integration/navbar.test.js +++ b/test/integration/navbar.test.js @@ -84,7 +84,6 @@ describe('www-integration navbar links', () => { test('Search Bar', async () => { let searchBar = await findByXpath('//input[@id="frc-q-1088"]'); - // await searchBar.click(); await searchBar.sendKeys('cat'); await driver.sleep(500); // without it sends an empty string on submit await searchBar.submit(); From 37d279f6e5b925ed388a78ae3fbfca0fac4b46da Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Thu, 22 Oct 2020 14:54:58 -0400 Subject: [PATCH 04/47] Search for the gui component in navbar create test --- test/integration/navbar.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/navbar.test.js b/test/integration/navbar.test.js index fca59c230..403082645 100644 --- a/test/integration/navbar.test.js +++ b/test/integration/navbar.test.js @@ -56,9 +56,9 @@ describe('www-integration navbar links', () => { test('create when signed out', async () => { await clickXpath('//li[@class="link create"]'); - let infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]'); - let areaVisible = await infoArea.isDisplayed(); - await expect(areaVisible).toBe(true); + let gui = await findByXpath('//div[contains(@class, "gui")]'); + let guiVisible = await gui.isDisplayed(); + await expect(guiVisible).toBe(true); }); test('Explore link when signed out', async () => { From 0cd1f6e6bee478436c537785c37dbe4204bdb04d Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Fri, 23 Oct 2020 14:00:11 -0400 Subject: [PATCH 05/47] Add class to searchbar for automated tests --- src/components/navigation/www/navigation.jsx | 1 + test/integration/navbar.test.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/navigation/www/navigation.jsx b/src/components/navigation/www/navigation.jsx index 39e69c242..0f25c79da 100644 --- a/src/components/navigation/www/navigation.jsx +++ b/src/components/navigation/www/navigation.jsx @@ -135,6 +135,7 @@ class Navigation extends React.Component { /> { }); test('Search Bar', async () => { - let searchBar = await findByXpath('//input[@id="frc-q-1088"]'); + let searchBar = await findByXpath('//div[contains(@class, "search-input")]/div/input'); await searchBar.sendKeys('cat'); await driver.sleep(500); // without it sends an empty string on submit await searchBar.submit(); From 7a5bdc040064ff56eff4fe41207e03777ef3b525 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 27 Oct 2020 11:47:59 -0400 Subject: [PATCH 06/47] Change class for search input wrapper to search-wrapper --- src/components/navigation/www/navigation.jsx | 2 +- test/integration/navbar.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/navigation/www/navigation.jsx b/src/components/navigation/www/navigation.jsx index 0f25c79da..14a6d412b 100644 --- a/src/components/navigation/www/navigation.jsx +++ b/src/components/navigation/www/navigation.jsx @@ -135,7 +135,7 @@ class Navigation extends React.Component { /> { }); test('Search Bar', async () => { - let searchBar = await findByXpath('//div[contains(@class, "search-input")]/div/input'); + let searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input'); await searchBar.sendKeys('cat'); await driver.sleep(500); // without it sends an empty string on submit await searchBar.submit(); From c8445561b30af14c191f0d2c15d0ac2da6a240ca Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Tue, 22 Dec 2020 14:18:29 -0500 Subject: [PATCH 07/47] set, purge static_assets surrogate key on deploy --- bin/configure-fastly.js | 11 +++++------ package.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/bin/configure-fastly.js b/bin/configure-fastly.js index c3eb4cca2..2d3b0c189 100644 --- a/bin/configure-fastly.js +++ b/bin/configure-fastly.js @@ -270,12 +270,11 @@ async.auto({ fastly.activateVersion(results.version, function (e, resp) { if (e) throw new Error(e); process.stdout.write('Successfully configured and activated version ' + resp.number + '\n'); - if (process.env.FASTLY_PURGE_ALL) { - fastly.purgeAll(FASTLY_SERVICE_ID, function (error) { - if (error) throw new Error(error); - process.stdout.write('Purged all.\n'); - }); - } + // purge static_assets using surrogate key + fastly.purgeKey(FASTLY_SERVICE_ID, 'static_assets', function (error) { + if (error) throw new Error(error); + process.stdout.write('Purged static assets.\n'); + }); }); } }); diff --git a/package.json b/package.json index da40221bd..2023d6a8c 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "deploy": "npm run deploy:s3 && npm run deploy:fastly", "deploy:fastly": "node ./bin/configure-fastly.js", "deploy:s3": "npm run deploy:s3:all && npm run deploy:s3:svg && npm run deploy:s3:js", - "deploy:s3cmd": "s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600", + "deploy:s3cmd": "s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600 --add-header=Surrogate-Key:static_assets", "deploy:s3:all": "npm run deploy:s3cmd -- --exclude '.DS_Store' --exclude '*.svg' --exclude '*.js' ./build/ s3://$S3_BUCKET_NAME/", "deploy:s3:svg": "npm run deploy:s3cmd -- --exclude '*' --include '*.svg' --mime-type 'image/svg+xml' ./build/ s3://$S3_BUCKET_NAME/", "deploy:s3:js": "npm run deploy:s3cmd -- --exclude '*' --include '*.js' --mime-type 'application/javascript' ./build/ s3://$S3_BUCKET_NAME/", From 177c02824c9f00dd31514fa2139ea5996510c89d Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 23 Dec 2020 14:25:01 -0500 Subject: [PATCH 08/47] use x-amz-meta-surrogate-key to get around S3 header goodlist --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2023d6a8c..2707f12b1 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "deploy": "npm run deploy:s3 && npm run deploy:fastly", "deploy:fastly": "node ./bin/configure-fastly.js", "deploy:s3": "npm run deploy:s3:all && npm run deploy:s3:svg && npm run deploy:s3:js", - "deploy:s3cmd": "s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600 --add-header=Surrogate-Key:static_assets", + "deploy:s3cmd": "s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600 --add-header=x-amz-meta-surrogate-key:static_assets", "deploy:s3:all": "npm run deploy:s3cmd -- --exclude '.DS_Store' --exclude '*.svg' --exclude '*.js' ./build/ s3://$S3_BUCKET_NAME/", "deploy:s3:svg": "npm run deploy:s3cmd -- --exclude '*' --include '*.svg' --mime-type 'image/svg+xml' ./build/ s3://$S3_BUCKET_NAME/", "deploy:s3:js": "npm run deploy:s3cmd -- --exclude '*' --include '*.js' --mime-type 'application/javascript' ./build/ s3://$S3_BUCKET_NAME/", From 37a5dd93652e6550d0989a86ad2228426061308c Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Fri, 14 May 2021 19:17:22 -0400 Subject: [PATCH 09/47] use hyphen instead of underscore --- bin/configure-fastly.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/configure-fastly.js b/bin/configure-fastly.js index 2d3b0c189..d98c01b68 100644 --- a/bin/configure-fastly.js +++ b/bin/configure-fastly.js @@ -270,8 +270,8 @@ async.auto({ fastly.activateVersion(results.version, function (e, resp) { if (e) throw new Error(e); process.stdout.write('Successfully configured and activated version ' + resp.number + '\n'); - // purge static_assets using surrogate key - fastly.purgeKey(FASTLY_SERVICE_ID, 'static_assets', function (error) { + // purge static-assets using surrogate key + fastly.purgeKey(FASTLY_SERVICE_ID, 'static-assets', function (error) { if (error) throw new Error(error); process.stdout.write('Purged static assets.\n'); }); diff --git a/package.json b/package.json index 2707f12b1..4986ce2a0 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "deploy": "npm run deploy:s3 && npm run deploy:fastly", "deploy:fastly": "node ./bin/configure-fastly.js", "deploy:s3": "npm run deploy:s3:all && npm run deploy:s3:svg && npm run deploy:s3:js", - "deploy:s3cmd": "s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600 --add-header=x-amz-meta-surrogate-key:static_assets", + "deploy:s3cmd": "s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600 --add-header=x-amz-meta-surrogate-key:static-assets", "deploy:s3:all": "npm run deploy:s3cmd -- --exclude '.DS_Store' --exclude '*.svg' --exclude '*.js' ./build/ s3://$S3_BUCKET_NAME/", "deploy:s3:svg": "npm run deploy:s3cmd -- --exclude '*' --include '*.svg' --mime-type 'image/svg+xml' ./build/ s3://$S3_BUCKET_NAME/", "deploy:s3:js": "npm run deploy:s3cmd -- --exclude '*' --include '*.js' --mime-type 'application/javascript' ./build/ s3://$S3_BUCKET_NAME/", From cc663412522bd602b87d115d8b00a96b28deb6f0 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 17 May 2021 14:53:02 -0400 Subject: [PATCH 10/47] Wait for session to be fetched before loading comments --- src/redux/session.js | 1 + src/views/studio/studio-comments.jsx | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/redux/session.js b/src/redux/session.js index 36ce89927..b6ed97cc4 100644 --- a/src/redux/session.js +++ b/src/redux/session.js @@ -128,6 +128,7 @@ module.exports.selectToken = state => get(state, ['session', 'session', 'user', module.exports.selectIsAdmin = state => get(state, ['session', 'session', 'permissions', 'admin'], false); module.exports.selectIsSocial = state => get(state, ['session', 'session', 'permissions', 'social'], false); module.exports.selectIsEducator = state => get(state, ['session', 'session', 'permissions', 'educator'], false); +module.exports.selectHasFetchedSession = state => state.session.status === module.exports.Status.FETCHED; // NB logged out user id as NaN so that it can never be used in equality testing since NaN !== NaN module.exports.selectUserId = state => get(state, ['session', 'session', 'user', 'id'], NaN); diff --git a/src/views/studio/studio-comments.jsx b/src/views/studio/studio-comments.jsx index b6ac7c15d..b477f0d94 100644 --- a/src/views/studio/studio-comments.jsx +++ b/src/views/studio/studio-comments.jsx @@ -9,7 +9,7 @@ import TopLevelComment from '../preview/comment/top-level-comment.jsx'; import studioCommentActions from '../../redux/studio-comment-actions.js'; import StudioCommentsAllowed from './studio-comments-allowed.jsx'; -import {selectIsAdmin} from '../../redux/session'; +import {selectIsAdmin, selectHasFetchedSession} from '../../redux/session'; import { selectShowCommentComposer, selectCanDeleteComment, @@ -24,6 +24,7 @@ const StudioComments = ({ comments, commentsAllowed, isAdmin, + hasFetchedSession, handleLoadMoreComments, handleNewComment, moreCommentsToLoad, @@ -42,8 +43,8 @@ const StudioComments = ({ handleLoadMoreReplies }) => { useEffect(() => { - if (comments.length === 0) handleLoadMoreComments(); - }, [comments.length === 0]); + if (comments.length === 0 && hasFetchedSession) handleLoadMoreComments(); + }, [comments.length === 0, hasFetchedSession]); // The comments you see depend on your admin status // so reset them if isAdmin changes. @@ -108,6 +109,7 @@ StudioComments.propTypes = { comments: PropTypes.arrayOf(PropTypes.shape({})), commentsAllowed: PropTypes.bool, isAdmin: PropTypes.bool, + hasFetchedSession: PropTypes.bool, handleLoadMoreComments: PropTypes.func, handleNewComment: PropTypes.func, moreCommentsToLoad: PropTypes.bool, @@ -133,6 +135,7 @@ export { export default connect( state => ({ comments: state.comments.comments, + hasFetchedSession: selectHasFetchedSession(state), isAdmin: selectIsAdmin(state), moreCommentsToLoad: state.comments.moreCommentsToLoad, replies: state.comments.replies, From efe961e10310bad4ffd8ef63e3bf1b6799144d9b Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 17 May 2021 15:24:51 -0400 Subject: [PATCH 11/47] Handle more types of project add errors --- src/views/studio/l10n.json | 6 +++++- src/views/studio/studio-project-adder.jsx | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index e8e934ae3..a95952604 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -26,7 +26,11 @@ "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.projectErrors.checkUrl": "Could not find that project. Check the URL and try again.", + "studio.projectErrors.generic": "Could not add project", + "studio.projectErrors.tooFast": "You are adding projects too quickly", + "studio.projectErrors.permission": "You do not have permission to add that project", + "studio.projectErrors.duplicate": "That project is already in this studio", "studio.creatorRole": "Studio Creator", diff --git a/src/views/studio/studio-project-adder.jsx b/src/views/studio/studio-project-adder.jsx index abae09a92..7271cd4b2 100644 --- a/src/views/studio/studio-project-adder.jsx +++ b/src/views/studio/studio-project-adder.jsx @@ -5,10 +5,22 @@ import {connect} from 'react-redux'; import classNames from 'classnames'; import {FormattedMessage, intlShape, injectIntl} from 'react-intl'; -import {addProject} from './lib/studio-project-actions'; +import {Errors, addProject} from './lib/studio-project-actions'; import UserProjectsModal from './modals/user-projects-modal.jsx'; import ValidationMessage from '../../components/forms/validation-message.jsx'; +const errorToMessageId = error => { + switch (error) { + case Errors.NETWORK: return 'studio.projectErrors.generic'; + case Errors.SERVER: return 'studio.projectErrors.generic'; + case Errors.PERMISSION: return 'studio.projectErrors.permission'; + case Errors.DUPLICATE: return 'studio.projectErrors.duplicate'; + case Errors.RATE_LIMIT: return 'studio.projectErrors.tooFast'; + case Errors.UNKNOWN_PROJECT: return 'studio.projectErrors.checkUrl'; + default: return 'studio.projectErrors.generic'; + } +}; + const StudioProjectAdder = ({intl, onSubmit}) => { const [value, setValue] = useState(''); const [submitting, setSubmitting] = useState(false); @@ -30,7 +42,7 @@ const StudioProjectAdder = ({intl, onSubmit}) => { } + message={} /> } Date: Mon, 17 May 2021 15:31:08 -0400 Subject: [PATCH 12/47] Update tests --- test/unit/components/studio-comments.test.jsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/unit/components/studio-comments.test.jsx b/test/unit/components/studio-comments.test.jsx index 1f628fc66..1985d370f 100644 --- a/test/unit/components/studio-comments.test.jsx +++ b/test/unit/components/studio-comments.test.jsx @@ -7,10 +7,14 @@ describe('Studio comments', () => { const loadComments = jest.fn(); const component = mountWithIntl( ); + expect(loadComments).not.toHaveBeenCalled(); + component.setProps({hasFetchedSession: true}); + component.update(); expect(loadComments).toHaveBeenCalled(); // When updated to have comments, load is not called again @@ -30,6 +34,7 @@ describe('Studio comments', () => { const resetComments = jest.fn(); const component = mountWithIntl( { mountWithIntl( From b0eae61d5b6eb55f4e06ae94504959ee7acb66b0 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 17 May 2021 15:32:16 -0400 Subject: [PATCH 13/47] Fix periods --- src/views/studio/l10n.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index a95952604..87cdfb8c3 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -27,10 +27,10 @@ "studio.projectsEmpty2": "Suggest projects you want to add in the comments!", "studio.browseProjects": "Browse Projects", "studio.projectErrors.checkUrl": "Could not find that project. Check the URL and try again.", - "studio.projectErrors.generic": "Could not add project", - "studio.projectErrors.tooFast": "You are adding projects too quickly", - "studio.projectErrors.permission": "You do not have permission to add that project", - "studio.projectErrors.duplicate": "That project is already in this studio", + "studio.projectErrors.generic": "Could not add project.", + "studio.projectErrors.tooFast": "You are adding projects too quickly.", + "studio.projectErrors.permission": "You do not have permission to add that project.", + "studio.projectErrors.duplicate": "That project is already in this studio.", "studio.creatorRole": "Studio Creator", From 5ee1c7c20381711d60e85af3d4b25e2a2bbc494a Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 19 May 2021 13:11:07 -0400 Subject: [PATCH 14/47] Add reusable alert component using context --- src/components/alert/alert-component.jsx | 41 ++++++++++++++++ src/components/alert/alert-context.js | 18 +++++++ src/components/alert/alert-provider.jsx | 54 +++++++++++++++++++++ src/components/alert/alert-status.js | 5 ++ src/components/alert/alert.jsx | 33 +++++++++++++ src/components/alert/alert.scss | 37 ++++++++++++++ src/components/alert/icon-alert-error.svg | 3 ++ src/components/alert/icon-alert-success.svg | 9 ++++ src/views/components/components.jsx | 31 ++++++++++++ 9 files changed, 231 insertions(+) create mode 100644 src/components/alert/alert-component.jsx create mode 100644 src/components/alert/alert-context.js create mode 100644 src/components/alert/alert-provider.jsx create mode 100644 src/components/alert/alert-status.js create mode 100644 src/components/alert/alert.jsx create mode 100644 src/components/alert/alert.scss create mode 100644 src/components/alert/icon-alert-error.svg create mode 100644 src/components/alert/icon-alert-success.svg diff --git a/src/components/alert/alert-component.jsx b/src/components/alert/alert-component.jsx new file mode 100644 index 000000000..9dec54fd7 --- /dev/null +++ b/src/components/alert/alert-component.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import {FormattedMessage} from 'react-intl'; +import Button from '../../components/forms/button.jsx'; + +import './alert.scss'; + +const AlertComponent = ({className, icon, id, values, onClear}) => ( +
+
+ {icon && } +
+ +
+ {onClear &&
+
+); + +AlertComponent.propTypes = { + className: PropTypes.string, + icon: PropTypes.string, + id: PropTypes.string.isRequired, + values: PropTypes.shape({}), + onClear: PropTypes.func +}; + +export default AlertComponent; diff --git a/src/components/alert/alert-context.js b/src/components/alert/alert-context.js new file mode 100644 index 000000000..171f640e3 --- /dev/null +++ b/src/components/alert/alert-context.js @@ -0,0 +1,18 @@ +import {createContext, useContext} from 'react'; +import AlertStatus from './alert-status.js'; + +const AlertContext = createContext({ + // Note: defaults here are only used if there is no Provider in the tree + status: AlertStatus.NONE, + data: {}, + clearAlert: () => {}, + successAlert: () => {}, + errorAlert: () => {} +}); + +const useAlertContext = () => useContext(AlertContext); + +export { + AlertContext as default, + useAlertContext +}; diff --git a/src/components/alert/alert-provider.jsx b/src/components/alert/alert-provider.jsx new file mode 100644 index 000000000..2a75acd80 --- /dev/null +++ b/src/components/alert/alert-provider.jsx @@ -0,0 +1,54 @@ +import React, {useRef, useState} from 'react'; +import PropTypes from 'prop-types'; + +import AlertStatus from './alert-status.js'; +import AlertContext from './alert-context.js'; + +const AlertProvider = ({children}) => { + const defaultState = { + status: AlertStatus.NONE, + data: {}, + showClear: false + }; + const [state, setState] = useState(defaultState); + const timeoutRef = useRef(null); + + const clearAlert = () => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + timeoutRef.current = null; + setState(defaultState); + }; + + const handleAlert = (status, data, timeoutSeconds = 3) => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + setState({status, data, showClear: !timeoutSeconds}); + if (timeoutSeconds) { + timeoutRef.current = setTimeout(() => { + timeoutRef.current = null; + setState(defaultState); + }, timeoutSeconds * 1000); + } + }; + + return ( + + handleAlert(AlertStatus.SUCCESS, newData, timeoutSeconds), + errorAlert: (newData, timeoutSeconds = 3) => + handleAlert(AlertStatus.ERROR, newData, timeoutSeconds) + }} + > + {children} + + ); +}; +AlertProvider.propTypes = { + children: PropTypes.node +}; + +export default AlertProvider; diff --git a/src/components/alert/alert-status.js b/src/components/alert/alert-status.js new file mode 100644 index 000000000..a964d9fa1 --- /dev/null +++ b/src/components/alert/alert-status.js @@ -0,0 +1,5 @@ +export default { + NONE: 'NONE', + SUCCESS: 'SUCCESS', + ERROR: 'ERROR' +}; diff --git a/src/components/alert/alert.jsx b/src/components/alert/alert.jsx new file mode 100644 index 000000000..6f686e46b --- /dev/null +++ b/src/components/alert/alert.jsx @@ -0,0 +1,33 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +import AlertComponent from './alert-component.jsx'; +import AlertStatus from './alert-status.js'; +import {useAlertContext} from './alert-context.js'; + +import successIcon from './icon-alert-success.svg'; +import errorIcon from './icon-alert-error.svg'; + +const Alert = ({className}) => { + const {status, data, showClear, clearAlert} = useAlertContext(); + if (status === AlertStatus.NONE) return null; + return ( + + ); +}; + +Alert.propTypes = { + className: PropTypes.string +}; + +export default Alert; diff --git a/src/components/alert/alert.scss b/src/components/alert/alert.scss new file mode 100644 index 000000000..02b28fea5 --- /dev/null +++ b/src/components/alert/alert.scss @@ -0,0 +1,37 @@ + +.alert-wrapper { + position: absolute; + display: flex; + width: 100%; + justify-content: center; + z-index: 100; + .alert { + display: flex; + box-sizing: border-box; + padding: 10px 20px; + border-radius: 8px; + align-items: center; + margin-top: 1rem; + min-height: 60px; + &.alert-error { + background: #FFF0DF; + border: 1px solid #FF8C1A; + box-shadow: 0px 0px 0px 2px rgba(255, 140, 26, 0.25) + } + + &.alert-success { + background: #CEF2E8; + border: 1px solid #0EBD8C; + box-shadow: 0px 0px 0px rgba(14, 189, 140, 0.25); + } + .alert-msg { + font-size: 14px; + font-weight: bold; + } + .alert-close-button { + position: unset; + margin-left: 1rem; + } + } + +} \ No newline at end of file diff --git a/src/components/alert/icon-alert-error.svg b/src/components/alert/icon-alert-error.svg new file mode 100644 index 000000000..6dc116bdf --- /dev/null +++ b/src/components/alert/icon-alert-error.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/alert/icon-alert-success.svg b/src/components/alert/icon-alert-success.svg new file mode 100644 index 000000000..fbe57da4b --- /dev/null +++ b/src/components/alert/icon-alert-success.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/views/components/components.jsx b/src/views/components/components.jsx index 9fd180fc0..18f8dbb20 100644 --- a/src/views/components/components.jsx +++ b/src/views/components/components.jsx @@ -14,12 +14,43 @@ const SubNavigation = require('../../components/subnavigation/subnavigation.jsx' const Select = require('../../components/forms/select.jsx'); const OverflowMenu = require('../../components/overflow-menu/overflow-menu.jsx').default; const exampleIcon = require('./example-icon.svg'); +const AlertProvider = require('../../components/alert/alert-provider.jsx').default; +const {useAlertContext} = require('../../components/alert/alert-context.js'); +const Alert = require('../../components/alert/alert.jsx').default; require('./components.scss'); +/* eslint-disable react/prop-types, react/jsx-no-bind */ +/* Demo of how to use the useAlertContext hook */ +const AlertButton = ({type, timeoutSeconds}) => { + const {errorAlert, successAlert} = useAlertContext(); + const onClick = type === 'success' ? + () => successAlert({id: 'success-alert.string.id'}, timeoutSeconds) : + () => errorAlert({id: 'error-alert.string.id'}, timeoutSeconds); + return ( + + ); +}; + const Components = () => (
+

Alert Provider, Display and Hooks

+ +
+ +
+
+
+

Overflow Menu

From 9a931b026e55e628c3f87b5fe475a8a3d67d001d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 19 May 2021 13:36:16 -0400 Subject: [PATCH 15/47] Add and use alert providers on curators, managers, projects and project modal --- src/views/studio/l10n.json | 12 +- src/views/studio/lib/studio-member-actions.js | 2 - .../studio/modals/user-projects-modal.jsx | 55 ++++---- .../studio/modals/user-projects-tile.jsx | 14 +- src/views/studio/studio-curator-inviter.jsx | 23 +++- src/views/studio/studio-curators.jsx | 108 ++++++++------- src/views/studio/studio-managers.jsx | 45 ++++--- src/views/studio/studio-member-tile.jsx | 31 +++-- src/views/studio/studio-project-adder.jsx | 26 +++- src/views/studio/studio-project-tile.jsx | 11 +- src/views/studio/studio-projects.jsx | 125 +++++++++--------- src/views/studio/studio.scss | 6 +- 12 files changed, 270 insertions(+), 188 deletions(-) diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index b2cc54c35..530dfe9f4 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -73,5 +73,15 @@ "studio.reportPleaseExplain": "Please explain why you feel this studio is disrespectful or inappropriate, or otherwise breaks the Scratch Community Guidelines.", "studio.reportAreThereComments": "Are there inappropriate comments in the studio? Please report them by clicking the \"report\" button on the individual comments.", "studio.reportThanksForLettingUsKnow": "Thanks for letting us know!", - "studio.reportYourFeedback": "Your feedback will help us make Scratch better." + "studio.reportYourFeedback": "Your feedback will help us make Scratch better.", + + "studio.alertProjectAdded": "\"{title}\" added to studio", + "studio.alertProjectAlreadyAdded": "\"{title}\" is already in this studio", + "studio.alertProjectRemoveError": "Something went wrong removing the project", + "studio.alertProjectAddError": "Something went wrong adding the project", + "studio.alertCuratorAlreadyInvited": "\"{name}\" has already been invited", + "studio.alertCuratorInvited": "Curator invite sent to \"{name}\"", + "studio.alertManagerPromote": "\"{name}\" is now a manager", + "studio.alertManagerPromoteError": "Something went wrong promoting \"{name}\"", + "studio.alertMemberRemoveError": "Something went wrong removing \"{name}\"" } diff --git a/src/views/studio/lib/studio-member-actions.js b/src/views/studio/lib/studio-member-actions.js index 887ff683a..31cf319bc 100644 --- a/src/views/studio/lib/studio-member-actions.js +++ b/src/views/studio/lib/studio-member-actions.js @@ -121,8 +121,6 @@ const inviteCurator = username => ((dispatch, getState) => new Promise((resolve, }, (err, body, res) => { const error = normalizeError(err, body, res); if (error) return reject(error); - // eslint-disable-next-line no-alert - alert(`successfully invited ${username}`); return resolve(username); }); })); diff --git a/src/views/studio/modals/user-projects-modal.jsx b/src/views/studio/modals/user-projects-modal.jsx index 9b951117c..218cf8034 100644 --- a/src/views/studio/modals/user-projects-modal.jsx +++ b/src/views/studio/modals/user-projects-modal.jsx @@ -18,6 +18,8 @@ import UserProjectsTile from './user-projects-tile.jsx'; import './user-projects-modal.scss'; import {selectIsEducator} from '../../../redux/session'; +import AlertProvider from '../../../components/alert/alert-provider.jsx'; +import Alert from '../../../components/alert/alert.jsx'; const UserProjectsModal = ({ items, error, loading, moreToLoad, showStudentsFilter, @@ -72,32 +74,35 @@ const UserProjectsModal = ({ } - {error &&
Error loading {filter}: {error}
} -
- {items.map(project => ( - - ))} - {moreToLoad && -
- + + {error &&
Error loading {filter}: {error}
} + +
+ {items.map(project => ( + + ))} + {moreToLoad && +
+ +
+ }
- } -
+ ); diff --git a/src/views/studio/modals/user-projects-tile.jsx b/src/views/studio/modals/user-projects-tile.jsx index cf49a1999..2fb7b1865 100644 --- a/src/views/studio/modals/user-projects-tile.jsx +++ b/src/views/studio/modals/user-projects-tile.jsx @@ -1,23 +1,26 @@ /* eslint-disable react/jsx-no-bind */ -import React, {useState} from 'react'; +import React, {useContext, useState} from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; +import AlertContext from '../../../components/alert/alert-context.js'; const UserProjectsTile = ({id, title, image, inStudio, onAdd, onRemove}) => { const [submitting, setSubmitting] = useState(false); const [added, setAdded] = useState(inStudio); - const [error, setError] = useState(null); + const {errorAlert} = useContext(AlertContext); const toggle = () => { setSubmitting(true); - setError(null); (added ? onRemove(id) : onAdd(id)) .then(() => { setAdded(!added); setSubmitting(false); }) - .catch(e => { - setError(e); + .catch(() => { setSubmitting(false); + errorAlert({ + id: added ? 'studio.alertProjectRemoveError' : + 'studio.alertProjectAddError' + }); }); }; return ( @@ -45,7 +48,6 @@ const UserProjectsTile = ({id, title, image, inStudio, onAdd, onRemove}) => {
{added ? '✔' : '+'}
- {error &&
{error}
}
); diff --git a/src/views/studio/studio-curator-inviter.jsx b/src/views/studio/studio-curator-inviter.jsx index 25a8b83d0..6d92b5e96 100644 --- a/src/views/studio/studio-curator-inviter.jsx +++ b/src/views/studio/studio-curator-inviter.jsx @@ -5,6 +5,7 @@ import {connect} from 'react-redux'; import classNames from 'classnames'; import {FormattedMessage, intlShape, injectIntl} from 'react-intl'; +import {useAlertContext} from '../../components/alert/alert-context'; import {Errors, inviteCurator} from './lib/studio-member-actions'; import ValidationMessage from '../../components/forms/validation-message.jsx'; @@ -24,12 +25,30 @@ const StudioCuratorInviter = ({intl, onSubmit}) => { const [value, setValue] = useState(''); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); + const {successAlert} = useAlertContext(); + const submit = () => { setSubmitting(true); setError(null); onSubmit(value) - .then(() => setValue('')) - .catch(e => setError(e)) + .then(() => { + successAlert({ + id: 'studio.alertCuratorInvited', + values: {name: value} + }); + setValue(''); + }) + .catch(e => { + if (e === Errors.DUPLICATE) { + successAlert({ + id: 'studio.alertCuratorAlreadyInvited', + values: {name: value} + }); + setValue(''); + } else { + setError(e); + } + }) .then(() => setSubmitting(false)); }; return ( diff --git a/src/views/studio/studio-curators.jsx b/src/views/studio/studio-curators.jsx index 089eb5549..870369d31 100644 --- a/src/views/studio/studio-curators.jsx +++ b/src/views/studio/studio-curators.jsx @@ -11,6 +11,8 @@ import CuratorInviter from './studio-curator-inviter.jsx'; import CuratorInvite from './studio-curator-invite.jsx'; import {loadCurators} from './lib/studio-member-actions'; import {selectCanInviteCurators, selectShowCuratorInvite} from '../../redux/studio-permissions'; +import AlertProvider from '../../components/alert/alert-provider.jsx'; +import Alert from '../../components/alert/alert.jsx'; const StudioCurators = ({ canInviteCurators, showCuratorInvite, items, error, loading, moreToLoad, onLoadMore @@ -19,61 +21,65 @@ const StudioCurators = ({ if (items.length === 0) onLoadMore(); }, []); - return (
-
-

-
- {canInviteCurators && } - {showCuratorInvite && } - {error && } -
- {items.length === 0 && !loading ? ( -
- - {canInviteCurators ? ( -
-
-
+ return ( + +
+ +
+

+
+ {canInviteCurators && } + {showCuratorInvite && } + {error && } +
+ {items.length === 0 && !loading ? ( +
+ + {canInviteCurators ? ( +
+
+
+
+ ) : ( +
+
+
+ )}
) : ( -
-
-
+ + {items.map(item => + () + )} + {moreToLoad && +
+ +
+ } +
)}
- ) : ( - - {items.map(item => - () - )} - {moreToLoad && -
- -
- } -
- )} -
-
); +
+ ); }; StudioCurators.propTypes = { diff --git a/src/views/studio/studio-managers.jsx b/src/views/studio/studio-managers.jsx index b4d4b260e..e70b28e35 100644 --- a/src/views/studio/studio-managers.jsx +++ b/src/views/studio/studio-managers.jsx @@ -8,6 +8,8 @@ import {managers} from './lib/redux-modules'; import {loadManagers} from './lib/studio-member-actions'; import Debug from './debug.jsx'; import {ManagerTile} from './studio-member-tile.jsx'; +import AlertProvider from '../../components/alert/alert-provider.jsx'; +import Alert from '../../components/alert/alert.jsx'; const StudioManagers = ({items, error, loading, moreToLoad, onLoadMore}) => { @@ -16,24 +18,26 @@ const StudioManagers = ({items, error, loading, moreToLoad, onLoadMore}) => { }, []); return ( -
-
-

-
- {error && } -
- {items.map(item => - () - )} - {moreToLoad && + +
+ +
+

+
+ {error && } +
+ {items.map(item => + () + )} + {moreToLoad &&
- } + } +
-
+ ); }; diff --git a/src/views/studio/studio-member-tile.jsx b/src/views/studio/studio-member-tile.jsx index e14c3b4b4..71e4987a6 100644 --- a/src/views/studio/studio-member-tile.jsx +++ b/src/views/studio/studio-member-tile.jsx @@ -13,6 +13,7 @@ import { removeCurator, removeManager } from './lib/studio-member-actions'; +import {useAlertContext} from '../../components/alert/alert-context'; import OverflowMenu from '../../components/overflow-menu/overflow-menu.jsx'; import removeIcon from './icons/remove-icon.svg'; @@ -23,7 +24,7 @@ const StudioMemberTile = ({ username, image // own props }) => { const [submitting, setSubmitting] = useState(false); - const [error, setError] = useState(null); + const {errorAlert, successAlert} = useAlertContext(); const userUrl = `/users/${username}`; return (
@@ -50,11 +51,20 @@ const StudioMemberTile = ({ disabled={submitting} onClick={() => { setSubmitting(true); - setError(null); - onPromote(username).catch(e => { - setError(e); - setSubmitting(false); - }); + onPromote(username) + .then(() => { + successAlert({ + id: 'studio.alertManagerPromote', + values: {name: username} + }); + }) + .catch(() => { + errorAlert({ + id: 'studio.alertManagerPromoteError', + values: {name: username} + }); + setSubmitting(false); + }); }} > @@ -69,9 +79,11 @@ const StudioMemberTile = ({ disabled={submitting} onClick={() => { setSubmitting(true); - setError(null); - onRemove(username).catch(e => { - setError(e); + onRemove(username).catch(() => { + errorAlert({ + id: 'studio.alertMemberRemoveError', + values: {name: username} + }); setSubmitting(false); }); }} @@ -82,7 +94,6 @@ const StudioMemberTile = ({ } } - {error &&
{error}
}
); }; diff --git a/src/views/studio/studio-project-adder.jsx b/src/views/studio/studio-project-adder.jsx index abae09a92..de6721052 100644 --- a/src/views/studio/studio-project-adder.jsx +++ b/src/views/studio/studio-project-adder.jsx @@ -5,21 +5,41 @@ import {connect} from 'react-redux'; import classNames from 'classnames'; import {FormattedMessage, intlShape, injectIntl} from 'react-intl'; -import {addProject} from './lib/studio-project-actions'; +import {Errors, addProject} from './lib/studio-project-actions'; import UserProjectsModal from './modals/user-projects-modal.jsx'; import ValidationMessage from '../../components/forms/validation-message.jsx'; +import {useAlertContext} from '../../components/alert/alert-context'; const StudioProjectAdder = ({intl, onSubmit}) => { const [value, setValue] = useState(''); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); const [modalOpen, setModalOpen] = useState(false); + const {successAlert} = useAlertContext(); const submit = () => { setSubmitting(true); setError(null); onSubmit(value) - .then(() => setValue('')) - .catch(e => setError(e)) + .then(() => { + successAlert({ + id: 'studio.alertProjectAdded', + values: {title: value} + }); + setValue(''); + }) + .catch(e => { + // Duplicate project will show success alert + if (e === Errors.DUPLICATE) { + successAlert({ + id: 'studio.alertProjectAlreadyAdded', + values: {title: value} + }); + setValue(''); + } else { + // Other errors are displayed by this component + setError(e); + } + }) .then(() => setSubmitting(false)); }; return ( diff --git a/src/views/studio/studio-project-tile.jsx b/src/views/studio/studio-project-tile.jsx index 6152c4451..27c2f7175 100644 --- a/src/views/studio/studio-project-tile.jsx +++ b/src/views/studio/studio-project-tile.jsx @@ -1,10 +1,11 @@ /* eslint-disable react/jsx-no-bind */ -import React, {useState} from 'react'; +import React, {useContext, useState} from 'react'; import PropTypes from 'prop-types'; import {connect} from 'react-redux'; import classNames from 'classnames'; import {FormattedMessage} from 'react-intl'; +import AlertContext from '../../components/alert/alert-context.js'; import {selectCanRemoveProject} from '../../redux/studio-permissions'; import {removeProject} from './lib/studio-project-actions'; @@ -16,9 +17,9 @@ const StudioProjectTile = ({ id, title, image, avatar, username // own props }) => { const [submitting, setSubmitting] = useState(false); - const [error, setError] = useState(null); const projectUrl = `/projects/${id}`; const userUrl = `/users/${username}`; + const {errorAlert} = useContext(AlertContext); return (
); diff --git a/src/views/studio/studio-projects.jsx b/src/views/studio/studio-projects.jsx index 7672b113d..69164a308 100644 --- a/src/views/studio/studio-projects.jsx +++ b/src/views/studio/studio-projects.jsx @@ -11,6 +11,8 @@ import StudioProjectAdder from './studio-project-adder.jsx'; import StudioProjectTile from './studio-project-tile.jsx'; import {loadProjects} from './lib/studio-project-actions.js'; import classNames from 'classnames'; +import AlertProvider from '../../components/alert/alert-provider.jsx'; +import Alert from '../../components/alert/alert.jsx'; const StudioProjects = ({ canAddProjects, canEditOpenToAll, items, error, loading, moreToLoad, onLoadMore @@ -20,62 +22,64 @@ const StudioProjects = ({ }, []); return ( -
-
-

- {canEditOpenToAll && } -
- {canAddProjects && } - {error && } -
- {items.length === 0 && !loading ? ( -
- {canAddProjects ? ( - - -
-
-
-
-
- ) : ( - - -
-
-
-
-
- )} -
- ) : ( - - {items.map(item => - () - )} - {moreToLoad && + +
+ +
+

+ {canEditOpenToAll && } +
+ {canAddProjects && } + {error && } +
+ {items.length === 0 && !loading ? ( +
+ {canAddProjects ? ( + + +
+
+
+
+
+ ) : ( + + +
+
+
+
+
+ )} +
+ ) : ( + + {items.map(item => + () + )} + {moreToLoad &&
- } -
- )} + } + + )} +
-
+ ); }; diff --git a/src/views/studio/studio.scss b/src/views/studio/studio.scss index 1227f9f2c..96832ff06 100644 --- a/src/views/studio/studio.scss +++ b/src/views/studio/studio.scss @@ -96,7 +96,10 @@ $radius: 8px; .active > li { background: $ui-blue; } } -.studio-projects {} +.studio-projects, .studio-members { + position: relative; +} + .studio-projects-grid { margin-top: 20px; display: grid; @@ -176,7 +179,6 @@ $radius: 8px; } } -.studio-members {} .studio-members-grid { margin-top: 20px; display: grid; From e2eb8611b197283d31483a29c70f536ef357bc23 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 19 May 2021 13:46:06 -0400 Subject: [PATCH 16/47] Dont catch pointer events in the alert container --- src/components/alert/alert.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/alert/alert.scss b/src/components/alert/alert.scss index 02b28fea5..043d17795 100644 --- a/src/components/alert/alert.scss +++ b/src/components/alert/alert.scss @@ -5,6 +5,8 @@ width: 100%; justify-content: center; z-index: 100; + pointer-events: none; + .alert { display: flex; box-sizing: border-box; @@ -13,6 +15,7 @@ align-items: center; margin-top: 1rem; min-height: 60px; + pointer-events: auto; &.alert-error { background: #FFF0DF; border: 1px solid #FF8C1A; From 64d4bd4fde06bbc59d29348e10bed7566dd21e28 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 19 May 2021 13:54:29 -0400 Subject: [PATCH 17/47] Do not use project name in duplicate message since we do not have it --- src/views/studio/l10n.json | 2 +- src/views/studio/studio-project-adder.jsx | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index 530dfe9f4..7b8297b9d 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -76,7 +76,7 @@ "studio.reportYourFeedback": "Your feedback will help us make Scratch better.", "studio.alertProjectAdded": "\"{title}\" added to studio", - "studio.alertProjectAlreadyAdded": "\"{title}\" is already in this studio", + "studio.alertProjectAlreadyAdded": "That project is already in this studio", "studio.alertProjectRemoveError": "Something went wrong removing the project", "studio.alertProjectAddError": "Something went wrong adding the project", "studio.alertCuratorAlreadyInvited": "\"{name}\" has already been invited", diff --git a/src/views/studio/studio-project-adder.jsx b/src/views/studio/studio-project-adder.jsx index de6721052..6d2c36871 100644 --- a/src/views/studio/studio-project-adder.jsx +++ b/src/views/studio/studio-project-adder.jsx @@ -30,10 +30,7 @@ const StudioProjectAdder = ({intl, onSubmit}) => { .catch(e => { // Duplicate project will show success alert if (e === Errors.DUPLICATE) { - successAlert({ - id: 'studio.alertProjectAlreadyAdded', - values: {title: value} - }); + successAlert({id: 'studio.alertProjectAlreadyAdded'}); setValue(''); } else { // Other errors are displayed by this component From 8a2cbc5ea4bcbc1ca8431407bc526c8f3a8f69f3 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 19 May 2021 15:09:06 -0400 Subject: [PATCH 18/47] Dont timeout error alerts --- src/views/studio/modals/user-projects-tile.jsx | 2 +- src/views/studio/studio-member-tile.jsx | 2 +- src/views/studio/studio-project-tile.jsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/studio/modals/user-projects-tile.jsx b/src/views/studio/modals/user-projects-tile.jsx index 2fb7b1865..c1334835d 100644 --- a/src/views/studio/modals/user-projects-tile.jsx +++ b/src/views/studio/modals/user-projects-tile.jsx @@ -20,7 +20,7 @@ const UserProjectsTile = ({id, title, image, inStudio, onAdd, onRemove}) => { errorAlert({ id: added ? 'studio.alertProjectRemoveError' : 'studio.alertProjectAddError' - }); + }, null); }); }; return ( diff --git a/src/views/studio/studio-member-tile.jsx b/src/views/studio/studio-member-tile.jsx index 71e4987a6..d9d55d850 100644 --- a/src/views/studio/studio-member-tile.jsx +++ b/src/views/studio/studio-member-tile.jsx @@ -83,7 +83,7 @@ const StudioMemberTile = ({ errorAlert({ id: 'studio.alertMemberRemoveError', values: {name: username} - }); + }, null); setSubmitting(false); }); }} diff --git a/src/views/studio/studio-project-tile.jsx b/src/views/studio/studio-project-tile.jsx index 27c2f7175..788f028db 100644 --- a/src/views/studio/studio-project-tile.jsx +++ b/src/views/studio/studio-project-tile.jsx @@ -58,7 +58,7 @@ const StudioProjectTile = ({ onRemove(id) .catch(() => { setSubmitting(false); - errorAlert({id: 'studio.alertProjectRemoveError'}); + errorAlert({id: 'studio.alertProjectRemoveError'}, null); }); }} > From 15b31c689e086eebe9b404c47b5c4dd91aee919a Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 21 May 2021 09:20:51 -0400 Subject: [PATCH 19/47] load 24 projects per page in add to studio modal --- src/views/studio/lib/user-projects-actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/studio/lib/user-projects-actions.js b/src/views/studio/lib/user-projects-actions.js index 6c568a421..a50e025b2 100644 --- a/src/views/studio/lib/user-projects-actions.js +++ b/src/views/studio/lib/user-projects-actions.js @@ -44,7 +44,7 @@ const normalizeError = (err, body, res) => { const loadUserProjects = type => ((dispatch, getState) => { const state = getState(); const projectCount = userProjects.selector(state).items.length; - const projectsPerPage = 20; + const projectsPerPage = 24; const opts = { ...Endpoints[type](state), params: { From 0a9e46583071bb4c56bdf98151b915965d155abe Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 21 May 2021 11:09:43 -0400 Subject: [PATCH 20/47] style border for added projects --- src/views/studio/modals/user-projects-modal.scss | 4 ++++ src/views/studio/modals/user-projects-tile.jsx | 1 + 2 files changed, 5 insertions(+) diff --git a/src/views/studio/modals/user-projects-modal.scss b/src/views/studio/modals/user-projects-modal.scss index 3530aa73f..68124459d 100644 --- a/src/views/studio/modals/user-projects-modal.scss +++ b/src/views/studio/modals/user-projects-modal.scss @@ -33,6 +33,10 @@ } } +.studio-tile-added { + border: 1px solid $ui-blue !important; // Override the tile border set in studio.scss .studio-project-tile + box-shadow: 0 0 0 4px $ui-blue-25percent; +} .studio-tile-dynamic-remove, .studio-tile-dynamic-add { diff --git a/src/views/studio/modals/user-projects-tile.jsx b/src/views/studio/modals/user-projects-tile.jsx index cf49a1999..1514ff556 100644 --- a/src/views/studio/modals/user-projects-tile.jsx +++ b/src/views/studio/modals/user-projects-tile.jsx @@ -25,6 +25,7 @@ const UserProjectsTile = ({id, title, image, inStudio, onAdd, onRemove}) => { role="button" tabIndex="0" className={classNames('studio-project-tile', { + 'studio-tile-added': added, 'mod-clickable': true, 'mod-mutating': submitting })} From a0992bb5f7336bc045656c4092c9c6a5f0844ab3 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Thu, 20 May 2021 18:32:43 -0700 Subject: [PATCH 21/47] add project and comment count to StudioTabNav --- src/redux/studio.js | 8 +++++++ src/views/studio/l10n.json | 2 ++ src/views/studio/studio-tab-nav.jsx | 35 ++++++++++++++++++++++++----- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/redux/studio.js b/src/redux/studio.js index 2cbb80394..328fdc72f 100644 --- a/src/redux/studio.js +++ b/src/redux/studio.js @@ -95,6 +95,9 @@ const selectStudioImage = state => state.studio.image; const selectStudioOpenToAll = state => state.studio.openToAll; const selectStudioCommentsAllowed = state => state.studio.commentsAllowed; const selectStudioLoadFailed = state => state.studio.infoStatus === Status.ERROR; +const selectStudioCommentCount = state => state.studio.commentCount; +const selectStudioFollowerCount = state => state.studio.followers; +const selectStudioProjectCount = state => state.studio.projectCount; const selectIsFetchingInfo = state => state.studio.infoStatus === Status.FETCHING; const selectIsFollowing = state => state.studio.following; const selectIsFetchingRoles = state => state.studio.rolesStatus === Status.FETCHING; @@ -115,7 +118,9 @@ const getInfo = () => ((dispatch, getState) => { openToAll: body.open_to_all, commentsAllowed: body.comments_allowed, updated: new Date(body.history.modified), + commentCount: body.stats.comments, followers: body.stats.followers, + projectCount: body.stats.projects, owner: body.owner })); }); @@ -171,6 +176,9 @@ module.exports = { selectStudioOpenToAll, selectStudioCommentsAllowed, selectStudioLoadFailed, + selectStudioCommentCount, + selectStudioFollowerCount, + selectStudioProjectCount, selectIsFetchingInfo, selectIsFetchingRoles, selectIsFollowing, diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index b2cc54c35..81861225d 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -1,7 +1,9 @@ { "studio.tabNavProjects": "Projects", + "studio.tabNavProjectsWithCount": "Projects ({projectCount})", "studio.tabNavCurators": "Curators", "studio.tabNavComments": "Comments", + "studio.tabNavCommentsWithCount": "Comments ({commentCount})", "studio.tabNavActivity": "Activity", "studio.title": "Title", diff --git a/src/views/studio/studio-tab-nav.jsx b/src/views/studio/studio-tab-nav.jsx index a6ea0fdd6..88567d39c 100644 --- a/src/views/studio/studio-tab-nav.jsx +++ b/src/views/studio/studio-tab-nav.jsx @@ -1,9 +1,14 @@ import React from 'react'; +import PropTypes from 'prop-types'; +import {connect} from 'react-redux'; import {useRouteMatch, NavLink} from 'react-router-dom'; -import SubNavigation from '../../components/subnavigation/subnavigation.jsx'; import {FormattedMessage} from 'react-intl'; -const StudioTabNav = () => { +import SubNavigation from '../../components/subnavigation/subnavigation.jsx'; + +import {selectIsFetchingInfo, selectStudioCommentCount, selectStudioProjectCount} from '../../redux/studio'; + +const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { const {params: {studioPath, studioId}} = useRouteMatch(); const base = `/${studioPath}/${studioId}`; return ( @@ -16,13 +21,19 @@ const StudioTabNav = () => { to={base} exact > -
  • +
  • -
  • +
  • { ); }; -export default StudioTabNav; +StudioTabNav.propTypes = { + isFetchingInfo: PropTypes.bool, + commentCount: PropTypes.number, + projectCount: PropTypes.number +}; + +const mapStateToProps = state => ({ + isFetchingInfo: selectIsFetchingInfo(state), + commentCount: selectStudioCommentCount(state), + projectCount: selectStudioProjectCount(state) +}); + +const mapDispatchToProps = () => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(StudioTabNav); From b21e55b5f3dd80255d90abadfd67c7d73844f454 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Fri, 21 May 2021 10:25:21 -0700 Subject: [PATCH 22/47] add followers, last-updated date to studio sidebar --- src/redux/studio.js | 2 ++ src/views/studio/l10n.json | 3 +++ src/views/studio/studio-info.jsx | 15 ++++++++--- src/views/studio/studio-stats.jsx | 41 +++++++++++++++++++++++++++++++ src/views/studio/studio.scss | 15 +++++++++++ 5 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/views/studio/studio-stats.jsx diff --git a/src/redux/studio.js b/src/redux/studio.js index 328fdc72f..02f885205 100644 --- a/src/redux/studio.js +++ b/src/redux/studio.js @@ -94,6 +94,7 @@ const selectStudioDescription = state => state.studio.description; const selectStudioImage = state => state.studio.image; const selectStudioOpenToAll = state => state.studio.openToAll; const selectStudioCommentsAllowed = state => state.studio.commentsAllowed; +const selectStudioLastUpdated = state => state.studio.updated; const selectStudioLoadFailed = state => state.studio.infoStatus === Status.ERROR; const selectStudioCommentCount = state => state.studio.commentCount; const selectStudioFollowerCount = state => state.studio.followers; @@ -175,6 +176,7 @@ module.exports = { selectStudioImage, selectStudioOpenToAll, selectStudioCommentsAllowed, + selectStudioLastUpdated, selectStudioLoadFailed, selectStudioCommentCount, selectStudioFollowerCount, diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index 81861225d..b1e1b0e3c 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -71,6 +71,9 @@ "studio.activityRemoveCurator": "{removerProfileLink} removed the curator {removedProfileLink}", "studio.activityBecomeOwner": "{promotedProfileLink} was promoted to manager by {promotorProfileLink}", + "studio.lastUpdated": "Updated {lastUpdatedDate, date, medium}", + "studio.followerCount": "{followerCount} followers", + "studio.reportThisStudio": "Report this studio", "studio.reportPleaseExplain": "Please explain why you feel this studio is disrespectful or inappropriate, or otherwise breaks the Scratch Community Guidelines.", "studio.reportAreThereComments": "Are there inappropriate comments in the studio? Please report them by clicking the \"report\" button on the individual comments.", diff --git a/src/views/studio/studio-info.jsx b/src/views/studio/studio-info.jsx index a8a9ab514..291d2f66c 100644 --- a/src/views/studio/studio-info.jsx +++ b/src/views/studio/studio-info.jsx @@ -1,14 +1,16 @@ import React, {useEffect} from 'react'; import PropTypes from 'prop-types'; import {connect} from 'react-redux'; + import StudioDescription from './studio-description.jsx'; import StudioFollow from './studio-follow.jsx'; -import StudioTitle from './studio-title.jsx'; import StudioImage from './studio-image.jsx'; +import StudioReport from './studio-report.jsx'; +import StudioStats from './studio-stats.jsx'; +import StudioTitle from './studio-title.jsx'; import {selectIsLoggedIn} from '../../redux/session'; import {getInfo, getRoles} from '../../redux/studio'; -import StudioReport from './studio-report.jsx'; const StudioInfo = ({ isLoggedIn, onLoadInfo, onLoadRoles @@ -27,7 +29,14 @@ const StudioInfo = ({ - +
    +
    + +
    +
    + +
    +
    ); }; diff --git a/src/views/studio/studio-stats.jsx b/src/views/studio/studio-stats.jsx new file mode 100644 index 000000000..f013a1657 --- /dev/null +++ b/src/views/studio/studio-stats.jsx @@ -0,0 +1,41 @@ +/* eslint-disable react/jsx-no-bind */ +import React from 'react'; +import PropTypes from 'prop-types'; +import {connect} from 'react-redux'; +import {FormattedMessage} from 'react-intl'; + +import {selectIsFetchingInfo, selectStudioFollowerCount, selectStudioLastUpdated} from '../../redux/studio'; + +const StudioStats = ({ + isFetchingInfo, + followerCount, + lastUpdatedDate +}) => { + if (isFetchingInfo) return ; + return ( +
    +
    +
    ); +}; + +StudioStats.propTypes = { + isFetchingInfo: PropTypes.bool, + followerCount: PropTypes.number, + lastUpdatedDate: PropTypes.instanceOf(Date) +}; + +export default connect( + state => ({ + isFetchingInfo: selectIsFetchingInfo(state), + followerCount: selectStudioFollowerCount(state), + lastUpdatedDate: selectStudioLastUpdated(state) + }), + { + } +)(StudioStats); diff --git a/src/views/studio/studio.scss b/src/views/studio/studio.scss index e384948b1..758937434 100644 --- a/src/views/studio/studio.scss +++ b/src/views/studio/studio.scss @@ -55,6 +55,21 @@ $radius: 8px; box-sizing: border-box; } } + + .studio-info-footer { + display: flex; + flex-direction: row; + justify-content: space-between; + } + + .studio-info-footer-stats { + justify-content: flex-start; + } + + .studio-info-footer-report { + justify-content: flex-end; + } + .studio-title { font-size: 28px; font-weight: 700; From 594cd7a285125463c4df8e74bc2f7e9f85989e6c Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Thu, 20 May 2021 18:18:33 -0700 Subject: [PATCH 23/47] add tab icons to StudioTabNav --- src/views/studio/icons/activity-icon.svg | 4 ++++ src/views/studio/icons/comments-icon.svg | 3 +++ src/views/studio/icons/projects-icon.svg | 3 +++ src/views/studio/studio-tab-nav.jsx | 21 +++++++++++++++++---- src/views/studio/studio.scss | 11 ++++++++++- 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/views/studio/icons/activity-icon.svg create mode 100644 src/views/studio/icons/comments-icon.svg create mode 100644 src/views/studio/icons/projects-icon.svg diff --git a/src/views/studio/icons/activity-icon.svg b/src/views/studio/icons/activity-icon.svg new file mode 100644 index 000000000..f7ec6145f --- /dev/null +++ b/src/views/studio/icons/activity-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/views/studio/icons/comments-icon.svg b/src/views/studio/icons/comments-icon.svg new file mode 100644 index 000000000..8a19100c1 --- /dev/null +++ b/src/views/studio/icons/comments-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/views/studio/icons/projects-icon.svg b/src/views/studio/icons/projects-icon.svg new file mode 100644 index 000000000..6b1ddccfd --- /dev/null +++ b/src/views/studio/icons/projects-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/views/studio/studio-tab-nav.jsx b/src/views/studio/studio-tab-nav.jsx index 88567d39c..389ef92bb 100644 --- a/src/views/studio/studio-tab-nav.jsx +++ b/src/views/studio/studio-tab-nav.jsx @@ -6,6 +6,11 @@ import {FormattedMessage} from 'react-intl'; import SubNavigation from '../../components/subnavigation/subnavigation.jsx'; +import activityIcon from './icons/activity-icon.svg'; +import commentsIcon from './icons/comments-icon.svg'; +import curatorsIcon from './icons/curator-icon.svg'; +import projectsIcon from './icons/projects-icon.svg'; + import {selectIsFetchingInfo, selectStudioCommentCount, selectStudioProjectCount} from '../../redux/studio'; const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { @@ -21,7 +26,9 @@ const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { to={base} exact > -
  • @@ -30,7 +37,9 @@ const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { activeClassName="active" to={`${base}/comments`} > -
  • @@ -39,13 +48,17 @@ const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { activeClassName="active" to={`${base}/curators`} > -
  • +
  • -
  • +
  • ); diff --git a/src/views/studio/studio.scss b/src/views/studio/studio.scss index 758937434..6a22ef12a 100644 --- a/src/views/studio/studio.scss +++ b/src/views/studio/studio.scss @@ -118,7 +118,16 @@ $radius: 8px; border-bottom: 1px solid $active-dark-gray; padding-bottom: 8px; font-size: 14px; - li { background: rgba(0, 0, 0, 0.15); } + li { + display: flex; + align-items: center; + background: rgba(0, 0, 0, 0.15); + padding: 0.5em 0.75em 0.5em 0.5em; + img { + margin-right: 0.5em; + width: 1.5em; + } + } .active > li { background: $ui-blue; } } From ddaa099cf09f50300934d3d5a8d3d2ced5fcb391 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Fri, 21 May 2021 10:58:10 -0700 Subject: [PATCH 24/47] add icons to StudioStats --- src/views/studio/icons/followers-icon.svg | 3 +++ src/views/studio/icons/last-updated-icon.svg | 3 +++ src/views/studio/studio-stats.jsx | 11 +++++++++-- src/views/studio/studio.scss | 10 ++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/views/studio/icons/followers-icon.svg create mode 100644 src/views/studio/icons/last-updated-icon.svg diff --git a/src/views/studio/icons/followers-icon.svg b/src/views/studio/icons/followers-icon.svg new file mode 100644 index 000000000..84e31d837 --- /dev/null +++ b/src/views/studio/icons/followers-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/views/studio/icons/last-updated-icon.svg b/src/views/studio/icons/last-updated-icon.svg new file mode 100644 index 000000000..320d0de62 --- /dev/null +++ b/src/views/studio/icons/last-updated-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/views/studio/studio-stats.jsx b/src/views/studio/studio-stats.jsx index f013a1657..3e210b502 100644 --- a/src/views/studio/studio-stats.jsx +++ b/src/views/studio/studio-stats.jsx @@ -6,6 +6,9 @@ import {FormattedMessage} from 'react-intl'; import {selectIsFetchingInfo, selectStudioFollowerCount, selectStudioLastUpdated} from '../../redux/studio'; +import lastUpdatedIcon from './icons/last-updated-icon.svg'; +import followersIcon from './icons/followers-icon.svg'; + const StudioStats = ({ isFetchingInfo, followerCount, @@ -13,11 +16,15 @@ const StudioStats = ({ }) => { if (isFetchingInfo) return ; return ( -
    -
    diff --git a/src/views/studio/studio.scss b/src/views/studio/studio.scss index 6a22ef12a..6c8428760 100644 --- a/src/views/studio/studio.scss +++ b/src/views/studio/studio.scss @@ -64,6 +64,16 @@ $radius: 8px; .studio-info-footer-stats { justify-content: flex-start; + + div { + display: flex; + align-items: center; + margin: 0.25em; + img { + margin-right: 0.25em; + width: 1.5em; + } + } } .studio-info-footer-report { From 87f4fb3a9c48cd82b1c92224566d71bd9a0f363a Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Fri, 21 May 2021 12:19:28 -0700 Subject: [PATCH 25/47] add icon & style to the StudioReport button --- src/views/studio/icons/report-icon.svg | 9 +++++++++ src/views/studio/studio-report.jsx | 11 ++++++++--- src/views/studio/studio.scss | 21 +++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/views/studio/icons/report-icon.svg diff --git a/src/views/studio/icons/report-icon.svg b/src/views/studio/icons/report-icon.svg new file mode 100644 index 000000000..cf68c1ae2 --- /dev/null +++ b/src/views/studio/icons/report-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/views/studio/studio-report.jsx b/src/views/studio/studio-report.jsx index e058239c4..3cf9767f3 100644 --- a/src/views/studio/studio-report.jsx +++ b/src/views/studio/studio-report.jsx @@ -11,15 +11,20 @@ import { selectors } from '../../redux/studio-report'; +import reportIcon from './icons/report-icon.svg'; + const StudioReport = ({ canReport, isOpen, handleOpen }) => (
    - {canReport && ( - - )} + {canReport && + + } {isOpen && ( )} diff --git a/src/views/studio/studio.scss b/src/views/studio/studio.scss index 6c8428760..8c10e3362 100644 --- a/src/views/studio/studio.scss +++ b/src/views/studio/studio.scss @@ -78,6 +78,27 @@ $radius: 8px; .studio-info-footer-report { justify-content: flex-end; + + button { + font-size: smaller; + background-color: $ui-blue; + border: 1px solid transparent; + border-radius: 999em; + color: $ui-white; + display: flex; + align-items: center; + padding: 0.25em; + padding-right: 0.75em; + + &:hover { + background-color: $ui-blue-dark; + } + + img { + margin-right: 0.25em; + width: 1.5em; + } + } } .studio-title { From ad6675f64d459f5ad38fb6ae71c4ba72f17d0b3f Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Fri, 21 May 2021 12:34:04 -0700 Subject: [PATCH 26/47] show '100+' if project/comment count is 100 or more --- src/views/studio/studio-tab-nav.jsx | 30 +++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/views/studio/studio-tab-nav.jsx b/src/views/studio/studio-tab-nav.jsx index 389ef92bb..c3a122b73 100644 --- a/src/views/studio/studio-tab-nav.jsx +++ b/src/views/studio/studio-tab-nav.jsx @@ -13,6 +13,32 @@ import projectsIcon from './icons/projects-icon.svg'; import {selectIsFetchingInfo, selectStudioCommentCount, selectStudioProjectCount} from '../../redux/studio'; + +/** + * Format a number to a string. If the number is below the limit, format as-is. Otherwise, show a '+' to indicate that + * the actual number might be higher. + * @example + * limitCount(1, 100) == '1' + * limitCount(12.5, 100) == '12.5' + * limitCount(100, 100) == '100+' + * limitCount(999, 100) == '100+' + * @param {number} num - the number to format + * @param {number} limit - the number at which we start showing a '+' + * @returns {string} - a string representing a number, possibly with a '+' at the end + */ +const limitCount = (num, limit) => { + if (num < limit) { + return `${num}`; + } + return `${limit}+`; +}; + +// These must match the limits used by the API +const countLimits = { + comments: 100, + projects: 100 +}; + const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { const {params: {studioPath, studioId}} = useRouteMatch(); const base = `/${studioPath}/${studioId}`; @@ -30,7 +56,7 @@ const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { src={projectsIcon} /> { src={commentsIcon} /> Date: Fri, 21 May 2021 12:53:14 -0700 Subject: [PATCH 27/47] fix nav tab size change on click --- src/views/studio/studio.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/views/studio/studio.scss b/src/views/studio/studio.scss index 8c10e3362..3e2788f92 100644 --- a/src/views/studio/studio.scss +++ b/src/views/studio/studio.scss @@ -154,6 +154,9 @@ $radius: 8px; align-items: center; background: rgba(0, 0, 0, 0.15); padding: 0.5em 0.75em 0.5em 0.5em; + &:active { + padding: calc(0.5em + 1px) calc(0.75em + 1px) calc(0.5em + 1px) calc(0.5em + 1px); + } img { margin-right: 0.5em; width: 1.5em; From b1b0d6b25925a98e0a081fbaba2dfb256e2bb307 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Fri, 21 May 2021 17:01:08 -0400 Subject: [PATCH 28/47] add/remove icons for project tiles --- src/views/studio/modals/user-projects-modal.scss | 8 +++++++- src/views/studio/modals/user-projects-tile.jsx | 8 +++++++- static/svgs/studio/check-icon-white.svg | 3 +++ static/svgs/studio/plus-icon-white.svg | 11 +++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 static/svgs/studio/check-icon-white.svg create mode 100644 static/svgs/studio/plus-icon-white.svg diff --git a/src/views/studio/modals/user-projects-modal.scss b/src/views/studio/modals/user-projects-modal.scss index 68124459d..137089b56 100644 --- a/src/views/studio/modals/user-projects-modal.scss +++ b/src/views/studio/modals/user-projects-modal.scss @@ -38,6 +38,10 @@ box-shadow: 0 0 0 4px $ui-blue-25percent; } +.studio-project-add-remove-image { + margin: 7px; +} + .studio-tile-dynamic-remove, .studio-tile-dynamic-add { position: absolute; @@ -54,7 +58,9 @@ margin: 0; padding: 0; line-height: 32px; - text-align: center; + align-content: center; + display: flex; + justify-content: center; } .studio-tile-dynamic-remove { background: #0FBD8C; diff --git a/src/views/studio/modals/user-projects-tile.jsx b/src/views/studio/modals/user-projects-tile.jsx index 1514ff556..a88216f3e 100644 --- a/src/views/studio/modals/user-projects-tile.jsx +++ b/src/views/studio/modals/user-projects-tile.jsx @@ -44,7 +44,13 @@ const UserProjectsTile = ({id, title, image, inStudio, onAdd, onRemove}) => {
    {title}
    - {added ? '✔' : '+'} +
    {error &&
    {error}
    }
    diff --git a/static/svgs/studio/check-icon-white.svg b/static/svgs/studio/check-icon-white.svg new file mode 100644 index 000000000..e61bdaaaf --- /dev/null +++ b/static/svgs/studio/check-icon-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/svgs/studio/plus-icon-white.svg b/static/svgs/studio/plus-icon-white.svg new file mode 100644 index 000000000..a0c1cdd64 --- /dev/null +++ b/static/svgs/studio/plus-icon-white.svg @@ -0,0 +1,11 @@ + + + + + + From 9df85ac9e471815e897511e8aa68509c0c09ede1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 22 May 2021 03:21:53 +0000 Subject: [PATCH 29/47] Bump scratch-l10n from 3.11.20210521031700 to 3.11.20210522031558 Bumps [scratch-l10n](https://github.com/LLK/scratch-l10n) from 3.11.20210521031700 to 3.11.20210522031558. - [Release notes](https://github.com/LLK/scratch-l10n/releases) - [Commits](https://github.com/LLK/scratch-l10n/compare/3.11.20210521031700...3.11.20210522031558) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3af75e8b6..1109cf5c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21310,6 +21310,19 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, + "scratch-l10n": { + "version": "3.11.20210521031700", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210521031700.tgz", + "integrity": "sha512-iY1xA8yZvjn0BpEOtKeiICuyaMlw7jmn5aO6P42DqWfVl9Uye34XBzeZJrMoFsUjhKZXXr7+IE2KUdiet5+7Yw==", + "dev": true, + "requires": { + "@babel/cli": "^7.1.2", + "@babel/core": "^7.1.2", + "babel-plugin-react-intl": "^3.0.1", + "react-intl": "^2.8.0", + "transifex": "1.6.6" + } + }, "scratch-storage": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-1.3.4.tgz", @@ -21387,9 +21400,9 @@ } }, "scratch-l10n": { - "version": "3.11.20210521031700", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210521031700.tgz", - "integrity": "sha512-iY1xA8yZvjn0BpEOtKeiICuyaMlw7jmn5aO6P42DqWfVl9Uye34XBzeZJrMoFsUjhKZXXr7+IE2KUdiet5+7Yw==", + "version": "3.11.20210522031558", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210522031558.tgz", + "integrity": "sha512-An6Synzs0MzFnAMDaZpUL7wttZzysq0r/2MWeKO6CdU7+1AVmFDAxtCP/h5xdGzoNhxf8Vy02LvSfn4ofYZDCA==", "dev": true, "requires": { "@babel/cli": "^7.1.2", From e76f1ed1061a819f0383c39b335b0767f29a906e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 23 May 2021 04:30:41 +0000 Subject: [PATCH 30/47] Bump @formatjs/intl-locale from 2.4.27 to 2.4.28 Bumps [@formatjs/intl-locale](https://github.com/formatjs/formatjs) from 2.4.27 to 2.4.28. - [Release notes](https://github.com/formatjs/formatjs/releases) - [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-locale@2.4.27...@formatjs/intl-locale@2.4.28) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1109cf5c1..b03a1b214 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1404,17 +1404,26 @@ } }, "@formatjs/intl-locale": { - "version": "2.4.27", - "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-2.4.27.tgz", - "integrity": "sha512-pUq/0jXqKhFE1j19/TAgHAptrmS2J7CUlR04fov/fF/VV+J1+RMh2Uh9pkp7mZktROQ9t3YfqZIv6oyph+C1Ng==", + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-2.4.28.tgz", + "integrity": "sha512-z20qVhgtHFTCGLDCl/pWs3cdnxGT4whsbjxwfrhyF2Qf0TNYWrJ/y88f3vINJ19iGVY3GJ6bxaRI5d+uyQ/7ig==", "dev": true, "requires": { - "@formatjs/ecma402-abstract": "1.9.0", + "@formatjs/ecma402-abstract": "1.9.1", "@formatjs/intl-getcanonicallocales": "1.7.0", "cldr-core": "38", "tslib": "^2.1.0" }, "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.1.tgz", + "integrity": "sha512-XAJ1ygWKgGEaFuNg3Cf+maJNYEJjl5LjSVZ1iAnSaOKDg/VXa+dDPWhWQP6jimvWv6h9NyDj6Zgh+2qFBeVABw==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, "tslib": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", From 054acc955ac4e02ed03fa77b04647d149cdf9351 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 23 May 2021 04:31:01 +0000 Subject: [PATCH 31/47] Bump @formatjs/intl-pluralrules from 4.0.21 to 4.0.22 Bumps [@formatjs/intl-pluralrules](https://github.com/formatjs/formatjs) from 4.0.21 to 4.0.22. - [Release notes](https://github.com/formatjs/formatjs/releases) - [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-pluralrules@4.0.21...@formatjs/intl-pluralrules@4.0.22) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1109cf5c1..18228be04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1424,15 +1424,24 @@ } }, "@formatjs/intl-pluralrules": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-4.0.21.tgz", - "integrity": "sha512-SEouCAFL1QLVfFWCsZFNYtWXU05Q7wIaq9kGQujT25iy7eT53kvt9SVE2DySHooe56y9VBt4jS0YKPzP+BLTug==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-4.0.22.tgz", + "integrity": "sha512-4pSxb31AsjZXUjQHid9eJuUJrXqLOH3tgfiryvBfgNoS76cqk0cFUAuTGdC07YQZlVuJ4c3K4rqBlRpFJwn4Mg==", "dev": true, "requires": { - "@formatjs/ecma402-abstract": "1.9.0", + "@formatjs/ecma402-abstract": "1.9.1", "tslib": "^2.1.0" }, "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.1.tgz", + "integrity": "sha512-XAJ1ygWKgGEaFuNg3Cf+maJNYEJjl5LjSVZ1iAnSaOKDg/VXa+dDPWhWQP6jimvWv6h9NyDj6Zgh+2qFBeVABw==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, "tslib": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", From e3ba371c6ab6dfc96145811e1e10b5cec2cc90fd Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 24 May 2021 03:47:21 +0000 Subject: [PATCH 32/47] Bump scratch-l10n from 3.11.20210522031558 to 3.11.20210524031609 Bumps [scratch-l10n](https://github.com/LLK/scratch-l10n) from 3.11.20210522031558 to 3.11.20210524031609. - [Release notes](https://github.com/LLK/scratch-l10n/releases) - [Commits](https://github.com/LLK/scratch-l10n/compare/3.11.20210522031558...3.11.20210524031609) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 78bc4acee..653cdfad8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1368,23 +1368,6 @@ } } }, - "@formatjs/ecma402-abstract": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.0.tgz", - "integrity": "sha512-hKWk3t4uKmGW1kS6lR8j3vzHhyK3oXb/sgQ6YImsHLen8FFbmPDEEiwz6geNaKtEioCGYFF1B2BYLBH8JjbFxQ==", - "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.7.0", "resolved": "https://registry.npmjs.org/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-1.7.0.tgz", @@ -21418,9 +21401,9 @@ } }, "scratch-l10n": { - "version": "3.11.20210522031558", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210522031558.tgz", - "integrity": "sha512-An6Synzs0MzFnAMDaZpUL7wttZzysq0r/2MWeKO6CdU7+1AVmFDAxtCP/h5xdGzoNhxf8Vy02LvSfn4ofYZDCA==", + "version": "3.11.20210524031609", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210524031609.tgz", + "integrity": "sha512-J6fqjT9QAMACI98mk58rn48nKoQNzuP2LiEt5GgkSw+kTt/kKJTYTtT2C2hOnYJZcZrTyPFwAWTyi68sxg23xQ==", "dev": true, "requires": { "@babel/cli": "^7.1.2", From eba106143df975bc541cafcb9c7141c67847fd14 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 24 May 2021 10:51:34 +0000 Subject: [PATCH 33/47] Bump scratch-gui Bumps [scratch-gui](https://github.com/LLK/scratch-gui) from 0.1.0-prerelease.20210521035500 to 0.1.0-prerelease.20210522033750. - [Release notes](https://github.com/LLK/scratch-gui/releases) - [Commits](https://github.com/LLK/scratch-gui/compare/0.1.0-prerelease.20210521035500...0.1.0-prerelease.20210522033750) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 20 ++++++++++---------- package.json | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 653cdfad8..f860c0c93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20866,9 +20866,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20210521035500", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210521035500.tgz", - "integrity": "sha512-wo7kKITvLVhsOJYag9LjKdeURfwdcGlDaIkkW0+uq5OioDw+7OkH5ejdE+5HKByHVuo2vbSLc3VEL5JAThlVwQ==", + "version": "0.1.0-prerelease.20210522033750", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210522033750.tgz", + "integrity": "sha512-P32L88nVkWgnlOYZ637+wMxKor2qphP0UmOlFVMwr38UVfvovUjj+k/lp/60SX/coalCByKHdZTOuboKZcggNQ==", "dev": true, "requires": { "arraybuffer-loader": "^1.0.6", @@ -20920,7 +20920,7 @@ "redux-throttle": "0.1.1", "scratch-audio": "0.1.0-prerelease.20200528195344", "scratch-blocks": "0.1.0-prerelease.20210521033213", - "scratch-l10n": "3.11.20210521031700", + "scratch-l10n": "3.11.20210522031558", "scratch-paint": "0.2.0-prerelease.20210407203313", "scratch-render": "0.1.0-prerelease.20210325231800", "scratch-render-fonts": "1.0.0-prerelease.20210401210003", @@ -21089,9 +21089,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.735", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.735.tgz", - "integrity": "sha512-cp7MWzC3NseUJV2FJFgaiesdrS+A8ZUjX5fLAxdRlcaPDkaPGFplX930S5vf84yqDp4LjuLdKouWuVOTwUfqHQ==", + "version": "1.3.736", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.736.tgz", + "integrity": "sha512-DY8dA7gR51MSo66DqitEQoUMQ0Z+A2DSXFi7tK304bdTVqczCAfUuyQw6Wdg8hIoo5zIxkU1L24RQtUce1Ioig==", "dev": true }, "has-flag": { @@ -21312,9 +21312,9 @@ "dev": true }, "scratch-l10n": { - "version": "3.11.20210521031700", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210521031700.tgz", - "integrity": "sha512-iY1xA8yZvjn0BpEOtKeiICuyaMlw7jmn5aO6P42DqWfVl9Uye34XBzeZJrMoFsUjhKZXXr7+IE2KUdiet5+7Yw==", + "version": "3.11.20210522031558", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210522031558.tgz", + "integrity": "sha512-An6Synzs0MzFnAMDaZpUL7wttZzysq0r/2MWeKO6CdU7+1AVmFDAxtCP/h5xdGzoNhxf8Vy02LvSfn4ofYZDCA==", "dev": true, "requires": { "@babel/cli": "^7.1.2", diff --git a/package.json b/package.json index db98b19ca..a6731745a 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.20210521035500", + "scratch-gui": "0.1.0-prerelease.20210522033750", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From 40295d38608787e5753f76d7d3fa2a9c67d297e6 Mon Sep 17 00:00:00 2001 From: rschamp Date: Mon, 24 May 2021 09:36:47 -0400 Subject: [PATCH 34/47] Bump conference URL one year Resolves #5197 --- src/routes.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/routes.json b/src/routes.json index 97976d6bb..8d351c0f8 100644 --- a/src/routes.json +++ b/src/routes.json @@ -25,7 +25,7 @@ "name": "conference-index", "pattern": "^/conference/?(\\?.*)?$", "routeAlias": "/conference(?!/201[4-9])", - "redirect": "/conference/2020" + "redirect": "/conference/2021" }, { "name": "conference-index-2017", @@ -83,6 +83,12 @@ "name": "conference-index-2020", "pattern": "^/conference/2020/?$", "routeAlias": "/conference(?!/201[4-9])", + "redirect": "/conference/2021" + }, + { + "name": "conference-index-2021", + "pattern": "^/conference/2021/?$", + "routeAlias": "/conference(?!/201[4-9])", "view": "conference/2020/index/index", "title": "Scratch Conferences", "viewportWidth": "device-width" From 59a4146d3bf946bce200cecf7545cad69d99900a Mon Sep 17 00:00:00 2001 From: rschamp Date: Mon, 24 May 2021 14:23:06 -0400 Subject: [PATCH 35/47] Fix integration test broken in #5476 --- test/integration/footer-links.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/footer-links.test.js b/test/integration/footer-links.test.js index fe5c8eeda..1e2eadd2f 100644 --- a/test/integration/footer-links.test.js +++ b/test/integration/footer-links.test.js @@ -139,7 +139,7 @@ describe('www-integration footer links', () => { await clickText('Scratch Conference'); let url = await driver.getCurrentUrl(); let pathname = (new URL(url)).pathname; - expect(pathname).toMatch(/^\/conference\/2020\/?$/); + expect(pathname).toMatch(/^\/conference\/2021\/?$/); }); }); From 38c2af740e018e5ee50cb1236d1165d731522a02 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 24 May 2021 17:08:45 -0400 Subject: [PATCH 36/47] look for guiPlayer on project page in project rows test --- test/integration/project-rows.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/integration/project-rows.test.js b/test/integration/project-rows.test.js index 3910c44d9..ccf436e5f 100644 --- a/test/integration/project-rows.test.js +++ b/test/integration/project-rows.test.js @@ -12,7 +12,7 @@ let rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; if (remote) { jest.setTimeout(60000); } else { - jest.setTimeout(10000); + jest.setTimeout(20000); } let driver; @@ -38,9 +38,9 @@ describe('www-integration project rows', () => { test('Featured Project link', async () => { await clickXpath('//div[@class="box"][descendant::text()="Featured Projects"]' + '//div[contains(@class, "thumbnail")][1]/a[@class="thumbnail-image"]'); - let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); - let gfOverlayDisplayed = await gfOverlay.isDisplayed(); - await expect(gfOverlayDisplayed).toBe(true); + let guiPlayer = await findByXpath('//div[@class="guiPlayer"]'); + let guiPlayerDisplayed = await guiPlayer.isDisplayed(); + await expect(guiPlayerDisplayed).toBe(true); }); test('Featured Studios row title', async () => { From 2c241ce953d3198be814ae874fd96709adc830fc Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 24 May 2021 17:09:18 -0400 Subject: [PATCH 37/47] increase timeouts for local tests --- test/integration/my-stuff.test.js | 2 +- test/integration/project-page.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/my-stuff.test.js b/test/integration/my-stuff.test.js index 7686abefb..5723d6e8a 100644 --- a/test/integration/my-stuff.test.js +++ b/test/integration/my-stuff.test.js @@ -16,7 +16,7 @@ let myStuffURL = rootUrl + '/mystuff'; if (remote){ jest.setTimeout(60000); } else { - jest.setTimeout(10000); + jest.setTimeout(20000); } let driver; diff --git a/test/integration/project-page.test.js b/test/integration/project-page.test.js index 993e6c6d4..35112fa7f 100644 --- a/test/integration/project-page.test.js +++ b/test/integration/project-page.test.js @@ -14,7 +14,7 @@ let projectUrl = rootUrl + '/projects/' + projectId; if (remote){ jest.setTimeout(60000); } else { - jest.setTimeout(10000); + jest.setTimeout(20000); } let driver; From 0dee03c57c5479548460498bd32d53613d8f4fe6 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 24 May 2021 17:09:40 -0400 Subject: [PATCH 38/47] bump chromedriver to version 90.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f92a0ecd9..535570cbd 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "babel-preset-react": "6.22.0", "bowser": "1.9.4", "cheerio": "1.0.0-rc.2", - "chromedriver": "86.0.0", + "chromedriver": "90.0.1", "classnames": "2.2.5", "cookie": "0.4.1", "copy-webpack-plugin": "0.2.0", From a9239985d5cb98d9f6bf812e1fb529238585f9e6 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 24 May 2021 17:12:02 -0400 Subject: [PATCH 39/47] rename project-rows tests to homepage-rows --- test/integration/{project-rows.test.js => homepage-rows.test.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/integration/{project-rows.test.js => homepage-rows.test.js} (100%) diff --git a/test/integration/project-rows.test.js b/test/integration/homepage-rows.test.js similarity index 100% rename from test/integration/project-rows.test.js rename to test/integration/homepage-rows.test.js From a194b485666194e2d7acee556ad971d944b5b4fa Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 24 May 2021 17:12:20 -0400 Subject: [PATCH 40/47] load more button is fill width --- src/views/studio/modals/user-projects-modal.jsx | 6 +++--- src/views/studio/modals/user-projects-modal.scss | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/views/studio/modals/user-projects-modal.jsx b/src/views/studio/modals/user-projects-modal.jsx index 9b951117c..7da275529 100644 --- a/src/views/studio/modals/user-projects-modal.jsx +++ b/src/views/studio/modals/user-projects-modal.jsx @@ -85,7 +85,8 @@ const UserProjectsModal = ({ onRemove={onRemove} /> ))} - {moreToLoad && +
    + {moreToLoad &&
    - } -
    + } ); diff --git a/src/views/studio/modals/user-projects-modal.scss b/src/views/studio/modals/user-projects-modal.scss index 137089b56..7573f89ab 100644 --- a/src/views/studio/modals/user-projects-modal.scss +++ b/src/views/studio/modals/user-projects-modal.scss @@ -31,6 +31,10 @@ & { max-height: calc(100vh - 105px); } } } + + .studio-projects-load-more { + display: contents; + } } .studio-tile-added { @@ -70,6 +74,7 @@ .user-projects-modal-grid { margin-top: 12px; + margin-bottom: 8px; display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); @@ -82,10 +87,6 @@ column-gap: 14px; row-gap: 14px; - .studio-projects-load-more { - grid-column: 1 / -1; - } - .studio-project-bottom { padding: 8px 10px 8px 10px; } From e5212234ac29a4e34db8a43b28e2ff8b9ee2bd4d Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 24 May 2021 17:22:20 -0400 Subject: [PATCH 41/47] lint --- .../studio/modals/user-projects-modal.jsx | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/views/studio/modals/user-projects-modal.jsx b/src/views/studio/modals/user-projects-modal.jsx index 00a510f4b..631bab5be 100644 --- a/src/views/studio/modals/user-projects-modal.jsx +++ b/src/views/studio/modals/user-projects-modal.jsx @@ -89,20 +89,19 @@ const UserProjectsModal = ({ onRemove={onRemove} /> ))} +
    + {moreToLoad && +
    +
    - {moreToLoad && -
    - -
    - } - + } From 6e67bfbaeac8d392d0739f2cd34b95419020dc4b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 25 May 2021 03:24:23 +0000 Subject: [PATCH 42/47] Bump scratch-l10n from 3.11.20210524031609 to 3.11.20210525031530 Bumps [scratch-l10n](https://github.com/LLK/scratch-l10n) from 3.11.20210524031609 to 3.11.20210525031530. - [Release notes](https://github.com/LLK/scratch-l10n/releases) - [Commits](https://github.com/LLK/scratch-l10n/compare/3.11.20210524031609...3.11.20210525031530) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f860c0c93..3ab2162da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21401,9 +21401,9 @@ } }, "scratch-l10n": { - "version": "3.11.20210524031609", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210524031609.tgz", - "integrity": "sha512-J6fqjT9QAMACI98mk58rn48nKoQNzuP2LiEt5GgkSw+kTt/kKJTYTtT2C2hOnYJZcZrTyPFwAWTyi68sxg23xQ==", + "version": "3.11.20210525031530", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210525031530.tgz", + "integrity": "sha512-TsfrhADYKGP2++wT9emiyfp8DKnVd0iELX0ICF1zy9G9aNdAnPUVvmdZghjwkk1CuEdIfWk/+XEa4CrF1ahgeg==", "dev": true, "requires": { "@babel/cli": "^7.1.2", From e2bc78444eb012c5e929494ba016b0819234007c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 25 May 2021 10:51:08 +0000 Subject: [PATCH 43/47] Bump scratch-gui Bumps [scratch-gui](https://github.com/LLK/scratch-gui) from 0.1.0-prerelease.20210522033750 to 0.1.0-prerelease.20210525033905. - [Release notes](https://github.com/LLK/scratch-gui/releases) - [Commits](https://github.com/LLK/scratch-gui/compare/0.1.0-prerelease.20210522033750...0.1.0-prerelease.20210525033905) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 27 +++++++-------------------- package.json | 2 +- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3ab2162da..914666cbe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20866,9 +20866,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20210522033750", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210522033750.tgz", - "integrity": "sha512-P32L88nVkWgnlOYZ637+wMxKor2qphP0UmOlFVMwr38UVfvovUjj+k/lp/60SX/coalCByKHdZTOuboKZcggNQ==", + "version": "0.1.0-prerelease.20210525033905", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210525033905.tgz", + "integrity": "sha512-uFNZ3cTZeyrENCo89JY+12bRMxIi+TaLvXKsr4/UDpFx3mMBO080USk7tOzNJYAma85Z7cwjYiL16t6HgXCXIQ==", "dev": true, "requires": { "arraybuffer-loader": "^1.0.6", @@ -20920,7 +20920,7 @@ "redux-throttle": "0.1.1", "scratch-audio": "0.1.0-prerelease.20200528195344", "scratch-blocks": "0.1.0-prerelease.20210521033213", - "scratch-l10n": "3.11.20210522031558", + "scratch-l10n": "3.11.20210525031530", "scratch-paint": "0.2.0-prerelease.20210407203313", "scratch-render": "0.1.0-prerelease.20210325231800", "scratch-render-fonts": "1.0.0-prerelease.20210401210003", @@ -21089,9 +21089,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.736", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.736.tgz", - "integrity": "sha512-DY8dA7gR51MSo66DqitEQoUMQ0Z+A2DSXFi7tK304bdTVqczCAfUuyQw6Wdg8hIoo5zIxkU1L24RQtUce1Ioig==", + "version": "1.3.738", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.738.tgz", + "integrity": "sha512-vCMf4gDOpEylPSLPLSwAEsz+R3ShP02Y3cAKMZvTqule3XcPp7tgc/0ESI7IS6ZeyBlGClE50N53fIOkcIVnpw==", "dev": true }, "has-flag": { @@ -21311,19 +21311,6 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, - "scratch-l10n": { - "version": "3.11.20210522031558", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210522031558.tgz", - "integrity": "sha512-An6Synzs0MzFnAMDaZpUL7wttZzysq0r/2MWeKO6CdU7+1AVmFDAxtCP/h5xdGzoNhxf8Vy02LvSfn4ofYZDCA==", - "dev": true, - "requires": { - "@babel/cli": "^7.1.2", - "@babel/core": "^7.1.2", - "babel-plugin-react-intl": "^3.0.1", - "react-intl": "^2.8.0", - "transifex": "1.6.6" - } - }, "scratch-storage": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-1.3.4.tgz", diff --git a/package.json b/package.json index a6731745a..d54583cd7 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.20210522033750", + "scratch-gui": "0.1.0-prerelease.20210525033905", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From f50d8dbf66107bdbd7b051d79c70d930035c7a20 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 25 May 2021 09:48:33 -0400 Subject: [PATCH 44/47] Wrap counts in span for styling --- src/views/studio/l10n.json | 4 ++-- src/views/studio/studio-tab-nav.jsx | 16 ++++++++++++++-- src/views/studio/studio.scss | 3 +++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/views/studio/l10n.json b/src/views/studio/l10n.json index b1e1b0e3c..435d71fb8 100644 --- a/src/views/studio/l10n.json +++ b/src/views/studio/l10n.json @@ -1,9 +1,9 @@ { "studio.tabNavProjects": "Projects", - "studio.tabNavProjectsWithCount": "Projects ({projectCount})", + "studio.tabNavProjectsWithCount": "Projects {projectCount}", "studio.tabNavCurators": "Curators", "studio.tabNavComments": "Comments", - "studio.tabNavCommentsWithCount": "Comments ({commentCount})", + "studio.tabNavCommentsWithCount": "Comments {commentCount}", "studio.tabNavActivity": "Activity", "studio.title": "Title", diff --git a/src/views/studio/studio-tab-nav.jsx b/src/views/studio/studio-tab-nav.jsx index c3a122b73..2192af0de 100644 --- a/src/views/studio/studio-tab-nav.jsx +++ b/src/views/studio/studio-tab-nav.jsx @@ -56,7 +56,13 @@ const StudioTabNav = ({isFetchingInfo, commentCount, projectCount}) => { src={projectsIcon} /> + ({limitCount(projectCount, countLimits.projects)}) + + ) + }} /> { src={commentsIcon} /> + ({limitCount(commentCount, countLimits.comments)}) + + ) + }} /> li { background: $ui-blue; } } From d6a9c8d1bd72b8e613746bf9b068ad2b854163a8 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 25 May 2021 15:55:19 -0400 Subject: [PATCH 45/47] Revert "bump chromedriver to version 90.0.1" This reverts commit 0dee03c57c5479548460498bd32d53613d8f4fe6. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 535570cbd..f92a0ecd9 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "babel-preset-react": "6.22.0", "bowser": "1.9.4", "cheerio": "1.0.0-rc.2", - "chromedriver": "90.0.1", + "chromedriver": "86.0.0", "classnames": "2.2.5", "cookie": "0.4.1", "copy-webpack-plugin": "0.2.0", From 242085163408125b00c94674c54489bee77dd8b8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 26 May 2021 03:33:55 +0000 Subject: [PATCH 46/47] Bump scratch-l10n from 3.11.20210525031530 to 3.11.20210526031609 Bumps [scratch-l10n](https://github.com/LLK/scratch-l10n) from 3.11.20210525031530 to 3.11.20210526031609. - [Release notes](https://github.com/LLK/scratch-l10n/releases) - [Commits](https://github.com/LLK/scratch-l10n/compare/3.11.20210525031530...3.11.20210526031609) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 914666cbe..db3084b49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -503,9 +503,9 @@ } }, "electron-to-chromium": { - "version": "1.3.735", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.735.tgz", - "integrity": "sha512-cp7MWzC3NseUJV2FJFgaiesdrS+A8ZUjX5fLAxdRlcaPDkaPGFplX930S5vf84yqDp4LjuLdKouWuVOTwUfqHQ==", + "version": "1.3.739", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz", + "integrity": "sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==", "dev": true }, "semver": { @@ -21311,6 +21311,19 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, + "scratch-l10n": { + "version": "3.11.20210525031530", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210525031530.tgz", + "integrity": "sha512-TsfrhADYKGP2++wT9emiyfp8DKnVd0iELX0ICF1zy9G9aNdAnPUVvmdZghjwkk1CuEdIfWk/+XEa4CrF1ahgeg==", + "dev": true, + "requires": { + "@babel/cli": "^7.1.2", + "@babel/core": "^7.1.2", + "babel-plugin-react-intl": "^3.0.1", + "react-intl": "^2.8.0", + "transifex": "1.6.6" + } + }, "scratch-storage": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-1.3.4.tgz", @@ -21388,9 +21401,9 @@ } }, "scratch-l10n": { - "version": "3.11.20210525031530", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210525031530.tgz", - "integrity": "sha512-TsfrhADYKGP2++wT9emiyfp8DKnVd0iELX0ICF1zy9G9aNdAnPUVvmdZghjwkk1CuEdIfWk/+XEa4CrF1ahgeg==", + "version": "3.11.20210526031609", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210526031609.tgz", + "integrity": "sha512-Lr2d09o92jgBptCA5FfC3U9YXesKhPAVzRTQkydsz7DpQKmMilI81gxP6o5CLzxi85hyzZmvIRGlhRIhfHbgBQ==", "dev": true, "requires": { "@babel/cli": "^7.1.2", From 050f52e36859746d6148a89d58819e2c708c7960 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 26 May 2021 10:40:50 +0000 Subject: [PATCH 47/47] Bump scratch-gui Bumps [scratch-gui](https://github.com/LLK/scratch-gui) from 0.1.0-prerelease.20210525033905 to 0.1.0-prerelease.20210526041028. - [Release notes](https://github.com/LLK/scratch-gui/releases) - [Commits](https://github.com/LLK/scratch-gui/compare/0.1.0-prerelease.20210525033905...0.1.0-prerelease.20210526041028) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 35 +++++++++++------------------------ package.json | 2 +- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index db3084b49..0f8bd4a5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20856,9 +20856,9 @@ } }, "scratch-blocks": { - "version": "0.1.0-prerelease.20210521033213", - "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20210521033213.tgz", - "integrity": "sha512-a6fmtfr3Wyr+sX9+HSxGdcUOV43fgAVYU6sDtwOWiyUiGzvzWZKUWLaf52hQOgJ5tH3Ob7OJPdkt8nvGIYU1nQ==", + "version": "0.1.0-prerelease.20210526033756", + "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20210526033756.tgz", + "integrity": "sha512-KI5qN+EUhrqRfyCgW7/on3pZuzGxxpWhnTdsv7t4PS4fpOmjTMWXxFg2bCh0pJcFrOWHCF/SfQZh/fhwtmaDGg==", "dev": true, "requires": { "exports-loader": "0.6.3", @@ -20866,9 +20866,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20210525033905", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210525033905.tgz", - "integrity": "sha512-uFNZ3cTZeyrENCo89JY+12bRMxIi+TaLvXKsr4/UDpFx3mMBO080USk7tOzNJYAma85Z7cwjYiL16t6HgXCXIQ==", + "version": "0.1.0-prerelease.20210526041028", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20210526041028.tgz", + "integrity": "sha512-BUgeYEXcs3rbPQb+V93mQX5sXvE2z1Biq2+bSQuWWZzahJKCuLgfwSlBio5T2NTFk0G0QekQmmX5hasvDTPEtw==", "dev": true, "requires": { "arraybuffer-loader": "^1.0.6", @@ -20919,8 +20919,8 @@ "redux": "3.7.2", "redux-throttle": "0.1.1", "scratch-audio": "0.1.0-prerelease.20200528195344", - "scratch-blocks": "0.1.0-prerelease.20210521033213", - "scratch-l10n": "3.11.20210525031530", + "scratch-blocks": "0.1.0-prerelease.20210526033756", + "scratch-l10n": "3.11.20210526031609", "scratch-paint": "0.2.0-prerelease.20210407203313", "scratch-render": "0.1.0-prerelease.20210325231800", "scratch-render-fonts": "1.0.0-prerelease.20210401210003", @@ -21089,9 +21089,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.738", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.738.tgz", - "integrity": "sha512-vCMf4gDOpEylPSLPLSwAEsz+R3ShP02Y3cAKMZvTqule3XcPp7tgc/0ESI7IS6ZeyBlGClE50N53fIOkcIVnpw==", + "version": "1.3.739", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz", + "integrity": "sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==", "dev": true }, "has-flag": { @@ -21311,19 +21311,6 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, - "scratch-l10n": { - "version": "3.11.20210525031530", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.11.20210525031530.tgz", - "integrity": "sha512-TsfrhADYKGP2++wT9emiyfp8DKnVd0iELX0ICF1zy9G9aNdAnPUVvmdZghjwkk1CuEdIfWk/+XEa4CrF1ahgeg==", - "dev": true, - "requires": { - "@babel/cli": "^7.1.2", - "@babel/core": "^7.1.2", - "babel-plugin-react-intl": "^3.0.1", - "react-intl": "^2.8.0", - "transifex": "1.6.6" - } - }, "scratch-storage": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-1.3.4.tgz", diff --git a/package.json b/package.json index 78b472851..08bfbc397 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.20210525033905", + "scratch-gui": "0.1.0-prerelease.20210526041028", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0",