diff --git a/canapGEST/API/app/Helpers/AccessLevelHelper.php b/canapGEST/API/app/Helpers/AccessLevelHelper.php index 72d30ced68d00831fc3148db2307f75535eb1a99..6dda7a491a0e6cf3726744d537c69933db4a6ef4 100644 --- a/canapGEST/API/app/Helpers/AccessLevelHelper.php +++ b/canapGEST/API/app/Helpers/AccessLevelHelper.php @@ -55,7 +55,7 @@ class AccessLevelHelper { $default_access_groups = self::getDefaultAccessGroups(); $user_alloweds = []; - $user_role = 'formateur'; + $user_role = 'responsable'; // formateur $user_groups = explode(',', $user_groups); foreach ($default_access_groups as $group => $accesses) { diff --git a/canapGEST/API/app/Http/Controllers/PositionController.php b/canapGEST/API/app/Http/Controllers/PositionController.php index 9955df2c2df708f4d40de19fa6e9dbecbffccd2c..639b7c43679e9dcba9b5cb2031079c926b55ed82 100644 --- a/canapGEST/API/app/Http/Controllers/PositionController.php +++ b/canapGEST/API/app/Http/Controllers/PositionController.php @@ -38,7 +38,7 @@ class PositionController extends Controller return DB::table('job')->get(); } - public function create() + public function createPosition() { $this->validate($this->request, [ 'position_access_group' => 'required', @@ -47,7 +47,7 @@ class PositionController extends Controller 'job_id' => 'required' ], [lang::get('validation.required')]); - $has_permitted_role = AccessLevelHelper::hasPermittedRole($this->user_role, 'formateur'); + $has_permitted_role = AccessLevelHelper::hasPermittedRole($this->user_role, 'responsable'); $new_position_access_group = $this->request->input('position_access_group'); $new_position_spot_number = $this->request->input('position_spot_number'); @@ -68,7 +68,7 @@ class PositionController extends Controller } } - public function update($id) + public function updatePosition($id) { $this->validate($this->request, [ 'position_access_group' => 'required', @@ -77,6 +77,8 @@ class PositionController extends Controller 'job_id' => 'required' ], [lang::get('validation.required')]); + $has_permitted_role = AccessLevelHelper::hasPermittedRole($this->user_role, 'responsable'); + $position_access_group = $this->request->input('position_access_group'); $position_spot_number = $this->request->input('position_spot_number'); $location_id = $this->request->input('location_id'); @@ -84,7 +86,7 @@ class PositionController extends Controller $wanted_position_exists = DB::table('position')->where('position_id', $id)->exists(); - if ($wanted_position_exists) { + if ($wanted_position_exists && $has_permitted_role) { DB::table('position')->where('position_id', $id)->update([ "position_access_group" => $position_access_group, "position_spot_number" => $position_spot_number, @@ -96,4 +98,44 @@ class PositionController extends Controller return abort(403, lang::get('http.unauthorized')); } } + + public function createLocation () { + $this->validate($this->request, [ + 'location_site' => 'required' + ], [lang::get('validation.required')]); + + $has_permitted_role = AccessLevelHelper::hasPermittedRole($this->user_role, 'responsable'); + + $new_location = $this->request->input('location_site'); + + if ($has_permitted_role) { + $inserted_id = DB::table('location')->insertGetId([ + "location_site" => $new_location + ]); + return ["message" => lang::get('http.success.created.location'), "id" => $inserted_id]; + } else { + return abort(403, lang::get('http.unauthorized')); + } + } + + public function createJob () { + $this->validate($this->request, [ + 'job_full_value' => 'required' + ], [lang::get('validation.required')]); + + $has_permitted_role = AccessLevelHelper::hasPermittedRole($this->user_role, 'responsable'); + + $new_value = $this->request->input('job_full_value'); + $new_short_value = preg_replace('/[0-9]+/', '', preg_replace('/[^A-Za-z0-9\-]/', '', preg_replace('/\s+/', '', $new_value))); + + if ($has_permitted_role) { + $inserted_id = DB::table('job')->insertGetId([ + "job_full_value" => $new_value, + "job_short_value" => $new_short_value + ]); + return ["message" => lang::get('http.success.created.job'), "id" => $inserted_id]; + } else { + return abort(403, lang::get('http.unauthorized')); + } + } } diff --git a/canapGEST/API/resources/lang/fr/http.php b/canapGEST/API/resources/lang/fr/http.php index 16ac67cd62e69be420f7c440977899010609e2ff..0d6d194b0fee24fe83e68c4a7e410b81b2da9680 100644 --- a/canapGEST/API/resources/lang/fr/http.php +++ b/canapGEST/API/resources/lang/fr/http.php @@ -7,17 +7,23 @@ return [ 'created' => [ 'marker' => 'Marqueur ajouté', 'comment' => 'Commentaire ajouté', - 'position' => 'Offre ajoutée' + 'position' => 'Offre ajoutée', + 'location' => 'Lieu ajouté', + 'job' => 'Métier ajouté' ], 'updated' => [ 'marker' => 'Marqueur modifié', 'comment' => 'Commentaire modifié', - 'position' => 'Offre modifiée' + 'position' => 'Offre modifiée', + 'location' => 'Lieu modifié', + 'job' => 'Métier modifié' ], 'deleted' => [ 'marker' => 'Marqueur supprimé', 'comment' => 'Commentaire supprimé', - 'position' => 'Offre supprimée' + 'position' => 'Offre supprimée', + 'location' => 'Lieu supprimé', + 'job' => 'Métier supprimé' ] ] ]; diff --git a/canapGEST/API/routes/web.php b/canapGEST/API/routes/web.php index 1a173ecb23cac768d6aba44fe8c79dcab81e8037..816e8e3d8692af98f863f693783c53160993c358 100644 --- a/canapGEST/API/routes/web.php +++ b/canapGEST/API/routes/web.php @@ -34,12 +34,14 @@ $router->group(['middleware' => 'jwt.auth'], function () use ($router) { $router->get('api/status', 'StatusController@getAvailableStatus'); $router->patch('api/status/applicant/{id:[0-9]+}', 'StatusController@updateApplicantStatus'); - // TODO: Positions + // Positions, jobs and locations $router->get('api/positions', 'PositionController@getAll'); $router->get('api/locations', 'PositionController@getAvailableLocations'); $router->get('api/jobs', 'PositionController@getAvailableJobs'); - $router->put('api/position', 'PositionController@create'); - $router->patch('api/position/{id:[0-9]+}', 'PositionController@update'); + $router->put('api/position', 'PositionController@createPosition'); + $router->put('api/location', 'PositionController@createLocation'); + $router->put('api/job', 'PositionController@createJob'); + $router->patch('api/position/{id:[0-9]+}', 'PositionController@updatePosition'); // Files $router->get('api/file/{id:[0-9]+}', 'FilesController@getFile'); diff --git a/canapGEST/Documentation/journal_travail.xlsx b/canapGEST/Documentation/journal_travail.xlsx index 234422504b4254041759d62af3bbba767030b8a1..303f4116bb7439c513e98329ce515c9bf425199d 100644 Binary files a/canapGEST/Documentation/journal_travail.xlsx and b/canapGEST/Documentation/journal_travail.xlsx differ diff --git a/canapGEST/Site/src/store/modules/modules.js b/canapGEST/Site/src/store/modules/modules.js index a0171efe3cf363b239b638e82b65c4de396aec64..4c25b2bd05abfc090870c97053c5ae9cd63de577 100644 --- a/canapGEST/Site/src/store/modules/modules.js +++ b/canapGEST/Site/src/store/modules/modules.js @@ -1,7 +1,9 @@ import moduleUser from './user' import moduleApplications from './applications' +import modulePositions from './positions' export default { moduleUser, - moduleApplications + moduleApplications, + modulePositions } \ No newline at end of file diff --git a/canapGEST/Site/src/store/modules/positions/actions.js b/canapGEST/Site/src/store/modules/positions/actions.js new file mode 100644 index 0000000000000000000000000000000000000000..02d4ea7126c15836022f255caeb775a059f947b0 --- /dev/null +++ b/canapGEST/Site/src/store/modules/positions/actions.js @@ -0,0 +1,95 @@ +import axios from '../../../plugins/axios' + +export function getPositions(context) { + axios({ + method: 'get', + url: '/positions' + }) + .then(response => { + context.commit('setPositions', response.data) + }) +} + +export function getJobs(context) { + axios({ + method: 'get', + url: '/jobs' + }) + .then(response => { + context.commit('setJobs', response.data) + }) +} + +export function getLocations(context) { + axios({ + method: 'get', + url: '/locations' + }) + .then(response => { + context.commit('setLocations', response.data) + }) +} + +export function createPosition(context, data) { + axios({ + method: 'put', + url: '/position', + data: data + }) + .then(response => { + console.log(response) + // Notif this + }) + .catch(err => { + console.log(err) + // Notif this + }) +} + +export function updatePosition(context, data) { + axios({ + method: 'patch', + url: '/position/' + data.position_id, + data: data + }) + .then(response => { + console.log(response) + // Notif this + }) + .catch(err => { + console.log(err) + // Notif this + }) +} + +export function createJob(context, data) { + return new Promise((resolve, reject) => { + axios({ + method: 'put', + url: '/job', + data: data + }) + .then(response => { + resolve(response.data) + }) + .catch(err => { + reject(err) + }) + }) +} + +export function createLocation(context, data) { + return new Promise((resolve, reject) => { + axios({ + method: 'put', + url: '/location', + data: data + }) + .then(response => { + resolve(response.data) + }) + .catch(err => { + reject(err) + }) + }) +} \ No newline at end of file diff --git a/canapGEST/Site/src/store/modules/positions/getters.js b/canapGEST/Site/src/store/modules/positions/getters.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/canapGEST/Site/src/store/modules/positions/index.js b/canapGEST/Site/src/store/modules/positions/index.js new file mode 100644 index 0000000000000000000000000000000000000000..4b0c8d847d7bba60a0d61cf502a9ec3fa03c605a --- /dev/null +++ b/canapGEST/Site/src/store/modules/positions/index.js @@ -0,0 +1,12 @@ +import state from './state' +// import * as getters from './getters' +import * as mutations from './mutations' +import * as actions from './actions' + +export default { + namespaced: true, + state, + // getters, + mutations, + actions +} \ No newline at end of file diff --git a/canapGEST/Site/src/store/modules/positions/mutations.js b/canapGEST/Site/src/store/modules/positions/mutations.js new file mode 100644 index 0000000000000000000000000000000000000000..62c0af728d31381e9404b57e3cec0943c0f8b43a --- /dev/null +++ b/canapGEST/Site/src/store/modules/positions/mutations.js @@ -0,0 +1,11 @@ +export function setPositions (state, data) { + state.positions = data +} + +export function setJobs (state, data) { + state.available_jobs = data +} + +export function setLocations (state, data) { + state.available_locations = data +} \ No newline at end of file diff --git a/canapGEST/Site/src/store/modules/positions/state.js b/canapGEST/Site/src/store/modules/positions/state.js new file mode 100644 index 0000000000000000000000000000000000000000..2b7e85ae8dfa6dccfdd23cbc3cfad9f7c5ecec84 --- /dev/null +++ b/canapGEST/Site/src/store/modules/positions/state.js @@ -0,0 +1,5 @@ +export default { + positions: [], + available_jobs: [], + available_locations: [] +} \ No newline at end of file diff --git a/canapGEST/Site/src/store/modules/user/actions.js b/canapGEST/Site/src/store/modules/user/actions.js index 9be3e7074e209ba41f5a6a26f0f76bc20925e0b5..2afcd0e07212095f5333183d4343d8dbfdabbf73 100644 --- a/canapGEST/Site/src/store/modules/user/actions.js +++ b/canapGEST/Site/src/store/modules/user/actions.js @@ -16,6 +16,10 @@ export function login() { } export function logout() { + axios({ + method: 'get', + url: '/auth/logout' + }) localStorage.removeItem('stored_token'); } diff --git a/canapGEST/Site/src/views/OpenJobsView.vue b/canapGEST/Site/src/views/OpenJobsView.vue index 60d6277e1e817f201dcf8838804a34772db72323..55b3cc36f9e20874cdd7438483254dd3447e80ec 100644 --- a/canapGEST/Site/src/views/OpenJobsView.vue +++ b/canapGEST/Site/src/views/OpenJobsView.vue @@ -1,12 +1,220 @@ <template> <div id="openjobs-view"> <h1>Places ouvertes</h1> + <template> + <div> + <v-toolbar flat color="white"> + <v-spacer></v-spacer> + <v-dialog v-model="dialog" max-width="600px"> + <template v-slot:activator="{ on }"> + <v-btn color="primary" dark class="mb-2" v-on="on">Ajouter</v-btn> + </template> + <v-card> + <v-card-title> + <span class="headline">{{ modalTitle }}</span> + </v-card-title> + + <v-card-text> + <v-container grid-list-md> + <v-layout wrap> + <!-- <v-text-field + v-model="editedItem.job_short_value" + label="Clé métier" + readonly + disabled + ></v-text-field>--> + <v-flex xs12 sm8 v-if="addJob"> + <v-text-field v-model="newJob.job_full_value" label="Nouveau métier"></v-text-field> + </v-flex> + <v-flex xs12 sm5 v-else> + <v-select + :items="$store.state.modulePositions.available_jobs" + label="Métier" + item-text="job_full_value" + item-value="job_id" + v-model="editedItem.job_id" + ></v-select> + </v-flex> + <v-flex xs12 sm1> + <v-btn flat icon color="primary" @click="addNewJob" v-if="!addJob"> + <v-icon>add</v-icon> + </v-btn> + <v-btn flat color="primary" @click="addNewJob" v-else>Confirmer</v-btn> + </v-flex> + <v-flex xs12 sm8 v-if="addLocation"> + <v-text-field v-model="newLocation.location_site" label="Nouveau lieu"></v-text-field> + </v-flex> + <v-flex xs12 sm5 v-else> + <v-select + :items="$store.state.modulePositions.available_locations" + label="Lieu" + item-text="location_site" + item-value="location_id" + v-model="editedItem.location_id" + ></v-select> + </v-flex> + <v-flex xs12 sm1> + <v-btn flat icon color="primary" @click="AddNewLocation" v-if="!addLocation"> + <v-icon>add</v-icon> + </v-btn> + <v-btn flat color="primary" @click="AddNewLocation" v-else>Confirmer</v-btn> + </v-flex> + + <v-flex xs12 sm6> + <v-text-field + v-model="editedItem.position_access_group" + label="Groupe d'accès" + ></v-text-field> + </v-flex> + <v-flex xs12 sm6> + <v-text-field + v-model="editedItem.position_spot_number" + label="Nombre de places" + type="number" + min="0" + ></v-text-field> + </v-flex> + </v-layout> + </v-container> + </v-card-text> + + <v-card-actions> + <v-spacer></v-spacer> + <v-btn color="primary" flat @click="close">Annuler</v-btn> + <v-btn color="green" flat @click="save">Confirmer</v-btn> + </v-card-actions> + </v-card> + </v-dialog> + </v-toolbar> + <v-data-table :headers="headers" :items="$store.state.modulePositions.positions"> + <template v-slot:items="props"> + <td>{{ props.item.job_full_value }}</td> + <td>{{ props.item.location_site }}</td> + <td>{{ props.item.position_access_group }}</td> + <td>{{ props.item.position_spot_number }}</td> + <td> + <v-icon small class="mr-2" @click="editItem(props.item)">edit</v-icon> + <v-icon small @click="deleteItem(props.item)">delete</v-icon> + </td> + </template> + </v-data-table> + </div> + </template> </div> </template> <script> export default { - name: 'openjobs-view' + name: 'openjobs-view', + data() { + return { + dialog: false, + addJob: false, + addLocation: false, + headers: [ + { text: 'Métier', value: 'job_full_value' }, + { text: 'Lieu', value: 'location_site' }, + { text: 'Groupe d\'accès', value: 'position_access_group' }, + { text: 'Nombre de places', value: 'position_spot_number' }, + { text: 'Actions', value: 'actions', sortable: false } + ], + editedIndex: -1, + editedItem: { + job_id: -1, + location_id: -1, + position_access_group: '', + position_spot_number: 0 + }, + defaultItem: { + job_id: -1, + location_id: -1, + position_access_group: '', + position_spot_number: 0 + }, + newJob: { + job_full_value: '', + job_short_value: '' + }, + newLocation: { + location_site: '' + } + } + }, + + computed: { + modalTitle() { + return this.editedIndex === -1 ? 'Nouvelle place' : 'Edition' + } + }, + + watch: { + dialog(val) { + val || this.close() + } + }, + created() { + this.loadData() + }, + methods: { + loadData() { + this.$store.dispatch('modulePositions/getPositions') + this.$store.dispatch('modulePositions/getJobs') + this.$store.dispatch('modulePositions/getLocations') + }, + editItem(item) { + this.editedIndex = item.position_id + this.editedItem = Object.assign({}, item) + this.dialog = true + }, + deleteItem(item) { + if (confirm('Voulez-vous vraiment supprimer cette offre ?')) { + // dispatch delete item.position_id + console.log(item.position_id) + } + }, + close() { + this.dialog = false + setTimeout(() => { + this.editedItem = Object.assign({}, this.defaultItem) + this.editedIndex = -1 + this.addJob = false + this.addLocation = false + }, 300) + }, + save() { + if (this.editedIndex > -1) { + // Edit + this.$store.dispatch('modulePositions/updatePosition', this.editedItem) + } else { + // create + this.$store.dispatch('modulePositions/createPosition', this.editedItem) + } + this.close() + this.loadData() + }, + addNewJob() { + if (this.addJob) { + this.$store.dispatch('modulePositions/createJob', this.newJob).then(response => { + this.$store.dispatch('modulePositions/getJobs') + this.addJob = false + this.editedItem.job_id = response.id + }) + } + this.addJob = true + this.addLocation = false + }, + AddNewLocation() { + if (this.addLocation) { + this.$store.dispatch('modulePositions/createLocation', this.newLocation).then(response => { + this.$store.dispatch('modulePositions/getLocations') + this.addLocation = false + this.editedItem.location_id = response.id + }) + } + this.addLocation = true + this.addJob = false + } + } } </script>