├── .gitignore ├── LICENSE ├── README.md ├── bower.json ├── config ├── env.js ├── jest │ ├── CSSStub.js │ └── FileStub.js ├── paths.js ├── polyfills.js ├── webpack.config.dev.js └── webpack.config.prod.js ├── content └── sass │ ├── _all.scss │ ├── _animation.scss │ ├── _color.scss │ ├── _common.scss │ ├── _components.scss │ ├── _fonts.scss │ ├── _grids.scss │ ├── _login-rtl.scss │ ├── _media.scss │ ├── _typography.scss │ ├── login.scss │ └── style.scss ├── debug.log ├── docs ├── content │ ├── css │ │ ├── basic.min.css │ │ ├── bootstrap-rtl.min.css │ │ ├── dropzone-styler.css │ │ ├── dropzone.min.css │ │ ├── filepicker.css │ │ ├── metisMenu.min.css │ │ ├── mystyle.css │ │ ├── react-metismenu-standart.min.css │ │ ├── redactor.min.css │ │ ├── sb-admin-2.min.css │ │ └── style.css │ ├── fonts │ │ ├── BYekan.eot │ │ ├── BYekan.ttf │ │ ├── BYekan.woff │ │ ├── FontAwesome.otf │ │ ├── Lato-Bold.woff2 │ │ ├── Lato-Light.woff2 │ │ ├── Lato-Regular.woff2 │ │ ├── OpenSans-Regular.eot │ │ ├── OpenSans-Regular.svg │ │ ├── OpenSans-Regular.ttf │ │ ├── OpenSans-Regular.woff │ │ ├── Shabnam-Bold.eot │ │ ├── Shabnam-Bold.ttf │ │ ├── Shabnam-Bold.woff │ │ ├── Shabnam-Light.eot │ │ ├── Shabnam-Light.ttf │ │ ├── Shabnam-Light.woff │ │ ├── Shabnam.eot │ │ ├── Shabnam.ttf │ │ ├── Shabnam.woff │ │ ├── bootstrap │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── images │ │ ├── DashboardDemo.png │ │ ├── LoginDemo.png │ │ ├── favicon.png │ │ └── login-bg.jpg │ └── js │ │ ├── bootstrap.min.js │ │ ├── jquery-migrate-1.4.1.min.js │ │ ├── jquery.min.js │ │ ├── metisMenu.min.js │ │ ├── myred.js │ │ ├── redactor-crossorigin-upload.js │ │ ├── redactor.min.js │ │ └── sb-admin-2.min.js ├── favicon.ico ├── index.html └── static │ ├── css │ ├── main.80540410.css │ └── main.80540410.css.map │ └── js │ ├── main.d5330913.js │ └── main.d5330913.js.map ├── gulpfile.js ├── package.json ├── public ├── favicon.ico └── index.html ├── scripts ├── build.js ├── start.js └── test.js ├── src ├── actions │ ├── action-types.js │ ├── article-actions.js │ ├── dashboard-actions.js │ ├── job-actions.js │ ├── jobowner-actions.js │ ├── login-actions.js │ └── service-actions.js ├── api │ ├── article-api.js │ ├── article-list-container.js │ ├── identity-api.js │ ├── jobowner-api.js │ ├── service-api.js │ └── urls.js ├── components │ ├── containers │ │ ├── article-container.js │ │ ├── article-list-container.js │ │ ├── dashboard-container.js │ │ ├── jobownerJob-container.js │ │ ├── login-container.js │ │ ├── main-layout-container.js │ │ ├── page-layout-container.js │ │ ├── service-container.js │ │ └── service-list-container.js │ ├── layouts │ │ ├── header.js │ │ ├── main-layout.js │ │ ├── menu.js │ │ ├── page-layout.js │ │ └── panel-layout.js │ └── views │ │ ├── article.js │ │ ├── dashboard.js │ │ ├── jobownerJob.js │ │ ├── login.js │ │ ├── service.js │ │ └── simple-list.js ├── helpers │ ├── bdate-input.js │ ├── bfile-input.js │ ├── bmulti-input.js │ ├── bselect-input.js │ ├── btags-input.js │ ├── icons.js │ ├── sweet-alert.js │ └── timer.js ├── index.js ├── models │ ├── article.js │ ├── baseModel.js │ ├── jobownerJob.js │ └── service.js ├── reducers │ ├── article-reducer.js │ ├── dashboard-layout-reducer.js │ ├── index.js │ ├── jobowner-reducer.js │ ├── login-reducer.js │ └── service-reducer.js ├── router.js ├── store.js └── validations │ ├── bvalidation.js │ └── login-validation.js ├── yarn-error.log └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # dependencies 7 | bower_components 8 | 9 | # sass cache 10 | .sass-cache 11 | 12 | # public content 13 | public/content 14 | 15 | # testing 16 | coverage 17 | 18 | # production 19 | build 20 | 21 | # misc 22 | .DS_Store 23 | .env 24 | npm-debug.log 25 | npm-debug.log* 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 mohammadreza berneti 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## React Admin is SB Admin v2.0 that rewritten in React.js based on [Redux](http://redux.js.org) 2 | 3 | This project is a port of the famous Free Admin Bootstrap Theme [SB Admin v2.0](http://startbootstrap.com/template-overviews/sb-admin-2/) to React.js Theme based on [Create React App](https://github.com/facebookincubator/create-react-app) using ES6 & Webpack. 4 | 5 | ## [Demo](https://mberneti.github.io/ReactAdmin/) 6 | 7 | Login Demo 8 | 9 | ## Available Scripts 10 | 11 | No configuration or complicated folder structures, just the files you need to build your app.
12 | Once the installation is done, you can run some commands inside the project folder: 13 | 14 | ## Installation 15 | #### 1. Clone this project or Download that ZIP file 16 | 17 | ```sh 18 | $ git clone https://github.com/mberneti/react-admin.git 19 | ``` 20 | 21 | #### 2. Make sure you have [npm](https://www.npmjs.org/) installed globally 22 | 23 | More details [here](https://nodejs.org/en/download/) 24 | 25 | 26 | #### 3. On the command prompt run the following commands 27 | 28 | ```sh 29 | $ cd `project-directory` 30 | ``` 31 | ```sh 32 | $ npm install 33 | ``` 34 | 35 | ### `npm start` or `yarn start` 36 | 37 | Runs the app in development mode.
38 | Open [http://localhost:3000/ReactAdmin/](http://localhost:3000/ReactAdmin/) to view it in the browser. 39 | 40 | Note: The page will reload if you make edits.
41 | 42 | Login Demo 43 | 44 | Now you have two choices to make: 45 | #### 1. Login as an Admin with `11111` verification key 46 | 47 | #### 2 Or Login as a User with `12345` verification key 48 | 49 | ### `npm test` or `yarn test` 50 | 51 | Runs the test watcher in an interactive mode.
52 | By default, runs tests related to files changed since the last commit. 53 | 54 | [Read more about testing.](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#running-tests) 55 | 56 | ### `npm run build` or `yarn build` 57 | 58 | Builds the app for production to the `build` folder.
59 | It correctly bundles React in production mode and optimizes the build for the best performance. 60 | 61 | The build is minified and the filenames include the hashes.
62 | By default, it also [includes a service worker](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app) so that your app loads from local cache on future visits. 63 | 64 | Your app is ready to be deployed. 65 | 66 | ## Features 67 | * Bootstrap CSS Framework 68 | * Dropzone File Uploader Example 69 | * SweetAlert Plugin 70 | * React-Select (A Multi Select control built with and for React JS) 71 | * Jalaali DatePicker 72 | * Daynamic Complex Form Examples (with text, dropdown, fileuploader and ...) 73 | * Real World Example Of Authentication Using JWT 74 | * Based On React & Redux 75 | 76 | 77 | ## From [mberneti](https://twitter.com/mberneti) 78 | Enjoy! 79 | I'm always happy to hear your feedback. 80 | 81 | ## Contributing 82 | Contributions are **welcome** and will be fully **credited**. 83 | I'd be happy to accept PRs for that. 84 | 85 | ## License 86 | 87 | Copyright (c) 2016 [mberneti](https://twitter.com/mberneti) Inc. and individual contributors. Licensed under MIT license, see [LICENSE](LICENSE) for the full license. 88 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactApp", 3 | "description": "", 4 | "main": "", 5 | "authors": [ 6 | "mohammaadreza berneti " 7 | ], 8 | "license": "MIT", 9 | "homepage": "index", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "font-awesome": "^4.7.0", 20 | "bootstrap-sass": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 2 | // injected into the application via DefinePlugin in Webpack configuration. 3 | 4 | var REACT_APP = /^REACT_APP_/i; 5 | 6 | function getClientEnvironment(publicUrl) { 7 | return Object 8 | .keys(process.env) 9 | .filter(key => REACT_APP.test(key)) 10 | .reduce((env, key) => { 11 | env['process.env.' + key] = JSON.stringify(process.env[key]); 12 | return env; 13 | }, { 14 | // Useful for determining whether we’re running in production mode. 15 | // Most importantly, it switches React into the correct mode. 16 | 'process.env.NODE_ENV': JSON.stringify( 17 | process.env.NODE_ENV || 'development' 18 | ), 19 | // Useful for resolving the correct path to static assets in `public`. 20 | // For example, . 21 | // This should only be used as an escape hatch. Normally you would put 22 | // images into the `src` and `import` them in code to get their paths. 23 | 'process.env.PUBLIC_URL': JSON.stringify(publicUrl) 24 | }); 25 | } 26 | 27 | module.exports = getClientEnvironment; 28 | -------------------------------------------------------------------------------- /config/jest/CSSStub.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /config/jest/FileStub.js: -------------------------------------------------------------------------------- 1 | module.exports = "test-file-stub"; 2 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | 4 | // Make sure any symlinks in the project folder are resolved: 5 | // https://github.com/facebookincubator/create-react-app/issues/637 6 | var appDirectory = fs.realpathSync(process.cwd()); 7 | function resolveApp(relativePath) { 8 | return path.resolve(appDirectory, relativePath); 9 | } 10 | 11 | // We support resolving modules according to `NODE_PATH`. 12 | // This lets you use absolute paths in imports inside large monorepos: 13 | // https://github.com/facebookincubator/create-react-app/issues/253. 14 | 15 | // It works similar to `NODE_PATH` in Node itself: 16 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 17 | 18 | // We will export `nodePaths` as an array of absolute paths. 19 | // It will then be used by Webpack configs. 20 | // Jest doesn’t need this because it already handles `NODE_PATH` out of the box. 21 | 22 | var nodePaths = (process.env.NODE_PATH || '') 23 | .split(process.platform === 'win32' ? ';' : ':') 24 | .filter(Boolean) 25 | .map(resolveApp); 26 | 27 | // config after eject: we're in ./config/ 28 | module.exports = { 29 | appBuild: resolveApp('build'), 30 | appPublic: resolveApp('public'), 31 | appHtml: resolveApp('public/index.html'), 32 | appIndexJs: resolveApp('src/index.js'), 33 | appPackageJson: resolveApp('package.json'), 34 | appSrc: resolveApp('src'), 35 | testsSetup: resolveApp('src/setupTests.js'), 36 | appNodeModules: resolveApp('node_modules'), 37 | ownNodeModules: resolveApp('node_modules'), 38 | nodePaths: nodePaths 39 | }; 40 | -------------------------------------------------------------------------------- /config/polyfills.js: -------------------------------------------------------------------------------- 1 | if (typeof Promise === 'undefined') { 2 | // Rejection tracking prevents a common issue where React gets into an 3 | // inconsistent state due to an error, but it gets swallowed by a Promise, 4 | // and the user has no idea what causes React's erratic future behavior. 5 | require('promise/lib/rejection-tracking').enable(); 6 | window.Promise = require('promise/lib/es6-extensions.js'); 7 | } 8 | 9 | // fetch() polyfill for making API calls. 10 | require('whatwg-fetch'); 11 | 12 | // Object.assign() is commonly used with React. 13 | // It will use the native implementation if it's present and isn't buggy. 14 | Object.assign = require('object-assign'); 15 | -------------------------------------------------------------------------------- /content/sass/_all.scss: -------------------------------------------------------------------------------- 1 | @import "../../bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss"; 2 | @import "_animation.scss"; 3 | @import "_grids.scss"; 4 | @import "_typography.scss"; 5 | @import "_color.scss"; 6 | @import "_common.scss"; 7 | @import "_media.scss"; 8 | @import "_components.scss"; 9 | @import "login.scss"; 10 | @import "_login-rtl.scss"; -------------------------------------------------------------------------------- /content/sass/_animation.scss: -------------------------------------------------------------------------------- 1 | @import "_fonts.scss"; 2 | @keyframes arrow { 3 | 0% { 4 | padding-right: 4px; 5 | } 6 | 100% { 7 | padding-right: 8px; 8 | } 9 | } 10 | 11 | 12 | /*----------- svg animation ---------*/ 13 | 14 | .path { 15 | stroke-dasharray: 1000; 16 | stroke-dashoffset: 1000; 17 | animation: dash 5s linear alternate infinite; 18 | } 19 | 20 | @keyframes dash { 21 | from { 22 | stroke-dashoffset: 1000; 23 | } 24 | to { 25 | stroke-dashoffset: 0; 26 | } 27 | } 28 | 29 | 30 | /*-----------------*/ 31 | 32 | 33 | /*--------button loading---------*/ 34 | 35 | @keyframes blink { 36 | 0% { 37 | opacity: .2; 38 | } 39 | 20% { 40 | opacity: 1; 41 | } 42 | 100% { 43 | opacity: .2; 44 | } 45 | } 46 | 47 | button.active-loading { 48 | > span { 49 | display: none; 50 | } 51 | div { 52 | span { 53 | display: inline-block; 54 | font-size: 2em; 55 | } 56 | span { 57 | animation-name: blink; 58 | animation-duration: 1.4s; 59 | animation-iteration-count: infinite; 60 | animation-fill-mode: both; 61 | width: 4px; 62 | height: 4px; 63 | margin: 0 1px; 64 | display: inline-block; 65 | background: #fff; 66 | border-radius: 100%; 67 | } 68 | span:nth-child(2) { 69 | animation-delay: .2s; 70 | } 71 | span:nth-child(3) { 72 | animation-delay: .4s; 73 | } 74 | } 75 | } 76 | 77 | button.deactive-loading { 78 | div { 79 | display: none; 80 | } 81 | } 82 | 83 | /*-----------------*/ -------------------------------------------------------------------------------- /content/sass/_color.scss: -------------------------------------------------------------------------------- 1 | $primary-color: #042590; 2 | $dark-gray: #222222; 3 | $light-gray: #d9d9d9; 4 | $lighter-gray: #F1F1F1; 5 | 6 | $back-green:#41AB6B; 7 | $back-yellow:#EEA303; 8 | 9 | $back-header:#E6AE48; 10 | /*$back-header:#2980b9;*/ 11 | $back-nav:#EEA303; 12 | /*$back-nav:#3498db;*/ 13 | 14 | $color-light-text: #5e5e5e; 15 | $color-dark-text: #2A2A2A; 16 | 17 | 18 | $color-light-text-hex: #5e5e5e; 19 | $color-dark-text-hex: #2A2A2A; 20 | 21 | 22 | $color-nav-gray:$color-light-text; 23 | /*$color-nav-gray:#dcdcdc;*/ 24 | 25 | $color-border-light: #eee; 26 | $color-border-dark: #e1e1e1; 27 | 28 | $color-back-copyright:#16202A; -------------------------------------------------------------------------------- /content/sass/_common.scss: -------------------------------------------------------------------------------- 1 | 2 | /*black command white*/ 3 | .bw { 4 | -webkit-filter: grayscale(100%); 5 | filter: grayscale(100%); 6 | filter: gray; 7 | filter: url("data:image/svg+xml;utf8,#greyscale"); 8 | } 9 | /* --------------------------- */ 10 | *::-moz-selection { 11 | background-color: rgba(22, 144, 147, 0.15); 12 | } 13 | 14 | *::selection { 15 | background-color: rgba(22, 144, 147, 0.15); 16 | } 17 | 18 | .rotate { 19 | -moz-transform: rotate(-180deg); 20 | -ms-transform: rotate(-180deg); 21 | -o-transform: rotate(-180deg); 22 | -webkit-transform: rotate(-180deg); 23 | transform: rotate(-180deg); 24 | } 25 | 26 | .text-center { 27 | text-align: center; 28 | } 29 | 30 | .text-left { 31 | text-align: left; 32 | } 33 | 34 | .text-right { 35 | text-align: right; 36 | } 37 | 38 | .text-ltr { 39 | direction: ltr; 40 | } 41 | 42 | .text-rtl { 43 | direction: rtl; 44 | } 45 | 46 | 47 | /*make an html svg object also a clickable link*/ 48 | 49 | a.svg { 50 | position: relative; 51 | display: inline-block; 52 | } 53 | 54 | a.svg:after { 55 | content: ""; 56 | position: absolute; 57 | top: 0; 58 | right: 0; 59 | bottom: 0; 60 | left: 0; 61 | } 62 | 63 | .hidden { 64 | display: none; 65 | } 66 | 67 | 68 | 69 | .no-gutter > [class*='col-'] { 70 | padding-right:0; 71 | padding-left:0; 72 | } 73 | 74 | .clear{ 75 | clear:both; 76 | } 77 | 78 | .rotate-y { 79 | -moz-transform: rotateY( 180deg ); 80 | -ms-transform: rotateY( 180deg ); 81 | -o-transform: rotateY( 180deg ); 82 | -webkit-transform: rotateY( 180deg ); 83 | transform: rotateY( 180deg ); 84 | } 85 | 86 | /*input { 87 | -moz-box-shadow: none!important; 88 | -webkit-box-shadow: none!important; 89 | box-shadow: none!important; 90 | }*/ 91 | .no-border{ 92 | border:none!important; 93 | } 94 | .responsive-img{ 95 | width:100%; 96 | } 97 | 98 | .relative{ 99 | position:relative; 100 | } 101 | 102 | .disable-btn{ 103 | opacity:.3; 104 | a{ 105 | cursor:default!important; 106 | } 107 | } 108 | .center-position{ 109 | position: absolute; 110 | left: 50%; 111 | top: 50%; 112 | -moz-transform: translate(-50%, -50%); 113 | -ms-transform: translate(-50%, -50%); 114 | -o-transform: translate(-50%, -50%); 115 | -webkit-transform: translate(-50%, -50%); 116 | transform: translate(-50%, -50%); 117 | -moz-transition: 2s ease; 118 | -o-transition: 2s ease; 119 | -webkit-transition: 2s ease; 120 | transition: 2s ease; 121 | } 122 | 123 | 124 | 125 | /** 126 | * Computes a top-shadow for a card effect. 127 | * 128 | * @param {Number} $depth - depth level 129 | * 130 | * @return {List} 131 | */ 132 | @function top-shadow($depth) { 133 | $primary-offset: nth(1.5 3 10 14 19, $depth) * 1px; 134 | $blur: nth(1.5 3 10 14 19, $depth) * 4px; 135 | $color: rgba(black, nth(.12 .16 .19 .25 .30, $depth)); 136 | 137 | @return 0 $primary-offset $blur $color; 138 | } 139 | 140 | /** 141 | * Computes a bottom-shadow for a card effect. 142 | * 143 | * @param {Number} $depth - depth level 144 | * 145 | * @return {List} 146 | */ 147 | @function bottom-shadow($depth) { 148 | $primary-offset: nth(1.5 3 6 10 15, $depth) * 1px; 149 | $blur: nth(1 3 3 5 6, $depth) * 4px; 150 | $color: rgba(black, nth(.24 .23 .23 .22 .22, $depth)); 151 | 152 | @return 0 $primary-offset $blur $color; 153 | } 154 | 155 | /** 156 | * Gives a card depth effect. 157 | * 158 | * @param {Number} $depth - depth level (between 1 and 5) 159 | * 160 | * @link http://www.google.com/design/spec/layout/layout-principles.html#layout-principles-dimensionality Google Design 161 | * 162 | * @requires {function} top-shadow 163 | * @requires {function} bottom-shadow 164 | */ 165 | @mixin card($depth) { 166 | @if $depth < 1 { 167 | box-shadow: none; 168 | } @else if $depth > 5 { 169 | @warn "Invalid $depth `#{$depth}` for mixin `card`."; 170 | } @else { 171 | box-shadow: bottom-shadow($depth), top-shadow($depth); 172 | } 173 | } 174 | 175 | .rtl { 176 | direction: rtl; 177 | } 178 | 179 | .ltr { 180 | direction: ltr; 181 | } 182 | 183 | 184 | .panel,.panel-heading,.form-control,.dropdown-menu{ 185 | border-radius: 0; 186 | } 187 | .form-control:focus{ 188 | box-shadow: none; 189 | border-color: #9c9c9c; 190 | } 191 | 192 | .form-control{ 193 | box-shadow: none; 194 | border-color: #ddd; 195 | } 196 | .dz-hidden-input{ 197 | position: relative!important; 198 | } -------------------------------------------------------------------------------- /content/sass/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import "../../bower_components/font-awesome/scss/font-awesome.scss"; 2 | 3 | $open-sans: "BBlog Open Sans", sans-serif; 4 | $yekan: "BBlog BYekan",'Lato', Tahoma; 5 | $shabnam: "shabnam",'Lato', Tahoma; 6 | /*$lato:'Lato', Calibri, Arial, sans-serif;*/ 7 | $lato:'Lato', $yekan; 8 | $font-vazir:"BBlog Vazir"; 9 | $font-droid:"BBlog Droid"; 10 | 11 | @font-face { 12 | font-family: "BBlog Open Sans"; 13 | font-style: normal; 14 | font-weight: normal; 15 | src: url("../fonts/OpenSans-Regular.eot?#iefix") format("embedded-opentype"), url("../fonts/OpenSans-Regular.woff") format("woff"), url("../fonts/OpenSans-Regular.ttf") format("truetype"), url("../fonts/OpenSans-Regular.svg#OpenSansRegular") format("svg"); 16 | } 17 | 18 | @font-face { 19 | font-family: "BBlog BYekan"; 20 | src: url("../fonts/BYekan.eot?#") format("eot"), url("../fonts/BYekan.woff") format("woff"), url("../fonts/BYekan.ttf") format("truetype"); 21 | } 22 | 23 | /* ----- Lato ----------------------------------------------------- */ 24 | /* latin-ext */ 25 | @font-face { 26 | font-family: 'Lato'; 27 | font-style: normal; 28 | font-weight: 300; 29 | src: local('Lato Light'), local('Lato-Light'), url(../fonts/Lato-Light.woff2) format('woff2'); 30 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 31 | } 32 | /* latin */ 33 | @font-face { 34 | font-family: 'Lato'; 35 | font-style: normal; 36 | font-weight: 300; 37 | src: local('Lato Light'), local('Lato-Light'), url(../fonts/Lato-Light.woff2) format('woff2'); 38 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 39 | } 40 | /* latin-ext */ 41 | @font-face { 42 | font-family: 'Lato'; 43 | font-style: normal; 44 | font-weight: 400; 45 | src: local('Lato Regular'), local('Lato-Regular'), url(../fonts/Lato-Regular.woff2) format('woff2'); 46 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 47 | } 48 | /* latin */ 49 | @font-face { 50 | font-family: 'Lato'; 51 | font-style: normal; 52 | font-weight: 400; 53 | src: local('Lato Regular'), local('Lato-Regular'), url(../fonts/Lato-Regular.woff2) format('woff2'); 54 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 55 | } 56 | /* latin-ext */ 57 | @font-face { 58 | font-family: 'Lato'; 59 | font-style: normal; 60 | font-weight: 700; 61 | src: local('Lato Bold'), local('Lato-Bold'), url(../fonts/Lato-Bold.woff2) format('woff2'); 62 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 63 | } 64 | /* latin */ 65 | @font-face { 66 | font-family: 'Lato'; 67 | font-style: normal; 68 | font-weight: 700; 69 | src: local('Lato Bold'), local('Lato-Bold'), url(../fonts/Lato-Bold.woff2) format('woff2'); 70 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 71 | } 72 | /* -------------------------------------------------------------------- */ 73 | @font-face { 74 | font-family: shabnam; 75 | src: url("../fonts/Shabnam.eot"); 76 | src: url("../fonts/Shabnam.eot?#iefix") format("embedded-opentype"),url("../fonts/Shabnam.woff") format("woff"),url("../fonts/Shabnam.ttf") format("truetype"); 77 | font-weight: normal 78 | } 79 | 80 | @font-face { 81 | font-family: shabnam; 82 | src: url("../fonts/Shabnam-Bold.eot"); 83 | src: url("../fonts/Shabnam-Bold.eot?#iefix") format("embedded-opentype"),url("../fonts/Shabnam-Bold.woff") format("woff"),url("../fonts/Shabnam-Bold.ttf") format("truetype"); 84 | font-weight: bold 85 | } 86 | 87 | @font-face { 88 | font-family: shabnam; 89 | src: url("../fonts/Shabnam-Light.eot"); 90 | src: url("../fonts/Shabnam-Light.eot?#iefix") format("embedded-opentype"),url("../fonts/Shabnam-Light.woff") format("woff"),url("../fonts/Shabnam-Light.ttf") format("truetype"); 91 | font-weight: 300 92 | } 93 | -------------------------------------------------------------------------------- /content/sass/_grids.scss: -------------------------------------------------------------------------------- 1 | @import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap"; 2 | @import "_common.scss"; 3 | 4 | .no-gutter-item { 5 | padding-right: 0; 6 | padding-left: 0; 7 | } 8 | 9 | .card { 10 | /* start thumb */ 11 | .thumb-img, .thumb-description ,.news-img, .news-description{ 12 | @extend .pull-right; 13 | @extend .no-gutter-item; 14 | } 15 | 16 | .thumb-img { 17 | @extend .col-xs-5; 18 | @extend .col-sm-3; 19 | @extend .col-md-5; 20 | } 21 | 22 | .thumb-description { 23 | @extend .col-xs-7; 24 | @extend .col-sm-9; 25 | @extend .col-md-7; 26 | padding-right: 0; 27 | padding-left: 0; 28 | } 29 | /* end thumb */ 30 | 31 | 32 | /* start news */ 33 | .news-img { 34 | @extend .col-sm-4; 35 | @extend .col-md-5; 36 | } 37 | 38 | .news-description { 39 | @extend .col-sm-8; 40 | @extend .col-md-7; 41 | } 42 | /* end news */ 43 | &.gallery{ 44 | figure{ 45 | @extend .col-xs-12; 46 | @extend .col-sm-4; 47 | @extend .col-md-4; 48 | @extend .pull-right; 49 | } 50 | } 51 | 52 | /* start gallery */ 53 | /* end gallery */ 54 | 55 | } 56 | -------------------------------------------------------------------------------- /content/sass/_login-rtl.scss: -------------------------------------------------------------------------------- 1 | html,body{ 2 | background-color: #c8c8c8; 3 | } 4 | label{ 5 | text-align: right; 6 | } 7 | .login-wrap { 8 | button, 9 | input, 10 | label, 11 | .tel-prefix, 12 | a { 13 | font-family: $shabnam; 14 | font-weight: 300; 15 | font-size: 1.1em; 16 | } 17 | .input, 18 | .tel-prefix { 19 | letter-spacing: 2px; 20 | } 21 | .login-btn { 22 | display: inline-block; 23 | text-align: center; 24 | margin-bottom: 20px; 25 | color: #549ef8; 26 | font-family: $shabnam; 27 | padding-bottom: 4px; 28 | border-bottom: 1px solid rgba(0, 0, 0, 0); 29 | font-size: 1em; 30 | margin-top: 5px; 31 | &:hover { 32 | border-bottom: 1px solid; 33 | } 34 | } 35 | .tab { 36 | color: #fff; 37 | border-color: #1161ee; 38 | } 39 | .group { 40 | position: relative; 41 | .tel-input { 42 | padding-left: 80px; 43 | } 44 | .tel-prefix { 45 | left: 20px; 46 | position: absolute; 47 | direction: ltr; 48 | color: #fff; 49 | top: 50%; 50 | margin-top: .1em; 51 | top: 50%; 52 | } 53 | .tel-preview { 54 | direction: ltr; 55 | text-align: center; 56 | color: #fff; 57 | font-weight: normal; 58 | font-size: 2em; 59 | letter-spacing: 3px; 60 | font-weight: 100; 61 | display: block; 62 | } 63 | >label { 64 | color: #ec5252; 65 | text-align: right; 66 | font-size: .9em; 67 | } 68 | } 69 | } 70 | 71 | .login-form { 72 | direction: rtl; 73 | .foot-lnk { 74 | font-family: $shabnam; 75 | line-height: 1.5; 76 | } 77 | >div { 78 | padding-top: 20px; 79 | } 80 | } 81 | 82 | input { 83 | &::-webkit-input-placeholder { 84 | /* Chrome/Opera/Safari */ 85 | direction: rtl; 86 | font-family: $shabnam; 87 | font-weight: normal; 88 | font-size: 1.1em; 89 | letter-spacing: 0; 90 | } 91 | &::-moz-placeholder { 92 | /* Firefox 19+ */ 93 | direction: rtl; 94 | font-family: $shabnam; 95 | font-weight: normal; 96 | font-size: 1.1em; 97 | letter-spacing: 0; 98 | } 99 | &:-ms-input-placeholder { 100 | /* IE 10+ */ 101 | direction: rtl; 102 | font-family: $shabnam; 103 | font-weight: normal; 104 | font-size: 1.1em; 105 | letter-spacing: 0; 106 | } 107 | &:-moz-placeholder { 108 | /* Firefox 18- */ 109 | direction: rtl; 110 | font-family: $shabnam; 111 | font-weight: normal; 112 | font-size: 1.1em; 113 | letter-spacing: 0; 114 | } 115 | } -------------------------------------------------------------------------------- /content/sass/_media.scss: -------------------------------------------------------------------------------- 1 | $screen-lg-min: 1200px; 2 | $screen-md-min: 992px; 3 | $screen-sm-min: 768px; 4 | $screen-xs-max: 767px; 5 | 6 | //xs only 7 | @media(max-width: $screen-xs-max) { 8 | 9 | .ac-scroll, .scroll-list{ 10 | max-height:200px!important; 11 | } 12 | .navbar-header, .navbar-form, #navbar { 13 | border: none; 14 | -moz-box-shadow: none; 15 | -webkit-box-shadow: none; 16 | box-shadow: none; 17 | } 18 | 19 | #navbar { 20 | text-align: center; 21 | 22 | li a { 23 | border-bottom: 1px solid #2980b9 !important; 24 | } 25 | 26 | .dropdown.open { 27 | a { 28 | background-color: #2980b9; 29 | } 30 | 31 | li a { 32 | background-color: #0e659e; 33 | text-align: center; 34 | border: none; 35 | 36 | &:hover { 37 | background-color: #2980b9; 38 | } 39 | } 40 | 41 | .dropdown-menu { 42 | li a { 43 | color: #fff !important; 44 | } 45 | } 46 | } 47 | } 48 | 49 | #head > .title h1 { 50 | margin-left: 0; 51 | } 52 | 53 | .search-form .btn { 54 | width: 100%; 55 | left:0!important; 56 | } 57 | .map-container{ 58 | margin-bottom:20px; 59 | } 60 | .login-html{ 61 | padding:10%; 62 | } 63 | } 64 | /* Small devices (tablets, 768px and up) */ 65 | 66 | @media (min-width: $screen-sm-min) { 67 | #head > .title h1 { 68 | margin-left: 30px; 69 | } 70 | 71 | .search-form { 72 | width: 100%; 73 | } 74 | } 75 | 76 | /* Medium devices (desktops, 992px and up) */ 77 | 78 | @media (min-width: $screen-md-min) { 79 | 80 | .login-html{ 81 | padding:90px 70px 50px 70px; 82 | } 83 | .search-form { 84 | width: auto; 85 | } 86 | } 87 | /* Large devices (large desktops, 1200px and up) */ 88 | 89 | @media (min-width: $screen-lg-min) { 90 | } 91 | 92 | 93 | /*items container*/ 94 | 95 | @media(max-width: 450px) { 96 | header > #head h1 { 97 | font-size: 1em; 98 | } 99 | } 100 | 101 | @media(min-width: 451px) { 102 | header > #head h1 { 103 | font-size: 1.9em; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /content/sass/_typography.scss: -------------------------------------------------------------------------------- 1 | @import "_color.scss"; 2 | @import "_fonts.scss"; 3 | $lato: "muli", sans-serif; 4 | 5 | a, 6 | a:hover, 7 | a:focus, 8 | a:active { 9 | // -moz-transition: .3s all; 10 | // -o-transition: .3s all; 11 | // -webkit-transition: .3s all; 12 | // transition: .3s all; 13 | text-decoration: none; 14 | outline: none; 15 | } 16 | 17 | p { 18 | font-size: 16px; 19 | } 20 | 21 | h1, 22 | h2, 23 | h3, 24 | h4, 25 | h5, 26 | h6, 27 | .h1, 28 | .h2, 29 | .h3, 30 | .h4, 31 | .h5, 32 | .h6 { 33 | font-family: $shabnam; 34 | } 35 | 36 | html { 37 | min-height: 100%; 38 | } 39 | 40 | html, 41 | body { 42 | background-color: #fff; 43 | font-family: $shabnam; 44 | font-weight: 300; 45 | direction: ltr; 46 | color: $color-light-text; 47 | } 48 | 49 | .no-top-margin { 50 | margin-top: 0 !important; 51 | } 52 | 53 | form.inline-form { 54 | margin-top: 1.2em; 55 | 56 | input, textarea { 57 | padding: 15px; 58 | font-size: 1.1em; 59 | border: none; 60 | box-shadow: 0 0 6px -2px #414141; 61 | font-weight: 300; 62 | background-color: $lighter-gray; 63 | margin-bottom: 1em; 64 | border-radius: 5px; 65 | } 66 | 67 | textarea { 68 | min-height: 200px !important; 69 | } 70 | 71 | .clearform { 72 | color: red; 73 | margin-top: .75em; 74 | } 75 | } 76 | 77 | .cbp-qtrotator blockquote p { 78 | font-family: $shabnam; 79 | } 80 | 81 | .menu .menu__item { 82 | font-family: $shabnam; 83 | } 84 | 85 | .btn.search { 86 | font-family: $shabnam; 87 | } 88 | 89 | .Tokenize { 90 | font-size: 1.4em; 91 | font-family: $lato; 92 | } 93 | 94 | .quote-container { 95 | min-height: 100vh; 96 | } 97 | -------------------------------------------------------------------------------- /content/sass/login.scss: -------------------------------------------------------------------------------- 1 | body{ 2 | margin:0; 3 | background:#c8c8c8; 4 | // font:600 16px/18px 'Open Sans',sans-serif; 5 | } 6 | *,:after,:before{box-sizing:border-box} 7 | .clearfix:after,.clearfix:before{content:'';display:table} 8 | .clearfix:after{clear:both;display:block} 9 | a{color:inherit;text-decoration:none} 10 | 11 | .login-wrap{ 12 | color:#bcbcbc; 13 | 14 | /*contain login box in the middle*/ 15 | top: 50%; 16 | left: 50%; 17 | position: absolute; 18 | overflow: auto; 19 | transform: translate(-50%, -50%); 20 | /*-------------------------------*/ 21 | 22 | 23 | width:100%; 24 | margin:auto; 25 | max-width:525px; 26 | min-height:670px; 27 | /*position:relative;*/ 28 | background:url('https://mberneti.github.io/ReactAdmin/content/images/login-bg.jpg') no-repeat center; 29 | box-shadow:0 12px 15px 0 rgba(0,0,0,.24),0 17px 50px 0 rgba(0,0,0,.19); 30 | } 31 | .login-html{ 32 | width:100%; 33 | height:100%; 34 | position:absolute; 35 | // padding:10%; 36 | background:rgba(40,57,101,.9); 37 | } 38 | .login-html .sign-in-htm, 39 | .login-html .sign-up-htm{ 40 | top:0; 41 | left:0; 42 | right:0; 43 | bottom:0; 44 | position:absolute; 45 | -webkit-transform:rotateY(180deg); 46 | transform:rotateY(180deg); 47 | -webkit-backface-visibility:hidden; 48 | backface-visibility:hidden; 49 | -webkit-transition:all .4s linear; 50 | transition:all .4s linear; 51 | } 52 | .login-html .sign-in, 53 | .login-html .sign-up, 54 | .login-form .group .check{ 55 | display:none; 56 | } 57 | .login-html .tab, 58 | .login-form .group .label, 59 | .login-form .group .button{ 60 | text-transform:uppercase; 61 | } 62 | .login-html .tab{ 63 | font-size:22px; 64 | margin-right:15px; 65 | padding-bottom:5px; 66 | margin:0 15px 10px 0; 67 | display:inline-block; 68 | border-bottom:2px solid transparent; 69 | } 70 | .login-html .sign-in:checked + .tab, 71 | .login-html .sign-up:checked + .tab{ 72 | color:#fff; 73 | border-color:#1161ee; 74 | } 75 | .login-form{ 76 | min-height:345px; 77 | position:relative; 78 | -webkit-perspective:1000px; 79 | perspective:1000px; 80 | -webkit-transform-style:preserve-3d; 81 | transform-style:preserve-3d; 82 | } 83 | .login-form .group{ 84 | margin-bottom:15px; 85 | } 86 | .login-form .group .label, 87 | .login-form .group .input, 88 | .login-form .group .button{ 89 | width:100%; 90 | display:block; 91 | } 92 | .login-form .group .input, 93 | .login-form .group .button{ 94 | color:#fff; 95 | } 96 | .login-form .group .input, 97 | .login-form .group .button{ 98 | border:none; 99 | padding:15px 20px; 100 | border-radius:25px; 101 | background:rgba(255,255,255,.1); 102 | } 103 | .login-form .group input[data-type="password"]{ 104 | text-security:circle; 105 | -webkit-text-security:circle; 106 | } 107 | // .login-form .group .label{ 108 | // color:#aaa; 109 | // font-size:12px; 110 | // } 111 | .login-form .group .button{ 112 | background:#1161ee; 113 | } 114 | .login-form .group label .icon{ 115 | width:15px; 116 | height:15px; 117 | border-radius:2px; 118 | position:relative; 119 | display:inline-block; 120 | background:rgba(255,255,255,.1); 121 | } 122 | .login-form .group label .icon:before, 123 | .login-form .group label .icon:after{ 124 | content:''; 125 | width:10px; 126 | height:2px; 127 | background:#fff; 128 | position:absolute; 129 | -webkit-transition:all .2s ease-in-out 0s; 130 | transition:all .2s ease-in-out 0s; 131 | } 132 | .login-form .group label .icon:before{ 133 | left:3px; 134 | width:5px; 135 | bottom:6px; 136 | -webkit-transform:scale(0) rotate(0); 137 | transform:scale(0) rotate(0); 138 | } 139 | .login-form .group label .icon:after{ 140 | top:6px; 141 | right:0; 142 | -webkit-transform:scale(0) rotate(0); 143 | transform:scale(0) rotate(0); 144 | } 145 | .login-form .group .check:checked + label{ 146 | color:#fff; 147 | } 148 | .login-form .group .check:checked + label .icon{ 149 | background:#1161ee; 150 | } 151 | .login-form .group .check:checked + label .icon:before{ 152 | -webkit-transform:scale(1) rotate(45deg); 153 | transform:scale(1) rotate(45deg); 154 | } 155 | .login-form .group .check:checked + label .icon:after{ 156 | -webkit-transform:scale(1) rotate(-45deg); 157 | transform:scale(1) rotate(-45deg); 158 | } 159 | .login-html .sign-in:checked + .tab + .sign-up + .tab + .login-form .sign-in-htm{ 160 | -webkit-transform:rotate(0); 161 | transform:rotate(0); 162 | } 163 | .login-html .sign-up:checked + .tab + .login-form .sign-up-htm{ 164 | -webkit-transform:rotate(0); 165 | transform:rotate(0); 166 | } 167 | 168 | .hr{ 169 | height:2px; 170 | margin:60px 0 50px 0; 171 | background:rgba(255,255,255,.2); 172 | } 173 | .foot-lnk{ 174 | text-align:center; 175 | } -------------------------------------------------------------------------------- /content/sass/style.scss: -------------------------------------------------------------------------------- 1 | // @import "./login.scss"; 2 | // @import "../../bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss"; 3 | // @import "../../bower_components/font-awesome/scss/font-awesome.scss"; 4 | @import "_all.scss"; 5 | #wrapper>nav { 6 | margin-bottom: 0; 7 | background-color: #F8F8F8!important; 8 | .nav.navbar-top-links .fullname { 9 | padding-left: 10px; 10 | padding-right: 5px; 11 | } 12 | } 13 | 14 | #page-wrapper { 15 | margin: 0 250px 0 0!important; 16 | padding-bottom: 1px!important; 17 | } 18 | 19 | // menu 20 | .sidebar ul li { 21 | border-bottom: none!important; 22 | } 23 | 24 | .metismenu { 25 | background-color: #F8F8F8; 26 | color: #5e5e5e; 27 | &::after, 28 | .metismenu-container { 29 | box-shadow: none; 30 | padding: 0; 31 | } 32 | font-family: $shabnam; 33 | .metismenu-state-icon { 34 | float: left; 35 | } 36 | } 37 | 38 | .metismenu-link.has-active-child { 39 | color: #5e5e5e; 40 | background-color: #e4e4e4; 41 | } 42 | 43 | .metismenu-link, 44 | .metismenu-link.active { 45 | color: #5e5e5e; 46 | font-family: $shabnam; 47 | text-shadow: none; 48 | padding-right: 15px; 49 | } 50 | 51 | .metismenu-link.active { 52 | font-weight: bolder; 53 | background-color: #e4e4e4!important; 54 | } 55 | 56 | .metismenu-link:hover { 57 | color: #5e5e5e; 58 | background-color: #EEE!important; 59 | } 60 | 61 | i.metismenu-icon { 62 | text-align: center; 63 | width: 16px; 64 | margin-left: 7px; 65 | } 66 | 67 | i.metismenu-icon.fa.fa-undefined { 68 | display: none; 69 | } 70 | // -------------------------------------------------------------------------------------- 71 | body { 72 | background-color: #efefef; 73 | } 74 | 75 | .tether-target input { 76 | text-align: left; 77 | width: 100%; 78 | height: 35px; 79 | padding: 6px 12px; 80 | background-color: #fff; 81 | background-image: none; 82 | border: 1px solid #eee; 83 | border-radius: 3px; 84 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); 85 | -webkit-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out; 86 | transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out; 87 | } 88 | 89 | .dropdown-menu{ 90 | left:0px!important; 91 | right: auto!important; 92 | } 93 | .navbar-top-links .dropdown-user{ 94 | left:2px!important; 95 | right: auto!important; 96 | li{ 97 | min-width: 180px; 98 | } 99 | } 100 | 101 | .multi-input-container{ 102 | border-right: 1px solid; 103 | background-color: cornsilk; 104 | padding: 15px; 105 | margin-bottom: 10px; 106 | } 107 | 108 | .multi-input-item{ 109 | border: 1px solid #cccccc; 110 | padding: 15px; 111 | margin-bottom: 15px; 112 | background-color: #fff; 113 | } 114 | // -------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /debug.log: -------------------------------------------------------------------------------- 1 | [1219/000045:ERROR:tcp_listen_socket.cc(76)] Could not bind socket to 127.0.0.1:6004 2 | [1219/000045:ERROR:node_debugger.cc(86)] Cannot start debugger server 3 | [1223/104646:ERROR:tcp_listen_socket.cc(76)] Could not bind socket to 127.0.0.1:6004 4 | [1223/104646:ERROR:node_debugger.cc(86)] Cannot start debugger server 5 | [1225/115019:ERROR:tcp_listen_socket.cc(76)] Could not bind socket to 127.0.0.1:6004 6 | [1225/115019:ERROR:node_debugger.cc(86)] Cannot start debugger server 7 | [0205/010607:ERROR:tcp_listen_socket.cc(76)] Could not bind socket to 127.0.0.1:6004 8 | [0205/010607:ERROR:node_debugger.cc(86)] Cannot start debugger server 9 | -------------------------------------------------------------------------------- /docs/content/css/basic.min.css: -------------------------------------------------------------------------------- 1 | .dropzone,.dropzone *{box-sizing:border-box}.dropzone{position:relative}.dropzone .dz-preview{position:relative;display:inline-block;width:120px;margin:0.5em}.dropzone .dz-preview .dz-progress{display:block;height:15px;border:1px solid #aaa}.dropzone .dz-preview .dz-progress .dz-upload{display:block;height:100%;width:0;background:green}.dropzone .dz-preview .dz-error-message{color:red;display:none}.dropzone .dz-preview.dz-error .dz-error-message,.dropzone .dz-preview.dz-error .dz-error-mark{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{display:block}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark{position:absolute;display:none;left:30px;top:30px;width:54px;height:58px;left:50%;margin-left:-27px} 2 | -------------------------------------------------------------------------------- /docs/content/css/dropzone.min.css: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-moz-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-webkit-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-moz-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-webkit-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-moz-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone{min-height:150px;border:2px solid rgba(0,0,0,0.3);background:white;padding:20px 20px}.dropzone.dz-clickable{cursor:pointer}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:0.5}.dropzone .dz-message{text-align:center;margin:2em 0}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(to bottom, #eee, #ddd)}.dropzone .dz-preview.dz-file-preview .dz-details{opacity:1}.dropzone .dz-preview.dz-image-preview{background:white}.dropzone .dz-preview.dz-image-preview .dz-details{-webkit-transition:opacity 0.2s linear;-moz-transition:opacity 0.2s linear;-ms-transition:opacity 0.2s linear;-o-transition:opacity 0.2s linear;transition:opacity 0.2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,0.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid rgba(200,200,200,0.8);background-color:rgba(255,255,255,0.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid transparent}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:rgba(255,255,255,0.4);padding:0 0.4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{-webkit-transform:scale(1.05, 1.05);-moz-transform:scale(1.05, 1.05);-ms-transform:scale(1.05, 1.05);-o-transform:scale(1.05, 1.05);transform:scale(1.05, 1.05);-webkit-filter:blur(8px);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{-webkit-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;-webkit-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview .dz-success-mark,.dropzone .dz-preview .dz-error-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px}.dropzone .dz-preview .dz-success-mark svg,.dropzone .dz-preview .dz-error-mark svg{display:block;width:54px;height:54px}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;-webkit-transition:all 0.2s linear;-moz-transition:all 0.2s linear;-ms-transition:all 0.2s linear;-o-transition:all 0.2s linear;transition:all 0.2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;-webkit-transition:opacity 0.4s ease-in;-moz-transition:opacity 0.4s ease-in;-ms-transition:opacity 0.4s ease-in;-o-transition:opacity 0.4s ease-in;transition:opacity 0.4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{-webkit-animation:pulse 6s ease infinite;-moz-animation:pulse 6s ease infinite;-ms-animation:pulse 6s ease infinite;-o-animation:pulse 6s ease infinite;animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:16px;left:50%;top:50%;margin-top:-8px;width:80px;margin-left:-40px;background:rgba(255,255,255,0.9);-webkit-transform:scale(1);border-radius:8px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#333;background:linear-gradient(to bottom, #666, #444);position:absolute;top:0;left:0;bottom:0;width:0;-webkit-transition:width 300ms ease-in-out;-moz-transition:width 300ms ease-in-out;-ms-transition:width 300ms ease-in-out;-o-transition:width 300ms ease-in-out;transition:width 300ms ease-in-out}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;-webkit-transition:opacity 0.3s ease;-moz-transition:opacity 0.3s ease;-ms-transition:opacity 0.3s ease;-o-transition:opacity 0.3s ease;transition:opacity 0.3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#be2626;background:linear-gradient(to bottom, #be2626, #a92222);padding:0.5em 1.2em;color:white}.dropzone .dz-preview .dz-error-message:after{content:'';position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #be2626} 2 | -------------------------------------------------------------------------------- /docs/content/css/filepicker.css: -------------------------------------------------------------------------------- 1 | /* Filepicker CSS */ 2 | .filepicker { 3 | font-family: sans-serif; 4 | } 5 | 6 | div.filepicker { 7 | text-align: center; 8 | padding: 5px; 9 | background-color: #E1E1E1; 10 | border-radius: 5px; 11 | min-height: 60px; 12 | border: 2px dashed #C7C7C7; 13 | } 14 | 15 | /* Icon */ 16 | .filepicker-file-icon 17 | { 18 | position: relative; 19 | 20 | display: inline-block; 21 | 22 | margin: 1.5em 0 2.5em 0; 23 | padding-left: 45px; 24 | 25 | color: black; 26 | } 27 | .filepicker-file-icon::before 28 | { 29 | position: absolute; 30 | top: -7px; 31 | left: 0; 32 | 33 | width: 29px; 34 | height: 34px; 35 | 36 | content: ''; 37 | 38 | border: solid 2px #7F7F7F; 39 | border-radius: 2px; 40 | } 41 | .filepicker-file-icon::after 42 | { 43 | font-size: 11px; 44 | line-height: 1.3; 45 | 46 | position: absolute; 47 | top: 9px; 48 | left: -4px; 49 | 50 | padding: 0 2px; 51 | 52 | content: 'file'; 53 | content: attr(data-filetype); 54 | text-align: right; 55 | letter-spacing: 1px; 56 | text-transform: uppercase; 57 | 58 | color: #fff; 59 | background-color: #000; 60 | } 61 | .filepicker-file-icon .fileCorner 62 | { 63 | position: absolute; 64 | top: -7px; 65 | left: 22px; 66 | 67 | width: 0; 68 | height: 0; 69 | 70 | border-width: 11px 0 0 11px; 71 | border-style: solid; 72 | border-color: white transparent transparent #920035; 73 | } 74 | -------------------------------------------------------------------------------- /docs/content/css/metisMenu.min.css: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v2.6.1 3 | * A jQuery menu plugin 4 | * https://github.com/onokumus/metisMenu#readme 5 | * 6 | * Made by Osman Nuri Okumuş (https://github.com/onokumus) 7 | * Under MIT License 8 | */ 9 | 10 | .metismenu .arrow{float:right;line-height:1.42857}[dir=rtl] .metismenu .arrow{float:left}.metismenu .glyphicon.arrow:before{content:"\e079"}.metismenu .active>a>.glyphicon.arrow:before{content:"\e114"}.metismenu .fa.arrow:before{content:"\f104"}.metismenu .active>a>.fa.arrow:before{content:"\f107"}.metismenu .ion.arrow:before{content:"\f3d2"}.metismenu .active>a>.ion.arrow:before{content:"\f3d0"}.metismenu .plus-times{float:right}[dir=rtl] .metismenu .plus-times{float:left}.metismenu .fa.plus-times:before{content:"\f067"}.metismenu .active>a>.fa.plus-times{-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.metismenu .plus-minus{float:right}[dir=rtl] .metismenu .plus-minus{float:left}.metismenu .fa.plus-minus:before{content:"\f067"}.metismenu .active>a>.fa.plus-minus:before{content:"\f068"}.metismenu .collapse{display:none}.metismenu .collapse.in{display:block}.metismenu .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.metismenu .has-arrow{position:relative}.metismenu .has-arrow:after{position:absolute;content:'';width:.5em;height:.5em;border-width:1px 0 0 1px;border-style:solid;border-color:#fff;right:1em;-webkit-transform:rotate(-45deg) translateY(-50%);-ms-transform:rotate(-45deg) translateY(-50%);-o-transform:rotate(-45deg) translateY(-50%);transform:rotate(-45deg) translateY(-50%);-webkit-transform-origin:top;-ms-transform-origin:top;-o-transform-origin:top;transform-origin:top;top:50%;-webkit-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}[dir=rtl] .metismenu .has-arrow:after{right:auto;left:1em;-webkit-transform:rotate(135deg) translateY(-50%);-ms-transform:rotate(135deg) translateY(-50%);-o-transform:rotate(135deg) translateY(-50%);transform:rotate(135deg) translateY(-50%)}.metismenu .active>.has-arrow:after,.metismenu .has-arrow[aria-expanded=true]:after{-webkit-transform:rotate(-135deg) translateY(-50%);-ms-transform:rotate(-135deg) translateY(-50%);-o-transform:rotate(-135deg) translateY(-50%);transform:rotate(-135deg) translateY(-50%)} -------------------------------------------------------------------------------- /docs/content/css/mystyle.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/css/mystyle.css -------------------------------------------------------------------------------- /docs/content/css/react-metismenu-standart.min.css: -------------------------------------------------------------------------------- 1 | .metismenu{background:#303336;font-family:'Open Sans',sans-serif;font-size:12pt;overflow:hidden;position:relative}.metismenu>.metismenu-container>.metismenu-item>.metismenu-link{line-height:2.5em}.metismenu>.metismenu-container>.metismenu-item>.metismenu-link .metismenu-state-icon{line-height:2.5em}.metismenu::after{box-shadow:0 0 .4em rgba(0,0,0,.5) inset;-webkit-box-shadow:0 0 .4em rgba(0,0,0,.5) inset;content:" ";pointer-events:none;position:absolute;bottom:0;left:0;right:0;top:0}.metismenu-container,.metismenu-item{margin:0;padding:0}.metismenu-container{list-style:none}.metismenu-container .metismenu-container{box-shadow:0 .3em .3em -.3em #0c0d0e inset,0 -.3em .3em -.3em #0c0d0e inset;-webkit-box-shadow:0 .3em .3em -.3em #0c0d0e inset,0 -.3em .3em -.3em #0c0d0e inset;transition:padding .3s;-webkit-transition:padding .3s;background:rgba(255,255,255,.05)}.metismenu-container .metismenu-container .metismenu-item>.metismenu-link{height:0;overflow:hidden}.metismenu-container .metismenu-container .metismenu-link{padding-left:1em}.metismenu-container .metismenu-container .metismenu-container .metismenu-link{padding-left:2em}.metismenu-container.visible{padding:.5em 0}.metismenu-container.visible>.metismenu-item>.metismenu-link{height:2.5em}.metismenu-link{color:#DDD;text-shadow:0 -1px 0 rgba(0,0,0,.5);-webkit-text-shadow:0 -1px 0 rgba(0,0,0,.5);transition:height .3s,color .3s,background-color .3s;-webkit-transition:height .3s,color .3s,background-color .3s;display:block;line-height:2.5em;text-decoration:none}.metismenu-link:hover{background:rgba(255,255,255,.05);color:#f7f7f7}.metismenu-link.active{text-shadow:0 -1px 0 rgba(0,0,0,.25);-webkit-text-shadow:0 -1px 0 rgba(0,0,0,.25);background:#F53;color:#FFF}.metismenu-link.has-active-child{color:#F53}I.metismenu-icon{text-align:center;width:3em}I.metismenu-state-icon{transition:transform .3s;-webkit-transition:transform .3s;float:right;line-height:2.5em;text-align:center;width:3em}I.metismenu-state-icon.rotate-minus-90{transform:rotate(-90deg);-webkit-transform:rotate(-90deg)} -------------------------------------------------------------------------------- /docs/content/css/sb-admin-2.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - SB Admin 2 v3.3.7+1 (http://startbootstrap.com/template-overviews/sb-admin-2) 3 | * Copyright 2013-2016 Start Bootstrap 4 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE) 5 | */.chat,.timeline{list-style:none}body{background-color:#f8f8f8}#wrapper{width:100%}#page-wrapper{padding:0 15px;min-height:568px;background-color:#fff}@media (min-width:768px){#page-wrapper{position:inherit;margin:0 0 0 250px;padding:0 30px;border-left:1px solid #e7e7e7}}.navbar-top-links{margin-right:0}.navbar-top-links li{display:inline-block}.flot-chart,.navbar-top-links .dropdown-menu li{display:block}.navbar-top-links li:last-child{margin-right:15px}.navbar-top-links li a{padding:15px;min-height:50px}.navbar-top-links .dropdown-menu li:last-child{margin-right:0}.navbar-top-links .dropdown-menu li a{padding:3px 20px;min-height:0}.navbar-top-links .dropdown-menu li a div{white-space:normal}.navbar-top-links .dropdown-alerts,.navbar-top-links .dropdown-messages,.navbar-top-links .dropdown-tasks{width:310px;min-width:0}.navbar-top-links .dropdown-messages{margin-left:5px}.navbar-top-links .dropdown-tasks{margin-left:-59px}.navbar-top-links .dropdown-alerts{margin-left:-123px}.navbar-top-links .dropdown-user{right:0;left:auto}.sidebar .sidebar-nav.navbar-collapse{padding-left:0;padding-right:0}.sidebar .sidebar-search{padding:15px}.sidebar ul li{border-bottom:1px solid #e7e7e7}.sidebar ul li a.active{background-color:#eee}.sidebar .arrow{float:right}.sidebar .fa.arrow:before{content:"\f104"}.sidebar .active>a>.fa.arrow:before{content:"\f107"}.sidebar .nav-second-level li,.sidebar .nav-third-level li{border-bottom:none!important}.sidebar .nav-second-level li a{padding-left:37px}.sidebar .nav-third-level li a{padding-left:52px}@media (min-width:768px){.sidebar{z-index:1;position:absolute;width:250px;margin-top:51px}.navbar-top-links .dropdown-alerts,.navbar-top-links .dropdown-messages,.navbar-top-links .dropdown-tasks{margin-left:auto}}.btn-outline{color:inherit;background-color:transparent;transition:all .5s}.btn-primary.btn-outline{color:#428bca}.btn-success.btn-outline{color:#5cb85c}.btn-info.btn-outline{color:#5bc0de}.btn-warning.btn-outline{color:#f0ad4e}.btn-danger.btn-outline{color:#d9534f}.btn-danger.btn-outline:hover,.btn-info.btn-outline:hover,.btn-primary.btn-outline:hover,.btn-success.btn-outline:hover,.btn-warning.btn-outline:hover{color:#fff}.chat{margin:0;padding:0}.chat li{margin-bottom:10px;padding-bottom:5px;border-bottom:1px dotted #999}.chat li.left .chat-body{margin-left:60px}.chat li.right .chat-body{margin-right:60px}.chat li .chat-body p{margin:0}.chat .glyphicon,.panel .slidedown .glyphicon{margin-right:5px}.chat-panel .panel-body{height:350px;overflow-y:scroll}.login-panel{margin-top:25%}.flot-chart{height:400px}.flot-chart-content{width:100%;height:100%}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_desc_disabled{background:0 0}table.dataTable thead .sorting_asc:after{content:"\f0de";float:right;font-family:fontawesome}table.dataTable thead .sorting_desc:after{content:"\f0dd";float:right;font-family:fontawesome}table.dataTable thead .sorting:after{content:"\f0dc";float:right;font-family:fontawesome;color:rgba(50,50,50,.5)}.btn-circle{width:30px;height:30px;padding:6px 0;border-radius:15px;text-align:center;font-size:12px;line-height:1.428571429}.btn-circle.btn-lg{width:50px;height:50px;padding:10px 16px;border-radius:25px;font-size:18px;line-height:1.33}.btn-circle.btn-xl{width:70px;height:70px;padding:10px 16px;border-radius:35px;font-size:24px;line-height:1.33}.show-grid [class^=col-]{padding-top:10px;padding-bottom:10px;border:1px solid #ddd;background-color:#eee!important}.show-grid{margin:15px 0}.huge{font-size:40px}.panel-green{border-color:#5cb85c}.panel-green>.panel-heading{border-color:#5cb85c;color:#fff;background-color:#5cb85c}.panel-green>a{color:#5cb85c}.panel-green>a:hover{color:#3d8b3d}.panel-red{border-color:#d9534f}.panel-red>.panel-heading{border-color:#d9534f;color:#fff;background-color:#d9534f}.panel-red>a{color:#d9534f}.panel-red>a:hover{color:#b52b27}.panel-yellow{border-color:#f0ad4e}.panel-yellow>.panel-heading{border-color:#f0ad4e;color:#fff;background-color:#f0ad4e}.panel-yellow>a{color:#f0ad4e}.panel-yellow>a:hover{color:#df8a13}.timeline{position:relative;padding:20px 0}.timeline:before{content:" ";position:absolute;top:0;bottom:0;left:50%;width:3px;margin-left:-1.5px;background-color:#eee}.timeline>li{position:relative;margin-bottom:20px}.timeline>li:after,.timeline>li:before{content:" ";display:table}.timeline>li:after{clear:both}.timeline>li>.timeline-panel{float:left;position:relative;width:46%;padding:20px;border:1px solid #d4d4d4;border-radius:2px;-webkit-box-shadow:0 1px 6px rgba(0,0,0,.175);box-shadow:0 1px 6px rgba(0,0,0,.175)}.timeline>li>.timeline-panel:before{content:" ";display:inline-block;position:absolute;top:26px;right:-15px;border-top:15px solid transparent;border-right:0 solid #ccc;border-bottom:15px solid transparent;border-left:15px solid #ccc}.timeline>li>.timeline-panel:after{content:" ";display:inline-block;position:absolute;top:27px;right:-14px;border-top:14px solid transparent;border-right:0 solid #fff;border-bottom:14px solid transparent;border-left:14px solid #fff}.timeline>li>.timeline-badge{z-index:100;position:absolute;top:16px;left:50%;width:50px;height:50px;margin-left:-25px;border-radius:50%;text-align:center;font-size:1.4em;line-height:50px;color:#fff;background-color:#999}.timeline>li.timeline-inverted>.timeline-panel{float:right}.timeline>li.timeline-inverted>.timeline-panel:before{right:auto;left:-15px;border-right-width:15px;border-left-width:0}.timeline>li.timeline-inverted>.timeline-panel:after{right:auto;left:-14px;border-right-width:14px;border-left-width:0}.timeline-badge.primary{background-color:#2e6da4!important}.timeline-badge.success{background-color:#3f903f!important}.timeline-badge.warning{background-color:#f0ad4e!important}.timeline-badge.danger{background-color:#d9534f!important}.timeline-badge.info{background-color:#5bc0de!important}.timeline-title{margin-top:0;color:inherit}.timeline-body>p,.timeline-body>ul{margin-bottom:0}.timeline-body>p+p{margin-top:5px}@media (max-width:767px){ul.timeline:before{left:40px}ul.timeline>li>.timeline-panel{width:calc(10%);width:-moz-calc(10%);width:-webkit-calc(10%);float:right}ul.timeline>li>.timeline-badge{top:16px;left:15px;margin-left:0}ul.timeline>li>.timeline-panel:before{right:auto;left:-15px;border-right-width:15px;border-left-width:0}ul.timeline>li>.timeline-panel:after{right:auto;left:-14px;border-right-width:14px;border-left-width:0}} -------------------------------------------------------------------------------- /docs/content/fonts/BYekan.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/BYekan.eot -------------------------------------------------------------------------------- /docs/content/fonts/BYekan.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/BYekan.ttf -------------------------------------------------------------------------------- /docs/content/fonts/BYekan.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/BYekan.woff -------------------------------------------------------------------------------- /docs/content/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /docs/content/fonts/Lato-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Lato-Bold.woff2 -------------------------------------------------------------------------------- /docs/content/fonts/Lato-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Lato-Light.woff2 -------------------------------------------------------------------------------- /docs/content/fonts/Lato-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Lato-Regular.woff2 -------------------------------------------------------------------------------- /docs/content/fonts/OpenSans-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/OpenSans-Regular.eot -------------------------------------------------------------------------------- /docs/content/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /docs/content/fonts/OpenSans-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/OpenSans-Regular.woff -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam-Bold.eot -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam-Bold.ttf -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam-Bold.woff -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam-Light.eot -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam-Light.ttf -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam-Light.woff -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam.eot -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam.ttf -------------------------------------------------------------------------------- /docs/content/fonts/Shabnam.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/Shabnam.woff -------------------------------------------------------------------------------- /docs/content/fonts/bootstrap/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/bootstrap/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /docs/content/fonts/bootstrap/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/bootstrap/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /docs/content/fonts/bootstrap/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/bootstrap/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /docs/content/fonts/bootstrap/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/bootstrap/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /docs/content/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/content/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/content/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/content/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/content/images/DashboardDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/images/DashboardDemo.png -------------------------------------------------------------------------------- /docs/content/images/LoginDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/images/LoginDemo.png -------------------------------------------------------------------------------- /docs/content/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/images/favicon.png -------------------------------------------------------------------------------- /docs/content/images/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/content/images/login-bg.jpg -------------------------------------------------------------------------------- /docs/content/js/metisMenu.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v2.6.1 3 | * A jQuery menu plugin 4 | * https://github.com/onokumus/metisMenu#readme 5 | * 6 | * Made by Osman Nuri Okumuş (https://github.com/onokumus) 7 | * Under MIT License 8 | */ 9 | 10 | !function(a,b){if("function"==typeof define&&define.amd)define(["jquery"],b);else if("undefined"!=typeof exports)b(require("jquery"));else{var c={exports:{}};b(a.jquery),a.metisMenu=c.exports}}(this,function(a){"use strict";function b(a){return a&&a.__esModule?a:{"default":a}}function c(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}var d=(b(a),"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}),e=function(){function a(a,b){for(var c=0;c 0 ? this.window.innerWidth : this.screen.width; n < 768 ? ($("div.navbar-collapse").addClass("collapse"), i = 100) : $("div.navbar-collapse").removeClass("collapse"); var e = (this.window.innerHeight > 0 ? this.window.innerHeight : this.screen.height) - 1; e -= i, e < 1 && (e = 1), e > i && $("#page-wrapper").css("min-height", e + "px") }); for (var i = window.location, n = $("ul.nav a").filter(function () { return this.href == i }).addClass("active").parent(); ;) { if (!n.is("li")) break; n = n.parent().addClass("in").parent() } }); -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/docs/favicon.ico -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | React Admin 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/static/css/main.80540410.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"static/css/main.80540410.css","sourceRoot":""} -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | sass = require('gulp-ruby-sass'), 3 | notify = require('gulp-notify'), 4 | bower = require('gulp-bower'); 5 | 6 | var config = { 7 | sassPath: './content/sass', 8 | bowerDir: './bower_components', 9 | nodeDir: './node_modules' 10 | } 11 | // create a task to do bower install 12 | gulp.task('bower', function () { 13 | return bower() 14 | .pipe(gulp.dest(config.bowerDir)); 15 | }); 16 | 17 | // Copy js files to public folder 18 | gulp.task('js', function () { 19 | return gulp.src([ 20 | config.bowerDir + '/bootstrap-sass/assets/javascripts/bootstrap.min.js', 21 | config.bowerDir + '/jquery/dist/jquery.min.js', 22 | config.bowerDir + '/metisMenu/dist/metisMenu.min.js' 23 | ]) 24 | .pipe(gulp.dest('./public/content/js')); 25 | }); 26 | 27 | // Copy rain bow language js files to public folder 28 | gulp.task('js2', function () { 29 | return gulp.src([ 30 | config.bowerDir + '/rainbow/js/language/generic.js', 31 | config.bowerDir + '/rainbow/js/language/html.js', 32 | config.bowerDir + '/rainbow/js/language/csharp.js', 33 | config.bowerDir + '/rainbow/js/language/css.js', 34 | config.bowerDir + '/rainbow/js/language/php.js', 35 | config.bowerDir + '/rainbow/js/language/python.js', 36 | config.bowerDir + '/rainbow/js/language/scheme.js', 37 | config.bowerDir + '/rainbow/js/language/shell.js' 38 | ]) 39 | .pipe(gulp.dest('./public/content/js/lang')); 40 | }); 41 | 42 | // Copy fontawesome icons to public/fonts folder 43 | gulp.task('icons', function () { 44 | return gulp.src(config.bowerDir + '/font-awesome/fonts/**.*') 45 | .pipe(gulp.dest('./public/content/fonts')); 46 | }); 47 | 48 | gulp.task('css', function () { 49 | return sass(config.sassPath + '/style.scss', { // Our coustom sass 50 | style: 'compressed', // minify css 51 | loadPath: [ // load paths to easy use import in resources/sass 52 | config.bowerDir + '/bootstrap-sass/assets/stylesheets', // bootstrap sass files 53 | config.bowerDir + '/font-awesome/scss' // awesome icons sass files 54 | ] 55 | }) 56 | .on('error', notify.onError(function (error) { 57 | return 'Error: ' + error.message; 58 | })) 59 | .pipe(gulp.dest('./public/content/css')); 60 | }); 61 | 62 | 63 | // Copy css to content folder 64 | gulp.task('css2', function () { 65 | return gulp.src([ 66 | config.nodeDir + '/react-metismenu/dist/react-metismenu-standart.min.css', 67 | config.nodeDir + '/dropzone/dist/min/basic.min.css', 68 | config.nodeDir + '/dropzone/dist/min/dropzone.min.css', 69 | config.nodeDir + '/react-dropzone-component/styles/filepicker.css' 70 | ]) 71 | .pipe(gulp.dest('./public/content/css')); 72 | }); 73 | 74 | // Copy fontawesome icons to public/fonts folder 75 | gulp.task('icons', function () { 76 | return gulp.src(config.bowerDir + '/font-awesome/fonts/**.*') 77 | .pipe(gulp.dest('./public/content/fonts')); 78 | }); 79 | 80 | // Copy fontawesome icons to public/fonts folder 81 | gulp.task('icons2', function () { 82 | return gulp.src(config.bowerDir + '/bootstrap-sass/assets/fonts/bootstrap/**.*') 83 | .pipe(gulp.dest('./public/content/fonts/bootstrap')); 84 | }); 85 | 86 | // Rerun the task when a file changes 87 | // Run this task : gulp watch 88 | gulp.task('watch', ['css'], function () { 89 | gulp.watch([config.sassPath + '/**/*.scss'], ['css']); 90 | gulp.watch(config.htmlPath, ['html']); 91 | }); 92 | 93 | // Run this task : gulp 94 | // OR gulp default 95 | gulp.task('default', ['bower', 'icons', 'css', 'js', 'js2']); 96 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactAdmin", 3 | "version": "0.0.1", 4 | "private": true, 5 | "devDependencies": { 6 | "autoprefixer": "6.4.1", 7 | "babel-core": "6.14.0", 8 | "babel-eslint": "6.1.2", 9 | "babel-jest": "15.0.0", 10 | "babel-loader": "6.2.5", 11 | "babel-preset-react-app": "^0.2.1", 12 | "case-sensitive-paths-webpack-plugin": "1.1.4", 13 | "chalk": "1.1.3", 14 | "connect-history-api-fallback": "1.3.0", 15 | "cross-spawn": "4.0.0", 16 | "css-loader": "^0.24.0", 17 | "detect-port": "1.0.0", 18 | "dotenv": "2.0.0", 19 | "eslint": "3.5.0", 20 | "eslint-config-react-app": "^0.2.1", 21 | "eslint-loader": "1.5.0", 22 | "eslint-plugin-flowtype": "2.18.1", 23 | "eslint-plugin-import": "1.12.0", 24 | "eslint-plugin-jsx-a11y": "2.2.2", 25 | "eslint-plugin-react": "6.3.0", 26 | "extract-text-webpack-plugin": "1.0.1", 27 | "file-loader": "0.9.0", 28 | "filesize": "3.3.0", 29 | "find-cache-dir": "0.1.1", 30 | "fs-extra": "0.30.0", 31 | "gulp": "^3.9.1", 32 | "gulp-bower": "0.0.13", 33 | "gulp-notify": "^2.2.0", 34 | "gulp-ruby-sass": "^2.1.1", 35 | "gzip-size": "3.0.0", 36 | "html-webpack-plugin": "2.22.0", 37 | "http-proxy-middleware": "0.17.1", 38 | "jest": "15.1.1", 39 | "json-loader": "0.5.4", 40 | "object-assign": "4.1.0", 41 | "path-exists": "2.1.0", 42 | "postcss-loader": "0.13.0", 43 | "promise": "7.1.1", 44 | "react-dev-utils": "^0.2.1", 45 | "recursive-readdir": "2.1.0", 46 | "rimraf": "2.5.4", 47 | "strip-ansi": "3.0.1", 48 | "style-loader": "0.13.1", 49 | "url-loader": "0.5.7", 50 | "webpack": "1.13.2", 51 | "webpack-dev-server": "1.16.1", 52 | "whatwg-fetch": "1.0.0" 53 | }, 54 | "dependencies": { 55 | "axios": "^0.15.3", 56 | "es6-promise": "^4.0.5", 57 | "history": "^4.6.1", 58 | "jquery": "^3.1.1", 59 | "jwt-decode": "^2.1.0", 60 | "load-script": "^1.0.0", 61 | "lodash": "^4.17.2", 62 | "moment-jalaali": "^0.6.1", 63 | "platform": "^1.3.3", 64 | "qs": "^6.3.0", 65 | "react": "^15.3.2", 66 | "react-autosuggest": "^7.0.2", 67 | "react-bootstrap": "^0.30.7", 68 | "react-bootstrap-sweetalert": "^3.0.0", 69 | "react-datepicker": "^0.41.1", 70 | "react-dom": "^15.3.2", 71 | "react-dropzone-component": "^1.4.1", 72 | "react-json-view": "^1.8.3", 73 | "react-metismenu": "^1.1.3", 74 | "react-metismenu-router-link": "^1.0.0", 75 | "react-persian-datepicker": "^3.0.1", 76 | "react-redux": "^5.0.1", 77 | "react-router": "2.8.1", 78 | "react-router-dom": "^4.1.1", 79 | "react-router-redux": "^4.0.8", 80 | "react-select": "^1.0.0-rc.2", 81 | "react-tagsinput": "^3.14.0", 82 | "redux": "^3.6.0", 83 | "style-loader": "^0.13.1", 84 | "validate.js": "^0.11.1" 85 | }, 86 | "scripts": { 87 | "start": "node scripts/start.js", 88 | "build": "node scripts/build.js", 89 | "test": "node scripts/test.js --env=jsdom" 90 | }, 91 | "jest": { 92 | "moduleFileExtensions": [ 93 | "jsx", 94 | "js", 95 | "json" 96 | ], 97 | "moduleNameMapper": { 98 | "^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "\\config\\jest\\FileStub.js", 99 | "^.+\\.css$": "\\config\\jest\\CSSStub.js" 100 | }, 101 | "setupFiles": [ 102 | "\\config\\polyfills.js" 103 | ], 104 | "testPathIgnorePatterns": [ 105 | "/(build|docs|node_modules)/" 106 | ], 107 | "testEnvironment": "node", 108 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(js|jsx)$" 109 | }, 110 | "babel": { 111 | "presets": [ 112 | "react-app" 113 | ] 114 | }, 115 | "eslintConfig": { 116 | "extends": "react-app" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mberneti/ReactAdmin/3b385361c590c51daf8477d4b409d572ada36d00/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | React Admin 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 53 | 54 | 55 | 56 | 57 | 58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | // Do this as the first thing so that any code reading it knows the right env. 2 | process.env.NODE_ENV = 'production'; 3 | 4 | // Load environment variables from .env file. Surpress warnings using silent 5 | // if this file is missing. dotenv will never modify any environment variables 6 | // that have already been set. 7 | // https://github.com/motdotla/dotenv 8 | require('dotenv').config({silent: true}); 9 | 10 | var chalk = require('chalk'); 11 | var fs = require('fs-extra'); 12 | var path = require('path'); 13 | var filesize = require('filesize'); 14 | var gzipSize = require('gzip-size').sync; 15 | var rimrafSync = require('rimraf').sync; 16 | var webpack = require('webpack'); 17 | var config = require('../config/webpack.config.prod'); 18 | var paths = require('../config/paths'); 19 | var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); 20 | var recursive = require('recursive-readdir'); 21 | var stripAnsi = require('strip-ansi'); 22 | 23 | // Warn and crash if required files are missing 24 | if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { 25 | process.exit(1); 26 | } 27 | 28 | // Input: /User/dan/app/build/static/js/main.82be8.js 29 | // Output: /static/js/main.js 30 | function removeFileNameHash(fileName) { 31 | return fileName 32 | .replace(paths.appBuild, '') 33 | .replace(/\/?(.*)(\.\w+)(\.js|\.css)/, (match, p1, p2, p3) => p1 + p3); 34 | } 35 | 36 | // Input: 1024, 2048 37 | // Output: "(+1 KB)" 38 | function getDifferenceLabel(currentSize, previousSize) { 39 | var FIFTY_KILOBYTES = 1024 * 50; 40 | var difference = currentSize - previousSize; 41 | var fileSize = !Number.isNaN(difference) ? filesize(difference) : 0; 42 | if (difference >= FIFTY_KILOBYTES) { 43 | return chalk.red('+' + fileSize); 44 | } else if (difference < FIFTY_KILOBYTES && difference > 0) { 45 | return chalk.yellow('+' + fileSize); 46 | } else if (difference < 0) { 47 | return chalk.green(fileSize); 48 | } else { 49 | return ''; 50 | } 51 | } 52 | 53 | // First, read the current file sizes in build directory. 54 | // This lets us display how much they changed later. 55 | recursive(paths.appBuild, (err, fileNames) => { 56 | var previousSizeMap = (fileNames || []) 57 | .filter(fileName => /\.(js|css)$/.test(fileName)) 58 | .reduce((memo, fileName) => { 59 | var contents = fs.readFileSync(fileName); 60 | var key = removeFileNameHash(fileName); 61 | memo[key] = gzipSize(contents); 62 | return memo; 63 | }, {}); 64 | 65 | // Remove all content but keep the directory so that 66 | // if you're in it, you don't end up in Trash 67 | rimrafSync(paths.appBuild + '/*'); 68 | 69 | // Start the webpack build 70 | build(previousSizeMap); 71 | 72 | // Merge with the public folder 73 | copyPublicFolder(); 74 | }); 75 | 76 | // Print a detailed summary of build files. 77 | function printFileSizes(stats, previousSizeMap) { 78 | var assets = stats.toJson().assets 79 | .filter(asset => /\.(js|css)$/.test(asset.name)) 80 | .map(asset => { 81 | var fileContents = fs.readFileSync(paths.appBuild + '/' + asset.name); 82 | var size = gzipSize(fileContents); 83 | var previousSize = previousSizeMap[removeFileNameHash(asset.name)]; 84 | var difference = getDifferenceLabel(size, previousSize); 85 | return { 86 | folder: path.join('build', path.dirname(asset.name)), 87 | name: path.basename(asset.name), 88 | size: size, 89 | sizeLabel: filesize(size) + (difference ? ' (' + difference + ')' : '') 90 | }; 91 | }); 92 | assets.sort((a, b) => b.size - a.size); 93 | var longestSizeLabelLength = Math.max.apply(null, 94 | assets.map(a => stripAnsi(a.sizeLabel).length) 95 | ); 96 | assets.forEach(asset => { 97 | var sizeLabel = asset.sizeLabel; 98 | var sizeLength = stripAnsi(sizeLabel).length; 99 | if (sizeLength < longestSizeLabelLength) { 100 | var rightPadding = ' '.repeat(longestSizeLabelLength - sizeLength); 101 | sizeLabel += rightPadding; 102 | } 103 | console.log( 104 | ' ' + sizeLabel + 105 | ' ' + chalk.dim(asset.folder + path.sep) + chalk.cyan(asset.name) 106 | ); 107 | }); 108 | } 109 | 110 | // Create the production build and print the deployment instructions. 111 | function build(previousSizeMap) { 112 | console.log('Creating an optimized production build...'); 113 | webpack(config).run((err, stats) => { 114 | if (err) { 115 | console.error('Failed to create a production build. Reason:'); 116 | console.error(err.message || err); 117 | process.exit(1); 118 | } 119 | 120 | console.log(chalk.green('Compiled successfully.')); 121 | console.log(); 122 | 123 | console.log('File sizes after gzip:'); 124 | console.log(); 125 | printFileSizes(stats, previousSizeMap); 126 | console.log(); 127 | 128 | var openCommand = process.platform === 'win32' ? 'start' : 'open'; 129 | var homepagePath = require(paths.appPackageJson).homepage; 130 | var publicPath = config.output.publicPath; 131 | if (homepagePath && homepagePath.indexOf('.github.io/') !== -1) { 132 | // "homepage": "http://user.github.io/project" 133 | console.log('The project was built assuming it is hosted at ' + chalk.green(publicPath) + '.'); 134 | console.log('You can control this with the ' + chalk.green('homepage') + ' field in your ' + chalk.cyan('package.json') + '.'); 135 | console.log(); 136 | console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.'); 137 | console.log('To publish it at ' + chalk.green(homepagePath) + ', run:'); 138 | console.log(); 139 | console.log(' ' + chalk.cyan('git') + ' commit -am ' + chalk.yellow('"Save local changes"')); 140 | console.log(' ' + chalk.cyan('git') + ' checkout -B gh-pages'); 141 | console.log(' ' + chalk.cyan('git') + ' add -f build'); 142 | console.log(' ' + chalk.cyan('git') + ' commit -am ' + chalk.yellow('"Rebuild website"')); 143 | console.log(' ' + chalk.cyan('git') + ' filter-branch -f --prune-empty --subdirectory-filter build'); 144 | console.log(' ' + chalk.cyan('git') + ' push -f origin gh-pages'); 145 | console.log(' ' + chalk.cyan('git') + ' checkout -'); 146 | console.log(); 147 | } else if (publicPath !== '/') { 148 | // "homepage": "http://mywebsite.com/project" 149 | console.log('The project was built assuming it is hosted at ' + chalk.green(publicPath) + '.'); 150 | console.log('You can control this with the ' + chalk.green('homepage') + ' field in your ' + chalk.cyan('package.json') + '.'); 151 | console.log(); 152 | console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.'); 153 | console.log(); 154 | } else { 155 | // no homepage or "homepage": "http://mywebsite.com" 156 | console.log('The project was built assuming it is hosted at the server root.'); 157 | if (homepagePath) { 158 | // "homepage": "http://mywebsite.com" 159 | console.log('You can control this with the ' + chalk.green('homepage') + ' field in your ' + chalk.cyan('package.json') + '.'); 160 | console.log(); 161 | } else { 162 | // no homepage 163 | console.log('To override this, specify the ' + chalk.green('homepage') + ' in your ' + chalk.cyan('package.json') + '.'); 164 | console.log('For example, add this to build it for GitHub Pages:') 165 | console.log(); 166 | console.log(' ' + chalk.green('"homepage"') + chalk.cyan(': ') + chalk.green('"http://myname.github.io/myapp"') + chalk.cyan(',')); 167 | console.log(); 168 | } 169 | console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.'); 170 | console.log('You may also serve it locally with a static server:') 171 | console.log(); 172 | console.log(' ' + chalk.cyan('npm') + ' install -g pushstate-server'); 173 | console.log(' ' + chalk.cyan('pushstate-server') + ' build'); 174 | console.log(' ' + chalk.cyan(openCommand) + ' http://localhost:9000'); 175 | console.log(); 176 | } 177 | }); 178 | } 179 | 180 | function copyPublicFolder() { 181 | fs.copySync(paths.appPublic, paths.appBuild, { 182 | dereference: true, 183 | filter: file => file !== paths.appHtml 184 | }); 185 | } 186 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test'; 2 | process.env.PUBLIC_URL = ''; 3 | 4 | // Load environment variables from .env file. Surpress warnings using silent 5 | // if this file is missing. dotenv will never modify any environment variables 6 | // that have already been set. 7 | // https://github.com/motdotla/dotenv 8 | require('dotenv').config({silent: true}); 9 | 10 | const jest = require('jest'); 11 | const argv = process.argv.slice(2); 12 | 13 | // Watch unless on CI 14 | if (!process.env.CI) { 15 | argv.push('--watch'); 16 | } 17 | 18 | 19 | jest.run(argv); 20 | -------------------------------------------------------------------------------- /src/actions/action-types.js: -------------------------------------------------------------------------------- 1 | // login 2 | export const LOGIN_REQUEST = 'LOGIN_REQUEST'; 3 | export const LOGIN_SUCCESS = 'LOGIN_SUCCESS'; 4 | export const LOGIN_FAILURE = 'LOGIN_FAILURE'; 5 | export const GETVERIFYCODE_REQUEST = 'GETVERIFYCODE_REQUEST'; 6 | export const GETVERIFYCODE_SUCCESS = 'GETVERIFYCODE_SUCCESS'; 7 | export const LOGOUT_REQUEST = 'LOGOUT_REQUEST'; 8 | export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS'; 9 | export const LOGIN_ERROR_MESSAGES = 'LOGIN_ERROR_MESSAGES'; 10 | export const LOGIN_LOAD_TAB = 'LOGIN_LOAD_TAB'; 11 | export const LOGIN_UPDATE_FREEZETIME = 'LOGIN_UPDATE_FREEZETIME'; 12 | 13 | // identity 14 | export const GET_PROFILE_SUCCESS = 'GET_PROFILE_SUCCESS'; 15 | 16 | // articles 17 | export const GET_ARTICLE_TAGS = 'GET_ARTICLE_TAGS'; 18 | export const UPDATE_ARTICLE_TAGS = 'UPDATE_ARTICLE_TAGS'; 19 | export const UPDATE_ARTICLE_IMAGES = 'UPDATE_ARTICLE_IMAGES'; 20 | export const UPDATE_ARTICLE_MODEL = 'UPDATE_ARTICLE_MODEL'; 21 | export const UPDATE_ARTICLE_LIST = 'UPDATE_ARTICLE_LIST'; 22 | export const GET_ARTICLES_SUCCESS = 'GET_ARTICLES_SUCCESS'; 23 | export const DELETE_ARTICLE_SUCCESS = 'DELETE_ARTICLE_SUCCESS'; 24 | export const RESET_ARTICLE_MODEL = 'RESET_ARTICLE_MODEL'; 25 | 26 | // JOBOWNER job 27 | export const GET_JOBOWNERJOB_GUILDS = 'GET_JOBOWNERJOB_TAGS'; 28 | export const UPDATE_JOBOWNERJOB_GUILD = 'UPDATE_JOBOWNERJOB_TAGS'; 29 | export const UPDATE_JOBOWNERJOB_USER = 'UPDATE_JOBOWNERJOB_USER'; 30 | export const UPDATE_JOBOWNERJOB_IMAGES = 'UPDATE_JOBOWNERJOB_IMAGES'; 31 | export const UPDATE_JOBOWNERJOB_MODEL = 'UPDATE_JOBOWNERJOB_MODEL'; 32 | export const DELETE_JOBOWNERJOB_SUCCESS = 'DELETE_JOBOWNERJOB_SUCCESS'; 33 | export const RESET_JOBOWNERJOB_MODEL = 'RESET_JOBOWNERJOB_MODEL'; 34 | 35 | // SERVICE job 36 | export const GET_SERVICE_SERVICETYPES = 'GET_SERVICE_SERVICETYPES'; 37 | export const UPDATE_SERVICE_SERVICETYPE = 'UPDATE_SERVICE_SERVICETYPE'; 38 | export const UPDATE_SERVICE_IMAGES = 'UPDATE_SERVICE_IMAGES'; 39 | export const UPDATE_SERVICE_MODEL = 'UPDATE_SERVICE_MODEL'; 40 | export const DELETE_SERVICE_SUCCESS = 'DELETE_SERVICE_SUCCESS'; 41 | export const RESET_SERVICE_MODEL = 'RESET_SERVICE_MODEL'; 42 | export const UPDATE_SERVICE_LIST = 'UPDATE_SERVICE_LIST'; 43 | 44 | // Widgets 45 | export const GET_WIDGETS_SUCCESS = 'GET_WIDGETS_SUCCESS'; 46 | export const DELETE_WIDGET_SUCCESS = 'DELETE_WIDGET_SUCCESS'; 47 | 48 | // Search Layout 49 | export const LOAD_SEARCH_LAYOUT = 'LOAD_SEARCH_LAYOUT'; 50 | 51 | // Dashboard Layout 52 | export const LOAD_DASHBOARD_LAYOUT = 'LOAD_DASHBOARD_LAYOUT'; 53 | export const LOAD_DASHBOARD_TITLE = 'LOAD_DASHBOARD_TITLE'; 54 | export const LOAD_DASHBOARD_COMPLETED = 'LOAD_DASHBOARD_COMPLETED'; 55 | export const UPDATE_DASHBOARD_TAGS = 'UPDATE_DASHBOARD_TAGS'; 56 | export const ALERT = 'ALERT'; 57 | 58 | export const TEST = 'TEST'; 59 | -------------------------------------------------------------------------------- /src/actions/article-actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './action-types'; 2 | 3 | export function getArticlesSuccess(articles) { 4 | return { 5 | type: types.GET_ARTICLES_SUCCESS, 6 | articles 7 | }; 8 | } 9 | 10 | export function getArticleTags(tags) { 11 | return { 12 | type: types.GET_ARTICLE_TAGS, 13 | tags 14 | }; 15 | } 16 | 17 | export function updateArticleTags(tags) { 18 | return { 19 | type: types.UPDATE_ARTICLE_TAGS, 20 | tags 21 | }; 22 | } 23 | export function updateArticleImages(images) { 24 | return { 25 | type: types.UPDATE_ARTICLE_IMAGES, 26 | images 27 | }; 28 | } 29 | export function updateArticleList(articleList) { 30 | return { 31 | type: types.UPDATE_ARTICLE_LIST, 32 | articleList 33 | }; 34 | } 35 | 36 | export function updateArticleModel(article) { 37 | return { 38 | type: types.UPDATE_ARTICLE_MODEL, 39 | article 40 | }; 41 | } 42 | 43 | export function resetArticleModel() { 44 | return { 45 | type: types.RESET_ARTICLE_MODEL 46 | }; 47 | } 48 | 49 | 50 | export function deleteArticleSuccess(articleId) { 51 | return { 52 | type: types.DELETE_ARTICLE_SUCCESS, 53 | articleId 54 | }; 55 | } 56 | 57 | export function articleSuccess(article) { 58 | return { 59 | type: types.USER_PROFILE_SUCCESS, 60 | article 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /src/actions/dashboard-actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './action-types'; 2 | 3 | export function loadDashboardTitle(title) { 4 | return { 5 | type: types.LOAD_DASHBOARD_TITLE, 6 | title 7 | }; 8 | } 9 | 10 | export function loadDashboardCompleted() { 11 | return { 12 | type: types.LOAD_DASHBOARD_COMPLETED 13 | }; 14 | } 15 | 16 | export function updateDashboardSuggestions(suggestions) { 17 | return { 18 | type: types.LOAD_DASHBOARD_SUGGESTIONS, 19 | suggestions 20 | }; 21 | } 22 | 23 | export function showAlert(alert) { 24 | return { 25 | type: types.ALERT, 26 | alert 27 | }; 28 | } -------------------------------------------------------------------------------- /src/actions/job-actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './action-types'; 2 | 3 | export function getJOBsSuccess(JOBs) { 4 | return { 5 | type: types.GET_JOBS_SUCCESS, 6 | JOBs 7 | }; 8 | } 9 | 10 | export function getJOBTags(guilds) { 11 | return { 12 | type: types.GET_JOB_GUILDS, 13 | guilds 14 | }; 15 | } 16 | 17 | export function updateJOBGuild(guild) { 18 | return { 19 | type: types.UPDATE_JOB_GUILD, 20 | guild 21 | }; 22 | } 23 | export function updateJOBUser(user) { 24 | return { 25 | type: types.UPDATE_JOB_USER, 26 | user 27 | }; 28 | } 29 | export function updateJOBImages(images) { 30 | return { 31 | type: types.UPDATE_JOB_IMAGES, 32 | images 33 | }; 34 | } 35 | export function updateJOBList(jobList) { 36 | return { 37 | type: types.UPDATE_JOB_LIST, 38 | jobList 39 | }; 40 | } 41 | 42 | export function updateJOBModel(job) { 43 | return { 44 | type: types.UPDATE_JOB_MODEL, 45 | job 46 | }; 47 | } 48 | 49 | export function resetJOBModel() { 50 | return { 51 | type: types.RESET_JOB_MODEL 52 | }; 53 | } 54 | 55 | export function deleteJOBSuccess(JOBId) { 56 | return { 57 | type: types.DELETE_JOB_SUCCESS, 58 | JOBId 59 | }; 60 | } -------------------------------------------------------------------------------- /src/actions/jobowner-actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './action-types'; 2 | 3 | export function getJOBTags(guilds) { 4 | return { 5 | type: types.GET_JOBOWNERJOB_GUILDS, 6 | guilds 7 | }; 8 | } 9 | 10 | export function updateJOBGuild(guild) { 11 | return { 12 | type: types.UPDATE_JOBOWNERJOB_GUILD, 13 | guild 14 | }; 15 | } 16 | export function updateJOBUser(user) { 17 | return { 18 | type: types.UPDATE_JOBOWNERJOB_USER, 19 | user 20 | }; 21 | } 22 | export function updateJOBImages(images) { 23 | return { 24 | type: types.UPDATE_JOBOWNERJOB_IMAGES, 25 | images 26 | }; 27 | } 28 | 29 | export function updateJOBModel(jobownerJob) { 30 | return { 31 | type: types.UPDATE_JOBOWNERJOB_MODEL, 32 | jobownerJob 33 | }; 34 | } 35 | export function resetJOBModel() { 36 | return { 37 | type: types.RESET_JOBOWNERJOB_MODEL 38 | }; 39 | } 40 | 41 | export function deleteJOBSuccess(jobownerJobId) { 42 | return { 43 | type: types.DELETE_JOBOWNERJOB_SUCCESS, 44 | jobownerJobId 45 | }; 46 | } -------------------------------------------------------------------------------- /src/actions/login-actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './action-types'; 2 | 3 | export function requestLogin(creds) { 4 | return { 5 | type: types.LOGIN_REQUEST, 6 | isFetching: true, 7 | isAuthenticated: false, 8 | creds 9 | } 10 | } 11 | 12 | export function receiveLogin(token) { 13 | return { 14 | type: types.LOGIN_SUCCESS, 15 | isFetching: false, 16 | isAuthenticated: true, 17 | token: token 18 | } 19 | } 20 | 21 | export function requestGETVERIFYCODE(tel) { 22 | return { 23 | type: types.GETVERIFYCODE_REQUEST, 24 | tel 25 | } 26 | } 27 | 28 | export function loginLoadTab(index) { 29 | return { 30 | type: types.LOGIN_LOAD_TAB, 31 | activeTab: index 32 | } 33 | } 34 | 35 | export function receiveGETVERIFYCODE() { 36 | return { 37 | type: types.GETVERIFYCODE_SUCCESS 38 | } 39 | } 40 | 41 | export function loginErrorMessages(messages) { 42 | return { 43 | type: types.LOGIN_ERROR_MESSAGES, 44 | messages: messages 45 | } 46 | } 47 | 48 | export function loginError(key,message) { 49 | return { 50 | type: types.LOGIN_FAILURE, 51 | isFetching: false, 52 | isAuthenticated: false, 53 | messages: [[key, message]] 54 | } 55 | } 56 | 57 | export function requestLogout() { 58 | return { 59 | type: types.LOGOUT_REQUEST, 60 | isFetching: true, 61 | isAuthenticated: true 62 | } 63 | } 64 | 65 | export function receiveLogout() { 66 | return { 67 | type: types.LOGOUT_SUCCESS, 68 | isFetching: false, 69 | isAuthenticated: false 70 | } 71 | } 72 | 73 | export function updateFreezeTime(t) { 74 | return { 75 | type: types.LOGIN_UPDATE_FREEZETIME, 76 | freezeTime: t.minutes + ':' + t.seconds, 77 | isActive: t.total !== 0 78 | } 79 | } 80 | 81 | export const LOGIN_TAB = 'LOGIN_TAB'; 82 | export const REGISTER_TAB = 'REGISTER_TAB'; -------------------------------------------------------------------------------- /src/actions/service-actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './action-types'; 2 | 3 | export function getServiceTypes(serviceTypes) { 4 | return { 5 | type: types.GET_SERVICE_SERVICETYPES, 6 | serviceTypes 7 | }; 8 | } 9 | 10 | export function updateServiceType(serviceType) { 11 | return { 12 | type: types.UPDATE_SERVICE_SERVICETYPES, 13 | serviceType 14 | }; 15 | } 16 | export function updateServiceImages(images) { 17 | return { 18 | type: types.UPDATE_SERVICE_IMAGES, 19 | images 20 | }; 21 | } 22 | 23 | export function updateServiceModel(service) { 24 | return { 25 | type: types.UPDATE_SERVICE_MODEL, 26 | service 27 | }; 28 | } 29 | export function updateBMultiInput(multiInput) { 30 | return { 31 | type: types.UPDATE_BMULTI, 32 | multiInput 33 | }; 34 | } 35 | 36 | export function resetServiceModel() { 37 | return { 38 | type: types.RESET_SERVICE_MODEL 39 | }; 40 | } 41 | 42 | export function deleteServiceSuccess(serviceId) { 43 | return { 44 | type: types.DELETE_SERVICE_SUCCESS, 45 | serviceId 46 | }; 47 | } 48 | 49 | export function updateServiceList(serviceList) { 50 | return { 51 | type: types.UPDATE_SERVICE_LIST, 52 | serviceList 53 | }; 54 | } -------------------------------------------------------------------------------- /src/api/article-api.js: -------------------------------------------------------------------------------- 1 | import api from './urls'; 2 | import store from '../store'; 3 | import { getArticleTags, updateArticleModel,updateArticleList } from '../actions/article-actions'; 4 | import * as urls from './urls'; 5 | import qs from 'qs'; 6 | import ArticleModel from '../models/article'; 7 | 8 | // Get all tags 9 | 10 | export function getTags() { 11 | 12 | // mock action ----------------------------------------- 13 | //------------------------------------------------------ 14 | 15 | return new Promise((resolve, reject) => { 16 | 17 | setTimeout(function () { 18 | 19 | let tags = [{ label: 'سلام', value: 1 }, { label: 'دات نت', value: 2 }, { label: 'جاوا اسکریپت', value: 3 }, { label: 'تست', value:4 }, { label: 'test', value: 5 }, { label: 'tag', value: 6 }, { label: 'mock test', value:7 }]; 20 | store.dispatch(getArticleTags(tags)); 21 | 22 | resolve('ok'); 23 | 24 | }, 500); 25 | 26 | }); 27 | 28 | //------------------------------------------------------ 29 | 30 | 31 | // a real example -------------------------------------- 32 | //------------------------------------------------------ 33 | 34 | // return api.get(urls.GETARTICLETAGS) 35 | // .then(response => { 36 | // store.dispatch(getArticleTags(response.data)); 37 | // return response; 38 | // }); 39 | 40 | //------------------------------------------------------ 41 | } 42 | 43 | // Add or Update an article 44 | 45 | export function addOrUpdate(article) { 46 | 47 | console.log(article.Id); 48 | 49 | if(article.Id>0) 50 | return update(article); 51 | else 52 | return add(article); 53 | 54 | } 55 | 56 | // Add article 57 | 58 | export function add(article) { 59 | 60 | return api.post(urls.ARTICLE, qs.stringify(article)) 61 | .then(response => { 62 | if (response.status === 200) { 63 | // store.dispatch(receiveGETVERIFYCODE(response.data)); 64 | // store.dispatch(push("/")); 65 | } else { 66 | // store.dispatch(loginError('',response.data)); 67 | } 68 | }) 69 | .catch(error => { 70 | if (error.response) { 71 | // store.dispatch(loginError('',error.response.data)); 72 | } else { 73 | // store.dispatch(loginError('',error.message)); 74 | } 75 | }); 76 | } 77 | 78 | // Update an article 79 | 80 | export function update(article) { 81 | 82 | return api.put(urls.ARTICLE, qs.stringify(article)) 83 | .then(response => { 84 | if (response.status === 200) { 85 | // store.dispatch(receiveGETVERIFYCODE(response.data)); 86 | // store.dispatch(push("/")); 87 | } else { 88 | // store.dispatch(loginError('',response.data)); 89 | } 90 | }) 91 | .catch(error => { 92 | if (error.response) { 93 | // store.dispatch(loginError('',error.response.data)); 94 | } else { 95 | // store.dispatch(loginError('',error.message)); 96 | } 97 | }); 98 | } 99 | 100 | // get article 101 | 102 | export function getArticle(id) { 103 | 104 | // mock action ----------------------------------------- 105 | //------------------------------------------------------ 106 | 107 | return new Promise((resolve, reject) => { 108 | 109 | setTimeout(function () { 110 | 111 | let imageBaseUrl = 'https://unsplash.it/300/400/?random='; 112 | 113 | let model = new ArticleModel(); 114 | 115 | model.Id = id; 116 | model.Title = 'عنوان مقاله '+id; 117 | model.Abstract = 'متن خلاصه '+id; 118 | model.Images = [{ name: "1", url: imageBaseUrl+"1" }, { name: "2", url: imageBaseUrl+"2" }, { name: "3", url: imageBaseUrl+"3" }]; 119 | model.SelectedTags = [{ label: 'سلام', value: 1 }, { label: 'دات نت', value: 2 }, { label: 'جاوا اسکریپت', value: 3 }]; 120 | 121 | store.dispatch(updateArticleModel(model)); 122 | 123 | resolve('ok'); 124 | 125 | 126 | }, 500); 127 | 128 | }); 129 | 130 | //------------------------------------------------------ 131 | 132 | // a real example -------------------------------------- 133 | //------------------------------------------------------ 134 | 135 | // return api.get(urls.ARTICLE+"/"+id) 136 | // .then(response => { 137 | // if (response.status === 200) { 138 | // store.dispatch(updateArticleModel(response.data)); 139 | // // store.dispatch(push("/")); 140 | // } else { 141 | // // store.dispatch(loginError('',response.data)); 142 | // } 143 | // }) 144 | // .catch(error => { 145 | // if (error.response) { 146 | // // store.dispatch(loginError('',error.response.data)); 147 | // } else { 148 | // // store.dispatch(loginError('',error.message)); 149 | // } 150 | // }); 151 | 152 | //------------------------------------------------------ 153 | 154 | } 155 | 156 | // get article list 157 | 158 | export function getArticleList() { 159 | 160 | // a real example -------------------------------------- 161 | //------------------------------------------------------ 162 | 163 | return new Promise((resolve, reject) => { 164 | 165 | setTimeout(function () { 166 | 167 | let articles=[{Id:1,Title:"عنوان ۱"},{Id:2,Title:"عنوان ۲"},{Id:3,Title:"عنوان ۳"}]; 168 | 169 | store.dispatch(updateArticleList(articles)); 170 | 171 | resolve('ok'); 172 | }, 500); 173 | 174 | }); 175 | 176 | //------------------------------------------------------ 177 | 178 | // a real example -------------------------------------- 179 | //------------------------------------------------------ 180 | 181 | // return api.get(urls.ARTICLE) 182 | // .then(response => { 183 | // if (response.status === 200) { 184 | // store.dispatch(updateArticleList(response.data)); 185 | // // store.dispatch(push("/")); 186 | // } else { 187 | // // store.dispatch(loginError('',response.data)); 188 | // } 189 | // }) 190 | // .catch(error => { 191 | // if (error.response) { 192 | // // store.dispatch(loginError('',error.response.data)); 193 | // } else { 194 | // // store.dispatch(loginError('',error.message)); 195 | // } 196 | // }); 197 | 198 | //------------------------------------------------------ 199 | } -------------------------------------------------------------------------------- /src/api/article-list-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import SimpleList from '../views/simple-list'; 4 | import store from '../../store'; 5 | import { loadDashboardTitle, showAlert } from '../../actions/dashboard-actions'; 6 | import * as articleApi from '../../api/article-api'; 7 | import * as swAlert from '../../helpers/sweet-alert'; 8 | import { push } from 'react-router-redux'; 9 | 10 | class ArticleContainer extends React.Component { 11 | constructor(props) { 12 | super(props); 13 | this.deleteItem = this.handleClick.bind(this); 14 | } 15 | componentDidMount() { 16 | store.dispatch(loadDashboardTitle(this.props.route.title)); 17 | articleApi.getArticleList(); 18 | } 19 | componentDidUpdate() { 20 | //ajax update 21 | if (!this.props.title) { 22 | store.dispatch(loadDashboardTitle(this.props.route.title)); 23 | return; 24 | } 25 | //change route 26 | if (this.props.route.title === this.props.title) 27 | return; 28 | store.dispatch(loadDashboardTitle(this.props.route.title)); 29 | } 30 | editItem(id) { 31 | store.dispatch(push('/ReactAdmin/admin/article/edit/' + id)); 32 | } 33 | deleteItem(id) { 34 | swAlert.warning(() => this.onConfirmDelete(id)); 35 | } 36 | onConfirmDelete(payload) { 37 | swAlert.success(() => { alert(`deleted item id:${payload}asd`); }); 38 | } 39 | hideAlert() { 40 | store.dispatch(showAlert(null)); 41 | } 42 | render() { 43 | return ( 44 | 45 | ); 46 | } 47 | }; 48 | 49 | const mapStateToProps = store => { 50 | return { 51 | title: store.dashboardLayoutState.title, 52 | articleList: store.articleState.articleList 53 | }; 54 | }; 55 | 56 | export default connect(mapStateToProps)(ArticleContainer); -------------------------------------------------------------------------------- /src/api/identity-api.js: -------------------------------------------------------------------------------- 1 | import store from '../store'; 2 | import { requestLogin, receiveLogin, loginError, requestGETVERIFYCODE, receiveGETVERIFYCODE} from '../actions/login-actions'; 3 | import { push } from 'react-router-redux'; 4 | import jwt_decode from 'jwt-decode'; 5 | // import api from './urls'; 6 | // import qs from 'qs'; 7 | // import * as urls from './urls'; 8 | // import platform from 'platform'; 9 | 10 | // Login 11 | export function login(info = '') { 12 | 13 | store.dispatch(requestLogin(info)); 14 | 15 | 16 | // mock action ----------------------------------------- 17 | //------------------------------------------------------ 18 | return new Promise((resolve, reject) => { 19 | setTimeout(function () { successLogin(info.verifycode); resolve('ok');}, 500); 20 | }); 21 | //------------------------------------------------------ 22 | 23 | // a real example -------------------------------------- 24 | //------------------------------------------------------ 25 | 26 | // let userData = { 27 | // username: JSON.stringify({ "Tel": info.tel, OSName: platform.os.family + ' ' + platform.os.version, DeviceName: platform.name }), 28 | // grant_type: "password", 29 | // password: info.verifycode 30 | // }; 31 | 32 | // return api.post(urls.LOGIN, qs.stringify(userData)) 33 | // .then(response => { 34 | // if (response.status === 200) { 35 | // // If login was successful, set the token in local storage 36 | // localStorage.setItem('identityToken', JSON.stringify(response.data)); 37 | // store.dispatch(receiveLogin(response.data)); 38 | // store.dispatch(push("/")); 39 | // } else { 40 | // store.dispatch(loginError("verifycode","کد فعالسازی نامعتبر است.")); 41 | // } 42 | // }) 43 | // .catch(error => { 44 | // if (error.response) { 45 | // store.dispatch(loginError("verifycode","کد فعالسازی نامعتبر است.")); 46 | // } else { 47 | // store.dispatch(loginError("verifycode","کد فعالسازی نامعتبر است.")); 48 | // } 49 | // }); 50 | 51 | //------------------------------------------------------ 52 | 53 | } 54 | 55 | // Get Verify Code 56 | export function getverifycode(tel) { 57 | 58 | store.dispatch(requestGETVERIFYCODE(tel)); 59 | 60 | // mock action ----------------------------------------- 61 | //------------------------------------------------------ 62 | return new Promise((resolve, reject) => { 63 | setTimeout(function () { successSentVerifyCode(); resolve('ok'); }, 3000); 64 | }); 65 | //------------------------------------------------------ 66 | 67 | // a real example -------------------------------------- 68 | //------------------------------------------------------ 69 | 70 | // let data = { tel }; 71 | 72 | // return api.post(urls.GETVERIFYCODE, qs.stringify(data)) 73 | // .then(response => { 74 | // if (response.status === 200) { 75 | // store.dispatch(receiveGETVERIFYCODE()); 76 | // } else { 77 | // store.dispatch(loginError('', response.data)); 78 | // } 79 | // }) 80 | // .catch(error => { 81 | // if (error.response) { 82 | // store.dispatch(loginError('', error.response.data)); 83 | // } else { 84 | // store.dispatch(loginError('', error.message)); 85 | // } 86 | // }); 87 | 88 | //------------------------------------------------------ 89 | } 90 | 91 | // Remove User Identity Token 92 | export function logout() { 93 | // store.dispatch(requestLogout()); 94 | localStorage.removeItem('identityToken'); 95 | // store.dispatch(receiveLogout()); 96 | store.dispatch(push("/ReactAdmin/login")); 97 | } 98 | 99 | // Check User Login Status 100 | export function loggedIn() { 101 | return localStorage.getItem('identityToken') ? true : false; 102 | } 103 | 104 | // Check User Role 105 | export function hasRole(role) { 106 | let token = jwt_decode(localStorage.getItem('identityToken')); 107 | return (token.role.indexOf(role) !== -1); 108 | } 109 | 110 | // Get User Identity Token 111 | export function token() { 112 | return localStorage.getItem('identityToken'); 113 | } 114 | 115 | // Get User Identity Token 116 | export function getDecodedToken() { 117 | return jwt_decode(localStorage.getItem('identityToken')); 118 | } 119 | 120 | // Mocking Functions --------------------------------------------- 121 | 122 | function successLogin(verifycode) { 123 | 124 | if(verifycode.length!==5) 125 | { 126 | store.dispatch(loginError('',"شماره تاییدیه باید ۵ رقم باشد.")); 127 | return; 128 | } 129 | 130 | //with "Admin" role in jwt token 131 | var identityToken = { 132 | "token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOjEsInJvbGUiOiJBZG1pbiIsImNlcnRzZXJpYWxudW1iZXIiOiI0MTQ3YmE1NjQ2ZGM0MGRkODkzNTU4ZjcwMmFhZGVhYiIsImZ1bGxuYW1lIjoi2LPbjNivINmF2K3Zhdiv2LHYttinINio2LHZhtiq24wiLCJuYmYiOjE0OTcwMTU1MTYsImV4cCI6MTQ5NzAxNjExNiwiaWF0IjoxNDk3MDE1NTE2LCJpc3MiOiJodHRwOi8vYmVybmV0aS5pciIsImF1ZCI6IkV4YW1wbGVJc3N1ZXIifQ.v3MqXBmxsdaqsbMOnCZhAsYt5i34sNhcT4kayO2vyn8", 133 | "refresh_token": "45ce29e9e7794cf3bc648b77d6cd1ee6", 134 | "expires_in": "2017-06-09T13:48:36.4920929Z" 135 | }; 136 | 137 | //with "User" role in jwt token 138 | if (verifycode === "12345") 139 | identityToken.token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOjEsInJvbGUiOiJVc2VyIiwiY2VydHNlcmlhbG51bWJlciI6IjQxNDdiYTU2NDZkYzQwZGQ4OTM1NThmNzAyYWFkZWFiIiwiZnVsbG5hbWUiOiLYs9uM2K8g2YXYrdmF2K_Ysdi22Kcg2KjYsdmG2KrbjCIsIm5iZiI6MTQ5NzAxNTUxNiwiZXhwIjoxNDk3MDE2MTE2LCJpYXQiOjE0OTcwMTU1MTYsImlzcyI6Imh0dHA6Ly9iZXJuZXRpLmlyIiwiYXVkIjoiRXhhbXBsZUlzc3VlciJ9.hVMZLOVn9tvy-Md0aho6PXEkKAXLgSm5_vdIDk6ehec"; 140 | 141 | localStorage.setItem('identityToken', JSON.stringify(identityToken)); 142 | 143 | store.dispatch(receiveLogin(identityToken)); 144 | store.dispatch(push("/ReactAdmin/")); 145 | } 146 | 147 | function successSentVerifyCode() { 148 | store.dispatch(receiveGETVERIFYCODE()); 149 | } -------------------------------------------------------------------------------- /src/api/jobowner-api.js: -------------------------------------------------------------------------------- 1 | import api from './urls'; 2 | import store from '../store'; 3 | import { getJOBTags, updateJOBModel } from '../actions/jobowner-actions'; 4 | import * as urls from './urls'; 5 | import qs from 'qs'; 6 | 7 | /** 8 | * Get all guilds 9 | */ 10 | 11 | export function getGuilds() { 12 | return api.get(urls.GETJOBGUILDS) 13 | .then(response => { 14 | store.dispatch(getJOBTags(response.data)); 15 | return response; 16 | }); 17 | } 18 | 19 | /** 20 | * update JOB 21 | */ 22 | 23 | export function update(JOB) { 24 | 25 | return api.put(urls.JOBOWENRJOBS+`/{JOB.Id}`, qs.stringify(JOB)) 26 | .then(response => { 27 | if (response.status === 200) { 28 | // store.dispatch(receiveGETVERIFYCODE(response.data)); 29 | // store.dispatch(push("/")); 30 | } else { 31 | // store.dispatch(loginError('',response.data)); 32 | } 33 | }) 34 | .catch(error => { 35 | if (error.response) { 36 | // store.dispatch(loginError('',error.response.data)); 37 | } else { 38 | // store.dispatch(loginError('',error.message)); 39 | } 40 | }); 41 | } 42 | 43 | /** 44 | * get JOB 45 | */ 46 | 47 | export function getJOB() { 48 | 49 | return api.get(urls.JOBOWENRJOBS) 50 | .then(response => { 51 | if (response.status === 200) { 52 | store.dispatch(updateJOBModel(response.data)); 53 | // store.dispatch(push("/")); 54 | } else { 55 | // store.dispatch(loginError('',response.data)); 56 | } 57 | }) 58 | .catch(error => { 59 | if (error.response) { 60 | // store.dispatch(loginError('',error.response.data)); 61 | } else { 62 | // store.dispatch(loginError('',error.message)); 63 | } 64 | }); 65 | 66 | } -------------------------------------------------------------------------------- /src/api/service-api.js: -------------------------------------------------------------------------------- 1 | import store from '../store'; 2 | import { getServiceTypes, updateServiceModel ,updateServiceList} from '../actions/service-actions'; 3 | import serviceModel from '../models/service'; 4 | import moment from 'moment-jalaali'; 5 | // import * as urls from './urls'; 6 | // import qs from 'qs'; 7 | // import api from './urls'; 8 | 9 | // Get All ServiceTypes 10 | 11 | export function getTypes() { 12 | 13 | // mock action ----------------------------------------- 14 | //------------------------------------------------------ 15 | 16 | return new Promise((resolve, reject) => { 17 | 18 | setTimeout(function () { 19 | 20 | let serviceTypes = [{ label: 'سرویس نوع ۱', value: 1 }, { label: 'سرویس نوع ۲', value: 2 }, { label: 'سرویس نوع ۳', value: 3 }, { label: 'سرویس نوع ۴', value: 4 }]; 21 | store.dispatch(getServiceTypes(serviceTypes)); 22 | 23 | resolve('ok'); 24 | 25 | }, 500); 26 | 27 | }); 28 | 29 | //------------------------------------------------------ 30 | 31 | 32 | // a real example -------------------------------------- 33 | //------------------------------------------------------ 34 | 35 | // return api.get(urls.GETMODULES) 36 | // .then(response => { 37 | // store.dispatch(getServiceTypes(response.data)); 38 | // return response; 39 | // }); 40 | 41 | //------------------------------------------------------ 42 | } 43 | 44 | // Add Plan 45 | 46 | export function add(plan) { 47 | 48 | // return api.post(urls.PLANS, qs.stringify(plan)) 49 | // .then(response => { 50 | // if (response.status === 200) { 51 | // // store.dispatch(receiveGETVERIFYCODE(response.data)); 52 | // // store.dispatch(push("/")); 53 | // } else { 54 | // // store.dispatch(loginError('',response.data)); 55 | // } 56 | // }) 57 | // .catch(error => { 58 | // if (error.response) { 59 | // // store.dispatch(loginError('',error.response.data)); 60 | // } else { 61 | // // store.dispatch(loginError('',error.message)); 62 | // } 63 | // }); 64 | } 65 | 66 | 67 | export function getJob(id) { 68 | 69 | // mock action ----------------------------------------- 70 | //------------------------------------------------------ 71 | 72 | return new Promise((resolve, reject) => { 73 | 74 | setTimeout(function () { 75 | 76 | let imageBaseUrl = 'https://unsplash.it/300/400/?random='; 77 | let model = new serviceModel(); 78 | 79 | model ={ 80 | "Id":id, 81 | "Title":"سرویس "+id, 82 | "Description":" توضیحات"+id, 83 | "Price":"1000", 84 | "DiscountCode":"freeforall", 85 | "Discount":"60", 86 | "StartDiscount":moment("Sat Jun 10 2017 05:40:05 GMT+0430"), 87 | "EndDiscount":moment("Sat Jun 17 2017 05:40:05 GMT+0430"), 88 | "Images":[{"name":"acc1a9d0-e6c4-44d5-a118-7409f86cc603.png", 89 | "url":imageBaseUrl+id}], 90 | "MultiInput": 91 | [{"Id":"1","CreditTime":"10","SelectedModule":1}, {"Id":"2","CreditTime":"7","SelectedModule":3}]} 92 | 93 | 94 | store.dispatch(updateServiceModel(model)); 95 | 96 | resolve('ok'); 97 | 98 | }, 500); 99 | 100 | }); 101 | 102 | //------------------------------------------------------ 103 | 104 | // a real example -------------------------------------- 105 | //------------------------------------------------------ 106 | 107 | // return api.get(urls.SERVICES+"/"+id) 108 | // .then(response => { 109 | // if (response.status === 200) { 110 | // store.dispatch(updateServiceModel(response.data)); 111 | // // store.dispatch(push("/")); 112 | // } else { 113 | // // store.dispatch(loginError('',response.data)); 114 | // } 115 | // }) 116 | // .catch(error => { 117 | // if (error.response) { 118 | // // store.dispatch(loginError('',error.response.data)); 119 | // } else { 120 | // // store.dispatch(loginError('',error.message)); 121 | // } 122 | // }); 123 | 124 | //------------------------------------------------------ 125 | 126 | } 127 | 128 | // get article list 129 | 130 | export function getList() { 131 | 132 | // a real example -------------------------------------- 133 | //------------------------------------------------------ 134 | 135 | return new Promise((resolve, reject) => { 136 | 137 | setTimeout(function () { 138 | 139 | let list=[{Id:1,Title:"سرویس ۱"},{Id:2,Title:"سرویس ۲"},{Id:3,Title:"سرویس ۳"}]; 140 | 141 | store.dispatch(updateServiceList(list)); 142 | 143 | resolve('ok'); 144 | }, 500); 145 | 146 | }); 147 | 148 | //------------------------------------------------------ 149 | 150 | // a real example -------------------------------------- 151 | //------------------------------------------------------ 152 | 153 | // return api.get(urls.ARTICLE) 154 | // .then(response => { 155 | // if (response.status === 200) { 156 | // store.dispatch(updateArticleList(response.data)); 157 | // // store.dispatch(push("/")); 158 | // } else { 159 | // // store.dispatch(loginError('',response.data)); 160 | // } 161 | // }) 162 | // .catch(error => { 163 | // if (error.response) { 164 | // // store.dispatch(loginError('',error.response.data)); 165 | // } else { 166 | // // store.dispatch(loginError('',error.message)); 167 | // } 168 | // }); 169 | 170 | //------------------------------------------------------ 171 | } -------------------------------------------------------------------------------- /src/api/urls.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import * as loginAPI from './identity-api'; 3 | 4 | 5 | // create apiInstance by axios -------------------------------------- 6 | // ------------------------------------------------------------------- 7 | 8 | const apiInstance = axios.create({ 9 | timeout: 10000, 10 | // `withCredentials` indicates whether or not cross-site Access-Control requests 11 | // should be made using credentials 12 | //'Access-Control-Allow-Origin' header 13 | withCredentials: false 14 | }); 15 | 16 | apiInstance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 17 | 18 | //If exist Bearer token, add it into Authorization header 19 | if (JSON.parse(loginAPI.token())) { 20 | let token = JSON.parse(loginAPI.token()).token; 21 | // config.headers['authorization'] = 'Bearer ' + token; 22 | apiInstance.defaults.headers.common['Authorization'] = 'Bearer ' + token; 23 | } 24 | 25 | export default apiInstance 26 | 27 | // ------------------------------------------------------------------- 28 | 29 | 30 | // Upload Url -------------------------------------------------------- 31 | // NOTE:THIS IS TEMP UPLOAD DEMO URL---------------------------------- 32 | // ------------------------------------------------------------------- 33 | 34 | export const BASEFILEUPLOAD = 'http://berneti.ir:8888/api/v1/upload/folder/demo'; 35 | 36 | // 37 | // 38 | // 39 | // ------------------------------------------------------------------- 40 | 41 | 42 | 43 | // api static urls --------------------------------------------------- 44 | // ------------------------------------------------------------------- 45 | 46 | export const BASEURL='http://localhost:8083'; 47 | 48 | //login 49 | export const LOGIN = BASEURL+'/api/v1/account/login'; 50 | export const GETVERIFYCODE = BASEURL+'/api/v1/account/getverifycode'; 51 | 52 | //user 53 | export const USER = BASEURL+'/api/v1/users'; 54 | 55 | //jobowners 56 | export const JOBOWNERS = BASEURL+'/api/v1/jobowners'; 57 | 58 | //article 59 | export const ARTICLE = BASEURL+'/api/v1/article'; 60 | export const GETARTICLETAGS = BASEURL+'/api/v1/article/tags'; 61 | 62 | //job 63 | export const JOB = BASEURL+'/api/v1/admin/jobs'; 64 | 65 | //guilds 66 | export const GETJOBGUILDS = BASEURL+'/api/v1/guilds'; 67 | 68 | //modules 69 | export const GETMODULES = BASEURL+'/api/v1/main/modules'; 70 | 71 | //plans 72 | export const PLANS = BASEURL+'/api/v1/admin/plans'; 73 | 74 | //serviceTypes 75 | export const GETSERVICETYPES = BASEURL+'/api/v1/servicetypes'; 76 | 77 | //jobOwner Jobs 78 | export const JOBOWENRJOBS = BASEURL+'/api/v1/jobowner/jobs'; 79 | 80 | // ------------------------------------------------------------------- -------------------------------------------------------------------------------- /src/components/containers/article-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import Article from '../views/article'; 4 | import store from '../../store'; 5 | import { loadDashboardCompleted } from '../../actions/dashboard-actions'; 6 | import { resetArticleModel } from '../../actions/article-actions'; 7 | import * as articleApi from '../../api/article-api'; 8 | 9 | class ArticleContainer extends React.Component { 10 | componentDidMount() { 11 | 12 | let _current = this; 13 | 14 | this.type = this.props.route.title; //this is the name of the route 15 | 16 | if (this.props.route.isEditRoute) { 17 | 18 | let id = this.props.params.itemId; 19 | 20 | //fetch tags list from api 21 | articleApi.getTags().then(function () { 22 | //fetch registered article data from api 23 | articleApi.getArticle(id); 24 | }); 25 | 26 | } else { 27 | //fetch tags list 28 | articleApi.getTags(); 29 | } 30 | 31 | } 32 | componentDidUpdate(prevProps) { 33 | 34 | if(!this.props.isLoaded && !this.props.route.isEditRoute){ 35 | this.refs.child.clearFiles(); 36 | store.dispatch(resetArticleModel()); 37 | store.dispatch(loadDashboardCompleted()); 38 | } 39 | 40 | } 41 | submit() { 42 | 43 | event.preventDefault(); 44 | let data = this.refs.child.getData(); 45 | console.log(data); 46 | 47 | // articleApi.addOrUpdate(data); 48 | 49 | } 50 | render() { 51 | return ( 52 |
53 | ); 54 | } 55 | 56 | }; 57 | 58 | const mapStateToProps = store => { 59 | return { 60 | isLoaded: store.dashboardLayoutState.isLoaded, 61 | article: store.articleState.article, 62 | suggestions: store.articleState.suggestions 63 | }; 64 | }; 65 | 66 | export default connect(mapStateToProps)(ArticleContainer); 67 | -------------------------------------------------------------------------------- /src/components/containers/article-list-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import SimpleList from '../views/simple-list'; 4 | import store from '../../store'; 5 | import { loadDashboardTitle, showAlert } from '../../actions/dashboard-actions'; 6 | import * as articleApi from '../../api/article-api'; 7 | import * as swAlert from '../../helpers/sweet-alert'; 8 | import { push } from 'react-router-redux'; 9 | 10 | class ArticleContainer extends React.Component { 11 | constructor(props) { 12 | super(props); 13 | this.deleteItem = this.deleteItem.bind(this); 14 | } 15 | componentDidMount() { 16 | store.dispatch(loadDashboardTitle(this.props.route.title)); 17 | articleApi.getArticleList(); 18 | } 19 | componentDidUpdate() { 20 | //ajax update 21 | if (!this.props.title) { 22 | store.dispatch(loadDashboardTitle(this.props.route.title)); 23 | return; 24 | } 25 | //change route 26 | if (this.props.route.title === this.props.title) 27 | return; 28 | store.dispatch(loadDashboardTitle(this.props.route.title)); 29 | } 30 | editItem(id) { 31 | store.dispatch(push('/ReactAdmin/admin/article/edit/' + id)); 32 | } 33 | deleteItem(id) { 34 | swAlert.warning(() => this.onConfirmDelete(id)); 35 | } 36 | onConfirmDelete(payload) { 37 | swAlert.success(() => { alert(`deleted item id:${payload}`); }); 38 | } 39 | hideAlert() { 40 | store.dispatch(showAlert(null)); 41 | } 42 | render() { 43 | return ( 44 | 45 | ); 46 | } 47 | }; 48 | 49 | const mapStateToProps = store => { 50 | return { 51 | title: store.dashboardLayoutState.title, 52 | articleList: store.articleState.articleList 53 | }; 54 | }; 55 | 56 | export default connect(mapStateToProps)(ArticleContainer); -------------------------------------------------------------------------------- /src/components/containers/dashboard-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import Dashboard from '../views/dashboard'; 4 | 5 | class DashboardContainer extends React.Component { 6 | render() { 7 | return ( 8 |
9 | 10 |
11 | ); 12 | } 13 | }; 14 | 15 | const mapStateToProps = store => { 16 | return store.loginState; 17 | }; 18 | 19 | export default connect(mapStateToProps)(DashboardContainer); 20 | -------------------------------------------------------------------------------- /src/components/containers/jobownerJob-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import JobOwnerJob from '../views/jobownerJob'; 4 | import store from '../../store'; 5 | import { loadDashboardTitle } from '../../actions/dashboard-actions'; 6 | import * as jobApi from '../../api/jobowner-api'; 7 | 8 | class jobownerJobContainer extends React.Component { 9 | componentDidMount() { 10 | let _current = this; 11 | 12 | store.dispatch(loadDashboardTitle(this.props.route.title)); 13 | 14 | jobApi.getGuilds().then(function () { 15 | 16 | jobApi.getJOB(); 17 | 18 | }); 19 | 20 | } 21 | submit() { 22 | 23 | event.preventDefault(); 24 | let data = this.refs.child.getData(); 25 | console.log(data); 26 | // jobApi.update(data); 27 | 28 | } 29 | render() { 30 | return ( 31 | 32 | ); 33 | } 34 | 35 | }; 36 | 37 | const mapStateToProps = store => { 38 | return { 39 | isLoaded: store.dashboardLayoutState.isLoaded, 40 | job: store.jobownerState.jobownerJob, 41 | test: store.jobownerState.test, 42 | guilds: store.jobownerState.guilds 43 | }; 44 | }; 45 | 46 | export default connect(mapStateToProps)(jobownerJobContainer); 47 | -------------------------------------------------------------------------------- /src/components/containers/login-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import Login from '../views/login'; 4 | import store from '../../store'; 5 | import * as loginApi from '../../api/identity-api'; 6 | import { push } from 'react-router-redux'; 7 | import { loginLoadTab, updateFreezeTime, LOGIN_TAB, REGISTER_TAB } from '../../actions/login-actions'; 8 | import { IsValidLogin } from '../../validations/login-validation'; 9 | import { initTimer } from '../../helpers/timer'; 10 | 11 | class LoginContainer extends React.Component { 12 | constructor(props) { 13 | super(props); 14 | this.getverifycode = this.getverifycode.bind(this); 15 | this.getverifycodeHandler = this.getverifycodeHandler.bind(this); 16 | this.getverifycodeKeyPress = this.getverifycodeKeyPress.bind(this); 17 | this.login = this.login.bind(this); 18 | this.loginHandler = this.loginHandler.bind(this); 19 | this.loginKeyPress = this.loginKeyPress.bind(this); 20 | } 21 | 22 | componentDidMount() { 23 | 24 | if (this.props.isAuthenticated) { 25 | store.dispatch(push('/ReactAdmin/')); 26 | } 27 | 28 | } 29 | updateFreezeTime(t) { 30 | 31 | store.dispatch(updateFreezeTime(t)); 32 | 33 | } 34 | getverifycode() { 35 | 36 | let info = this.refs.child.getInfo(); 37 | 38 | if (IsValidLogin({ tel: info.tel })) { 39 | store.dispatch(loginLoadTab(REGISTER_TAB)); 40 | loginApi.getverifycode(info.tel); 41 | initTimer(.2, this.updateFreezeTime);// set freeze time 42 | } 43 | 44 | } 45 | getverifycodeHandler(e) { 46 | 47 | e.preventDefault(); 48 | this.getverifycode(); 49 | 50 | } 51 | getverifycodeKeyPress(e) { 52 | 53 | if (e.key === 'Enter') { 54 | this.getverifycode(); 55 | } 56 | 57 | } 58 | login(event) { 59 | 60 | let info = this.refs.child.getInfo(); 61 | 62 | if (IsValidLogin(info) && !this.props.isFetching) { 63 | loginApi.login(info); 64 | } 65 | 66 | } 67 | loginHandler(event) { 68 | 69 | event.preventDefault(); 70 | this.login(); 71 | 72 | } 73 | loginKeyPress(event) { 74 | 75 | let info = this.refs.child.getInfo(); 76 | if (info.verifycode.length > 4) 77 | this.login(); 78 | 79 | } 80 | telEdit(event) { 81 | 82 | event.preventDefault(); 83 | store.dispatch(loginLoadTab(LOGIN_TAB)); 84 | 85 | } 86 | 87 | render() { 88 | return ( 89 |
90 | 98 |
99 | ); 100 | } 101 | 102 | }; 103 | 104 | const mapStateToProps = store => { 105 | return store.loginState; 106 | }; 107 | 108 | export default connect(mapStateToProps)(LoginContainer); -------------------------------------------------------------------------------- /src/components/containers/main-layout-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import MainLayout from '../layouts/main-layout'; 4 | 5 | class MainLayoutContainer extends React.Component { 6 | 7 | render() { 8 | return ( 9 | 10 | ); 11 | } 12 | 13 | }; 14 | 15 | const mapStateToProps = store => { 16 | return { 17 | fullname: store.loginState.fullname, 18 | alert: store.dashboardLayoutState.alert 19 | }; 20 | }; 21 | 22 | export default connect(mapStateToProps)(MainLayoutContainer); 23 | -------------------------------------------------------------------------------- /src/components/containers/page-layout-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import PageLayout from '../layouts/page-layout'; 4 | import store from '../../store'; 5 | import * as loginApi from '../../api/identity-api'; 6 | import { push } from 'react-router-redux'; 7 | import { loadDashboardTitle } from '../../actions/dashboard-actions'; 8 | 9 | class PageLayoutContainer extends React.Component { 10 | 11 | //load route by url 12 | componentDidMount() { 13 | 14 | store.dispatch(loadDashboardTitle(this.props.children.props.route.title)); 15 | 16 | } 17 | 18 | componentWillReceiveProps(nextProps) { 19 | 20 | let routeTitle = nextProps.children.props.route.title; 21 | 22 | if (nextProps.title !== routeTitle) { 23 | 24 | //the route has changed 25 | 26 | store.dispatch(loadDashboardTitle(routeTitle)); 27 | 28 | } 29 | } 30 | //change route by button click 31 | componentDidUpdate() { 32 | 33 | if (!loginApi.loggedIn()) 34 | store.dispatch(push('/ReactAdmin/login')); 35 | 36 | } 37 | 38 | render() { 39 | return ( 40 | 41 | ); 42 | } 43 | 44 | }; 45 | 46 | const mapStateToProps = store => { 47 | return { 48 | title: store.dashboardLayoutState.title 49 | }; 50 | }; 51 | 52 | export default connect(mapStateToProps)(PageLayoutContainer); 53 | -------------------------------------------------------------------------------- /src/components/containers/service-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import Service from '../views/service'; 4 | import store from '../../store'; 5 | import { loadDashboardTitle, loadDashboardCompleted } from '../../actions/dashboard-actions'; 6 | import { resetServiceModel } from '../../actions/service-actions'; 7 | import * as serviceApi from '../../api/service-api'; 8 | 9 | class ServiceContainer extends React.Component { 10 | constructor(props) { 11 | super(props); 12 | this.submit = this.submit.bind(this); 13 | } 14 | componentDidMount() { 15 | let _current = this; 16 | 17 | store.dispatch(loadDashboardTitle(this.props.route.title)); 18 | 19 | if (this.props.route.isEditRoute) { 20 | 21 | let id = this.props.params.itemId; 22 | 23 | serviceApi.getTypes().then(function () { 24 | 25 | serviceApi.getJob(id); 26 | 27 | }); 28 | 29 | } else { 30 | 31 | serviceApi.getTypes().then(function () { 32 | store.dispatch(resetServiceModel()); 33 | }); 34 | } 35 | 36 | } 37 | componentDidUpdate() { 38 | 39 | if (!this.props.isLoaded && !this.props.route.isEditRoute) { 40 | this.refs.child.clearFiles(); 41 | store.dispatch(resetServiceModel()); 42 | store.dispatch(loadDashboardCompleted()); 43 | } 44 | 45 | } 46 | submit() { 47 | event.preventDefault(); 48 | let data = this.refs.child.getData(); 49 | console.log(data); 50 | serviceApi.add(data); 51 | } 52 | render() { 53 | return ( 54 | 55 | ); 56 | } 57 | 58 | }; 59 | 60 | const mapStateToProps = store => { 61 | return { 62 | isLoaded: store.dashboardLayoutState.isLoaded, 63 | service: store.serviceState.service, 64 | serviceTypes: store.serviceState.serviceTypes 65 | }; 66 | }; 67 | 68 | 69 | export default connect(mapStateToProps)(ServiceContainer); 70 | -------------------------------------------------------------------------------- /src/components/containers/service-list-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import SimpleList from '../views/simple-list'; 4 | import store from '../../store'; 5 | import { loadDashboardTitle, showAlert } from '../../actions/dashboard-actions'; 6 | import * as serviceApi from '../../api/service-api'; 7 | import * as swAlert from '../../helpers/sweet-alert'; 8 | import { push } from 'react-router-redux'; 9 | 10 | class ServiceContainer extends React.Component { 11 | constructor(props) { 12 | super(props); 13 | this.deleteItem = this.deleteItem.bind(this); 14 | } 15 | componentDidMount() { 16 | store.dispatch(loadDashboardTitle(this.props.route.title)); 17 | serviceApi.getList(); 18 | } 19 | componentDidUpdate() { 20 | //ajax update 21 | if (!this.props.title) { 22 | store.dispatch(loadDashboardTitle(this.props.route.title)); 23 | return; 24 | } 25 | //change route 26 | if (this.props.route.title === this.props.title) 27 | return; 28 | store.dispatch(loadDashboardTitle(this.props.route.title)); 29 | } 30 | editItem(id) { 31 | store.dispatch(push('/ReactAdmin/admin/service/edit/' + id)); 32 | } 33 | deleteItem(id) { 34 | swAlert.warning(() => this.onConfirmDelete(id)); 35 | } 36 | onConfirmDelete(payload) { 37 | swAlert.success(() => { alert(`deleted item id:${payload}`); }); 38 | } 39 | hideAlert() { 40 | store.dispatch(showAlert(null)); 41 | } 42 | render() { 43 | return ( 44 | 45 | ); 46 | } 47 | }; 48 | 49 | const mapStateToProps = store => { 50 | return { 51 | title: store.dashboardLayoutState.title, 52 | serviceList: store.serviceState.serviceList 53 | }; 54 | }; 55 | 56 | export default connect(mapStateToProps)(ServiceContainer); -------------------------------------------------------------------------------- /src/components/layouts/main-layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Menu from './menu'; 3 | import Header from './header'; 4 | 5 | const mainLayout = props => { 6 | return ( 7 |
8 | {props.alert} 9 | 13 | {props.children} 14 |
15 | ); 16 | }; 17 | 18 | export default mainLayout; -------------------------------------------------------------------------------- /src/components/layouts/menu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MetisMenu from 'react-metismenu'; 3 | import RouterLink from 'react-metismenu-router-link'; 4 | import _ from 'lodash'; 5 | import store from '../../store'; 6 | import { syncHistoryWithStore } from 'react-router-redux'; 7 | import { browserHistory } from 'react-router'; 8 | import { hasRole } from '../../api/identity-api'; 9 | 10 | let content = [ 11 | { 12 | icon: 'home', 13 | label: 'داشبورد', 14 | to: '/ReactAdmin/' 15 | } 16 | ]; 17 | 18 | const userMenu = [{ 19 | icon: 'gear', 20 | label: 'ویرایش مشخصات', 21 | to: '/ReactAdmin/job/edit' 22 | }]; 23 | 24 | const adminMenu = [{ 25 | icon: 'book', 26 | label: 'مقالات', 27 | content: [ 28 | { 29 | label: 'مقاله جدید', 30 | to: '/ReactAdmin/admin/article/add' 31 | }, 32 | { 33 | label: 'مدیریت مقالات', 34 | to: '/ReactAdmin/admin/article/manage' 35 | } 36 | ] 37 | }, 38 | { 39 | icon: 'shopping-cart', 40 | label: 'سرویس‌ها', 41 | content: [ 42 | { 43 | label: 'سرویس جدید', 44 | to: '/ReactAdmin/admin/service/add' 45 | }, 46 | { 47 | label: 'مدیریت سرویس‌ها', 48 | to: '/ReactAdmin/admin/service/manage' 49 | } 50 | ] 51 | }]; 52 | 53 | 54 | class menu extends React.Component { 55 | constructor(props) { 56 | super(props); 57 | this.activeLink = this.activeLink.bind(this); 58 | } 59 | componentWillMount() { 60 | 61 | if (hasRole('Admin')) { 62 | content = content.concat(adminMenu); 63 | } else { 64 | content = content.concat(userMenu); 65 | } 66 | } 67 | componentDidMount() { 68 | 69 | let current = this; 70 | const history = syncHistoryWithStore(browserHistory, store); 71 | 72 | history.listen(location => { 73 | 74 | if (_.includes(location.pathname, '/ReactAdmin/admin/article/edit')) 75 | current.activeLink('/ReactAdmin/admin/article/manage'); 76 | 77 | if (_.includes(location.pathname, '/ReactAdmin/admin/plan/edit')) 78 | current.activeLink('/ReactAdmin/admin/plan/manage'); 79 | 80 | }); 81 | 82 | } 83 | activeLink(link) { 84 | 85 | this.refs.menu.changeActiveLinkTo(link); 86 | 87 | } 88 | render() { 89 | return ( 90 |
91 |
92 | 93 |
94 |
95 | ); 96 | } 97 | }; 98 | 99 | export default menu; -------------------------------------------------------------------------------- /src/components/layouts/page-layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const pageLayout = props => { 4 | return ( 5 |
6 |
7 |
8 |

{props.title}

9 |
10 |
11 | {props.children} 12 |
13 | ); 14 | }; 15 | 16 | export default pageLayout; -------------------------------------------------------------------------------- /src/components/layouts/panel-layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const panelLayout = props => { 4 | return ( 5 |
6 |
7 | {props.title} 8 |
9 | {props.children} 10 |
11 | ); 12 | }; 13 | 14 | export default panelLayout; -------------------------------------------------------------------------------- /src/components/views/article.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from 'react-bootstrap'; 3 | import PanelLayout from '../layouts/panel-layout'; 4 | import 'react-tagsinput/react-tagsinput.css'; 5 | import { updateArticleModel } from '../../actions/article-actions'; 6 | import BTagsInput from '../../helpers/btags-input'; 7 | import BFileInput from '../../helpers/bfile-input'; 8 | import ArticleModel from '../../models/article'; 9 | import store from '../../store'; 10 | import ReactJson from 'react-json-view'; 11 | import * as urls from '../../api/urls'; 12 | 13 | class article extends React.Component { 14 | constructor(props) { 15 | super(props); 16 | this.handleTextChange = this.handleTextChange.bind(this); 17 | this.updateTags = this.updateTags.bind(this); 18 | this.updateImages = this.updateImages.bind(this); 19 | this.refreshModel = this.refreshModel.bind(this); 20 | this.getData = this.getData.bind(this); 21 | } 22 | handleTextChange(event) { 23 | this.refreshModel(); 24 | } 25 | updateTags (tags) { 26 | this.refreshModel(); 27 | } 28 | updateImages (images) { 29 | this.refreshModel(); 30 | } 31 | refreshModel () { 32 | let model = new ArticleModel(this.refs); 33 | console.log(this.props.article.Images); 34 | console.log(model); 35 | store.dispatch(updateArticleModel(model)); 36 | } 37 | clearFiles () { 38 | this.refs.Images.clearFiles(); 39 | } 40 | getData () { 41 | let model = new ArticleModel(this.refs); 42 | return model; 43 | } 44 | render () { 45 | return ( 46 | 47 |
48 |
49 | 50 |
51 | 54 | 55 |
56 |
57 | 60 | 61 |
62 |
63 | 65 |
66 |
67 | 70 |
71 |
72 | 73 |
74 |
75 |
76 | 77 |
78 |
79 |
80 | ); 81 | } 82 | }; 83 | 84 | export default article; -------------------------------------------------------------------------------- /src/components/views/dashboard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class dashboard extends React.Component { render() { 4 | return ( 5 |
6 |
7 |
8 |
9 |
10 |
11 | 12 |
13 |
14 |
۲۶
15 |
نظرات جدید!
16 |
17 |
18 |
19 | 20 |
21 | مشاهده جزییات 22 | 23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 |
۱۲
37 |
وظایف جدید!
38 |
39 |
40 |
41 | 42 |
43 | مشاهده جزییات 44 | 45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | 56 |
57 |
58 |
۱۲۳
59 |
سفارشات جدید!
60 |
61 |
62 |
63 | 64 |
65 | مشاهده جزییات 66 | 67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 78 |
79 |
80 |
۱۴
81 |
تیکت‌های جدید!
82 |
83 |
84 |
85 | 86 |
87 | مشاهده جزییات 88 | 89 |
90 |
91 |
92 |
93 |
94 |
95 | ); 96 | }}; 97 | 98 | export default dashboard; -------------------------------------------------------------------------------- /src/components/views/jobownerJob.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from 'react-bootstrap'; 3 | import PanelLayout from '../layouts/panel-layout'; 4 | import 'react-tagsinput/react-tagsinput.css'; 5 | import { updateJOBModel } from '../../actions/jobowner-actions'; 6 | import BFileInput from '../../helpers/bfile-input'; 7 | import jobownerJobModel from '../../models/jobownerJob'; 8 | import store from '../../store'; 9 | import BSelectInput from '../../helpers/bselect-input'; 10 | import BMultiInput from '../../helpers/bmulti-input'; 11 | import 'react-select/dist/react-select.css'; 12 | import * as urls from '../../api/urls'; 13 | import ReactJson from 'react-json-view'; 14 | 15 | class jobownerJob extends React.Component { 16 | constructor(props) { 17 | super(props); 18 | this.getData = this.getData.bind(this); 19 | this.handleTextChange = this.handleTextChange.bind(this); 20 | this.refreshModel = this.refreshModel.bind(this); 21 | this.updateSelect = this.updateSelect.bind(this); 22 | this.updateImages = this.updateImages.bind(this); 23 | } 24 | getData () { 25 | let model = new jobownerJobModel(this.refs); 26 | return model; 27 | } 28 | handleTextChange(event) { 29 | this.refreshModel(); 30 | } 31 | refreshModel () { 32 | let model = new jobownerJobModel(this.refs); 33 | store.dispatch(updateJOBModel(model)); 34 | } 35 | updateSelect (item) { 36 | this.refreshModel(); 37 | } 38 | updateMulti (items) { 39 | console.log('updateMulti', items); 40 | // store.dispatch(updateBMultiInput(items)); 41 | } 42 | updateImages (images) { 43 | this.refreshModel(); 44 | } 45 | render () { 46 | return ( 47 | 48 |
49 |
50 | 51 | 52 |
53 | 56 |
57 | 58 | 59 | 60 | 61 | 62 |
63 | 64 |
65 | 66 |
67 | 69 |
70 | 71 |
72 | 73 |
74 | 77 | 78 |
79 |
80 | 83 | 85 |
86 |
87 | 90 | 91 |
92 |
93 | 96 | 98 |
99 |
100 | 103 | 111 |
112 |
113 | 116 |
117 |
118 | 119 |
120 |
121 |
122 | 123 |
124 |
125 |
126 | ); 127 | } 128 | }; 129 | 130 | export default jobownerJob; -------------------------------------------------------------------------------- /src/components/views/login.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LOGIN_TAB, REGISTER_TAB } from '../../actions/login-actions'; 3 | 4 | class login extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | this.getInfo = this.getInfo.bind(this); 8 | } 9 | 10 | getInfo() { 11 | return { 12 | tel: "+98" + this.refs.tel.value.trim() 13 | , verifycode: this.refs.verifycode.value.trim() 14 | }; 15 | } 16 | 17 | render() { 18 | return ( 19 |
20 |
21 | { }} /> 22 | 23 | { }} /> 24 | 25 |
26 |
27 |
28 | 29 | +98 | 30 | 31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | {this.props.tel} 39 | ویرایش 40 |
41 |
42 | یک پیامک حاوی کد فعالسازی برای تلفن همراه شما ارسال شده‌است. 43 |
44 |
45 | 46 | 47 |
48 |
49 | 57 |
58 |
59 | {this.props.isActive && 60 |
61 |  {this.props.freezeTime}  62 | دقیقه دیگر می‌توانید درخواست مجدد کد فعالسازی را ارسال کنید. 63 |
64 | } 65 | {!this.props.isActive && 66 | 69 | } 70 |
71 |
72 |
73 |
74 | ); 75 | } 76 | }; 77 | 78 | export default login; -------------------------------------------------------------------------------- /src/components/views/service.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from 'react-bootstrap'; 3 | import PanelLayout from '../layouts/panel-layout'; 4 | import 'react-tagsinput/react-tagsinput.css'; 5 | import { updateServiceModel } from '../../actions/service-actions'; 6 | import BFileInput from '../../helpers/bfile-input'; 7 | import BSelectInput from '../../helpers/bselect-input'; 8 | import serviceModel from '../../models/service'; 9 | import store from '../../store'; 10 | import BMultiInput from '../../helpers/bmulti-input'; 11 | import BDateInput from '../../helpers/bdate-input'; 12 | import moment from 'moment-jalaali'; 13 | import ReactJson from 'react-json-view'; 14 | import * as urls from '../../api/urls'; 15 | 16 | class service extends React.Component { 17 | constructor(props) { 18 | super(props); 19 | this.getData = this.getData.bind(this); 20 | this.handleTextChange = this.handleTextChange.bind(this); 21 | this.refreshModel = this.refreshModel.bind(this); 22 | this.updateSelect = this.updateSelect.bind(this); 23 | this.updateImages = this.updateImages.bind(this); 24 | } 25 | getData() { 26 | let model = new serviceModel(this.refs); 27 | return model; 28 | } 29 | handleTextChange(event) { 30 | this.refreshModel(); 31 | } 32 | refreshModel() { 33 | let model = new serviceModel(this.refs); 34 | store.dispatch(updateServiceModel(model)); 35 | } 36 | updateSelect(item) { 37 | this.refreshModel(); 38 | } 39 | updateImages(images) { 40 | this.refreshModel(); 41 | } 42 | clearFiles () { 43 | this.refs.Images.clearFiles(); 44 | } 45 | render() { 46 | return ( 47 | 48 |
49 | 50 |
51 | 52 | 53 | { }} value={this.props.service.MultiInput || []}> 54 | 55 | 56 | 57 |
58 | 59 |
60 | 61 |
62 | 65 | 66 | 74 |
75 | 76 |
77 | 78 |
79 | 82 | 83 |
84 | 85 |
86 | 89 | 91 |
92 |
93 | 96 | 97 |
98 | 99 |
100 | 103 | 105 |
106 | 107 |
108 | 111 | 113 |
114 | 115 |
116 | 119 |
120 | 121 |
122 | 125 |
126 | 127 |
128 |
129 |
130 | 133 |
134 | 135 |
136 |
137 | 138 |
139 | 141 |
142 | 143 |
144 | 145 |
146 | 147 |
148 | 149 |
150 | 151 |
152 |
153 |
154 | ); 155 | } 156 | }; 157 | 158 | export default service; -------------------------------------------------------------------------------- /src/components/views/simple-list.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Table, Button, Glyphicon } from 'react-bootstrap'; 3 | import PanelLayout from '../layouts/panel-layout'; 4 | 5 | const simpleList = props => { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {props.items && props.items.map((item, idx) => { 21 | return ( 22 | 23 | 24 | 28 | ); 29 | })} 30 | 31 | 32 |
#Title
{++idx}{item.Title} 25 | 26 | 27 |
33 | 34 |
35 | ); 36 | }; 37 | 38 | export default simpleList; -------------------------------------------------------------------------------- /src/helpers/bdate-input.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DatePicker } from 'react-persian-datepicker'; 3 | import moment from 'moment-jalaali'; 4 | 5 | import 'react-persian-datepicker/lib/styles/basic.css'; 6 | 7 | const styles = { 8 | calendarContainer: 'calendarContainer', 9 | heading: 'heading', 10 | prev: 'prev', 11 | next: 'next', 12 | title: 'title', 13 | dayWrapper: 'dayWrapper', 14 | currentMonth: 'currentMonth', 15 | daysOfWeek: 'daysOfWeek', 16 | monthsList: 'monthsList', 17 | selected: 'selected', 18 | dayPickerContainer: 'dayPickerContainer' 19 | }; 20 | 21 | export default class BDateInput extends React.Component { 22 | constructor(props) { 23 | super(props); 24 | 25 | this.value = (props.value || moment()).toString(); 26 | 27 | this.state = { value: moment('Thu Feb 02 1000 06:17:17 GMT+0330') }; 28 | 29 | this.onDateChange = (value) => { 30 | this.value = value.toString(); 31 | this.setState({ value }); 32 | this.props.onChange(value) 33 | } 34 | 35 | } 36 | 37 | // fired after value props changed 38 | componentWillReceiveProps(nextProps) { 39 | this.value=nextProps.value; 40 | this.setState({ value: moment(nextProps.value) }); 41 | } 42 | // fired after state changed 43 | shouldComponentUpdate(nextProps, nextState) { 44 | return ((this.state.value|| moment()).toString() !== (nextState.value|| moment()).toString() )|| 45 | (this.value !== nextProps.value ) ; 46 | } 47 | // fired after component render 48 | componentDidUpdate() { 49 | // this.onChange(this.state.value); 50 | } 51 | 52 | render() { 53 | return ; 54 | } 55 | } -------------------------------------------------------------------------------- /src/helpers/bfile-input.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DropzoneComponent from 'react-dropzone-component'; 3 | import { uploadIcon } from './icons'; 4 | import _ from 'lodash'; 5 | import * as urls from '../api/urls'; 6 | 7 | export default class BFileInput extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | 11 | this.value = typeof props.value !== 'object' ? [] : props.value; 12 | 13 | this.state = { value: this.value }; 14 | 15 | this.djsConfig = { 16 | init: this.init, 17 | autoProcessQueue: true, 18 | addRemoveLinks: true, 19 | acceptedFiles: props.acceptedFiles || "image/jpeg,image/png,image/gif", 20 | maxFilesize: props.maxFilesize || 1, 21 | thumbnailWidth: 250, 22 | thumbnailHeight: 250, 23 | dictRemoveFile: 'پاک کردن', 24 | dictResponseError: 'بروز خطا', 25 | dictDefaultMessage: 'آپلود فایل' + uploadIcon, 26 | dictCancelUpload: 'لغو آپلود', 27 | dictCancelUploadConfirmation: 'آیا از لغو آپلود مطمعن هستید؟', 28 | dictMaxFilesExceeded: 'شما نمی‌توانید فایل‌های بیشتری آپلود کنید!', 29 | dictInvalidFileType: 'فایل انتخاب شده غیر مجاز است!', 30 | dictFileTooBig: 'حجم فایل انتخاب شده بیش از حد مجاز است!', 31 | maxFiles: props.maxFiles 32 | 33 | // headers: { 34 | // 'Authorization': '123', 35 | // // remove Cache-Control and X-Requested-With 36 | // // to be sent along with the request 37 | // 'Cache-Control': null, 38 | // 'X-Requested-With': '123' 39 | // } 40 | 41 | }; 42 | let files = []; 43 | 44 | this.componentConfig = { 45 | postUrl:props.postUrl||( urls.BASEFILEUPLOAD + (props.folderName || 'root') ) 46 | }; 47 | 48 | //init 49 | this.init = (dz) => { 50 | this.dropzone = dz; 51 | }; 52 | 53 | 54 | // this.clearFiles = () => { 55 | // this.dropzone.removeAllFiles(true); 56 | // } 57 | 58 | this.clearFiles = this.clearFiles.bind(this); 59 | 60 | //mock files 61 | this.setImages = (images) => { 62 | 63 | let dz = this.dropzone; 64 | 65 | if (typeof images === "undefined" || images === null) 66 | return; 67 | 68 | if (images.length <= 0) 69 | return; 70 | 71 | if (typeof images[0].url !== 'undefined' && _.findIndex(files, { name: images[0].name }) === -1) 72 | dz.removeAllFiles(true); 73 | // dz.removeAllFiles(true); 74 | 75 | let mockFiles = []; 76 | 77 | for (let i = 0; i < images.length; i++) { 78 | 79 | if (typeof images[i].url !== 'undefined' && _.findIndex(files, { name: images[i].name }) === -1) 80 | mockFiles.push({ 81 | name: images[i].name, size: 5000, isMock: true 82 | , serverFilename: images[i].name, serverImgUrl: images[i].url, 83 | accepted: true //it's important for limitations 84 | }); 85 | } 86 | 87 | // setTimeout(function () { 88 | mockFiles.forEach(function (mockFile) { 89 | dz.emit('addedfile', mockFile); 90 | dz.emit('complete', mockFile); 91 | dz.files.push(mockFile); 92 | }); 93 | // }, 300); 94 | 95 | }; 96 | 97 | // If you want to attach multiple callbacks, simply 98 | // create an array filled with all your callbacks. 99 | // this.callbackArray = [() => console.log('Hi!'), () => console.log('Ho!')]; 100 | 101 | // Simple callbacks work too, of course 102 | this.callback = (file) => { 103 | 104 | // If added file is a mock file 105 | // create thumbnail from url provided by server in mock file array 106 | if (file.isMock) { 107 | 108 | this.dropzone.createThumbnailFromUrl(file, file.serverImgUrl, null, true); 109 | 110 | files.push({ name: file.name, url: file.serverImgUrl }); 111 | 112 | this.value = files; 113 | this.props.updateImagesHandler(files); 114 | 115 | } 116 | 117 | }; 118 | 119 | this.success = (file, responseText) => { 120 | 121 | file.serverFilename = responseText.name; 122 | 123 | files.push({ name: responseText.name, url: responseText.url }); 124 | 125 | this.value = files; 126 | this.props.updateImagesHandler(files); 127 | 128 | }; 129 | 130 | this.removedfile = (file) => { 131 | 132 | // if (files.indexOf(file.serverFilename) !== -1) 133 | // files.splice(files.indexOf(file.serverFilename), 1); 134 | 135 | _.remove(files, { name: file.serverFilename }); 136 | 137 | this.value = files; 138 | this.props.updateImagesHandler(files); 139 | 140 | }; 141 | 142 | this.dropzone = null; 143 | 144 | } 145 | clearFiles(){ 146 | this.dropzone.removeAllFiles(true); 147 | } 148 | // fired after component render 149 | componentDidMount() { 150 | this.setImages(this.state.value); 151 | } 152 | 153 | // fired after value props changed 154 | componentWillReceiveProps(nextProps) { 155 | this.setState({ value: nextProps.value }); 156 | } 157 | 158 | // fired after state changed 159 | shouldComponentUpdate(nextProps, nextState) { 160 | return (nextState.value || []).length > 0; 161 | } 162 | 163 | // fired after component render 164 | componentDidUpdate(prevProps, prevState) { 165 | this.setImages(this.state.value); 166 | } 167 | 168 | render() { 169 | 170 | const config = this.componentConfig; 171 | const djsConfig = this.djsConfig; 172 | 173 | // For a list of all possible events (there are many), see README.md! 174 | const eventHandlers = { 175 | init: this.init, 176 | drop: this.callbackArray, 177 | addedfile: this.callback, 178 | success: this.success, 179 | removedfile: this.removedfile 180 | }; 181 | 182 | return 183 | } 184 | } -------------------------------------------------------------------------------- /src/helpers/bmulti-input.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button, Glyphicon } from 'react-bootstrap'; 3 | import _ from 'lodash'; 4 | 5 | export default class MultiInput extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.IsFirstTime=true; 10 | 11 | this.state = { value: props.value || [], deleted: props.deleted || [] }; 12 | 13 | this.value = {}; 14 | 15 | this.deleteItemHandler = (idx) => { 16 | 17 | let value = this.state.value.filter((item, index) => { return !_.includes([idx], index); }); 18 | 19 | //deleted index history 20 | let deleted = this.state.deleted.concat([idx]); 21 | 22 | this.setState({ deleted, value }); 23 | 24 | this.value=value; 25 | 26 | this.onChange(value); 27 | 28 | } 29 | 30 | this.addItemHandler = () => { 31 | 32 | let value = this.state.value.concat([{}]); 33 | 34 | this.setState({ value }); 35 | 36 | this.value=value; 37 | 38 | this.onChange(value); 39 | 40 | } 41 | 42 | this.onChange=(value)=>{this.props.onChange(value)}; 43 | 44 | } 45 | 46 | 47 | // fired after component render 48 | componentDidMount() { 49 | 50 | } 51 | // fired after value props changed 52 | componentWillReceiveProps(nextProps) { 53 | this.setState({value:nextProps.value}); 54 | // console.log(nextProps.value); 55 | } 56 | // fired after state changed 57 | // shouldComponentUpdate(nextProps, nextState){ 58 | // return ((this.props.value||[]).length!==(nextProps.value||[]).length)|| 59 | // ((this.props.value||[]).length!==(nextState.value||[]).length); 60 | // } 61 | // fired after component render 62 | componentDidUpdate() { 63 | // this.setImages(this.state.value); 64 | // this.onChange(this.state.value); 65 | } 66 | 67 | setChildInput(child,idx,values,parent) 68 | { 69 | 70 | if(child.constructor === Array) 71 | { 72 | let children=[]; 73 | child.forEach( (item)=> { 74 | children.push(this.setChildInput(item,idx,values,parent)); 75 | }); 76 | return children; 77 | } 78 | 79 | if (child.ref !== null) 80 | { 81 | 82 | //rename component name in parent refs 83 | let nchild = { 84 | ...child, 85 | ref: this.props.name + '-' + child.ref + '-' + idx 86 | }; 87 | 88 | let itemValue=values[child.ref]; 89 | 90 | itemValue = typeof itemValue==='undefined'?'':itemValue; 91 | 92 | let nElement=React.cloneElement(nchild, { value:itemValue }); 93 | 94 | return nElement; 95 | } 96 | 97 | if (typeof child.props.children !== 'object') 98 | return child; 99 | 100 | let result = {...child.props,children:this.setChildInput(child.props.children,idx,values,child.props)}; 101 | 102 | return {...child,props:result}; 103 | 104 | } 105 | 106 | renderChildren(values, idx) { 107 | 108 | values = values || []; 109 | 110 | return React.Children.map(this.props.children, (child) => { 111 | 112 | // console.log(child); 113 | // console.log((this.setChildInput(child,idx,values))); 114 | return (this.setChildInput(child,idx,values)); 115 | 116 | }); 117 | 118 | } 119 | 120 | render() { 121 | 122 | return ( 123 |
124 | { 125 | this.state.value.map((item, idx) => { 126 | return ( 127 |
128 | 129 | { 130 | this.renderChildren(item, idx) 131 | } 132 | 133 |
134 | ); 135 | }) 136 | } 137 |
138 | 139 |
140 | ); 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/helpers/bselect-input.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Select from 'react-select'; 3 | import 'react-select/dist/react-select.css'; 4 | 5 | export default class BSelectInput extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { value: props.value || {} }; 10 | 11 | this.value = props.value || {}; 12 | 13 | this.onSelectChange = (selectedItem) => { 14 | 15 | if (this.props.async) { 16 | //if it's in async mode get label name from mocked or selected option 17 | this.value = selectedItem || {}; 18 | } 19 | else { 20 | //if it's NOT in async mode get label name from exist options 21 | this.value = selectedItem.value || selectedItem || {}; 22 | } 23 | 24 | props.onChangeHandler(selectedItem); 25 | this.setState({ value: this.value }); 26 | } 27 | 28 | } 29 | 30 | // fired after value props changed 31 | componentWillReceiveProps(nextProps) { 32 | this.setState({ value: nextProps.value }); 33 | } 34 | // fired after state changed 35 | shouldComponentUpdate(nextProps, nextState) { 36 | return (this.props.value !== nextProps.value) && typeof nextProps.value !== 'undefined'; 37 | } 38 | // fired after component render 39 | componentDidUpdate() { 40 | this.onSelectChange(this.state.value); 41 | } 42 | 43 | render() { 44 | // console.log(this.props.async); 45 | // console.log(this.props.loadOptions); 46 | return (this.props.async === true) ? 47 | ( 48 | 58 | ) : 59 | ( 60 |