Skip to content

Commit

Permalink
Migrate to TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
dnknth committed Mar 7, 2024
1 parent e6de333 commit d2ec7ed
Show file tree
Hide file tree
Showing 45 changed files with 2,209 additions and 1,028 deletions.
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"Vue.volar",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"bradlc.vscode-tailwindcss"
]
}
2 changes: 1 addition & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def _entry(res: Tuple[str, Any]) -> Dict[str, Any]:
for a in must_attrs],
'aux': sorted(aux - ocs),
'binary': sorted(binary),
'hints': {},
'hints': {}, # FIXME obsolete?
'autoFilled': [],
}
}
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<meta name="theme-color" content="aliceblue" />
<link rel="icon" href="/favicon.ico">
<script type="module" src="/src/main.js"></script>
<script type="module" src="/src/main.ts"></script>

<title>Directory</title>
</head>
Expand Down
1,637 changes: 1,293 additions & 344 deletions package-lock.json

Large diffs are not rendered by default.

49 changes: 40 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,43 @@
"name": "ldap-ui",
"version": "0.5.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"lint": "eslint src",
"test": "vitest",
"build": "vite build",
"build": "run-s type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build --force",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/",
"test": "vitest",
"tw-config": "tailwind-config-viewer -o"
},
"dependencies": {
"@vueuse/components": "^10.2.1",
"@vueuse/core": "^10.2.1",
"font-awesome": "^4.7.0",
"vue": "^3.2.37"
"vue": "^3.4.15"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4",
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node20": "^20.1.2",
"@types/node": "^20.11.10",
"@vitejs/plugin-vue": "^5.0.3",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.14",
"eslint": "latest",
"eslint-plugin-vue": "^9.15.1",
"eslint-plugin-vue": "^9.17.0",
"tailwind-config-viewer": "^1.7.2",
"tailwindcss": "^3.3",
"vite": "^4",
"vite-plugin-compression": "^0.5.0",
"npm-run-all2": "^6.1.1",
"prettier": "^3.0.3",
"typescript": "~5.3.0",
"vite": "^5.0.11",
"vue-tsc": "^1.8.27",
"vite-plugin-compression": "^0.5.1",
"vitest": "^0.34.2"
},
"eslintConfig": {
Expand All @@ -35,10 +49,27 @@
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-essential"
"plugin:vue/vue3-essential",
"@vue/typescript/recommended"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"vue/no-unused-vars": "error",
"vue/multi-word-component-names": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"args": "all",
"argsIgnorePattern": "^_",
"caughtErrors": "all",
"caughtErrorsIgnorePattern": "^_",
"destructuredArrayIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"ignoreRestSiblings": true
}
]
}
},
"browserslist": [
Expand Down
File renamed without changes.
54 changes: 31 additions & 23 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,46 @@
</div>
</template>

<script setup>
import { onMounted, provide, readonly, ref, watch } from 'vue';
<script setup lang="ts">
import { onMounted, provide, ref, watch } from 'vue';
import AttributeCard from './components/schema/AttributeCard.vue';
import EntryEditor from './components/editor/EntryEditor.vue';
import { LdapSchema } from './components/schema/schema.js';
import { LdapSchema } from './components/schema/schema';
import LdifImportDialog from './components/LdifImportDialog.vue';
import NavBar from './components/NavBar.vue';
import ObjectClassCard from './components/schema/ObjectClassCard.vue';
import { request } from './request.js';
import type { Provided } from './components/Provided';
import { request } from './request';
import type { Options } from './request';
import TreeView from './components/TreeView.vue';
interface Error {
counter: number;
cssClass: string;
msg: string
}
const
// Authentication
user = ref(null), // logged in user
baseDn = ref(null),
user = ref<string>(), // logged in user
baseDn = ref<string>(),
// Components
treeOpen = ref(true), // Is the tree visible?
activeDn = ref(null), // currently active DN in the editor
modal = ref(null), // modal popup
treeOpen = ref(true), // Is the tree visible?
activeDn = ref<string>(), // currently active DN in the editor
modal = ref<string>(), // modal popup
// Alerts
error = ref(null), // status alert
error = ref<Error>(), // status alert
// LDAP schema
schema = ref(null),
oc = ref(null), // objectClass info in side panel
attr = ref(null), // attribute info in side panel
schema = ref<LdapSchema>(),
oc = ref<string>(), // objectClass info in side panel
attr = ref<string>(), // attribute info in side panel
// Helpers for components
provided = {
get schema() { return readonly(schema.value); },
provided: Provided = {
get schema() { return schema.value; },
showInfo: showInfo,
showWarning: showWarning,
xhr: xhr,
Expand All @@ -86,7 +94,7 @@
watch(attr, (a) => { if (a) oc.value = undefined; });
watch(oc, (o) => { if (o) attr.value = undefined; });
function xhr(options) {
function xhr(options: Options) {
if (options.data && !options.binary) {
if (!options.headers) options.headers = {}
if (!options.headers['Content-Type']) {
Expand All @@ -99,24 +107,24 @@
}
// Display an info popup
function showInfo(msg) {
function showInfo(msg: string) {
error.value = { counter: 5, cssClass: 'bg-emerald-300', msg: '' + msg };
setTimeout(() => { error.value = null; }, 5000);
setTimeout(() => { error.value = undefined; }, 5000);
}
// Flash a warning popup
function showWarning(msg) {
function showWarning(msg: string) {
error.value = { counter: 10, cssClass: 'bg-amber-200', msg: '⚠️ ' + msg };
setTimeout(() => { error.value = null; }, 10000);
setTimeout(() => { error.value = undefined; }, 10000);
}
// Report an error
function showError(msg) {
function showError(msg: string) {
error.value = { counter: 60, cssClass: 'bg-red-300', msg: '' + msg };
setTimeout(() => { error.value = null; }, 60000);
setTimeout(() => { error.value = undefined; }, 60000);
}
function showException(msg) {
function showException(msg: string) {
const span = document.createElement('span');
span.innerHTML = msg.replace("\n", " ");
const titles = span.getElementsByTagName('title');
Expand Down
19 changes: 10 additions & 9 deletions src/components/LdifImportDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,32 @@
</modal>
</template>

<script setup>
<script setup lang="ts">
import { inject, ref } from 'vue';
import Modal from './ui/Modal.vue';
import type { Provided } from './Provided';
const
app = inject('app'),
app = inject<Provided>('app'),
ldifData = ref(''),
ldifFile = ref(null),
emit = defineEmits(['ok', 'update:modal']);
defineProps({ modal: String });
function init() {
ldifData.value = '';
ldifFile.value = null;
}
// Load LDIF from file
function upload(evt) {
const file = evt.target.files[0],
function upload(evt: Event) {
const target = evt.target as HTMLInputElement,
files = target.files as FileList,
file = files[0],
reader = new FileReader();
reader.onload = function() {
ldifData.value = reader.result;
evt.target.value = null;
ldifData.value = reader.result as string;
target.value = '';
}
reader.readAsText(file);
}
Expand All @@ -40,7 +41,7 @@
if (!ldifData.value) return;
emit('update:modal');
const data = await app.xhr({
const data = await app?.xhr({
url: 'api/ldif',
method: 'POST',
data: ldifData.value,
Expand Down
23 changes: 12 additions & 11 deletions src/components/NavBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
<span class="cursor-pointer" @click="emit('show-modal', 'ldif-import')">Import…</span>

<dropdown-menu title="Schema">
<li role="menuitem" v-for="obj in app.schema.ObjectClass.values"
:key="obj.name" @click="emit('show-oc', obj.name)">
{{ obj.name }}
<li role="menuitem" v-for="key in app?.schema?.objectClasses.keys()"
:key="key" @click="emit('show-oc', key)">
{{ key }}
</li>
</dropdown-menu>

<form @submit.prevent="search">
<input class="glyph px-2 py-1 rounded border border-front/80 outline-none text-front dark:bg-gray-800/80"
autofocus :placeholder="' \uf002'" name="q" @focusin="input.select();" accesskey="k"
<input class="glyph px-2 py-1 rounded focus:border focus:border-front/80 outline-none text-front dark:bg-gray-800/80"
autofocus :placeholder="' \uf002'" name="q" @focusin="input?.select();" accesskey="k"
@keyup.esc="query = '';" id="nav-search" ref="input" />
<search-results for="nav-search" @select-dn="query = ''; emit('select-dn', $event);"
:shorten="baseDn" :query="query" />
Expand All @@ -31,18 +31,19 @@
</nav>
</template>

<script setup>
<script setup lang="ts">
import { inject, nextTick, ref } from 'vue';
import DropdownMenu from './ui/DropdownMenu.vue';
import type { Provided } from './Provided';
import NodeLabel from './NodeLabel.vue';
import SearchResults from './SearchResults.vue';
const
app = inject('app'),
input = ref(null),
app = inject<Provided>('app'),
input = ref<HTMLInputElement | null>(null),
query = ref(''),
collapsed = ref(false),
emit = defineEmits(['select-dn', 'show-modal', 'show-oc']);
emit = defineEmits(['select-dn', 'show-modal', 'show-oc', 'update:treeOpen']);
defineProps({
baseDn: String,
Expand All @@ -52,6 +53,6 @@
function search() {
query.value = '';
nextTick(() => { query.value = input.value.value; });
nextTick(() => { query.value = input?.value?.value || ''; });
}
</script>
7 changes: 4 additions & 3 deletions src/components/NodeLabel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
</span>
</template>

<script setup>
<script setup lang="ts">
import { computed } from 'vue';
const props = defineProps({
dn: String,
oc: String,
}),
icons = { // OC -> icon mapping
icons : {[key: string]: string} = { // OC -> icon mapping
account: 'user',
groupOfNames: 'users',
groupOfURLs: 'users',
Expand All @@ -30,7 +30,8 @@
},
icon = computed(() => // Get the icon for an OC
' fa-' + icons[props.oc] || 'question'),
props.oc ? ' fa-' + (icons[props.oc] || 'question')
: 'fa-question'),
// Shorten a DN for readability
label = computed(() => (props.dn || '').split(',')[0]
Expand Down
9 changes: 9 additions & 0 deletions src/components/Provided.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Options } from '../request';
import type { LdapSchema } from './schema/schema';

export interface Provided {
readonly schema?: LdapSchema;
showInfo: (msg: string) => void;
showWarning: (msg: string) => void;
xhr: (options: Options) => Promise<unknown>;
}
Loading

0 comments on commit d2ec7ed

Please sign in to comment.