Skip to content

Commit

Permalink
Merge pull request #30 from ferviddigital/release/0.4.1
Browse files Browse the repository at this point in the history
Release/0.4.1
  • Loading branch information
roymckenzie authored Oct 23, 2023
2 parents b8d5be3 + a31d837 commit ea2ed98
Show file tree
Hide file tree
Showing 11 changed files with 790 additions and 324 deletions.
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.4.0] - 2023-10-117

## [0.4.1] - 2023-10-22

### Added
- Added Note view with an edit button
- Vital Summary chart shows high / low badge for specific measurement
- User can update owner name in Settings
- Introduced first typescript definition file

### Changed
- Mobile nav bar looks like traditional app navbar
- Update Signal Server URL in new edit view
- Updated packages

### Fixed


## [0.4.0] - 2023-10-17

### Added
- Measurements open in Vital and are highlighted on chart
Expand Down
877 changes: 619 additions & 258 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "healthrecord",
"private": true,
"version": "0.4.0",
"version": "0.4.1",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -24,8 +24,6 @@
"file-saver": "^2.0.5",
"number-to-words": "^1.2.4",
"pluralize": "^8.0.0",
"sass": "^1.66.1",
"vite-plugin-pwa": "^0.16.5",
"vue": "^3.3.4",
"vue-chartjs": "^5.2.0",
"vue-router": "^4.2.4",
Expand All @@ -40,7 +38,8 @@
"autoprefixer": "^10.4.15",
"postcss": "^8.4.29",
"tailwindcss": "^3.3.3",
"vite": "^4.4.5"
"vite": "^4.4.5",
"vite-plugin-pwa": "^0.16.5"
},
"prettier": {
"singleQuote": true,
Expand Down
35 changes: 35 additions & 0 deletions src/components/Interface/EditFields.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup lang="ts">
import HeaderTitleCenter from './HeaderTitleCenter.vue';
defineProps<{
fields: FormField[],
title: string
}>();
const runUpdateCallback = (event: FocusEvent, field: FormField) => {
if (!(event.target instanceof HTMLInputElement)) return;
const newValue = event.target.value
field.blurCallback(newValue)
}
</script>

<template>
<div>
<HeaderTitleCenter :title="title" />
<div class="p-4">
<div class="rounded-xl bg-white divide-y overflow-hidden">
<div v-for="field in fields">
<input
:type="field.type"
:name="field.name"
:placeholder="field.placeholder"
:value="field.currentValue"
class="border-none bg-none !ring-0 !p-3 !px-4 w-full"
:class="field.classes"
@blur="(event: FocusEvent) => runUpdateCallback(event, field)"
/>
</div>
</div>
</div>
</div>
</template>
2 changes: 1 addition & 1 deletion src/components/Interface/HeaderTitleCenter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const scrollToTop = () => {
<RouterLink class="text-indigo-500 justify-self-start" :to="backRoute">
<ChevronLeftIcon class="w-6 h-6 inline align-top" /> {{ backText }}
</RouterLink>
<h2 class="text-xl font-bold text-center" @click="scrollToTop">{{ title }}</h2>
<h2 class="text-xl font-bold text-center whitespace-nowrap" @click="scrollToTop">{{ title }}</h2>
<div class="grid grid-flow-col gap-3 justify-self-end">
<slot name="right"></slot>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ window.addEventListener('scroll', () => {
class="dash-layout grid grid-rows-[auto_min-content] sm:grid-rows-none sm:grid-flow-col sm:grid-cols-[min-content_auto] sm:min-h-0"
>
<header
class="main-header fixed sm:sticky grid grid-flow-col grid-cols-[auto_min-content] sm:grid-cols-none sm:grid-rows-[min-content_auto_min-content] gap-2 sm:gap-4 overflow-scroll sm:overflow-visible sm:min-h-[calc(100vh-2rem)] items-center sm:items-start sm:justify-normal order-last sm:order-none self-end sm:self-start p-4 py-2 sm:py-6 bottom-0 md:bottom-auto sm:mb-auto sm:mr-0 sm:ml-4 sm:top-4 right-0 left-0 sm:rounded-3xl bg-gray-900 text-white z-20"
class="main-header fixed sm:sticky grid grid-flow-col grid-cols-[auto_min-content] sm:grid-cols-none sm:grid-rows-[min-content_auto_min-content] gap-2 sm:gap-4 overflow-scroll sm:overflow-visible sm:min-h-[calc(100vh-2rem)] items-center sm:items-start sm:justify-normal order-last sm:order-none self-end sm:self-start p-4 py-2 sm:py-6 bottom-0 md:bottom-auto sm:mb-auto sm:mr-0 sm:ml-4 sm:mt-4 sm:top-4 right-0 left-0 sm:rounded-3xl bg-gray-900 text-white z-20"
>
<h2
class="app-title hidden sm:grid sm:grid-flow-col items-center self-start font-bold text-xl lg:mb-3 transition-all"
Expand Down
85 changes: 27 additions & 58 deletions src/components/Settings/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { ref } from 'vue';
import { Switch } from '@headlessui/vue';
import { peers, webrtcConnected } from '../../providers/webrtc';
import pluralize from 'pluralize';
import EditableContent from '../Interface/EditableContent.vue';
import { people } from '../../store/people';
import { vitals } from '../../store/vitals';
import { useRouter } from 'vue-router';
Expand All @@ -19,7 +18,6 @@ import HeaderTitleLeft from '../Interface/HeaderTitleLeft.vue';
const router = useRouter();
const passphraseModalOpen = ref(false);
const signalerUrlError = ref(false);
const downloadHealthRecordFile = (data) => {
const fileName = 'healthRecord-' + Date.now() + '.json';
Expand Down Expand Up @@ -53,38 +51,6 @@ const logout = async () => {
router.push({ name: 'Start' });
}
const validateSocketUrl = urlString => {
try {
const url = new URL(urlString);
return url.protocol === 'ws:' || url.protocol === 'wss:';
} catch (error) {
return false;
}
}
/**
* Update Record owner first and last name
* @param {string} newFullName
*/
const updateName = newFullName => {
const [firstName, lastName] = newFullName.split(' ');
record.value.user.firstName = firstName;
record.value.user.lastName = lastName;
}
/**
* Update Signal Server URL
* @param {string} newUrl
*/
const updateSignalServer = newUrl => {
if (validateSocketUrl(newUrl)) {
record.value.user.preferences.webRTC.signalerUrl = newUrl;
} else {
signalerUrlError.value = true;
}
}
// @ts-ignore
const appVersion = APP_VERSION;
</script>
Expand Down Expand Up @@ -120,7 +86,7 @@ const appVersion = APP_VERSION;
Record Details
</h3>
<div class="bg-white rounded-xl divide-y mb-10 overflow-hidden">
<section class="grid grid-flow-col gap-4 items-center p-4 py-3 pr-3 cursor-pointer hover:bg-gray-100">
<section @click="$router.push({ name: 'SettingsUserUpdate' })" class="grid grid-flow-col gap-4 items-center p-4 py-3 pr-3 cursor-pointer hover:bg-gray-100">
<h4>Owner</h4>
<span class="grid grid-flow-col gap-1 justify-self-end items-center text-gray-400">
{{ record.user.firstName + ' ' + record.user.lastName }}
Expand Down Expand Up @@ -186,32 +152,35 @@ const appVersion = APP_VERSION;
</section>
<section
v-if="record.user.preferences && record.user.preferences.webRTC.enabled"
class="grid grid-flow-row items-center p-4 py-3"
:key="4"
>
<span>
<span class="grid grid-flow-col items-start place-content-between">
<h4>Signal Server</h4>
<span
v-if="webrtcConnected"
class="text-xs text-right rounded-full bg-gray-200 p-1 px-3">
{{ peers > 0 ? pluralize('peer', peers, true) + ' connected' : 'Waiting for peers...' }}
<span
class="h-2 w-2 ml-1 inline-block bg-orange-300 rounded-full"
:class="{ '!bg-green-500' : peers > 0 }"
:title="peers > 0 ? pluralize('peer', peers, true) + ' connected' : 'Waiting for peers...'"
></span>
<section
class="grid grid-flow-row items-center p-4 py-3"
:key="4"
>
<span>
<span class="grid grid-flow-col items-start place-content-between">
<h4>Signal Server</h4>
<span
v-if="webrtcConnected"
class="text-xs text-right rounded-full bg-gray-200 p-1 px-3">
{{ peers > 0 ? pluralize('peer', peers, true) + ' connected' : 'Waiting for peers...' }}
<span
class="h-2 w-2 ml-1 inline-block bg-orange-300 rounded-full"
:class="{ '!bg-green-500' : peers > 0 }"
:title="peers > 0 ? pluralize('peer', peers, true) + ' connected' : 'Waiting for peers...'"
></span>
</span>
</span>
<p class="text-xs text-gray-400 mb-2 mt-2">HealthRecord uses a <a href="https://antmedia.io/webrtc-signaling-servers-everything-you-need-to-know/" target="_blank" class="underline">signal server</a> to identify your other devices to synchronize. Your health data is synchronized peer-to-peer and is never transmitted to the signal server. <a href="https://github.com/ferviddigital/y-webrtc-signaler" target="_blank" class="underline">Host your own signal server</a>.</p>
</span>
<p class="text-xs text-gray-400 mb-3 mt-2">HealthRecord uses a <a href="https://antmedia.io/webrtc-signaling-servers-everything-you-need-to-know/" target="_blank" class="underline">signal server</a> to identify your other devices to synchronize. Your health data is synchronized peer-to-peer and is never transmitted to the signal server. <a href="https://github.com/ferviddigital/y-webrtc-signaler" target="_blank" class="underline">Host your own signal server</a>.</p>
</span>
<span class="mb-1">
<EditableContent placeholder="wss://signalserver.com" type="url" :value="record.user.preferences.webRTC.signalerUrl" @updated="updateSignalServer" inputClasses="font-mono text-sm" />
<span
v-if="signalerUrlError"
class="block text-xs text-red-600 pt-1"
>Please try re-entering a valid WebSocket url.</span>
</span>
</section>
<section @click="$router.push({ name: 'SettingsSignalServerUpdate' })" class="grid grid-flow-col gap-4 items-center p-4 pr-3 cursor-pointer hover:bg-gray-100 border-t">
<h4>URL</h4>
<span class="grid grid-flow-col gap-1 justify-self-end items-center text-gray-400">
<span class="line-clamp-1 text-sm font-mono">{{ record.user.preferences.webRTC.signalerUrl }}</span>
<ChevronRightIcon class="w-5 h-5 text-gray-300" />
</span>
</section>
</section>
</TransitionGroup>
<h3 class="text-sm ml-4 mb-1 uppercase text-gray-500">
Expand Down
36 changes: 36 additions & 0 deletions src/components/Settings/SignalServerUpdate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script setup lang="ts">
import { record } from '../../store/record';
import EditFields from '../Interface/EditFields.vue';
const fields: FormField[] = [
{
name: 'signalServerUrl',
placeholder: 'wss://signalserver.com',
currentValue: record.value.user.preferences.webRTC.signalerUrl,
type: 'url',
classes: 'font-mono text-sm !p-4 !px-4',
blurCallback: (newValue) => updateSignalServer(newValue),
},
];
const validateSocketUrl = (urlString: string) => {
try {
const url = new URL(urlString);
return url.protocol === 'ws:' || url.protocol === 'wss:';
} catch (error) {
return false;
}
};
const updateSignalServer = (newUrl: string) => {
if (validateSocketUrl(newUrl) || newUrl.length === 0) {
record.value.user.preferences.webRTC.signalerUrl = newUrl;
} else {
alert('Signal Server URL is not valid.');
}
};
</script>

<template>
<EditFields title="Signal Server URL" :fields="fields" />
</template>
25 changes: 25 additions & 0 deletions src/components/Settings/UserUpdate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script setup lang="ts">
import { record } from '../../store/record';
import EditFields from '../Interface/EditFields.vue';
const fields: FormField[] = [
{
name: 'firstName',
placeholder: 'First name',
currentValue: record.value.user.firstName,
type: 'text',
blurCallback: (newValue) => record.value.user.firstName = newValue
},
{
name: 'lastName',
placeholder: 'Last name',
currentValue: record.value.user.lastName,
type: 'text',
blurCallback: (newValue) => record.value.user.lastName = newValue
},
];
</script>

<template>
<EditFields title="Owner" :fields="fields" />
</template>
8 changes: 8 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
interface FormField {
name: string;
type: string;
placeholder?: string;
currentValue?: string;
classes?: string;
blurCallback(newValue: string);
}
18 changes: 17 additions & 1 deletion src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ const PersonLogbook = () => import(/* webpackChunkName: "group-person" */ '../co
const PersonVitals = () => import(/* webpackChunkName: "group-person" */ '../components/Person/Vitals.vue');
const PersonVital = () => import(/* webpackChunkName: "group-person" */ '../components/Person/Vital.vue');
const PersonUpdate = () => import(/* webpackChunkName: "group-person" */ '../components/People/Update.vue');
const Settings = () => import('../components/Settings/Settings.vue');
const Settings = () => import(/* webpackChunkName: "group-settings" */ '../components/Settings/Settings.vue');
const SettingsUserUpdate = () => import(/* webpackChunkName: "group-settings" */ '../components/Settings/UserUpdate.vue');
const SettingsSignalServerUpdate = () => import(/* webpackChunkName: "group-settings" */ '../components/Settings/SignalServerUpdate.vue');

/** @type {import('vue-router').RouteRecordRaw[]} */
const routes = [
Expand Down Expand Up @@ -264,6 +266,20 @@ const routes = [
components: {
main: Vitals
}
},
{
path: 'user',
name: 'SettingsUserUpdate',
components: {
main: SettingsUserUpdate
}
},
{
path: 'signal-server',
name: 'SettingsSignalServerUpdate',
components: {
main: SettingsSignalServerUpdate
}
}
]
},
Expand Down

0 comments on commit ea2ed98

Please sign in to comment.