Skip to content

Commit

Permalink
Improve loading of items in the admin panel
Browse files Browse the repository at this point in the history
  • Loading branch information
petterhj committed Jan 15, 2025
1 parent c9818a4 commit f2c4d8f
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 55 deletions.
55 changes: 38 additions & 17 deletions src/store/admin.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,66 @@
import { computed } from 'vue';
import { defineStore } from 'pinia';
import { useCollection } from 'vuefire';
import { collection, orderBy, query, where } from 'firebase/firestore';
import { collection, orderBy, query } from 'firebase/firestore';
import { db } from '@/config/firebaseConfig';
import { useAuthStore } from '@/store/auth';
import { useTrackerStore } from '@/store/tracker';

export const useAdminStore = defineStore('admin', () => {
const authStore = useAuthStore();
const trackerStore = useTrackerStore();

// Users
const users = useCollection(
computed(
() =>
authStore.isLoggedIn &&
query(collection(db, 'users'), orderBy('displayName', 'asc'))
authStore.isAdmin && query(collection(db, 'users'), orderBy('displayName', 'asc'))
),
{ ssrKey: 'users' }
);

// Items
const organizations = computed(() => trackerStore.organizations);
const itemQuery = (collectionPath) =>
authStore.isAdmin &&
query(
collection(db, collectionPath),
orderBy('archived', 'asc'),
orderBy('name', 'asc')
);

const departments = useCollection(
computed(
() =>
authStore.isLoggedIn &&
query(
collection(db, 'departments'),
where('archived', '==', false),
orderBy('name', 'asc')
)
),
{ ssrKey: 'departments' }
const isItemAdmin = (item) => {
if (authStore.isSuperAdmin) {
return true;
}
if (item.organization) {
return authStore.user.admin.includes(item.organization.split('/')[1]);
}
return authStore.user.admin.includes(item.id);
};

const filterItems = (items) => items.filter((i) => isItemAdmin(i));

const _organizations = useCollection(
computed(() => itemQuery('organizations')),
{ maxRefDepth: 0, ssrKey: 'organizations' }
);
const organizations = computed(() => filterItems(_organizations.value));

const _departments = useCollection(
computed(() => itemQuery('departments')),
{ maxRefDepth: 0, ssrKey: 'departments' }
);
const departments = computed(() => filterItems(_departments.value));

const _products = useCollection(
computed(() => itemQuery('products')),
{ maxRefDepth: 0, ssrKey: 'products' }
);
const products = computed(() => filterItems(_products.value));

return {
users,
organizations,
departments,
products,
};
});

Expand Down
2 changes: 1 addition & 1 deletion src/views/Admin/CreateDepartment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const breadcrumbs = computed(() => [
const organizationOptions = computed(() =>
organizations.value
.filter((o) => isSuperAdmin.value || user.value.admin.includes(o.id))
.filter((o) => !o.archived && (isSuperAdmin.value || user.value.admin.includes(o.id)))
.map(({ id, name }) => ({ id, name }))
);
Expand Down
2 changes: 1 addition & 1 deletion src/views/Admin/CreateProduct.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const breadcrumbs = computed(() => [
const departmentOptions = computed(() =>
departments.value
.filter((o) => isSuperAdmin.value || user.value.admin.includes(o.id))
.filter((d) => !d.archived && (isSuperAdmin.value || user.value.admin.includes(d.id)))
.map(({ id, name, organization }) => ({ id, name, organization_id: organization.id }))
);
Expand Down
9 changes: 4 additions & 5 deletions src/views/Admin/components/AdminUsers.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<script setup>
import { computed, ref } from 'vue';
import { useCollection } from 'vuefire';
import { collection, query } from 'firebase/firestore';
import { ref } from 'vue';
import { useFuse } from '@vueuse/integrations/useFuse';
import { db } from '@/config/firebaseConfig';
import { PktButton } from '@oslokommune/punkt-vue';
import { storeToRefs } from 'pinia';
import { useAdminStore } from '@/store/admin';
import isAdmin from '@/util/user';
import AddUsers from './AddUsers.vue';
import EditUser from './EditUser.vue';
const users = useCollection(computed(() => query(collection(db, 'users'))));
const { users } = storeToRefs(useAdminStore());
const userQuery = ref('');
const selectedUser = ref(null);
Expand Down
52 changes: 21 additions & 31 deletions src/views/Admin/components/ItemList.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<script setup>
import { computed, ref } from 'vue';
import { useCollection } from 'vuefire';
import { collection, orderBy, query, where } from 'firebase/firestore';
import { storeToRefs } from 'pinia';
import { useFuse } from '@vueuse/integrations/useFuse';
import { db } from '@/config/firebaseConfig';
import { useAuthStore } from '@/store/auth';
import { useAdminStore } from '@/store/admin';
import ArchivedItemModal from './ArchivedItemModal.vue';
const props = defineProps({
Expand All @@ -21,7 +19,8 @@ const props = defineProps({
},
});
const { user, isSuperAdmin } = storeToRefs(useAuthStore());
const { isSuperAdmin } = storeToRefs(useAuthStore());
const { organizations, departments, products } = storeToRefs(useAdminStore());
const templateConfig = {
organizations: {
Expand All @@ -47,35 +46,24 @@ const templateConfig = {
},
}[props.collection];
const items = useCollection(
computed(() =>
query(
collection(db, props.collection),
where('archived', 'in', [false, props.includeArchived]),
orderBy('archived', 'asc'),
orderBy('slug', 'asc')
)
),
{ ssrKey: `items_${props.collection}` }
);
const filteredItems = computed(() => {
if (isSuperAdmin.value) {
// Return all items for super admins
return items.value;
}
const items = computed(() => {
let _items = [];
if (props.collection === 'organizations') {
// Return organizations of which the user is an admin
return items.value.filter((i) => user.value.admin.includes(i.id));
_items = organizations.value;
} else if (props.collection === 'departments') {
_items = departments.value;
} else if (props.collection === 'products') {
_items = products.value;
}
// Return items where the user is an admin of the parent organization
return items.value.filter((i) => user.value.admin.includes(i.organization.id));
return _items.filter(
(i) => i.slug && [false, props.includeArchived].includes(i.archived)
);
});
const selectedItem = ref(null);
const itemQuery = ref('');
const { results: searchResults } = useFuse(itemQuery, filteredItems, {
const { results: searchResults } = useFuse(itemQuery, items, {
fuseOptions: {
threshold: 0.5,
keys: [
Expand All @@ -92,6 +80,10 @@ const { results: searchResults } = useFuse(itemQuery, filteredItems, {
matchAllWhenSearchEmpty: true,
});
const canCreateItem = computed(
() => isSuperAdmin.value || props.collection !== 'organizations'
);
const itemRoute = (slug) => ({
name: 'ItemAbout',
params: { slug },
Expand All @@ -104,14 +96,12 @@ const itemRoute = (slug) => ({
<h2 class="title-2">{{ $t(templateConfig.title) }}</h2>

<div class="col">
<div v-if="filteredItems.length > 3" class="search">
<div v-if="items.length > 3" class="search">
<input
v-model="itemQuery"
class="pkt-input pkt-input--fullwidth"
type="text"
:placeholder="
$t(templateConfig.queryPlaceholder, { count: filteredItems.length })
"
:placeholder="$t(templateConfig.queryPlaceholder, { count: items.length })"
/>
</div>

Expand All @@ -135,7 +125,7 @@ const itemRoute = (slug) => ({
</div>
</div>

<div v-if="isSuperAdmin" class="col__footer">
<div v-if="canCreateItem" class="col__footer">
<RouterLink
class="pkt-btn pkt-btn--secondary pkt-btn--icon-left"
:to="templateConfig.createRoute"
Expand Down

0 comments on commit f2c4d8f

Please sign in to comment.