diff --git a/assets/js/ProfilePage.jsx b/assets/js/ProfilePage.jsx index 71de84c31f6e04828d7091c6e1cd670d5f7c3908..8d3b5ba933bd9c4af2f778fe0303b058b0fe8c37 100644 --- a/assets/js/ProfilePage.jsx +++ b/assets/js/ProfilePage.jsx @@ -58,6 +58,7 @@ export default class ProfilePage extends React.Component { refresh: 1, loading: false, linkedin_url: '', + self_description: '', student_gpa: 0.0, website_url: '', latest_work: '', @@ -102,6 +103,7 @@ export default class ProfilePage extends React.Component { job_seeking_status: data.job_seeking_status, volunteer: data.volunteer, linkedin_url: data.linkedin_url, + self_description: data.self_description, student_gpa: data.student_gpa, website_url: data.website_url, latest_work: data.latest_work, @@ -249,6 +251,10 @@ export default class ProfilePage extends React.Component { onClick={this.handleRadioGender} /> </Form.Field> + <Form.Field> + <label htmlFor="self_description">Deskripsi Diri</label> + <input onChange={this.handleChange} placeholder="Saya suka belajar" name="self_description" /> + </Form.Field> <Form.Field> <label htmlFor="linkedin_url">URL Profile LinkedIn</label> <input @@ -436,6 +442,17 @@ export default class ProfilePage extends React.Component { </Grid> </Segment> + <Segment basic vertical> + <Grid> + <Grid.Column width={2}> + <Icon name="user" size="big" /> + </Grid.Column> + <Grid.Column width={13}> + <p> { this.state.self_description || 'N/A' }</p> + </Grid.Column> + </Grid> + </Segment> + <Segment basic vertical> <Grid> <Grid.Column width={2}> diff --git a/assets/js/__test__/ProfilePage-test.jsx b/assets/js/__test__/ProfilePage-test.jsx index 177268f101df2c897456fcd0ecebe3e514d94ac1..c8f3f399b45a0c064e5db5084399c4aae09f0444 100644 --- a/assets/js/__test__/ProfilePage-test.jsx +++ b/assets/js/__test__/ProfilePage-test.jsx @@ -140,7 +140,7 @@ describe('ProfilePage', () => { const profile = ReactTestUtils.renderIntoDocument( <ProfilePage route={{ own: true, data: studentSession }} user={{ data: studentSession }} params={{ id: 3 }} />); - const checkboxNode = ReactTestUtils.scryRenderedDOMComponentsWithTag(profile, 'Input')[7]; + const checkboxNode = ReactTestUtils.scryRenderedDOMComponentsWithTag(profile, 'Input')[8]; const checkbox = false; checkboxNode.value = checkbox; profile.getProfile().then(()=> expect(profile.state.show_transcript).to.equal(true)); diff --git a/core/migrations/0014_student_self_description.py b/core/migrations/0014_student_self_description.py new file mode 100644 index 0000000000000000000000000000000000000000..4ab840c09a7a64973b1f05b94ae419157cea7bb4 --- /dev/null +++ b/core/migrations/0014_student_self_description.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2019-10-06 12:13 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0013_auto_20170602_1130'), + ] + + operations = [ + migrations.AddField( + model_name='student', + name='self_description', + field=models.CharField(blank=True, db_index=True, max_length=500, null=True), + ), + ] diff --git a/core/migrations/0020_merge_20191006_2103.py b/core/migrations/0020_merge_20191006_2103.py new file mode 100644 index 0000000000000000000000000000000000000000..a7371e1ff71d634c0e2a694450e3985a4cdcc216 --- /dev/null +++ b/core/migrations/0020_merge_20191006_2103.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2019-10-06 14:03 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0014_auto_20191004_1340'), + ('core', '0019_merge_20191006_0852'), + ('core', '0014_student_self_description'), + ('core', '0017_vacancy_amount'), + ] + + operations = [ + ] diff --git a/core/migrations/0051_merge_20191011_1834.py b/core/migrations/0051_merge_20191011_1834.py new file mode 100644 index 0000000000000000000000000000000000000000..2c22b2e0012d28978dfe499c7fff06044e59e051 --- /dev/null +++ b/core/migrations/0051_merge_20191011_1834.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.17 on 2019-10-11 11:34 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0020_merge_20191006_2103'), + ('core', '0050_merge_20191011_1609'), + ] + + operations = [ + ] diff --git a/core/migrations/0052_merge_20191011_1837.py b/core/migrations/0052_merge_20191011_1837.py new file mode 100644 index 0000000000000000000000000000000000000000..f13878cdcf04a0201f731df6655a2a6a03ca99ea --- /dev/null +++ b/core/migrations/0052_merge_20191011_1837.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.17 on 2019-10-11 11:37 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0051_merge_20191011_1730'), + ('core', '0051_merge_20191011_1834'), + ] + + operations = [ + ] diff --git a/core/models/accounts.py b/core/models/accounts.py index c3474b4cf40ac7dbdc2489295791dec1022d5b37..8d10b093c6accf96e00f0afe21a7b940cc855f7d 100644 --- a/core/models/accounts.py +++ b/core/models/accounts.py @@ -75,6 +75,7 @@ class Student(models.Model): major = models.CharField(max_length=30, blank=True, null=True) batch = models.CharField(max_length=4, blank=True, null=True) show_transcript = models.BooleanField(default=False) + self_description = models.CharField(max_length=500, blank=True, db_index=True, null=True) photo = models.FileField(upload_to=get_student_photo_file_path, null=True, blank=True, validators=[validate_image_file_extension]) linkedin_url = models.URLField(max_length=200,blank=True, null=True) website_url = models.URLField(max_length=200,blank=True, null=True) diff --git a/core/serializers/accounts.py b/core/serializers/accounts.py index 63185772a671bd9b11a0e28fa2b348f7c536e6db..9c396978026dce96dbeeb4cbbdf2170a0aeefa10 100644 --- a/core/serializers/accounts.py +++ b/core/serializers/accounts.py @@ -21,7 +21,8 @@ class StudentSerializer(serializers.ModelSerializer): model = Student fields = ['id', 'name', 'user', 'npm', 'resume', 'phone_number', 'gender','birth_place', 'birth_date', 'major', 'batch', \ 'show_transcript', 'photo', 'accepted_no', 'linkedin_url', 'region', 'intro', 'website_url', 'student_gpa', 'age','recommendations', - 'latest_work', 'latest_work_desc','read_no', 'volunteer','job_seeking_status', 'skills', 'expected_salary'] + 'latest_work', 'latest_work_desc','read_no', 'volunteer','job_seeking_status', 'skills', 'expected_salary', \ + 'self_description'] def get_accepted_no(self, obj): apps = Application.objects.filter(student=obj, status=4) @@ -52,6 +53,7 @@ class StudentUpdateSerializer(serializers.ModelSerializer): 'region': instance.region, 'photo': photo, 'show_transcript': instance.show_transcript, + 'self_description': instance.self_description, 'intro': instance.intro, 'expected_salary': instance.expected_salary, 'job_seeking_status' : instance.job_seeking_status, @@ -73,6 +75,7 @@ class StudentUpdateSerializer(serializers.ModelSerializer): instance.region = validated_data.get('region', instance.region) instance.photo = validated_data.get('photo', instance.photo) instance.user.email = validated_data.get('email', instance.user.email) + instance.self_description = validated_data.get('self_description', instance.self_description) instance.intro = validated_data.get('intro', instance.intro) instance.expected_salary = validated_data.get('expected_salary', instance.expected_salary) instance.volunteer = validated_data.get('volunteer', instance.volunteer) @@ -91,7 +94,8 @@ class StudentUpdateSerializer(serializers.ModelSerializer): class Meta: model = Student fields = ['resume', 'email', 'phone_number', 'gender','photo', 'show_transcript', 'linkedin_url', 'region', 'intro', 'website_url', 'student_gpa', - 'recommendations', 'latest_work', 'latest_work_desc', 'volunteer','job_seeking_status', 'skills', 'expected_salary'] + 'recommendations', 'latest_work', 'latest_work_desc', 'volunteer','job_seeking_status', 'skills', 'expected_salary', \ + 'self_description'] class CompanyUpdateSerializer(serializers.ModelSerializer): diff --git a/core/tests/test_accounts.py b/core/tests/test_accounts.py index fde8bb9cf9123cb4e87346f6ea70189527f23876..05f4f46c6481feafe3fcc191d8a43fe427763946 100644 --- a/core/tests/test_accounts.py +++ b/core/tests/test_accounts.py @@ -153,6 +153,11 @@ class ProfileUpdateTests(APITestCase): self.assertEqual(response.data.get('phone_number'), '08123123123') url = '/api/students/' + str(student_id) + "/profile/" + + response = self.client.patch(url, {'self_description': 'I am very happy'}, format='multipart') + self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED) + self.assertEqual(response.data.get('self_description'), 'I am very happy') + response = self.client.patch(url, {'linkedin_url': 'https://www.linkedin.com/in/jojo/'}, format='multipart') self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED) self.assertEqual(response.data.get('linkedin_url'), 'https://www.linkedin.com/in/jojo/') diff --git a/package-lock.json b/package-lock.json index d534692c4e377a85c16026fd1763416b965e8fd7..9a74b3a2590659295e431312ce0559aab366e20a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -90,7 +90,6 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, - "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -1920,8 +1919,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "optional": true + "dev": true }, "arraybuffer.slice": { "version": "0.0.7", @@ -2067,7 +2065,7 @@ "babel-core": { "version": "6.26.3", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha1-suLwnjQtDwyI4vAuBneUEl51wgc=", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "dev": true, "requires": { "babel-code-frame": "^6.26.0", @@ -4278,7 +4276,7 @@ "eslint-plugin-import": { "version": "2.18.2", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha1-AvEYC5Cwd7M9RHoXojJs60AKzrY=", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -4307,7 +4305,7 @@ "resolve": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha1-P8ZEo1yEpIVUYJ/ybsUrZvpXffY=", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -4937,8 +4935,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true, - "optional": true + "dev": true } } }, @@ -4948,7 +4945,7 @@ "integrity": "sha1-nvxRzhnsVykIayKuiJ5dfQ4lZgE=", "dev": true, "requires": { - "esprima": "github:substack/esprima#is-keyword" + "esprima": "github:substack/esprima#0a7f8489a11b44b019ce168506f535f22d0be290" } }, "fast-deep-equal": { @@ -5000,7 +4997,7 @@ "fetch-mock": { "version": "5.13.1", "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-5.13.1.tgz", - "integrity": "sha1-lVeUp389ly8WRLms5loP39YPHfc=", + "integrity": "sha512-eWUo2KI4sRGnRu8tKELCBfasALM5BfvrCxdI7J02j3eUM9mf+uYzJkURA0PSn/29JVapVrYFm+z+9XijXu1PdA==", "dev": true, "requires": { "glob-to-regexp": "^0.3.0", @@ -5755,7 +5752,6 @@ "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5772,7 +5768,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5932,8 +5927,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -6025,8 +6019,7 @@ }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -7250,8 +7243,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "optional": true + "dev": true }, "isomorphic-fetch": { "version": "2.2.1", @@ -7265,7 +7257,7 @@ "isparta": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/isparta/-/isparta-4.1.1.tgz", - "integrity": "sha1-yS5JZylGkU7FQHyAEWDzN04LfLQ=", + "integrity": "sha512-kGwkNqmALQzdfGhgo5o8kOA88p14R3Lwg0nfQ/qzv4IhB4rXarT9maPMaYbo6cms4poWbeulrlFlURLUR6rDwQ==", "dev": true, "requires": { "babel-core": "^6.1.4", @@ -7282,7 +7274,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true } } @@ -7945,7 +7937,7 @@ "karma-firefox-launcher": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.2.0.tgz", - "integrity": "sha1-ZP4D3RAwD5dU1I+ev78x9slKIAw=", + "integrity": "sha512-j9Zp8M8+VLq1nI/5xZGfzeaEPtGQ/vk3G+Y8vpmFWLvKLNZ2TDjD6cu2dUu7lDbu1HXNgatsAX4jgCZTkR9qhQ==", "dev": true, "requires": { "is-wsl": "^2.1.0" @@ -7997,7 +7989,7 @@ "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -8963,7 +8955,7 @@ "moment": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha1-DQVdU/UFKqZTyfbraLtdEr9cK1s=" + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, "move-concurrently": { "version": "1.0.1", @@ -10121,7 +10113,7 @@ "react-ckeditor-wrapper": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/react-ckeditor-wrapper/-/react-ckeditor-wrapper-1.1.2.tgz", - "integrity": "sha1-cvDGgo4X6mNxXV6YNvOrovhIfPM=", + "integrity": "sha512-/COVfezpSKFQxC/OjFoZf1PyzxTvUxzndlpGjEcajzjRgKPzSFZiCoh/VqqwGaaHJROO9pePQ9JxmJy2YlzDAQ==", "requires": { "babel-runtime": "6.x", "classnames": "2.x", @@ -10163,7 +10155,7 @@ "react-hot-loader": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-3.1.3.tgz", - "integrity": "sha1-b5KHcyaVjHywE0tRJHRReGkSYII=", + "integrity": "sha512-d7nZf78irxoGN5PY4zd6CSgZiroOhvIWzRast3qwTn4sSnBwlt08kV8WMQ9mitmxEdlCTwZt+5ClrRSjxWguMQ==", "dev": true, "requires": { "global": "^4.3.0", @@ -10176,7 +10168,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } @@ -10217,7 +10209,7 @@ "react-router": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-3.2.4.tgz", - "integrity": "sha1-/dQVoGKYLgyUP4FO/eUG6uFBjQ4=", + "integrity": "sha512-5kIJXV1Yx+FYk0lDJoPQnt+qFf7HxS6XrIm2aCw0r3XQTxixFd0HSVlHenYRWKmSHlcvSQ7bpYWgdRwJGXWPKw==", "requires": { "create-react-class": "^15.5.1", "history": "^3.0.0",