Skip to content

Commit

Permalink
Merge pull request #4 from indirectlylit/user_creation
Browse files Browse the repository at this point in the history
User creation - PR review updates
  • Loading branch information
66eli77 authored Aug 1, 2016
2 parents 0bb9ca4 + 5c71f51 commit 4416c63
Show file tree
Hide file tree
Showing 15 changed files with 85 additions and 529 deletions.
2 changes: 1 addition & 1 deletion docs/dev/frontend.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ For example:
management/
assets/
src/
learner-roster.vue # nested-view
user-roster.vue # nested-view
vue/index.vue # root view
app.js # instantiate mgmt app on client-side
test/
Expand Down
5 changes: 1 addition & 4 deletions docs/dev/user_management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interaction with the selectors and filters. Each item in this list corresponds t
* A ``manage`` button which summons a class and group management modal for that student.

.. note::
The roster described here corresponds to ``learner-roster.vue``.
The roster described here corresponds to ``user-roster.vue``.

The detail view modal displays learner account data and provides a mechanism to reset a learner's password.

Expand Down Expand Up @@ -91,9 +91,6 @@ The UI allows the list of learner in the roster to be filtered. This includes:
to the classroom selector.
* Potentially other filters, for example listing learners in alphabetical or reverse-alphabetical order.

.. note::
The classroom and group selectors are both instances of ``drop-down.vue``. Space is reserved in ``app-root.vue`` right now for other filters, however they don't correspond to subcomponents.

Miscellaneous widgets
*********************

Expand Down
2 changes: 1 addition & 1 deletion kolibri/auth/test/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def test_membership_str_method(self):
self.assertEqual(str(self.learner.membership_set.all()[0]), '"foo"@"Arkham"\'s membership in "Oodles of Fun" (learnergroup)')

def test_role_str_method(self):
self.assertEqual(str(self.classroom_coach.role_set.all()[0]), '"bar"@"Arkham"\'s coach role for "Classroom X" (classroom)')
self.assertEqual(str(self.classroom_coach.roles.all()[0]), '"bar"@"Arkham"\'s coach role for "Classroom X" (classroom)')

def test_facility_str_method(self):
self.assertEqual(str(self.facility), "Arkham")
Expand Down
35 changes: 15 additions & 20 deletions kolibri/plugins/management/assets/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ function createUser(store, payload, role) {
newUserPromise.then((model) => {
// assgin role to this new user if the role is not learner
if (role === 'learner' || !role) {
// mutation ADD_LEARNERS only take array
store.dispatch('ADD_LEARNERS', [model]);
// mutation ADD_USERS only take array
store.dispatch('ADD_USERS', [model]);
} else {
const rolePayload = {
user: model.id,
Expand All @@ -26,7 +26,7 @@ function createUser(store, payload, role) {
const newRolePromise = RoleModel.save(rolePayload);
newRolePromise.then((results) => {
FacilityUserModel.fetch({}, true).then(updatedModel => {
store.dispatch('ADD_LEARNERS', [updatedModel]);
store.dispatch('ADD_USERS', [updatedModel]);
});
}).catch((error) => {
store.dispatch('SET_ERROR', JSON.stringify(error, null, '\t'));
Expand Down Expand Up @@ -66,7 +66,7 @@ function updateUser(store, id, payload, role) {
// force role change because if the role is the only changing attribute
// FacilityUserModel.save() will not send request to server.
responses.roles = [newRole];
store.dispatch('UPDATE_LEARNERS', [responses]);
store.dispatch('UPDATE_USERS', [responses]);
})
.catch((error) => {
store.dispatch('SET_ERROR', JSON.stringify(error, null, '\t'));
Expand All @@ -89,7 +89,7 @@ function updateUser(store, id, payload, role) {
// force role change because if the role is the only changing attribute
// FacilityUserModel.save() will not send request to server.
responses.roles = [newRole];
store.dispatch('UPDATE_LEARNERS', [responses]);
store.dispatch('UPDATE_USERS', [responses]);
})
.catch((error) => {
store.dispatch('SET_ERROR', JSON.stringify(error, null, '\t'));
Expand All @@ -107,7 +107,7 @@ function updateUser(store, id, payload, role) {
// force role change because if the role is the only changing attribute
// FacilityUserModel.save() will not send request to server.
responses.roles = [];
store.dispatch('UPDATE_LEARNERS', [responses]);
store.dispatch('UPDATE_USERS', [responses]);
})
.catch((error) => {
store.dispatch('SET_ERROR', JSON.stringify(error, null, '\t'));
Expand All @@ -117,7 +117,7 @@ function updateUser(store, id, payload, role) {
} else {
// the role is not changed
FacilityUserModel.save(payload).then(responses => {
store.dispatch('UPDATE_LEARNERS', [responses]);
store.dispatch('UPDATE_USERS', [responses]);
})
.catch((error) => {
store.dispatch('SET_ERROR', JSON.stringify(error, null, '\t'));
Expand All @@ -137,31 +137,26 @@ function deleteUser(store, id) {
const FacilityUserModel = Kolibri.resources.FacilityUserResource.getModel(id);
const newUserPromise = FacilityUserModel.delete(id);
newUserPromise.then((userId) => {
store.dispatch('DELETE_LEARNERS', [userId]);
store.dispatch('DELETE_USERS', [userId]);
})
.catch((error) => {
store.dispatch('SET_ERROR', JSON.stringify(error, null, '\t'));
});
}

// An action for setting up the initial state of the app by fetching data from the server
function fetch(store) {
function fetchInitialData(store) {
const learnerCollection = FacilityUserResource.getCollection();
const roleCollection = RoleResource.getCollection();
const facilityIdPromise = learnerCollection.getCurrentFacility();
const learnerPromise = learnerCollection.fetch();
const userPromise = learnerCollection.fetch();
const rolePromise = roleCollection.fetch();
const promises = [facilityIdPromise, learnerPromise, rolePromise];
const promises = [facilityIdPromise, userPromise, rolePromise];
Promise.all(promises).then(responses => {
const id = responses[0];
if (id.constructor === Array) {
// for mvp, we assume only one facility ever existed.
store.dispatch('SET_FACILITY', id[0]);
} else {
store.dispatch('SET_FACILITY', id);
}
const learners = responses[1];
store.dispatch('ADD_LEARNERS', learners);
store.dispatch('SET_FACILITY', id[0]); // for mvp, we assume only one facility exists
const users = responses[1];
store.dispatch('ADD_USERS', users);
},
rejects => {
store.dispatch('SET_ERROR', JSON.stringify(rejects, null, '\t'));
Expand All @@ -172,5 +167,5 @@ module.exports = {
createUser,
updateUser,
deleteUser,
fetch,
fetchInitialData,
};
4 changes: 2 additions & 2 deletions kolibri/plugins/management/assets/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class ManagementModule extends KolibriModule {
store: require('./state/store.js').store,
vuex: {
actions: {
fetch: actions.fetch,
fetchInitialData: actions.fetchInitialData,
},
},
});
this.vm.fetch();
this.vm.fetchInitialData();
}
}

Expand Down
27 changes: 0 additions & 27 deletions kolibri/plugins/management/assets/src/state/getters.js

This file was deleted.

44 changes: 22 additions & 22 deletions kolibri/plugins/management/assets/src/state/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,45 @@ const Vuex = require('vuex');

function getInitialState() {
return {
facility: 1,
learners: [],
facility: undefined,
users: [],
error: '',
};
}


const mutations = {
ADD_LEARNERS(state, learners) {
learners.forEach(learner => {
state.learners.push({
id: learner.id,
username: learner.username,
first_name: learner.first_name,
last_name: learner.last_name,
roles: learner.roles,
ADD_USERS(state, users) {
users.forEach(user => {
state.users.push({
id: user.id,
username: user.username,
first_name: user.first_name,
last_name: user.last_name,
roles: user.roles,
});
});
},

UPDATE_LEARNERS(state, learners) {
learners.forEach(learner => {
state.learners.forEach(existingLearner => {
if (existingLearner.id === learner.id.toString()) {
existingLearner.username = learner.username;
existingLearner.first_name = learner.first_name;
existingLearner.last_name = learner.last_name;
existingLearner.roles = learner.roles;
UPDATE_USERS(state, users) {
users.forEach(user => {
state.users.forEach(existingUser => {
if (existingUser.id === user.id.toString()) {
existingUser.username = user.username;
existingUser.first_name = user.first_name;
existingUser.last_name = user.last_name;
existingUser.roles = user.roles;
}
});
});
},

DELETE_LEARNERS(state, ids) {
DELETE_USERS(state, ids) {
ids.forEach(id => {
state.learners.forEach((learner, index) => {
if (learner.id === id) {
state.users.forEach((user, index) => {
if (user.id === id) {
if (index > -1) {
state.learners.splice(index, 1);
state.users.splice(index, 1);
}
}
});
Expand Down
28 changes: 0 additions & 28 deletions kolibri/plugins/management/assets/src/vue/drop-down.vue

This file was deleted.

5 changes: 2 additions & 3 deletions kolibri/plugins/management/assets/src/vue/index.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>

<core-base>
<learner-roster></learner-roster>
<user-roster></user-roster>
</core-base>

</template>
Expand All @@ -12,8 +12,7 @@
module.exports = {
components: {
'core-base': require('core-base'),
'drop-down': require('./drop-down.vue'),
'learner-roster': require('./learner-roster.vue'),
'user-roster': require('./user-roster.vue'),
},
vuex: {
actions: require('../actions.js'),
Expand Down
24 changes: 12 additions & 12 deletions kolibri/plugins/management/assets/src/vue/user-create-modal.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<template>

<div class="user-creation-modal">
<modal btntext="+ Learner">
<modal btntext="+ User">
<div class="title" slot="header">User creation</div>
<div slot="body">
<br>Username: <input type="text" v-model="userName" placeholder="Please type in your username."><br>
<br>Password: <input type="text" v-model="passWord" placeholder="Please type in your password."><br>
<br>Username: <input type="text" v-model="username" placeholder="Please type in your username."><br>
<br>Password: <input type="text" v-model="password" placeholder="Please type in your password."><br>
<br>First name: <input type="text" v-model="firstName" placeholder="Please type in your first name."><br>
<br>Last name: <input type="text" v-model="lastName" placeholder="Please type in your last name."><br>
<!-- radio buttons for electing role -->
<br>Learner <input type="radio" name="picked" value="learner" v-model="role"><br>
<br>Admin <input type="radio" name="picked" value="admin" v-model="role"><br>
<!-- radio buttons for selecting role -->
<br>Learner <input type="radio" value="learner" v-model="role"><br>
<br>Admin <input type="radio" value="admin" v-model="role"><br>
</div>
<div slot="footer">
<button class="create-btn" type="button" @click="createNewUser">Create User</button>
Expand All @@ -31,8 +31,8 @@
},
data() {
return {
userName: '',
passWord: '',
username: '',
password: '',
firstName: '',
lastName: '',
role: 'learner',
Expand All @@ -41,8 +41,8 @@
methods: {
createNewUser() {
const payload = {
password: this.passWord,
username: this.userName,
password: this.password,
username: this.username,
first_name: this.firstName,
last_name: this.lastName,
facility: this.facility,
Expand All @@ -67,8 +67,8 @@
.title
display: inline
.create-btn
float: right
</style>
</style>
Loading

0 comments on commit 4416c63

Please sign in to comment.