<repo_name>wlingxiao/Flasky-FrontEnd<file_sep>/src/app/app.js
import angular from 'angular';
import '@uirouter/angularjs'

import 'bootstrap/dist/css/bootstrap.min.css'

import apiConfig from './api.config'
import routesConfig from './routes.config'

import './home'
import './login'
import './signup'
import './user'
import './post'
import './daily'

const app = angular.module('app', ['ui.router', 'home', 'login', 'signup', 'user', 'post', 'daily']);

app.config(apiConfig);
app.config(routesConfig);<file_sep>/src/app/user/users.service.js
export default function ($http, $httpParamSerializerJQLike) {
    this.listUsers = function (filter) {
        const usersUrl = '/users';
        return $http.get(usersUrl, {
            params: $httpParamSerializerJQLike(filter)
        })
    }
}<file_sep>/mock/posts.js
const faker = require('faker')
faker.locale = 'zh_CN';

module.exports = function () {
    const posts = {
        size: 100,
        data: []
    };
    for (let i = 0; i < 10; i++) {
        posts.data.push({
            id: i,
            title: faker.lorem.sentence(),
            content: faker.lorem.text(),
            'create_time': Date.parse(faker.date.past()),
            'image': faker.image.nature()
        })
    }
    return posts
}()<file_sep>/mock/db.js
module.exports = function () {
    return {
        posts: require('./posts'),
        users: require('./users')
    }
}<file_sep>/src/app/daily/index.js
import augular from 'angular'

import viewDailyDirective from './viewDaily.directive'
import dailyService from './daily.service'
import './news.css'
export default augular.module('daily', [])
    .directive('viewNews', viewDailyDirective)
    .service('dailyService', dailyService);<file_sep>/src/app/api.config.js
// api interceptor
import _ from 'lodash'

export default function ($httpProvider) {
    $httpProvider.interceptors.push(function ($q) {
        return {
            'request': function (config) {
                if (!_.endsWith(config.url, '.html')) {
                    config.url = '/api/v1' + config.url;
                }

                return config || $q.when(config);
            }
        }
    })
}<file_sep>/src/app/signup/index.js
import augular from 'angular'
import signupDirective from './signup.directive'
import {validateUsernameExist, validateEmailExist, hasSuccessOrError} from './validation.directive'

export default angular.module('signup', [])
    .directive('signUp', signupDirective)
    .filter('validateUsernameExist', validateUsernameExist)
    .filter('validateEmailExist', validateEmailExist)
    .filter('hasSuccessOrError', hasSuccessOrError);<file_sep>/src/app/user/datepicker.js
import $ from 'jquery'
import 'bootstrap-datepicker'
import 'bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css'


export const initDatePicker = function () {
    initDatePicker($('#last-login-time .input-daterange'));
    initDatePicker($('#sign-up-time .input-daterange'));

    function initDatePicker(jqeuryElement) {
        jqeuryElement.datepicker({
            format: 'yyyy-mm-dd',
            clearBtn: true,
            language: 'zh-CN',
            todayHighlight: true
        })
    }
};

export const clearDateRanger = function () {
    $('.input-daterange input').each(function () {
        $(this).datepicker('clearDates');
    });
};
<file_sep>/src/app/user/userManager.directive.js
import userManagerTpl from './user-manager.tpl.html'
import {initDatePicker, clearDateRanger} from './datepicker'

export default function (usersService, $log) {
    return {
        restrict: 'E',
        scope: {},
        template: userManagerTpl,
        link: function (scope, element) {
            initDatePicker()

            usersService.listUsers({}).then(function (response) {
                if (response['status'] === 200) {
                    transformUsers(response, scope)
                }
            })['catch'](function (response) {
                $log.error(response)
            });
        }
    }
}


function transformUsers(response, $scope) {
    const data = response['data'];
    $scope.totalItems = data['size'];
    const responseUsers = data['data'];
    $scope.totalPage = parseInt($scope.totalItems / 10) + 1;
    const users = [];
    for (let i = 0; i < responseUsers.length; i++) {
        const item = responseUsers[i];
        users.push({
            id: item['id'],
            username: item['username'],
            email: item['email'],
            signUpTime: item['sign_up_time'],
            lastVisitTime: item['last_visit_time']
        })
    }

    $scope.users = users;
}<file_sep>/src/app/home/home.directive.js
import indexTpl from './home.tpl.html'

export default function ($http, postsService, $log) {
    return {
        restrict: 'E',
        template: indexTpl,
        scope: {},
        link: function (scope, element) {
            postsService.listPosts().then(function (response) {
                if (response['status'] === 200) {
                    const responseData = response['data'];
                    scope.totalItems = responseData['size'];
                    scope.currentPage = 1;
                    scope.maxSize = 5;
                    scope.posts = transformPosts(responseData['data']);
                }
            })['catch'](function (error) {
                $log.error(error)
            })
        }
    }
}

function transformPosts(rawPosts) {
    const posts = [];
    rawPosts.map(function (post) {
        posts.push({
            id: post['id'],
            title: post['title'],
            summary: post['summary'],
            createTime: post['create_time'],
            image: post['image']

        })
    });
    return posts;
}<file_sep>/src/app/post/posts.service.js
export default function ($http, $httpParamSerializerJQLike) {
    const postUrl = "/posts";
    this.loadPosts = function (postId) {
        if (postId) {
            return $http.get(postUrl + "/" +postId);
        } else {
            return $http.get(postUrl);
        }
    }

    this.createPost = function (post) {
        return $http({
            method: 'POST',
            url: postUrl,
            headers: {'Content-Type': 'application/json;charset=UTF-8'}
        })
    }
}<file_sep>/src/app/daily/daily.service.js
export default function ($http, $httpParamSerializerJQLike) {

    const dailyNews = '/dailies/news';

    this.getNewsById = function (newsId) {
        return $http.get(dailyNews + '/' + newsId)
    };

}<file_sep>/src/app/home/index.js
import augular from 'angular'

import homeDirective from './home.directive'
import postsService from './posts.service'

import './home.css'

export default augular.module('home', [])
    .directive('home', homeDirective)
    .service('postsService', postsService);<file_sep>/README.md
#### run json mock server
`cd mock`  
`json-server db.js`

#### run posts server
`json-server --watch posts.json`<file_sep>/mock/README.md
#### run mock server
`json-server db.js`<file_sep>/src/app/signup/validation.directive.js
const validateUsernameExist = function ($http, $q) {
    return {
        require: 'ngModel',
        link: function (scope, element, attributes, ngModel) {
            ngModel.$asyncValidators.validateUsernameExist = function (modleValue, viewValue) {
                var validateUsernameUrl = '/auth/validate_username/';

                return $http({
                    method: 'POST',
                    url: validateUsernameUrl + modleValue
                }).then(function (response) {
                    if (response.data['code'] === 200) {
                        return true;
                    } else {
                        return $q.reject(response['msg']);
                    }
                })['catch'](function (response) {
                    return $q.reject('请求错误')
                });
            }
        }
    }
};

const validateEmailExist = function ($http, $q) {
    return {
        require: 'ngModel',
        link: function (scope, element, attributes, ngModel) {
            ngModel.$asyncValidators.validateEmailExist = function (modelValue, viewValue) {
                var validateEmailUrl = '/auth/validate_email/';

                return $http({
                    method: 'POST',
                    url: validateEmailUrl + modelValue
                }).then(function (response) {
                    if (response.data['code'] === 200) {
                        return true
                    } else {
                        return $q.reject(response['msg'])
                    }
                })['catch'](function (response) {
                    return $q.reject('请求错误');
                })
            }
        }
    }
};

const hasSuccessOrError = function () {
    return function (input, hasSuccess, hasError) {
        return input ? hasSuccess : hasError;
    }
};

export {validateUsernameExist, validateEmailExist, hasSuccessOrError}<file_sep>/src/app/routes.config.js
export default function ($stateProvider, $locationProvider) {
    $locationProvider.html5Mode(true);

    const homeState = {
        name: 'home',
        url: '/',
        template: '<home></home>'
    };

    const signUpState = {
        name: 'signUp',
        url: '/sign_up',
        template: '<sign-up></sign-up>'
    };

    const loginState = {
        name: 'login',
        url: '/login',
        template: '<login></login>'
    };

    const userState = {
        name: 'viewUser',
        url: '/view_user',
        template: '<user-manager></user-manager>'
    };

    const postState = {
        name: 'post',
        url: '/post/:postId',
        template: '<view-post post-id="{{ postId }}"></view-post>',
        controller: function ($scope, $stateParams) {
            $scope.postId = $stateParams.postId
        }
    };

    const createPostState = {
        name: 'createPost',
        url: '/create_post',
        template: '<create-post></create-post>'
    };

    const viewDailyState = {
        name: 'viewDaily',
        url: '/view_news/:newsId',
        template: '<view-news news-id="{{ newsId }}"></view-news>',
        controller: function ($scope, $stateParams) {
            $scope.newsId = $stateParams.newsId
        }
    }

    $stateProvider.state(homeState);
    $stateProvider.state(loginState);
    $stateProvider.state(signUpState);
    $stateProvider.state(userState);
    $stateProvider.state(postState);
    $stateProvider.state(createPostState);
    $stateProvider.state(viewDailyState);
}<file_sep>/src/app/post/comments.service.js
export default function ($http, $httpParamSerializerJQLike) {
    const postUrl = "/comments";
    this.loadComments = function (postId) {
        if (postId) {
            return $http.get(postUrl + "?postId=" + postId);
        } else {
            return $http.get(postUrl);
        }
    }
}<file_sep>/src/app/login/index.js
import augular from 'angular'
import 'angular-messages'
import loginDirective from './login.directive'

export default angular.module('login', ['ngMessages'])
    .directive('login', loginDirective)<file_sep>/src/app/post/commentToUser.directive.js
import commnetToUserTpl from './comment-to-user.tpl.html'

export default function () {
    return function () {
        return {
            replace: true,
            scope: false,
            restrict: 'E',
            template: commnetToUserTpl,
            link: function (scope, element) {

            }
        }
    }
}