Implement info view

This commit is contained in:
Johannes Zellner
2025-02-20 16:12:36 +01:00
parent 3647f3130f
commit 26e8eb8c11
4 changed files with 153 additions and 12 deletions

View File

@@ -1,16 +1,145 @@
<script setup>
import { onMounted } from 'vue';
import { onMounted, ref, useTemplateRef } from 'vue';
import { Button } from 'pankow';
import { prettyDate } from 'pankow/utils';
import { marked } from 'marked';
import AppsModel from '../../models/AppsModel.js';
const appsModel = AppsModel.create();
const props = defineProps([ 'app' ]);
const emit = defineEmits([ 'changed' ]);
const id = ref('');
const notesTextarea = useTemplateRef('notesTextarea');
const showDoneChecklist = ref(false);
const hasOldChecklist = ref(false);
const checklist = ref([]);
const manifest = ref({});
const editing = ref(false);
const busy = ref(false);
const placeholder = 'Add admin notes here...';
const noteContent = ref('');
async function onAckChecklistItem(item, key) {
// TODO
}
async function onSubmit() {
busy.value = true;
// skip saving if unchanged from postInstall
if (noteContent.value === props.app.manifest.postInstallMessage) {
busy.value = false;
editing.value = false;
return;
}
const [error] = await appsModel.configure(id.value, 'notes', { notes: noteContent.value });
if (error) {
busy.value = false;
return console.error(error);
}
// let main view know about this
emit('changed');
editing.value = false;
busy.value = false;
}
function onEdit() {
editing.value = true;
setTimeout(() => notesTextarea.value.focus(), 200);
}
function onDismiss() {
editing.value = false;
noteContent.value = props.app.notes === null ? props.app.manifest.postInstallMessage : props.app.notes;
}
onMounted(() => {
console.log(props.app)
const app = props.app;
manifest.value = app.manifest || {};
id.value = app.id;
checklist.value = app.checklist;
hasOldChecklist.value = !!Object.keys(app.checklist).find((k) => { return app.checklist[k].acknowledged; });
noteContent.value = app.notes === null ? app.manifest.postInstallMessage : app.notes;
editing.value = false;
busy.value = false;
});
</script>
<template>
<div>
Info {{ app.id }}
<label class="control-label">{{ $t('app.updates.info.title') }}</label>
<div class="actionable" @click="info.showDoneChecklist = true" v-show="hasOldChecklist && !showDoneChecklist">Show Checklist</div>
<div class="actionable" @click="info.showDoneChecklist = false" v-show="showDoneChecklist">Hide Checklist</div>
<div v-for="(item, key) in checklist" :key="key">
<div class="checklist-item" v-if="!item.acknowledged">
<span v-html="marked.parse(item.message)"></span>
<button class="btn btn-xs btn-default" style="margin-left: 10px;" @click="onAckChecklistItem(item, key)">Done</button>
</div>
</div>
<div v-for="(item, key) in checklist" :key="key" v-show="showDoneChecklist">
<div class="checklist-item checklist-item-acknowledged" v-if="item.acknowledged">
<span v-html="marked.parse(item.message)"></span>
<span class="text-muted text-small">{{ item.changedBy }} {{ prettyDate(item.changedAt) }}</span>
</div>
</div>
<div style="margin-top: 10px"></div>
<div class="info-row">
<div class="info-label">{{ $t('app.updates.info.description') }}</div>
<div class="info-value" v-if="app.appStoreId">{{ manifest.title }} {{ app.upstreamVersion }}</div>
<div class="info-value" v-else>{{ manifest.dockerImage }}</div>
</div>
<div class="info-row">
<div class="info-label">{{ $t('app.updates.info.appId') }}</div>
<div class="info-value">{{ app.id }}</div>
</div>
<div class="info-row">
<div class="info-label">{{ $t('app.updates.info.packageVersion') }}</div>
<div class="info-value" v-if="app.appStoreId"><a :href="`/#/appstore/${manifest.id}?version=${manifest.version}`">{{ manifest.id }}@{{ manifest.version }}</a></div>
<div class="info-value" v-else>{{ manifest.version }}</div>
</div>
<div class="info-row">
<div class="info-label">{{ $t('app.updates.info.installedAt') }}</div>
<div class="info-value">{{ prettyDate(app.creationTime) }}</div>
</div>
<div class="info-row">
<div class="info-label">{{ $t('app.updates.info.lastUpdated') }}</div>
<div class="info-value">{{ prettyDate(app.updateTime) }}</div>
</div>
<br/>
<p>
<label class="control-label">{{ $t('app.info.notes.title') }}</label><i v-show="!editing" class="info-edit-indicator fa fa-pencil-alt" @click="onEdit()"></i>
</p>
<div>
<div v-show="!editing">
<div v-if="noteContent" v-html="marked.parse(noteContent)"></div>
<div v-else class="text-muted hand" @click="onEdit()">{{ placeholder }}</div>
</div>
<div v-show="editing">
<textarea ref="notesTextarea" style="white-space: pre-wrap; margin-bottom: 5px; width: 100%" v-model="noteContent" rows="10"></textarea>
<div style="display: flex; gap: 5px">
<Button secondary @click="onDismiss()" v-show="!busy">{{ $t('main.dialog.cancel') }}</Button>
<Button @click="onSubmit()" :disabled="busy" :loading="busy">{{ $t('app.display.saveAction') }}</Button>
</div>
</div>
</div>
</div>
</template>