Add Delete Button for file attribute page
Problem - Add-delete-button-#457 Create Delete button function in the admin file page DatasetLog and CurationLog to log the events. Pass the unit test and acceptance test. How Create Delete button in /view/adminFile/_form.php <td><a role="button" class="btn js-delete" name="delete_file_attr" data="<?= $fa->id ?>">Delete</a></td> </script> $('.js-delete').click(function (e) { e.preventDefault(); id = $(this).attr('data'); row = $('.row-edit-' + id); if (id) { $.post('/adminFile/deleteFileAttribute', { 'id': id }, function(result) { if (result) { // console.log(result); } }, 'json'); } window.location.reload(); }) </script> Create action deleteFileAttribute in AdminFileController.php public function accessRules() { return array( array('allow', // admin only 'actions'=>array('linkFolder','admin','delete','index','view','create','update','update1', 'editAttr', 'uploadAttr', 'deleteFileAttribute'), 'roles'=>array('admin'), ), array('allow', 'actions' => array('create1'), 'users' => array('@'), ), array('allow', // allow all users 'actions' => array('downloadCount'), 'users'=>array('*'), ), array('deny', // deny all users 'users'=>array('*'), ), ); } /** * Yii's method for routing urls to an action. Override to use custom actions */ public function actions() { return array( 'deleteFileAttribute'=>'application.controllers.adminFile.DeleteFileAttributeAction', ); } Create DeleteFileAttributeAction.php in /controllers/adminFile, because AdminFileController.php is very big, so better be implemented in separate class <?php /** * This action will delete file attributes in admin file update page */ class DeleteFileAttributeAction extends CAction { public function run() { if (!Yii::app()->request->isPostRequest) throw new CHttpException(404, "The requested page does not exist."); if (isset($_POST['id'])) { $attribute = FileAttributes::model()->findByPk($_POST['id']); if ($attribute) { $out = $attribute->file->dataset_id; $fileName = $attribute->file->name; $fileModel = get_class($attribute); $fileId = $attribute->file->id; $modelId = $attribute->id; $model = Dataset::model()->findByPk($out); if ($model->upload_status === "Published") { DatasetLog::createDatasetLogEntry($out, $fileName, $fileModel, $modelId, $fileId); } else { CurationLog::createCurationLogEntry($out, $fileName); //Pass in dataset_id returned from File object. } $attribute->delete(); Yii::app()->end(); } } } } Factory method in /protected/models/DatasetLog.php to log Published dataset /** * Factory method to call for common attributes * @param int $id * @param string $fileName * @param string $fileModel * @param int $modelId * @param int $fileId * @return DatasetLog */ public static function makeNewInstanceForDatasetLogBy (int $id, string $fileName, string $fileModel, int $modelId, int $fileId): DatasetLog { $datasetlog = new DatasetLog(); $datasetlog->created_at = date("Y-m-d H:i:s"); $datasetlog->dataset_id = $id; $datasetlog->message = $fileName; $datasetlog->model = $fileModel; $datasetlog->model_id = $modelId; $datasetlog->url = Yii::app()->createUrl('/adminFile/update', array('id'=>$fileId)); return $datasetlog; } /** * Retrieves attributes and store them in dataset_log table when triggered. * @param int $id * @param string $fileName * @param string $fileModel * @param int $modelId * @param int $fileId * @return bool */ public static function createDatasetLogEntry(int $id, string $fileName, string $fileModel, int $modelId, int $fileId): bool { $datasetlog = self::makeNewInstanceForDatasetLogBy($id, $fileName, $fileModel, $modelId, $fileId); $datasetlog->message = $fileName. ": file attribute deleted"; return $datasetlog->save(); } Pass the unit test for datasetLog <?php class DatasetLogTest extends CDbTestCase { public function testDataSetLogEntryFactory() { // With reference to the entry in dataset_log fixture $datasetId = 1; $fileName = "File Tinamus_guttatus.fa.gz"; $fileModel = "File"; $modelId = 16945; $fileId = 16945; //mockup ID $datasetlog = DatasetLog::makeNewInstanceForDatasetLogBy($datasetId, $fileName, $fileModel, $modelId, $fileId); $this->assertNotNull($datasetlog); $this->assertTrue(is_a($datasetlog, DatasetLog::class)); $this->assertEquals($datasetId, $datasetlog->dataset_id); $this->assertEquals($fileName, $datasetlog->message); $this->assertEquals($fileModel, $datasetlog->model); $this->assertEquals($modelId, $datasetlog->model_id); $this->assertEquals("./bin/adminFile/update/id/$fileId", $datasetlog->url); $this->assertTrue($datasetlog->isNewRecord); } // Includde Dataset fixture to avoid unique duplicate key value violation with dataset_log_pkey protected $fixtures=array( 'datasets'=>'Dataset', ); public function testCreateDatasetLogEntry() { $datasetId = 1; $fileName = "File Tinamus_guttatus.fa.gz"; $fileModel = "File"; $modelId = 16945; $fileId = 16945; //mockup ID $saveNewEntry = DatasetLog::createDatasetLogEntry($datasetId, $fileName, $fileModel, $modelId, $fileId); $this->assertTrue(is_bool($saveNewEntry) === true, "bool is returned"); $this->assertTrue(true===$saveNewEntry, "No new entry is saved to dataset log table"); // To assert the delete message will be generated as expected $datasetlog = DatasetLog::model()->findByPk($datasetId); $this->assertEquals("File Tinamus_guttatus.fa.gz: file attribute deleted", $datasetlog->message, "Delete message was generated in different format"); } } Factory method in /protected/models/CurationLog.php to log non Published dataset /** * Factory method to make a new instance and factor out the common code * * @param int $id * @param string $creator * @return CurationLog */ public static function makeNewInstanceForCurationLogBy(int $id, string $creator): CurationLog { $curationlog = new CurationLog(); $curationlog->creation_date = date("Y-m-d"); $curationlog->last_modified_date = null; $curationlog->dataset_id = $id; $curationlog->created_by = $creator; return $curationlog; } public static function createlog($status,$id) { $curationlog = self::makeNewInstanceForCurationLogBy($id, "System"); $curationlog->action = "Status changed to ".$status; return $curationlog->save(); } public static function createlog_assign_curator($id,$creator,$username) { $curationlog = self::makeNewInstanceForCurationLogBy($id, $creator); $curationlog->action = "Curator Assigned"." $username"; return $curationlog->save(); } /** * Retrieves attributes and store them in curation_log table when triggered * @param $id * @param string $fileName * @return bool */ public static function createCurationLogEntry(int $id, string $fileName): bool { $curationlog = self::makeNewInstanceForCurationLogBy($id, "System"); $curationlog->action = $fileName.": file attribute deleted"; return $curationlog->save(); } Pass the unit test for CurationLog <?php class CurationLogTest extends CDbTestCase { public function testMakeNewInstance() { $datasetId = 1; $creator = "System"; $curationLog = CurationLog::makeNewInstanceForCurationLogBy($datasetId, $creator); $this->assertNotNull($curationLog); $this->assertTrue(is_a($curationLog, CurationLog::class)); $this->assertEquals($datasetId, $curationLog->dataset_id); $this->assertEquals($creator, $curationLog->created_by); $this->assertTrue($curationLog->isNewRecord); } } Create I should see a file attribute table in DatasetViewContext.php /** * @Then I should see a file attribute table */ public function iShouldSeeATable(TableNode $table) { foreach ($table as $row) { PHPUnit_Framework_Assert::assertTrue( $this->minkContext->getSession()->getPage()->hasContent($row['Attribute Name']) ); PHPUnit_Framework_Assert::assertTrue( $this->minkContext->getSession()->getPage()->hasContent($row['Value']) ); PHPUnit_Framework_Assert::assertTrue( $this->minkContext->getSession()->getPage()->hasContent($row['Unit']) ); } } Pass the acceptance test @admin-file @issue-457 Feature: A curator can manage file attributes in admin file update page As a curator, I want to manage file attributes from the update form So that I can associate various attributes to files Background: Given Gigadb web site is loaded with production-like data And an admin user exists @ok Scenario: Guest user cannot visit admin file update page Given I am not logged in to Gigadb web site When I go to "/adminFile/update/" Then I should see "Login" @ok Scenario: Go to a published dataset found in production-like database Given I am not logged in to Gigadb web site When I go to "dataset/100056" And I should see "Termitomyces sp. J132 fungus genome assembly data." And I follow "History" Then I should see "History" tab with text "File Termitomyces_assembly_v1.0.fa.gz updated" And I should see "History" tab with text "File Termitomyces_gene_v1.0.cds.fa updated" And I should see "History" tab with text "File Termitomyces_gene_v1.0.cds.fa updated" And I should see "History" tab with text "File Termitomyces_gene_v1.0.gff updated" And I should see "History" tab with text "File Termitomyces_gene_v1.0.gff updated" And I should see "History" tab with text "File Termitomyces_gene_v1.0.pep.fa updated" And I should see "History" tab with text "File Termitomyces_gene_v1.0.pep.fa updated" @ok @Published Scenario: Sign in as admin and visit admin file update page and see New Attribute, Edit, Delete buttons Given I sign in as an admin When I am on "/adminFile/update/id/13973" Then I should see a button "New Attribute" And I should see a file attribute table | Attribute Name | Value | Unit | | last_modified | 2013-7-15 | | And I should see a button input "Edit" And I should see a button input "Delete" @ok @javascript @Published Scenario: Sign in as admin, delete an attribute of a published dataset and check history tab Given I sign in as an admin And I am on "/adminFile/update/id/13973" And I should see "last_modified" When I press "Delete" And I go to "dataset/100056" Then I should see "Termitomyces sp. J132 fungus genome assembly data." And I follow "History" And I should see "History" tab with text "Termitomyces_assembly_v1.0.fa.gz: file attribute deleted" @ok @javascript @Published Scenario: Sign in as admin, no delete button should be seen after delete action has been triggered Given I sign in as an admin And I am on "/adminFile/update/id/13973" And I should see a file attribute table | Attribute Name | Value | Unit | | last_modified | 2013-7-15 | | And I should see a button input "Delete" When I press "Delete" And I wait "3" seconds Then I should not see "last_modified" And I should not see "2013-7-15" And I should not see a button "Delete" @ok @javascript @NonPublished Scenario: Go to a non published dataset found in production-like database, create then delete a keyword attribute Given I sign in as an admin And I am on "/adminFile/update/id/95354" And I should see "test Bauhinia" And I press "Delete" And I should not see "test Bauhinia" #Go to the last page of dataset log When I go to "datasetLog/admin/DatasetLog_page/74" Then I should not see "100245" And I should not see "FCHCGJYBBXX-HKBAUpcgEAACRAAPEI-201_L2_2.fq.gz: file attribute added" And I should not see "FCHCGJYBBXX-HKBAUpcgEAACRAAPEI-201_L2_2.fq.gz: file attribute deleted" Learn Tables relationship dataset file file_attribute id id id identifier dataset_id file_id upload_status value 2.1 Update file_attribute table in data/dev/production_like ...