summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue10
-rw-r--r--app/assets/javascripts/groups/components/item_actions.vue20
-rw-r--r--app/assets/javascripts/groups/components/item_caret.vue15
-rw-r--r--app/assets/javascripts/groups/components/item_stats.vue96
-rw-r--r--app/assets/javascripts/groups/components/item_stats_value.vue68
-rw-r--r--app/assets/javascripts/groups/components/item_type_icon.vue13
-rw-r--r--app/assets/javascripts/groups/constants.js6
-rw-r--r--app/assets/javascripts/groups/store/groups_store.js1
-rw-r--r--app/assets/javascripts/ide/components/ide_context_bar.vue33
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue33
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue6
-rw-r--r--app/assets/javascripts/ide/stores/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js5
-rw-r--r--app/assets/javascripts/ide/stores/state.js1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js46
-rw-r--r--app/assets/javascripts/vue_shared/components/panel_resizer.vue91
-rw-r--r--app/assets/stylesheets/framework/avatar.scss2
-rw-r--r--app/assets/stylesheets/framework/lists.scss72
-rw-r--r--app/assets/stylesheets/pages/repo.scss34
-rw-r--r--app/assets/stylesheets/pages/settings.scss4
23 files changed, 443 insertions, 130 deletions
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 6421547bbde..02129d39846 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -77,7 +77,8 @@ export default {
class="group-row"
>
<div
- class="group-row-contents">
+ class="group-row-contents"
+ :class="{ 'project-row-contents': !isGroup }">
<item-actions
v-if="isGroup"
:group="group"
@@ -97,7 +98,7 @@ export default {
/>
</div>
<div
- class="avatar-container s40 hidden-xs"
+ class="avatar-container prepend-top-8 prepend-left-5 s24 hidden-xs"
:class="{ 'content-loading': group.isChildrenLoading }"
>
<a
@@ -106,11 +107,12 @@ export default {
>
<img
v-if="hasAvatar"
- class="avatar s40"
+ class="avatar s24"
:src="group.avatarUrl"
/>
<identicon
v-else
+ size-class="s24"
:entity-id=group.id
:entity-name="group.name"
/>
@@ -123,7 +125,7 @@ export default {
:href="group.relativePath"
:title="group.fullName"
class="no-expand"
- data-placement="top"
+ data-placement="bottom"
>{{
// ending bracket must be by closing tag to prevent
// link hover text-decoration from over-extending
diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue
index 58ba5aff7cf..a685960d862 100644
--- a/app/assets/javascripts/groups/components/item_actions.vue
+++ b/app/assets/javascripts/groups/components/item_actions.vue
@@ -1,14 +1,14 @@
<script>
-import { s__ } from '../../locale';
-import tooltip from '../../vue_shared/directives/tooltip';
-import modal from '../../vue_shared/components/modal.vue';
+import { s__ } from '~/locale';
+import tooltip from '~/vue_shared/directives/tooltip';
+import icon from '~/vue_shared/components/icon.vue';
+import modal from '~/vue_shared/components/modal.vue';
import eventHub from '../event_hub';
import { COMMON_STR } from '../constants';
-import Icon from '../../vue_shared/components/icon.vue';
export default {
components: {
- Icon,
+ icon,
modal,
},
directives: {
@@ -64,10 +64,9 @@ export default {
:title="editBtnTitle"
:aria-label="editBtnTitle"
data-container="body"
+ data-placement="bottom"
class="edit-group btn no-expand">
- <icon
- name="settings">
- </icon>
+ <icon name="settings"/>
</a>
<a
v-tooltip
@@ -77,10 +76,9 @@ export default {
:title="leaveBtnTitle"
:aria-label="leaveBtnTitle"
data-container="body"
+ data-placement="bottom"
class="leave-group btn no-expand">
- <i
- class="fa fa-sign-out"
- aria-hidden="true"/>
+ <icon name="leave"/>
</a>
<modal
v-show="modalStatus"
diff --git a/app/assets/javascripts/groups/components/item_caret.vue b/app/assets/javascripts/groups/components/item_caret.vue
index 959b984816f..9e90fe2b701 100644
--- a/app/assets/javascripts/groups/components/item_caret.vue
+++ b/app/assets/javascripts/groups/components/item_caret.vue
@@ -1,4 +1,6 @@
<script>
+import icon from '~/vue_shared/components/icon.vue';
+
export default {
props: {
isGroupOpen: {
@@ -7,9 +9,12 @@ export default {
default: false,
},
},
+ components: {
+ icon,
+ },
computed: {
iconClass() {
- return this.isGroupOpen ? 'fa-caret-down' : 'fa-caret-right';
+ return this.isGroupOpen ? 'angle-down' : 'angle-right';
},
},
};
@@ -17,9 +22,9 @@ export default {
<template>
<span class="folder-caret">
- <i
- :class="iconClass"
- class="fa"
- aria-hidden="true"/>
+ <icon
+ :size="12"
+ :name="iconClass"
+ />
</span>
</template>
diff --git a/app/assets/javascripts/groups/components/item_stats.vue b/app/assets/javascripts/groups/components/item_stats.vue
index d9bc0588908..bd9a434e255 100644
--- a/app/assets/javascripts/groups/components/item_stats.vue
+++ b/app/assets/javascripts/groups/components/item_stats.vue
@@ -1,15 +1,19 @@
<script>
-import tooltip from '../../vue_shared/directives/tooltip';
+import icon from '~/vue_shared/components/icon.vue';
+import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
ITEM_TYPE,
VISIBILITY_TYPE_ICON,
GROUP_VISIBILITY_TYPE,
- PROJECT_VISIBILITY_TYPE,
+ PROJECT_VISIBILITY_TYPE
} from '../constants';
+import itemStatsValue from './item_stats_value.vue';
export default {
- directives: {
- tooltip,
+ components: {
+ icon,
+ timeAgoTooltip,
+ itemStatsValue,
},
props: {
item: {
@@ -39,65 +43,47 @@ export default {
<template>
<div class="stats">
- <span
- v-tooltip
+ <item-stats-value
v-if="isGroup"
+ css-class="number-subgroups"
+ icon-name="folder"
:title="s__('Subgroups')"
- class="number-subgroups"
- data-placement="top"
- data-container="body">
- <i
- class="fa fa-folder"
- aria-hidden="true"
- />
- {{item.subgroupCount}}
- </span>
- <span
- v-tooltip
+ :value=item.subgroupCount
+ />
+ <item-stats-value
v-if="isGroup"
+ css-class="number-projects"
+ icon-name="bookmark"
:title="s__('Projects')"
- class="number-projects"
- data-placement="top"
- data-container="body">
- <i
- class="fa fa-bookmark"
- aria-hidden="true"
- />
- {{item.projectCount}}
- </span>
- <span
- v-tooltip
+ :value=item.projectCount
+ />
+ <item-stats-value
v-if="isGroup"
+ css-class="number-users"
+ icon-name="users"
:title="s__('Members')"
- class="number-users"
- data-placement="top"
- data-container="body">
- <i
- class="fa fa-users"
- aria-hidden="true"
- />
- {{item.memberCount}}
- </span>
- <span
+ :value=item.memberCount
+ />
+ <item-stats-value
v-if="isProject"
- class="project-stars">
- <i
- class="fa fa-star"
- aria-hidden="true"
- />
- {{item.starCount}}
- </span>
- <span
- v-tooltip
+ css-class="project-stars"
+ icon-name="star"
+ :value=item.starCount
+ />
+ <item-stats-value
+ css-class="item-visibility"
+ tooltip-placement="left"
+ :icon-name="visibilityIcon"
:title="visibilityTooltip"
- data-placement="left"
- data-container="body"
- class="item-visibility">
- <i
- :class="visibilityIcon"
- class="fa"
- aria-hidden="true"
+ />
+ <div
+ class="last-updated"
+ v-if="isProject"
+ >
+ <time-ago-tooltip
+ tooltip-placement="bottom"
+ :time="item.updatedAt"
/>
- </span>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/groups/components/item_stats_value.vue b/app/assets/javascripts/groups/components/item_stats_value.vue
new file mode 100644
index 00000000000..f441cabf6d2
--- /dev/null
+++ b/app/assets/javascripts/groups/components/item_stats_value.vue
@@ -0,0 +1,68 @@
+<script>
+import tooltip from '~/vue_shared/directives/tooltip';
+import icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ cssClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ iconName: {
+ type: String,
+ required: true,
+ },
+ tooltipPlacement: {
+ type: String,
+ required: false,
+ default: 'bottom',
+ },
+ /**
+ * value could either be number or string
+ * as `memberCount` is always passed as string
+ * while `subgroupCount` & `projectCount`
+ * are always number
+ */
+ value: {
+ type: [Number, String],
+ required: false,
+ default: '',
+ },
+ },
+ directives: {
+ tooltip,
+ },
+ components: {
+ icon,
+ },
+ computed: {
+ isValuePresent() {
+ return this.value !== '';
+ },
+ },
+};
+</script>
+
+<template>
+ <span
+ v-tooltip
+ data-container="body"
+ :data-placement="tooltipPlacement"
+ :class="cssClass"
+ :title="title"
+ >
+ <icon :name="iconName"/>
+ <span
+ v-if="isValuePresent"
+ class="stat-value"
+ >
+ {{value}}
+ </span>
+ </span>
+</template>
diff --git a/app/assets/javascripts/groups/components/item_type_icon.vue b/app/assets/javascripts/groups/components/item_type_icon.vue
index c02a8ad6d8c..118d94d4937 100644
--- a/app/assets/javascripts/groups/components/item_type_icon.vue
+++ b/app/assets/javascripts/groups/components/item_type_icon.vue
@@ -1,7 +1,11 @@
<script>
+import icon from '~/vue_shared/components/icon.vue';
import { ITEM_TYPE } from '../constants';
export default {
+ components: {
+ icon,
+ },
props: {
itemType: {
type: String,
@@ -16,9 +20,9 @@ export default {
computed: {
iconClass() {
if (this.itemType === ITEM_TYPE.GROUP) {
- return this.isGroupOpen ? 'fa-folder-open' : 'fa-folder';
+ return this.isGroupOpen ? 'folder-open' : 'folder';
}
- return 'fa-bookmark';
+ return 'bookmark';
},
},
};
@@ -26,9 +30,6 @@ export default {
<template>
<span class="item-type-icon">
- <i
- :class="iconClass"
- class="fa"
- aria-hidden="true"/>
+ <icon :name="iconClass"/>
</span>
</template>
diff --git a/app/assets/javascripts/groups/constants.js b/app/assets/javascripts/groups/constants.js
index 6fde41414b3..b8baed682f5 100644
--- a/app/assets/javascripts/groups/constants.js
+++ b/app/assets/javascripts/groups/constants.js
@@ -29,7 +29,7 @@ export const PROJECT_VISIBILITY_TYPE = {
};
export const VISIBILITY_TYPE_ICON = {
- public: 'fa-globe',
- internal: 'fa-shield',
- private: 'fa-lock',
+ public: 'earth',
+ internal: 'shield',
+ private: 'lock',
};
diff --git a/app/assets/javascripts/groups/store/groups_store.js b/app/assets/javascripts/groups/store/groups_store.js
index a1689f4c5cc..ffc86175548 100644
--- a/app/assets/javascripts/groups/store/groups_store.js
+++ b/app/assets/javascripts/groups/store/groups_store.js
@@ -91,6 +91,7 @@ export default class GroupsStore {
subgroupCount: rawGroupItem.subgroup_count,
memberCount: rawGroupItem.number_users_with_delimiter,
starCount: rawGroupItem.star_count,
+ updatedAt: rawGroupItem.updated_at,
};
}
diff --git a/app/assets/javascripts/ide/components/ide_context_bar.vue b/app/assets/javascripts/ide/components/ide_context_bar.vue
index 5a08718e386..78c01272af6 100644
--- a/app/assets/javascripts/ide/components/ide_context_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_context_bar.vue
@@ -2,11 +2,18 @@
import { mapGetters, mapState, mapActions } from 'vuex';
import repoCommitSection from './repo_commit_section.vue';
import icon from '../../vue_shared/components/icon.vue';
+import panelResizer from '../../vue_shared/components/panel_resizer.vue';
export default {
+ data() {
+ return {
+ width: 290,
+ };
+ },
components: {
repoCommitSection,
icon,
+ panelResizer,
},
computed: {
...mapState([
@@ -18,10 +25,20 @@ export default {
currentIcon() {
return this.rightPanelCollapsed ? 'angle-double-left' : 'angle-double-right';
},
+ maxSize() {
+ return window.innerWidth / 2;
+ },
+ panelStyle() {
+ if (!this.rightPanelCollapsed) {
+ return { width: `${this.width}px` };
+ }
+ return {};
+ },
},
methods: {
...mapActions([
'setPanelCollapsedStatus',
+ 'setResizingStatus',
]),
toggleCollapsed() {
this.setPanelCollapsedStatus({
@@ -29,6 +46,12 @@ export default {
collapsed: !this.rightPanelCollapsed,
});
},
+ resizingStarted() {
+ this.setResizingStatus(true);
+ },
+ resizingEnded() {
+ this.setResizingStatus(false);
+ },
},
};
</script>
@@ -39,6 +62,7 @@ export default {
:class="{
'is-collapsed': rightPanelCollapsed,
}"
+ :style="panelStyle"
>
<div
class="multi-file-commit-panel-section">
@@ -71,5 +95,14 @@ export default {
<repo-commit-section
class=""/>
</div>
+ <panel-resizer
+ :size.sync="width"
+ :enabled="!rightPanelCollapsed"
+ :start-size="290"
+ :min-size="200"
+ :max-size="maxSize"
+ @resize-start="resizingStarted"
+ @resize-end="resizingEnded"
+ side="left"/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 535398d98c2..269f300a04d 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -2,11 +2,18 @@
import { mapState, mapActions } from 'vuex';
import projectTree from './ide_project_tree.vue';
import icon from '../../vue_shared/components/icon.vue';
+import panelResizer from '../../vue_shared/components/panel_resizer.vue';
export default {
+ data() {
+ return {
+ width: 290,
+ };
+ },
components: {
projectTree,
icon,
+ panelResizer,
},
computed: {
...mapState([
@@ -16,10 +23,20 @@ export default {
currentIcon() {
return this.leftPanelCollapsed ? 'angle-double-right' : 'angle-double-left';
},
+ maxSize() {
+ return window.innerWidth / 2;
+ },
+ panelStyle() {
+ if (!this.leftPanelCollapsed) {
+ return { width: `${this.width}px` };
+ }
+ return {};
+ },
},
methods: {
...mapActions([
'setPanelCollapsedStatus',
+ 'setResizingStatus',
]),
toggleCollapsed() {
this.setPanelCollapsedStatus({
@@ -27,6 +44,12 @@ export default {
collapsed: !this.leftPanelCollapsed,
});
},
+ resizingStarted() {
+ this.setResizingStatus(true);
+ },
+ resizingEnded() {
+ this.setResizingStatus(false);
+ },
},
};
</script>
@@ -37,6 +60,7 @@ export default {
:class="{
'is-collapsed': leftPanelCollapsed,
}"
+ :style="panelStyle"
>
<div class="multi-file-commit-panel-inner">
<project-tree
@@ -58,5 +82,14 @@ export default {
class="collapse-text"
>Collapse sidebar</span>
</button>
+ <panel-resizer
+ :size.sync="width"
+ :enabled="!leftPanelCollapsed"
+ :start-size="290"
+ :min-size="200"
+ :max-size="maxSize"
+ @resize-start="resizingStarted"
+ @resize-end="resizingEnded"
+ side="right"/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index 221be4b9074..343fd0a5300 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -90,6 +90,11 @@ export default {
rightPanelCollapsed() {
this.editor.updateDimensions();
},
+ panelResizing(isResizing) {
+ if (isResizing === false) {
+ this.editor.updateDimensions();
+ }
+ },
},
computed: {
...mapGetters([
@@ -99,6 +104,7 @@ export default {
...mapState([
'leftPanelCollapsed',
'rightPanelCollapsed',
+ 'panelResizing',
]),
shouldHideEditor() {
return this.activeFile.binary && !this.activeFile.raw;
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index c01046c8c76..335882bb6d7 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -63,6 +63,10 @@ export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => {
}
};
+export const setResizingStatus = ({ commit }, resizing) => {
+ commit(types.SET_RESIZING_STATUS, resizing);
+};
+
export const checkCommitStatus = ({ state }) =>
service
.getBranchData(state.currentProjectId, state.currentBranchId)
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index 4e3c10972ba..69b218a5e7d 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -5,6 +5,7 @@ export const SET_ROOT = 'SET_ROOT';
export const SET_LAST_COMMIT_DATA = 'SET_LAST_COMMIT_DATA';
export const SET_LEFT_PANEL_COLLAPSED = 'SET_LEFT_PANEL_COLLAPSED';
export const SET_RIGHT_PANEL_COLLAPSED = 'SET_RIGHT_PANEL_COLLAPSED';
+export const SET_RESIZING_STATUS = 'SET_RESIZING_STATUS';
// Project Mutation Types
export const SET_PROJECT = 'SET_PROJECT';
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 2fed9019cb6..03d81be10a1 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -49,6 +49,11 @@ export default {
rightPanelCollapsed: collapsed,
});
},
+ [types.SET_RESIZING_STATUS](state, resizing) {
+ Object.assign(state, {
+ panelResizing: resizing,
+ });
+ },
[types.SET_LAST_COMMIT_DATA](state, { entry, lastCommit }) {
Object.assign(entry.lastCommit, {
id: lastCommit.commit.id,
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
index 539e382830f..61d12096946 100644
--- a/app/assets/javascripts/ide/stores/state.js
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -19,4 +19,5 @@ export default () => ({
projects: {},
leftPanelCollapsed: false,
rightPanelCollapsed: true,
+ panelResizing: false,
});
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
index b25cc3443ef..dd8b2665b1d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
@@ -16,9 +16,9 @@ export default {
<div class="media-body">
<mr-widget-author-and-time
actionText="Closed by"
- :author="mr.closedEvent.author"
- :dateTitle="mr.closedEvent.updatedAt"
- :dateReadable="mr.closedEvent.formattedUpdatedAt"
+ :author="mr.metrics.closedBy"
+ :dateTitle="mr.metrics.closedAt"
+ :dateReadable="mr.metrics.readableClosedAt"
/>
<section class="mr-info-list">
<p>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
index 7c73ebf667d..ba9681680ef 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
@@ -68,9 +68,9 @@ export default {
<div class="space-children">
<mr-widget-author-and-time
actionText="Merged by"
- :author="mr.mergedEvent.author"
- :date-title="mr.mergedEvent.updatedAt"
- :date-readable="mr.mergedEvent.formattedUpdatedAt" />
+ :author="mr.metrics.mergedBy"
+ :date-title="mr.metrics.mergedAt"
+ :date-readable="mr.metrics.readableMergedAt" />
<a
v-if="mr.canRevertInCurrentMR"
v-tooltip
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 93d31a2a684..474c17ec133 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -39,9 +39,8 @@ export default class MergeRequestStore {
}
this.updatedAt = data.updated_at;
- this.mergedEvent = MergeRequestStore.getEventObject(data.merge_event);
- this.closedEvent = MergeRequestStore.getEventObject(data.closed_event);
- this.setToMWPSBy = MergeRequestStore.getAuthorObject({ author: data.merge_user || {} });
+ this.metrics = MergeRequestStore.buildMetrics(data.metrics);
+ this.setToMWPSBy = MergeRequestStore.formatUserObject(data.merge_user || {});
this.mergeUserId = data.merge_user_id;
this.currentUserId = gon.current_user_id;
this.sourceBranchPath = data.source_branch_path;
@@ -125,43 +124,42 @@ export default class MergeRequestStore {
return this.state === stateKey.nothingToMerge;
}
- static getEventObject(event) {
+ static buildMetrics(metrics) {
+ if (!metrics) {
+ return {};
+ }
+
return {
- author: MergeRequestStore.getAuthorObject(event),
- updatedAt: formatDate(MergeRequestStore.getEventUpdatedAtDate(event)),
- formattedUpdatedAt: MergeRequestStore.getEventDate(event),
+ mergedBy: MergeRequestStore.formatUserObject(metrics.merged_by),
+ closedBy: MergeRequestStore.formatUserObject(metrics.closed_by),
+ mergedAt: formatDate(metrics.merged_at),
+ closedAt: formatDate(metrics.closed_at),
+ readableMergedAt: MergeRequestStore.getReadableDate(metrics.merged_at),
+ readableClosedAt: MergeRequestStore.getReadableDate(metrics.closed_at),
};
}
- static getAuthorObject(event) {
- if (!event) {
+ static formatUserObject(user) {
+ if (!user) {
return {};
}
return {
- name: event.author.name || '',
- username: event.author.username || '',
- webUrl: event.author.web_url || '',
- avatarUrl: event.author.avatar_url || '',
+ name: user.name || '',
+ username: user.username || '',
+ webUrl: user.web_url || '',
+ avatarUrl: user.avatar_url || '',
};
}
- static getEventUpdatedAtDate(event) {
- if (!event) {
+ static getReadableDate(date) {
+ if (!date) {
return '';
}
- return event.updated_at;
- }
-
- static getEventDate(event) {
const timeagoInstance = new Timeago();
- if (!event) {
- return '';
- }
-
- return timeagoInstance.format(MergeRequestStore.getEventUpdatedAtDate(event));
+ return timeagoInstance.format(date);
}
}
diff --git a/app/assets/javascripts/vue_shared/components/panel_resizer.vue b/app/assets/javascripts/vue_shared/components/panel_resizer.vue
new file mode 100644
index 00000000000..4371534d345
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/panel_resizer.vue
@@ -0,0 +1,91 @@
+<script>
+export default {
+ props: {
+ startSize: {
+ type: Number,
+ required: true,
+ },
+ side: {
+ type: String,
+ required: true,
+ },
+ minSize: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ maxSize: {
+ type: Number,
+ required: false,
+ default: Number.MAX_VALUE,
+ },
+ enabled: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ size: this.startSize,
+ };
+ },
+ computed: {
+ className() {
+ return `drag${this.side}`;
+ },
+ cursorStyle() {
+ if (this.enabled) {
+ return { cursor: 'ew-resize' };
+ }
+ return {};
+ },
+ },
+ methods: {
+ resetSize(e) {
+ e.preventDefault();
+ this.size = this.startSize;
+ this.$emit('update:size', this.size);
+ },
+ startDrag(e) {
+ if (this.enabled) {
+ e.preventDefault();
+ this.startPos = e.clientX;
+ this.currentStartSize = this.size;
+ document.addEventListener('mousemove', this.drag);
+ document.addEventListener('mouseup', this.endDrag, { once: true });
+ this.$emit('resize-start', this.size);
+ }
+ },
+ drag(e) {
+ e.preventDefault();
+ let moved = e.clientX - this.startPos;
+ if (this.side === 'left') moved = -moved;
+ let newSize = this.currentStartSize + moved;
+ if (newSize < this.minSize) {
+ newSize = this.minSize;
+ } else if (newSize > this.maxSize) {
+ newSize = this.maxSize;
+ }
+ this.size = newSize;
+
+ this.$emit('update:size', newSize);
+ },
+ endDrag(e) {
+ e.preventDefault();
+ document.removeEventListener('mousemove', this.drag);
+ this.$emit('resize-end', this.size);
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="dragHandle"
+ :class="className"
+ :style="cursorStyle"
+ @mousedown="startDrag"
+ @dblclick="resetSize"
+ ></div>
+</template>
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index 26db2386879..077d0424093 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -71,7 +71,7 @@
vertical-align: top;
&.s16 { font-size: 12px; line-height: 1.33; }
- &.s24 { font-size: 14px; line-height: 1.8; }
+ &.s24 { font-size: 13px; line-height: 1.8; }
&.s26 { font-size: 20px; line-height: 1.33; }
&.s32 { font-size: 20px; line-height: 30px; }
&.s40 { font-size: 16px; line-height: 38px; }
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index dba482bfb23..dcd98cb522f 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -126,10 +126,8 @@ ul.content-list {
}
.description {
- p {
- @include str-truncated;
- margin-bottom: 0;
- }
+ @include str-truncated;
+ color: $gl-text-color-secondary;
}
.controls {
@@ -315,7 +313,7 @@ ul.indent-list {
border: 2px solid $white-normal;
&.identicon {
- line-height: 30px;
+ line-height: 15px;
}
}
}
@@ -349,14 +347,19 @@ ul.indent-list {
.folder-caret {
width: 15px;
+
+ svg {
+ margin-bottom: 2px;
+ }
}
.item-type-icon {
+ margin-top: 2px;
width: 20px;
}
> .group-row:not(.has-children) {
- .folder-caret .fa {
+ .folder-caret {
opacity: 0;
}
}
@@ -439,12 +442,61 @@ ul.indent-list {
.avatar-container > a {
width: 100%;
+ text-decoration: none;
}
&.has-more-items {
display: block;
padding: 20px 10px;
}
+
+ .stats {
+ position: relative;
+ line-height: 46px;
+
+ > span {
+ display: inline-flex;
+ align-items: center;
+ height: 16px;
+ min-width: 30px;
+ }
+
+ > span:last-child {
+ margin-right: 0;
+ }
+
+ .stat-value {
+ margin: 2px 0 0 5px;
+ }
+ }
+
+ .controls {
+ margin-left: 5px;
+
+ > .btn {
+ margin-right: $btn-xs-side-margin;
+ }
+ }
+ }
+
+ .project-row-contents .stats {
+ line-height: inherit;
+
+ > span:first-child {
+ margin-left: 25px;
+ }
+
+ .item-visibility {
+ margin-right: 0;
+ }
+
+ .last-updated {
+ position: absolute;
+ right: 12px;
+ min-width: 250px;
+ text-align: right;
+ color: $gl-text-color-secondary;
+ }
}
}
@@ -456,12 +508,12 @@ ul.indent-list {
ul.group-list-tree {
li.group-row {
- &.has-description .title {
- line-height: inherit;
+ > .group-row-contents .title {
+ line-height: $list-text-height;
}
- &:not(.has-description) .title {
- line-height: $list-text-height;
+ &.has-description > .group-row-contents .title {
+ line-height: inherit;
}
}
}
diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss
index 51cc1729d9a..d01cbadebcc 100644
--- a/app/assets/stylesheets/pages/repo.scss
+++ b/app/assets/stylesheets/pages/repo.scss
@@ -36,10 +36,6 @@
}
}
-.with-performance-bar .ide-view {
- height: calc(100vh - #{$header-height});
-}
-
.ide-file-list {
flex: 1;
@@ -242,12 +238,13 @@ table.table tr td.multi-file-table-name {
.multi-file-commit-panel {
display: flex;
+ position: relative;
flex-direction: column;
height: 100%;
width: 290px;
padding: 0;
background-color: $gray-light;
- border-left: 1px solid $white-dark;
+ padding-right: 3px;
.projects-sidebar {
display: flex;
@@ -496,3 +493,30 @@ table.table tr td.multi-file-table-name {
margin-top: $header-height;
margin-bottom: 0;
}
+
+.with-performance-bar {
+ .ide-flash-container.flash-container {
+ margin-top: $header-height + $performance-bar-height;
+ }
+
+ .ide-view {
+ height: calc(100vh - #{$header-height + $performance-bar-height});
+ }
+}
+
+
+.dragHandle {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 3px;
+ background-color: $white-dark;
+
+ &.dragright {
+ right: 0;
+ }
+
+ &.dragleft {
+ left: 0;
+ }
+}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 5d630c7d61e..6353482ede7 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -268,3 +268,7 @@
margin: 0 0 5px 17px;
}
}
+
+.deprecated-service {
+ cursor: default;
+}