diff options
Diffstat (limited to 'app/assets/javascripts/profile/preferences')
5 files changed, 392 insertions, 38 deletions
diff --git a/app/assets/javascripts/profile/preferences/components/diffs_colors.vue b/app/assets/javascripts/profile/preferences/components/diffs_colors.vue new file mode 100644 index 00000000000..1992819ab82 --- /dev/null +++ b/app/assets/javascripts/profile/preferences/components/diffs_colors.vue @@ -0,0 +1,107 @@ +<script> +import { validateHexColor, hexToRgb } from '~/lib/utils/color_utils'; +import { s__ } from '~/locale'; +import { getCssVariable } from '~/lib/utils/css_utils'; +import ColorPicker from '~/vue_shared/components/color_picker/color_picker.vue'; +import DiffsColorsPreview from './diffs_colors_preview.vue'; + +export default { + components: { + ColorPicker, + DiffsColorsPreview, + }, + inject: ['deletion', 'addition'], + data() { + return { + deletionColor: this.deletion || '', + additionColor: this.addition || '', + defaultDeletionColor: getCssVariable('--default-diff-color-deletion'), + defaultAdditionColor: getCssVariable('--default-diff-color-addition'), + }; + }, + computed: { + suggestedColors() { + const colors = { + '#d99530': s__('SuggestedColors|Orange'), + '#1f75cb': s__('SuggestedColors|Blue'), + }; + if (this.isValidColor(this.deletion)) { + colors[this.deletion] = s__('SuggestedColors|Current removal color'); + } + if (this.isValidColor(this.addition)) { + colors[this.addition] = s__('SuggestedColors|Current addition color'); + } + if (this.isValidColor(this.defaultDeletionColor)) { + colors[this.defaultDeletionColor] = s__('SuggestedColors|Default removal color'); + } + if (this.isValidColor(this.defaultAdditionColor)) { + colors[this.defaultAdditionColor] = s__('SuggestedColors|Default addition color'); + } + return colors; + }, + previewClasses() { + return { + 'diff-custom-addition-color': this.isValidColor(this.additionColor), + 'diff-custom-deletion-color': this.isValidColor(this.deletionColor), + }; + }, + previewStyle() { + let style = {}; + if (this.isValidColor(this.deletionColor)) { + const colorRgb = hexToRgb(this.deletionColor).join(); + style = { + ...style, + '--diff-deletion-color': `rgba(${colorRgb},0.2)`, + }; + } + if (this.isValidColor(this.additionColor)) { + const colorRgb = hexToRgb(this.additionColor).join(); + style = { + ...style, + '--diff-addition-color': `rgba(${colorRgb},0.2)`, + }; + } + return style; + }, + }, + methods: { + isValidColor(color) { + return validateHexColor(color); + }, + }, + i18n: { + colorDeletionInputLabel: s__('Preferences|Color for removed lines'), + colorAdditionInputLabel: s__('Preferences|Color for added lines'), + previewLabel: s__('Preferences|Preview'), + }, +}; +</script> +<template> + <div :style="previewStyle" :class="previewClasses"> + <diffs-colors-preview /> + <color-picker + v-model="deletionColor" + :label="$options.i18n.colorDeletionInputLabel" + :state="isValidColor(deletionColor)" + :suggested-colors="suggestedColors" + /> + <input + id="user_diffs_deletion_color" + v-model="deletionColor" + name="user[diffs_deletion_color]" + type="hidden" + /> + <color-picker + v-model="additionColor" + :label="$options.i18n.colorAdditionInputLabel" + :state="isValidColor(additionColor)" + :suggested-colors="suggestedColors" + /> + <input + id="user_diffs_addition_color" + v-model="additionColor" + name="user[diffs_addition_color]" + type="hidden" + /> + </div> +</template> diff --git a/app/assets/javascripts/profile/preferences/components/diffs_colors_preview.vue b/app/assets/javascripts/profile/preferences/components/diffs_colors_preview.vue new file mode 100644 index 00000000000..74dd2d5628a --- /dev/null +++ b/app/assets/javascripts/profile/preferences/components/diffs_colors_preview.vue @@ -0,0 +1,231 @@ +<script> +import { s__ } from '~/locale'; + +export default { + computed: { + themeClass() { + return window.gon?.user_color_scheme; + }, + }, + i18n: { + previewLabel: s__('Preferences|Preview'), + }, +}; +</script> +<template> + <div class="form-group"> + <label>{{ $options.i18n.previewLabel }}</label> + <!-- eslint-disable @gitlab/vue-require-i18n-strings --> + <table :class="themeClass" class="code"> + <tbody> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="1"></a> + </td> + <td class="line_content parallel left-side old"> + <span + ><span class="c1"># <span class="idiff deletion">Removed</span> content</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="1"></a> + </td> + <td class="line_content parallel right-side new"> + <span + ><span class="c1"># <span class="idiff addition">Added</span> content</span></span + > + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="2"></a> + </td> + <td class="line_content parallel left-side old"> + <span><span class="n">v</span> <span class="o">=</span> <span class="mi">1</span></span> + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="2"></a> + </td> + <td class="line_content parallel right-side new"> + <span><span class="n">v</span> <span class="o">=</span> <span class="mi">1</span></span> + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="3"></a> + </td> + <td class="line_content parallel left-side old"> + <span + ><span class="n">s</span> <span class="o">=</span> + <span class="s">"string"</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="3"></a> + </td> + <td class="line_content parallel right-side new"> + <span + ><span class="n">s</span> <span class="o">=</span> + <span class="s">"string"</span></span + > + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="4"></a> + </td> + <td class="line_content parallel left-side old"><span></span></td> + <td class="new_line diff-line-num new"> + <a data-linenumber="4"></a> + </td> + <td class="line_content parallel right-side new"><span></span></td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="5"></a> + </td> + <td class="line_content parallel left-side old"> + <span + ><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> + <span class="nb">range</span><span class="p">(</span><span class="o">-</span + ><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span + ><span class="p">):</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="5"></a> + </td> + <td class="line_content parallel right-side new"> + <span + ><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> + <span class="nb">range</span><span class="p">(</span><span class="o">-</span + ><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span + ><span class="p">):</span></span + > + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="6"></a> + </td> + <td class="line_content parallel left-side old"> + <span> + <span>{{ ' ' }}</span> + <span class="k">print</span><span class="p">(</span><span class="n">i</span> + <span class="o">+</span> <span class="mi">1</span><span class="p">)</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="6"></a> + </td> + <td class="line_content parallel right-side new"> + <span> + <span>{{ ' ' }}</span> + <span class="k">print</span><span class="p">(</span><span class="n">i</span> + <span class="o">+</span> <span class="mi">1</span><span class="p">)</span></span + > + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="7"></a> + </td> + <td class="line_content parallel left-side old"><span></span></td> + <td class="new_line diff-line-num new"> + <a data-linenumber="7"></a> + </td> + <td class="line_content parallel right-side new"><span></span></td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="8"></a> + </td> + <td class="line_content parallel left-side old"> + <span + ><span class="k">class</span> <span class="nc">LinkedList</span + ><span class="p">(</span><span class="nb">object</span><span class="p">):</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="8"></a> + </td> + <td class="line_content parallel right-side new"> + <span + ><span class="k">class</span> <span class="nc">LinkedList</span + ><span class="p">(</span><span class="nb">object</span><span class="p">):</span></span + > + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="9"></a> + </td> + <td class="line_content parallel left-side old"> + <span> + <span>{{ ' ' }}</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span + ><span class="bp">self</span><span class="p">,</span> <span class="n">x</span + ><span class="p">):</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="9"></a> + </td> + <td class="line_content parallel right-side new"> + <span> + <span>{{ ' ' }}</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span + ><span class="bp">self</span><span class="p">,</span> <span class="n">x</span + ><span class="p">):</span></span + > + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="10"></a> + </td> + <td class="line_content parallel left-side old"> + <span> + <span>{{ ' ' }}</span> + <span class="bp">self</span><span class="p">.</span><span class="n">val</span> + <span class="o">=</span> <span class="n">x</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="10"></a> + </td> + <td class="line_content parallel right-side new"> + <span> + <span>{{ ' ' }}</span> + <span class="bp">self</span><span class="p">.</span><span class="n">val</span> + <span class="o">=</span> <span class="n">x</span></span + > + </td> + </tr> + <tr class="line_holder parallel"> + <td class="old_line diff-line-num old"> + <a data-linenumber="11"></a> + </td> + <td class="line_content parallel left-side old"> + <span> + <span>{{ ' ' }}</span> + <span class="bp">self</span><span class="p">.</span><span class="nb">next</span> + <span class="o">=</span> <span class="bp">None</span></span + > + </td> + <td class="new_line diff-line-num new"> + <a data-linenumber="11"></a> + </td> + <td class="line_content parallel right-side new"> + <span> + <span>{{ ' ' }}</span> + <span class="bp">self</span><span class="p">.</span><span class="nb">next</span> + <span class="o">=</span> <span class="bp">None</span></span + > + </td> + </tr> + </tbody> + </table> + <!-- eslint-enable @gitlab/vue-require-i18n-strings --> + </div> +</template> diff --git a/app/assets/javascripts/profile/preferences/components/integration_view.vue b/app/assets/javascripts/profile/preferences/components/integration_view.vue index c2952629a5d..9924f248b89 100644 --- a/app/assets/javascripts/profile/preferences/components/integration_view.vue +++ b/app/assets/javascripts/profile/preferences/components/integration_view.vue @@ -1,13 +1,14 @@ <script> -import { GlFormText, GlIcon, GlLink } from '@gitlab/ui'; +import { GlIcon, GlLink, GlFormGroup, GlFormCheckbox } from '@gitlab/ui'; import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue'; export default { name: 'IntegrationView', components: { - GlFormText, GlIcon, GlLink, + GlFormGroup, + GlFormCheckbox, IntegrationHelpText, }, inject: ['userFields'], @@ -31,7 +32,7 @@ export default { }, data() { return { - isEnabled: this.userFields[this.config.formName], + isEnabled: this.userFields[this.config.formName] ? '1' : '0', }; }, computed: { @@ -46,36 +47,25 @@ export default { </script> <template> - <div> - <label class="label-bold"> + <gl-form-group> + <template #label> {{ config.title }} - </label> - <gl-link class="has-tooltip" title="More information" :href="helpLink"> - <gl-icon name="question-o" class="vertical-align-middle" /> - </gl-link> - <div class="form-group form-check" data-testid="profile-preferences-integration-form-group"> - <!-- Necessary for Rails to receive the value when not checked --> - <input - :name="formName" - type="hidden" - value="0" - data-testid="profile-preferences-integration-hidden-field" - /> - <input - :id="formId" - v-model="isEnabled" - type="checkbox" - class="form-check-input" - :name="formName" - value="1" - data-testid="profile-preferences-integration-checkbox" - /> - <label class="form-check-label" :for="formId"> - {{ config.label }} - </label> - <gl-form-text tag="div"> + <gl-link class="has-tooltip" title="More information" :href="helpLink"> + <gl-icon name="question-o" class="vertical-align-middle" /> + </gl-link> + </template> + <!-- Necessary for Rails to receive the value when not checked --> + <input + :name="formName" + type="hidden" + value="0" + data-testid="profile-preferences-integration-hidden-field" + /> + <gl-form-checkbox :id="formId" :checked="isEnabled" :name="formName" value="1" + >{{ config.label }} + <template #help> <integration-help-text :message="message" :message-url="messageUrl" /> - </gl-form-text> - </div> - </div> + </template> + </gl-form-checkbox> + </gl-form-group> </template> diff --git a/app/assets/javascripts/profile/preferences/components/profile_preferences.vue b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue index 757a66ef148..7542f81a361 100644 --- a/app/assets/javascripts/profile/preferences/components/profile_preferences.vue +++ b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue @@ -45,7 +45,7 @@ export default { return { isSubmitEnabled: true, darkModeOnCreate: null, - darkModeOnSubmit: null, + schemeOnCreate: null, }; }, computed: { @@ -61,6 +61,7 @@ export default { this.formEl.addEventListener('ajax:success', this.handleSuccess); this.formEl.addEventListener('ajax:error', this.handleError); this.darkModeOnCreate = this.darkModeSelected(); + this.schemeOnCreate = this.getSelectedScheme(); }, beforeDestroy() { this.formEl.removeEventListener('ajax:beforeSend', this.handleLoading); @@ -76,15 +77,19 @@ export default { const themeId = new FormData(this.formEl).get('user[theme_id]'); return this.applicationThemes[themeId] ?? null; }, + getSelectedScheme() { + return new FormData(this.formEl).get('user[color_scheme_id]'); + }, handleLoading() { this.isSubmitEnabled = false; - this.darkModeOnSubmit = this.darkModeSelected(); }, handleSuccess(customEvent) { // Reload the page if the theme has changed from light to dark mode or vice versa - // to correctly load all required styles. - const modeChanged = this.darkModeOnCreate ? !this.darkModeOnSubmit : this.darkModeOnSubmit; - if (modeChanged) { + // or if color scheme has changed to correctly load all required styles. + if ( + this.darkModeOnCreate !== this.darkModeSelected() || + this.schemeOnCreate !== this.getSelectedScheme() + ) { window.location.reload(); return; } diff --git a/app/assets/javascripts/profile/preferences/profile_preferences_diffs_colors.js b/app/assets/javascripts/profile/preferences/profile_preferences_diffs_colors.js new file mode 100644 index 00000000000..1b200187610 --- /dev/null +++ b/app/assets/javascripts/profile/preferences/profile_preferences_diffs_colors.js @@ -0,0 +1,21 @@ +import Vue from 'vue'; +import DiffsColors from './components/diffs_colors.vue'; + +export default () => { + const el = document.querySelector('#js-profile-preferences-diffs-colors-app'); + + if (!el) return false; + + const { deletion, addition } = el.dataset; + + return new Vue({ + el, + provide: { + deletion, + addition, + }, + render(createElement) { + return createElement(DiffsColors); + }, + }); +}; |