/** * 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; }
/** * 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); }); }); }
/** * 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>"; }
/** * 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; }
/** * 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]); }
/** * 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; }
/** * 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()]); } }
/** * 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()]); }
/** * 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)); // 推送到队列 } }
/** * @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 : ''; }
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); }
/** * 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(); }
/** * 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; }
/** * 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(); }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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); }
/** * 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'); }
/** * @return \yii\db\ActiveQuery */ public function getIssues() { return $this->hasMany(Issue::className(), ['project_id' => 'id']); }
/** * 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')); }
/** * @return \yii\db\ActiveQuery */ public function getIssue() { return $this->hasOne(Issue::className(), ['id' => 'issue_id']); }
<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">
/** * @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(); }
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()]; }
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]); }