mirror of
https://github.com/Squidly271/community.applications.git
synced 2025-06-03 14:52:13 +08:00
Add docker / plugins sub menu to installed / previous
This commit is contained in:
parent
d77cb121f3
commit
51b99c4bf5
BIN
archive/community.applications-2021.04.28-x86_64-1.txz
Normal file
BIN
archive/community.applications-2021.04.28-x86_64-1.txz
Normal file
Binary file not shown.
@ -339,9 +339,21 @@ $(function(){
|
|||||||
case "installed_apps":
|
case "installed_apps":
|
||||||
previousApps(true);
|
previousApps(true);
|
||||||
break;
|
break;
|
||||||
|
case "inst_docker":
|
||||||
|
previousApps(true,false,"docker");
|
||||||
|
break;
|
||||||
|
case "inst_plugins":
|
||||||
|
previousApps(true,false,"plugins");
|
||||||
|
break;
|
||||||
case "previous_apps":
|
case "previous_apps":
|
||||||
previousApps(false);
|
previousApps(false);
|
||||||
break;
|
break;
|
||||||
|
case "prev_docker":
|
||||||
|
previousApps(false,false,"docker");
|
||||||
|
break;
|
||||||
|
case "prev_plugins":
|
||||||
|
previousApps(false,false,"plugins");
|
||||||
|
break;
|
||||||
case "pinned_apps":
|
case "pinned_apps":
|
||||||
pinnedApps();
|
pinnedApps();
|
||||||
break;
|
break;
|
||||||
@ -950,7 +962,7 @@ function showModeration(script,title) {
|
|||||||
showDesc_openBox("/plugins/<?=$plugin?>/scripts/showStatistics.php?arg1="+script,title,550,900,true,false);
|
showDesc_openBox("/plugins/<?=$plugin?>/scripts/showStatistics.php?arg1="+script,title,550,900,true,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function previousApps(installed,dontClear=false) {
|
function previousApps(installed,dontClear=false,filter="") {
|
||||||
hideSortIcons();
|
hideSortIcons();
|
||||||
clearCategory();
|
clearCategory();
|
||||||
setPageOne();
|
setPageOne();
|
||||||
@ -960,7 +972,7 @@ function previousApps(installed,dontClear=false) {
|
|||||||
$(".dockerSearch").hide();
|
$(".dockerSearch").hide();
|
||||||
enableIcon("#sortIcon",true);
|
enableIcon("#sortIcon",true);
|
||||||
|
|
||||||
post({action:'previous_apps',installed:installed},function(result) {
|
post({action:'previous_apps',installed:installed,filter:filter},function(result) {
|
||||||
if ( installed ) {
|
if ( installed ) {
|
||||||
$(".multi_installDiv").hide();
|
$(".multi_installDiv").hide();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
767d6f2203fed9541daeb57bbf7b58b3 ./Apps.page
|
767d6f2203fed9541daeb57bbf7b58b3 ./Apps.page
|
||||||
83b3f89cd42e8601c7c217d5b4889c81 ./CA_notices.page
|
83b3f89cd42e8601c7c217d5b4889c81 ./CA_notices.page
|
||||||
5cdbd6e3fd10ca4e156cacb7b26dae1e ./CommunityApps.page
|
6b47f59ebd426b33c9c9b4e739d1f47a ./CommunityApps.page
|
||||||
6db73582f22dab13d329e862067ee84e ./PluginAPI.page
|
6db73582f22dab13d329e862067ee84e ./PluginAPI.page
|
||||||
b398273cf7daa62ab00d2de2336ca25f ./README.md
|
b398273cf7daa62ab00d2de2336ca25f ./README.md
|
||||||
1a908064914041c48be7bf0dab77515a ./ca_settings.page
|
1a908064914041c48be7bf0dab77515a ./ca_settings.page
|
||||||
@ -11,12 +11,12 @@ b398273cf7daa62ab00d2de2336ca25f ./README.md
|
|||||||
6e48a62b91bdd066f023f46c6b491afd ./images/discord-gray.svg
|
6e48a62b91bdd066f023f46c6b491afd ./images/discord-gray.svg
|
||||||
8e7dc33512b8a78f28d7179a972c7c34 ./images/discord-hover.svg
|
8e7dc33512b8a78f28d7179a972c7c34 ./images/discord-hover.svg
|
||||||
54e46db492ddb033dfeb2827c5efd4a8 ./images/discord-white.svg
|
54e46db492ddb033dfeb2827c5efd4a8 ./images/discord-white.svg
|
||||||
9c186878dde3a06d4a3e9f8f5769b553 ./include/exec.php
|
1743a5f99c606008ec90b6302cb2d280 ./include/exec.php
|
||||||
46a523633a4737378b64192db97fca27 ./include/helpers.php
|
46a523633a4737378b64192db97fca27 ./include/helpers.php
|
||||||
8f1129e0cdb994c6d1900192252433d8 ./include/paths.php
|
8f1129e0cdb994c6d1900192252433d8 ./include/paths.php
|
||||||
9ba7ea3ef8bad60cb8335da9c0daea4f ./javascript/libraries.js
|
9ba7ea3ef8bad60cb8335da9c0daea4f ./javascript/libraries.js
|
||||||
3a632db992fd18e3f5cfeca203bcff2c ./skins/Narrow/css.php
|
3a632db992fd18e3f5cfeca203bcff2c ./skins/Narrow/css.php
|
||||||
81e36a845dd30426806a0d0c04a8b786 ./skins/Narrow/skin.html
|
58a140a38ceb6836a5b7c5b9bca85b6c ./skins/Narrow/skin.html
|
||||||
7bebedcb67df7ed7c3933a79a3757d9b ./skins/Narrow/skin.php
|
7bebedcb67df7ed7c3933a79a3757d9b ./skins/Narrow/skin.php
|
||||||
38d1f40cbc64eed32cdb3292e1ec1f6e ./scripts/PluginAPI.php
|
38d1f40cbc64eed32cdb3292e1ec1f6e ./scripts/PluginAPI.php
|
||||||
bbd9dec6c5df486d75c46388c14f09ce ./scripts/installMulti.php
|
bbd9dec6c5df486d75c46388c14f09ce ./scripts/installMulti.php
|
||||||
|
@ -979,6 +979,7 @@ function previous_apps() {
|
|||||||
global $caPaths, $caSettings, $DockerClient;
|
global $caPaths, $caSettings, $DockerClient;
|
||||||
|
|
||||||
$installed = getPost("installed","");
|
$installed = getPost("installed","");
|
||||||
|
$filter = getPost("filter","");
|
||||||
$dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']);
|
$dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']);
|
||||||
$info = $caSettings['dockerRunning'] ? $DockerClient->getDockerContainers() : array();
|
$info = $caSettings['dockerRunning'] ? $DockerClient->getDockerContainers() : array();
|
||||||
|
|
||||||
@ -996,166 +997,174 @@ if ( $caSettings['dockerRunning'] ) {
|
|||||||
$all_files = glob("{$caPaths['dockerManTemplates']}/*.xml");
|
$all_files = glob("{$caPaths['dockerManTemplates']}/*.xml");
|
||||||
$all_files = $all_files ?: array();
|
$all_files = $all_files ?: array();
|
||||||
if ( $installed == "true" ) {
|
if ( $installed == "true" ) {
|
||||||
foreach ($info as $installedDocker) {
|
if ( !$filter || $filter == "docker" ) {
|
||||||
$installedName = $installedDocker['Name'];
|
foreach ($info as $installedDocker) {
|
||||||
if ( startsWith($installedImage,"library/") ) # official images are in DockerClient as library/mysql eg but template just shows mysql
|
$installedName = $installedDocker['Name'];
|
||||||
$installedImage = str_replace("library/","",$installedImage);
|
if ( startsWith($installedImage,"library/") ) # official images are in DockerClient as library/mysql eg but template just shows mysql
|
||||||
|
$installedImage = str_replace("library/","",$installedImage);
|
||||||
|
|
||||||
foreach ($file as $template) {
|
foreach ($file as $template) {
|
||||||
if ( $installedName == $template['Name'] ) {
|
if ( $installedName == $template['Name'] ) {
|
||||||
$template['testrepo'] = $installedImage;
|
$template['testrepo'] = $installedImage;
|
||||||
if ( startsWith($installedImage,$template['Repository']) ) {
|
if ( startsWith($installedImage,$template['Repository']) ) {
|
||||||
$template['Uninstall'] = true;
|
$template['Uninstall'] = true;
|
||||||
$template['InstallPath'] = $template['Path'];
|
$template['InstallPath'] = $template['Path'];
|
||||||
if ( $dockerUpdateStatus[$installedImage]['status'] == "false" || $dockerUpdateStatus[$template['Name']] == "false" ) {
|
if ( $dockerUpdateStatus[$installedImage]['status'] == "false" || $dockerUpdateStatus[$template['Name']] == "false" ) {
|
||||||
$template['UpdateAvailable'] = true;
|
$template['UpdateAvailable'] = true;
|
||||||
|
}
|
||||||
|
if ($template['Blacklist'] ) continue;
|
||||||
|
|
||||||
|
$displayed[] = $template;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ($template['Blacklist'] ) continue;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# handle renamed containers
|
||||||
|
foreach ($all_files as $xmlfile) {
|
||||||
|
$o = readXmlFile($xmlfile);
|
||||||
|
$o['Description'] = fixDescription($o['Description']);
|
||||||
|
$o['Overview'] = fixDescription($o['Overview']);
|
||||||
|
$o['InstallPath'] = $xmlfile;
|
||||||
|
$o['UnknownCompatible'] = true;
|
||||||
|
|
||||||
$displayed[] = $template;
|
$flag = false;
|
||||||
break;
|
$containerID = false;
|
||||||
|
foreach ($file as $templateDocker) {
|
||||||
|
# use startsWith to eliminate any version tags (:latest)
|
||||||
|
if ( startsWith($templateDocker['Repository'], $testRepo) ) {
|
||||||
|
if ( $templateDocker['Name'] == $o['Name'] ) {
|
||||||
|
$flag = true;
|
||||||
|
$containerID = $template['ID'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ! $flag ) {
|
||||||
|
$runningflag = false;
|
||||||
|
foreach ($info as $installedDocker) {
|
||||||
|
$installedImage = $installedDocker['Image'];
|
||||||
|
$installedName = $installedDocker['Name'];
|
||||||
|
if ( startsWith($installedImage, $o['Repository']) ) {
|
||||||
|
if ( $installedName == $o['Name'] ) {
|
||||||
|
$runningflag = true;
|
||||||
|
$searchResult = searchArray($file,'Repository',$o['Repository']);
|
||||||
|
if ( ! $searchResult ) {
|
||||||
|
$searchResult = searchArray($file,'Repository',explode(":",$o['Repository'])[0]);
|
||||||
|
}
|
||||||
|
if ( $searchResult !== false ) {
|
||||||
|
$tempPath = $o['InstallPath'];
|
||||||
|
$containerID = $file[$searchResult]['ID'];
|
||||||
|
$o = $file[$searchResult];
|
||||||
|
$o['Name'] = $installedName;
|
||||||
|
$o['InstallPath'] = $tempPath;
|
||||||
|
$o['SortName'] = str_replace("-"," ",$installedName);
|
||||||
|
if ( $dockerUpdateStatus[$installedImage]['status'] == "false" || $dockerUpdateStatus[$template['Name']] == "false" ) {
|
||||||
|
$o['UpdateAvailable'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( $runningflag ) {
|
||||||
|
$o['Uninstall'] = true;
|
||||||
|
$o['ID'] = $containerID;
|
||||||
|
if ( $o['Blacklist'] ) continue;
|
||||||
|
|
||||||
|
# handle a PR from LT where it is possible for an identical template (xml) to be present twice, with different filenames.
|
||||||
|
# Without this, an app could appear to be shown in installed apps twice
|
||||||
|
$fat32Fix[$searchResult]++;
|
||||||
|
if ($fat32Fix[$searchResult] > 1) continue;
|
||||||
|
$displayed[] = $o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# handle renamed containers
|
} else {
|
||||||
foreach ($all_files as $xmlfile) {
|
if ( ! $filter || $filter == "docker" ) {
|
||||||
$o = readXmlFile($xmlfile);
|
# now get the old not installed docker apps
|
||||||
$o['Description'] = fixDescription($o['Description']);
|
foreach ($all_files as $xmlfile) {
|
||||||
$o['Overview'] = fixDescription($o['Overview']);
|
$o = readXmlFile($xmlfile);
|
||||||
$o['InstallPath'] = $xmlfile;
|
if ( ! $o ) continue;
|
||||||
$o['UnknownCompatible'] = true;
|
$o['Description'] = fixDescription($o['Description']);
|
||||||
|
$o['Overview'] = fixDescription($o['Overview']);
|
||||||
|
$o['InstallPath'] = $xmlfile;
|
||||||
|
$o['UnknownCompatible'] = true;
|
||||||
|
$o['Removable'] = true;
|
||||||
|
# is the container running?
|
||||||
|
|
||||||
$flag = false;
|
$flag = false;
|
||||||
$containerID = false;
|
|
||||||
foreach ($file as $templateDocker) {
|
|
||||||
# use startsWith to eliminate any version tags (:latest)
|
|
||||||
if ( startsWith($templateDocker['Repository'], $testRepo) ) {
|
|
||||||
if ( $templateDocker['Name'] == $o['Name'] ) {
|
|
||||||
$flag = true;
|
|
||||||
$containerID = $template['ID'];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ! $flag ) {
|
|
||||||
$runningflag = false;
|
|
||||||
foreach ($info as $installedDocker) {
|
foreach ($info as $installedDocker) {
|
||||||
$installedImage = $installedDocker['Image'];
|
$installedImage = $installedDocker['Image'];
|
||||||
$installedName = $installedDocker['Name'];
|
$installedName = $installedDocker['Name'];
|
||||||
if ( startsWith($installedImage, $o['Repository']) ) {
|
if ( startsWith($installedImage, $o['Repository']) ) {
|
||||||
if ( $installedName == $o['Name'] ) {
|
if ( $installedName == $o['Name'] ) {
|
||||||
$runningflag = true;
|
$flag = true;
|
||||||
$searchResult = searchArray($file,'Repository',$o['Repository']);
|
continue;
|
||||||
if ( ! $searchResult ) {
|
|
||||||
$searchResult = searchArray($file,'Repository',explode(":",$o['Repository'])[0]);
|
|
||||||
}
|
|
||||||
if ( $searchResult !== false ) {
|
|
||||||
$tempPath = $o['InstallPath'];
|
|
||||||
$containerID = $file[$searchResult]['ID'];
|
|
||||||
$o = $file[$searchResult];
|
|
||||||
$o['Name'] = $installedName;
|
|
||||||
$o['InstallPath'] = $tempPath;
|
|
||||||
$o['SortName'] = str_replace("-"," ",$installedName);
|
|
||||||
if ( $dockerUpdateStatus[$installedImage]['status'] == "false" || $dockerUpdateStatus[$template['Name']] == "false" ) {
|
|
||||||
$o['UpdateAvailable'] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( $runningflag ) {
|
if ( ! $flag ) {
|
||||||
$o['Uninstall'] = true;
|
$testRepo = explode(":",$o['Repository'])[0];
|
||||||
$o['ID'] = $containerID;
|
# now associate the template back to a template in the appfeed
|
||||||
if ( $o['Blacklist'] ) continue;
|
foreach ($file as $appTemplate) {
|
||||||
|
if (startsWith($appTemplate['Repository'],$testRepo)) {
|
||||||
# handle a PR from LT where it is possible for an identical template (xml) to be present twice, with different filenames.
|
$tempPath = $o['InstallPath'];
|
||||||
# Without this, an app could appear to be shown in installed apps twice
|
$tempName = $o['Name'];
|
||||||
$fat32Fix[$searchResult]++;
|
$o = $appTemplate;
|
||||||
if ($fat32Fix[$searchResult] > 1) continue;
|
$o['Removable'] = true;
|
||||||
$displayed[] = $o;
|
$o['InstallPath'] = $tempPath;
|
||||||
}
|
$o['Name'] = $tempName;
|
||||||
}
|
$o['SortName'] = str_replace("-"," ",$o['Name']);
|
||||||
}
|
break;
|
||||||
} else {
|
}
|
||||||
# now get the old not installed docker apps
|
|
||||||
foreach ($all_files as $xmlfile) {
|
|
||||||
$o = readXmlFile($xmlfile);
|
|
||||||
if ( ! $o ) continue;
|
|
||||||
$o['Description'] = fixDescription($o['Description']);
|
|
||||||
$o['Overview'] = fixDescription($o['Overview']);
|
|
||||||
$o['InstallPath'] = $xmlfile;
|
|
||||||
$o['UnknownCompatible'] = true;
|
|
||||||
$o['Removable'] = true;
|
|
||||||
# is the container running?
|
|
||||||
|
|
||||||
$flag = false;
|
|
||||||
foreach ($info as $installedDocker) {
|
|
||||||
$installedImage = $installedDocker['Image'];
|
|
||||||
$installedName = $installedDocker['Name'];
|
|
||||||
if ( startsWith($installedImage, $o['Repository']) ) {
|
|
||||||
if ( $installedName == $o['Name'] ) {
|
|
||||||
$flag = true;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ! $flag ) {
|
|
||||||
$testRepo = explode(":",$o['Repository'])[0];
|
|
||||||
# now associate the template back to a template in the appfeed
|
|
||||||
foreach ($file as $appTemplate) {
|
|
||||||
if (startsWith($appTemplate['Repository'],$testRepo)) {
|
|
||||||
$tempPath = $o['InstallPath'];
|
|
||||||
$tempName = $o['Name'];
|
|
||||||
$o = $appTemplate;
|
|
||||||
$o['Removable'] = true;
|
|
||||||
$o['InstallPath'] = $tempPath;
|
|
||||||
$o['Name'] = $tempName;
|
|
||||||
$o['SortName'] = str_replace("-"," ",$o['Name']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! $o['Blacklist'] )
|
if ( ! $o['Blacklist'] )
|
||||||
$displayed[] = $o;
|
$displayed[] = $o;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# Now work on plugins
|
# Now work on plugins
|
||||||
if ( $installed == "true" ) {
|
if ( $installed == "true" ) {
|
||||||
foreach ($file as $template) {
|
if ( ! $filter || $filter == "plugins" ) {
|
||||||
if ( ! $template['Plugin'] ) continue;
|
foreach ($file as $template) {
|
||||||
|
if ( ! $template['Plugin'] ) continue;
|
||||||
|
|
||||||
$filename = pathinfo($template['Repository'],PATHINFO_BASENAME);
|
$filename = pathinfo($template['Repository'],PATHINFO_BASENAME);
|
||||||
|
|
||||||
if ( checkInstalledPlugin($template) ) {
|
if ( checkInstalledPlugin($template) ) {
|
||||||
if ( $template['Blacklist'] ) continue;
|
if ( $template['Blacklist'] ) continue;
|
||||||
|
|
||||||
$template['InstallPath'] = "/var/log/plugins/$filename";
|
$template['InstallPath'] = "/var/log/plugins/$filename";
|
||||||
$template['Uninstall'] = true;
|
$template['Uninstall'] = true;
|
||||||
$displayed[] = $template;
|
$displayed[] = $template;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$all_plugs = array_merge(glob("/boot/config/plugins-error/*.plg"),glob("/boot/config/plugins-removed/*.plg"));
|
if ( ! $filter || $filter == "plugins" ) {
|
||||||
foreach ($all_plugs as $oldplug) {
|
$all_plugs = array_merge(glob("/boot/config/plugins-error/*.plg"),glob("/boot/config/plugins-removed/*.plg"));
|
||||||
foreach ($file as $template) {
|
foreach ($all_plugs as $oldplug) {
|
||||||
if ( basename($oldplug) == basename($template['Repository']) ) {
|
foreach ($file as $template) {
|
||||||
if ( ! file_exists("/boot/config/plugins/".basename($oldplug)) ) {
|
if ( basename($oldplug) == basename($template['Repository']) ) {
|
||||||
if ( $template['Blacklist'] || ( ($caSettings['hideIncompatible'] == "true") && (! $template['Compatible']) ) ) continue;
|
if ( ! file_exists("/boot/config/plugins/".basename($oldplug)) ) {
|
||||||
$oldPlugURL = trim(plugin("pluginURL",$oldplug));
|
if ( $template['Blacklist'] || ( ($caSettings['hideIncompatible'] == "true") && (! $template['Compatible']) ) ) continue;
|
||||||
if ( strtolower(trim($template['PluginURL'])) != strtolower(trim($oldPlugURL)) ) {
|
$oldPlugURL = trim(plugin("pluginURL",$oldplug));
|
||||||
continue;
|
if ( strtolower(trim($template['PluginURL'])) != strtolower(trim($oldPlugURL)) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$template['Removable'] = true;
|
||||||
|
$template['InstallPath'] = $oldplug;
|
||||||
|
if ( $alreadySeen[$oldPlugURL] )
|
||||||
|
continue;
|
||||||
|
$alreadySeen[$oldPlugURL] = true;
|
||||||
|
$displayed[] = $template;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
$template['Removable'] = true;
|
|
||||||
$template['InstallPath'] = $oldplug;
|
|
||||||
if ( $alreadySeen[$oldPlugURL] )
|
|
||||||
continue;
|
|
||||||
$alreadySeen[$oldPlugURL] = true;
|
|
||||||
$displayed[] = $template;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,15 @@
|
|||||||
<div class='menuItems'>
|
<div class='menuItems'>
|
||||||
<ul class='caMenu'>
|
<ul class='caMenu'>
|
||||||
<li class='caMenuItem sectionMenu' data-category='installed_apps'><?tr("Installed Apps");?></li>
|
<li class='caMenuItem sectionMenu' data-category='installed_apps'><?tr("Installed Apps");?></li>
|
||||||
|
<ul class='subCategory'>
|
||||||
|
<li class='caMenuItem sectionMenu' data-category='inst_docker'><?tr("Docker");?></li>
|
||||||
|
<li class='caMenuItem sectionMenu' data-category='inst_plugins'><?tr("Plugins");?></li>
|
||||||
|
</ul>
|
||||||
<li class='caMenuItem sectionMenu' data-category='previous_apps'><?tr("Previous Apps");?></li>
|
<li class='caMenuItem sectionMenu' data-category='previous_apps'><?tr("Previous Apps");?></li>
|
||||||
|
<ul class='subCategory'>
|
||||||
|
<li class='caMenuItem sectionMenu' data-category='prev_docker'><?tr("Docker");?></li>
|
||||||
|
<li class='caMenuItem sectionMenu' data-category='prev_plugins'><?tr("Plugins");?></li>
|
||||||
|
</ul>
|
||||||
<li class='caMenuItem sectionMenu caPinnedMenu' data-category='pinned_apps'><?tr("Pinned Apps");?></li>
|
<li class='caMenuItem sectionMenu caPinnedMenu' data-category='pinned_apps'><?tr("Pinned Apps");?></li>
|
||||||
<li class='caMenuItem favouriteRepo'><?tr("Favourite Repo");?></li>
|
<li class='caMenuItem favouriteRepo'><?tr("Favourite Repo");?></li>
|
||||||
<hr>
|
<hr>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user