Commit 8b2fdca0 authored by Fabrice Gangler's avatar Fabrice Gangler 🎨
Browse files

Comptoir v2.9.0

parents e2ddddd8 e4862063
Pipeline #10283 passed with stage
in 5 minutes and 31 seconds
......@@ -5,6 +5,26 @@ Tous les changements notables de ce projet sont documentés dans ce fichier.
Le format s'appuie sur [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
et le projet suit [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [2.9.0](https://gitlab.adullact.net/Comptoir/Comptoir-srv/tags/v2.9.0) - 2020-06-26
### Added
- [#937](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/937) Page d'un logiciel : rendre visible "Pré-sélection Adullact" dans la rubrique Cartographie
### Changed
- [#938](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/938) UX - Menu principal : déplacer "Cartographie" après "prestataire"
- [#930](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/930) UX - Amélioration du menu utilisateur ('profil', 'Paramètres', 'Se déconnecter')
- [#924](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/924) UX - Cartographie, formulaire : renommer le bouton "Envoyer"
- [#933](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/933) UX - Cartographie, formulaire : modification du titre et du sous-titre
- [#934](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/934) UX - Cartographie, formulaire : ajout d'un texte pour éviter de cocher trop de cases
- [#935](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/935) Page d'un logiciel : rendre plus visible les données de la cartographie
- [#940](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/940) Page d'un logiciel : ajout des boutons pour modidifer la cartographie
### Fixed
- [#929](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/929) Formulaire de login : la redirection doit être faite sur `/<lang>/`
- [#922](https://gitlab.adullact.net/Comptoir/Comptoir-srv/issues/922) UX - Cartographie, page "Cas d'usage du Logiciel" : ajout du lien vers le logiciel
## [2.8.0](https://gitlab.adullact.net/Comptoir/Comptoir-srv/tags/v2.8.0) - 2020-06-15
### Added
......
## Changelog template
## Versioning
We tend to follow the [semantic versioning](http://semver.org/) recommendations.
## Template
```
## 2.x.y (unreleased)
### Added
### Changed
### Fixed
### Security
```
# How to upgrade from v2.8.0 to v2.9.0
## 1) First backup (DB + images files)
```bash
# (1) user comptoir
sudo su comptoir
# First backup (DB + images files)
/home/comptoir/Comptoir-srv/bin/COMPTOIR_export_DB_data_AND_images.sh
/home/comptoir/Comptoir-srv/bin/COMPTOIR_export_DB_structure_only.sh
ls -lh /home/comptoir/Comptoir-EXPORT/
```
## 2) Preloading vendor directory
```bash
# (1) use the user "comptoir"
sudo su comptoir
# Preloading vendor
mkdir /home/comptoir/tmp_migration
cd /home/comptoir/tmp_migration
git clone https://gitlab.adullact.net/Comptoir/Comptoir-srv.git
mv Comptoir-srv/ Comptoir_tmp_update_vendor
cd Comptoir_tmp_update_vendor/
git checkout origin/master
git log --decorate --oneline --graph --all
composer check-platform-reqs
composer validate
composer install
```
## 3) Activate maintenance site
see:
[www-maintenance-comptoir](https://gitlab.adullact.net/Adullact-prive/comptoir-prive/www-maintenance-comptoir)
(private repository)
```bash
# (1) use your user
# Activate maintenance site
sudo a2dissite 25-https_comptoir-du-libre.org.conf
sudo a2ensite 30-503-MAINTENANCE_https_comptoir-du-libre.org.conf
sudo service apache2 reload
# on your computer, the following command lines
# must retrun an HTTP 500 response
curl -v https://comptoir-du-libre.org/
curl -v https://comptoir-du-libre.org/notFoundPage
```
## 4) Backup before migration (DB + images files + main directory)
```bash
# (1) user comptoir
sudo su comptoir
# Second backup (DB + images files)
/home/comptoir/Comptoir-srv/bin/COMPTOIR_export_DB_data_AND_images.sh
/home/comptoir/Comptoir-srv/bin/COMPTOIR_export_DB_structure_only.sh
ls -lh /home/comptoir/Comptoir-EXPORT/
# Backup main directory
cd /home/comptoir/
DATE=$(date +"%Y.%m.%d_%Hh%M")
tar -czvf "Comptoir-srv_BACKUP_${DATE}.tar.gz" Comptoir-srv
```
## 5) Update source code
```bash
# (1) user comptoir
sudo su comptoir
# Update source code
cd /home/comptoir/Comptoir-srv
rm -rvf vendor/
git remote -v
git remote update -p
git checkout origin/master
git log --decorate --oneline --graph --all
```
## 6) Update vendor directory + clean cache
```bash
# (1) user comptoir
sudo su comptoir
# Update vendor directory (see step 2 "Preloading vendor directory")
cd /home/comptoir/Comptoir-srv
rm -rvf vendor/
mv -v ../tmp_migration/Comptoir_tmp_update_vendor/vendor ./
# Clean cache
cd /home/comptoir/Comptoir-srv
bin/cake cache clear_all
```
## 7) Apply migration of the database (new tables, adding fields, ...)
The following changes must be recorded in the [production version tracking](https://gitlab.adullact.net/Adullact-prive/comptoir-prive/Exploitation-Comptoir/-/blob/master/Suivi-versions-PROD.md) file.
```bash
# (1) user comptoir
sudo su comptoir
# Apply migration of the database (new tables, adding fields, ...)
cd /home/comptoir/Comptoir-srv
bin/cake migrations migrate
# Now you can apply additional changes in SQL with pgsl
# ---> nothing to do here for this version
```
## 8) Update config files
The following changes must be recorded in the [production version tracking](https://gitlab.adullact.net/Adullact-prive/comptoir-prive/Exploitation-Comptoir/-/blob/master/Suivi-versions-PROD.md) file.
nothing to do here for this version
```bash
# (1) user comptoir
sudo su comptoir
# Apply additional changes in config files
cd /home/comptoir/Comptoir-srv
vim config/comptoir.php # ---> nothing to do here for this version
vim config/app.php # ---> nothing to do here for this version
```
## 9) Enable the main website
see:
[www-maintenance-comptoir](https://gitlab.adullact.net/Adullact-prive/comptoir-prive/www-maintenance-comptoir)
(private repository)
```bash
# (1) use your user
# Enable the main website
sudo a2dissite 30-503-MAINTENANCE_https_comptoir-du-libre.org.conf
sudo a2ensite 25-https_comptoir-du-libre.org.conf
sudo service apache2 reload
# on your computer, the first following command line
# must return an HTTP 200 response code
# and the second return an HTTP 404 response code.
curl -v https://comptoir-du-libre.org/
curl -v https://comptoir-du-libre.org/notFoundPage
```
## 10) Backup after upgraded
```bash
# (1) user comptoir
sudo su comptoir
# Backup after upgraded (DB + images files)
/home/comptoir/Comptoir-srv/bin/COMPTOIR_export_DB_data_AND_images.sh
/home/comptoir/Comptoir-srv/bin/COMPTOIR_export_DB_structure_only.sh
ls -lh /home/comptoir/Comptoir-EXPORT/
```
## 11) Clean up
```bash
# (1) user comptoir
sudo su comptoir
# Clean up
cd /home/comptoir/
rm -rvf tmp_migration/
rm -v Comptoir-srv_BACKUP_*.tar.gz
```
......@@ -281,7 +281,7 @@ Configure::write(
Configure::write(
'VERSION',
[
"footer" => "v2.8.0"
"footer" => "v2.9.0"
]
);
......
......@@ -375,17 +375,31 @@ class SoftwaresController extends AppController
// Load mapping data if necessary
$mappingFirstLevels = [];
$mappingTaxons = [];
$taxonomiesPreSelection = [];
if (count($taxonomiesSoftware) > 0) {
$taxonIds = array_keys($taxonomiesSoftware);
$mappingFirstLevels = $this->getMappingFirstLevels($this->selectedLanguage);
$mappingTaxons = $this->getMappingTaxonsWithTaxonIdsFilter($taxonIds, $this->selectedLanguage);
} else {
$taxonomiesPreSelection = $this->TaxonomysSoftwares->getPreSelectionBySofwareId($softwareId);
if (count($taxonomiesPreSelection) > 0) {
$taxonIds = array_keys($taxonomiesPreSelection);
$mappingFirstLevels = $this->getMappingFirstLevels($this->selectedLanguage);
$mappingTaxons = $this->getMappingTaxonsWithTaxonIdsFilter($taxonIds, $this->selectedLanguage);
}
}
// Populate view data
$this->set(compact(['mappingFirstLevels']));
$this->set(compact(['mappingTaxons']));
$this->set(compact(['taxonomiesSoftware']));
$this->set('_serialize', ['taxonomiesSoftware','mappingTaxons','mappingFirstLevels']);
$this->set(compact(['taxonomiesPreSelection']));
$this->set('_serialize', [
'taxonomiesSoftware',
'taxonomiesPreSelection',
'mappingTaxons',
'mappingFirstLevels'
]);
}
/**
......
......@@ -1147,7 +1147,8 @@ class UsersController extends AppController
$user["user_type"] = $this->Users->UserTypes->get($user["user_type_id"])->get("name");
$this->Auth->setUser($user);
$this->Flash->success(__d("Forms", "You are logged"));
return $this->redirect($this->Auth->redirectUrl("/"));
$lang = $this->selectedLanguage;
return $this->redirect($this->Auth->redirectUrl("/$lang/"));
}
$this->Flash->error(__d("Forms", "You are not logged"));
}
......
......@@ -54,6 +54,10 @@ msgstr ""
msgid "Sign in"
msgstr ""
#: Template/Element/Navigation/navbarFixedTop.ctp:120
msgid "nav.profile"
msgstr ""
#: Template/Element/Navigation/navbarFixedTop.ctp:120
msgid "Profile setting"
msgstr ""
......
......@@ -95,6 +95,18 @@ msgstr ""
msgid "TaxonomySoftware.Form.Add.Help"
msgstr ""
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help2"
msgstr ""
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help3"
msgstr ""
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:77
msgid "TaxonomySoftware.Form.Submit"
msgstr ""
#: Template/Api/V1/TaxonomysSoftwares/mapping_taxon_users_of.ctp:10
msgid "TaxonomySoftware.UserOf.Software_forOneTaxon.Title"
msgstr ""
......@@ -111,6 +123,18 @@ msgstr ""
msgid "TaxonomySoftware.UserOf.comments.title"
msgstr ""
#: Template/Api/V1/Softwares/view.cpt:53
msgid "Taxonomy.softwarePage.sectionTitle"
msgstr ""
#: Template/Api/V1/Softwares/view.cpt:68
msgid "Taxonomy.softwarePage.sectionNoRecord"
msgstr ""
#: Template/Api/V1/Softwares/view.cpt:68
msgid "Taxonomy.softwarePage.preSelection"
msgstr ""
#: Template/Api/V1/TaxonomysSoftwares/mapping_taxon_users_of.ctp:
msgid "TaxonomySoftware.UserOf.comments.subtitle"
msgstr ""
......
......@@ -54,13 +54,17 @@ msgstr ""
msgid "Sign in"
msgstr ""
#: Template/Element/Navigation/navbarFixedTop.ctp:120
msgid "nav.profile"
msgstr "Profile"
#: Template/Element/Navigation/navbarFixedTop.ctp:120
msgid "Profile setting"
msgstr ""
#: Template/Element/Navigation/navbarFixedTop.ctp:125
msgid "Logout"
msgstr ""
msgstr "Logout"
#: Template/Element/Pages/header.ctp:40
msgid "Comptoir du libre"
......
......@@ -91,13 +91,25 @@ msgstr "{0} software: declare your use cases"
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:11
msgid "TaxonomySoftware.Form.Add.H1"
msgstr "Uses of <strong>{0}</strong> software"
"<br><small>by your organisation (<strong>{1}</strong>)</small>"
msgstr "Use cases of <strong>{0}</strong> software"
"<br><small>in your organisation (<strong>{1}</strong>)</small>"
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help"
msgstr "Can you tell us what areas where the <strong>{0}</strong> "
"<br> software is used by your organization? "
msgstr "Can you tell us what are the use cases of <strong>{0}</strong> "
"<br> software in your organization? "
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help2"
msgstr "This information will be added to <strong>mapping</strong> of business software."
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help3"
msgstr "Please select only the use cases really present within your organization."
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:77
msgid "TaxonomySoftware.Form.Submit"
msgstr "Submit your statement"
#: Template/Api/V1/TaxonomysSoftwares/mapping_taxon_users_of.ctp:10
msgid "TaxonomySoftware.UserOf.Software_forOneTaxon.Title"
......@@ -121,6 +133,19 @@ msgid "TaxonomySoftware.UserOf.comments.subtitle"
msgstr "Testimonials on the use of <strong>{0}</strong> free software"
"<br> in the field of <strong>{1}</strong>"
#: Template/Api/V1/Softwares/view.cpt:53
msgid "Taxonomy.softwarePage.sectionTitle"
msgstr "Use cases for {0} software"
#: Template/Api/V1/Softwares/view.cpt:68
msgid "Taxonomy.softwarePage.sectionNoRecord"
msgstr "No use case declared by local governments "
" in <strong>business mapping</strong> for {0} software."
#: Template/Api/V1/Softwares/view.cpt:68
msgid "Taxonomy.softwarePage.preSelection"
msgstr "<em>Adullact</em> pre-fetch for the following use case{0}: "
#: Template/Api/V1/Softwares/view.cpt:98
msgid "Taxonomy.softwarePage.description"
msgstr "<strong>Use case{0}</strong> of libre software <strong>{1}</strong>"
......
......@@ -61,12 +61,16 @@ msgid "Sign in"
msgstr "Se connecter"
#: Template/Element/Navigation/navbarFixedTop.ctp:120
msgid "Profile setting"
msgid "nav.profile"
msgstr "Profil"
#: Template/Element/Navigation/navbarFixedTop.ctp:120
msgid "Profile setting"
msgstr "Paramètres"
#: Template/Element/Navigation/navbarFixedTop.ctp:125
msgid "Logout"
msgstr "Deconnexion"
msgstr "Se déconnecter"
#: Template/Element/Pages/header.ctp:40
msgid "Comptoir du libre"
......
......@@ -91,14 +91,26 @@ msgstr "Logiciel {0} : déclarer vos usages"
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:11
msgid "TaxonomySoftware.Form.Add.H1"
msgstr "Usages du logiciel <strong>{0}</strong>"
"<br><small>par votre structure (<strong>{1}</strong>)</small>"
msgstr "Cas d'usages du logiciel <strong>{0}</strong>"
"<br><small>dans votre structure (<strong>{1}</strong>)</small>"
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help"
msgstr "Pouvez-vous nous préciser quels sont les domaines "
msgstr "Pouvez-vous nous préciser quels sont les <strong>cas d'usages</strong> "
"<br> où le logiciel <strong>{0}</strong> est utilisé par votre organisation ?"
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help2"
msgstr "Ces informations seront ajoutées à la <strong>cartographie</strong> des logiciels métiers."
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:12
msgid "TaxonomySoftware.Form.Add.Help3"
msgstr "Merci de sélectionner uniquement les cas d'usages réellement présent au sein de votre organisation."
#: Template/Api/V1/TaxonomysSoftwares/mapping_form.ctp:77
msgid "TaxonomySoftware.Form.Submit"
msgstr "Soumettre votre déclaration"
#: Template/Api/V1/TaxonomysSoftwares/mapping_taxon_users_of.ctp:10
msgid "TaxonomySoftware.UserOf.Software_forOneTaxon.Title"
msgstr "Logiciel {0}, cas d'usages {1}"
......@@ -122,6 +134,19 @@ msgid "TaxonomySoftware.UserOf.comments.subtitle"
msgstr "Témoignages sur l'utilisation du logiciel libre <strong>{0}</strong>"
"<br> dans le domaine <strong>{1}</strong>"
#: Template/Api/V1/Softwares/view.cpt:53
msgid "Taxonomy.softwarePage.sectionTitle"
msgstr "Cas d'usages pour le logiciel {0}"
#: Template/Api/V1/Softwares/view.cpt:68
msgid "Taxonomy.softwarePage.sectionNoRecord"
msgstr "Aucun cas d'usage déclaré par les collectivités et les administrations "
" dans la <strong>cartographie</strong> des <strong>métiers</strong> pour le logiciel {0}."
#: Template/Api/V1/Softwares/view.cpt:68
msgid "Taxonomy.softwarePage.preSelection"
msgstr "Pré-sélection <em>Adullact</em> pour le{0} cas d'usage{0} suivant{0} : "
#: Template/Api/V1/Softwares/view.cpt:98
msgid "Taxonomy.softwarePage.description"
msgstr "<strong>Cas d'usage{0}</strong> déclaré{0} du logiciel libre <strong>{1}</strong> "
......
......@@ -280,6 +280,20 @@ class TaxonomysSoftwaresTable extends Table
}
/**
* Returns a records list (with user ID NULL)
* grouped by Taxon for given software ID
*
* @param int $softwareId
* @return array example: [ <taxonId> => [taxonomySoftware, ...], ]
*/
public function getPreSelectionBySofwareId(int $softwareId)
{
$existingEntries = $this->find()->where(['software_id' => $softwareId, 'user_id IS NULL'])->toArray();
return $this->getRecordsGroupByTaxonId($existingEntries);
}
/**
* Returns a records list (with user ID not NULL)
* grouped by Taxon for given software ID
......
......@@ -13,7 +13,8 @@ $this->assign('title', __d("Softwares", "{0}", $software->softwarename));
<section>
<?php echo $this->Lists->block(
<?php
$htmlUsedBy = $this->Lists->block(
$software->userssoftwares,
[
"type" => "user",
......@@ -48,12 +49,40 @@ $this->assign('title', __d("Softwares", "{0}", $software->softwarename));
"titleFallBack" => __d("Softwares", "Softwares.Users.DeclareAs.user.removeMessage.", $software->softwarename),
"emptyMsg" => __d("Softwares", "No user for {0}", $software->softwarename)
]
); ?>
);
echo $htmlUsedBy;
?>
</section>
<?php
// Extract buttons for mapping section and rename some HTML ids
// @@@TODO ---> must be refactorized
$mappingButtons = '';
if ( 'Administration' === $this->request->session()->read("Auth.User.user_type")) {
$startPattern = '<div class="container_btn-participate">';
$endPattern = '</div><!-- END class "container_btn-participate" -->';
$mappingButtons = strstr($htmlUsedBy, $startPattern);
$mappingButtons = strstr($mappingButtons, $endPattern, true);
$mappingButtons = "$mappingButtons $endPattern <div class=\"clearFloat\"></div>";
$mappingButtons = str_replace('Form_', 'FormMapping_', $mappingButtons);
$mappingButtons = str_replace('btn_', 'btnMapping_', $mappingButtons);
}
?>
<section class="clearfix">
<div class="align">
<h2> <?= __d("Taxonomy", "Taxonomy.softwarePage.sectionTitle", $software->softwarename); ?></h2>
<?php echo $mappingButtons; ?>
</div>
<?php
// Mapping display for current software
$mappingNoRecord = __d("Taxonomy", "Taxonomy.softwarePage.sectionNoRecord", $software->softwarename);
if (count($taxonomiesSoftware) > 0) {
echo $this->element("Softwares/mappingOnSoftwarePage");
} elseif (count($taxonomiesPreSelection) > 0) {
echo "<p id=\"mappingForSoftware-noRecord\">$mappingNoRecord</p>";
echo $this->element("Softwares/mappingPreSelectionOnSoftwarePage");
} else {
echo "<p id=\"mappingForSoftware-noRecord\">$mappingNoRecord</p>";
}
?>
</section>
......@@ -156,7 +185,7 @@ $this->assign('title', __d("Softwares", "{0}", $software->softwarename));
],
"linkParticipate" => [
"id" => $software->id,
"action" => "",
"action" => "addWorksWellWith",
"text" => __d("Softwares", "Add a software that works well with {0}.", $software->softwarename),
"class" => "btn btn-default inactive-button",
],
......@@ -184,7 +213,7 @@ $this->assign('title', __d("Softwares", "{0}", $software->softwarename));
],
"linkParticipate" => [
"id" => $software->id,
"action" => "",
"action" => "addAlternativeTo",
"text" => __d("Softwares", "Add a software that is an alternative to {0}.", $software->softwarename),
"class" => "btn btn-default inactive-button",
],
......
......@@ -34,8 +34,13 @@ $pageUpdateDate = $this->Time->format($lastUpdate, [IntlDateFormatter::LONG, -1]
// [-1, IntlDateFormatter::FULL] ---> "vendredi 24 avril 2020" | "Friday, April 24, 2020"
$softwareName = $software->softwarename;
$softwareLink = $this->Html->link(
$softwareName,
"/$selectedLanguage/softwares/". $softwareId,
["title" => __d("Softwares", "software.softwareName") . $software->softwarename]
);
$headTitle = __d("Taxonomy", "TaxonomySoftware.UserOf.Software_forOneTaxon.Title", $softwareName, $taxonName);
$h1 = __d("Taxonomy", "TaxonomySoftware.UserOf.Software_forOneTaxon.H1", $softwareName, $taxonName);
$h1 = __d("Taxonomy", "TaxonomySoftware.UserOf.Software_forOneTaxon.H1", $softwareLink, $taxonName);
$subTitle = __d("Taxonomy", "TaxonomySoftware.UserOf.Software_forOneTaxon.subTitle", $softwareName, $taxonName);
$attId = "mappingTaxon$taxonId-UsersOf$softwareId";
......@@ -44,6 +49,7 @@ $this->assign('title', $headTitle);
<section id="<?php echo $attId; ?>" class="mappingTaxonUsersOfPage taxonomyPages clearfix">
<h1> <?php echo $h1; ?> </h1>
<p> <?php echo $subTitle; ?> </p>
<?php echo $this->Lists->block(
$users,
[
......
......@@ -9,7 +9,9 @@
$userName = $user->username;
$headTitle = __d("Taxonomy", "TaxonomySoftware.Form.Add.Title", h($softwareName));
$htmlH1 = __d("Taxonomy", "TaxonomySoftware.Form.Add.H1", h($softwareName), h($userName));
$formHelpNew = __d("Taxonomy", "TaxonomySoftware.Form.Add.Help", h($softwareName));
$formHelp1 = __d("Taxonomy", "TaxonomySoftware.Form.Add.Help", h($softwareName));
$formHelp2 = __d("Taxonomy", "TaxonomySoftware.Form.Add.Help2");
$formHelp3 = __d("Taxonomy", "TaxonomySoftware.Form.Add.Help3");
$this->assign('title', $headTitle);
// Build the form
......@@ -43,7 +45,7 @@
<section id="mappingForm" class="taxonomyPages clearfix">
<h1> <?php echo $htmlH1; ?> </h1>
<br>
<p> <?php echo $formHelpNew; ?> </p>
<p> <?php echo $formHelp1; ?> </p>
<?= $this->Form->create($software, [
'type' => 'file',
"enctype" => "multipart/form-data",
......@@ -74,12 +76,15 @@
?>
<?= $this->Form->hidden('id') ?>