datacore icon indicating copy to clipboard operation
datacore copied to clipboard

[Questions] Coloring of supercharged links plugin; shorter code like in dataview

Open merlinuwe opened this issue 4 months ago • 3 comments

Thanks for your great plugin (and also for dataview).

I have this dataview code:

TABLE WITHOUT ID
file.link AS "Notizen",
dateformat(erstellt, "dd.MM.yyyy, HH:mm 'Uhr'") AS "Erstellt",
dateformat(geändert, "dd.MM.yyyy, HH:mm 'Uhr'") AS "Letzte Änderung",
(date(now) - geändert) AS "das war vor"
WHERE 
geändert AND 
geändert >= (date(today) - dur(2 days))
SORT geändert DESC

Which gives me this output:

Image

When I use datacorefsx, the code is longer and there are no formatings from the supercharged links plugin visible anymore.

return function View() {
    const pages = dc.useQuery("@page and geändert");
    const now = new Date();

    // Nur Notizen mit Änderung in den letzten 2 Tagen
    const recent = pages.filter(page => {
        const changed = new Date(page.value("geändert"));
        return !isNaN(changed) && (now - changed) <= 2 * 24 * 60 * 60 * 1000;
    });

    // Neueste zuerst
    recent.sort((a, b) =>
        new Date(b.value("geändert")) - new Date(a.value("geändert"))
    );

    function formatDate(dstr) {
        if (!dstr) return "";
        const d = new Date(dstr);
        const pad = n => n < 10 ? "0" + n : n;
        return `${pad(d.getDate())}.${pad(d.getMonth() + 1)}.${d.getFullYear()}, ${pad(d.getHours())}:${pad(d.getMinutes())} Uhr`;
    }

    function formatDiff(dateStr) {
        if (!dateStr) return "";
        let ms = now - new Date(dateStr);
        const d = Math.floor(ms / (1000 * 60 * 60 * 24)); ms -= d * 24 * 60 * 60 * 1000;
        const h = Math.floor(ms / (1000 * 60 * 60)); ms -= h * 60 * 60 * 1000;
        const m = Math.floor(ms / (1000 * 60)); ms -= m * 60 * 1000;
        const s = Math.floor(ms / 1000); ms -= s * 1000;
        let parts = [];
        if (d) parts.push(`${d} Tage`);
        if (h) parts.push(`${h} Stunden`);
        if (m) parts.push(`${m} Minuten`);
        parts.push(`${s} Sekunden und ${ms} Millisekunden`);
        return parts.join(', ');
    }

    function fileName(page) {
        const raw = page.file?.name || page.file?.path || page.$path || "";
        return raw.replace(/^.*[\\/]/, '').replace(/\.md$/i, '');
    }

    function filePath(page) {
        return page.file?.path || page.$path || "";
    }

    return (
      <div>
        <table>
          <thead>
            <tr>
              <th>Notizen ({recent.length})</th>
              <th>Erstellt</th>
              <th>Letzte Änderung</th>
              <th>das war vor</th>
            </tr>
          </thead>
          <tbody>
            {recent.length === 0 ? (
              <tr>
                <td colSpan={4}><em>Keine Änderungen in den letzten 2 Tagen</em></td>
              </tr>
            ) : recent.map(page => {
                const erstellt = page.value("erstellt");
                const geaendert = page.value("geändert");
                const name = fileName(page);
                const relPath = filePath(page);
                return (
                  <tr key={page.$path}>
                    <td>
                      <a
                        className="internal-link supercharged-link"
                        href={relPath}
                        data-href={name}
                      >
                        {name}
                      </a>
                    </td>
                    <td>{formatDate(erstellt)}</td>
                    <td>{formatDate(geaendert)}</td>
                    <td>{formatDiff(geaendert)}</td>
                  </tr>
                );
            })}
          </tbody>
        </table>
      </div>
    );
}
Image

What can I do to also get the coloring from supercharged links plugin?

Is there a way to use a shorter datacorejsx code similar to dataview DQL?

merlinuwe avatar Aug 14 '25 09:08 merlinuwe

After rooting around in the documentations, I managed to make the table code significantly shorter:

const UNITS = ["days", "hours", "minutes", "seconds", "milliseconds"];

function formatDiff(date) {
  const diff = date.diffNow(UNITS).negate();

  // Duration has a removeZeros method, but the
  // version of Luxon included in Datacore is outdated,
  // so I have to do it manually here
  const zeroedUnits = new Set();

  for (const unit of UNITS) {
    if (diff[unit] === 0) zeroedUnits.add(unit);
  }
  
  return diff.shiftTo(...UNITS.filter((unit) => !zeroedUnits.has(unit))).toHuman({ showZeros: false });
}

return function View() {
  const recent = dc.useQuery("@page and geändert and geändert >= (date(today) - dur(2 days))");

  recent.sort((a, b) => b.value("geändert") - a.value("geändert"));
  
  const COLUMNS = [
    { id: `Notizen (${recent.length})`, value: (page) => String(page.$link) },
    { id: "Erstellt", value: (page) => page.value("erstellt").toFormat("dd.MM.yyyy, HH:mm 'Uhr'") },
    { id: "Letzte Änderung", value: (page) => page.value("geändert").toFormat("dd.MM.yyyy, HH:mm 'Uhr'") },
    { id: "das war vor", value: (page) => formatDiff(page.value("geändert")) },
  ];
  
  return <dc.Table columns={COLUMNS} rows={recent} />;
}

The main change was using the built-in table view, which is significantly shorter, though not as short as Dataview. I also had to look at the documentation for Luxon (the library Datacore uses for dates) to simulate the date formatting in Dataview.

As for the supercharged links issue, I found that converting the default link to string works, presumably because it then gets parsed as normal markdown instead of displayed using Datacore's own Link component.

Gudine avatar Aug 17 '25 20:08 Gudine

Thank you very much for the solution!

merlinuwe avatar Aug 18 '25 07:08 merlinuwe

return function SuperchargedLink({page, className}) {
    const frontmatterEntries = Object.entries(page.$frontmatter || {});
    const frontmatterMapped = frontmatterEntries.map(([key, value]) => ([`data-link-${key}`, value.raw]));
    const attributes = Object.fromEntries(frontmatterMapped);
    return (
        <span 
            className={className + " data-link-text-dc"}
            data-link-path={page.$path} 
            data-link-tags={page.$tags} 
            {...attributes}>
            <dc.Link link={page.$link} />
        </span>
    )
}

I'm using a Wrapper for this case, makes it easier to add stuff later on.

roman-balzer avatar Aug 18 '25 14:08 roman-balzer