Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-16 21:09:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-16 21:09:42 +0300
commitc44eade0d7b09c9d80c42aba6d1974ce9cd3146b (patch)
treeda0710de0a519f225755737cf5ffd93c75d1da8f /app
parent0c87da93750c6428328a3e3cd2ebd0882f6294e3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/toggle_replies_widget.vue10
-rw-r--r--app/assets/javascripts/lib/utils/secret_detection.js2
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js2
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/geo_json/constants.js24
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/geo_json/geo_json_viewer.vue32
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/geo_json/utils.js47
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/index.js1
-rw-r--r--app/assets/stylesheets/page_bundles/design_management.scss10
-rw-r--r--app/models/blob.rb1
-rw-r--r--app/models/blob_viewer/geo_json.rb12
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/user.rb16
-rw-r--r--app/views/projects/blob/_blob.html.haml3
14 files changed, 148 insertions, 16 deletions
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_note.vue b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
index 46ae87a36e4..0eac2cad68d 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
@@ -152,7 +152,7 @@ export default {
<span class="note-headline-light note-headline-meta">
<span class="system-note-message"> <slot></slot> </span>
<gl-link
- class="note-timestamp system-note-separator gl-display-block gl-mb-2"
+ class="note-timestamp system-note-separator gl-display-block gl-mb-2 gl-font-sm"
:href="`#note_${noteAnchorId}`"
>
<time-ago-tooltip :time="note.createdAt" tooltip-placement="bottom" />
diff --git a/app/assets/javascripts/design_management/components/design_notes/toggle_replies_widget.vue b/app/assets/javascripts/design_management/components/design_notes/toggle_replies_widget.vue
index 2e366282de3..189ddda525b 100644
--- a/app/assets/javascripts/design_management/components/design_notes/toggle_replies_widget.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/toggle_replies_widget.vue
@@ -39,31 +39,31 @@ export default {
<template>
<li
- class="toggle-comments gl-bg-gray-50 gl-display-flex gl-align-items-center gl-py-3"
+ class="toggle-comments gl-bg-gray-50 gl-display-flex gl-align-items-center gl-py-3 gl-min-h-8"
:class="{ expanded: !collapsed }"
data-testid="toggle-comments-wrapper"
>
<gl-icon :name="iconName" class="gl-ml-3" @click.stop="$emit('toggle')" />
<gl-button
variant="link"
- class="toggle-comments-button gl-ml-2 gl-mr-2"
+ class="toggle-comments-button gl-ml-2 gl-mr-2 gl-font-sm!"
@click.stop="$emit('toggle')"
>
{{ toggleText }}
</gl-button>
<template v-if="collapsed">
- <span class="gl-text-gray-500">{{ __('Last reply by') }}</span>
+ <span class="gl-text-gray-500 gl-font-sm">{{ __('Last reply by') }}</span>
<gl-link
:href="lastReply.author.webUrl"
target="_blank"
- class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-ml-2 gl-mr-2"
+ class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-font-sm gl-ml-2 gl-mr-2"
>
{{ lastReply.author.name }}
</gl-link>
<time-ago-tooltip
:time="lastReply.createdAt"
tooltip-placement="bottom"
- class="gl-text-gray-500"
+ class="gl-text-gray-500 gl-font-sm"
/>
</template>
</li>
diff --git a/app/assets/javascripts/lib/utils/secret_detection.js b/app/assets/javascripts/lib/utils/secret_detection.js
index eadd8ec1538..8e673855631 100644
--- a/app/assets/javascripts/lib/utils/secret_detection.js
+++ b/app/assets/javascripts/lib/utils/secret_detection.js
@@ -22,7 +22,7 @@ export const containsSensitiveToken = (message) => {
{
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'Feed Token',
- regex: 'feed_token=[0-9a-zA-Z_-]{20}',
+ regex: 'feed_token=((glft-)?[0-9a-zA-Z_-]{20}|glft-[a-h0-9]+-[0-9]+_)',
},
];
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index 2c93b3b636a..e7f2662ae09 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -11,7 +11,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-eoa-bronze-plan-banner',
'.js-security-newsletter-callout',
'.js-approaching-seat-count-threshold',
- '.js-storage-enforcement-banner',
+ '.js-storage-pre-enforcement-alert',
'.js-user-over-limit-free-plan-alert',
'.js-minute-limit-banner',
'.js-submit-license-usage-data-banner',
diff --git a/app/assets/javascripts/repository/components/blob_viewers/geo_json/constants.js b/app/assets/javascripts/repository/components/blob_viewers/geo_json/constants.js
new file mode 100644
index 00000000000..fd4d111b4b0
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_viewers/geo_json/constants.js
@@ -0,0 +1,24 @@
+import iconUrl from 'leaflet/dist/images/marker-icon.png';
+import iconRetinaUrl from 'leaflet/dist/images/marker-icon-2x.png';
+import shadowUrl from 'leaflet/dist/images/marker-shadow.png';
+import { __ } from '~/locale';
+
+export const RENDER_ERROR_MSG = __(
+ 'The map can not be displayed because there was an error loading the GeoJSON file.',
+);
+
+export const OPEN_STREET_TILE_URL = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
+export const ICON_CONFIG = { iconUrl, iconRetinaUrl, shadowUrl };
+export const MAP_ATTRIBUTION = __('Map data from');
+export const OPEN_STREET_COPYRIGHT_LINK =
+ '<a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a>';
+
+export const POPUP_CONTENT_TEMPLATE = `
+<div class="gl-pt-4">
+ <% eachFunction(popupProperties, function(value, label) { %>
+ <div>
+ <strong><%- label %>:</strong> <span><%- value %></span>
+ </div>
+ <% }); %>
+</div>
+`;
diff --git a/app/assets/javascripts/repository/components/blob_viewers/geo_json/geo_json_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/geo_json/geo_json_viewer.vue
new file mode 100644
index 00000000000..1c9fccc2c19
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_viewers/geo_json/geo_json_viewer.vue
@@ -0,0 +1,32 @@
+<script>
+import { createAlert } from '~/alert';
+import { RENDER_ERROR_MSG } from './constants';
+import { initLeafletMap } from './utils';
+
+export default {
+ props: {
+ blob: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ hasError: false,
+ loading: true,
+ };
+ },
+ mounted() {
+ try {
+ initLeafletMap(this.$refs.map, JSON.parse(this.blob.rawTextBlob));
+ } catch (error) {
+ createAlert({ message: RENDER_ERROR_MSG });
+ this.hasError = true;
+ }
+ },
+};
+</script>
+
+<template>
+ <div v-if="!hasError" ref="map" class="gl-h-100vh gl-z-index-0" data-testid="map"></div>
+</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/geo_json/utils.js b/app/assets/javascripts/repository/components/blob_viewers/geo_json/utils.js
new file mode 100644
index 00000000000..615f7fd2b47
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_viewers/geo_json/utils.js
@@ -0,0 +1,47 @@
+import { map, tileLayer, geoJson, featureGroup, Icon } from 'leaflet';
+import { template, each } from 'lodash';
+import {
+ OPEN_STREET_TILE_URL,
+ MAP_ATTRIBUTION,
+ OPEN_STREET_COPYRIGHT_LINK,
+ ICON_CONFIG,
+ POPUP_CONTENT_TEMPLATE,
+} from './constants';
+
+const generateOpenStreetMapTiles = () => {
+ const attribution = `${MAP_ATTRIBUTION} ${OPEN_STREET_COPYRIGHT_LINK}`;
+ return tileLayer(OPEN_STREET_TILE_URL, { attribution });
+};
+
+export const popupContent = (popupProperties) => {
+ return template(POPUP_CONTENT_TEMPLATE)({
+ eachFunction: each,
+ popupProperties,
+ });
+};
+
+const loadGeoJsonGroupAndBounds = (geoJsonData) => {
+ const layers = [];
+ const geoJsonGroup = geoJson(geoJsonData, {
+ onEachFeature: (feature, layer) => {
+ layers.push(layer);
+ if (feature.properties) {
+ layer.bindPopup(popupContent(feature.properties));
+ }
+ },
+ });
+
+ return { geoJsonGroup, bounds: featureGroup(layers).getBounds() };
+};
+
+export const initLeafletMap = (el, geoJsonData) => {
+ if (!el || !geoJsonData) return;
+
+ import('leaflet/dist/leaflet.css');
+ Icon.Default.mergeOptions(ICON_CONFIG);
+ const leafletMap = map(el, { layers: [generateOpenStreetMapTiles()] });
+ const { bounds, geoJsonGroup } = loadGeoJsonGroupAndBounds(geoJsonData);
+
+ geoJsonGroup.addTo(leafletMap);
+ leafletMap.fitBounds(bounds);
+};
diff --git a/app/assets/javascripts/repository/components/blob_viewers/index.js b/app/assets/javascripts/repository/components/blob_viewers/index.js
index a480710f8ac..b749702972f 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/index.js
+++ b/app/assets/javascripts/repository/components/blob_viewers/index.js
@@ -12,6 +12,7 @@ const viewers = {
sketch: () => import('./sketch_viewer.vue'),
notebook: () => import('./notebook_viewer.vue'),
openapi: () => import('./openapi_viewer.vue'),
+ geo_json: () => import('./geo_json/geo_json_viewer.vue'),
};
export const loadViewer = (type, isUsingLfs) => {
diff --git a/app/assets/stylesheets/page_bundles/design_management.scss b/app/assets/stylesheets/page_bundles/design_management.scss
index 15363e78eb3..c19561a5e5e 100644
--- a/app/assets/stylesheets/page_bundles/design_management.scss
+++ b/app/assets/stylesheets/page_bundles/design_management.scss
@@ -138,7 +138,7 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
}
.design-note-pin {
- margin-left: $gl-padding;
+ margin-left: 9px;
}
.design-discussion {
@@ -148,13 +148,13 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
content: '';
border-left: 1px solid var(--gray-100, $gray-100);
position: absolute;
- left: 28px;
+ left: 22px;
top: -17px;
height: 17px;
}
.design-note {
- padding: $gl-padding;
+ padding: $gl-padding-8;
list-style: none;
transition: background $gl-transition-duration-medium $general-hover-transition-curve;
border-top-left-radius: $border-radius-default; // same border radius used by .bordered-box
@@ -170,7 +170,9 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
}
.reply-wrapper {
- padding: $gl-padding;
+ padding: $gl-padding-8 $gl-padding-8 $gl-padding-4;
+ background: $gray-10;
+ border-radius: 0 0 $border-radius-default $border-radius-default;
}
}
diff --git a/app/models/blob.rb b/app/models/blob.rb
index 7c88833b19d..bb8c9345573 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -33,6 +33,7 @@ class Blob < SimpleDelegator
BlobViewer::Notebook,
BlobViewer::SVG,
BlobViewer::OpenApi,
+ BlobViewer::GeoJson,
BlobViewer::Image,
BlobViewer::Sketch,
diff --git a/app/models/blob_viewer/geo_json.rb b/app/models/blob_viewer/geo_json.rb
new file mode 100644
index 00000000000..01dcf7707eb
--- /dev/null
+++ b/app/models/blob_viewer/geo_json.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module BlobViewer
+ class GeoJson < Base
+ include Rich
+ include ClientSide
+
+ self.binary = false
+ self.extensions = %w[geojson]
+ self.partial_name = 'geo_json'
+ end
+end
diff --git a/app/models/group.rb b/app/models/group.rb
index 13f622c7839..85971c48567 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -38,7 +38,7 @@ class Group < Namespace
has_many :users, through: :group_members
has_many :owners,
-> { where(members: { access_level: Gitlab::Access::OWNER }) },
- through: :group_members,
+ through: :all_group_members,
source: :user
has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' # rubocop:disable Cop/ActiveRecordDependent
diff --git a/app/models/user.rb b/app/models/user.rb
index 3ac58b75879..96cdbb192bc 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -57,10 +57,14 @@ class User < ApplicationRecord
FORBIDDEN_SEARCH_STATES = %w(blocked banned ldap_blocked).freeze
+ INCOMING_MAIL_TOKEN_PREFIX = 'glimt-'
+ FEED_TOKEN_PREFIX = 'glft-'
+
columns_changing_default :notified_of_own_activity
- add_authentication_token_field :incoming_email_token, token_generator: -> { SecureRandom.hex.to_i(16).to_s(36) }
- add_authentication_token_field :feed_token
+ # lib/tasks/tokens.rake needs to be updated when changing mail and feed tokens
+ add_authentication_token_field :incoming_email_token, token_generator: -> { self.generate_incoming_mail_token }
+ add_authentication_token_field :feed_token, format_with_prefix: :prefix_for_feed_token
add_authentication_token_field :static_object_token, encrypted: :optional
attribute :admin, default: false
@@ -968,6 +972,10 @@ class User < ApplicationRecord
def get_ids_by_ids_or_usernames(ids, usernames)
by_ids_or_usernames(ids, usernames).pluck(:id)
end
+
+ def generate_incoming_mail_token
+ "#{INCOMING_MAIL_TOKEN_PREFIX}#{SecureRandom.hex.to_i(16).to_s(36)}"
+ end
end
#
@@ -2596,6 +2604,10 @@ class User < ApplicationRecord
Ci::NamespaceMirror.contains_traversal_ids(traversal_ids)
end
+
+ def prefix_for_feed_token
+ FEED_TOKEN_PREFIX
+ end
end
User.prepend_mod_with('User')
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 2aed0a92407..e5566882371 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -2,7 +2,8 @@
- project = @project.present(current_user: current_user)
- ref = local_assigns[:ref] || @ref
- expanded = params[:expanded].present?
-- if blob.rich_viewer
+-# If the blob has a RichViewer we preload the content except for GeoJSON since it is handled by Vue
+- if blob.rich_viewer && blob.extension != 'geojson'
- add_page_startup_api_call local_assigns.fetch(:viewer_url) { url_for(safe_params.merge(viewer: blob.rich_viewer.type, format: :json)) }
.info-well.d-none.d-sm-block