Add developer toolkit UI component

The commit adds a new a UI component that's enabled in development mode.
This component, initially, provides a button that wen clicked, logs all
the script and category names to the console. It helps revising names
used throughout the application.

By having this component in a conditionally rendered component, it's
excluded from the production builds.
This commit is contained in:
undergroundwires
2023-10-07 15:14:53 +02:00
parent 286295128d
commit 2147eae687
4 changed files with 114 additions and 2 deletions

View File

@@ -7,11 +7,12 @@
<TheCodeButtons class="app__row app__code-buttons" /> <TheCodeButtons class="app__row app__code-buttons" />
<TheFooter /> <TheFooter />
</div> </div>
<OptionalDevToolkit />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineAsyncComponent, defineComponent } from 'vue';
import TheHeader from '@/presentation/components/TheHeader.vue'; import TheHeader from '@/presentation/components/TheHeader.vue';
import TheFooter from '@/presentation/components/TheFooter/TheFooter.vue'; import TheFooter from '@/presentation/components/TheFooter/TheFooter.vue';
import TheCodeButtons from '@/presentation/components/Code/CodeButtons/TheCodeButtons.vue'; import TheCodeButtons from '@/presentation/components/Code/CodeButtons/TheCodeButtons.vue';
@@ -22,6 +23,10 @@ import { provideDependencies } from '../bootstrapping/DependencyProvider';
const singletonAppContext = await buildContext(); const singletonAppContext = await buildContext();
const OptionalDevToolkit = process.env.NODE_ENV !== 'production'
? defineAsyncComponent(() => import('@/presentation/components/DevToolkit/DevToolkit.vue'))
: null;
export default defineComponent({ export default defineComponent({
components: { components: {
TheHeader, TheHeader,
@@ -29,6 +34,7 @@ export default defineComponent({
TheScriptArea, TheScriptArea,
TheSearchBar, TheSearchBar,
TheFooter, TheFooter,
OptionalDevToolkit,
}, },
setup() { setup() {
provideDependencies(singletonAppContext); // In Vue 3.0 we can move it to main.ts provideDependencies(singletonAppContext); // In Vue 3.0 we can move it to main.ts
@@ -59,5 +65,4 @@ export default defineComponent({
} }
} }
} }
</style> </style>

View File

@@ -0,0 +1,71 @@
<template>
<div class="dev-toolkit">
<div class="title">
Tools
</div>
<hr />
<button
v-for="action in devActions"
@click="action.handler"
:key="action.name"
type="button">
{{ action.name }}
</button>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { dumpNames } from './DumpNames';
export default defineComponent({
setup() {
const devActions: readonly DevAction[] = [
{
name: 'Log script/category names',
handler: async () => {
const names = await dumpNames();
console.log(names);
},
},
];
return {
devActions,
};
},
});
interface DevAction {
readonly name: string;
readonly handler: () => void | Promise<void>;
}
</script>
<style scoped lang="scss">
@use "@/presentation/assets/styles/main" as *;
.dev-toolkit {
position: fixed;
top: 0;
right: 0;
background-color: rgba($color-on-surface, 0.5);
color: $color-on-primary;
padding: 10px;
z-index: 10000;
.title {
font-weight: bold;
text-align: center;
}
button {
display: block;
margin-bottom: 10px;
padding: 5px 10px;
background-color: $color-primary;
color: $color-on-primary;
border: none;
cursor: pointer;
}
}
</style>

View File

@@ -0,0 +1,35 @@
import { IApplication } from '@/domain/IApplication';
import { ApplicationFactory } from '@/application/ApplicationFactory';
export async function dumpNames(): Promise<string> {
const application = await ApplicationFactory.Current.getApp();
const names = collectNames(application);
const output = names.join('\n');
return output;
}
function collectNames(application: IApplication): string[] {
const { collections } = application;
const allNames = [
...collections.flatMap((collection) => collection.getAllCategories().map((c) => c.name)),
...collections.flatMap((collection) => collection.getAllScripts().map((c) => c.name)),
];
const uniqueNames = [...new Set(allNames)];
return shuffle(uniqueNames);
}
/*
Shuffle an array of strings, returning a new array with elements in random order.
Uses the Fisher-Yates (or Durstenfeld) algorithm.
*/
function shuffle(array: readonly string[]): string[] {
const shuffledArray = [...array];
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
}
return shuffledArray;
}

View File

@@ -22,6 +22,7 @@ export default defineComponent({
}; };
}, },
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">