Skip to content
Snippets Groups Projects
Commit 9de3c684 authored by robinwilliam.hundt's avatar robinwilliam.hundt
Browse files

Started added typings in store files

parent f59e3839
No related branches found
No related tags found
1 merge request!113Resolve "Frontend Refactor"
Pipeline #78104 failed
This commit is part of merge request !113. Comments created here will be created in the context of that merge request.
import axios from 'axios' import axios from 'axios'
import {Credentials} from "@/store/modules/authentication";
function addFieldsToUrl ({url, fields = []}) { function addFieldsToUrl ({url, fields = []}: {url: string, fields?: string[]}) {
return fields.length > 0 ? url + '?fields=pk,' + fields : url return fields.length > 0 ? url + '?fields=pk,' + fields : url
} }
...@@ -22,27 +23,27 @@ let ax = axios.create({ ...@@ -22,27 +23,27 @@ let ax = axios.create({
} }
} }
export async function registerTutor (credentials) { export async function registerTutor (credentials: Credentials) {
return ax.post('/api/tutor/register/', credentials) return ax.post('/api/tutor/register/', credentials)
} }
export async function fetchJWT (credentials) { export async function fetchJWT (credentials: Credentials): Promise<string> {
const token = (await ax.post('/api/get-token/', credentials)).data.token const token: string = (await ax.post('/api/get-token/', credentials)).data.token
ax.defaults.headers['Authorization'] = `JWT ${token}` ax.defaults.headers['Authorization'] = `JWT ${token}`
return token return token
} }
export async function refreshJWT (token) { export async function refreshJWT (token: string): Promise<string> {
const newToken = (await ax.post('/api/refresh-token/', {token})).data.token const newToken: string = (await ax.post('/api/refresh-token/', {token})).data.token
ax.defaults.headers['Authorization'] = `JWT ${newToken}` ax.defaults.headers['Authorization'] = `JWT ${newToken}`
return newToken return newToken
} }
export async function fetchJWTTimeDelta () { export async function fetchJWTTimeDelta (): Promise<number> {
return (await ax.get('/api/jwt-time-delta/')).data.timeDelta return (await ax.get('/api/jwt-time-delta/')).data.timeDelta
} }
export async function fetchUserRole () { export async function fetchUserRole (): Promise<string> {
return (await ax.get('/api/user-role/')).data.role return (await ax.get('/api/user-role/')).data.role
} }
...@@ -54,11 +55,11 @@ export async function fetchStudentSubmissions () { ...@@ -54,11 +55,11 @@ export async function fetchStudentSubmissions () {
return (await ax.get('/api/student-submissions/')).data return (await ax.get('/api/student-submissions/')).data
} }
export async function fetchSubmissionFeedbackTests ({pk}) { export async function fetchSubmissionFeedbackTests ({pk}: {pk: string}) {
return (await ax.get(`/api/submission/${pk}/`)).data return (await ax.get(`/api/submission/${pk}/`)).data
} }
export async function fetchAllStudents (fields = []) { export async function fetchAllStudents (fields: string[] = []) {
const url = addFieldsToUrl({ const url = addFieldsToUrl({
url: '/api/student/', url: '/api/student/',
fields fields
...@@ -66,7 +67,8 @@ export async function fetchAllStudents (fields = []) { ...@@ -66,7 +67,8 @@ export async function fetchAllStudents (fields = []) {
return (await ax.get(url)).data return (await ax.get(url)).data
} }
export async function fetchStudent ({pk, fields = []}) { export async function fetchStudent ({pk, fields = []}:
{pk: string, fields?: string[]}) {
const url = addFieldsToUrl({ const url = addFieldsToUrl({
url: `/api/student/${pk}/`, url: `/api/student/${pk}/`,
fields fields
...@@ -74,7 +76,7 @@ export async function fetchStudent ({pk, fields = []}) { ...@@ -74,7 +76,7 @@ export async function fetchStudent ({pk, fields = []}) {
return (await ax.get(url)).data return (await ax.get(url)).data
} }
export async function fetchAllTutors (fields = []) { export async function fetchAllTutors (fields: string[] = []) {
const url = addFieldsToUrl({ const url = addFieldsToUrl({
url: '/api/tutor/', url: '/api/tutor/',
fields fields
...@@ -86,16 +88,16 @@ export async function fetchSubscriptions () { ...@@ -86,16 +88,16 @@ export async function fetchSubscriptions () {
return (await ax.get('/api/subscription/')).data return (await ax.get('/api/subscription/')).data
} }
export async function deactivateSubscription ({pk}) { export async function deactivateSubscription ({pk}: {pk: string}) {
const url = `/api/subscription/${pk}/` const url = `/api/subscription/${pk}/`
return (await ax.delete(url)).data return (await ax.delete(url)).data
} }
export async function fetchSubscription (subscriptionPk) { export async function fetchSubscription (subscriptionPk: string) {
return (await ax.get(`/api/subscription/${subscriptionPk}/`)).data return (await ax.get(`/api/subscription/${subscriptionPk}/`)).data
} }
export async function fetchAllFeedback (fields = []) { export async function fetchAllFeedback (fields: string[] = []) {
const url = addFieldsToUrl({ const url = addFieldsToUrl({
url: '/api/feedback/', url: '/api/feedback/',
fields fields
...@@ -108,7 +110,8 @@ export async function fetchFeedback ({ofSubmission}) { ...@@ -108,7 +110,8 @@ export async function fetchFeedback ({ofSubmission}) {
return (await ax.get(url)).data return (await ax.get(url)).data
} }
export async function fetchExamType ({examPk, fields = []}) { export async function fetchExamType ({examPk, fields = []}:
{examPk: string, fields?: string[]}) {
const url = addFieldsToUrl({ const url = addFieldsToUrl({
url: `/api/examtype/${examPk !== undefined ? examPk + '/' : ''}`, url: `/api/examtype/${examPk !== undefined ? examPk + '/' : ''}`,
fields}) fields})
...@@ -189,7 +192,7 @@ export async function deactivateAllStudentAccess () { ...@@ -189,7 +192,7 @@ export async function deactivateAllStudentAccess () {
return ax.post('/api/student/deactivate/') return ax.post('/api/student/deactivate/')
} }
export async function changePassword (userPk, data) { export async function changePassword (userPk: string, data) {
return ax.patch(`/api/user/${userPk}/change_password/`, data) return ax.patch(`/api/user/${userPk}/change_password/`, data)
} }
...@@ -197,7 +200,7 @@ export async function getOwnUser () { ...@@ -197,7 +200,7 @@ export async function getOwnUser () {
return (await ax.get('/api/user/me/')).data return (await ax.get('/api/user/me/')).data
} }
export async function changeActiveForUser (userPk, active) { export async function changeActiveForUser (userPk: string, active: boolean) {
return (await ax.patch(`/api/user/${userPk}/change_active/`, {'is_active': active})).data return (await ax.patch(`/api/user/${userPk}/change_active/`, {'is_active': active})).data
} }
......
...@@ -88,32 +88,26 @@ export default { ...@@ -88,32 +88,26 @@ export default {
items: [ items: [
{ {
name: 'showFinal', name: 'showFinal',
path: 'showFinal',
mutation: feedbackSearchOptsMut.SET_SHOW_FINAL mutation: feedbackSearchOptsMut.SET_SHOW_FINAL
}, },
{ {
name: 'searchOtherUserComments', name: 'searchOtherUserComments',
path: 'searchOtherUserComments',
mutation: feedbackSearchOptsMut.SET_SEARCH_OTHER_USER_COMMENTS mutation: feedbackSearchOptsMut.SET_SEARCH_OTHER_USER_COMMENTS
}, },
{ {
name: 'caseSensitive', name: 'caseSensitive',
path: 'caseSensitive',
mutation: feedbackSearchOptsMut.SET_CASE_SENSITIVE mutation: feedbackSearchOptsMut.SET_CASE_SENSITIVE
}, },
{ {
name: 'useRegex', name: 'useRegex',
path: 'useRegex',
mutation: feedbackSearchOptsMut.SET_USE_REGEX mutation: feedbackSearchOptsMut.SET_USE_REGEX
}, },
{ {
name: 'filterByTutors', name: 'filterByTutors',
path: 'filterByTutors',
mutation: feedbackSearchOptsMut.SET_FILTER_BY_TUTORS mutation: feedbackSearchOptsMut.SET_FILTER_BY_TUTORS
}, },
{ {
name: 'filterByStage', name: 'filterByStage',
path: 'filterByStage',
mutation: feedbackSearchOptsMut.SET_FILTER_BY_STAGE mutation: feedbackSearchOptsMut.SET_FILTER_BY_STAGE
} }
......
...@@ -41,10 +41,8 @@ export default { ...@@ -41,10 +41,8 @@ export default {
watch: { watch: {
nextRoute (newVal, oldVal) { nextRoute (newVal, oldVal) {
if (newVal !== oldVal && this.$store.getters['submissionNotes/workInProgress']) { if (newVal !== oldVal && this.$store.getters['submissionNotes/workInProgress']) {
console.log('here')
this.dialog = true this.dialog = true
} else { } else {
console.log('there')
this.nextRoute() this.nextRoute()
} }
} }
......
import * as api from '@/api' import * as api from '@/api'
import gradySays from '../grady_speak' import gradySays from '../grady_speak'
import {ActionContext, Module} from "vuex";
function initialState () { export interface Credentials {
username: string,
password: string
}
interface AuthState {
token: string,
lastTokenRefreshTry: number,
refreshingToken: boolean,
jwtTimeDelta: number,
message: string,
user: {
pk: string,
username: string,
role: string,
is_admin: boolean
}
}
function initialState (): AuthState {
return { return {
token: sessionStorage.getItem('token'), token: sessionStorage.getItem('token') || '',
lastTokenRefreshTry: Date.now(), lastTokenRefreshTry: Date.now(),
refreshingToken: false, refreshingToken: false,
jwtTimeDelta: 0, jwtTimeDelta: 0,
...@@ -12,7 +31,7 @@ function initialState () { ...@@ -12,7 +31,7 @@ function initialState () {
pk: '', pk: '',
username: '', username: '',
role: '', role: '',
is_admin: '' is_admin: false
} }
} }
} }
...@@ -27,53 +46,53 @@ export const authMut = Object.freeze({ ...@@ -27,53 +46,53 @@ export const authMut = Object.freeze({
SET_REFRESHING_TOKEN: 'SET_REFRESHING_TOKEN' SET_REFRESHING_TOKEN: 'SET_REFRESHING_TOKEN'
}) })
const authentication = { const authentication: Module<AuthState, any> = {
state: initialState(), state: initialState(),
getters: { getters: {
gradySpeak: () => { gradySpeak: () => {
return gradySays[Math.floor(Math.random() * gradySays.length)] return gradySays[Math.floor(Math.random() * gradySays.length)]
}, },
isStudent: state => { isStudent: (state: AuthState) => {
return state.user.role === 'Student' return state.user.role === 'Student'
}, },
isTutor: state => { isTutor: (state: AuthState)=> {
return state.user.role === 'Tutor' return state.user.role === 'Tutor'
}, },
isReviewer: state => { isReviewer: (state: AuthState)=> {
return state.user.role === 'Reviewer' return state.user.role === 'Reviewer'
}, },
isTutorOrReviewer: (state, getters) => { isTutorOrReviewer: (state: AuthState, getters) => {
return getters.isTutor || getters.isReviewer return getters.isTutor || getters.isReviewer
}, },
isLoggedIn: state => !!state.token isLoggedIn: (state: AuthState) => !!state.token
}, },
mutations: { mutations: {
[authMut.SET_MESSAGE] (state, message) { [authMut.SET_MESSAGE] (state: AuthState, message: string) {
state.message = message state.message = message
}, },
[authMut.SET_JWT_TOKEN] (state, token) { [authMut.SET_JWT_TOKEN] (state: AuthState, token: string) {
sessionStorage.setItem('token', token) sessionStorage.setItem('token', token)
state.token = token state.token = token
}, },
[authMut.SET_JWT_TIME_DELTA] (state, timeDelta) { [authMut.SET_JWT_TIME_DELTA] (state: AuthState, timeDelta: number) {
state.jwtTimeDelta = timeDelta state.jwtTimeDelta = timeDelta
}, },
[authMut.SET_USER] (state, user) { [authMut.SET_USER] (state: AuthState, user) {
state.user = user state.user = user
}, },
[authMut.SET_REFRESHING_TOKEN] (state, refreshing) { [authMut.SET_REFRESHING_TOKEN] (state: AuthState, refreshing: boolean) {
state.refreshingToken = refreshing state.refreshingToken = refreshing
}, },
[authMut.SET_LAST_TOKEN_REFRESH_TRY] (state) { [authMut.SET_LAST_TOKEN_REFRESH_TRY] (state: AuthState) {
state.lastTokenRefreshTry = Date.now() state.lastTokenRefreshTry = Date.now()
}, },
[authMut.RESET_STATE] (state) { [authMut.RESET_STATE] (state: AuthState) {
sessionStorage.setItem('token', '') sessionStorage.setItem('token', '')
Object.assign(state, initialState()) Object.assign(state, initialState())
} }
}, },
actions: { actions: {
async getJWT (context, credentials) { async getJWT (context: ActionContext<AuthState, any>, credentials: Credentials) {
try { try {
const token = await api.fetchJWT(credentials) const token = await api.fetchJWT(credentials)
context.commit(authMut.SET_JWT_TOKEN, token) context.commit(authMut.SET_JWT_TOKEN, token)
......
import vueInstance from '@/main.ts'
export function nameSpacer (namespace) { export function nameSpacer (namespace: string) {
return function (commitType) { return function (commitType: string) {
return namespace + commitType return namespace + commitType
} }
} }
export function getObjectValueByPath (obj, path) { export function getObjectValueByPath (obj: any, path: string): any {
// credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621 // credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
if (!path || path.constructor !== String) return if (!path || path.constructor !== String) return
path = path.replace(/\[(\w+)\]/g, '.$1') // convert indexes to properties path = path.replace(/\[(\w+)\]/g, '.$1') // convert indexes to properties
...@@ -22,6 +23,11 @@ export function getObjectValueByPath (obj, path) { ...@@ -22,6 +23,11 @@ export function getObjectValueByPath (obj, path) {
return obj return obj
} }
interface GetSetPair {
get: () => any,
set: (val: object) => void
}
/** /**
* Use this method to generate a computed property accessing the store for a Vue instance. * Use this method to generate a computed property accessing the store for a Vue instance.
* The get method will return the value at this.$store.state.<path>. * The get method will return the value at this.$store.state.<path>.
...@@ -31,17 +37,29 @@ export function getObjectValueByPath (obj, path) { ...@@ -31,17 +37,29 @@ export function getObjectValueByPath (obj, path) {
* @param namespace to prepend the mutation type with * @param namespace to prepend the mutation type with
* @returns {*} * @returns {*}
*/ */
export function createComputedGetterSetter ({path, mutation, namespace}) { export function createComputedGetterSetter (
{path, mutation, namespace}:
{path: string, mutation: string, namespace:string}): GetSetPair {
return { return {
get () { get (): any {
return getObjectValueByPath(this.$store.state, path) return getObjectValueByPath(vueInstance.$store.state, path)
}, },
set (val) { set (val: object): void {
this.$store.commit(`${namespace ? namespace + '/' : ''}${mutation}`, val) vueInstance.$store.commit(`${namespace ? namespace + '/' : ''}${mutation}`, val)
} }
} }
} }
interface StateMapperItem {
name: string,
mutation: string,
path?: string
}
interface MappedState {
[key: string]: GetSetPair
}
/** /**
* Returns an object of generated computed getter/setter pairs. * Returns an object of generated computed getter/setter pairs.
* Can be used to quickly bind a stores state and corresponding setters to a vue component * Can be used to quickly bind a stores state and corresponding setters to a vue component
...@@ -49,12 +67,14 @@ export function createComputedGetterSetter ({path, mutation, namespace}) { ...@@ -49,12 +67,14 @@ export function createComputedGetterSetter ({path, mutation, namespace}) {
* @param pathPrefix if set, all items path will be prepended by the path prefix * @param pathPrefix if set, all items path will be prepended by the path prefix
* @param items array that contains objects {name, path, mutation} * @param items array that contains objects {name, path, mutation}
*/ */
export function mapStateToComputedGetterSetter ({namespace = '', pathPrefix = '', items = []}) { export function mapStateToComputedGetterSetter (
return items.reduce((acc, curr) => { {namespace = '', pathPrefix = '', items = []}:
{namespace: string, pathPrefix: string, items: StateMapperItem[]}): MappedState {
return items.reduce((acc: MappedState, curr) => {
// if no path is give, use name // if no path is give, use name
const itemPath = curr.path || curr.name const itemPath = curr.path || curr.name
const path = pathPrefix ? `${pathPrefix}.${itemPath}` : itemPath const path = pathPrefix ? `${pathPrefix}.${itemPath}` : itemPath
acc[curr.name] = createComputedGetterSetter({...curr, path, namespace}) acc[curr.name] = createComputedGetterSetter({mutation: curr.mutation, path, namespace})
return acc return acc
}, {}) }, {})
} }
...@@ -67,13 +87,13 @@ export function cartesian (a, b, ...c) { ...@@ -67,13 +87,13 @@ export function cartesian (a, b, ...c) {
} }
// flatten an array // flatten an array
export function flatten (list) { export function flatten (list: any[]): any[] {
return list.reduce( return list.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [] (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
) )
} }
export function objectifyArray (arr, key = 'pk') { export function objectifyArray<T> (arr: T[], key = 'pk'): {[key: string]: T} {
return arr.reduce((acc, curr) => { return arr.reduce((acc, curr) => {
acc[curr[key]] = curr acc[curr[key]] = curr
return acc return acc
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "esnext",
"module": "esnext", "module": "esnext",
"strict": true, "strict": false,
"jsx": "preserve", "jsx": "preserve",
"importHelpers": true, "importHelpers": true,
"moduleResolution": "node", "moduleResolution": "node",
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
] ]
}, },
"lib": [ "lib": [
"es2015", "es2017",
"dom", "dom",
"dom.iterable", "dom.iterable",
"scripthost" "scripthost"
......
...@@ -5,7 +5,8 @@ const projectRoot = path.resolve(__dirname) ...@@ -5,7 +5,8 @@ const projectRoot = path.resolve(__dirname)
module.exports = { module.exports = {
assetsDir: 'static', assetsDir: 'static',
devServer: { devServer: {
allowedHosts: ['localhost'] allowedHosts: ['localhost'],
host: 'localhost'
}, },
configureWebpack: { configureWebpack: {
resolve: { resolve: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment