mirror of
https://github.com/netfun2000/hipudding-teslamate.git
synced 2026-02-27 09:44:28 +08:00
* ci: add treefmt as code formatting multiplexer * style: linter findings in entrypoint.sh script * style: linter findings for yaml and yml * style: linter findings for json files * style: linter findings for nix files * style: linter findings for js files * style: linter findings for dashboards.sh * style: linter findings for md and mdx files * chore: remove unused clang formatter in treefmt config * style: linter findings for mdx files * ci: exclude Grafana dashboard JSON files from prettier formatting * Revert "style: linter findings for json files" This reverts commit f40c2e175992f66f887a3f4fc5aa1a1a89393147. * ci: exclude Grafana dashboard JSON files from all formatting as we use the grafana export style * style: linter findings for json files * doc: update changelog * ci(refactor): use composite action to avoid duplication in elixir workflow * doc: update changelog * ci: prevent workflow runs for certain conditions and allow scheduled runs * ci(refactor): use reusable workflow to check paths * ci(fix): correct output syntax for check_paths workflow and setting base branch * ci(refactor): use reusable workflows for streamlined DevOps pipeline * ci(fix): add write permission for packages in DevOps workflow * ci(test): test DevOps workflow * ci(test): test DevOps workflow * ci(fix): Update condition for spell_check, ensure_linting, elixir, and ghcr_build workflows to reflect empty result instead of false * ci: revert test DevOps * ci(refactor): allow ghcr_build parallel to elixir test * ci(refactor): Remove redundant check_paths job from elixir.yml, elixir_test.yml, and spell_check.yml workflows, check is done in devops.yml * feat: add treefmt-nix to nix flake (#4219 - @JakobLichterfeld) * ci: ensure proper linting via treefmt * ci(test): test ensure_linting workflow * ci(fix): checkout code for spell_checker to access file to check * ci(fix): allow impure in ensure_linting workflow * Revert "ci(test): test ensure_linting workflow" This reverts commit a67b17ec098a628a8b093ec20b34b0e2696811cc. * ci(fix): correct use of flake-utils for formatter and checks Co-authored-by: scottbot95 <scottbot95@gmail.com> * ci(fix): correct use of flake-utils for treefmt Co-authored-by: scottbot95 <scottbot95@gmail.com> * refactor: Remove unnecessary imports in flake * ci(fix): correct syntax in flake * ci(refactor): Remove unused code in flake.nix * style: standardised style for input url in flake * ci(fix): treefmt-nix config with existing options * ci(feat): Add Nix binary cache and update treefmt command in CI workflow * ci(refactor): Remove unused code in flake.nix * fix: include devShell packages only on supported platforms * fix: update hash for mix-deps package in flake.nix * ci(fix): Update treefmt command in CI workflow * ci(test): test ensure_linting workflow * feat: ensure mix deps are present in devShell * ci(feat): use flake-parts to enable treefmt-nix * feat: use flake-parts * fix: correct use of flake-parts for package build * doc: update CI badge URL for devops workflow * ci(fix): handle empty path filter output * ci: remove --impure flag from treefmt command in CI workflow * fix: correct treefmt.config settings in formatter.nix * fix: correct flake-parts inputs, avoid with in imports * fix: correct program name for mix-format in formatter.nix * feat: devenv via flake-parts * fix: correct use of legacy nix code with flake-parts * ci(fix): correct nix develop command in ensure_linting.yml * refactor: list imports explicitly in flake, rename folder to flake-modules to be precise * style: use tabs for indent size to format sh * style: use nixfmt-rfc-style * Revert "style: use nixfmt-rfc-style" This reverts commit 082056159e611c2c0639f8b4dc509446f5308a92. * style: use nixfmt style * fix: remove glibcLocales from optional dependencies to avoid "A definition for option `packages."[definition 4-entry 16]"' is not of type `package'." * fix: remove inotify-tools from optional dependencies to avoid "A definition for option `packages."[definition 4-entry 16]"' is not of type `package'." * fix: Remove inotify-tools and glibcLocales from optional dependencie * fix: correct file paths in flake.nix to version * fix: add ELIXIR_ERL_OPTIONS to shell environment to force utf8 locale * fix: add LOCALE_ARCHIVE to shell environment in flake.nix * Revert "fix: add LOCALE_ARCHIVE to shell environment in flake.nix" This reverts commit d45f6e32eea1fcaf55cd03733e648cda4dbb764b. * ci(refactor): rename workflow to elixir_dep_verification_and_static_analysis.yml to better reflect the intention,, remove duplicate checks * ci(debug): debug locale settings * Revert "ci(debug): debug locale settings" This reverts commit 9b402f3c5f9b41ff4716dc4fc99f711fc9ef8135. * Revert "fix: add ELIXIR_ERL_OPTIONS to shell environment to force utf8 locale" This reverts commit d02419cba44055d55978ad36d23493d8790ce21b. * fix: add LOCALE_ARCHIVE to shell environment in flake.nix * Revert "fix: add LOCALE_ARCHIVE to shell environment in flake.nix" This reverts commit 761b437e699d8381a0726dd969052b1e85c3f08f. * fix: add LANG=C.UTF-8 to shell environment in flake.nix * fix: add mix local.rebar and mix local.hex commands to flake.nix * fix: pin devenv to version without unix socket bug * chore: update nixpkgs to nixos-24.05 and update dependencies * doc: add treefmt config comments * ci: do not expose treefmt formatter programs in devshell * fix: correct use of module option to enable PostgreSQL server in flake.nix * Revert "chore: update nixpkgs to nixos-24.05 and update dependencies" This reverts commit a6ea3f25aa393c32d9c2494b21e6330de2482496. * feat: consistent use of erlang 26 and elixir 1_16 in flake * ci: switch to macOS runner for linting workflow * Revert "ci: do not expose treefmt formatter programs in devshell" This reverts commit 1ecfa451dcf4199554a5d96d241ee846601862d9. * Revert "ci: switch to macOS runner for linting workflow" This reverts commit 7b430667d8737e5adf91f5ba59bbf83eb15bcb7a. * ci: Remove nixpkgs channel specification in ensure_linting workflow * ci(debug): Add debug output for PATH and NIX_PATH in flake.nix * Revert "ci(debug): Add debug output for PATH and NIX_PATH in flake.nix" This reverts commit 07faec5ddf88195969f89f3e74791d030c980b03. * fix: avoid the need for impure for devenv see #4245 * fix: remove invalid custom build.check for formatter and use default * style: linter findings * fix: Add emptyTest to avoid nix flake check test execution on non-Linux systems * chore: Remove LANG=C.UTF-8 from enterShell in flake.nix * ci(fix): Remove --impure flag from treefmt command in CI mode * ci(fix): avoid impure mode in ensure_linting workflow * style: linter findings * ci(debug): debug elixir version and locale * chore: Update flake.lock dependencies * feat: use newer devenv as unix socket bug is fixed in upstream https://github.com/cachix/devenv/issues/1497 * fix: set rebar3 path in devenv * Revert "ci(debug): debug elixir version and locale" This reverts commit 7ecdc77c163cd6ef9c913689c1f75e86ce8587cb. * ci: re-enable path check in DevOps workflow * doc: update Development and Contributing guide with nix and treefmt * ci: use PostgreSQL 17 * style: linter findings * ci(fix): ensure cache name in build action does not contain invalid characters to avoid invalid reference format * doc: update changelog * Revert "ci(fix): ensure cache name in build action does not contain invalid characters to avoid invalid reference format" This reverts commit 02abb0359db4f22e5a28283476b3ced0d99729ff. * ci: remove branch restriction for check_paths workflow to increase sec * ci(fix): run ghcr build workflow only for specific conditions - Ensure workflow only run if there are no changes to the .github folder - Allow workflow to run on workflow call or PRs from forks - Prevent duplicate runs for PRs from non-forks - Avoid invalid reference format for cache name in PRs from our repository * doc: update changelog * fix: update hash for mix-deps package in flake.nix * fix: disable flakeCheck for formatter, as mix format need the dep to be fetched beforehand * ci(fix): run ghcr build workflow only for specific conditions * fix: move nixosModules.default to top-level attribute set * refactor: remove unnecessary config nesting in formatter.nix * ci(fix): ensure version for buildx is set to correct name --------- Co-authored-by: scottbot95 <scottbot95@gmail.com>
329 lines
7.4 KiB
JavaScript
329 lines
7.4 KiB
JavaScript
const LANG = navigator.languages
|
||
? navigator.languages[0]
|
||
: navigator.language || navigator.userLanguage;
|
||
|
||
function toLocalTime(dateStr, opts) {
|
||
const date = new Date(dateStr);
|
||
|
||
return date instanceof Date && !isNaN(date.valueOf())
|
||
? date.toLocaleTimeString(LANG, opts)
|
||
: "–";
|
||
}
|
||
|
||
function toLocalDate(dateStr, opts) {
|
||
const date = new Date(dateStr);
|
||
|
||
return date instanceof Date && !isNaN(date.valueOf())
|
||
? date.toLocaleDateString(LANG, opts)
|
||
: "–";
|
||
}
|
||
|
||
export const Dropdown = {
|
||
mounted() {
|
||
const $el = this.el;
|
||
|
||
$el.querySelector("button").addEventListener("click", (e) => {
|
||
e.stopPropagation();
|
||
$el.classList.toggle("is-active");
|
||
});
|
||
|
||
document.addEventListener("click", () => {
|
||
$el.classList.remove("is-active");
|
||
});
|
||
},
|
||
};
|
||
|
||
export const LocalTime = {
|
||
mounted() {
|
||
this.el.innerText = toLocalTime(this.el.dataset.date);
|
||
},
|
||
|
||
updated() {
|
||
this.el.innerText = toLocalTime(this.el.dataset.date);
|
||
},
|
||
};
|
||
|
||
export const LocalTimeRange = {
|
||
exec() {
|
||
const date = toLocalDate(this.el.dataset.startDate, {
|
||
year: "numeric",
|
||
month: "short",
|
||
day: "numeric",
|
||
});
|
||
|
||
const time = [this.el.dataset.startDate, this.el.dataset.endDate]
|
||
.map((date) =>
|
||
toLocalTime(date, {
|
||
hour: "2-digit",
|
||
minute: "2-digit",
|
||
hour12: false,
|
||
}),
|
||
)
|
||
.join(" – ");
|
||
|
||
this.el.innerText = `${date}, ${time}`;
|
||
},
|
||
|
||
mounted() {
|
||
this.exec();
|
||
},
|
||
updated() {
|
||
this.exec();
|
||
},
|
||
};
|
||
|
||
export const ConfirmGeoFenceDeletion = {
|
||
mounted() {
|
||
const { id, msg } = this.el.dataset;
|
||
|
||
this.el.addEventListener("click", () => {
|
||
if (window.confirm(msg)) {
|
||
this.pushEvent("delete", { id });
|
||
}
|
||
});
|
||
},
|
||
};
|
||
|
||
import {
|
||
Map as M,
|
||
TileLayer,
|
||
LatLng,
|
||
Control,
|
||
Marker,
|
||
Icon,
|
||
Circle,
|
||
CircleMarker,
|
||
} from "leaflet";
|
||
|
||
import markerIcon from "leaflet/dist/images/marker-icon.png";
|
||
import markerShadow from "leaflet/dist/images/marker-shadow.png";
|
||
|
||
const icon = new Icon({
|
||
iconUrl: markerIcon,
|
||
shadowUrl: markerShadow,
|
||
iconAnchor: [12, 40],
|
||
popupAnchor: [0, -25],
|
||
});
|
||
|
||
const DirectionArrow = CircleMarker.extend({
|
||
initialize(latLng, heading, options) {
|
||
this._heading = heading;
|
||
CircleMarker.prototype.initialize.call(this, latLng, {
|
||
fillOpacity: 1,
|
||
radius: 5,
|
||
...options,
|
||
});
|
||
},
|
||
|
||
setHeading(heading) {
|
||
this._heading = heading;
|
||
this.redraw();
|
||
},
|
||
|
||
_updatePath() {
|
||
const { x, y } = this._point;
|
||
|
||
if (this._heading === "")
|
||
return CircleMarker.prototype._updatePath.call(this);
|
||
|
||
this.getElement().setAttributeNS(
|
||
null,
|
||
"transform",
|
||
`translate(${x},${y}) rotate(${this._heading})`,
|
||
);
|
||
|
||
const path = this._empty() ? "" : `M0,${3} L-4,${5} L0,${-5} L4,${5} z}`;
|
||
|
||
this._renderer._setPath(this, path);
|
||
},
|
||
});
|
||
|
||
function createMap(opts) {
|
||
const map = new M(opts.elId != null ? `map_${opts.elId}` : "map", opts);
|
||
|
||
const osm = new TileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||
maxZoom: 19,
|
||
});
|
||
|
||
if (opts.enableHybridLayer) {
|
||
const hybrid = new TileLayer(
|
||
"http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}",
|
||
{ maxZoom: 20, subdomains: ["mt0", "mt1", "mt2", "mt3"] },
|
||
);
|
||
|
||
new Control.Layers({ OSM: osm, Hybrid: hybrid }).addTo(map);
|
||
}
|
||
|
||
map.addLayer(osm);
|
||
|
||
return map;
|
||
}
|
||
|
||
export const SimpleMap = {
|
||
mounted() {
|
||
const $position = document.querySelector(`#position_${this.el.dataset.id}`);
|
||
|
||
const map = createMap({
|
||
elId: this.el.dataset.id,
|
||
zoomControl: !!this.el.dataset.zoom,
|
||
boxZoom: false,
|
||
doubleClickZoom: false,
|
||
keyboard: false,
|
||
scrollWheelZoom: false,
|
||
tap: false,
|
||
dragging: false,
|
||
touchZoom: false,
|
||
});
|
||
|
||
const isArrow = this.el.dataset.marker === "arrow";
|
||
const [lat, lng, heading] = $position.value.split(",");
|
||
|
||
const marker = isArrow
|
||
? new DirectionArrow([lat, lng], heading)
|
||
: new Marker([lat, lng], { icon });
|
||
|
||
map.setView([lat, lng], 17);
|
||
marker.addTo(map);
|
||
|
||
map.removeControl(map.zoomControl);
|
||
|
||
map.on("mouseover", function (e) {
|
||
map.addControl(map.zoomControl);
|
||
});
|
||
map.on("mouseout", function (e) {
|
||
map.removeControl(map.zoomControl);
|
||
});
|
||
|
||
if (isArrow) {
|
||
const setView = () => {
|
||
const [lat, lng, heading] = $position.value.split(",");
|
||
marker.setHeading(heading);
|
||
marker.setLatLng([lat, lng]);
|
||
map.setView([lat, lng], map.getZoom());
|
||
};
|
||
|
||
$position.addEventListener("change", setView);
|
||
}
|
||
},
|
||
};
|
||
|
||
export const TriggerChange = {
|
||
updated() {
|
||
this.el.dispatchEvent(new CustomEvent("change"));
|
||
},
|
||
};
|
||
|
||
import("leaflet-control-geocoder");
|
||
import("@geoman-io/leaflet-geoman-free");
|
||
|
||
export const Map = {
|
||
mounted() {
|
||
const geoFence = (name) =>
|
||
document.querySelector(`input[name='geo_fence[${name}]']`);
|
||
|
||
const $radius = geoFence("radius");
|
||
const $latitude = geoFence("latitude");
|
||
const $longitude = geoFence("longitude");
|
||
|
||
const location = new LatLng($latitude.value, $longitude.value);
|
||
|
||
const controlOpts = {
|
||
position: "topleft",
|
||
cutPolygon: false,
|
||
drawCircle: false,
|
||
drawCircleMarker: false,
|
||
drawMarker: false,
|
||
drawPolygon: false,
|
||
drawPolyline: false,
|
||
drawRectangle: false,
|
||
removalMode: false,
|
||
};
|
||
|
||
const editOpts = {
|
||
allowSelfIntersection: false,
|
||
preventMarkerRemoval: true,
|
||
};
|
||
|
||
const map = createMap({ enableHybridLayer: true });
|
||
map.setView(location, 17, { animate: false });
|
||
map.pm.setLang(LANG);
|
||
map.pm.addControls(controlOpts);
|
||
map.pm.enableGlobalEditMode(editOpts);
|
||
|
||
const circle = new Circle(location, { radius: $radius.value })
|
||
.addTo(map)
|
||
.on("pm:edit", (e) => {
|
||
const { lat, lng } = e.target.getLatLng();
|
||
const radius = Math.round(e.target.getRadius());
|
||
|
||
$radius.value = radius;
|
||
$latitude.value = lat;
|
||
$longitude.value = lng;
|
||
|
||
const mBox = map.getBounds();
|
||
const cBox = circle.getBounds();
|
||
const bounds = mBox.contains(cBox) ? mBox : cBox;
|
||
map.fitBounds(bounds);
|
||
});
|
||
|
||
new Control.geocoder({ defaultMarkGeocode: false })
|
||
.on("markgeocode", (e) => {
|
||
const { bbox, center } = e.geocode;
|
||
|
||
const poly = L.polygon([
|
||
bbox.getSouthEast(),
|
||
bbox.getNorthEast(),
|
||
bbox.getNorthWest(),
|
||
bbox.getSouthWest(),
|
||
]);
|
||
|
||
circle.setLatLng(center);
|
||
|
||
const lBox = poly.getBounds();
|
||
const cBox = circle.getBounds();
|
||
const bounds = cBox.contains(lBox) ? cBox : lBox;
|
||
|
||
map.fitBounds(bounds);
|
||
map.pm.enableGlobalEditMode();
|
||
|
||
const { lat, lng } = center;
|
||
$latitude.value = lat;
|
||
$longitude.value = lng;
|
||
})
|
||
.addTo(map);
|
||
|
||
map.fitBounds(circle.getBounds(), { animate: false });
|
||
},
|
||
};
|
||
|
||
export const Modal = {
|
||
_freeze() {
|
||
document.documentElement.classList.add("is-clipped");
|
||
},
|
||
|
||
_unfreeze() {
|
||
document.documentElement.classList.remove("is-clipped");
|
||
},
|
||
|
||
mounted() {
|
||
// assumption: 'is-active' is always added after the initial mount
|
||
},
|
||
|
||
updated() {
|
||
this.el.classList.contains("is-active") ? this._freeze() : this._unfreeze();
|
||
},
|
||
|
||
destroyed() {
|
||
this._unfreeze();
|
||
},
|
||
};
|
||
|
||
export const NumericInput = {
|
||
mounted() {
|
||
this.el.onkeypress = (evt) => {
|
||
const charCode = evt.which ? evt.which : evt.keyCode;
|
||
return !(charCode > 31 && (charCode < 48 || charCode > 57));
|
||
};
|
||
},
|
||
};
|