Commit f535dc12 authored by Vincent Laroye's avatar Vincent Laroye

Merge branch 'bugfix/view-duplication' into 'develop'

bugfix/view-duplication

See merge request !663
parents e5f40cf5 a928530c
Pipeline #4486 passed with stage
in 3 minutes and 8 seconds
......@@ -72,8 +72,14 @@
import { find, omit } from 'lodash';
import { MODALS, USERS_RIGHTS_TYPES, USERS_RIGHTS_MASKS } from '@/constants';
import { generateView, generateViewRow, generateRight, generateRoleRightByChecksum } from '@/helpers/entities';
import uuid from '@/helpers/uid';
import {
generateView,
generateRight,
generateRoleRightByChecksum,
generateCopyOfView,
getViewsWidgetsIdsMappings,
} from '@/helpers/entities';
import authMixin from '@/mixins/auth';
import popupMixin from '@/mixins/popup';
import modalInnerMixin from '@/mixins/modal/inner';
......@@ -81,6 +87,7 @@ import entitiesViewMixin from '@/mixins/entities/view';
import entitiesRoleMixin from '@/mixins/entities/role';
import entitiesRightMixin from '@/mixins/entities/right';
import entitiesViewGroupMixin from '@/mixins/entities/view/group';
import entitiesUserPreferenceMixin from '@/mixins/entities/user-preference';
import rightsTechnicalViewMixin from '@/mixins/rights/technical/view';
import vuetifyComboboxMixin from '@/mixins/vuetify/combobox';
......@@ -100,6 +107,7 @@ export default {
entitiesRoleMixin,
entitiesRightMixin,
entitiesViewGroupMixin,
entitiesUserPreferenceMixin,
rightsTechnicalViewMixin,
vuetifyComboboxMixin,
],
......@@ -258,7 +266,7 @@ export default {
/**
* If we're creating a new view, or duplicating an existing one.
* Generate a new view. Then copy rows and widgets if we're duplicating a view
* Generate a new view. Then copy tabs, rows and widgets if we're duplicating a view
*/
if (!this.config.view || this.config.isDuplicating) {
const data = {
......@@ -268,12 +276,13 @@ export default {
};
if (this.config.isDuplicating) {
data.rows = this.config.view.rows.map(row => ({
...generateViewRow(),
const { tabs } = generateCopyOfView(this.config.view);
data.tabs = tabs;
const widgetsIdsMappings = getViewsWidgetsIdsMappings(this.config.view, data);
title: row.title,
widgets: row.widgets.map(widget => ({ ...widget, _id: uuid(`widget_${widget.type}`) })),
}));
await this.copyUserPreferencesByWidgetsIdsMappings(widgetsIdsMappings);
}
const response = await this.createView({ data });
......
......@@ -53,25 +53,17 @@
</template>
<script>
import { omit } from 'lodash';
import Draggable from 'vuedraggable';
import { createNamespacedHelpers } from 'vuex';
import { VUETIFY_ANIMATION_DELAY } from '@/config';
import { MODALS } from '@/constants';
import {
generateViewTab,
generateViewRow,
generateWidgetByType,
generateUserPreferenceByWidgetAndUser,
} from '@/helpers/entities';
import { generateCopyOfViewTab, getViewsTabsWidgetsIdsMappings } from '@/helpers/entities';
import authMixin from '@/mixins/auth';
import modalMixin from '@/mixins/modal';
import vuetifyTabsMixin from '@/mixins/vuetify/tabs';
const { mapActions: userPreferenceMapActions } = createNamespacedHelpers('userPreference');
import entitiesUserPreferenceMixin from '@/mixins/entities/user-preference';
export default {
components: { Draggable },
......@@ -79,6 +71,7 @@ export default {
authMixin,
modalMixin,
vuetifyTabsMixin,
entitiesUserPreferenceMixin,
],
props: {
view: {
......@@ -133,11 +126,6 @@ export default {
},
},
methods: {
...userPreferenceMapActions({
createUserPreference: 'create',
fetchUserPreferenceByWidgetIdWithoutStore: 'fetchItemByWidgetIdWithoutStore',
}),
showUpdateTabModal(tab) {
this.showModal({
name: MODALS.textFieldEditor,
......@@ -183,54 +171,17 @@ export default {
},
async duplicateTabAction(tab, title) {
const widgetsIdsMap = {};
const newTab = {
...generateViewTab(),
...generateCopyOfViewTab(tab),
title,
rows: tab.rows.map(row => ({
...generateViewRow(),
title: row.title,
widgets: row.widgets.map((widget) => {
const newWidget = generateWidgetByType(widget.type);
widgetsIdsMap[widget._id] = newWidget._id;
return {
...newWidget,
...omit(widget, ['_id']),
};
}),
})),
};
await this.copyUserPreferencesForWidgets(widgetsIdsMap);
const widgetsIdsMappings = getViewsTabsWidgetsIdsMappings(tab, newTab);
return this.addTab(newTab);
},
await this.copyUserPreferencesByWidgetsIdsMappings(widgetsIdsMappings);
async copyUserPreferencesForWidgets(widgetsIdsMap) {
const oldWidgetsIds = Object.keys(widgetsIdsMap);
const userPreferences = await Promise.all(oldWidgetsIds.map(widgetId =>
this.fetchUserPreferenceByWidgetIdWithoutStore({ widgetId })));
return Promise.all(userPreferences.map((userPreference) => {
if (!userPreference) {
return Promise.resolve();
}
const newWidgetId = widgetsIdsMap[userPreference.widget_id];
const newUserPreference = generateUserPreferenceByWidgetAndUser({ _id: newWidgetId }, this.currentUser);
return this.createUserPreference({
userPreference: {
...newUserPreference,
...omit(userPreference, ['_id', 'widget_id']),
},
});
}));
return this.addTab(newTab);
},
updateTab(tab) {
......
import moment from 'moment';
import { get, omit } from 'lodash';
import i18n from '@/i18n';
import { PAGINATION_LIMIT } from '@/config';
......@@ -6,6 +7,12 @@ import { WIDGET_TYPES, STATS_CALENDAR_COLORS, STATS_DURATION_UNITS, SERVICE_WEAT
import uuid from './uuid';
/**
* Generate widget by type
*
* @param {string} type
* @returns {Object}
*/
export function generateWidgetByType(type) {
const widget = {
type,
......@@ -198,6 +205,11 @@ export function generateWidgetByType(type) {
return widget;
}
/**
* Generate view row
*
* @returns {Object}
*/
export function generateViewRow() {
return {
_id: uuid('view-row'),
......@@ -206,6 +218,11 @@ export function generateViewRow() {
};
}
/**
* Generate view tab
*
* @returns {Object}
*/
export function generateViewTab() {
return {
_id: uuid('view-tab'),
......@@ -214,6 +231,11 @@ export function generateViewTab() {
};
}
/**
* Generate view
*
* @returns {Object}
*/
export function generateView() {
const defaultTab = { ...generateViewTab(), title: 'Default' };
......@@ -228,6 +250,13 @@ export function generateView() {
};
}
/**
* Generate user preference by widget and user objects
*
* @param {Object} widget
* @param {Object} user
* @returns {Object}
*/
export function generateUserPreferenceByWidgetAndUser(widget, user) {
return {
_id: `${widget._id}_${user.crecord_name}`,
......@@ -239,6 +268,11 @@ export function generateUserPreferenceByWidgetAndUser(widget, user) {
};
}
/**
* Generate user
*
* @returns {Object}
*/
export function generateUser() {
return {
crecord_write_time: null,
......@@ -264,6 +298,11 @@ export function generateUser() {
};
}
/**
* Generate role
*
* @returns {Object}
*/
export function generateRole() {
return {
crecord_write_time: null,
......@@ -276,6 +315,11 @@ export function generateRole() {
};
}
/**
* Generate right
*
* @returns {Object}
*/
export function generateRight() {
return {
crecord_creation_time: null,
......@@ -290,6 +334,12 @@ export function generateRight() {
};
}
/**
* Generate role right by checksum
*
* @param {number} checksum
* @returns {Object}
*/
export function generateRoleRightByChecksum(checksum) {
return {
checksum,
......@@ -297,6 +347,78 @@ export function generateRoleRightByChecksum(checksum) {
};
}
/**
* Generate copy of view tab
*
* @param {Object} tab
* @returns {Object}
*/
export function generateCopyOfViewTab(tab) {
return {
...generateViewTab(),
rows: tab.rows.map(row => ({
...generateViewRow(),
title: row.title,
widgets: row.widgets.map(widget => ({
...generateWidgetByType(widget.type),
...omit(widget, ['_id']),
})),
})),
};
}
/**
* Generate copy of view
*
* @param {Object} view
* @returns {Object}
*/
export function generateCopyOfView(view) {
return {
...generateView(),
...omit(view, ['_id', 'tabs']),
tabs: view.tabs.map(tab => ({
...generateCopyOfViewTab(tab),
...omit(tab, ['_id', 'rows']),
})),
};
}
/**
* Get mappings for widgets ids from old tab to new tab
*
* @param {Object} oldTab
* @param {Object} newTab
* @returns {Array.<{ oldId: number, newId: number }>}
*/
export function getViewsTabsWidgetsIdsMappings(oldTab, newTab) {
return oldTab.rows.reduce((acc, row, rowIndex) => {
const widgetsIds = row.widgets.map((widget, widgetIndex) => ({
oldId: widget._id,
newId: get(newTab, `rows.${rowIndex}.widgets.${widgetIndex}._id`, null),
}));
return acc.concat(widgetsIds);
}, []);
}
/**
* Get mappings for widgets from old view to new view
*
* @param {Object} oldView
* @param {Object} newView
* @returns {Array.<{ oldId: number, newId: number }>}
*/
export function getViewsWidgetsIdsMappings(oldView, newView) {
return oldView.tabs.reduce((acc, tab, index) =>
acc.concat(getViewsTabsWidgetsIdsMappings(tab, newView.tabs[index])), []);
}
export default {
generateWidgetByType,
generateViewRow,
......@@ -306,4 +428,9 @@ export default {
generateRole,
generateRight,
generateRoleRightByChecksum,
generateCopyOfViewTab,
generateCopyOfView,
getViewsTabsWidgetsIdsMappings,
getViewsWidgetsIdsMappings,
};
import omit from 'lodash/omit';
import { createNamespacedHelpers } from 'vuex';
import { generateUserPreferenceByWidgetAndUser } from '@/helpers/entities';
const { mapActions, mapGetters } = createNamespacedHelpers('userPreference');
/**
......@@ -19,6 +22,7 @@ export default {
...mapActions({
fetchUserPreferencesList: 'fetchList',
fetchUserPreferenceByWidgetId: 'fetchItemByWidgetId',
fetchUserPreferenceByWidgetIdWithoutStore: 'fetchItemByWidgetIdWithoutStore',
createUserPreference: 'create',
}),
......@@ -30,5 +34,32 @@ export default {
},
});
},
/**
* Send requests to create userPreference by widgetsIdsMappings
*
* @param {Array.<{oldId: string, newId: string}>} widgetsIdsMappings
* @returns {Promise.<*[]>}
*/
copyUserPreferencesByWidgetsIdsMappings(widgetsIdsMappings) {
return Promise.all(widgetsIdsMappings.map(async ({ oldId, newId }) => {
const userPreference = await this.fetchUserPreferenceByWidgetIdWithoutStore({ widgetId: oldId });
if (!userPreference) {
return Promise.resolve();
}
const newUserPreference = generateUserPreferenceByWidgetAndUser({
_id: newId,
}, this.currentUser);
return this.createUserPreference({
userPreference: {
...newUserPreference,
...omit(userPreference, ['_id', 'widget_id']),
},
});
}));
},
},
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment