Repository: conan-io/conan

Issue:
graph --table=file.html does not show outdated packages
They were previously shown in colors. I guess adding a column "outdated" will resolve this issue.


Discussion:
It is only about adding it to the requested headers in this snippet, as documented here: https://docs.conan.io/en/latest/extending/template_system/search_table.html

```html
<thead>
    <tr>
        {%- set headers = results.get_headers(keys=['remote', 'package_id']) %}
        {%- for header in headers.row(n_rows=1) %}
        <th>{{ header }}</th>
        {%- endfor %}
    </tr>
</thead>
```

Users can add their own template if they want to.

Resolving patch:
diff --git a/conans/assets/templates/search_table_html.py b/conans/assets/templates/search_table_html.py
--- a/conans/assets/templates/search_table_html.py
+++ b/conans/assets/templates/search_table_html.py
@@ -25,7 +25,7 @@
 
         <table id="results" class="table table-striped table-bordered" style="width:100%">
             <thead>
-                {%- set headers = results.get_headers(keys=['remote', 'package_id']) %}
+                {%- set headers = results.get_headers(keys=['remote', 'package_id', 'outdated']) %}
                 {%- set headers2rows = headers.row(n_rows=2) %}
                 <tr>
                     {%- for category, subheaders in headers2rows %}


Test patch:
diff --git a/conans/test/functional/command/search_test.py b/conans/test/functional/command/search_test.py
--- a/conans/test/functional/command/search_test.py
+++ b/conans/test/functional/command/search_test.py
@@ -387,12 +387,14 @@ def search_html_table_test(self):
         html = ''.join([line.strip() for line in self.client.load("table.html").splitlines()])
         self.assertIn("<h1>Hello/1.4.10@myuser/testing</h1>", html)
         self.assertIn("<td>LinuxPackageSHA</td>"
+                      "<td>False</td>"
                       "<td>Linux</td>"
                       "<td>x86</td>"
                       "<td>gcc</td>"
                       "<td>libstdc++11</td>"
                       "<td>4.5</td>", html)
         self.assertIn("<td>WindowsPackageSHA</td>"
+                      "<td>True</td>"
                       "<td>Windows</td>"
                       "<td>x64</td>"
                       "<td>Visual Studio</td>"
@@ -411,6 +413,7 @@ def search_html_table_all_test(self):
         self.assertIn("<h1>Hello/1.4.10@myuser/testing</h1>", html)
         self.assertIn("<td>local</td>"
                       "<td>LinuxPackageSHA</td>"
+                      "<td>False</td>"
                       "<td>Linux</td>"
                       "<td>x86</td>"
                       "<td>gcc</td>"
@@ -418,6 +421,7 @@ def search_html_table_all_test(self):
                       "<td>4.5</td>", html)
         self.assertIn("<td>search_able</td>"
                       "<td>WindowsPackageSHA</td>"
+                      "<td>True</td>"
                       "<td>Windows</td>"
                       "<td>x64</td>"
                       "<td>Visual Studio</td>"
@@ -1288,6 +1292,42 @@ def test_exception_client_without_revs(self):
         client.run("search lib/0.1@user/testing --revisions", assert_error=True)
         self.assertIn("ERROR: The client doesn't have the revisions feature enabled", client.out)
 
+    def test_outdated_html_table(self):
+        test_server = TestServer(users={"user": "password"})
+        servers = {"default": test_server}
+        client = TestClient(servers=servers, users={"default": [("user", "password")]})
+        conanfile = textwrap.dedent("""
+                from conans import ConanFile
+                class Test(ConanFile):
+                    name = "test"
+                    version = "0.1.0"
+                """)
+        client.save({"conanfile.py": conanfile})
+        client.run("create . user/testing")
+        client.run("upload test/0.1.0@user/testing --all")
+        client.run("search test/0.1.0@user/testing --table=table.html -r default")
+
+        html = ''.join([line.strip() for line in client.load("table.html").splitlines()])
+        self.assertIn("<h1>test/0.1.0@user/testing</h1>", html)
+        self.assertIn("<th>remote</th>"
+                      "<th>package_id</th>"
+                      "<th>outdated</th>"
+                      , html)
+        self.assertIn("<td>default</td>"
+                      "<td>5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9</td>"
+                      "<td>False</td>"
+                      , html)
+
+        client.save({"conanfile.py": "# comment\n%s" % conanfile})
+        client.run("create . user/testing")
+        client.run("upload test/0.1.0@user/testing")
+        client.run("search test/0.1.0@user/testing --table=table.html -r default")
+        html = ''.join([line.strip() for line in client.load("table.html").splitlines()])
+        self.assertIn("<td>default</td>"
+                      "<td>5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9</td>"
+                      "<td>True</td>"
+                      , html)
+
 
 @unittest.skipUnless(get_env("TESTING_REVISIONS_ENABLED", False),
                      "set TESTING_REVISIONS_ENABLED=1")