From 791f72d8ff71daaec3f18e254f5d8ca9267cfc8b Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Sun, 14 Mar 2021 21:09:33 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../behaviors/shortcuts/keybindings.js | 134 ++++++++---------- ...-terraform-module-registry-iteration-1.yml | 5 + ...orm_module_max_file_size_to_plan_limits.rb | 9 ++ db/schema_migrations/20210305145622 | 1 + db/structure.sql | 3 +- .../fe_guide/keyboard_shortcuts.md | 63 +++++--- locale/gitlab.pot | 6 + .../behaviors/shortcuts/keybindings_spec.js | 74 +++++++--- 8 files changed, 181 insertions(+), 114 deletions(-) create mode 100644 changelogs/unreleased/321102-terraform-module-registry-iteration-1.yml create mode 100644 db/migrate/20210305145622_add_terraform_module_max_file_size_to_plan_limits.rb create mode 100644 db/schema_migrations/20210305145622 diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js index 0513e807ed6..fe75a4562cc 100644 --- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js +++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js @@ -1,91 +1,77 @@ -import { flatten } from 'lodash'; +import { memoize } from 'lodash'; import AccessorUtilities from '~/lib/utils/accessor'; import { s__ } from '~/locale'; -import { shouldDisableShortcuts } from './shortcuts_toggle'; export const LOCAL_STORAGE_KEY = 'gl-keyboard-shortcuts-customizations'; -let parsedCustomizations = {}; -const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe(); - -if (localStorageIsSafe) { - try { - parsedCustomizations = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) || '{}'); - } catch (e) { - /* do nothing */ - } -} - /** - * A map of command => keys of all keyboard shortcuts - * that have been customized by the user. + * @returns { Object. } A map of command ID => keys of all + * keyboard shortcuts that have been customized by the user. These + * customizations are fetched from `localStorage`. This function is memoized, + * so its return value will not reflect changes made to the `localStorage` data + * after it has been called once. * * @example * { "globalShortcuts.togglePerformanceBar": ["p e r f"] } - * - * @type { Object. } */ -export const customizations = parsedCustomizations; +export const getCustomizations = memoize(() => { + let parsedCustomizations = {}; + const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe(); + + if (localStorageIsSafe) { + try { + parsedCustomizations = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) || '{}'); + } catch (e) { + /* do nothing */ + } + } + + return parsedCustomizations; +}); // All available commands -export const TOGGLE_PERFORMANCE_BAR = 'globalShortcuts.togglePerformanceBar'; -export const TOGGLE_CANARY = 'globalShortcuts.toggleCanary'; +export const TOGGLE_PERFORMANCE_BAR = { + id: 'globalShortcuts.togglePerformanceBar', + description: s__('KeyboardShortcuts|Toggle the Performance Bar'), + // eslint-disable-next-line @gitlab/require-i18n-strings + defaultKeys: ['p b'], +}; + +export const TOGGLE_CANARY = { + id: 'globalShortcuts.toggleCanary', + description: s__('KeyboardShortcuts|Toggle GitLab Next'), + // eslint-disable-next-line @gitlab/require-i18n-strings + defaultKeys: ['g x'], +}; + +export const WEB_IDE_COMMIT = { + id: 'webIDE.commit', + description: s__('KeyboardShortcuts|Commit (when editing commit message)'), + defaultKeys: ['mod+enter'], + customizable: false, +}; + +// All keybinding groups +export const GLOBAL_SHORTCUTS_GROUP = { + id: 'globalShortcuts', + name: s__('KeyboardShortcuts|Global Shortcuts'), + keybindings: [TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY], +}; + +export const WEB_IDE_GROUP = { + id: 'webIDE', + name: s__('KeyboardShortcuts|Web IDE'), + keybindings: [WEB_IDE_COMMIT], +}; /** All keybindings, grouped and ordered with descriptions */ -export const keybindingGroups = [ - { - groupId: 'globalShortcuts', - name: s__('KeyboardShortcuts|Global Shortcuts'), - keybindings: [ - { - description: s__('KeyboardShortcuts|Toggle the Performance Bar'), - command: TOGGLE_PERFORMANCE_BAR, - // eslint-disable-next-line @gitlab/require-i18n-strings - defaultKeys: ['p b'], - }, - { - description: s__('KeyboardShortcuts|Toggle GitLab Next'), - command: TOGGLE_CANARY, - // eslint-disable-next-line @gitlab/require-i18n-strings - defaultKeys: ['g x'], - }, - ], - }, -] - - // For each keybinding object, add a `customKeys` property populated with the - // user's custom keybindings (if the command has been customized). - // `customKeys` will be `undefined` if the command hasn't been customized. - .map((group) => { - return { - ...group, - keybindings: group.keybindings.map((binding) => ({ - ...binding, - customKeys: customizations[binding.command], - })), - }; - }); - -/** - * A simple map of command => keys. All user customizations are included in this map. - * This mapping is used to simplify `keysFor` below. - * - * @example - * { "globalShortcuts.togglePerformanceBar": ["p e r f"] } - */ -const commandToKeys = flatten(keybindingGroups.map((group) => group.keybindings)).reduce( - (acc, binding) => { - acc[binding.command] = binding.customKeys || binding.defaultKeys; - return acc; - }, - {}, -); +export const keybindingGroups = [GLOBAL_SHORTCUTS_GROUP, WEB_IDE_GROUP]; /** * Gets keyboard shortcuts associated with a command * - * @param {string} command The command string. All command - * strings are available as imports from this file. + * @param {string} command The command object. All command + * objects are available as imports from this file. * * @returns {string[]} An array of keyboard shortcut strings bound to the command * @@ -95,9 +81,11 @@ const commandToKeys = flatten(keybindingGroups.map((group) => group.keybindings) * Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), handler); */ export const keysFor = (command) => { - if (shouldDisableShortcuts()) { - return []; + if (command.customizable === false) { + // if the command is defined with `customizable: false`, + // don't allow this command to be customized. + return command.defaultKeys; } - return commandToKeys[command]; + return getCustomizations()[command.id] || command.defaultKeys; }; diff --git a/changelogs/unreleased/321102-terraform-module-registry-iteration-1.yml b/changelogs/unreleased/321102-terraform-module-registry-iteration-1.yml new file mode 100644 index 00000000000..1ceddac6a88 --- /dev/null +++ b/changelogs/unreleased/321102-terraform-module-registry-iteration-1.yml @@ -0,0 +1,5 @@ +--- +title: Add plan limit for Terraform Module package file size +merge_request: 56414 +author: +type: added diff --git a/db/migrate/20210305145622_add_terraform_module_max_file_size_to_plan_limits.rb b/db/migrate/20210305145622_add_terraform_module_max_file_size_to_plan_limits.rb new file mode 100644 index 00000000000..d2342a66549 --- /dev/null +++ b/db/migrate/20210305145622_add_terraform_module_max_file_size_to_plan_limits.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddTerraformModuleMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def change + add_column :plan_limits, :terraform_module_max_file_size, :bigint, default: 1.gigabyte, null: false + end +end diff --git a/db/schema_migrations/20210305145622 b/db/schema_migrations/20210305145622 new file mode 100644 index 00000000000..4a4c89a03c8 --- /dev/null +++ b/db/schema_migrations/20210305145622 @@ -0,0 +1 @@ +be22d5a1c61cbb8b2396a351951ffcee54fbf37dc5ef5f899576a36a14200e75 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index aa121ae6187..39b8b0461d0 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -15762,7 +15762,8 @@ CREATE TABLE plan_limits ( ci_pipeline_deployments integer DEFAULT 500 NOT NULL, pull_mirror_interval_seconds integer DEFAULT 300 NOT NULL, daily_invites integer DEFAULT 0 NOT NULL, - rubygems_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL + rubygems_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL, + terraform_module_max_file_size bigint DEFAULT 1073741824 NOT NULL ); CREATE SEQUENCE plan_limits_id_seq diff --git a/doc/development/fe_guide/keyboard_shortcuts.md b/doc/development/fe_guide/keyboard_shortcuts.md index e50e9ec65df..aab252da305 100644 --- a/doc/development/fe_guide/keyboard_shortcuts.md +++ b/doc/development/fe_guide/keyboard_shortcuts.md @@ -33,9 +33,10 @@ Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), togglePerformanceBar); ## Shortcut customization `keybindings.js` stores keyboard shortcut customizations as a JSON string in -`localStorage`. When `keybindings.js` is first imported, it fetches any -customizations from `localStorage` and merges these customizations into the -default set of keybindings. There is no UI to edit these customizations. +`localStorage`. When `keysFor` is called, it uses the provided command object's +`id` to lookup any customizations found in `localStorage` and returns the custom +keybindings, or the default keybindings if the command has not been customized. +There is no UI to edit these customizations. ## Adding new shortcuts @@ -44,27 +45,33 @@ developers are encouraged to build _lots_ of keyboard shortcuts into GitLab. Shortcuts that are less likely to be used should be [disabled](#disabling-shortcuts) by default. -To add a new shortcut, define and export a new command string in +To add a new shortcut, define and export a new command object in `keybindings.js`: ```javascript -export const MAKE_COFFEE = 'foodAndBeverage.makeCoffee'; +export const MAKE_COFFEE = { + id: 'foodAndBeverage.makeCoffee', + description: s__('KeyboardShortcuts|Make coffee'), + defaultKeys: ['mod+shift+c'], +}; ``` -Next, add a new command definition under the appropriate group in the -`keybindingGroups` array: +Next, add a new command to the appropriate keybinding group object: ```javascript -{ - description: s__('KeyboardShortcuts|Make coffee'), - command: MAKE_COFFEE, - defaultKeys: ['mod+shift+c'], - customKeys: customizations[MAKE_COFFEE], +const COFFEE_GROUP = { + id: 'foodAndBeverage', + name: s__('KeyboardShortcuts|Food and Beverage'), + keybindings: [ + MAKE_ESPRESSO, + MAKE_LATTE, + MAKE_COFFEE + ]; } ``` Finally, in the application code, import the `keysFor` function and the new -command and bind the shortcut to the handler using Mousetrap: +command object and bind the shortcut to the handler using Mousetrap: ```javascript import { keysFor, MAKE_COFFEE } from '~/behaviors/shortcuts/keybindings' @@ -81,16 +88,34 @@ shortcut to an empty array `[]`. For example, to introduce a new shortcut that is disabled by default, a command can be defined like this: ```javascript -export const MAKE_MOCHA = 'foodAndBeverage.makeMocha'; - -{ +export const MAKE_MOCHA = { + id: 'foodAndBeverage.makeMocha', description: s__('KeyboardShortcuts|Make a mocha'), - command: MAKE_MOCHA, defaultKeys: [], - customKeys: customizations[MAKE_MOCHA], -} +}; ``` +## Making shortcuts non-customizable + +Occasionally, it's important that a keyboard shortcut _not_ be customizable +(although this should be a rare occurrence). + +In this case, a shortcut can be defined with `customizable: false`, which +disables customization of the keybinding: + +```javascript +export const MAKE_AMERICANO = { + id: 'foodAndBeverage.makeAmericano', + description: s__('KeyboardShortcuts|Make an Americano'), + defaultKeys: ['mod+shift+a'], + + // this disables customization of this shortcut + customizable: false +}; +``` + +This shortcut will always be bound to its `defaultKeys`. + ## Make cross-platform shortcuts It's difficult to make shortcuts that work well in all platforms and browsers. diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 8d5042e1036..c42e7b4e6d1 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -17544,6 +17544,9 @@ msgstr "" msgid "KeyboardKey|Ctrl+" msgstr "" +msgid "KeyboardShortcuts|Commit (when editing commit message)" +msgstr "" + msgid "KeyboardShortcuts|Global Shortcuts" msgstr "" @@ -17553,6 +17556,9 @@ msgstr "" msgid "KeyboardShortcuts|Toggle the Performance Bar" msgstr "" +msgid "KeyboardShortcuts|Web IDE" +msgstr "" + msgid "Keys" msgstr "" diff --git a/spec/frontend/behaviors/shortcuts/keybindings_spec.js b/spec/frontend/behaviors/shortcuts/keybindings_spec.js index d05b3fbdce2..53ce06e78c6 100644 --- a/spec/frontend/behaviors/shortcuts/keybindings_spec.js +++ b/spec/frontend/behaviors/shortcuts/keybindings_spec.js @@ -1,33 +1,53 @@ +import { flatten } from 'lodash'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; +import { + keysFor, + getCustomizations, + keybindingGroups, + TOGGLE_PERFORMANCE_BAR, + LOCAL_STORAGE_KEY, + WEB_IDE_COMMIT, +} from '~/behaviors/shortcuts/keybindings'; -describe('~/behaviors/shortcuts/keybindings.js', () => { - let keysFor; - let TOGGLE_PERFORMANCE_BAR; - let LOCAL_STORAGE_KEY; - +describe('~/behaviors/shortcuts/keybindings', () => { beforeAll(() => { useLocalStorageSpy(); }); - const setupCustomizations = async (customizationsAsString) => { + const setupCustomizations = (customizationsAsString) => { localStorage.clear(); if (customizationsAsString) { localStorage.setItem(LOCAL_STORAGE_KEY, customizationsAsString); } - jest.resetModules(); - ({ keysFor, TOGGLE_PERFORMANCE_BAR, LOCAL_STORAGE_KEY } = await import( - '~/behaviors/shortcuts/keybindings' - )); + getCustomizations.cache.clear(); }; - describe('when a command has not been customized', () => { - beforeEach(async () => { - await setupCustomizations('{}'); + describe('keybinding definition errors', () => { + beforeEach(() => { + setupCustomizations(); }); - it('returns the default keybinding for the command', () => { + it('has no duplicate group IDs', () => { + const allGroupIds = keybindingGroups.map((group) => group.id); + expect(allGroupIds).toHaveLength(new Set(allGroupIds).size); + }); + + it('has no duplicate commands IDs', () => { + const allCommandIds = flatten( + keybindingGroups.map((group) => group.keybindings.map((kb) => kb.id)), + ); + expect(allCommandIds).toHaveLength(new Set(allCommandIds).size); + }); + }); + + describe('when a command has not been customized', () => { + beforeEach(() => { + setupCustomizations('{}'); + }); + + it('returns the default keybindings for the command', () => { expect(keysFor(TOGGLE_PERFORMANCE_BAR)).toEqual(['p b']); }); }); @@ -35,18 +55,30 @@ describe('~/behaviors/shortcuts/keybindings.js', () => { describe('when a command has been customized', () => { const customization = ['p b a r']; - beforeEach(async () => { - await setupCustomizations(JSON.stringify({ [TOGGLE_PERFORMANCE_BAR]: customization })); + beforeEach(() => { + setupCustomizations(JSON.stringify({ [TOGGLE_PERFORMANCE_BAR.id]: customization })); }); - it('returns the default keybinding for the command', () => { + it('returns the custom keybindings for the command', () => { expect(keysFor(TOGGLE_PERFORMANCE_BAR)).toEqual(customization); }); }); + describe('when a command is marked as non-customizable', () => { + const customization = ['mod+shift+c']; + + beforeEach(() => { + setupCustomizations(JSON.stringify({ [WEB_IDE_COMMIT.id]: customization })); + }); + + it('returns the default keybinding for the command', () => { + expect(keysFor(WEB_IDE_COMMIT)).toEqual(['mod+enter']); + }); + }); + describe("when the localStorage entry isn't valid JSON", () => { - beforeEach(async () => { - await setupCustomizations('{'); + beforeEach(() => { + setupCustomizations('{'); }); it('returns the default keybinding for the command', () => { @@ -55,8 +87,8 @@ describe('~/behaviors/shortcuts/keybindings.js', () => { }); describe(`when localStorage doesn't contain the ${LOCAL_STORAGE_KEY} key`, () => { - beforeEach(async () => { - await setupCustomizations(); + beforeEach(() => { + setupCustomizations(); }); it('returns the default keybinding for the command', () => {