Пример #1
0
 /**
  * Save the changes.
  *
  * @param Issue $issue
  *
  * @return bool
  */
 public function persist(Issue $issue)
 {
     $issue->user_id = $issue->exists ? $issue->user_id : Auth::id();
     $issue->title = $this->input('title', $issue->title);
     $issue->description = $this->input('description', $issue->description);
     $issue->occurred_at = $this->input('occurred_at', $issue->occurred_at);
     if ($issue->save()) {
         // Check if we have any files to upload and attach.
         if (count($this->files) > 0) {
             foreach ($this->file('files') as $file) {
                 if (!is_null($file)) {
                     $issue->uploadFile($file);
                 }
             }
         }
         // Sync the issues labels.
         $labels = $this->input('labels', []);
         if (is_array($labels)) {
             $issue->labels()->sync($labels);
         }
         // Sync the issues users.
         $users = $this->input('users', []);
         if (is_array($users)) {
             $issue->users()->sync($users);
         }
         return true;
     }
     return false;
 }
Пример #2
0
 /**
  * Returns a new Issue table.
  *
  * @param Issue|Builder $issue
  * @param array         $with
  * @param Closure       $closure
  *
  * @return \Orchestra\Contracts\Html\Builder
  */
 public function table($issue, array $with = ['users', 'labels'], Closure $closure = null)
 {
     $label = request('label');
     // Filter issues with the specified request label.
     $issue->with($with)->label($label)->latest();
     return $this->table->of('issues', function (TableGrid $table) use($issue, $closure) {
         if ($closure instanceof Closure) {
             $table = call_user_func($closure, $table, $issue);
         } else {
             $table->with($issue)->paginate($this->perPage);
         }
         $table->sortable(['title', 'description', 'created_at']);
         $table->searchable(['title', 'description']);
         $table->column('status', function (Column $column) {
             $column->label = '';
             $column->value = function (Issue $issue) {
                 return $issue->present()->statusIcon();
             };
             $column->attributes(function () {
                 return ['width' => '30'];
             });
         });
         $table->column('title', function (Column $column) {
             return $this->tableTitle($column);
         });
     });
 }
Пример #3
0
 /**
  * Returns an icon for the status of the issue.
  *
  * @return string
  */
 public function statusIcon()
 {
     if ($this->issue->isOpen()) {
         $class = 'text-success fa fa-exclamation-circle';
     } else {
         $class = 'text-danger fa fa-check-circle';
     }
     return "<i class='{$class}'></i>";
 }
Пример #4
0
 /**
  * Save the changes.
  *
  * @param Issue $issue
  *
  * @return bool
  */
 public function persist(Issue $issue)
 {
     if ($issue->isClosed()) {
         $issue->closed = false;
         $issue->closed_at = null;
         $issue->closed_by_user_id = null;
         return $issue->save();
     }
     return false;
 }
Пример #5
0
 /**
  * Updates the specified issue labels.
  *
  * @param IssueLabelRequest $request
  * @param int|string        $id
  *
  * @return \Illuminate\Http\RedirectResponse
  */
 public function store(IssueLabelRequest $request, $id)
 {
     $issue = $this->issue->findOrFail($id);
     if ($request->persist($issue)) {
         flash()->success('Success!', 'Successfully updated labels for this issue.');
         return redirect()->route('issues.show', [$id]);
     }
     flash()->error('Error!', 'There was an issue adding labels to this issue. Please try again.');
     return redirect()->route('issues.show', [$id]);
 }
Пример #6
0
 /**
  * Save the changes.
  *
  * @param Issue $issue
  *
  * @return bool
  */
 public function persist(Issue $issue)
 {
     if ($issue->isOpen()) {
         $issue->closed = true;
         $issue->closed_at = $issue->freshTimestamp();
         $issue->closed_by_user_id = auth()->id();
         return $issue->save();
     }
     return false;
 }
Пример #7
0
 /**
  * Bind data to the view.
  *
  * @param View $view
  */
 public function compose(View $view)
 {
     $user = Auth::user();
     // Check for the user instance due to the layout
     // navigation being composed by guests as well.
     if ($user instanceof User) {
         $query = $issues = $this->issue->open();
         if ($user->cannot('manage.issues')) {
             $query = $query->forUser($user);
         }
         $view->with(['issues' => $query->count()]);
     }
 }
Пример #8
0
 /**
  * Bind data to the view.
  *
  * @param View $view
  */
 public function compose(View $view)
 {
     $user = Auth::user();
     $open = $this->issue->open();
     $closed = $this->issue->closed();
     if ($user->cannot('manage.issues')) {
         // If the user doesn't have permission to view all issues, we
         // need to scope the query by the current user to only
         // show the users issue count.
         $open->forUser($user);
         $closed->forUser($user);
     }
     $view->with(['open' => $open->count(), 'closed' => $closed->count()]);
 }
Пример #9
0
 /**
  * Execute the console command.
  * 该任务具体的执行代码, 这边实现定时发邮件
  *
  * @return mixed
  */
 public function handle()
 {
     $issue = Issue::published()->latest('issue')->pluck('issue');
     $issueArticles = Issue::published()->latest()->first()->articles->groupBy('category_id');
     $recommendId = Category::recommend()->pluck('id');
     $otherId = Category::other()->pluck('id');
     $recommArticles = [];
     $normalArticles = collect();
     // 创建一个新集合
     $otherArticles = [];
     foreach ($issueArticles as $key => $value) {
         if ($key == $recommendId) {
             // 推荐分类文章
             $recommArticles = $value;
         } elseif ($key == $otherId) {
             // 其他分类文章
             $otherArticles = $value;
         } else {
             $normalArticles = $normalArticles->merge($value);
         }
     }
     // 把推荐分类文章放在集合第一个  其他分类文章放在集合最后一个
     $articles = collect();
     $articles = $articles->merge($recommArticles)->merge($normalArticles)->merge($otherArticles)->groupBy('category_id');
     $users = Subscribe::where('is_confirmed', 1)->get();
     foreach ($users as $user) {
         $this->dispatch(new SendIssueEmail($user, $issue, $articles));
         // 推送到队列
     }
 }
Пример #10
0
 /**
  * @return \Illuminate\Routing\Route|null|string
  */
 public function ingnoreId()
 {
     $id = $this->route('issue');
     $receipt_id = $this->input('receipt_id');
     $topup_request_id = $this->input('topup_request_id');
     $user_id = $this->input('user_id');
     return Issue::where(compact('id', 'receipt_id', 'topup_request_id', 'user_id'))->exists() ? $id : '';
 }
Пример #11
0
 public function byProject($projectId)
 {
     $issues = Issue::byProject($projectId)->get();
     $statuses = Issue\Status::all();
     $types = CommentType::where('key_name', '!=', 'external')->get();
     $this->setViewPath('issue.index');
     $this->setJavascriptData(compact('issues', 'statuses', 'types'));
 }
 /**
  * Returns a download response for the specified issue attachment.
  *
  * @param int|string $issueId
  * @param string     $fileUuid
  *
  * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
  */
 public function download($issueId, $fileUuid)
 {
     $issue = $this->issue->findOrFail($issueId);
     $this->authorize($issue);
     $file = $issue->findFile($fileUuid);
     if ($path = $file->complete_path) {
         return response()->download($path);
     }
     $file->delete();
     abort(404);
 }
Пример #13
0
 /**
  * Re-Opens an issue.
  *
  * @param IssueOpenRequest $request
  * @param int|string       $id
  *
  * @return \Illuminate\Http\RedirectResponse
  */
 public function open(IssueOpenRequest $request, $id)
 {
     $issue = $this->issue->findOrFail($id);
     $this->authorize('issues.open', [$issue]);
     if ($request->persist($issue)) {
         flash()->success('Success!', 'Successfully re-opened ticket.');
         return redirect()->back();
     }
     flash()->error('Error!', 'There was a problem re-opening this ticket. Please try again.');
     return redirect()->back();
 }
Пример #14
0
 /**
  * Operations to run upon deleting an issue.
  *
  * @param Issue $issue
  */
 public function deleting(Issue $issue)
 {
     // Make sure the model isn't soft deleted.
     if (!$issue->deleted_at) {
         // Detach the issue labels.
         $issue->labels()->detach();
         // Retrieve the comments attached to the current issue.
         $comments = $issue->comments()->get();
         // Detach the comments issue comments.
         $issue->comments()->detach();
         // Delete all of the comments.
         foreach ($comments as $comment) {
             $comment->delete();
         }
         // Delete the issue attachments.
         $files = $issue->files()->get();
         foreach ($files as $file) {
             $file->delete();
         }
     }
 }
 /**
  * Save the changes.
  *
  * @param Issue   $issue
  * @param Comment $comment
  *
  * @return bool
  */
 public function persist(Issue $issue, Comment $comment)
 {
     $comment->content = $this->input('content', $comment->content);
     $resolution = $this->input('resolution', false);
     // Make sure we only allow one comment resolution
     if (!$issue->hasCommentResolution() || $comment->resolution) {
         $issue->comments()->updateExistingPivot($comment->id, compact('resolution'));
     }
     if ($comment->save()) {
         // Check if we have any files to upload and attach them to the comment.
         if (count($this->files) > 0) {
             foreach ($this->file('files') as $file) {
                 if (!is_null($file)) {
                     $comment->uploadFile($file);
                 }
             }
         }
         return true;
     }
     return false;
 }
Пример #16
0
 /**
  * Deletes the specified issues comment.
  *
  * @param int|string $id
  * @param int|string $commentId
  *
  * @return \Illuminate\Http\RedirectResponse
  */
 public function destroy($id, $commentId)
 {
     $issue = $this->issue->findOrFail($id);
     $comment = $issue->comments()->findOrFail($commentId);
     $this->authorize('comments.destroy', [$comment]);
     $issue->comments()->detach($comment);
     if ($comment->delete()) {
         flash()->success('Success!', 'Successfully deleted comment.');
         return redirect()->back();
     }
     flash()->error('Error!', 'There was a problem deleting this comment. Please try again.');
     return redirect()->back();
 }
Пример #17
0
 /**
  * Creates data provider instance with search query applied
  *
  * @param array $params
  *
  * @return ActiveDataProvider
  */
 public function search($params)
 {
     $query = Issue::find();
     $dataProvider = new ActiveDataProvider(['query' => $query]);
     $this->load($params);
     if (!$this->validate()) {
         // uncomment the following line if you do not want to return any records when validation fails
         // $query->where('0=1');
         return $dataProvider;
     }
     $query->andFilterWhere(['id' => $this->id, 'tracker_id' => $this->tracker_id, 'project_id' => $this->project_id, 'issue_category_id' => $this->issue_category_id, 'user_id' => $this->user_id, 'issue_priority_id' => $this->issue_priority_id, 'version_id' => $this->version_id, 'assigned_to' => $this->assigned_to, 'created' => $this->created, 'modified' => $this->modified, 'done_ratio' => $this->done_ratio, 'closed' => $this->closed, 'pre_done_ratio' => $this->pre_done_ratio, 'updated_by' => $this->updated_by, 'last_comment' => $this->last_comment]);
     $query->andFilterWhere(['like', 'subject', $this->subject])->andFilterWhere(['like', 'description', $this->description])->andFilterWhere(['like', 'status', $this->status]);
     return $dataProvider;
 }
Пример #18
0
 /**
  * Creates data provider instance with search query applied
  *
  * @param array $params
  *
  * @return ActiveDataProvider
  */
 public function search($params)
 {
     $query = Issue::find();
     $dataProvider = new ActiveDataProvider(['query' => $query]);
     $this->load($params);
     if (!$this->validate()) {
         // uncomment the following line if you do not want to return any records when validation fails
         // $query->where('0=1');
         return $dataProvider;
     }
     $query->andFilterWhere(['id' => $this->id]);
     $query->andFilterWhere(['like', 'yes', $this->yes])->andFilterWhere(['like', 'no', $this->no])->andFilterWhere(['like', 'sum', $this->sum])->andFilterWhere(['like', 'plus', $this->plus]);
     return $dataProvider;
 }
Пример #19
0
 /**
  * Creates data provider instance with search query applied
  *
  * @param array $params
  *
  * @return ActiveDataProvider
  */
 public function search($params)
 {
     $query = Issue::find()->joinWith(['author', 'project', 'checkLists']);
     $dataProvider = new ActiveDataProvider(['query' => $query, 'pagination' => ['pageSize' => 50], 'sort' => ['defaultOrder' => ['priority_id' => SORT_DESC, 'id' => SORT_DESC]]]);
     $this->load($params);
     if (!$this->validate()) {
         // uncomment the following line if you do not want to return any records when validation fails
         // $query->where('0=1');
         return $dataProvider;
     }
     $query->andFilterWhere(['id' => $this->id, 'tracker_id' => $this->tracker_id, 'status_id' => $this->status_id, 'priority_id' => $this->priority_id, 'assignee_id' => $this->assignee_id, 'deadline' => $this->deadline, 'readiness_id' => $this->readiness_id, 'project_id' => $this->project_id, 'issue.creator_id' => $this->creator_id, 'milestone_id' => $this->milestone_id, 'created_date' => $this->created_date, 'updated_date' => $this->updated_date]);
     $query->andFilterWhere(['like', 'subject', $this->subject])->andFilterWhere(['like', 'description', $this->description]);
     return $dataProvider;
 }
 /**
  * Save the changes.
  *
  * @param Issue $issue
  *
  * @return bool
  */
 public function persist(Issue $issue)
 {
     $attributes = ['content' => $this->input('content'), 'user_id' => Auth::id()];
     $resolution = $this->has('resolution');
     // Make sure we only allow one comment resolution
     if ($issue->hasCommentResolution()) {
         $resolution = false;
     }
     // Create the comment.
     $comment = $issue->comments()->create($attributes, compact('resolution'));
     // Check that the comment was created successfully.
     if ($comment instanceof Comment) {
         // Check if we have any files to upload and attach them to the comment.
         if (count($this->files) > 0) {
             foreach ($this->file('files') as $file) {
                 if (!is_null($file)) {
                     $comment->uploadFile($file);
                 }
             }
         }
         return $comment;
     }
     return false;
 }
Пример #21
0
 /**
  * Returns a form of the issue comment.
  *
  * @param Issue   $issue
  * @param Comment $comment
  *
  * @return \Orchestra\Contracts\Html\Builder
  */
 public function form(Issue $issue, Comment $comment)
 {
     return (new CommentPresenter($this->form, $this->table))->form($comment, function (FormGrid $form, Comment $comment) use($issue) {
         // Check if the issue already has a resolution
         $hasResolution = $issue->findCommentResolution();
         if ($comment->exists) {
             $hash = sprintf('#comment-%s', $comment->id);
             $url = route('issues.comments.update', [$issue->id, $comment->id, $hash]);
             $method = 'PATCH';
             $form->submit = 'Save';
         } else {
             $url = route('issues.comments.store', [$issue->id, '#comment']);
             $method = 'POST';
             $form->submit = 'Comment';
         }
         $files = true;
         $form->attributes(compact('url', 'method', 'files'));
         // Setup the comment form fieldset.
         $form->fieldset(function (Fieldset $fieldset) use($comment, $hasResolution) {
             $isResolution = $comment->resolution;
             $fieldset->control('input:file', 'files[]', function (Field $field) use($comment) {
                 if ($comment->exists) {
                     $field->label = 'Attach More Files';
                 } else {
                     $field->label = 'Attach Files';
                 }
                 $field->attributes = ['multiple' => true, 'accept' => '.xlx,.xlsx,.pdf,.doc,.docx,.jpg,.jpeg,.png'];
             });
             // If the issue doesn't have a resolution, or the current comment
             // is the resolution, we'll add the mark resolution checkbox
             if (!$hasResolution || $isResolution) {
                 $fieldset->control('input:checkbox', 'Mark as Answer')->attributes(['class' => 'switch-mark', $isResolution ? 'checked' : null])->name('resolution')->value(1);
             }
         });
     });
 }
 /**
  * Returns a download response for the specified issue attachment.
  *
  * @param int|string $issueId
  * @param int|string $commentId
  * @param string     $fileUuid
  *
  * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
  */
 public function download($issueId, $commentId, $fileUuid)
 {
     $issue = $this->issue->findOrFail($issueId);
     $this->authorize($issue);
     $comment = $issue->comments()->findOrFail($commentId);
     $file = $comment->findFile($fileUuid);
     if ($path = $file->complete_path) {
         return response()->download($path);
     }
     // The path doesn't exist, which means the file does
     // not exist. We'll delete the file to prevent
     // users from accessing it again.
     $file->delete();
     abort(404);
 }
Пример #23
0
 /**
  * Execute the console command.
  *
  * @return mixed
  */
 public function handle()
 {
     /** @var \Maatwebsite\Excel\Excel $excel */
     $excel = app('excel');
     $excel->create('issues', function ($excel) {
         $excel->sheet('issues', function ($sheet) {
             $issues = Issue::latest()->get();
             $headers = ['Title', 'Description', 'Resolution'];
             $row = 1;
             $sheet->row($row, $headers);
             foreach ($issues as $issue) {
                 $row++;
                 $resolution = $issue->findCommentResolution();
                 $sheet->row($row, [$issue->title, $issue->description, $resolution ? $resolution->content : null]);
             }
         });
     })->store('xls');
 }
Пример #24
0
 /**
  * @return \yii\db\ActiveQuery
  */
 public function getIssues()
 {
     return $this->hasMany(Issue::className(), ['project_id' => 'id']);
 }
Пример #25
0
 /**
  * Remove the specified resource from storage.
  *
  * @param  int  $id
  * @return Response
  */
 public function delete($id)
 {
     //Soft delete the item
     $issue = Issue::find($id);
     $issue->delete();
     // redirect
     return redirect()->to('issue.index')->with('message', trans('messages.issue-succesfully-deleted'));
 }
Пример #26
0
 /**
  * @return \yii\db\ActiveQuery
  */
 public function getIssue()
 {
     return $this->hasOne(Issue::className(), ['id' => 'issue_id']);
 }
Пример #27
0
            <dt><?php 
echo \Yii::t('app', 'Assignee');
?>
</dt>
            <dd>
                <?php 
echo Editable::widget(['model' => $model, 'attribute' => 'assignee_id', 'header' => \Yii::t('app', 'Assignee'), 'inputType' => Editable::INPUT_DROPDOWN_LIST, 'data' => \app\models\Project::getAssigneeOptions($model->project_id), 'options' => ['class' => 'form-control', 'prompt' => ' - '], 'displayValue' => $model->assignee ? $model->assignee->getFullName() : '<i>(' . \Yii::t('app', 'not set') . ')</i>']);
?>
            </dd>
            <dt><?php 
echo \Yii::t('app', '% Done');
?>
</dt>
            <dd>
                <?php 
echo Editable::widget(['model' => $model, 'attribute' => 'readiness_id', 'header' => \Yii::t('app', '% Done'), 'inputType' => Editable::INPUT_DROPDOWN_LIST, 'data' => Issue::getReadinessOptions(), 'options' => ['class' => 'form-control'], 'displayValue' => Issue::getReadinessOptions()[$model->readiness_id]]);
?>
            </dd>
            <dt><?php 
echo \Yii::t('app', 'Deadline');
?>
</dt>
            <dd>
                <?php 
echo Editable::widget(['model' => $model, 'attribute' => 'deadline', 'size' => 'md', 'inputType' => Editable::INPUT_DATE, 'displayValue' => $model->deadline, 'options' => ['pluginOptions' => ['autoclose' => true, 'format' => 'yyyy-mm-dd']]]);
?>
            </dd>
        </dl>
    </div>
    <div class="col-sm-6">
Пример #28
0
 /**
  * @return \yii\db\ActiveQuery
  */
 public function getClosedTasks()
 {
     return $this->hasMany(Issue::className(), ['project_id' => 'id'])->where('tracker_id=:task AND status_id=:closed', [':task' => TrackerEnum::TASK, ':closed' => StatusEnum::CLOSED])->count();
 }
Пример #29
0
 public function actionGetIssuesJson()
 {
     \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
     return ['New' => Issue::find()->where('status_id IN (' . implode(',', StatusEnum::getOpenStatuses()) . ')')->orderBy('id DESC')->limit(self::ISSUE_LIMIT)->all(), 'In work' => Issue::find()->where(['status_id' => StatusEnum::IN_WORK])->orderBy('id DESC')->limit(self::ISSUE_LIMIT)->all(), 'Closed' => Issue::find()->where('status_id IN (' . implode(',', StatusEnum::getClosedStatuses()) . ')')->orderBy('id DESC')->limit(self::ISSUE_LIMIT)->all()];
 }
Пример #30
0
 public function actionCreateEmpty()
 {
     $model = new Issue();
     if ($model->load(\Yii::$app->request->post()) && $model->save()) {
         $this->saveChecklist($model);
         $this->sendMessage($model);
         return $this->redirect(['/issue/index', 'id' => $model->project_id]);
     }
     $checklistItems[] = new IssueChecklist();
     return $this->render('createEmpty', ['model' => $model, 'checklistItems' => $checklistItems]);
 }