Showing
61 changed files
with
2041 additions
and
92 deletions
A_Team_Khuloud/frontend/.editorconfig
0 → 100644
A_Team_Khuloud/frontend/.gitignore
0 → 100644
1 | +#Created by .ignore support plugin (hsz.mobi) | ||
2 | +### Node template | ||
3 | +# Logs | ||
4 | +/logs | ||
5 | +*.log | ||
6 | +npm-debug.log* | ||
7 | +yarn-debug.log* | ||
8 | +yarn-error.log* | ||
9 | + | ||
10 | +# Runtime data | ||
11 | +pids | ||
12 | +*.pid | ||
13 | +*.seed | ||
14 | +*.pid.lock | ||
15 | + | ||
16 | +# Directory for instrumented libs generated by jscoverage/JSCover | ||
17 | +lib-cov | ||
18 | + | ||
19 | +# Coverage directory used by tools like istanbul | ||
20 | +coverage | ||
21 | + | ||
22 | +# nyc test coverage | ||
23 | +.nyc_output | ||
24 | + | ||
25 | +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
26 | +.grunt | ||
27 | + | ||
28 | +# Bower dependency directory (https://bower.io/) | ||
29 | +bower_components | ||
30 | + | ||
31 | +# node-waf configuration | ||
32 | +.lock-wscript | ||
33 | + | ||
34 | +# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
35 | +build/Release | ||
36 | + | ||
37 | +# Dependency directories | ||
38 | +node_modules/ | ||
39 | +jspm_packages/ | ||
40 | + | ||
41 | +# TypeScript v1 declaration files | ||
42 | +typings/ | ||
43 | + | ||
44 | +# Optional npm cache directory | ||
45 | +.npm | ||
46 | + | ||
47 | +# Optional eslint cache | ||
48 | +.eslintcache | ||
49 | + | ||
50 | +# Optional REPL history | ||
51 | +.node_repl_history | ||
52 | + | ||
53 | +# Output of 'npm pack' | ||
54 | +*.tgz | ||
55 | + | ||
56 | +# Yarn Integrity file | ||
57 | +.yarn-integrity | ||
58 | + | ||
59 | +# dotenv environment variables file | ||
60 | +.env | ||
61 | + | ||
62 | +# parcel-bundler cache (https://parceljs.org/) | ||
63 | +.cache | ||
64 | + | ||
65 | +# next.js build output | ||
66 | +.next | ||
67 | + | ||
68 | +# nuxt.js build output | ||
69 | +.nuxt | ||
70 | + | ||
71 | +# Nuxt generate | ||
72 | +dist | ||
73 | + | ||
74 | +# vuepress build output | ||
75 | +.vuepress/dist | ||
76 | + | ||
77 | +# Serverless directories | ||
78 | +.serverless | ||
79 | + | ||
80 | +# IDE / Editor | ||
81 | +.idea | ||
82 | + | ||
83 | +# Service worker | ||
84 | +sw.* | ||
85 | + | ||
86 | +# macOS | ||
87 | +.DS_Store | ||
88 | + | ||
89 | +# Vim swap files | ||
90 | +*.swp | ||
91 | + | ||
92 | +node_modules/ |
A_Team_Khuloud/frontend/README.md
0 → 100644
1 | +# frontend | ||
2 | + | ||
3 | +> My incredible Nuxt.js project | ||
4 | + | ||
5 | +## Build Setup | ||
6 | + | ||
7 | +```bash | ||
8 | +# install dependencies | ||
9 | +$ npm install | ||
10 | + | ||
11 | +# serve with hot reload at localhost:3000 | ||
12 | +$ npm run dev | ||
13 | + | ||
14 | +# build for production and launch server | ||
15 | +$ npm run build | ||
16 | +$ npm run start | ||
17 | + | ||
18 | +# generate static project | ||
19 | +$ npm run generate | ||
20 | +``` | ||
21 | + | ||
22 | +For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org). |
A_Team_Khuloud/frontend/assets/README.md
0 → 100644
1 | +# ASSETS | ||
2 | + | ||
3 | +**This directory is not required, you can delete it if you don't want to use it.** | ||
4 | + | ||
5 | +This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. | ||
6 | + | ||
7 | +More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked). |
1 | +<template> | ||
2 | + <div> | ||
3 | + <v-btn class="pink white--text">click me</v-btn> | ||
4 | + <v-btn depressed class="pink">click me</v-btn> | ||
5 | + <v-btn flat class="pink">click me</v-btn> | ||
6 | + | ||
7 | + <v-btn depressed class="pink white--text"> | ||
8 | + <v-icon left>email</v-icon> | ||
9 | + <span>email me</span> | ||
10 | + </v-btn> | ||
11 | + | ||
12 | + <v-btn depressed small class="pink white--text"> | ||
13 | + <v-icon left small>email</v-icon> | ||
14 | + <span>email me</span> | ||
15 | + </v-btn> | ||
16 | + | ||
17 | + <v-btn fab small dark class="purple"> | ||
18 | + <v-icon>favorite</v-icon> | ||
19 | + </v-btn> | ||
20 | + | ||
21 | + | ||
22 | + <h1>HomePage</h1> | ||
23 | + <v-btn class="hidden-md-and-down">click me</v-btn> | ||
24 | + <v-btn class="hidden-md-and-up">click me</v-btn> | ||
25 | + <v-btn class="hidden-sm-only">click me</v-btn> | ||
26 | + | ||
27 | + </div> | ||
28 | +</template> | ||
29 | + | ||
30 | +<script> | ||
31 | + export default { | ||
32 | + name: "ButtonIconVisibility" | ||
33 | + } | ||
34 | +</script> | ||
35 | + | ||
36 | +<style scoped> | ||
37 | + | ||
38 | +</style> |
1 | +<template> | ||
2 | + <div> | ||
3 | + <v-btn | ||
4 | + text | ||
5 | + @click="$refs.fileInput.click()"> | ||
6 | + <v-icon>vertical_align_top</v-icon> | ||
7 | + <span class="caption">업로드</span> | ||
8 | + </v-btn> | ||
9 | + <input | ||
10 | + v-show="false" | ||
11 | + type="file" | ||
12 | + ref="fileInput" | ||
13 | + multiple="multiple" | ||
14 | + @change="uploadFile"> | ||
15 | + </div> | ||
16 | +</template> | ||
17 | + | ||
18 | +<script> | ||
19 | + import 'material-design-icons-iconfont/dist/material-design-icons.css' | ||
20 | + | ||
21 | + export default { | ||
22 | + name: "CreateFileFormComponent", | ||
23 | + data() { | ||
24 | + return { | ||
25 | + filepath: '', | ||
26 | + } | ||
27 | + }, | ||
28 | + methods: { | ||
29 | + async uploadFile(e) { | ||
30 | + try { | ||
31 | + const formData = new FormData(); | ||
32 | + const now = Date.now(); | ||
33 | + Array.prototype.forEach.call(e.target.files, (file) => { | ||
34 | + formData.append('file', file); | ||
35 | + formData.append('name', file.name); | ||
36 | + formData.append('isFolder', true); | ||
37 | + formData.append('path', this.filepath); | ||
38 | + formData.append('fileSize', file.size); | ||
39 | + formData.append('createdDate', now); | ||
40 | + formData.append('updatedDate', now); | ||
41 | + formData.append('share', false); | ||
42 | + console.log(file); | ||
43 | + }); | ||
44 | + | ||
45 | + await this.$store.dispatch('file/uploadFile', {formData}); | ||
46 | + return this.$router.replace('/'); | ||
47 | + } catch (e) { | ||
48 | + console.error(e); | ||
49 | + } | ||
50 | + } | ||
51 | + } | ||
52 | + } | ||
53 | +</script> | ||
54 | + | ||
55 | +<style scoped> | ||
56 | + | ||
57 | +</style> |
1 | +<template> | ||
2 | + <v-dialog max-width="400px"> | ||
3 | + <template v-slot:activator="{on}"> | ||
4 | + <v-btn | ||
5 | + flat slot="activator" | ||
6 | + text | ||
7 | + v-on="on"> | ||
8 | + <v-icon>add</v-icon> | ||
9 | + <span overline class="caption">새로 만들기</span> | ||
10 | + </v-btn> | ||
11 | + </template> | ||
12 | + <v-card> | ||
13 | + <v-card-title> | ||
14 | + <p class="title font-weight-light">폴더</p> | ||
15 | + </v-card-title> | ||
16 | + <v-form class="px-3" @submit.prevent="uploadFolder"> | ||
17 | + <v-card-text> | ||
18 | + <v-text-field | ||
19 | + outlined | ||
20 | + label="폴더 이름" | ||
21 | + v-model="folderName" | ||
22 | + color="blue" | ||
23 | + /> | ||
24 | + </v-card-text> | ||
25 | + <v-card-actions> | ||
26 | + <v-spacer/> | ||
27 | + <v-btn | ||
28 | + depressed | ||
29 | + class="mr-3 mb-3 text-lowercase font-weight-light" | ||
30 | + type="submit"> | ||
31 | + 만들기 | ||
32 | + </v-btn> | ||
33 | + </v-card-actions> | ||
34 | + </v-form> | ||
35 | + </v-card> | ||
36 | + </v-dialog> | ||
37 | +</template> | ||
38 | + | ||
39 | +<script> | ||
40 | + export default { | ||
41 | + name: "CreateFolderFormComponent", | ||
42 | + data() { | ||
43 | + return { | ||
44 | + valid: false, | ||
45 | + folderName: '', | ||
46 | + folderPath: '/', | ||
47 | + } | ||
48 | + }, | ||
49 | + methods: { | ||
50 | + async uploadFolder() { | ||
51 | + try { | ||
52 | + console.log('폴더이름 test', this.folderName); | ||
53 | + | ||
54 | + const now = Date.now(); | ||
55 | + const formData = new FormData(); | ||
56 | + formData.append('name', this.folderName); | ||
57 | + formData.append('owner', 'owner'); | ||
58 | + formData.append('path', this.folderPath); | ||
59 | + formData.append('isFolder', true); | ||
60 | + formData.append('createdAt', now); | ||
61 | + formData.append('fileSize', 0); | ||
62 | + formData.append('share', false); | ||
63 | + | ||
64 | + console.log(now, this.folderPath); | ||
65 | + | ||
66 | + await this.$store.dispatch('file/uploadFolder', {formData}); | ||
67 | + // await this.$router.replace('/'); | ||
68 | + } catch (e) { | ||
69 | + console.error(e); | ||
70 | + } | ||
71 | + }, | ||
72 | + | ||
73 | + } | ||
74 | + } | ||
75 | +</script> | ||
76 | + | ||
77 | +<style scoped> | ||
78 | + | ||
79 | +</style> |
1 | +<template> | ||
2 | + <v-layout justify-center="center" class="my-10"> | ||
3 | + <v-flex | ||
4 | + xs12 md10> | ||
5 | + <v-data-table | ||
6 | + :headers="headers" | ||
7 | + :items="files" | ||
8 | + hide-actions | ||
9 | + hide-default-footer | ||
10 | + > | ||
11 | + <template slot="items" slot-scope="props"> | ||
12 | + <td> | ||
13 | + <v-btn | ||
14 | + icon> | ||
15 | + <v-icon>folder</v-icon> | ||
16 | + </v-btn> | ||
17 | + </td> | ||
18 | + <td> | ||
19 | + {{ props.item.name }} | ||
20 | + </td> | ||
21 | + <td class="text-xs-right">{{ props.item.modifiedDate }}</td> | ||
22 | + <td class="text-xs-right">{{ props.item.owner }}</td> | ||
23 | + <td class="text-xs-right">{{ props.item.fileSize }}</td> | ||
24 | + <td class="text-xs-right">{{ props.item.share }}</td> | ||
25 | + </template> | ||
26 | + </v-data-table> | ||
27 | + </v-flex> | ||
28 | + </v-layout> | ||
29 | +</template> | ||
30 | + | ||
31 | +<script> | ||
32 | + import 'material-design-icons-iconfont/dist/material-design-icons.css' | ||
33 | + | ||
34 | + export default { | ||
35 | + name: 'DataTableComponent', | ||
36 | + data() { | ||
37 | + return { | ||
38 | + currentPath: 'root', | ||
39 | + fileTypeIcon: '', | ||
40 | + headers: [ | ||
41 | + {text: '', value: 'icon'}, | ||
42 | + { | ||
43 | + text: '이름', | ||
44 | + align: 'left', | ||
45 | + sortable: 'false', | ||
46 | + value: 'name' | ||
47 | + }, | ||
48 | + {text: '수정한 날짜', value: 'modifiedDate'}, | ||
49 | + {text: '수정한 사람', value: 'owner'}, | ||
50 | + {text: '파일 크기', value: 'fileSize'}, | ||
51 | + {text: '공유', value: 'share'} | ||
52 | + ], | ||
53 | + files: [ | ||
54 | + { | ||
55 | + name: '90.944339.pdf', | ||
56 | + modifiedDate: '2020-02-08', | ||
57 | + owner: 'tjddus', | ||
58 | + fileSize: '1000', | ||
59 | + share: false | ||
60 | + } | ||
61 | + ] | ||
62 | + } | ||
63 | + } | ||
64 | + } | ||
65 | +</script> |
1 | +<template> | ||
2 | + <v-system-bar | ||
3 | + :height="55"> | ||
4 | + | ||
5 | + <create-folder-form-component/> | ||
6 | + | ||
7 | + <create-file-form-component/> | ||
8 | + | ||
9 | + <v-spacer/> | ||
10 | + <v-menu offset-y> | ||
11 | + <template | ||
12 | + v-slot:activator="{on}"> | ||
13 | + <v-btn | ||
14 | + text | ||
15 | + v-on="on" | ||
16 | + > | ||
17 | + <v-icon>sort</v-icon> | ||
18 | + <span class="caption">정렬</span> | ||
19 | + </v-btn> | ||
20 | + </template> | ||
21 | + <v-list> | ||
22 | + <v-list-item v-for="view in views" :key="view.title" @click="changeCurrentView(view.title)"> | ||
23 | + <v-list-action> | ||
24 | + <v-icon small>{{view.icon}}</v-icon> | ||
25 | + </v-list-action> | ||
26 | + <v-list-title class="ml-1 body-2">{{view.title}}</v-list-title> | ||
27 | + </v-list-item> | ||
28 | + </v-list> | ||
29 | + </v-menu> | ||
30 | + </v-system-bar> | ||
31 | +</template> | ||
32 | + | ||
33 | +<script> | ||
34 | + import 'material-design-icons-iconfont/dist/material-design-icons.css' | ||
35 | + import CreateFolderFormComponent from "./CreateFolderFormComponent"; | ||
36 | + import CreateFileFormComponent from "./CreateFileFormComponent"; | ||
37 | + | ||
38 | + export default { | ||
39 | + name: "FileNavbarComponent", | ||
40 | + components: {CreateFolderFormComponent, CreateFileFormComponent}, | ||
41 | + data() { | ||
42 | + return { | ||
43 | + currentView: 0, | ||
44 | + views: [ | ||
45 | + {value: 0, icon: 'format_align_left', title: '목록'}, | ||
46 | + {value: 1, icon: 'border_all', title: '타일'} | ||
47 | + ], | ||
48 | + } | ||
49 | + }, | ||
50 | + methods: { | ||
51 | + changeCurrentView(value) { | ||
52 | + this.currentView = value; | ||
53 | + console.log(this.currentView); | ||
54 | + }, | ||
55 | + } | ||
56 | + } | ||
57 | +</script> | ||
58 | + | ||
59 | +<style scoped> | ||
60 | +</style> |
1 | +<template> | ||
2 | + <div> | ||
3 | + <v-row | ||
4 | + align="center" | ||
5 | + justify="center"> | ||
6 | + <v-col | ||
7 | + cols="12" | ||
8 | + sm="8" | ||
9 | + md="4" | ||
10 | + > | ||
11 | + <v-card> | ||
12 | + <v-form v-model="valid" @submit.prevent="login"> | ||
13 | + <v-card-text> | ||
14 | + <v-text-field | ||
15 | + v-model="username" | ||
16 | + :rules="[rules.username]" | ||
17 | + label="username" | ||
18 | + prepend-icon="person"> | ||
19 | + </v-text-field> | ||
20 | + <v-text-field | ||
21 | + v-model="password" | ||
22 | + :rules="[rules.password]" | ||
23 | + type="password" | ||
24 | + label="password" | ||
25 | + prepend-icon="lock"> | ||
26 | + </v-text-field> | ||
27 | + </v-card-text> | ||
28 | + <v-card-actions> | ||
29 | + <v-spacer/> | ||
30 | + <v-btn | ||
31 | + color="grey" | ||
32 | + type="submit"> | ||
33 | + 로그인 | ||
34 | + </v-btn> | ||
35 | + </v-card-actions> | ||
36 | + </v-form> | ||
37 | + </v-card> | ||
38 | + </v-col> | ||
39 | + </v-row> | ||
40 | + </div> | ||
41 | +</template> | ||
42 | + | ||
43 | + | ||
44 | +<script> | ||
45 | + export default { | ||
46 | + name: "loginComponent", | ||
47 | + data() { | ||
48 | + return { | ||
49 | + valid: false, | ||
50 | + tryLogin: true, | ||
51 | + username: '', | ||
52 | + password: '', | ||
53 | + rules: { | ||
54 | + username: v => !!v || 'username is required', | ||
55 | + password: v => !!v || 'password is required', | ||
56 | + } | ||
57 | + } | ||
58 | + }, | ||
59 | + methods: { | ||
60 | + async login() { | ||
61 | + try { | ||
62 | + console.log('login Method'); | ||
63 | + await this.$store.dispatch('user/login', { | ||
64 | + username: this.username, | ||
65 | + password: this.password | ||
66 | + }); | ||
67 | + await this.$router.replace('/'); | ||
68 | + } catch (e) { | ||
69 | + console.error(e); | ||
70 | + } | ||
71 | + }, | ||
72 | + changeTryLogin() { | ||
73 | + this.tryLogin = !this.tryLogin; | ||
74 | + } | ||
75 | + } | ||
76 | + } | ||
77 | +</script> |
A_Team_Khuloud/frontend/components/Logo.vue
0 → 100644
1 | +<template> | ||
2 | + <div class="VueToNuxtLogo"> | ||
3 | + <div class="Triangle Triangle--two" /> | ||
4 | + <div class="Triangle Triangle--one" /> | ||
5 | + <div class="Triangle Triangle--three" /> | ||
6 | + <div class="Triangle Triangle--four" /> | ||
7 | + </div> | ||
8 | +</template> | ||
9 | + | ||
10 | +<style> | ||
11 | +.VueToNuxtLogo { | ||
12 | + display: inline-block; | ||
13 | + animation: turn 2s linear forwards 1s; | ||
14 | + transform: rotateX(180deg); | ||
15 | + position: relative; | ||
16 | + overflow: hidden; | ||
17 | + height: 180px; | ||
18 | + width: 245px; | ||
19 | +} | ||
20 | + | ||
21 | +.Triangle { | ||
22 | + position: absolute; | ||
23 | + top: 0; | ||
24 | + left: 0; | ||
25 | + width: 0; | ||
26 | + height: 0; | ||
27 | +} | ||
28 | + | ||
29 | +.Triangle--one { | ||
30 | + border-left: 105px solid transparent; | ||
31 | + border-right: 105px solid transparent; | ||
32 | + border-bottom: 180px solid #41b883; | ||
33 | +} | ||
34 | + | ||
35 | +.Triangle--two { | ||
36 | + top: 30px; | ||
37 | + left: 35px; | ||
38 | + animation: goright 0.5s linear forwards 3.5s; | ||
39 | + border-left: 87.5px solid transparent; | ||
40 | + border-right: 87.5px solid transparent; | ||
41 | + border-bottom: 150px solid #3b8070; | ||
42 | +} | ||
43 | + | ||
44 | +.Triangle--three { | ||
45 | + top: 60px; | ||
46 | + left: 35px; | ||
47 | + animation: goright 0.5s linear forwards 3.5s; | ||
48 | + border-left: 70px solid transparent; | ||
49 | + border-right: 70px solid transparent; | ||
50 | + border-bottom: 120px solid #35495e; | ||
51 | +} | ||
52 | + | ||
53 | +.Triangle--four { | ||
54 | + top: 120px; | ||
55 | + left: 70px; | ||
56 | + animation: godown 0.5s linear forwards 3s; | ||
57 | + border-left: 35px solid transparent; | ||
58 | + border-right: 35px solid transparent; | ||
59 | + border-bottom: 60px solid #fff; | ||
60 | +} | ||
61 | + | ||
62 | +@keyframes turn { | ||
63 | + 100% { | ||
64 | + transform: rotateX(0deg); | ||
65 | + } | ||
66 | +} | ||
67 | + | ||
68 | +@keyframes godown { | ||
69 | + 100% { | ||
70 | + top: 180px; | ||
71 | + } | ||
72 | +} | ||
73 | + | ||
74 | +@keyframes goright { | ||
75 | + 100% { | ||
76 | + left: 70px; | ||
77 | + } | ||
78 | +} | ||
79 | +</style> | ||
80 | + |
1 | +<template> | ||
2 | + <div class="mx-4 mb-4"> | ||
3 | + <h1 class="subheading grey--text">Team</h1> | ||
4 | + | ||
5 | + <v-container fluid class="my-5"> | ||
6 | + <v-layout row wrap> | ||
7 | + <v-flex xs12 md6> | ||
8 | + <v-btn outline block class="primary">1</v-btn> | ||
9 | + </v-flex> | ||
10 | + <v-flex xs4 md2> | ||
11 | + <v-btn outline block class="primary">2</v-btn> | ||
12 | + </v-flex> | ||
13 | + <v-flex xs4 md2> | ||
14 | + <v-btn outline block class="primary">2</v-btn> | ||
15 | + </v-flex> | ||
16 | + <v-flex xs4 md2> | ||
17 | + <v-btn outline block class="primary">2</v-btn> | ||
18 | + </v-flex> | ||
19 | + </v-layout> | ||
20 | + | ||
21 | + <!-- justify-end, center, space-around--> | ||
22 | + | ||
23 | + <v-layout row wrap justify-end> | ||
24 | + <v-flex xs4 md3> | ||
25 | + <v-btn outline block class="success">1</v-btn> | ||
26 | + </v-flex> | ||
27 | + <v-flex xs4 md3> | ||
28 | + <v-btn outline block class="success">2</v-btn> | ||
29 | + </v-flex> | ||
30 | + </v-layout> | ||
31 | + </v-container> | ||
32 | + | ||
33 | + | ||
34 | + <v-container class="my-5"> | ||
35 | + | ||
36 | + <v-layout row class="mb-3"> | ||
37 | + <v-tooltip top> | ||
38 | + <template v-slot:activator="{ on }"> | ||
39 | + <v-btn small flat color="grey" @click="sortBy('title')" v-on="on"> | ||
40 | + <v-icon left small>folder</v-icon> | ||
41 | + <span class="caption text-lowercase">By project name</span> | ||
42 | + </v-btn> | ||
43 | + </template> | ||
44 | + <span>Sort projects by project name</span> | ||
45 | + </v-tooltip> | ||
46 | + | ||
47 | + <v-tooltip top> | ||
48 | + <template v-slot:activator="{ on }"> | ||
49 | + <v-btn small flat color="grey" @click="sortBy('person')" v-on="on"> | ||
50 | + <v-icon left small>person</v-icon> | ||
51 | + <span class="caption text-lowercase">By person</span> | ||
52 | + </v-btn> | ||
53 | + </template> | ||
54 | + <span>Sort projects by person</span> | ||
55 | + </v-tooltip> | ||
56 | + </v-layout> | ||
57 | + | ||
58 | + | ||
59 | + <v-card flat class="pa-3" v-for="project in projects" :key="project.title"> | ||
60 | + <v-layout row wrap :class="`pa-3 project ${project.status}`"> | ||
61 | + <v-flex xs12 md6> | ||
62 | + <div class="caption grey--text">project title</div> | ||
63 | + <div>{{project.title}}</div> | ||
64 | + </v-flex> | ||
65 | + <v-flex xs4 md2> | ||
66 | + <div class="caption grey--text">Person</div> | ||
67 | + <div>{{project.person}}</div> | ||
68 | + </v-flex> | ||
69 | + <v-flex xs4 md2> | ||
70 | + <div class="caption grey--text">Due by</div> | ||
71 | + <div>{{project.due}}</div> | ||
72 | + </v-flex> | ||
73 | + <v-flex xs4 md2> | ||
74 | + <v-chip small :class="`${project.status} white--text caption my-2`">{{project.status}}</v-chip> | ||
75 | + </v-flex> | ||
76 | + </v-layout> | ||
77 | + </v-card> | ||
78 | + </v-container> | ||
79 | + </div> | ||
80 | +</template> | ||
81 | + | ||
82 | +<script> | ||
83 | + export default { | ||
84 | + name: "PaddingMarginGrid", | ||
85 | + data() { | ||
86 | + return { | ||
87 | + projects: [ | ||
88 | + {title: 'Design a new website', person: 'The Net Ninja', due: '1st Jan 2019', status: 'ongoing'}, | ||
89 | + {title: 'Write a new website', person: 'Net Ninja', due: '1st Jan 2019', status: 'complete'}, | ||
90 | + {title: 'Create a new website', person: 'Ninja', due: '1st Jan 2019', status: 'ongoing'}, | ||
91 | + {title: 'Update a new website', person: 'tjddus', due: '1st Jan 2019', status: 'overdue'} | ||
92 | + ] | ||
93 | + } | ||
94 | + }, | ||
95 | + methods: { | ||
96 | + sortBy(props) { | ||
97 | + this.projects.sort((a, b) => a[props] < b[props] ? -1 : 1); | ||
98 | + } | ||
99 | + } | ||
100 | + } | ||
101 | +</script> | ||
102 | + | ||
103 | +<style scoped> | ||
104 | + .project.complete { | ||
105 | + border-left: 4px solid #3cd1c2; | ||
106 | + } | ||
107 | + | ||
108 | + .project.ongoing { | ||
109 | + border-left: 4px solid orange; | ||
110 | + } | ||
111 | + | ||
112 | + .project.overdue { | ||
113 | + border-left: 4px solid tomato; | ||
114 | + } | ||
115 | + | ||
116 | + .v-chip.complete { | ||
117 | + background: #3cd1c2; | ||
118 | + } | ||
119 | + | ||
120 | + .v-chip.ongoing { | ||
121 | + background: orange; | ||
122 | + } | ||
123 | + | ||
124 | + .v-chip.overdue { | ||
125 | + background: tomato; | ||
126 | + } | ||
127 | +</style> |
A_Team_Khuloud/frontend/components/README.md
0 → 100644
1 | +<template> | ||
2 | + <v-layout class="py-10" justify-center="center"> | ||
3 | + <v-flex | ||
4 | + xs12 md10> | ||
5 | + <v-data-table | ||
6 | + :headers="headers" | ||
7 | + :items="files" | ||
8 | + hide-actions | ||
9 | + hide-default-footer | ||
10 | + > | ||
11 | + <template slot="items" slot-scope="props"> | ||
12 | + <td>{{ props.item.name }}</td> | ||
13 | + <td class="text-xs-right">{{ props.item.shareDate }}</td> | ||
14 | + <td class="text-xs-right">{{ props.item.sharePerson }}</td> | ||
15 | + <td class="text-xs-right">{{ props.item.acitivity }}</td> | ||
16 | + </template> | ||
17 | + </v-data-table> | ||
18 | + </v-flex> | ||
19 | + </v-layout> | ||
20 | +</template> | ||
21 | + | ||
22 | +<script> | ||
23 | + export default { | ||
24 | + name: 'ShareTableComponent', | ||
25 | + // computed: { | ||
26 | + // files: this.$store.state.file.files | ||
27 | + // }, | ||
28 | + data () { | ||
29 | + return { | ||
30 | + headers: [ | ||
31 | + { | ||
32 | + text: '이름', | ||
33 | + align: 'left', | ||
34 | + sortable: 'false', | ||
35 | + value: 'name' | ||
36 | + }, | ||
37 | + { text: '공유된 날짜', value: 'shareDate'}, | ||
38 | + { text: '공유한 사람', value: 'sharePerson'}, | ||
39 | + { text: '활동', value: 'activity'} | ||
40 | + ], | ||
41 | + files: [ | ||
42 | + ] | ||
43 | + } | ||
44 | + } | ||
45 | + } | ||
46 | +</script> |
1 | +<template> | ||
2 | + <div> | ||
3 | + <v-row | ||
4 | + align="center" | ||
5 | + justify="center" | ||
6 | + > | ||
7 | + <v-col | ||
8 | + cols="12" | ||
9 | + sm="8" | ||
10 | + md="4" | ||
11 | + > | ||
12 | + <v-card> | ||
13 | + <v-form v-model="valid" @submit.prevent="signUp"> | ||
14 | + <v-card-text> | ||
15 | + <v-text-field | ||
16 | + v-model="email" | ||
17 | + :rules="[rules.email]" | ||
18 | + prepend-icon="email" | ||
19 | + label="email"> | ||
20 | + </v-text-field> | ||
21 | + <v-text-field | ||
22 | + v-model="username" | ||
23 | + :rules="[rules.username]" | ||
24 | + prepend-icon="person" | ||
25 | + label="username"> | ||
26 | + </v-text-field> | ||
27 | + <v-text-field | ||
28 | + v-model="password" | ||
29 | + :rules="[rules.password]" | ||
30 | + prepend-icon="lock" | ||
31 | + type="password" | ||
32 | + label="password"> | ||
33 | + </v-text-field> | ||
34 | + <v-text-field | ||
35 | + v-model="checkpassword" | ||
36 | + :rules="[rules.checkpassword]" | ||
37 | + prepend-icon="lock" | ||
38 | + type="password" | ||
39 | + label="checkpassword"> | ||
40 | + </v-text-field> | ||
41 | + </v-card-text> | ||
42 | + <v-card-actions> | ||
43 | + <v-spacer/> | ||
44 | + <v-btn | ||
45 | + color="grey" | ||
46 | + type="submit"> | ||
47 | + 회원가입 | ||
48 | + </v-btn> | ||
49 | + </v-card-actions> | ||
50 | + </v-form> | ||
51 | + </v-card> | ||
52 | + </v-col> | ||
53 | + </v-row> | ||
54 | + </div> | ||
55 | +</template> | ||
56 | + | ||
57 | +<script> | ||
58 | + export default { | ||
59 | + name: "SignUpComponent", | ||
60 | + data() { | ||
61 | + return { | ||
62 | + valid: false, | ||
63 | + email: '', | ||
64 | + username: '', | ||
65 | + password: '', | ||
66 | + checkpassword: '', | ||
67 | + rules: { | ||
68 | + email: v => (v || '').match(/@/) || 'Please enter a valid email', | ||
69 | + username: v => !!v || 'username is required', | ||
70 | + password: v => !!v || 'password is required', | ||
71 | + checkpassword: v => v == this.password || 'checkpassword is incorrect' | ||
72 | + } | ||
73 | + } | ||
74 | + }, | ||
75 | + methods: { | ||
76 | + async signUp() { | ||
77 | + try { | ||
78 | + console.log('signUp Method'); | ||
79 | + //$store.dispatch -> action의 signUp 함수를 불러올 수 있음 | ||
80 | + await this.$store.dispatch('user/signUp', { | ||
81 | + email: this.email, | ||
82 | + username: this.username, | ||
83 | + password: this.password | ||
84 | + }); | ||
85 | + await this.$router.replace('/'); | ||
86 | + } catch (e) { | ||
87 | + console.error(e); | ||
88 | + } | ||
89 | + } | ||
90 | + } | ||
91 | + } | ||
92 | +</script> | ||
93 | + | ||
94 | +<style scoped> | ||
95 | + | ||
96 | +</style> | ||
97 | + | ||
98 | + |
1 | +<template> | ||
2 | + <v-layout justify-center="center" class="my-10"> | ||
3 | + <v-flex xs12 md10> | ||
4 | + <v-data-table :headers="headers" :items="files" hide-actions hide-default-footer> | ||
5 | + <template slot="items" slot-scope="props"> | ||
6 | + <td>{{ props.item.name }}</td> | ||
7 | + <td class="text-xs-right">{{ props.item.deletedDate }}</td> | ||
8 | + <td class="text-xs-right">{{ props.item.deletePerson }}</td> | ||
9 | + <td class="text-xs-right">{{ props.item.makePerson }}</td> | ||
10 | + <td class="text-xs-right">{{ props.item.originalPath }}</td> | ||
11 | + </template> | ||
12 | + </v-data-table> | ||
13 | + </v-flex> | ||
14 | + </v-layout> | ||
15 | + | ||
16 | +</template> | ||
17 | + | ||
18 | +<script> | ||
19 | + export default { | ||
20 | + name: 'TrashTableComponent', | ||
21 | + data() { | ||
22 | + return { | ||
23 | + headers: [ | ||
24 | + { | ||
25 | + text: '이름', | ||
26 | + align: 'left', | ||
27 | + sortable: 'false', | ||
28 | + value: 'name' | ||
29 | + }, | ||
30 | + {text: '삭제된 날짜', value: 'deletedDate'}, | ||
31 | + {text: '삭제한 사람', value: 'deletePerson'}, | ||
32 | + {text: '만든 사람', value: 'makePerson'}, | ||
33 | + {text: '원래 위치', value: 'originalPath'} | ||
34 | + ], | ||
35 | + files: [] | ||
36 | + } | ||
37 | + } | ||
38 | + } | ||
39 | +</script> |
1 | +<template> | ||
2 | + <img | ||
3 | + class="VuetifyLogo" | ||
4 | + alt="Vuetify Logo" | ||
5 | + src="/vuetify-logo.svg" | ||
6 | + > | ||
7 | +</template> | ||
8 | + | ||
9 | +<style> | ||
10 | +.VuetifyLogo { | ||
11 | + height:180px; | ||
12 | + width: 180px; | ||
13 | + transform: rotateY(560deg); | ||
14 | + animation: turn 3.5s ease-out forwards 1s; | ||
15 | +} | ||
16 | + | ||
17 | +@keyframes turn { | ||
18 | + 100% { | ||
19 | + transform: rotateY(0deg); | ||
20 | + } | ||
21 | +} | ||
22 | +</style> |
A_Team_Khuloud/frontend/layouts/README.md
0 → 100644
A_Team_Khuloud/frontend/layouts/default.vue
0 → 100644
1 | +<template> | ||
2 | + <v-app> | ||
3 | + <v-navigation-drawer | ||
4 | + v-model="drawer" | ||
5 | + app | ||
6 | + clipped | ||
7 | + > | ||
8 | + <v-list dense> | ||
9 | + <v-list-item v-for="item in items" :key="item.title" router :to="item.route"> | ||
10 | + <v-list-item-action :to="item.to"> | ||
11 | + <v-icon>{{item.icon}}</v-icon> | ||
12 | + </v-list-item-action> | ||
13 | + <v-list-item-content> | ||
14 | + <v-list-item-title>{{item.title}}</v-list-item-title> | ||
15 | + </v-list-item-content> | ||
16 | + </v-list-item> | ||
17 | + </v-list> | ||
18 | + </v-navigation-drawer> | ||
19 | + | ||
20 | + <v-app-bar | ||
21 | + app | ||
22 | + clipped-left | ||
23 | + :height="55" | ||
24 | + > | ||
25 | + <v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon> | ||
26 | + <v-toolbar-title small>KHULOUD</v-toolbar-title> | ||
27 | + <v-spacer/> | ||
28 | + <v-btn icon class="mr-2" nuxt to="inspire"> | ||
29 | + <v-icon flat small>person</v-icon> | ||
30 | + </v-btn> | ||
31 | + </v-app-bar> | ||
32 | + | ||
33 | + <v-content> | ||
34 | + <nuxt/> | ||
35 | + </v-content> | ||
36 | + | ||
37 | + <v-footer app> | ||
38 | + <span>© 2020</span> | ||
39 | + </v-footer> | ||
40 | + </v-app> | ||
41 | +</template> | ||
42 | + | ||
43 | +<script> | ||
44 | + import 'material-design-icons-iconfont/dist/material-design-icons.css' | ||
45 | + | ||
46 | + export default { | ||
47 | + props: { | ||
48 | + source: String, | ||
49 | + }, | ||
50 | + data() { | ||
51 | + return { | ||
52 | + drawer: null, | ||
53 | + items: [ | ||
54 | + {title: 'Khuloud', icon: 'school', route: '/'}, | ||
55 | + {title: '내 파일', icon: 'folder', route: '/drive/file'}, | ||
56 | + {title: '최근 항목', icon: 'list', route: '/'}, | ||
57 | + {title: '사진', icon: 'image', route: '/inspire'}, | ||
58 | + {title: '공유됨', icon: 'get_app', route: '/drive/shared-with-me'}, | ||
59 | + {title: '휴지통', icon: 'delete', route: '/drive/trash'} | ||
60 | + ] | ||
61 | + } | ||
62 | + } | ||
63 | + } | ||
64 | +</script> | ||
65 | + | ||
66 | +<style scoped> | ||
67 | + #app { | ||
68 | + font-family: Avenir, Helvetica, Arial, sans-serif; | ||
69 | + -webkit-font-smoothing: antialiased; | ||
70 | + -moz-osx-font-smoothing: grayscale; | ||
71 | + color: #2c3e50; | ||
72 | + } | ||
73 | +</style> |
A_Team_Khuloud/frontend/layouts/error.vue
0 → 100644
1 | +<template> | ||
2 | + <v-app dark> | ||
3 | + <h1 v-if="error.statusCode === 404"> | ||
4 | + {{ pageNotFound }} | ||
5 | + </h1> | ||
6 | + <h1 v-else> | ||
7 | + {{ otherError }} | ||
8 | + </h1> | ||
9 | + <NuxtLink to="/"> | ||
10 | + Home page | ||
11 | + </NuxtLink> | ||
12 | + </v-app> | ||
13 | +</template> | ||
14 | + | ||
15 | +<script> | ||
16 | +export default { | ||
17 | + layout: 'empty', | ||
18 | + props: { | ||
19 | + error: { | ||
20 | + type: Object, | ||
21 | + default: null | ||
22 | + } | ||
23 | + }, | ||
24 | + data () { | ||
25 | + return { | ||
26 | + pageNotFound: '404 Not Found', | ||
27 | + otherError: 'An error occurred' | ||
28 | + } | ||
29 | + }, | ||
30 | + head () { | ||
31 | + const title = | ||
32 | + this.error.statusCode === 404 ? this.pageNotFound : this.otherError | ||
33 | + return { | ||
34 | + title | ||
35 | + } | ||
36 | + } | ||
37 | +} | ||
38 | +</script> | ||
39 | + | ||
40 | +<style scoped> | ||
41 | +h1 { | ||
42 | + font-size: 20px; | ||
43 | +} | ||
44 | +</style> |
A_Team_Khuloud/frontend/middleware/README.md
0 → 100644
1 | +# MIDDLEWARE | ||
2 | + | ||
3 | +**This directory is not required, you can delete it if you don't want to use it.** | ||
4 | + | ||
5 | +This directory contains your application middleware. | ||
6 | +Middleware let you define custom functions that can be run before rendering either a page or a group of pages. | ||
7 | + | ||
8 | +More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). |
A_Team_Khuloud/frontend/nuxt.config.js
0 → 100644
1 | +// import colors from 'vuetify/es5/util/colors' | ||
2 | +// | ||
3 | +// export default { | ||
4 | +// mode: 'universal', | ||
5 | +// /* | ||
6 | +// ** Headers of the page | ||
7 | +// */ | ||
8 | +// head: { | ||
9 | +// titleTemplate: '%s - ' + process.env.npm_package_name, | ||
10 | +// title: process.env.npm_package_name || '', | ||
11 | +// meta: [ | ||
12 | +// { charset: 'utf-8' }, | ||
13 | +// { name: 'viewport', content: 'width=device-width, initial-scale=1' }, | ||
14 | +// { hid: 'description', name: 'description', content: process.env.npm_package_description || '' } | ||
15 | +// ], | ||
16 | +// link: [ | ||
17 | +// { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } | ||
18 | +// ] | ||
19 | +// }, | ||
20 | +// /* | ||
21 | +// ** Customize the progress-bar color | ||
22 | +// */ | ||
23 | +// loading: { color: '#fff' }, | ||
24 | +// /* | ||
25 | +// ** Global CSS | ||
26 | +// */ | ||
27 | +// css: [ | ||
28 | +// ], | ||
29 | +// /* | ||
30 | +// ** Plugins to load before mounting the App | ||
31 | +// */ | ||
32 | +// plugins: [ | ||
33 | +// ], | ||
34 | +// /* | ||
35 | +// ** Nuxt.js dev-modules | ||
36 | +// */ | ||
37 | +// buildModules: [ | ||
38 | +// '@nuxtjs/vuetify', | ||
39 | +// '@nuxtjs/moment', | ||
40 | +// ], | ||
41 | +// /* | ||
42 | +// ** Nuxt.js modules | ||
43 | +// */ | ||
44 | +// modules: [ | ||
45 | +// '@nuxtjs/axios', | ||
46 | +// '@nuxtjs/pwa' | ||
47 | +// ], | ||
48 | +// /* | ||
49 | +// ** Build configuration | ||
50 | +// */ | ||
51 | +// build: { | ||
52 | +// /* | ||
53 | +// ** You can extend webpack config here | ||
54 | +// */ | ||
55 | +// extend (config, ctx) { | ||
56 | +// } | ||
57 | +// } | ||
58 | +// } | ||
59 | + | ||
60 | + | ||
61 | +import webpack from 'webpack' | ||
62 | + | ||
63 | +module.exports = { | ||
64 | + | ||
65 | + server: { | ||
66 | + host: 'localhost', | ||
67 | + port: 3001 | ||
68 | + }, | ||
69 | + head: { | ||
70 | + meta: [{ | ||
71 | + charset: 'utf-8', | ||
72 | + }, { | ||
73 | + name: 'viewport', | ||
74 | + content: 'width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no', | ||
75 | + }], | ||
76 | + cookie: {} | ||
77 | + }, | ||
78 | + modules: [ | ||
79 | + '@nuxtjs/axios', | ||
80 | + '@nuxtjs/pwa', | ||
81 | + ], | ||
82 | + buildModules: [ | ||
83 | + '@nuxtjs/vuetify', | ||
84 | + '@nuxtjs/moment', | ||
85 | + ], | ||
86 | + | ||
87 | + // pwa: { | ||
88 | + // icon: { | ||
89 | + // iconSrc: 'static/icon.png' | ||
90 | + // }, | ||
91 | + // manifest: { | ||
92 | + // name: 'node_express_study_final' | ||
93 | + // }, | ||
94 | + // workbox: { | ||
95 | + // dev: true, | ||
96 | + // runtimeCaching: [{ | ||
97 | + // urlPattern: 'http://localhost:4001/.*', | ||
98 | + // method: 'GET' | ||
99 | + // }, { | ||
100 | + // urlPattern: 'http://localhost:5001/.*', | ||
101 | + // method: 'GET' | ||
102 | + // }] | ||
103 | + // }, | ||
104 | + // } | ||
105 | +}; |
A_Team_Khuloud/frontend/package-lock.json
0 → 100644
This diff could not be displayed because it is too large.
A_Team_Khuloud/frontend/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "frontend", | ||
3 | + "scripts": { | ||
4 | + "start": "nuxt" | ||
5 | + }, | ||
6 | + "dependencies": { | ||
7 | + "@nuxtjs/axios": "^5.9.5", | ||
8 | + "@nuxtjs/moment": "^1.6.0", | ||
9 | + "@nuxtjs/pwa": "^3.0.0-beta.20", | ||
10 | + "@nuxtjs/vuetify": "^1.11.0", | ||
11 | + "jquery": "^3.4.1", | ||
12 | + "js-cookie": "^2.2.1", | ||
13 | + "loadsh": "0.0.4", | ||
14 | + "lodash.throttle": "^4.1.1", | ||
15 | + "material-design-icons-iconfont": "^5.0.1", | ||
16 | + "nuxt": "^2.11.0", | ||
17 | + "socket.io-client": "^2.3.0", | ||
18 | + "webpack": "^4.43.0" | ||
19 | + } | ||
20 | +} |
A_Team_Khuloud/frontend/pages/README.md
0 → 100644
1 | +# PAGES | ||
2 | + | ||
3 | +This directory contains your Application Views and Routes. | ||
4 | +The framework reads all the `*.vue` files inside this directory and creates the router of your application. | ||
5 | + | ||
6 | +More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing). |
A_Team_Khuloud/frontend/pages/drive/file.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <file-navbar-component/> | ||
4 | + <data-table-component/> | ||
5 | + </div> | ||
6 | +</template> | ||
7 | + | ||
8 | +<script> | ||
9 | + import FileNavbarComponent from "../../components/FileNavbarComponent"; | ||
10 | + import DataTableComponent from "../../components/DataTableComponent"; | ||
11 | + | ||
12 | + export default { | ||
13 | + name: "file", | ||
14 | + components: { | ||
15 | + FileNavbarComponent, | ||
16 | + DataTableComponent, | ||
17 | + } | ||
18 | + } | ||
19 | +</script> | ||
20 | + | ||
21 | +<style scoped> | ||
22 | + | ||
23 | +</style> |
1 | +<template> | ||
2 | + <div> | ||
3 | + <file-navbar-component/> | ||
4 | + <share-table-component/> | ||
5 | + </div> | ||
6 | +</template> | ||
7 | + | ||
8 | +<script> | ||
9 | + import FileNavbarComponent from "../../components/FileNavbarComponent"; | ||
10 | + import ShareTableComponent from "../../components/ShareTableComponent"; | ||
11 | + | ||
12 | + export default { | ||
13 | + name: "shared-with-me.vue", | ||
14 | + components: {FileNavbarComponent, ShareTableComponent}, | ||
15 | + } | ||
16 | +</script> | ||
17 | + | ||
18 | +<style scoped> | ||
19 | + | ||
20 | +</style> |
A_Team_Khuloud/frontend/pages/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <div v-if="!me"> | ||
4 | + Do login | ||
5 | + </div> | ||
6 | + <div v-else> | ||
7 | + {{me.username}}님 환영합니다 | ||
8 | + </div> | ||
9 | + | ||
10 | + </div> | ||
11 | +</template> | ||
12 | + | ||
13 | +<script> | ||
14 | + | ||
15 | + export default { | ||
16 | + name: "home", | ||
17 | + data() { | ||
18 | + return { | ||
19 | + headers: [ | ||
20 | + { | ||
21 | + text: '이름', | ||
22 | + }, { | ||
23 | + text: '수정한 날짜', | ||
24 | + }, { | ||
25 | + text: '공유', | ||
26 | + }, { | ||
27 | + text: '크기', | ||
28 | + } | ||
29 | + ], | ||
30 | + files: [] | ||
31 | + } | ||
32 | + }, | ||
33 | + computed: { | ||
34 | + me() { | ||
35 | + return this.$store.state.user.me; | ||
36 | + } | ||
37 | + } | ||
38 | + } | ||
39 | +</script> | ||
40 | + |
A_Team_Khuloud/frontend/pages/inspire.vue
0 → 100644
1 | +<template> | ||
2 | + <v-layout> | ||
3 | + <v-flex class="text-center"> | ||
4 | + <div | ||
5 | + v-if="me"> | ||
6 | + <v-btn @click="logout">로그아웃</v-btn> | ||
7 | + </div> | ||
8 | + <div | ||
9 | + v-else> | ||
10 | + <div | ||
11 | + v-if="tryLogin"> | ||
12 | + <login-component/> | ||
13 | + <v-btn @click="changeTryLogin">회원가입</v-btn> | ||
14 | + </div> | ||
15 | + <div | ||
16 | + v-else> | ||
17 | + <sign-up-component/> | ||
18 | + <v-btn @click="changeTryLogin">로그인</v-btn> | ||
19 | + </div> | ||
20 | + </div> | ||
21 | + | ||
22 | + <PaddingMarginGrid/> | ||
23 | + </v-flex> | ||
24 | + </v-layout> | ||
25 | +</template> | ||
26 | + | ||
27 | +<script> | ||
28 | + import LoginComponent from "../components/LoginComponent"; | ||
29 | + import SignUpComponent from "../components/SignUpComponent"; | ||
30 | + import PaddingMarginGrid from "../components/PaddingMarginGrid"; | ||
31 | + | ||
32 | + | ||
33 | + export default { | ||
34 | + data() { | ||
35 | + return { | ||
36 | + tryLogin: true, | ||
37 | + } | ||
38 | + }, | ||
39 | + computed: { | ||
40 | + me() { | ||
41 | + return this.$store.state.user.me | ||
42 | + } | ||
43 | + }, | ||
44 | + components: { | ||
45 | + LoginComponent, | ||
46 | + SignUpComponent, | ||
47 | + PaddingMarginGrid, | ||
48 | + }, | ||
49 | + methods: { | ||
50 | + changeTryLogin() { | ||
51 | + this.tryLogin = !this.tryLogin | ||
52 | + }, | ||
53 | + async logout() { | ||
54 | + try { | ||
55 | + await this.$store.dispatch('user/logout'); | ||
56 | + await this.$router.replace('/'); | ||
57 | + } catch (e) { | ||
58 | + console.error(e); | ||
59 | + } | ||
60 | + } | ||
61 | + } | ||
62 | + } | ||
63 | + | ||
64 | +</script> |
A_Team_Khuloud/frontend/pages/vuetifyT.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <PaddingMarginGrid/> | ||
4 | + </div> | ||
5 | +</template> | ||
6 | + | ||
7 | +<script> | ||
8 | + import PaddingMarginGrid from "../components/PaddingMarginGrid"; | ||
9 | + | ||
10 | + export default { | ||
11 | + name: "vuetifyT", | ||
12 | + components: {PaddingMarginGrid} | ||
13 | + } | ||
14 | +</script> | ||
15 | + | ||
16 | +<style scoped> | ||
17 | + | ||
18 | +</style> |
A_Team_Khuloud/frontend/plugins/README.md
0 → 100644
1 | +# PLUGINS | ||
2 | + | ||
3 | +**This directory is not required, you can delete it if you don't want to use it.** | ||
4 | + | ||
5 | +This directory contains Javascript plugins that you want to run before mounting the root Vue.js application. | ||
6 | + | ||
7 | +More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins). |
A_Team_Khuloud/frontend/static/README.md
0 → 100644
1 | +# STATIC | ||
2 | + | ||
3 | +**This directory is not required, you can delete it if you don't want to use it.** | ||
4 | + | ||
5 | +This directory contains your static files. | ||
6 | +Each file inside this directory is mapped to `/`. | ||
7 | +Thus you'd want to delete this README.md before deploying to production. | ||
8 | + | ||
9 | +Example: `/static/robots.txt` is mapped as `/robots.txt`. | ||
10 | + | ||
11 | +More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). |
A_Team_Khuloud/frontend/static/favicon.ico
0 → 100644
No preview for this file type
A_Team_Khuloud/frontend/static/v.png
0 → 100644

5.54 KB
1 | +<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.5 100"><defs><style>.cls-1{fill:#1697f6;}.cls-2{fill:#7bc6ff;}.cls-3{fill:#1867c0;}.cls-4{fill:#aeddff;}</style></defs><title>Artboard 46</title><polyline class="cls-1" points="43.75 0 23.31 0 43.75 48.32"/><polygon class="cls-2" points="43.75 62.5 43.75 100 0 14.58 22.92 14.58 43.75 62.5"/><polyline class="cls-3" points="43.75 0 64.19 0 43.75 48.32"/><polygon class="cls-4" points="64.58 14.58 87.5 14.58 43.75 100 43.75 62.5 64.58 14.58"/></svg> |
A_Team_Khuloud/frontend/store/README.md
0 → 100644
1 | +# STORE | ||
2 | + | ||
3 | +**This directory is not required, you can delete it if you don't want to use it.** | ||
4 | + | ||
5 | +This directory contains your Vuex Store files. | ||
6 | +Vuex Store option is implemented in the Nuxt.js framework. | ||
7 | + | ||
8 | +Creating a file in this directory automatically activates the option in the framework. | ||
9 | + | ||
10 | +More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). |
A_Team_Khuloud/frontend/store/file.js
0 → 100644
1 | +export const state = () => ({ | ||
2 | + files: [], | ||
3 | + file: null, | ||
4 | +}); | ||
5 | + | ||
6 | +export const mutation = { | ||
7 | + loadFiles(state, payload) { | ||
8 | + const {files} = payload; | ||
9 | + state.files = files; | ||
10 | + }, | ||
11 | + uploadFolder({commit}, payload) { | ||
12 | + const {file} = payload; | ||
13 | + state.files.push(file); | ||
14 | + }, | ||
15 | + uploadFiles(state, payload) { | ||
16 | + const {files} = payload; | ||
17 | + state.files.concat(files); | ||
18 | + }, | ||
19 | + deleteFile(state, payload) { | ||
20 | + const {fileId} = payload; | ||
21 | + state.file = null; | ||
22 | + state.files.splice(state.files.findIndex(file => file.id === fileId), 1); | ||
23 | + }, | ||
24 | +}; | ||
25 | + | ||
26 | +export const actions = { | ||
27 | + loadFiles({commit}, payload) { | ||
28 | + return new Promise(async (resolve, reject) => { | ||
29 | + try { | ||
30 | + const res = await this.$axios.get('http://127.0.0.1:8000/files/loadFiles', { | ||
31 | + withCredentials: true | ||
32 | + }); | ||
33 | + const {files} = res.data; | ||
34 | + commit('loadFiles', {files}); | ||
35 | + return resolve(); | ||
36 | + } catch (e) { | ||
37 | + console.error(e); | ||
38 | + return reject(e); | ||
39 | + } | ||
40 | + }) | ||
41 | + }, | ||
42 | + uploadFolder({commit}, payload) { | ||
43 | + return new Promise(async (resolve, reject) => { | ||
44 | + try { | ||
45 | + const {formData} = payload; | ||
46 | + // const res = await this.$axios.post('http://127.0.0.1:8000/files/uploadFolder', formData, { | ||
47 | + // withCredentials: true | ||
48 | + // }); | ||
49 | + let res = { | ||
50 | + file: { | ||
51 | + name: '90.944339.pdf', | ||
52 | + modifiedDate: '2020-02-08', | ||
53 | + owner: 'tjddus', | ||
54 | + fileSize: '1000', | ||
55 | + share: false | ||
56 | + } | ||
57 | + }; | ||
58 | + const {file} = res; | ||
59 | + commit('uploadFiles', {file}); | ||
60 | + return resolve(); | ||
61 | + | ||
62 | + } catch (e) { | ||
63 | + console.error(e); | ||
64 | + return reject(e); | ||
65 | + } | ||
66 | + }) | ||
67 | + }, | ||
68 | + uploadFiles({commit}, payload) { | ||
69 | + return new Promise(async (resolve, reject) => { | ||
70 | + try { | ||
71 | + const {formData} = payload; | ||
72 | + const res = await this.$axios.post('http:/127.0.0.1:8000/files/uploadFiles', formData, { | ||
73 | + withCredentials: true | ||
74 | + }); | ||
75 | + const {files} = res.data; | ||
76 | + commit('uploadFiles', files); | ||
77 | + return resolve(); | ||
78 | + | ||
79 | + } catch (e) { | ||
80 | + console.error(e); | ||
81 | + return reject(e); | ||
82 | + } | ||
83 | + }); | ||
84 | + }, | ||
85 | + deleteFolder({commit}, payload) { | ||
86 | + return new Promise(async (resolve, reject) => { | ||
87 | + try { | ||
88 | + const {folderId} = payload; | ||
89 | + await this.$axios.get('http://127.0.0.1/files/deleteFile', { | ||
90 | + fileId: folderId | ||
91 | + }, { | ||
92 | + withCredentials: true | ||
93 | + }); | ||
94 | + commit('deleteFile', {fileId: folderId}); | ||
95 | + | ||
96 | + } catch (e) { | ||
97 | + console.error(e); | ||
98 | + return reject(e); | ||
99 | + } | ||
100 | + }); | ||
101 | + }, | ||
102 | + deleteFile({commit}, payload) { | ||
103 | + return new Promise(async (resolve, reject) => { | ||
104 | + try { | ||
105 | + const {fileId} = payload; | ||
106 | + await this.$axios.get('http://127.0.0.1/files/deleteFile', { | ||
107 | + fileId: fileId | ||
108 | + }, { | ||
109 | + withCredentials: true | ||
110 | + }); | ||
111 | + commit('deleteFile', {fileId: fileId}); | ||
112 | + | ||
113 | + } catch (e) { | ||
114 | + console.error(e); | ||
115 | + return reject(e); | ||
116 | + } | ||
117 | + }) | ||
118 | + }, | ||
119 | + // updateFolder({commit}, payload) { | ||
120 | + // | ||
121 | + // }, | ||
122 | + // updateFile({commit}, payload) { | ||
123 | + // | ||
124 | + // } | ||
125 | +}; |
A_Team_Khuloud/frontend/store/index.js
0 → 100644
1 | +import Cookie from 'js-cookie'; | ||
2 | + | ||
3 | +export const state = () => ({}); | ||
4 | +export const mutations = {}; | ||
5 | +export const actions = { | ||
6 | + async nuxtServerInit({dispatch}, {req}) { | ||
7 | + try { | ||
8 | + const cookie = req.headers.cookie.split('=')[1]; | ||
9 | + console.log(cookie); | ||
10 | + await dispatch('user/loadMe', {cookie}); | ||
11 | + // await dispatch('post/loadPosts', {reset: true}); | ||
12 | + // await dispatch('waitingRoom/loadChatMe'); | ||
13 | + } catch (e) { | ||
14 | + console.error(e); | ||
15 | + } | ||
16 | + } | ||
17 | +}; |
A_Team_Khuloud/frontend/store/user.js
0 → 100644
1 | +import Cookie from 'js-cookie'; | ||
2 | + | ||
3 | +export const state = () => ({ | ||
4 | + me: null, | ||
5 | +}); | ||
6 | + | ||
7 | +export const mutations = { | ||
8 | + loadMe(state, payload) { | ||
9 | + const {user} = payload; | ||
10 | + state.me = user; | ||
11 | + }, | ||
12 | + login(state, payload) { | ||
13 | + const {user} = payload; | ||
14 | + state.me = user; | ||
15 | + }, | ||
16 | + logout(state) { | ||
17 | + state.me = null; | ||
18 | + } | ||
19 | +}; | ||
20 | + | ||
21 | +export const actions = { | ||
22 | +//mutation{commit} 호출 | ||
23 | + loadMe({commit}, payload) { | ||
24 | + return new Promise(async (resolve, reject) => { | ||
25 | + try { | ||
26 | + const {cookie} = payload; | ||
27 | + this.$axios.defaults.headers.common['Authorization'] = `Token ${cookie}`; | ||
28 | + const res = await this.$axios.get('http://localhost:8000/api/auth/loadMe', { | ||
29 | + withCredentials: true | ||
30 | + }); | ||
31 | + commit('loadMe', {user: res.data}); | ||
32 | + return resolve(); | ||
33 | + } catch (e) { | ||
34 | + console.error(e); | ||
35 | + return reject(e); | ||
36 | + } | ||
37 | + }) | ||
38 | + }, | ||
39 | + | ||
40 | + /* signUp */ | ||
41 | + signUp({commit}, payload) { | ||
42 | + return new Promise(async (resolve, reject) => { | ||
43 | + try { | ||
44 | + const {email, username, password} = payload; | ||
45 | + const res = await this.$axios.post('http://127.0.0.1:8000/api/auth/signUp', { | ||
46 | + email, username, password | ||
47 | + }, { | ||
48 | + withCredentials: true | ||
49 | + }); | ||
50 | + | ||
51 | + const {user, token} = res.data; | ||
52 | + if (process.browser) { | ||
53 | + localStorage.setItem('accessToken', token); | ||
54 | + Cookie.set('accessToken', token); | ||
55 | + console.log(localStorage); | ||
56 | + } | ||
57 | + | ||
58 | + commit('login', {user}); | ||
59 | + return resolve(); | ||
60 | + | ||
61 | + } catch (e) { | ||
62 | + console.log(res.data); | ||
63 | + console.error(e); | ||
64 | + return reject(e); | ||
65 | + } | ||
66 | + }) | ||
67 | + }, | ||
68 | + | ||
69 | + /* login */ | ||
70 | + login({commit}, payload) { | ||
71 | + return new Promise(async (resolve, reject) => { | ||
72 | + try { | ||
73 | + const {username, password} = payload; | ||
74 | + const res = await this.$axios.post('http://127.0.0.1:8000/api/auth/login', { | ||
75 | + username, password | ||
76 | + }, { | ||
77 | + withCredentials: true | ||
78 | + }); | ||
79 | + | ||
80 | + console.log(res); | ||
81 | + const {user, token} = res.data; | ||
82 | + console.log(user, token); | ||
83 | + if (process.browser) { | ||
84 | + localStorage.setItem('accessToken', token); | ||
85 | + Cookie.set('accessToken', token); | ||
86 | + console.log(localStorage); | ||
87 | + } | ||
88 | + | ||
89 | + | ||
90 | + commit('login', {user}); | ||
91 | + return resolve(); | ||
92 | + | ||
93 | + } catch (e) { | ||
94 | + console.error(e); | ||
95 | + return reject(e); | ||
96 | + } | ||
97 | + }); | ||
98 | + }, | ||
99 | + | ||
100 | + /* logout */ | ||
101 | + logout({commit}) { | ||
102 | + return new Promise(async (resolve, reject) => { | ||
103 | + try { | ||
104 | + // await this.$axios.get('http://127.0.0.1:8000/user/logout', { | ||
105 | + // withCredentials: true | ||
106 | + // }); | ||
107 | + if (process.browser) { | ||
108 | + localStorage.removeItem('accessToken'); | ||
109 | + Cookie.remove('accessToken'); | ||
110 | + } | ||
111 | + commit('logout'); | ||
112 | + return resolve(); | ||
113 | + | ||
114 | + } catch (e) { | ||
115 | + console.error(e); | ||
116 | + return reject(e); | ||
117 | + } | ||
118 | + }) | ||
119 | + } | ||
120 | + | ||
121 | + | ||
122 | +}; |
1 | -''' | ||
2 | -import boto3 | ||
3 | -import sys | ||
4 | -from django.conf import settings | ||
5 | -import configparser | ||
6 | - | ||
7 | -config = configparser.ConfigParser() | ||
8 | -config.read('config.ini') | ||
9 | - | ||
10 | -s3_client = boto3.client( | ||
11 | - 's3', | ||
12 | - aws_access_key_id=config['aws']['AWS_ACCESS_KEY_ID'], | ||
13 | - aws_secret_access_key=config['aws']['AWS_SECRET_ACCESS_KEY'] | ||
14 | -) | ||
15 | -s3 = boto3.resource('s3', aws_access_key_id=config['aws']['AWS_ACCESS_KEY_ID'], | ||
16 | - aws_secret_access_key=config['aws']['AWS_SECRET_ACCESS_KEY']) | ||
17 | - | ||
18 | - | ||
19 | -def get_folder_with_items(self, main_folder): | ||
20 | - print("HI~~~~") | ||
21 | - | ||
22 | - try: | ||
23 | - result = self.s3_client.list_objects( | ||
24 | - Bucket="opijaeclouds", Prefix=main_folder[1:], Delimiter="/") | ||
25 | - result_files = get_files(main_folder, result.get( | ||
26 | - 'Contents')) if result.get('Contents') else [] | ||
27 | - result_folders = get_folders(main_folder, result.get('CommonPrefixes')) if result.get( | ||
28 | - 'CommonPrefixes') else [] | ||
29 | - return result_folders + result_files # return files and folders | ||
30 | - except Exception as e: | ||
31 | - print('Error on line {}'.format( | ||
32 | - sys.exc_info()[-1].tb_lineno), type(e).__name__, e) | ||
33 | - | ||
34 | - | ||
35 | -def get_files(main_folder, result): | ||
36 | - try: | ||
37 | - files_list = [] | ||
38 | - for obj in result: | ||
39 | - # main_folder[1:] exp; -folder1/folder2 => delete "-" | ||
40 | - if main_folder[1:] != obj.get('Key'): # if obj is not folder item | ||
41 | - object_url = "https://s3.console.amazonaws.com/s3/buckets/{0}/{1}".format( | ||
42 | - "opijaeclouds", obj.get('Key')) | ||
43 | - # for template file icon | ||
44 | - icon_list = [ | ||
45 | - 'ai.png', 'audition.png', 'avi.png', 'bridge.png', 'css.png', 'csv.png', 'dbf.png', 'doc.png', | ||
46 | - 'dreamweaver.png', 'dwg.png', 'exe.png', 'file.png', 'fireworks.png', 'fla.png', 'flash.png', | ||
47 | - 'folder_icon.png', 'html.png', 'illustrator.png', 'indesign.png', 'iso.png', 'javascript.png', | ||
48 | - 'jpg.png', 'json-file.png', 'mp3.png', 'mp4.png', 'pdf.png', 'photoshop.png', 'png.png', | ||
49 | - 'ppt.png', 'prelude.png', 'premiere.png', 'psd.png', 'rtf.png', 'search.png', 'svg.png', | ||
50 | - 'txt.png', 'xls.png', 'xml.png', 'zip.png', 'zip-1.png'] | ||
51 | - img_file_list = ['ani', 'bmp', 'cal', 'fax', 'gif', 'img', 'jbg', 'jpg', 'jpe', 'mac', 'pbm', | ||
52 | - 'pcd', 'pcx', 'pct', 'pgm', 'png', 'jpeg', 'ppm', 'psd', 'ras', 'tag', 'tif', | ||
53 | - 'wmf'] | ||
54 | - extension, icon = str(obj['Key'].split('.')[-1]).lower(), None | ||
55 | - if extension in img_file_list: | ||
56 | - icon = object_url if extension in ['bmp', 'jpg', 'jpeg', 'png', | ||
57 | - 'gif'] else "/static/images/jpg.png" | ||
58 | - if not icon: | ||
59 | - icon = "/static/images/" + extension + ".png" if extension + \ | ||
60 | - ".png" in icon_list else "/static/images/file.png" | ||
61 | - item_type = "folder" if obj.get( | ||
62 | - 'Key')[-1] == "/" else "other" # for show template | ||
63 | - files_list.append( | ||
64 | - {'key': obj.get('Key'), 'url': object_url, 'icon': icon, | ||
65 | - 'text': obj.get('Key')[len(main_folder) - 1:], 'type': item_type}) | ||
66 | - return sorted(files_list, key=lambda k: str(k['key']).lower(), reverse=no) | ||
67 | - except Exception as e: | ||
68 | - print('Error on line {}'.format( | ||
69 | - sys.exc_info()[-1].tb_lineno), type(e).__name__, e) | ||
70 | - | ||
71 | - | ||
72 | -def get_folders(main_folder, result): | ||
73 | - try: | ||
74 | - files_list = [] | ||
75 | - for obj in result: | ||
76 | - icon = "/static/images/folder_icon.png" | ||
77 | - item_type = "folder" # for show template | ||
78 | - url = obj.get('Prefix') | ||
79 | - files_list.append( | ||
80 | - {'key': obj.get('Prefix'), 'url': url, 'icon': icon, | ||
81 | - 'text': obj.get('Prefix')[len(main_folder) - 1:], 'type': item_type}) | ||
82 | - return sorted(files_list, key=lambda k: str(k['key']).lower(), reverse=no) | ||
83 | - except Exception as e: | ||
84 | - print('Error on line {}'.format( | ||
85 | - sys.exc_info()[-1].tb_lineno), type(e).__name__, e) | ||
86 | -''' |
... | @@ -2,7 +2,18 @@ from django.db import models | ... | @@ -2,7 +2,18 @@ from django.db import models |
2 | from django.utils import timezone | 2 | from django.utils import timezone |
3 | 3 | ||
4 | # Create your models here. | 4 | # Create your models here. |
5 | + | ||
6 | + | ||
5 | class File(models.Model): | 7 | class File(models.Model): |
6 | - path=models.CharField(max_length=300) | ||
7 | - created_date = models.DateTimeField(default=timezone.now) | ||
8 | - modified_date = models.DateTimeField(blank=True, null=True) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
8 | + file = models.FileField(upload_to=None, max_length=100, ) | ||
9 | + name = models.CharField(max_length=50) | ||
10 | + isFolder = models.BooleanField(default=False) | ||
11 | + path = models.FilePathField( | ||
12 | + path=None, match=None, recursive=False, max_length=100) | ||
13 | + owner = models.CharField(max_length=30) | ||
14 | + fileSize = models.IntegerField() | ||
15 | + createdDate = models.DateTimeField(auto_now_add=True) | ||
16 | + modifiedDate = models.DateTimeField(blank=True, null=True) | ||
17 | + | ||
18 | + class Meta: | ||
19 | + ordering = ['createdDate'] | ... | ... |
A_Team_Khuloud/khuloud/cloud/serializers.py
0 → 100644
... | @@ -14,6 +14,7 @@ import configparser | ... | @@ -14,6 +14,7 @@ import configparser |
14 | 14 | ||
15 | config = configparser.ConfigParser() | 15 | config = configparser.ConfigParser() |
16 | config.read('config.ini') | 16 | config.read('config.ini') |
17 | + | ||
17 | # class FileToURL(View): | 18 | # class FileToURL(View): |
18 | # s3_client = boto3.client( | 19 | # s3_client = boto3.client( |
19 | # 's3', | 20 | # 's3', |
... | @@ -89,9 +90,6 @@ class FileList(View): | ... | @@ -89,9 +90,6 @@ class FileList(View): |
89 | bucket = "opijaeclouds" | 90 | bucket = "opijaeclouds" |
90 | 91 | ||
91 | bucketMy = self.s3.Bucket(bucket) | 92 | bucketMy = self.s3.Bucket(bucket) |
92 | - # Iterates through all the objects, doing the pagination for you. Each obj | ||
93 | - # is an ObjectSummary, so it doesn't contain the body. You'll need to call | ||
94 | - # get to get the whole body. | ||
95 | for obj in bucketMy.objects.all(): | 93 | for obj in bucketMy.objects.all(): |
96 | key = obj.key | 94 | key = obj.key |
97 | body = obj.get()['Body'].read() | 95 | body = obj.get()['Body'].read() | ... | ... |
A_Team_Khuloud/user_server/.gitignore
0 → 100644
File mode changed
File mode changed
File mode changed
1 | +from django.contrib.auth.models import User | ||
2 | +from django.contrib.auth import authenticate | ||
3 | +from rest_framework import serializers | ||
4 | + | ||
5 | +# 접속 유지 확인 및 사용자 확인 | ||
6 | +class UserSerializer(serializers.ModelSerializer): | ||
7 | + class Meta: | ||
8 | + model = User | ||
9 | + fields = ['id', 'username', 'email'] | ||
10 | + | ||
11 | +# 회원가입 | ||
12 | +class SignUpSerializer(serializers.ModelSerializer): | ||
13 | + class Meta: | ||
14 | + model = User | ||
15 | + fields = ["username", "email", "password"] | ||
16 | + | ||
17 | + def create(self, validated_data): | ||
18 | + user = User.objects.create_user( | ||
19 | + validated_data['username'], validated_data['email'], validated_data['password'] | ||
20 | + ) | ||
21 | + return user | ||
22 | + | ||
23 | + | ||
24 | +# 로그인 (커스터마이징 => Serializer) | ||
25 | +class LoginSerializer(serializers.Serializer): | ||
26 | + username = serializers.CharField() | ||
27 | + password = serializers.CharField() | ||
28 | + | ||
29 | + def validate(self, data): | ||
30 | + print('validate data',data) | ||
31 | + user = authenticate(**data) | ||
32 | + if user and user.is_active: | ||
33 | + return user | ||
34 | + raise serializers.validationError('Unable to log in with provided credentials.') | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +from django.urls import path, include | ||
2 | +from rest_framework import routers | ||
3 | +from accounts.views import LoginAPI, UserAPI, SignUpAPI | ||
4 | + | ||
5 | +# router = routers.DefaultRouter() | ||
6 | +# router.register(r'user', views.login) | ||
7 | + | ||
8 | +urlpatterns = [ | ||
9 | + path("api/auth/signUp", SignUpAPI.as_view()), | ||
10 | + path("api/auth/login", LoginAPI.as_view()), | ||
11 | + path("api/auth/loadMe", UserAPI.as_view()), | ||
12 | +] |
1 | +from django.shortcuts import render | ||
2 | +from rest_framework.authtoken.models import Token | ||
3 | +from accounts.serializers import ( | ||
4 | + UserSerializer, | ||
5 | + LoginSerializer, | ||
6 | + SignUpSerializer, | ||
7 | +) | ||
8 | +from rest_framework import viewsets, permissions, generics, status | ||
9 | +from rest_framework.response import Response | ||
10 | +from django.contrib.auth.models import User | ||
11 | + | ||
12 | +# LoadUserAPI | ||
13 | +# ssr user loading | ||
14 | +# used for read_only endpoints to represent a single model instance. | ||
15 | +class UserAPI(generics.RetrieveAPIView): | ||
16 | + permission_classes = [ | ||
17 | + permissions.IsAuthenticated, | ||
18 | + ] | ||
19 | + serializer_class = UserSerializer | ||
20 | + | ||
21 | + def get_object(self): | ||
22 | + print('Load Me 인증 성공', self.request.user) | ||
23 | + user = UserSerializer(self.request.user).data | ||
24 | + return self.request.user | ||
25 | + | ||
26 | +# SignUpAPI | ||
27 | +# 회원가입 API | ||
28 | +class SignUpAPI(generics.GenericAPIView): | ||
29 | + serializer_class = SignUpSerializer | ||
30 | + | ||
31 | + def post(self, request, *args, **kwargs): | ||
32 | + print(request.data) | ||
33 | + serializer = self.get_serializer(data=request.data) | ||
34 | + print(serializer) | ||
35 | + serializer.is_valid(raise_exception=True) | ||
36 | + user = serializer.save() | ||
37 | + print(user) | ||
38 | + token, created = Token.objects.get_or_create(user=user) | ||
39 | + return Response({ | ||
40 | + 'user': UserSerializer( | ||
41 | + user, context = self.get_serializer_context() | ||
42 | + ).data, | ||
43 | + 'token': token.key | ||
44 | + }) | ||
45 | + | ||
46 | + | ||
47 | +# LoginAPI: req.data(username, password)=>deserializer=>valid(authenticate)=>serializer | ||
48 | +# 로그인 API | ||
49 | +class LoginAPI(generics.GenericAPIView): | ||
50 | + # field : username, password | ||
51 | + serializer_class = LoginSerializer | ||
52 | + | ||
53 | + def post(self, request, *args, **kwargs): | ||
54 | + print('login request가 들어왔으면 말좀 해줘', request.data) | ||
55 | + serializer = self.get_serializer(data=request.data) | ||
56 | + serializer.is_valid(raise_exception=True) | ||
57 | + user = serializer.validated_data # complex type data | ||
58 | + token, created = Token.objects.get_or_create(user=user) | ||
59 | + print(user, token) | ||
60 | + return Response({ | ||
61 | + 'user': UserSerializer( | ||
62 | + user, context = self.get_serializer_context() | ||
63 | + ).data, | ||
64 | + 'token': token.key | ||
65 | + }) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
A_Team_Khuloud/user_server/mysite/manage.py
0 → 100755
1 | +#!/usr/bin/env python | ||
2 | +"""Django's command-line utility for administrative tasks.""" | ||
3 | +import os | ||
4 | +import sys | ||
5 | + | ||
6 | + | ||
7 | +def main(): | ||
8 | + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') | ||
9 | + try: | ||
10 | + from django.core.management import execute_from_command_line | ||
11 | + except ImportError as exc: | ||
12 | + raise ImportError( | ||
13 | + "Couldn't import Django. Are you sure it's installed and " | ||
14 | + "available on your PYTHONPATH environment variable? Did you " | ||
15 | + "forget to activate a virtual environment?" | ||
16 | + ) from exc | ||
17 | + execute_from_command_line(sys.argv) | ||
18 | + | ||
19 | + | ||
20 | +if __name__ == '__main__': | ||
21 | + main() |
File mode changed
1 | +""" | ||
2 | +ASGI config for mysite project. | ||
3 | + | ||
4 | +It exposes the ASGI callable as a module-level variable named ``application``. | ||
5 | + | ||
6 | +For more information on this file, see | ||
7 | +https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ | ||
8 | +""" | ||
9 | + | ||
10 | +import os | ||
11 | + | ||
12 | +from django.core.asgi import get_asgi_application | ||
13 | + | ||
14 | +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') | ||
15 | + | ||
16 | +application = get_asgi_application() |
1 | +""" | ||
2 | +Django settings for mysite project. | ||
3 | + | ||
4 | +Generated by 'django-admin startproject' using Django 3.0.6. | ||
5 | + | ||
6 | +For more information on this file, see | ||
7 | +https://docs.djangoproject.com/en/3.0/topics/settings/ | ||
8 | + | ||
9 | +For the full list of settings and their values, see | ||
10 | +https://docs.djangoproject.com/en/3.0/ref/settings/ | ||
11 | +""" | ||
12 | + | ||
13 | +import os | ||
14 | +import datetime | ||
15 | + | ||
16 | +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) | ||
17 | +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||
18 | + | ||
19 | + | ||
20 | +# Quick-start development settings - unsuitable for production | ||
21 | +# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ | ||
22 | + | ||
23 | +# SECURITY WARNING: keep the secret key used in production secret! | ||
24 | +SECRET_KEY = '&041&h2k89h+l=^#)0fgf*df-4crdid&fw_duhy5(i#-#g+xaj' | ||
25 | + | ||
26 | +# SECURITY WARNING: don't run with debug turned on in production! | ||
27 | +DEBUG = True | ||
28 | + | ||
29 | +ALLOWED_HOSTS = [ | ||
30 | + 'localhost', | ||
31 | + '127.0.0.1', | ||
32 | +] | ||
33 | + | ||
34 | + | ||
35 | +# Application definition | ||
36 | + | ||
37 | +INSTALLED_APPS = [ | ||
38 | + 'django.contrib.admin', | ||
39 | + 'django.contrib.auth', | ||
40 | + 'django.contrib.contenttypes', | ||
41 | + 'django.contrib.sessions', | ||
42 | + 'django.contrib.messages', | ||
43 | + 'django.contrib.staticfiles', | ||
44 | + 'rest_framework', | ||
45 | + 'rest_framework.authtoken', | ||
46 | + 'corsheaders', | ||
47 | + 'accounts', | ||
48 | +] | ||
49 | + | ||
50 | +MIDDLEWARE = [ | ||
51 | + 'corsheaders.middleware.CorsMiddleware', | ||
52 | + 'django.middleware.common.CommonMiddleware', | ||
53 | + 'django.middleware.security.SecurityMiddleware', | ||
54 | + 'django.contrib.sessions.middleware.SessionMiddleware', | ||
55 | + 'django.middleware.common.CommonMiddleware', | ||
56 | + 'django.middleware.csrf.CsrfViewMiddleware', | ||
57 | + 'django.contrib.auth.middleware.AuthenticationMiddleware', | ||
58 | + 'django.contrib.messages.middleware.MessageMiddleware', | ||
59 | + 'django.middleware.clickjacking.XFrameOptionsMiddleware', | ||
60 | +] | ||
61 | +CORS_ORIGIN_ALLOWED_ALL = True | ||
62 | +CORS_ALLOW_CREDENTIALS = True | ||
63 | + | ||
64 | +CORS_ORIGIN_WHITELIST = [ | ||
65 | +'http://localhost:3001', | ||
66 | +'http://127.0.0.1:3001', | ||
67 | +] | ||
68 | + | ||
69 | +ROOT_URLCONF = 'mysite.urls' | ||
70 | + | ||
71 | +TEMPLATES = [ | ||
72 | + { | ||
73 | + 'BACKEND': 'django.template.backends.django.DjangoTemplates', | ||
74 | + 'DIRS': [], | ||
75 | + 'APP_DIRS': True, | ||
76 | + 'OPTIONS': { | ||
77 | + 'context_processors': [ | ||
78 | + 'django.template.context_processors.debug', | ||
79 | + 'django.template.context_processors.request', | ||
80 | + 'django.contrib.auth.context_processors.auth', | ||
81 | + 'django.contrib.messages.context_processors.messages', | ||
82 | + ], | ||
83 | + }, | ||
84 | + }, | ||
85 | +] | ||
86 | + | ||
87 | +WSGI_APPLICATION = 'mysite.wsgi.application' | ||
88 | + | ||
89 | + | ||
90 | +# Database | ||
91 | +# https://docs.djangoproject.com/en/3.0/ref/settings/#databases | ||
92 | + | ||
93 | +DATABASES = { | ||
94 | + 'default': { | ||
95 | + 'ENGINE': 'django.db.backends.sqlite3', | ||
96 | + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), | ||
97 | + } | ||
98 | +} | ||
99 | + | ||
100 | + | ||
101 | +# Password validation | ||
102 | +# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators | ||
103 | + | ||
104 | +AUTH_PASSWORD_VALIDATORS = [ | ||
105 | + { | ||
106 | + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', | ||
107 | + }, | ||
108 | + { | ||
109 | + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', | ||
110 | + }, | ||
111 | + { | ||
112 | + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', | ||
113 | + }, | ||
114 | + { | ||
115 | + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', | ||
116 | + }, | ||
117 | +] | ||
118 | + | ||
119 | + | ||
120 | +# Internationalization | ||
121 | +# https://docs.djangoproject.com/en/3.0/topics/i18n/ | ||
122 | + | ||
123 | +LANGUAGE_CODE = 'ko' | ||
124 | + | ||
125 | +TIME_ZONE = 'Asia/Seoul' | ||
126 | + | ||
127 | +USE_I18N = True | ||
128 | + | ||
129 | +USE_L10N = True | ||
130 | + | ||
131 | +USE_TZ = True | ||
132 | + | ||
133 | + | ||
134 | +# Static files (CSS, JavaScript, Images) | ||
135 | +# https://docs.djangoproject.com/en/3.0/howto/static-files/ | ||
136 | + | ||
137 | +STATIC_URL = '/static/' | ||
138 | + | ||
139 | +REST_FRAMEWORK = { | ||
140 | + # 권한 인증 | ||
141 | + 'DEFAULT_AUTHENTICATION_CLASSES': ( | ||
142 | + 'rest_framework.authentication.TokenAuthentication', | ||
143 | + ), | ||
144 | +} |
1 | +"""mysite URL Configuration | ||
2 | + | ||
3 | +The `urlpatterns` list routes URLs to views. For more information please see: | ||
4 | + https://docs.djangoproject.com/en/3.0/topics/http/urls/ | ||
5 | +Examples: | ||
6 | +Function views | ||
7 | + 1. Add an import: from my_app import views | ||
8 | + 2. Add a URL to urlpatterns: path('', views.home, name='home') | ||
9 | +Class-based views | ||
10 | + 1. Add an import: from other_app.views import Home | ||
11 | + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') | ||
12 | +Including another URLconf | ||
13 | + 1. Import the include() function: from django.urls import include, path | ||
14 | + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) | ||
15 | +""" | ||
16 | +from django.contrib import admin | ||
17 | +from django.urls import path, include | ||
18 | + | ||
19 | +urlpatterns = [ | ||
20 | + path('admin/', admin.site.urls), | ||
21 | + path('', include('accounts.urls')), | ||
22 | +] |
1 | +""" | ||
2 | +WSGI config for mysite project. | ||
3 | + | ||
4 | +It exposes the WSGI callable as a module-level variable named ``application``. | ||
5 | + | ||
6 | +For more information on this file, see | ||
7 | +https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ | ||
8 | +""" | ||
9 | + | ||
10 | +import os | ||
11 | + | ||
12 | +from django.core.wsgi import get_wsgi_application | ||
13 | + | ||
14 | +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') | ||
15 | + | ||
16 | +application = get_wsgi_application() |
-
Please register or login to post a comment