Skip to content

Commit

Permalink
Merge pull request #103 from lageIBUSP/bulk
Browse files Browse the repository at this point in the history
Bulk
  • Loading branch information
Lobz authored May 15, 2024
2 parents b573624 + 0fd543a commit a2823b5
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 87 deletions.
35 changes: 23 additions & 12 deletions app/Http/Controllers/TurmaController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
use App\Models\User;
use App\Models\Exercicio;
use App\Models\Prazo;
use App\Rules\Emails;
use App\Rules\CsvRule;
use App\Utils\Csv;

class TurmaController extends Controller
{
Expand Down Expand Up @@ -154,30 +155,40 @@ public function updateprazos(Request $request, Turma $turma)
public function update(Request $request, Turma $turma)
{
$this->authorize('edit',$turma);
$rules = array(
'name' => 'required',
'description'=> 'required',
'maillist' => [new Emails],
'defaultpassword' => 'required_with:maillist'
);
$rules = [
'name' => 'required',
'description'=> 'required',
'maillist' => [
'file',
new CsvRule([
'name' => 'required',
'email' => 'required|email'
])
],
'defaultpassword' => 'required_with:maillist'
];
$data = $request->validate($rules);
$turma->update(['name' => $data['name'],'description' => $data['description']]);

// bulk add users
if ($request->maillist ?? "") {
$emails = array_map('trim', explode("\n", $request->maillist)); //$value
$csv = new Csv($request->maillist->get());
$pssw = $request->defaultpassword;
foreach( $emails as $email ) {
$newmember = User::where('email',$email)->first();
foreach( $csv->getData() as $user ) {
$email = $user['email'];
$name = $user['name'];
$newmember = User::where('email', $email)->first();
if($newmember) {
// if user not in turma, add
if ($turma->users()->find($newmember) == null) {
$turma->users()->save($newmember);
}
} else {
// if user doesn't exist, create new
$newmember = User::create(['email' => $email]);
$newmember->password = $pssw;
$newmember = User::create([
'email' => $email,
'name' => $name,
'password' => $pssw]);
$turma->users()->save($newmember);
}
}
Expand Down
83 changes: 83 additions & 0 deletions app/Rules/CsvRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Arr;
use App\Utils\Csv;

class CsvRule implements Rule
{
private $rules = [];
private $colNames = [];
private $error_messages = [];

/**
* Create a new rule instance.
*
* @param array $rules
* @return void
*/
public function __construct($rules)
{
$this->rules = $rules;
$this->colNames = array_keys($this->rules);
}

/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$result = false;
$request = request();

if($request->hasFile($attribute)) {

$errors = [];

// Get data
$csv = new Csv($request->file($attribute)->get());
$csv_data = $csv->getData();

foreach($csv_data as $row_index => $row_data) {

$validator = \Validator::make(
$row_data,
$this->rules
);

if($validator->fails()) {

$line_errors = $validator->errors()->toArray();
foreach($line_errors as $error_index => $line_error) {
// Add line information on error message
$errors[] = "Line ".($row_index+2).": ".$line_error[0];
}
}
}

$this->error_messages = $errors;

if(empty($errors)) {
$result = true;
}

}
return $result;
}

/**
* Get the validation error messages.
*
* @return array
*/
public function message()
{
return $this->error_messages;
}
}
56 changes: 0 additions & 56 deletions app/Rules/Emails.php

This file was deleted.

34 changes: 34 additions & 0 deletions app/Utils/Csv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\Utils;

class Csv
{
protected $columnsNames = [];
protected $data = [];

public function __construct(string $content) {
$rows = array_map('str_getcsv', explode(PHP_EOL, $content));
$this->columnsNames = array_map('trim', array_shift($rows));

foreach ($rows as $row) {
$row = array_map('trim', $row);
if( sizeof($row) == sizeof($this->columnsNames) ) {
$associatedRowData = array_combine($this->columnsNames, $row);
if (empty($keyField)) {
$this->data[] = $associatedRowData;
} else {
$this->data[$associatedRowData[$keyField]] = $associatedRowData;
}
}
}
}

public function getColumnNames(): array {
return $this->columnsNames;
}

public function getData(): array {
return $this->data;
}
}
1 change: 0 additions & 1 deletion resources/views/exercicio/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
@error('file')
<div class="invalid-feedback">{{ $message }}</div>
@enderror

</form>

<form action="{{ route('exercicio.submit',$exercicio)}}#enviar" method="POST">
Expand Down
6 changes: 3 additions & 3 deletions resources/views/turma/edit.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<h1>Editando {{ $turma->name }}</h1>
</div>
<div class="row">
<form action={{URL::to('/turma/'.$turma->id)}} method="POST">
<form action={{URL::to('/turma/'.$turma->id)}} method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
@include ('includes.error_alert')
Expand All @@ -25,8 +25,8 @@
@enderror
</div>
<div class="form-group">
<label for="maillist">Adicionar alunos por e-mail (um e-mail por linha) </label>
<textarea class="form-control @error('maillist') is-invalid @enderror" id="maillist" name="maillist">{{ old('maillist','') }}</textarea>
<label for="maillist">Adicionar alunos por csv (deve conter colunas "name" e "email"; <b><a href="/storage/examples/bulk_add_users.csv">baixe aqui</a></b> um arquivo de exemplo)</label>
<input type="file" class="form-control @error('maillist') is-invalid @enderror" id="maillist" name="maillist">{{ old('maillist','') }}</input>
@error('maillist')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
Expand Down
24 changes: 12 additions & 12 deletions resources/views/turma/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@
</div>
@endif

@can ('edit', $turma)
<a class="btn btn-edit" href="{{ URL::to('turma/' . $turma->id . '/edit') }}">Editar</a>
<a class="btn btn-edit" href="{{ URL::to('turma/' . $turma->id . '/prazos') }}">Alterar prazos</a>
@endcan
@can ('delete', $turma)
<form method="POST" action="{{URL::to("/turma/".$turma->id)}}">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<div class="row gridline">
@can ('edit', $turma)
<a class="btn btn-edit" href="{{ URL::to('turma/' . $turma->id . '/edit') }}">Editar</a>
<a class="btn btn-edit" href="{{ URL::to('turma/' . $turma->id . '/prazos') }}">Alterar prazos</a>
@endcan
@can ('delete', $turma)
<form method="POST" action="{{URL::to("/turma/".$turma->id)}}">
{{ csrf_field() }}
{{ method_field('DELETE') }}

<div class="form-group">
<input type="submit" class="btn btn-danger delete" value="Deletar">
</div>
</form>
@endcan
</form>
@endcan
</div>

@endsection
3 changes: 1 addition & 2 deletions storage/app/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
*
!public/
temp/
!.gitignore
3 changes: 2 additions & 1 deletion storage/app/public/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*
arquivos/
!examples/
!.gitignore
4 changes: 4 additions & 0 deletions storage/app/public/examples/bulk_add_users.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name,email
Fulano de Tal, [email protected]
Cicrana de Tal, [email protected]
Zé da Silva, [email protected]
34 changes: 34 additions & 0 deletions storage/app/public/examples/exercicio.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: '101.00 Bem-vindo(a) ao notaR'
description: |-
Olá! Este deve ser o primeiro exercício que você resolve no notaR, e ele serve para você ganhar familiaridade com o conceito de um corretor automático e com o funcionamento deste sistema.
O notaR funciona executando o script (código) que você envia e verificando se esse script cumpre os requisitos do exercício. Nós não estamos verificando quais são os comandos que você escreve, e sim qual é o resultado, já que existem várias maneiras de resolver os mesmos problemas.
Para pegar um gostinho de como o sistema funciona, nesse exercício você precisa criar 2 objetos. O primeiro deles é um vetor da classe "character" chamado <code>carambola</code>, contendo os elementos "abacaxi" e "beterraba".
Para isso, crie um arquivo no seu computador contendo o comando:
<code>
 carambola <- c("abacaxi", "beterraba")
</code>
Salve esse arquivo e envie para o corretor usando a caixinha abaixo.
Feito? Você deve ter recebido uma mensagem indicando que seu aproveitamento foi de 50% até agora, e dando uma dica de como melhorar! O próximo passo é criar um objeto chamado <code>salada</code>, contendo "beringela" e "batata". Acrescente no seu script a seguinte linha (perceba que ela tem errinhos de digitação):
<code>
salada <- c("berinjuela", "babata")
</code>
Envie para o corretor e veja qual é a mensagem de ajuda agora! Corrija a digitação e envie de novo para receber a nota máxima!
Por fim, às vezes cometemos erros e o código não executa. Tente enviar um arquivo com a seguinte linha (onde faltam os (parênteses)) para ver o que acontece.
<code>
salada <- c"beringela", "batata"
</code>
Se você receber essa mensagem nos próximos exercícios, <a href="panic.jpg">não se desespere</a>! Clique no linque de ajuda que fica abaixo de todos os enunciados para ver dicas de como descobrir o que está errado!
precondicoes: |-
my_carambola <- c("abacaxi", "beterraba")
my_salada <- c("beringela", "batata")
testes:
- { condicao: 'exists("carambola")', dica: 'Não existe um objeto chamado carambola. Você selecionou o arquivo correto?', peso: 1.0 }
- { condicao: 'class(carambola)=="character"', dica: 'O objeto carambola deveria ser da classe character', peso: 1.0 }
- { condicao: 'identical(carambola, my_carambola)', dica: 'O conteúdo do objeto carambola está incorreto. Você digitou corretamente?', peso: 1.0 }
- { condicao: 'exists("salada")', dica: 'Não existe um objeto chamado salada', peso: 1.0 }
- { condicao: 'class(salada)=="character"', dica: 'O objeto salada deveria ser da classe character', peso: 1.0 }
- { condicao: 'identical(salada, my_salada)', dica: 'O conteúdo do objeto salada está incorreto. Você digitou corretamente?', peso: 1.0 }

0 comments on commit a2823b5

Please sign in to comment.