commit
4839d4be2b
44 changed files with 571 additions and 121 deletions
17
README.md
17
README.md
|
@ -34,6 +34,12 @@ Afin d'initialiser l'environnement de développement, exécutez la commande suiv
|
|||
bundle install
|
||||
yarn install
|
||||
|
||||
## Bouchonnage de l’authentification
|
||||
|
||||
Créer les fichiers de configuration avec les valeurs par défaut :
|
||||
|
||||
cp config/france_connect.example.yml config/france_connect.yml
|
||||
cp config/github_secrets.example.yml config/github_secrets.yml
|
||||
|
||||
## Création de la base de données
|
||||
|
||||
|
@ -53,13 +59,6 @@ Afin de générer la BDD de l'application, il est nécessaire d'exécuter les co
|
|||
# Migrate the development database and the test database
|
||||
bin/rails db:migrate
|
||||
|
||||
## Bouchonnage de l’authentification
|
||||
|
||||
Créer les fichiers de configuration avec les valeurs par défaut :
|
||||
|
||||
cp config/france_connect.example.yml config/france_connect.yml
|
||||
cp config/github_secrets.example.yml config/github_secrets.yml
|
||||
|
||||
## Connexion a Pipedrive
|
||||
|
||||
Dans le fichier `config/intializers/token.rb`, ajouter
|
||||
|
@ -70,9 +69,9 @@ Dans le fichier `config/intializers/token.rb`, ajouter
|
|||
|
||||
## Lancement de l'application
|
||||
|
||||
overmind s
|
||||
overmind start
|
||||
|
||||
Un utilisateur de test est disponible, avec les identifiants `test@exemple.fr`/`testpassword`.
|
||||
L'application tourne à l'adresse `http://localhost:3000`. Un utilisateur de test est disponible, avec les identifiants `test@exemple.fr`/`testpassword`.
|
||||
|
||||
## Programmation des jobs
|
||||
|
||||
|
|
1
app/assets/images/icons/frown-regular.svg
Normal file
1
app/assets/images/icons/frown-regular.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z" fill="#dc3832"/></svg>
|
After Width: | Height: | Size: 613 B |
1
app/assets/images/icons/meh-regular.svg
Normal file
1
app/assets/images/icons/meh-regular.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z" fill="#f9b916"/></svg>
|
After Width: | Height: | Size: 479 B |
1
app/assets/images/icons/smile-regular.svg
Normal file
1
app/assets/images/icons/smile-regular.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z" fill="#4daa75"/></svg>
|
After Width: | Height: | Size: 604 B |
|
@ -1,9 +1,10 @@
|
|||
$(document).on('turbolinks:load', link_init);
|
||||
|
||||
function link_init() {
|
||||
$('#dossiers-list tr').on('click', function (event) {
|
||||
if (event.target.className !== 'btn-sm btn-danger') {
|
||||
$(location).attr('href', $(this).data('dossier_url'));
|
||||
$('#dossiers-list tr').on('click', function(event) {
|
||||
var href = $(this).data('href');
|
||||
if (href && event.target.tagName !== 'A') {
|
||||
location.href = href;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
15
app/assets/stylesheets/new_design/dossier_index.scss
Normal file
15
app/assets/stylesheets/new_design/dossier_index.scss
Normal file
|
@ -0,0 +1,15 @@
|
|||
@import "colors";
|
||||
@import "constants";
|
||||
|
||||
#user-satisfaction {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
|
||||
.icon {
|
||||
padding: 10px 5px;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -89,4 +89,16 @@
|
|||
background-image: image-url("icons/info-blue.svg");
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
&.smile {
|
||||
background-image: image-url("icons/smile-regular.svg");
|
||||
}
|
||||
|
||||
&.frown {
|
||||
background-image: image-url("icons/frown-regular.svg");
|
||||
}
|
||||
|
||||
&.meh {
|
||||
background-image: image-url("icons/meh-regular.svg");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,38 +75,37 @@ class ApplicationController < ActionController::Base
|
|||
].compact
|
||||
end
|
||||
|
||||
def logged_user
|
||||
logged_users.first
|
||||
end
|
||||
|
||||
def logged_user_roles
|
||||
roles = logged_users.map { |logged_user| logged_user.class.name }
|
||||
roles.any? ? roles.join(', ') : 'Guest'
|
||||
end
|
||||
|
||||
def logged_user_info
|
||||
logged_user = logged_users.first
|
||||
|
||||
if logged_user
|
||||
{
|
||||
id: logged_user.id,
|
||||
email: logged_user.email
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def set_raven_context
|
||||
user = logged_user
|
||||
|
||||
context = {
|
||||
ip_address: request.ip,
|
||||
id: user&.id,
|
||||
email: user&.email,
|
||||
roles: logged_user_roles
|
||||
}
|
||||
context.merge!(logged_user_info || {})
|
||||
}.compact
|
||||
|
||||
Raven.user_context(context)
|
||||
end
|
||||
|
||||
def append_info_to_payload(payload)
|
||||
payload.merge!({
|
||||
def session_info_payload
|
||||
user = logged_user
|
||||
|
||||
payload = {
|
||||
user_agent: request.user_agent,
|
||||
current_user: logged_user_info,
|
||||
current_user_id: user&.id,
|
||||
current_user_email: user&.email,
|
||||
current_user_roles: logged_user_roles
|
||||
}.compact)
|
||||
}.compact
|
||||
|
||||
if browser.known?
|
||||
payload.merge!({
|
||||
|
@ -115,6 +114,8 @@ class ApplicationController < ActionController::Base
|
|||
platform: browser.platform.name,
|
||||
})
|
||||
end
|
||||
|
||||
payload
|
||||
end
|
||||
|
||||
def reject
|
||||
|
|
|
@ -96,7 +96,6 @@ module NewGestionnaire
|
|||
sign_in(gestionnaire, scope: :gestionnaire)
|
||||
|
||||
Avis.link_avis_to_gestionnaire(gestionnaire)
|
||||
avis = Avis.find(params[:id])
|
||||
redirect_to url_for(gestionnaire_avis_index_path)
|
||||
else
|
||||
flash[:alert] = gestionnaire.errors.full_messages
|
||||
|
|
|
@ -4,8 +4,8 @@ module NewUser
|
|||
|
||||
helper_method :new_demarche_url
|
||||
|
||||
before_action :ensure_ownership!, except: [:index, :modifier, :update, :recherche]
|
||||
before_action :ensure_ownership_or_invitation!, only: [:modifier, :update]
|
||||
before_action :ensure_ownership!, except: [:index, :show, :modifier, :update, :recherche]
|
||||
before_action :ensure_ownership_or_invitation!, only: [:show, :modifier, :update]
|
||||
before_action :ensure_dossier_can_be_updated, only: [:update_identite, :update]
|
||||
before_action :forbid_invite_submission!, only: [:update]
|
||||
|
||||
|
@ -23,6 +23,17 @@ module NewUser
|
|||
end
|
||||
end
|
||||
|
||||
def show
|
||||
if dossier.brouillon?
|
||||
redirect_to modifier_dossier_path(dossier)
|
||||
|
||||
elsif !Flipflop.new_dossier_details?
|
||||
redirect_to users_dossier_recapitulatif_path(dossier)
|
||||
end
|
||||
|
||||
@dossier = dossier
|
||||
end
|
||||
|
||||
def attestation
|
||||
send_data(dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf')
|
||||
end
|
||||
|
@ -209,7 +220,7 @@ module NewUser
|
|||
end
|
||||
|
||||
def draft?
|
||||
params[:submit_action] == 'draft'
|
||||
params[:save_draft]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
6
app/controllers/new_user/feedbacks_controller.rb
Normal file
6
app/controllers/new_user/feedbacks_controller.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class NewUser::FeedbacksController < ApplicationController
|
||||
def create
|
||||
current_user.feedbacks.create!(mark: params[:mark])
|
||||
flash.notice = "Merci de votre retour"
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
import Turbolinks from 'turbolinks';
|
||||
import Rails from 'rails-ujs';
|
||||
import * as ActiveStorage from 'activestorage';
|
||||
import ActiveStorage from '../shared/activestorage/ujs';
|
||||
import Chartkick from 'chartkick';
|
||||
import Highcharts from 'highcharts';
|
||||
import Bloodhound from 'bloodhound-js';
|
||||
|
@ -14,7 +14,6 @@ import 'babel-polyfill';
|
|||
import 'typeahead.js';
|
||||
|
||||
import '../shared/rails-ujs-fix';
|
||||
import '../shared/direct-uploads';
|
||||
|
||||
// Start Rails helpers
|
||||
Chartkick.addAdapter(Highcharts);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Turbolinks from 'turbolinks';
|
||||
import Rails from 'rails-ujs';
|
||||
import * as ActiveStorage from 'activestorage';
|
||||
|
||||
import ActiveStorage from '../shared/activestorage/ujs';
|
||||
import Chartkick from 'chartkick';
|
||||
import Highcharts from 'highcharts';
|
||||
import jQuery from 'jquery';
|
||||
|
@ -15,7 +14,6 @@ import 'select2';
|
|||
import 'typeahead.js';
|
||||
|
||||
import '../shared/rails-ujs-fix';
|
||||
import '../shared/direct-uploads';
|
||||
|
||||
import '../new_design/buttons';
|
||||
import '../new_design/form-validation';
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
// Include runtime-polyfills for older browsers.
|
||||
// Due to .babelrc's 'useBuiltIns', only polyfills actually
|
||||
// required by the browsers we support will be included.
|
||||
import 'babel-polyfill';
|
||||
|
||||
// This file is copied from mailjet. We serve here a copy of it ourselves
|
||||
// to avoid loading javascript files from other domains on the frontpage.
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
import { DirectUpload } from 'activestorage';
|
||||
import { dispatchEvent } from './helpers';
|
||||
|
||||
export class DirectUploadController {
|
||||
constructor(input, file) {
|
||||
this.input = input;
|
||||
this.file = file;
|
||||
this.directUpload = new DirectUpload(this.file, this.url, this);
|
||||
this.dispatch('initialize');
|
||||
}
|
||||
|
||||
start(callback) {
|
||||
const hiddenInput = document.createElement('input');
|
||||
hiddenInput.type = 'hidden';
|
||||
hiddenInput.name = this.input.name;
|
||||
this.input.insertAdjacentElement('beforebegin', hiddenInput);
|
||||
|
||||
this.dispatch('start');
|
||||
|
||||
this.directUpload.create((error, attributes) => {
|
||||
if (error) {
|
||||
hiddenInput.parentNode.removeChild(hiddenInput);
|
||||
this.dispatchError(error);
|
||||
} else {
|
||||
hiddenInput.value = attributes.signed_id;
|
||||
}
|
||||
|
||||
this.dispatch('end');
|
||||
callback(error);
|
||||
});
|
||||
}
|
||||
|
||||
uploadRequestDidProgress(event) {
|
||||
const progress = (event.loaded / event.total) * 100;
|
||||
if (progress) {
|
||||
this.dispatch('progress', { progress });
|
||||
}
|
||||
}
|
||||
|
||||
get url() {
|
||||
return this.input.getAttribute('data-direct-upload-url');
|
||||
}
|
||||
|
||||
dispatch(name, detail = {}) {
|
||||
detail.file = this.file;
|
||||
detail.id = this.directUpload.id;
|
||||
return dispatchEvent(this.input, `direct-upload:${name}`, { detail });
|
||||
}
|
||||
|
||||
dispatchError(error) {
|
||||
const event = this.dispatch('error', { error });
|
||||
if (!event.defaultPrevented) {
|
||||
alert(error);
|
||||
}
|
||||
}
|
||||
|
||||
// DirectUpload delegate
|
||||
|
||||
directUploadWillCreateBlobWithXHR(xhr) {
|
||||
this.dispatch('before-blob-request', { xhr });
|
||||
}
|
||||
|
||||
directUploadWillStoreFileWithXHR(xhr) {
|
||||
this.dispatch('before-storage-request', { xhr });
|
||||
xhr.upload.addEventListener('progress', event =>
|
||||
this.uploadRequestDidProgress(event)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
import { DirectUploadController } from './direct_upload_controller';
|
||||
import { findElements, dispatchEvent, toArray } from './helpers';
|
||||
|
||||
const inputSelector =
|
||||
'input[type=file][data-direct-upload-url]:not([disabled])';
|
||||
|
||||
export class DirectUploadsController {
|
||||
constructor(form) {
|
||||
this.form = form;
|
||||
this.inputs = findElements(form, inputSelector).filter(
|
||||
input => input.files.length
|
||||
);
|
||||
}
|
||||
|
||||
start(callback) {
|
||||
const controllers = this.createDirectUploadControllers();
|
||||
|
||||
const startNextController = () => {
|
||||
const controller = controllers.shift();
|
||||
if (controller) {
|
||||
controller.start(error => {
|
||||
if (error) {
|
||||
callback(error);
|
||||
this.dispatch('end');
|
||||
} else {
|
||||
startNextController();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
this.dispatch('end');
|
||||
}
|
||||
};
|
||||
|
||||
this.dispatch('start');
|
||||
startNextController();
|
||||
}
|
||||
|
||||
createDirectUploadControllers() {
|
||||
const controllers = [];
|
||||
this.inputs.forEach(input => {
|
||||
toArray(input.files).forEach(file => {
|
||||
const controller = new DirectUploadController(input, file);
|
||||
controllers.push(controller);
|
||||
});
|
||||
});
|
||||
return controllers;
|
||||
}
|
||||
|
||||
dispatch(name, detail = {}) {
|
||||
return dispatchEvent(this.form, `direct-uploads:${name}`, { detail });
|
||||
}
|
||||
}
|
51
app/javascript/shared/activestorage/helpers.js
Normal file
51
app/javascript/shared/activestorage/helpers.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
export function getMetaValue(name) {
|
||||
const element = findElement(document.head, `meta[name="${name}"]`);
|
||||
if (element) {
|
||||
return element.getAttribute('content');
|
||||
}
|
||||
}
|
||||
|
||||
export function findElements(root, selector) {
|
||||
if (typeof root == 'string') {
|
||||
selector = root;
|
||||
root = document;
|
||||
}
|
||||
const elements = root.querySelectorAll(selector);
|
||||
return toArray(elements);
|
||||
}
|
||||
|
||||
export function findElement(root, selector) {
|
||||
if (typeof root == 'string') {
|
||||
selector = root;
|
||||
root = document;
|
||||
}
|
||||
return root.querySelector(selector);
|
||||
}
|
||||
|
||||
export function dispatchEvent(element, type, eventInit = {}) {
|
||||
const { disabled } = element;
|
||||
const { bubbles, cancelable, detail } = eventInit;
|
||||
const event = document.createEvent('Event');
|
||||
|
||||
event.initEvent(type, bubbles || true, cancelable || true);
|
||||
event.detail = detail || {};
|
||||
|
||||
try {
|
||||
element.disabled = false;
|
||||
element.dispatchEvent(event);
|
||||
} finally {
|
||||
element.disabled = disabled;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
export function toArray(value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value;
|
||||
} else if (Array.from) {
|
||||
return Array.from(value);
|
||||
} else {
|
||||
return [].slice.call(value);
|
||||
}
|
||||
}
|
|
@ -47,30 +47,3 @@ addEventListener('direct-upload:end', event => {
|
|||
|
||||
element.classList.add('direct-upload--complete');
|
||||
});
|
||||
|
||||
addEventListener('turbolinks:load', () => {
|
||||
const submitButtons = document.querySelectorAll(
|
||||
'form button[type=submit][data-action]'
|
||||
);
|
||||
const hiddenInput = document.querySelector(
|
||||
'form input[type=hidden][name=submit_action]'
|
||||
);
|
||||
|
||||
for (let button of submitButtons) {
|
||||
button.addEventListener('click', () => {
|
||||
// Active Storage will intercept the form.submit event to upload
|
||||
// the attached files, and then fire the submit action again – but forgetting
|
||||
// which button was clicked. So we manually set the type of action that trigerred
|
||||
// the form submission.
|
||||
const action = button.getAttribute('data-action');
|
||||
hiddenInput.value = action;
|
||||
// Some form fields are marked as mandatory, but when saving a draft we don't want them
|
||||
// to be enforced by the browser.
|
||||
if (action === 'submit') {
|
||||
button.form.removeAttribute('novalidate');
|
||||
} else {
|
||||
button.form.setAttribute('novalidate', 'novalidate');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
105
app/javascript/shared/activestorage/ujs.js
Normal file
105
app/javascript/shared/activestorage/ujs.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
import { DirectUploadsController } from './direct_uploads_controller';
|
||||
import { findElement } from './helpers';
|
||||
import './progress';
|
||||
|
||||
// This is a patched copy of https://github.com/rails/rails/blob/master/activestorage/app/javascript/activestorage/ujs.js
|
||||
// It fixes support for multiple input/button elements on direct upload forms
|
||||
|
||||
const processingAttribute = 'data-direct-uploads-processing';
|
||||
let started = false;
|
||||
|
||||
export function start() {
|
||||
if (!started) {
|
||||
started = true;
|
||||
document.addEventListener('submit', didSubmitForm);
|
||||
document.addEventListener('click', didSubmitFormElement);
|
||||
document.addEventListener('ajax:before', didSubmitRemoteElement);
|
||||
}
|
||||
}
|
||||
|
||||
export default { start };
|
||||
|
||||
function didSubmitForm(event) {
|
||||
handleFormSubmissionEvent(event);
|
||||
}
|
||||
|
||||
function didSubmitFormElement(event) {
|
||||
const { target } = event;
|
||||
if (isSubmitElement(target)) {
|
||||
handleFormSubmissionEvent(formSubmitEvent(event), target);
|
||||
}
|
||||
}
|
||||
|
||||
function didSubmitRemoteElement(event) {
|
||||
if (event.target.tagName == 'FORM') {
|
||||
handleFormSubmissionEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
function formSubmitEvent(event) {
|
||||
return {
|
||||
target: event.target.form,
|
||||
preventDefault() {
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function isSubmitElement({ tagName, type, form }) {
|
||||
if (form && (tagName === 'BUTTON' || tagName === 'INPUT')) {
|
||||
return type === 'submit';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleFormSubmissionEvent(event, button) {
|
||||
const form = event.target;
|
||||
|
||||
if (form.hasAttribute(processingAttribute)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
const controller = new DirectUploadsController(form);
|
||||
const { inputs } = controller;
|
||||
|
||||
if (inputs.length) {
|
||||
event.preventDefault();
|
||||
form.setAttribute(processingAttribute, '');
|
||||
inputs.forEach(disable);
|
||||
controller.start(error => {
|
||||
form.removeAttribute(processingAttribute);
|
||||
if (error) {
|
||||
inputs.forEach(enable);
|
||||
} else {
|
||||
submitForm(form, button);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function submitForm(form, button) {
|
||||
button = button || findElement(form, 'input[type=submit]');
|
||||
if (button) {
|
||||
const { disabled } = button;
|
||||
button.disabled = false;
|
||||
button.focus();
|
||||
button.click();
|
||||
button.disabled = disabled;
|
||||
} else {
|
||||
button = document.createElement('input');
|
||||
button.type = 'submit';
|
||||
button.style.display = 'none';
|
||||
form.appendChild(button);
|
||||
button.click();
|
||||
form.removeChild(button);
|
||||
}
|
||||
}
|
||||
|
||||
function disable(input) {
|
||||
input.disabled = true;
|
||||
}
|
||||
|
||||
function enable(input) {
|
||||
input.disabled = false;
|
||||
}
|
3
app/models/feedback.rb
Normal file
3
app/models/feedback.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Feedback < ApplicationRecord
|
||||
belongs_to :user
|
||||
end
|
|
@ -16,6 +16,7 @@ class User < ApplicationRecord
|
|||
has_many :invites, dependent: :destroy
|
||||
has_many :dossiers_invites, through: :invites, source: :dossier
|
||||
has_many :piece_justificative, dependent: :destroy
|
||||
has_many :feedbacks, dependent: :destroy
|
||||
has_one :france_connect_information, dependent: :destroy
|
||||
|
||||
delegate :given_name, :family_name, :email_france_connect, :gender, :birthdate, :birthplace, :france_connect_particulier_id, to: :france_connect_information
|
||||
|
|
|
@ -13,22 +13,20 @@
|
|||
|
||||
- @procedures.each do |procedure|
|
||||
- procedure = procedure.decorate
|
||||
%tr{ id: "tr_dossier_#{procedure.id}", 'data-dossier_url' => admin_procedure_path(id: procedure.id) }
|
||||
%td= procedure.id
|
||||
%td.col-xs-6
|
||||
= procedure.libelle
|
||||
- if @active_class
|
||||
%td.procedure-lien= link_to procedure.lien, procedure.lien, 'data-method' => :get
|
||||
- if @active_class || @archived_class
|
||||
%td
|
||||
= procedure.published_at_fr
|
||||
- admin_procedure_href = admin_procedure_path(procedure)
|
||||
%tr{ id: "tr_dossier_#{procedure.id}", data: { href: admin_procedure_href } }
|
||||
%td= link_to(procedure.id, admin_procedure_href)
|
||||
%td.col-xs-6= link_to(procedure.libelle, admin_procedure_href)
|
||||
- if procedure.publiee?
|
||||
%td.procedure-lien= link_to(procedure.lien, procedure.lien)
|
||||
- if procedure.publiee_ou_archivee?
|
||||
%td= link_to(procedure.published_at_fr, admin_procedure_href)
|
||||
- else
|
||||
%td= link_to(procedure.created_at_fr, admin_procedure_href)
|
||||
%td
|
||||
= procedure.created_at_fr
|
||||
%td
|
||||
= link_to('Cloner', admin_procedure_clone_path(procedure.id), 'data-method' => :put, class: 'btn-sm btn-primary clone-btn')
|
||||
= link_to('Cloner', admin_procedure_clone_path(procedure.id), data: { method: :put }, class: 'btn-sm btn-primary clone-btn')
|
||||
- if !procedure.publiee_ou_archivee?
|
||||
= link_to('X', url_for(controller: 'admin/procedures', action: :destroy, id: procedure.id), 'data-method' => :delete, class: 'btn-sm btn-danger')
|
||||
= link_to('X', url_for(controller: 'admin/procedures', action: :destroy, id: procedure.id), data: { method: :delete }, class: 'btn-sm btn-danger')
|
||||
|
||||
= smart_listing.paginate
|
||||
= smart_listing.pagination_per_page_links
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
- if @avis.gestionnaire.present?
|
||||
%p
|
||||
= link_to "Connectez-vous pour donner votre avis", gestionnaire_dossier_url(@avis.dossier.procedure, @avis.dossier)
|
||||
= link_to "Connectez-vous pour donner votre avis", gestionnaire_avis_url(@avis)
|
||||
- else
|
||||
%p
|
||||
= link_to "Inscrivez-vous pour donner votre avis", sign_up_gestionnaire_avis_url(@avis.id, @avis.email)
|
||||
|
|
|
@ -15,6 +15,17 @@
|
|||
= link_to(dossiers_path(current_tab: 'dossiers-invites')) do
|
||||
dossiers invités
|
||||
|
||||
- if current_user.feedbacks.empty?
|
||||
.container#user-satisfaction
|
||||
%h3 Que pensez-vous de ce service ?
|
||||
.icons
|
||||
= link_to feedback_path(mark: 0), data: { remote: true, method: :post } do
|
||||
%span.icon.frown
|
||||
= link_to feedback_path(mark: 1), data: { remote: true, method: :post } do
|
||||
%span.icon.meh
|
||||
= link_to feedback_path(mark: 2), data: { remote: true, method: :post } do
|
||||
%span.icon.smile
|
||||
|
||||
.container
|
||||
- if @dossiers.present?
|
||||
- if @dossiers.total_pages >= 2
|
||||
|
|
3
app/views/new_user/dossiers/show.html.haml
Normal file
3
app/views/new_user/dossiers/show.html.haml
Normal file
|
@ -0,0 +1,3 @@
|
|||
%h1
|
||||
Dossier
|
||||
= @dossier.id
|
4
app/views/new_user/feedbacks/create.js.erb
Normal file
4
app/views/new_user/feedbacks/create.js.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
document.querySelector('#user-satisfaction').innerHTML = '';
|
||||
var flashMessagesView = "<%= escape_javascript(render partial: 'layouts/flash_messages') %>";
|
||||
document.querySelector("#flash_messages").outerHTML = flashMessagesView;
|
||||
<% flash.clear %>
|
|
@ -5,7 +5,7 @@
|
|||
Vous pouvez retrouver et compléter le brouillon que vous avez créé pour la démarche
|
||||
%strong= @dossier.procedure.libelle
|
||||
à l'adresse suivante :
|
||||
= link_to users_dossiers_url(liste: 'brouillon'), users_dossiers_url(liste: 'brouillon'), target: '_blank'
|
||||
= link_to dossier_url(@dossier), dossier_url(@dossier), target: '_blank'
|
||||
|
||||
%p
|
||||
Bonne journée,
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
%span.icon.search
|
||||
%span.icon.sign-out
|
||||
%span.icon.info
|
||||
%span.icon.frown
|
||||
%span.icon.meh
|
||||
%span.icon.smile
|
||||
|
||||
%h1 Formulaires
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
- if apercu
|
||||
- form_options = { url: '', method: :get, html: { class: 'form', multipart: true } }
|
||||
- else
|
||||
- form_options = { url: modifier_dossier_url(dossier), method: :patch, html: { class: 'form', multipart: true, novalidate: dossier.brouillon? } }
|
||||
- form_options = { url: modifier_dossier_url(dossier), method: :patch, html: { class: 'form', multipart: true } }
|
||||
|
||||
= form_for dossier, form_options do |f|
|
||||
|
||||
|
@ -59,31 +59,31 @@
|
|||
|
||||
- if !apercu
|
||||
.send-wrapper
|
||||
= hidden_field_tag 'submit_action', 'draft'
|
||||
|
||||
- if dossier.brouillon?
|
||||
- if current_user.owns?(dossier)
|
||||
= link_to ask_deletion_dossier_path(dossier),
|
||||
method: :post,
|
||||
class: 'button danger',
|
||||
data: { confirm: "En continuant, vous allez supprimer ce dossier ainsi que les informations qu’il contient. Toute suppression entraine l’annulation de la démarche en cours.\n\nConfirmer la suppression ?" } do
|
||||
data: { disable_with: 'Supprimer le brouillon', confirm: 'En continuant, vous allez supprimer ce dossier ainsi que les informations qu’il contient. Toute suppression entraine l’annulation de la démarche en cours.\n\nConfirmer la suppression ?' } do
|
||||
Supprimer le brouillon
|
||||
|
||||
= f.button 'Enregistrer le brouillon',
|
||||
formnovalidate: true,
|
||||
name: :save_draft,
|
||||
value: true,
|
||||
class: 'button send secondary',
|
||||
data: { action: 'draft', disable_with: 'Envoi...' }
|
||||
data: { disable_with: 'Enregistrer le brouillon' }
|
||||
|
||||
- if dossier.can_transition_to_en_construction?
|
||||
= f.button 'Soumettre le dossier',
|
||||
class: 'button send primary',
|
||||
disabled: !current_user.owns?(dossier),
|
||||
data: { action: 'submit', disable_with: 'Envoi...' }
|
||||
data: { disable_with: 'Soumettre le dossier' }
|
||||
|
||||
- else
|
||||
= f.button 'Enregistrer les modifications du dossier',
|
||||
class: 'button send primary',
|
||||
data: { action: 'submit', disable_with: 'Envoi...' }
|
||||
data: { disable_with: 'Enregistrer les modifications du dossier' }
|
||||
|
||||
- if dossier.brouillon? && !current_user.owns?(dossier)
|
||||
.send-notice.invite-cannot-submit
|
||||
|
|
|
@ -17,6 +17,9 @@ Flipflop.configure do
|
|||
|
||||
feature :web_hook
|
||||
|
||||
feature :new_dossier_details,
|
||||
title: "Nouvelle page « Dossier »"
|
||||
|
||||
group :production do
|
||||
feature :remote_storage,
|
||||
default: Rails.env.production? || Rails.env.staging?
|
||||
|
|
|
@ -3,17 +3,7 @@ if LogStasher.enabled
|
|||
fields[:type] = "tps"
|
||||
end
|
||||
|
||||
LogStasher.watch('process_action.action_controller') do |name, start, finish, id, payload, store|
|
||||
store[:user_agent] = payload[:user_agent]
|
||||
store[:browser] = payload[:browser]
|
||||
store[:browser_version] = payload[:browser_version]
|
||||
store[:platform] = payload[:platform]
|
||||
|
||||
store[:current_user_roles] = payload[:current_user_roles]
|
||||
|
||||
if payload[:current_user].present?
|
||||
store[:current_user_id] = payload[:current_user][:id]
|
||||
store[:current_user_email] = payload[:current_user][:email]
|
||||
end
|
||||
LogStasher.add_custom_fields_to_request_context do |fields|
|
||||
fields.merge!(session_info_payload)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ fr:
|
|||
date: 'Date'
|
||||
datetime: 'Date et Heure'
|
||||
number: 'Nombre'
|
||||
checkbox: 'Checkbox'
|
||||
checkbox: 'Case à cocher'
|
||||
civilite: 'Civilité'
|
||||
email: 'Email'
|
||||
phone: 'Téléphone'
|
||||
|
|
11
config/logstasher.yml
Normal file
11
config/logstasher.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
backtrace: true
|
||||
suppress_app_log: false
|
||||
log_controller_parameters: false
|
||||
development:
|
||||
enabled: false
|
||||
test:
|
||||
enabled: false
|
||||
staging:
|
||||
enabled: false
|
||||
production:
|
||||
enabled: true
|
|
@ -267,7 +267,7 @@ Rails.application.routes.draw do
|
|||
#
|
||||
|
||||
scope module: 'new_user' do
|
||||
resources :dossiers, only: [:index, :update] do
|
||||
resources :dossiers, only: [:index, :show, :update] do
|
||||
member do
|
||||
get 'identite'
|
||||
patch 'update_identite'
|
||||
|
@ -282,6 +282,7 @@ Rails.application.routes.draw do
|
|||
post 'recherche'
|
||||
end
|
||||
end
|
||||
resource :feedback, only: [:create]
|
||||
end
|
||||
|
||||
#
|
||||
|
|
10
db/migrate/20180808142237_create_feedbacks.rb
Normal file
10
db/migrate/20180808142237_create_feedbacks.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class CreateFeedbacks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :feedbacks do |t|
|
||||
t.references :user, foreign_key: true
|
||||
t.integer :mark
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
11
db/schema.rb
11
db/schema.rb
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2018_07_24_153247) do
|
||||
ActiveRecord::Schema.define(version: 2018_08_08_142237) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -328,6 +328,14 @@ ActiveRecord::Schema.define(version: 2018_07_24_153247) do
|
|||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "feedbacks", force: :cascade do |t|
|
||||
t.bigint "user_id"
|
||||
t.integer "mark"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["user_id"], name: "index_feedbacks_on_user_id"
|
||||
end
|
||||
|
||||
create_table "flipflop_features", force: :cascade do |t|
|
||||
t.string "key", null: false
|
||||
t.boolean "enabled", default: false, null: false
|
||||
|
@ -625,6 +633,7 @@ ActiveRecord::Schema.define(version: 2018_07_24_153247) do
|
|||
add_foreign_key "closed_mails", "procedures"
|
||||
add_foreign_key "commentaires", "dossiers"
|
||||
add_foreign_key "dossiers", "users"
|
||||
add_foreign_key "feedbacks", "users"
|
||||
add_foreign_key "initiated_mails", "procedures"
|
||||
add_foreign_key "procedure_paths", "administrateurs"
|
||||
add_foreign_key "procedure_paths", "procedures"
|
||||
|
|
|
@ -17,7 +17,7 @@ describe ApplicationController, type: :controller do
|
|||
let(:current_gestionnaire) { nil }
|
||||
let(:current_administrateur) { nil }
|
||||
let(:current_administration) { nil }
|
||||
let(:payload) { {} }
|
||||
let(:payload) { @controller.send(:session_info_payload) }
|
||||
|
||||
before do
|
||||
expect(@controller).to receive(:current_user).and_return(current_user)
|
||||
|
@ -27,7 +27,6 @@ describe ApplicationController, type: :controller do
|
|||
allow(Raven).to receive(:user_context)
|
||||
|
||||
@controller.send(:set_raven_context)
|
||||
@controller.send(:append_info_to_payload, payload)
|
||||
end
|
||||
|
||||
context 'when no one is logged in' do
|
||||
|
@ -50,10 +49,8 @@ describe ApplicationController, type: :controller do
|
|||
it do
|
||||
expect(payload).to eq({
|
||||
user_agent: 'Rails Testing',
|
||||
current_user: {
|
||||
id: current_user.id,
|
||||
email: current_user.email
|
||||
},
|
||||
current_user_id: current_user.id,
|
||||
current_user_email: current_user.email,
|
||||
current_user_roles: 'User'
|
||||
})
|
||||
end
|
||||
|
@ -73,10 +70,8 @@ describe ApplicationController, type: :controller do
|
|||
it do
|
||||
expect(payload).to eq({
|
||||
user_agent: 'Rails Testing',
|
||||
current_user: {
|
||||
id: current_user.id,
|
||||
email: current_user.email
|
||||
},
|
||||
current_user_id: current_user.id,
|
||||
current_user_email: current_user.email,
|
||||
current_user_roles: 'User, Gestionnaire, Administrateur, Administration'
|
||||
})
|
||||
end
|
||||
|
|
|
@ -100,38 +100,38 @@ describe NewUser::DossiersController, type: :controller do
|
|||
let(:user) { create(:user) }
|
||||
let(:asked_dossier) { create(:dossier) }
|
||||
let(:ensure_authorized) { :forbid_invite_submission! }
|
||||
let(:submit_action) { 'submit' }
|
||||
let(:draft) { false }
|
||||
|
||||
before do
|
||||
@controller.params = @controller.params.merge(dossier_id: asked_dossier.id, submit_action: submit_action)
|
||||
@controller.params = @controller.params.merge(dossier_id: asked_dossier.id, save_draft: draft)
|
||||
allow(@controller).to receive(:current_user).and_return(user)
|
||||
allow(@controller).to receive(:redirect_to)
|
||||
end
|
||||
|
||||
context 'when a user save their own draft' do
|
||||
let(:asked_dossier) { create(:dossier, user: user) }
|
||||
let(:submit_action) { 'draft' }
|
||||
let(:draft) { true }
|
||||
|
||||
it_behaves_like 'does not redirect nor flash'
|
||||
end
|
||||
|
||||
context 'when a user submit their own dossier' do
|
||||
let(:asked_dossier) { create(:dossier, user: user) }
|
||||
let(:submit_action) { 'submit' }
|
||||
let(:draft) { false }
|
||||
|
||||
it_behaves_like 'does not redirect nor flash'
|
||||
end
|
||||
|
||||
context 'when an invite save the draft for a dossier where they where invited' do
|
||||
before { create(:invite, dossier: asked_dossier, user: user, type: 'InviteUser') }
|
||||
let(:submit_action) { 'draft' }
|
||||
let(:draft) { true }
|
||||
|
||||
it_behaves_like 'does not redirect nor flash'
|
||||
end
|
||||
|
||||
context 'when an invite submit a dossier where they where invited' do
|
||||
before { create(:invite, dossier: asked_dossier, user: user, type: 'InviteUser') }
|
||||
let(:submit_action) { 'submit' }
|
||||
let(:draft) { false }
|
||||
|
||||
it_behaves_like 'redirects and flashes'
|
||||
end
|
||||
|
@ -353,7 +353,7 @@ describe NewUser::DossiersController, type: :controller do
|
|||
it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) }
|
||||
|
||||
context 'and the user saves a draft' do
|
||||
let(:payload) { submit_payload.merge(submit_action: 'draft') }
|
||||
let(:payload) { submit_payload.merge(save_draft: true) }
|
||||
|
||||
it { expect(response).to render_template(:modifier) }
|
||||
it { expect(flash.notice).to eq('Votre brouillon a bien été sauvegardé.') }
|
||||
|
@ -376,7 +376,7 @@ describe NewUser::DossiersController, type: :controller do
|
|||
let!(:invite) { create(:invite, dossier: dossier, user: user, type: 'InviteUser') }
|
||||
|
||||
context 'and the invite saves a draft' do
|
||||
let(:payload) { submit_payload.merge(submit_action: 'draft') }
|
||||
let(:payload) { submit_payload.merge(save_draft: true) }
|
||||
|
||||
before do
|
||||
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
|
||||
|
@ -478,6 +478,37 @@ describe NewUser::DossiersController, type: :controller do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#show' do
|
||||
let(:new_dossier_details_enabled) { false }
|
||||
|
||||
before do
|
||||
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, new_dossier_details_enabled)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
subject! { get(:show, params: { id: dossier.id }) }
|
||||
|
||||
context 'when the dossier is a brouillon' do
|
||||
let(:dossier) { create(:dossier, user: user) }
|
||||
it { is_expected.to redirect_to(modifier_dossier_path(dossier)) }
|
||||
end
|
||||
|
||||
context 'when the dossier has been submitted' do
|
||||
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
||||
|
||||
context 'and the new dossier details page is disabled' do
|
||||
let(:new_dossier_details_enabled) { false }
|
||||
it { is_expected.to redirect_to(users_dossier_recapitulatif_path(dossier)) }
|
||||
end
|
||||
|
||||
context 'and the new dossier details page is enabled' do
|
||||
let(:new_dossier_details_enabled) { true }
|
||||
it { expect(assigns(:dossier)).to eq(dossier) }
|
||||
it { is_expected.to render_template(:show) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#ask_deletion' do
|
||||
before { sign_in(user) }
|
||||
|
||||
|
|
5
spec/factories/feedback.rb
Normal file
5
spec/factories/feedback.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
FactoryBot.define do
|
||||
factory :feedback do
|
||||
mark 3
|
||||
end
|
||||
end
|
28
spec/features/new_user/dossier_details_spec.rb
Normal file
28
spec/features/new_user/dossier_details_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
describe 'Dossier details:' do
|
||||
let(:user) { create(:user) }
|
||||
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
||||
|
||||
before do
|
||||
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, true)
|
||||
end
|
||||
|
||||
scenario 'the user can see the details of their dossier' do
|
||||
visit_dossier dossier
|
||||
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
expect(page).to have_content(dossier.id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def visit_dossier(dossier)
|
||||
visit dossier_path(dossier)
|
||||
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
fill_in 'user_email', with: user.email
|
||||
fill_in 'user_password', with: user.password
|
||||
click_on 'Se connecter'
|
||||
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
end
|
||||
end
|
|
@ -9,5 +9,15 @@ RSpec.describe AvisMailer, type: :mailer do
|
|||
it { expect(subject.subject).to eq("Donnez votre avis sur le dossier nº #{avis.dossier.id} (#{avis.dossier.procedure.libelle})") }
|
||||
it { expect(subject.body).to include("Vous avez été invité par #{avis.claimant.email} à donner votre avis sur le dossier nº #{avis.dossier.id} de la procédure "#{avis.dossier.procedure.libelle}".") }
|
||||
it { expect(subject.body).to include(avis.introduction) }
|
||||
it { expect(subject.body).to include(gestionnaire_avis_url(avis)) }
|
||||
|
||||
context 'when the recipient is not already registered' do
|
||||
before do
|
||||
avis.email = 'accompagnateur@email.com'
|
||||
avis.gestionnaire = nil
|
||||
end
|
||||
|
||||
it { expect(subject.body).to include(sign_up_gestionnaire_avis_url(avis.id, avis.email)) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -556,6 +556,8 @@ describe Dossier do
|
|||
end
|
||||
|
||||
describe "#send_draft_notification_email" do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
|
@ -564,15 +566,17 @@ describe Dossier do
|
|||
end
|
||||
|
||||
it "send an email when the dossier is created for the very first time" do
|
||||
dossier = nil
|
||||
ActiveJob::Base.queue_adapter = :test
|
||||
expect do
|
||||
perform_enqueued_jobs do
|
||||
Dossier.create(procedure: procedure, state: "brouillon", user: user)
|
||||
dossier = Dossier.create(procedure: procedure, state: "brouillon", user: user)
|
||||
end
|
||||
end.to change(ActionMailer::Base.deliveries, :size).from(0).to(1)
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.subject).to eq("Retrouvez votre brouillon pour la démarche \"#{procedure.libelle}\"")
|
||||
expect(mail.html_part.body).to include(dossier_url(dossier))
|
||||
end
|
||||
|
||||
it "does not send an email when the dossier is created with a non brouillon state" do
|
||||
|
|
|
@ -10,6 +10,7 @@ describe 'new_user/dossiers/index.html.haml', type: :view do
|
|||
|
||||
before do
|
||||
allow(view).to receive(:new_demarche_url).and_return('#')
|
||||
allow(controller).to receive(:current_user) { user }
|
||||
assign(:user_dossiers, Kaminari.paginate_array(user_dossiers).page(1))
|
||||
assign(:dossiers_invites, Kaminari.paginate_array(dossiers_invites).page(1))
|
||||
assign(:dossiers, Kaminari.paginate_array(user_dossiers).page(1))
|
||||
|
@ -70,4 +71,17 @@ describe 'new_user/dossiers/index.html.haml', type: :view do
|
|||
expect(rendered).to have_selector('ul.tabs li.active', count: 1)
|
||||
end
|
||||
end
|
||||
|
||||
context "quand le user n'a aucun feedback" do
|
||||
it "affiche le formulaire de satisfaction" do
|
||||
expect(rendered).to have_selector('#user-satisfaction', text: 'Que pensez-vous de ce service ?')
|
||||
end
|
||||
end
|
||||
|
||||
context "quand le user a un feedback" do
|
||||
let(:user) { create(:user, feedbacks: [build(:feedback)]) }
|
||||
it "n'affiche pas le formulaire de satisfaction" do
|
||||
expect(rendered).to_not have_selector('#user-satisfaction')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
16
spec/views/new_user/dossiers/show.html.haml_spec.rb
Normal file
16
spec/views/new_user/dossiers/show.html.haml_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'new_user/dossiers/show.html.haml', type: :view do
|
||||
let(:dossier) { create(:dossier, :with_service, state: 'brouillon', procedure: create(:procedure)) }
|
||||
|
||||
before do
|
||||
sign_in dossier.user
|
||||
assign(:dossier, dossier)
|
||||
end
|
||||
|
||||
subject! { render }
|
||||
|
||||
it 'affiche les informations du dossier' do
|
||||
expect(rendered).to have_text("Dossier #{dossier.id}")
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue