diff --git a/.DS_Store b/.DS_Store new file mode 100755 index 0000000000000000000000000000000000000000..877d8f79f51a6e99addb143fe20b35e312133f9a Binary files /dev/null and b/.DS_Store differ diff --git a/.dockerignore b/.dockerignore old mode 100644 new mode 100755 diff --git a/.eslintrc b/.eslintrc old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore index 2c6cae6466efa0b98f94cfdcec948ab8ae135093..7f0104ca2c8ad7939275db70693984d5ab31d84b 100755 --- a/.gitignore +++ b/.gitignore @@ -301,6 +301,7 @@ dmypy.json .pyre/ ### VisualStudioCode ### +.vscode .vscode/* !.vscode/settings.json !.vscode/tasks.json @@ -319,3 +320,8 @@ webpack-stats.json assets/bundles/* test/* .tmp/ + +# package-lock.json +package-lock.json +# MacOS related files +.DS_Store diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 040e750df5706268df1aca69ac51240efc58fb7f..018b68feffeaab91aebc3431e205fc625fdb1557 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,23 @@ --- -image: python:2-jessie +image: python:2-stretch stages: - build - test - deploy -test: +test-frontend: + image: amio/node-chrome:latest + stage: test + script: + - npm install + - npm run build-production + - npm run karma + artifacts: + paths: + - test/ + +test-backend: services: - postgres:9.6-alpine variables: @@ -15,18 +26,10 @@ test: POSTGRES_PASSWORD: kape stage: test script: - - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - - - sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' - - apt-get update && apt-get install -y google-chrome-stable libappindicator1 libindicator7 libpq-dev libxss1 python-dev python-pip sudo - - export CHROME_BIN=/usr/bin/google-chrome - - curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash - - - apt-get install -y build-essential nodejs - - npm install - - npm run build-production - pip install -r requirements.txt + - python manage.py makemigrations - python manage.py migrate - python manage.py test - - npm run karma artifacts: paths: - test/ @@ -44,14 +47,15 @@ SonarScanner Analysis: pages: stage: deploy dependencies: - - test + - test-backend + - test-frontend script: - mv test/ public/ artifacts: paths: - public expire_in: 30 days - + staging: type: deploy script: diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS new file mode 100755 index 0000000000000000000000000000000000000000..a69023229f36573edb56148d0e187d8e397ce110 --- /dev/null +++ b/.gitlab/CODEOWNERS @@ -0,0 +1,4 @@ +# Code owners file + +## Changes to these file(s) require approval from the teaching team +sonar-project.properties @addianto @hafiyyan94 \ No newline at end of file diff --git a/.tmp/mocha-webpack/455fffbb3125fc1ebc427c559e4e5438-entry.js b/.tmp/mocha-webpack/455fffbb3125fc1ebc427c559e4e5438-entry.js old mode 100644 new mode 100755 diff --git a/Dockerfile b/Dockerfile old mode 100644 new mode 100755 index f2c6d104e0a78dee7246ef4f596bdc9b38ec75ea..a604c3143011a27a0594fd79dcbd3c328388b9b1 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:4 AS frontend-builder +FROM node:8 AS frontend-builder WORKDIR /home/kape/app COPY . . @@ -7,7 +7,7 @@ RUN npm config set proxy ${NPM_PROXY} \ && npm install \ && npm run build-production -FROM python:2-jessie AS app +FROM python:2-stretch AS app # Avoid warnings by switching to noninteractive ENV DEBIAN_FRONTEND=noninteractive @@ -65,20 +65,20 @@ ARG IMAGE_VENDOR="Faculty of Computer Science Universitas Indonesia" ARG IMAGE_TITLE="Kape" ARG IMAGE_DESCRIPTION="Fork of https://gitlab.com/PPL2017csui/PPLA1" LABEL org.opencontainers.image.created=${IMAGE_CREATED} \ - org.opencontainers.image.authors=${IMAGE_AUTHORS} \ - org.opencontainers.image.source=${IMAGE_SOURCE} \ - org.opencontainers.image.version=${IMAGE_VERSION} \ - org.opencontainers.image.revision=${IMAGE_REVISION} \ - org.opencontainers.image.vendor=${IMAGE_VENDOR} \ - org.opencontainers.image.licenses="ISC" \ - org.opencontainers.image.title=${IMAGE_TITLE} \ - org.opencontainers.image.description=${IMAGE_DESCRIPTION} + org.opencontainers.image.authors=${IMAGE_AUTHORS} \ + org.opencontainers.image.source=${IMAGE_SOURCE} \ + org.opencontainers.image.version=${IMAGE_VERSION} \ + org.opencontainers.image.revision=${IMAGE_REVISION} \ + org.opencontainers.image.vendor=${IMAGE_VENDOR} \ + org.opencontainers.image.licenses="ISC" \ + org.opencontainers.image.title=${IMAGE_TITLE} \ + org.opencontainers.image.description=${IMAGE_DESCRIPTION} ## Note to editors: The following label assignments are to ensure backward ## compatibility with Label Schema standard LABEL org.label-schema.build-date=${IMAGE_CREATED} \ - org.label-schema.vcs-url=${IMAGE_SOURCE} \ - org.label-schema.version=${IMAGE_VERSION} \ - org.label-schema.vendor=${IMAGE_VENDOR} \ - org.label-schema.title=${IMAGE_TITLE} \ - org.label-schema.description=${IMAGE_DESCRIPTION} \ No newline at end of file + org.label-schema.vcs-url=${IMAGE_SOURCE} \ + org.label-schema.version=${IMAGE_VERSION} \ + org.label-schema.vendor=${IMAGE_VENDOR} \ + org.label-schema.title=${IMAGE_TITLE} \ + org.label-schema.description=${IMAGE_DESCRIPTION} \ No newline at end of file diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md index 3020546098563953b463aa84d24bb2958f22f589..0d15c3e1a4a3d4193d36023c23f69242093bd4cc 100755 --- a/README.md +++ b/README.md @@ -2,6 +2,13 @@ > Internship matchmaking platform for students and companies. +[](https://gitlab.cs.ui.ac.id/pmpl/class-project/kape/commits/master) +[](https://gitlab.cs.ui.ac.id/pmpl/class-project/kape/commits/master) + +[](https://pmpl.cs.ui.ac.id/sonarqube/dashboard?id=id.ac.ui.cs.foss%3Akape) +[](https://pmpl.cs.ui.ac.id/sonarqube/dashboard?id=id.ac.ui.cs.foss%3Akape) +[](https://pmpl.cs.ui.ac.id/sonarqube/dashboard?id=id.ac.ui.cs.foss%3Akape) + ## Table of Contents - [Install](#install) @@ -12,20 +19,21 @@ ## Install -This project uses Python 2 and Node.js v4 for building the backend and frontend, +This project uses Python 2 and Node.js v8 for building the backend and frontend, respectively. The backend uses Django Framework and PostgreSQL database, while the frontend is developed using React. You need to install the required dependencies prior to building and contributing to the project. -- [Node.js v4.9.1](https://nodejs.org/en/download/releases/) and `npm` package +- [Node.js v10.16.0](https://nodejs.org/en/download/releases/) and `npm` package manager. > Note: We recommend `nvm` (Node Version Manager) for installing Node.js. You > can find `nvm` for your OS at the following links: + > > - [nvm for macOS or GNU/Linux-based OS](https://github.com/creationix/nvm) > - [nvm for Windows](https://github.com/coreybutler/nvm-windows) > > Once `nvm` has been installed, install Node.js and activate it by executing - > `nvm install 4.9.1` followed by `nvm activate 4.9.1`. + > `nvm install 10.16.0` followed by `nvm activate 10.16.0`. - [Python 2.7.16](https://www.python.org/downloads/release/) and `pip` package manager. > Note: We recommend using _virtual environment_ to isolate project-specific @@ -52,7 +60,7 @@ $ source env/bin/activate $ python --version # or: python2 --version Python 2.7.16 $ node --version -v4.9.1 +v10.16.0 ``` Now install the packages required by Node.js and Python 2: @@ -107,7 +115,7 @@ npm run webpack # If you want the uglified, zipped, production-ready version, run: npm run build-production ``` -You can see the app running by going to `localhost:8080` via your favourite +You can see the app running by going to `localhost:8000` via your favourite Web browser. ## Running Development Mode (Containerised) @@ -123,6 +131,7 @@ docker-compose run --rm app python manage.py loaddata seeder.json ``` > Explanation: +> > 1. Rebuild the application (the frontend + backend), then start it along with > the database (`postgres`) and Web server (`nginx`). > 1. Perform database migration diff --git a/README.old.md b/README.old.md old mode 100644 new mode 100755 diff --git a/assets/css/custom.css b/assets/css/custom.css index 9b7cf50a1356d41530baa447984f2fb2abfd873a..9432451ec7f4047c1a29eadd639ed68f1bfd8f57 100755 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,4 +1,4 @@ -.center{ +.center { text-align: center; } @@ -13,9 +13,9 @@ img { -moz-box-sizing: border-box; } -.ui.inverted.segment.header{ - background-color: #EEEEEE; - color:black; +.ui.inverted.segment.header { + background-color: #eeeeee; + color: black; } .item-list { @@ -23,17 +23,17 @@ img { width: 100%; } -.ui.card.register{ -background-color: #EEEEEE; +.ui.card.register { + background-color: #eeeeee; } -.create-lowongan{ - padding-bottom: 7%; - padding-left:15%; - padding-right:15%; +.create-lowongan { + padding-bottom: 7%; + padding-left: 15%; + padding-right: 15%; } -.ui.segment.form-segment{ +.ui.segment.form-segment { padding-bottom: 50px; } @@ -65,9 +65,8 @@ background-color: #EEEEEE; padding: 25px; } -.halamanLogin{ - background-size: cover; - background: url("../img/background.png")no-repeat center center fixed; +.halamanLogin { + background: url("../img/background.png") no-repeat center center fixed; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; @@ -75,64 +74,58 @@ background-color: #EEEEEE; padding-bottom: 80px; } - -.headerLoginform{ +.headerLoginform { background-color: #2e6da4; } -.formLogin{ - /*margin: auto;*/ - /*width: 430px;*/ -} - -.registerModal{ +.registerModal { margin: 0 auto; } -.bookmark{ +.bookmark { float: right; } -.formLogin img{ -height: 70px !important; -margin:5px; +.formLogin img { + height: 70px !important; + margin: 5px; } -.formLogin span{ -font-size: 32px; +.formLogin span { + font-size: 32px; } -.formLogin span{ +.formLogin span { margin-left: 5px; } -.LoginPage{ +.LoginPage { height: 700px; } -.input{ +.input { margin-top: 5px; } -.daftar{ +.daftar { float: right; - margin-top:10px; + margin-top: 10px; } -.registerForm{ +.registerForm { margin: 0 auto; /*padding:50px;*/ - background-color: #3B8686; + background-color: #3b8686; } -h3{ - color:black; +h3 { + color: black; } -h4{ +h4 { color: black; } -h5{ +h5 { color: black; } @@ -155,43 +148,43 @@ input.active:invalid { margin-top: 5px; } -card .formRegis{ +card .formRegis { margin-top: 100px; } -.itemLowongan{ +.itemLowongan { color: black; } -.ui.pointing.secondary.menu{ +.ui.pointing.secondary.menu { background-color: #ffffff; margin-bottom: 10px; margin-top: 0px; } -.extra.extra-company h3{ - padding-top:10px; +.extra.extra-company h3 { + padding-top: 10px; } -.extra.extra-company h2{ +.extra.extra-company h2 { color: black; } -.biodata h5{ +.biodata h5 { line-height: 30%; } -.biodataCompany h4{ +.biodataCompany h4 { color: grey; } -.buttonProfile{ - margin-top:30px; +.buttonProfile { + margin-top: 30px; } -.ui.segment.profile-form{ +.ui.segment.profile-form { padding-bottom: 37px; - margin-top:4%; + margin-top: 4%; } .profilePage { @@ -200,93 +193,119 @@ card .formRegis{ margin-right: 5%; } -#react-app{ - position: relative; /* needed for footer positioning*/ - /*height: 100% !important; !* real browsers *!*/ - min-height: 100%; /* real browsers */ - background-color: #EEEEEE; +#react-app { + position: relative; /* needed for footer positioning*/ + /*height: 100% !important; !* real browsers *!*/ + min-height: 100%; /* real browsers */ + background-color: #eeeeee; } -.content{ +.content { padding-bottom: 5%; } -.mainContent{ - padding-bottom: 40px; +.mainContent { + padding-bottom: 40px; } -.footer{ - background-color: #031634; - position: absolute; - right: 0; - bottom: 0; - left: 0; - width: 100%; - height: 30px; - padding: 6px; +.footer { + background-color: #031634; + position: absolute; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 30px; + padding: 6px; } -.footer h5{ - color:white; +.footer h5 { + color: white; } -.profilePage{ - margin-left:5%; - margin-right:5%; +.profilePage { + margin-left: 5%; + margin-right: 5%; margin-bottom: auto; } -.ui.segment.segmentProfileCompany{ +.ui.segment.segmentProfileCompany { margin-left: 10%; margin-right: 10%; padding: 5%; } -.ui.segment.profileFormCompany{ - margin-top:4%; +.ui.segment.profileFormCompany { + margin-top: 4%; margin-left: 10%; margin-right: 10%; - padding-bottom:3%; + padding-bottom: 3%; } -.companyProfile{ - padding-bottom:5%; +.companyProfile { + padding-bottom: 5%; } -.ui.segment.vacancyListCompany{ +.ui.segment.vacancyListCompany { margin-left: 10%; margin-right: 10%; } -.ui.segment.paginationCompany{ +.ui.segment.paginationCompany { margin: 2% 7%; } -.admin-bar{ +.admin-bar { margin: 0; padding: 10px; width: 100%; text-align: right; - background-color: #304D8A; + background-color: #304d8a; color: white; } -.dropdownApplicant{ - margin-left:7%; - margin-top:2%; +.dropdownApplicant { + margin-left: 7%; + margin-top: 2%; margin-bottom: 0; } .administrationButtons { - margin-left:7%; - margin-top:2%; + margin-left: 7%; + margin-top: 2%; margin-bottom: 2%; } -.ui.segment.transkrip{ - margin-left:7%; - margin-right:7%; +.ui.segment.transkrip { + margin-left: 7%; + margin-right: 7%; } .ui.segment.kop { line-height: 5px; -} \ No newline at end of file +} + +.jumlahLamaran { + font-weight: bold; +} +.search-container { + width: fit-content; + margin: auto; +} + +.search-form { + border: none; + border-bottom: solid #0d5aa7 2px; + text-decoration: none; + outline: none; + font-size: 14pt; +} + +.search-button { + background-color: #0d5aa7; + color: white; + border: none; + padding: 10px; + font-size: 14pt; + border-radius: 5px; + margin-left: 10px; +} diff --git a/assets/img/UI.png b/assets/img/UI.png old mode 100644 new mode 100755 diff --git a/assets/img/background.png b/assets/img/background.png old mode 100644 new mode 100755 diff --git a/assets/img/background2.png b/assets/img/background2.png old mode 100644 new mode 100755 diff --git a/assets/img/bw-blur.png b/assets/img/bw-blur.png old mode 100644 new mode 100755 diff --git a/assets/img/bw.jpg b/assets/img/bw.jpg old mode 100644 new mode 100755 diff --git a/assets/img/image-coba.jpg b/assets/img/image-coba.jpg new file mode 100755 index 0000000000000000000000000000000000000000..71582c476ad9d91e873d5a123b48e958428686d4 Binary files /dev/null and b/assets/img/image-coba.jpg differ diff --git a/assets/js/AdminVacancyPage.jsx b/assets/js/AdminVacancyPage.jsx old mode 100644 new mode 100755 diff --git a/assets/js/ApplicantPage.jsx b/assets/js/ApplicantPage.jsx old mode 100644 new mode 100755 index bbdbcb40073b10b469b5f9ad2b11c93b309f8e6b..703d5457907b209bd86fbe31113712bb9bcd994a --- a/assets/js/ApplicantPage.jsx +++ b/assets/js/ApplicantPage.jsx @@ -7,7 +7,6 @@ import Pagination from './components/Pagination'; import Server from './lib/Server'; export default class ApplicantPage extends React.Component { - static propTypes = { user: React.PropTypes.object.isRequired, }; @@ -29,33 +28,39 @@ export default class ApplicantPage extends React.Component { this.getVacancyList(); } - - getVacancyList= () => Server.get(`/companies/${this.props.user.data.company.id}/vacancies/`, false).then((data) => { - const results = data.results; - const names = ['Semua Lowongan']; - const urls = [{ - key: 0, - value: `/companies/${this.props.user.data.company.id}/applications/`, - text: 'Semua Lowongan', - }]; - results.map((vacancy) => { - names.push(vacancy.name); - const url = `/companies/${this.props.user.data.company.id}/applications/${vacancy.id}/by_vacancy/`; - const info = { - key: vacancy.id, - value: url, - text: vacancy.name, - }; - urls.push(info); - return urls; - }); - this.setState({ urls }); - }, error => error.then((r) => { - this.modalAlert.open('Gagal mendapatkan daftar lowongan', r.detail); - })); + getVacancyList = () => + Server.get(`/companies/${this.props.user.data.company.id}/vacancies/`, false).then( + (data) => { + const results = data.results; + const names = ['Semua Lowongan']; + const urls = [ + { + key: 0, + value: `/companies/${this.props.user.data.company.id}/applications/`, + text: 'Semua Lowongan', + }, + ]; + results.map((vacancy) => { + names.push(vacancy.name); + const url = `/companies/${this.props.user.data.company.id}/applications/${vacancy.id}/by_vacancy/`; + const info = { + key: vacancy.id, + value: url, + text: vacancy.name, + }; + urls.push(info); + return urls; + }); + this.setState({ urls }); + }, + error => + error.then((r) => { + this.modalAlert.open('Gagal mendapatkan daftar lowongan', r.detail); + }), + ); handleChange = (e, data) => { - this.setState({ selected: data.value, refresh: this.state.refresh + 5 }); + this.setState({ selected: data.value, refresh: this.state.refresh + 6 }); }; render() { @@ -63,9 +68,23 @@ export default class ApplicantPage extends React.Component { return (
{ data.description }
+{ this.state.category } - { this.state.description }
+{ this.state.website }
{ this.state.major || 'N/A' }, { this.state.batch || 'N/A' }
+{this.state.major || 'N/A'}, {this.state.batch || 'N/A'}
{ this.state.email || 'N/A' }
+{this.state.email || 'N/A'}
{ this.state.phone_number || 'N/A' }
+{this.state.phone_number || 'N/A'}
+{ this.state.gender || 'N/A' }
{ this.state.cityOfBirth || 'N/A' }, { this.state.dateOfBirth || 'N/A' }
+{this.state.cityOfBirth || 'N/A'}, {this.state.dateOfBirth || 'N/A'}
+{ this.state.self_description || 'N/A' }
+N/A
+ }{this.state.region || 'N/A'}
+{this.state.skills || 'Skills belum ditambahkan'}
+Latest working experience as: {this.state.latest_work || 'N/A'}
+Description: {this.state.latest_work_desc || 'N/A'}
+{ this.state.expected_salary || 'N/A' }
+{this.state.volunteer || 'N/A'}
+{this.state.age + ' years' || 'N/A'}
+{ this.state.region || 'N/A' }
+{this.state.intro || 'N/A'}
+{ this.state.intro || 'N/A' }
+Jumlah lamaran diterima: {this.state.acceptedNo || '0' }
+Jumlah lamaran dibaca perusahaan: {this.state.readNo || '0'}
+Saya sedang mencari pekerjaan sekarang dan saya terbuka untuk + mendapat informasi mengenai lowongan kerja.
+Saya sedang tidak mencari pekerjaan. Mohon jangan kirimkan + informasi mengenai lowongan pekerjaan.
+- { this.props.data.cover_letter ? this.props.data.cover_letter : 'Kosong' } -
+{this.props.data.cover_letter ? this.props.data.cover_letter : 'Kosong'}
@@ -76,6 +88,9 @@ export default class TopMenu extends React.Component {