Browse Source

Feature: Mobile - Add localized absolute and relative date/time output/component.

Martin Gruner 3 years ago
parent
commit
709dfb4281

+ 1 - 0
.storybook/preview.ts

@@ -1,5 +1,6 @@
 // Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
 
+import '@common/initializer/translatableMarker'
 import initializeGlobalComponents from '@common/initializer/globalComponents'
 import '@common/styles/main.css'
 import { i18n } from '@common/utils/i18n'

+ 4 - 2
app/frontend/apps/mobile/components/ticket/TicketList.vue

@@ -20,6 +20,7 @@
         </span>
       </th>
       <th>Customer</th>
+      <th>Created</th>
     </thead>
     <tbody>
       <tr
@@ -34,11 +35,12 @@
         <td>
           {{ ticket?.customer.firstname }} {{ ticket?.customer.lastname }}
         </td>
+        <td>
+          <CommonDateTime v-bind:date-time="ticket?.createdAt" />
+        </td>
       </tr>
     </tbody>
   </table>
-  {{ orderBy }}
-  {{ orderDirection }}
   <p v-if="pagination.hasNextPage">
     <a v-on:click="pagination.fetchNextPage()">Load more...</a>
   </p>

+ 2 - 0
app/frontend/apps/mobile/graphql/api.ts

@@ -33,6 +33,8 @@ export const TicketsByOverviewDocument = gql`
         id
         number
         title
+        createdAt
+        updatedAt
         owner {
           firstname
           lastname

+ 2 - 0
app/frontend/apps/mobile/graphql/queries/ticketsByOverviews.graphql

@@ -18,6 +18,8 @@ query ticketsByOverview(
         id
         number
         title
+        createdAt
+        updatedAt
         owner {
           firstname
           lastname

+ 2 - 1
app/frontend/apps/mobile/main.ts

@@ -1,6 +1,7 @@
 // Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
 
 import { createApp } from 'vue'
+import '@common/initializer/translatableMarker'
 import App from '@mobile/App.vue'
 import {
   DefaultApolloClient,
@@ -14,7 +15,7 @@ import initializeStoreSubscriptions from '@common/initializer/storeSubscriptions
 import initializeRouter from '@common/router/index'
 import initializeGlobalComponents from '@common/initializer/globalComponents'
 import routes from '@mobile/router'
-import useApplicationConfigStore from '@common//stores/application/config'
+import useApplicationConfigStore from '@common/stores/application/config'
 import { i18n } from '@common/utils/i18n'
 import useLocaleStore from '@common/stores/locale'
 import useSessionUserStore from '@common/stores/session/user'

+ 1 - 1
app/frontend/apps/mobile/views/Home.vue

@@ -76,7 +76,7 @@ const refetchConfig = async (): Promise<void> => {
 }
 
 const fetchCurrentUser = () => {
-  const { result } = useCurrentUserQuery({ fetchPolicy: 'no-cache' })
+  useCurrentUserQuery({ fetchPolicy: 'no-cache' })
 }
 
 const goToTickets = () => {

+ 35 - 0
app/frontend/common/components/common/CommonDateTime.vue

@@ -0,0 +1,35 @@
+<!-- Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/ -->
+
+<template>
+  <span v-if="outputFormat === 'absolute'">{{ i18n.dateTime(dateTime) }}</span>
+  <span v-else v-bind:title="i18n.dateTime(dateTime)">{{
+    i18n.relativeDateTime(dateTime)
+  }}</span>
+</template>
+
+<script setup lang="ts">
+import useApplicationConfigStore from '@common/stores/application/config'
+import { computed, ComputedRef } from 'vue'
+
+type Format = 'configured' | 'absolute' | 'relative'
+type OutputFormat = Exclude<Format, 'configured'>
+
+interface Props {
+  dateTime: string
+  format?: Format
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  format: 'configured',
+})
+
+const configStore = useApplicationConfigStore()
+
+const outputFormat: ComputedRef<OutputFormat> = computed(() => {
+  if (props.format !== 'configured') return props.format
+
+  return configStore.value.pretty_date_format === 'relative'
+    ? 'relative'
+    : 'absolute'
+})
+</script>

+ 1 - 1
app/frontend/common/graphql/types.ts

@@ -523,7 +523,7 @@ export type TicketsByOverviewQueryVariables = Exact<{
 }>;
 
 
-export type TicketsByOverviewQuery = { __typename?: 'Queries', ticketsByOverview: { __typename?: 'TicketConnection', totalCount: number, edges?: Array<{ __typename?: 'TicketEdge', cursor: string, node?: { __typename?: 'Ticket', id: string, number: string, title: string, owner: { __typename?: 'User', firstname?: string | null | undefined, lastname?: string | null | undefined }, customer: { __typename?: 'User', firstname?: string | null | undefined, lastname?: string | null | undefined }, organization?: { __typename?: 'Organization', name: string } | null | undefined, state: { __typename?: 'TicketState', name: string, stateTypeName: string }, group: { __typename?: 'Group', name: string }, priority: { __typename?: 'TicketPriority', name: string }, objectAttributeValues: Array<{ __typename?: 'ObjectAttributeValue', value?: string | null | undefined, attribute: { __typename?: 'ObjectManagerAttribute', name: string, display: string, dataType: string, dataOption?: any | null | undefined, screens?: any | null | undefined, editable: boolean, active: boolean } }> } | null | undefined } | null | undefined> | null | undefined, pageInfo: { __typename?: 'PageInfo', endCursor?: string | null | undefined, hasNextPage: boolean } } };
+export type TicketsByOverviewQuery = { __typename?: 'Queries', ticketsByOverview: { __typename?: 'TicketConnection', totalCount: number, edges?: Array<{ __typename?: 'TicketEdge', cursor: string, node?: { __typename?: 'Ticket', id: string, number: string, title: string, createdAt: any, updatedAt: any, owner: { __typename?: 'User', firstname?: string | null | undefined, lastname?: string | null | undefined }, customer: { __typename?: 'User', firstname?: string | null | undefined, lastname?: string | null | undefined }, organization?: { __typename?: 'Organization', name: string } | null | undefined, state: { __typename?: 'TicketState', name: string, stateTypeName: string }, group: { __typename?: 'Group', name: string }, priority: { __typename?: 'TicketPriority', name: string }, objectAttributeValues: Array<{ __typename?: 'ObjectAttributeValue', value?: string | null | undefined, attribute: { __typename?: 'ObjectManagerAttribute', name: string, display: string, dataType: string, dataOption?: any | null | undefined, screens?: any | null | undefined, editable: boolean, active: boolean } }> } | null | undefined } | null | undefined> | null | undefined, pageInfo: { __typename?: 'PageInfo', endCursor?: string | null | undefined, hasNextPage: boolean } } };
 
 export type ObjectAttributeValuesFragment = { __typename?: 'ObjectAttributeValue', value?: string | null | undefined, attribute: { __typename?: 'ObjectManagerAttribute', name: string, display: string, dataType: string, dataOption?: any | null | undefined, screens?: any | null | undefined, editable: boolean, active: boolean } };
 

+ 3 - 0
app/frontend/common/initializer/globalComponents.ts

@@ -3,15 +3,18 @@
 import type { App } from 'vue'
 import CommonIcon from '@common/components/common/CommonIcon.vue'
 import CommonLink from '@common/components/common/CommonLink.vue'
+import CommonDateTime from '@common/components/common/CommonDateTime.vue'
 
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
     CommonIcon: typeof CommonIcon
     CommonLink: typeof CommonLink
+    CommonDateTime: typeof CommonDateTime
   }
 }
 
 export default function initializeGlobalComponents(app: App): void {
   app.component('CommonIcon', CommonIcon)
   app.component('CommonLink', CommonLink)
+  app.component('CommonDateTime', CommonDateTime)
 }

+ 11 - 0
app/frontend/common/initializer/translatableMarker.ts

@@ -0,0 +1,11 @@
+// Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
+
+// Add global __() method for marking translatable strings.
+
+// eslint-disable-next-line no-underscore-dangle
+window.__ = function __(source: string): string {
+  return source
+}
+
+// Add 'export' to treat this as a JS module.
+export {}

Some files were not shown because too many files changed in this diff