-
Notifications
You must be signed in to change notification settings - Fork 177
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1264 from jayoshih/vue-channel-list
Vueified channel list page
- Loading branch information
Showing
74 changed files
with
4,088 additions
and
2,073 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Vue from 'vue'; | ||
var vueIntl = require("vue-intl"); | ||
|
||
// Just copy/pasted code from utils/translations.js here | ||
// as trying to import the actual file led to some errors | ||
|
||
var translations = window.ALL_MESSAGES || {}; // Set in django | ||
|
||
// Flatten translation dictionary | ||
var unnested_translations = {}; | ||
Object.keys(translations).forEach(function (key) { | ||
Object.keys(translations[key]).forEach(function(nestedKey) { | ||
unnested_translations[key + "." + nestedKey] = translations[key][nestedKey]; | ||
}); | ||
}); | ||
|
||
Vue.use(vueIntl, {"defaultLocale": "en"}); | ||
|
||
var currentLanguage = "en"; | ||
if (global.languageCode) { | ||
currentLanguage = global.languageCode; | ||
Vue.setLocale(currentLanguage); | ||
} | ||
|
||
Vue.registerMessages(currentLanguage, unnested_translations); | ||
Vue.prototype.$tr = function $tr(messageId, args) { | ||
const nameSpace = this.$options.name; | ||
if (args) { | ||
if (!Array.isArray(args) && typeof args !== 'object') { | ||
logging.error(`The $tr functions take either an array of positional | ||
arguments or an object of named options.`); | ||
} | ||
} | ||
const defaultMessageText = this.$options.$trs[messageId]; | ||
const message = { | ||
id: `${nameSpace}.${messageId}`, | ||
defaultMessage: defaultMessageText, | ||
}; | ||
|
||
return this.$formatMessage(message, args); | ||
}; | ||
|
||
module.exports = Vue; |
19 changes: 19 additions & 0 deletions
19
contentcuration/contentcuration/static/js/edit_channel/channel_list/constants.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
export const ListTypes = { | ||
EDITABLE: 'EDITABLE', | ||
STARRED: 'STARRED', | ||
VIEW_ONLY: 'VIEW_ONLY', | ||
PUBLIC: 'PUBLIC', | ||
CHANNEL_SETS: 'CHANNEL_SETS' | ||
}; | ||
|
||
export const ChannelListUrls = { | ||
[ListTypes.EDITABLE]: window.Urls.get_user_edit_channels(), | ||
[ListTypes.STARRED]: window.Urls.get_user_bookmarked_channels(), | ||
[ListTypes.VIEW_ONLY]: window.Urls.get_user_view_channels(), | ||
[ListTypes.PUBLIC]: window.Urls.get_user_public_channels() | ||
} | ||
|
||
export const ChannelInvitationMapping = { | ||
'edit': ListTypes.EDITABLE, | ||
'view': ListTypes.VIEW_ONLY | ||
} |
59 changes: 59 additions & 0 deletions
59
contentcuration/contentcuration/static/js/edit_channel/channel_list/mixins.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import _ from 'underscore'; | ||
import { mapGetters, mapActions, mapMutations, mapState } from 'vuex'; | ||
import { createTranslator } from 'utils/i18n'; | ||
import { dialog, alert } from 'edit_channel/utils/dialog'; | ||
|
||
const channelStrings = createTranslator('ChannelStrings', { | ||
unsavedChanges: "Unsaved Changes!", | ||
unsavedChangesText: "Exiting now will undo any new changes. Are you sure you want to exit?", | ||
dontSave: "Discard Changes", | ||
keepOpen: "Keep Editing", | ||
save: "Save", | ||
errorChannelSave: "Error Saving Channel" | ||
}); | ||
|
||
exports.setChannelMixin = { | ||
computed: { | ||
...mapState('channel_list', ['activeChannel']), | ||
...mapState('channel_list', ['changed']), | ||
channelStrings() { | ||
return channelStrings; | ||
} | ||
}, | ||
methods: { | ||
...mapActions('channel_list', ['saveChannel']), | ||
...mapMutations('channel_list', { | ||
setActiveChannel: 'SET_ACTIVE_CHANNEL', | ||
cancelChanges: 'CANCEL_CHANNEL_CHANGES' | ||
}), | ||
setChannel: function (channelID) { | ||
// Check for changes here when user switches or closes panel | ||
if(this.changed && channelID !== this.activeChannel.id) { | ||
dialog(this.channelStrings("unsavedChanges"), this.channelStrings("unsavedChangesText"), { | ||
[this.channelStrings("dontSave")]: () => { | ||
this.cancelChanges(); | ||
this.setActiveChannel(channelID); | ||
}, | ||
[this.channelStrings("keepOpen")]:() => {}, | ||
[this.channelStrings("save")]: () => { | ||
this.saveChannel().then(() => { | ||
this.setActiveChannel(channelID); | ||
}).catch( (error) => { | ||
alert(this.channelStrings('errorChannelSave'), error.responseText || error); | ||
}); | ||
}, | ||
}, null); | ||
} else { | ||
this.setActiveChannel(channelID); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
exports.tabMixin = { | ||
mounted() { | ||
this.$nextTick(() => { | ||
this.$refs.firstTab.focus(); | ||
}); | ||
} | ||
}; |
27 changes: 27 additions & 0 deletions
27
...on/contentcuration/static/js/edit_channel/channel_list/tests/channelDeleteSection.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { mount } from '@vue/test-utils'; | ||
import ChannelDeleteSection from './../views/ChannelDeleteSection.vue'; | ||
import _ from 'underscore'; | ||
import { localStore, mockFunctions } from './data.js'; | ||
|
||
|
||
function makeWrapper(props = {}) { | ||
return mount(ChannelDeleteSection, { | ||
store: localStore | ||
}) | ||
} | ||
|
||
describe('channelDeleteSection', () => { | ||
let wrapper; | ||
beforeEach(() => { | ||
wrapper = makeWrapper(); | ||
}); | ||
|
||
it('clicking delete channel should open a dialog warning', () => { | ||
wrapper.find('.delete-channel').trigger('click'); | ||
expect(mockFunctions.deleteChannel).not.toHaveBeenCalled(); | ||
|
||
expect(document.querySelector('#dialog-box')).toBeTruthy(); | ||
wrapper.vm.deleteChannel(wrapper.channel); | ||
expect(mockFunctions.deleteChannel).toHaveBeenCalled(); | ||
}); | ||
}); |
33 changes: 33 additions & 0 deletions
33
...ion/contentcuration/static/js/edit_channel/channel_list/tests/channelDetailsPanel.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { shallowMount } from '@vue/test-utils'; | ||
import ChannelDetailsPanel from './../views/ChannelDetailsPanel.vue'; | ||
import _ from 'underscore'; | ||
import { localStore, mockFunctions } from './data.js'; | ||
|
||
|
||
function makeWrapper(props = {}) { | ||
let channel = { | ||
id: 'test', | ||
main_tree: "abc", | ||
...props | ||
} | ||
localStore.commit('channel_list/RESET_STATE', channel) | ||
localStore.commit('channel_list/ADD_CHANNEL', channel) | ||
localStore.commit('channel_list/SET_ACTIVE_CHANNEL', channel.id) | ||
return shallowMount(ChannelDetailsPanel, { | ||
store: localStore | ||
}) | ||
} | ||
|
||
describe('channelDetailsPanel', () => { | ||
it('panel should set background as thumbnail', () => { | ||
let wrapper = makeWrapper({'thumbnail_url': 'test.png'}); | ||
let panel = wrapper.find('#channel-preview-wrapper'); | ||
let expectedStyle = "background-image: url('test.png')"; | ||
expect(panel.attributes('style')).toContain('test.png'); | ||
}); | ||
it('panel should set background as default thumbnail for new channels', () => { | ||
let wrapper = makeWrapper(); | ||
let panel = wrapper.find('#channel-preview-wrapper'); | ||
expect(panel.attributes('style')).toContain('kolibri_placeholder.png'); | ||
}); | ||
}); |
41 changes: 41 additions & 0 deletions
41
...contentcuration/static/js/edit_channel/channel_list/tests/channelDownloadDropdown.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { mount } from '@vue/test-utils'; | ||
import ChannelDownloadDropdown from './../views/ChannelDownloadDropdown.vue'; | ||
import _ from 'underscore'; | ||
import { localStore, mockFunctions } from './data.js'; | ||
|
||
|
||
function makeWrapper(props = {}) { | ||
return mount(ChannelDownloadDropdown, { | ||
store: localStore | ||
}) | ||
} | ||
|
||
const testChannel = { id: 'test', name: 'test' } | ||
localStore.commit('channel_list/ADD_CHANNEL', testChannel) | ||
|
||
|
||
describe('channelDownloadDropdown', () => { | ||
let wrapper; | ||
beforeEach(() => { | ||
localStore.commit('channel_list/SET_ACTIVE_CHANNEL', testChannel.id); | ||
mockFunctions.downloadChannelDetails.mockReset(); | ||
wrapper = makeWrapper(); | ||
}); | ||
|
||
it('clicking a download link should trigger a download', () => { | ||
wrapper.find('li a').trigger('click'); | ||
expect(mockFunctions.downloadChannelDetails).toHaveBeenCalled(); | ||
}); | ||
it('requesting a format should trigger corresponding format download', () => { | ||
function test(format) { | ||
wrapper.vm.downloadDetails(format); | ||
let args = mockFunctions.downloadChannelDetails.mock.calls[0][1]; | ||
expect(args.format).toEqual(format); | ||
mockFunctions.downloadChannelDetails.mockReset(); | ||
} | ||
test('pdf'); | ||
test('csv'); | ||
test('detailedPdf'); | ||
test('ppt'); | ||
}); | ||
}); |
122 changes: 122 additions & 0 deletions
122
...tcuration/contentcuration/static/js/edit_channel/channel_list/tests/channelEditor.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { mount } from '@vue/test-utils'; | ||
import ChannelEditor from './../views/ChannelEditor.vue'; | ||
import { localStore, mockFunctions } from './data.js'; | ||
require('handlebars/helpers'); // Needed for image uploader | ||
|
||
let testChannel = { | ||
'id': 'test', | ||
'name': 'channel', | ||
'description': "description", | ||
'language': 'en', | ||
} | ||
|
||
function makeWrapper(props = {}) { | ||
let channel = { | ||
...testChannel, | ||
...props | ||
}; | ||
localStore.commit('channel_list/RESET_STATE'); | ||
localStore.commit('channel_list/ADD_CHANNEL', channel); | ||
localStore.commit('channel_list/SET_ACTIVE_CHANNEL', channel.id); | ||
return mount(ChannelEditor, { | ||
store: localStore | ||
}); | ||
} | ||
|
||
describe('channelEditor', () => { | ||
let wrapper; | ||
beforeEach(() => { | ||
wrapper = makeWrapper(); | ||
}); | ||
|
||
describe('on load', () => { | ||
it('changed is false', () => { | ||
expect(wrapper.vm.changed).toBe(false); | ||
}); | ||
it('thumbnail is shown', () => { | ||
let thumbnail = "thumbnail.png"; | ||
let thumbnailWrapper = makeWrapper({'thumbnail_url': thumbnail}); | ||
expect(thumbnailWrapper.find('img').attributes('src')).toContain(thumbnail); | ||
}); | ||
it('default thumbnail is shown if channel has no thumbnail', () => { | ||
expect(wrapper.find('img').attributes('src')).toContain('kolibri_placeholder.png') | ||
}); | ||
it('.channel-name is set to channel.name', () => { | ||
expect(wrapper.find('.channel-name').element.value).toEqual(testChannel.name); | ||
}); | ||
it('.channel-description is set to channel.description', () => { | ||
expect(wrapper.find('.channel-description').element.value).toEqual(testChannel.description); | ||
}); | ||
it('#select-language is set to channel.language_id', () => { | ||
expect(wrapper.find('#select-language').element.value).toEqual(testChannel.language); | ||
}); | ||
}); | ||
|
||
describe('changes registered', () => { | ||
beforeEach(() => { | ||
localStore.commit('channel_list/SET_CHANGED', false); | ||
}); | ||
it('setChannelThumbnail sets channel.thumbnail', () => { | ||
let thumbnail = 'newthumbnail.png' | ||
wrapper.vm.setChannelThumbnail(thumbnail, {'new encoding': thumbnail}, thumbnail, thumbnail) | ||
expect(wrapper.vm.changed).toBe(true); | ||
expect(wrapper.vm.channel.thumbnail).toEqual(thumbnail); | ||
expect(wrapper.vm.channel.thumbnail_encoding).toEqual({'new encoding': thumbnail}); | ||
}); | ||
it('removeChannelThumbnail removes channel.thumbnail', () => { | ||
let thumbnailWrapper = makeWrapper({'thumbnail': 'thumbnail.png', 'thumbnail_encoding': {'test': 'test'}}) | ||
thumbnailWrapper.vm.removeChannelThumbnail(); | ||
expect(wrapper.vm.changed).toBe(true); | ||
expect(wrapper.vm.channel.thumbnail).toEqual(""); | ||
expect(wrapper.vm.channel.thumbnail_encoding).toEqual({}); | ||
}); | ||
it('typing in .channel-name sets channel.name', () => { | ||
let newName = 'new channel name'; | ||
let nameInput = wrapper.find('.channel-name'); | ||
nameInput.element.value = newName; | ||
nameInput.trigger('input'); | ||
nameInput.trigger('blur'); | ||
expect(wrapper.vm.changed).toBe(true); | ||
expect(wrapper.vm.channel.name).toEqual(newName); | ||
}); | ||
it('setting .channel-description sets channel.description', () => { | ||
let newDescription = "new channel description"; | ||
let descriptionInput = wrapper.find('.channel-description'); | ||
descriptionInput.element.value = newDescription; | ||
descriptionInput.trigger('input'); | ||
descriptionInput.trigger('blur'); | ||
expect(wrapper.vm.changed).toBe(true); | ||
expect(wrapper.vm.channel.description).toEqual(newDescription); | ||
}); | ||
it('setting #select-language sets channel.language_id', () => { | ||
let newLanguage = "en"; | ||
let languageDropdown = wrapper.find('#select-language'); | ||
languageDropdown.element.value = newLanguage; | ||
languageDropdown.trigger('input'); | ||
languageDropdown.trigger('blur'); | ||
expect(wrapper.vm.changed).toBe(true); | ||
expect(wrapper.vm.channel.language).toEqual(newLanguage); | ||
}); | ||
}) | ||
|
||
it('clicking CANCEL cancels edits', () => { | ||
let nameInput = wrapper.find('.channel-name'); | ||
nameInput.element.value = 'new channel name'; | ||
nameInput.trigger('input'); | ||
nameInput.trigger('blur'); | ||
|
||
// Cancel changes | ||
wrapper.find(".cancel-edits").trigger('click'); | ||
expect(wrapper.vm.changed).toBe(false); | ||
expect(wrapper.vm.channel.name).toEqual('channel'); | ||
expect(wrapper.emitted().cancelEdit).toBeTruthy(); | ||
}); | ||
|
||
it('clicking SAVE saves edits', () => { | ||
wrapper.find('form').trigger('submit'); | ||
expect(mockFunctions.saveChannel).toHaveBeenCalled(); | ||
wrapper.vm.$nextTick(() => { | ||
expect(wrapper.emitted('submitChanges')).toBeTruthy(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.