From b3f1408739a00d9e683fbb97ceb5cefc4f292dbc Mon Sep 17 00:00:00 2001
From: Zamil Majdy <z.majdy1996@gmail.com>
Date: Sun, 9 Apr 2017 16:56:26 +0700
Subject: [PATCH] Implement JS fetch for upload from library

---
 assets/js/Dashboard.jsx                |  2 +-
 assets/js/VacancyPage.jsx              | 40 +++++++++++++-------------
 assets/js/components/RegisterModal.jsx | 25 ++++------------
 assets/js/index.jsx                    |  8 ++++--
 assets/js/lib/Server.jsx               | 31 ++++++++++++++------
 assets/js/lib/Storage.jsx              | 17 +++++++++--
 core/serializers/accounts.py           | 10 +++----
 core/views/accounts.py                 | 14 ++++-----
 8 files changed, 80 insertions(+), 67 deletions(-)

diff --git a/assets/js/Dashboard.jsx b/assets/js/Dashboard.jsx
index 513a5b8c..634fdefa 100755
--- a/assets/js/Dashboard.jsx
+++ b/assets/js/Dashboard.jsx
@@ -11,7 +11,7 @@ export default class Dashboard extends React.Component {
 
   render = () => (
     <div>
-      <TopMenu  />
+      <TopMenu />
       {this.props.children}
     </div>
   )
diff --git a/assets/js/VacancyPage.jsx b/assets/js/VacancyPage.jsx
index 27abae5b..cb25fd82 100644
--- a/assets/js/VacancyPage.jsx
+++ b/assets/js/VacancyPage.jsx
@@ -14,30 +14,30 @@ export default class VacancyPage extends React.Component {
       password: '',
       errorFlag: false,
       vacancies: [],
+      student: false,
     };
+    Storage.getUserData().then(r => this.setState({ student: r.student }));
+
     this.handleItemClick = this.handleItemClick.bind(this);
   }
 
   handleItemClick = (e, { name }) => this.setState({ activeItem: name });
 
-  render() {
-    const student = Storage.get('user-data').student;
-    return (
-  <div className="halamanLowongan">
-      <Tabs selected={0}>
-        <Pane label="Semua Lowongan" >
-          <VacancyList key={1} studentId={student.id}  url="/vacancies/" />
-        </Pane>
-        <Pane label="Lamaran saya" >
-          <VacancyList key={2} status="Batal" studentId={student.id} url={`/students/${student.id}/applied-vacancies/`} />
-        </Pane>
-        <Pane label="Lamaran Ditandai" >
-          <VacancyList key={3} studentId={student.id}  url={`/students/${student.id}/bookmarked-vacancies/`} />
-        </Pane>
-      </Tabs>
-
-  </div>
-
-    );
-  }
+  render = () => (
+    this.state.student && (
+      <div className="halamanLowongan">
+        <Tabs selected={0}>
+          <Pane label="Semua Lowongan" >
+            <VacancyList key={1} studentId={this.state.student.id} url="/vacancies/" />
+          </Pane>
+          <Pane label="Lamaran saya" >
+            <VacancyList key={2} status="Batal" studentId={this.state.student.id} url={`/students/${this.state.student.id}/applied-vacancies/`} />
+          </Pane>
+          <Pane label="Lamaran Ditandai" >
+            <VacancyList key={3} studentId={this.state.student.id} url={`/students/${this.state.student.id}/bookmarked-vacancies/`} />
+          </Pane>
+        </Tabs>
+      </div>
+    )
+  );
 }
diff --git a/assets/js/components/RegisterModal.jsx b/assets/js/components/RegisterModal.jsx
index 06d91044..43631df1 100644
--- a/assets/js/components/RegisterModal.jsx
+++ b/assets/js/components/RegisterModal.jsx
@@ -32,27 +32,12 @@ export default class RegisterModal extends React.Component {
 
   handleSubmit = (e) => {
     e.preventDefault();
-    const form = new FormData();
-    Object.keys(this.state).map(k => form.append(k, this.state[k]));
 
-    const data = {
-      'X-CSRFToken': Server.getCookie('csrftoken'),
-      mode: 'no-cors',
-      method: 'POST',
-      body: form,
-      credentials: 'same-origin',
-    };
-
-    fetch('/api/register/', data)
-      .then((response) => {
-        if (response.status < 200 || response.status > 399) throw response.json();
-        else return response.json();
-      })
-      .then((response) => {
-        alert('Akun berhasil dibuat :)');
-        Storage.set('user-data', response);
-        browserHistory.push('/home');
-      }, error => error.then(r => alert(JSON.stringify(r))));
+    Server.submit('/register/', this.state).then((response) => {
+      alert('Akun berhasil dibuat :)');
+      Storage.set('user-data', response);
+      browserHistory.push('/home');
+    }, error => error.then(r => alert(JSON.stringify(r))));
   };
 
   render = () => (
diff --git a/assets/js/index.jsx b/assets/js/index.jsx
index cc866085..18cb7f6a 100644
--- a/assets/js/index.jsx
+++ b/assets/js/index.jsx
@@ -28,9 +28,12 @@ export default class App extends React.Component {
     Server.isLoggedIn() || replace({ pathname: '/login' })
   );
 
-  handleHome= (nextState, replace) => {
+  handleHome= (nextState, replace, cb) => {
     if (Server.isLoggedIn()) {
-      Storage.get('user-data').student ? replace({pathname: '/lowongan'}) : replace({pathname: '/profile'});
+      Storage.getUserData().then((data) => {
+        const next = data.student ? '/lowongan' : '/profile';
+        replace({ pathname: next }); cb();
+      });
     } else {
       replace({ pathname: '/login' });
     }
@@ -40,7 +43,6 @@ export default class App extends React.Component {
     <Router history={browserHistory}>
       <Route path="/login" component={Login} />
       <Route component={Dashboard} onEnter={this.handleAuth}>
-        <Route path="/" component={VacancyPage} />
         <Route path="/profile" component={Profile} />
         <Route path="/lowongan" component={VacancyPage} />
         <Route path="/users" component={Profile} />
diff --git a/assets/js/lib/Server.jsx b/assets/js/lib/Server.jsx
index b9c7e142..6f912c84 100644
--- a/assets/js/lib/Server.jsx
+++ b/assets/js/lib/Server.jsx
@@ -17,8 +17,23 @@ export default class Server {
     return null;
   }
 
+  static submit(path, data, method = 'POST', useCache = false) {
+    const form = new FormData();
+    /* istanbul ignore next */
+    Object.keys(data).map(k => form.append(k, this.state[k]));
+
+    const requestData = {
+      'X-CSRFToken': Server.getCookie('csrftoken'),
+      mode: 'no-cors',
+      method: 'POST',
+      body: form,
+      credentials: 'same-origin',
+    };
+
+    return this.handleFetchRequest(requestData, path, useCache);
+  }
+
   static sendRequest(path, method, data, useCache = false) {
-    const url = `/api${path}`;
     const csrftoken = this.getCookie('csrftoken');
     const headers = {
       'content-type': 'application/json',
@@ -32,7 +47,11 @@ export default class Server {
       credentials: 'same-origin',
     };
 
-    //  noinspection JSUnresolvedFunction
+    return this.handleFetchRequest(requestData, path, useCache);
+  }
+
+  static handleFetchRequest(requestData, path, useCache) {
+    const url = `/api${path}`;
     const request = fetch(url, requestData);
 
     /* istanbul ignore next */
@@ -43,12 +62,8 @@ export default class Server {
       const contentType = response.headers.get('content-type');
       const result = contentType && contentType.indexOf('application/json') !== -1 ? response.json() : response.text();
 
-      if (response.status < 200 || response.status > 399) {
-        throw result;
-      }
-      else {
-        return result;
-      }
+      if (response.status < 200 || response.status > 399) throw result;
+      else return result;
     });
 
     /* istanbul ignore next */
diff --git a/assets/js/lib/Storage.jsx b/assets/js/lib/Storage.jsx
index 0e28781e..cb2a24ce 100644
--- a/assets/js/lib/Storage.jsx
+++ b/assets/js/lib/Storage.jsx
@@ -1,3 +1,5 @@
+import Server from './../lib/Server';
+
 /** Session Storage Polyfill */
 
 /* eslint-disable */
@@ -120,14 +122,23 @@ polyfil();
 
 export default class Storage {
   static get(key) {
-    return JSON.parse(sessionStorage.getItem(key));
+    return JSON.parse(localStorage.getItem(key));
   }
 
   static set(key, value) {
-    return sessionStorage.setItem(key, JSON.stringify(value));
+    return localStorage.setItem(key, JSON.stringify(value));
   }
 
   static clear() {
-    return sessionStorage.clear();
+    return localStorage.clear();
+  }
+
+  static getUserData() {
+    const data = Storage.get('user-data');
+    /* istanbul ignore next */
+    return (data != null) ? Promise.resolve(data) : Server.get('/users/me/').then((response) => {
+      Storage.set(('user-data'), response);
+      return response;
+    });
   }
 }
diff --git a/core/serializers/accounts.py b/core/serializers/accounts.py
index 986f4c4f..63f67d1a 100644
--- a/core/serializers/accounts.py
+++ b/core/serializers/accounts.py
@@ -4,14 +4,14 @@ from rest_framework import serializers
 from core.models.accounts import Supervisor, Company, Student
 
 
-class UserSerializer(serializers.HyperlinkedModelSerializer):
+class BasicUserSerializer(serializers.HyperlinkedModelSerializer):
     class Meta:
         model = User
         fields = ('url', 'username', 'email', 'is_staff')
 
 
 class StudentSerializer(serializers.ModelSerializer):
-    user = UserSerializer()
+    user = BasicUserSerializer()
     name = serializers.ReadOnlyField()
 
     class Meta:
@@ -20,7 +20,7 @@ class StudentSerializer(serializers.ModelSerializer):
 
 
 class CompanySerializer(serializers.ModelSerializer):
-    user = UserSerializer()
+    user = BasicUserSerializer()
     name = serializers.ReadOnlyField()
 
     class Meta:
@@ -29,7 +29,7 @@ class CompanySerializer(serializers.ModelSerializer):
 
 
 class SupervisorSerializer(serializers.ModelSerializer):
-    user = UserSerializer()
+    user = BasicUserSerializer()
     name = serializers.ReadOnlyField()
 
     class Meta:
@@ -37,7 +37,7 @@ class SupervisorSerializer(serializers.ModelSerializer):
         fields = '__all__'
 
 
-class LoginSerializer(serializers.HyperlinkedModelSerializer):
+class UserSerializer(serializers.HyperlinkedModelSerializer):
     company = CompanySerializer()
     supervisor = SupervisorSerializer()
     student = StudentSerializer()
diff --git a/core/views/accounts.py b/core/views/accounts.py
index 4afa426a..3f75bb29 100644
--- a/core/views/accounts.py
+++ b/core/views/accounts.py
@@ -11,8 +11,8 @@ from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_409_CONFLICT
 
 from core.lib.permissions import IsAdminOrStudent, IsAdminOrSelfOrReadOnly, IsAdminOrCompany, IsAdminOrSupervisor
 from core.models.accounts import Student, Company, Supervisor
-from core.serializers.accounts import UserSerializer, StudentSerializer, CompanySerializer, SupervisorSerializer, \
-    LoginSerializer, RegisterSerializer
+from core.serializers.accounts import BasicUserSerializer, StudentSerializer, CompanySerializer, SupervisorSerializer, \
+    UserSerializer, RegisterSerializer
 
 
 class UserViewSet(viewsets.ModelViewSet):
@@ -26,7 +26,7 @@ class UserViewSet(viewsets.ModelViewSet):
         Get current user's details
         """
         user = self.request.user
-        serializer = UserSerializer(user, context={"request": request})
+        serializer = BasicUserSerializer(user, context={"request": request})
         return Response(serializer.data)
 
     def get_permissions(self):
@@ -62,7 +62,7 @@ class SupervisorViewSet(viewsets.ModelViewSet):
 
 class LoginViewSet(viewsets.GenericViewSet):
     permission_classes = (AllowAny, )
-    serializer_class = LoginSerializer
+    serializer_class = UserSerializer
     queryset = User.objects.all()
 
     def create(self, request):
@@ -115,9 +115,9 @@ class LoginViewSet(viewsets.GenericViewSet):
                             nip=resp.get("kodeidentitas")
                         )
                         supervisor.save()
-                    serializer = LoginSerializer(user, context={'request': request})
+                    serializer = UserSerializer(user, context={'request': request})
                     return Response(serializer.data, status=status.HTTP_201_CREATED)
-                serializer = LoginSerializer(user, context={'request': request})
+                serializer = UserSerializer(user, context={'request': request})
                 return Response(serializer.data, status=status.HTTP_200_OK)
             else:
                 return Response(status=status.HTTP_401_UNAUTHORIZED)
@@ -125,7 +125,7 @@ class LoginViewSet(viewsets.GenericViewSet):
             user = authenticate(username = username, password = password)
             if user is not None:
                 login(request, user)
-                serializer = LoginSerializer(user, context={'request': request})
+                serializer = UserSerializer(user, context={'request': request})
                 return Response(serializer.data, status=status.HTTP_200_OK)
             else:
                 return Response(status=status.HTTP_401_UNAUTHORIZED)
-- 
GitLab