parent
16221a46a7
commit
1390cc1f13
@ -0,0 +1,37 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
ManyToOne,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { MediaStatus } from '../constants/media';
|
||||
import Media from './Media';
|
||||
|
||||
@Entity()
|
||||
class Season {
|
||||
@PrimaryGeneratedColumn()
|
||||
public id: number;
|
||||
|
||||
@Column()
|
||||
public seasonNumber: number;
|
||||
|
||||
@Column({ type: 'int', default: MediaStatus.UNKNOWN })
|
||||
public status: MediaStatus;
|
||||
|
||||
@ManyToOne(() => Media, (media) => media.seasons)
|
||||
public media: Media;
|
||||
|
||||
@CreateDateColumn()
|
||||
public createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
public updatedAt: Date;
|
||||
|
||||
constructor(init?: Partial<Season>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
|
||||
export default Season;
|
@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import useSWR from 'swr';
|
||||
import LoadingSpinner from '../Common/LoadingSpinner';
|
||||
import Badge from '../Common/Badge';
|
||||
import { FormattedDate, FormattedRelativeTime } from 'react-intl';
|
||||
import Button from '../Common/Button';
|
||||
import { hasPermission } from '../../../server/lib/permissions';
|
||||
import { Permission } from '../../hooks/useUser';
|
||||
|
||||
const SettingsJobs: React.FC = () => {
|
||||
const { data, error } = useSWR<{ name: string; nextExecutionTime: string }[]>(
|
||||
'/api/v1/settings/jobs'
|
||||
);
|
||||
|
||||
if (!data && !error) {
|
||||
return <LoadingSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="my-2 overflow-x-auto -mx-6 sm:-mx-6 md:mx-4 lg:mx-4">
|
||||
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
||||
<div className="shadow overflow-hidden sm:rounded-lg">
|
||||
<table className="min-w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="px-6 py-3 bg-cool-gray-500 text-left text-xs leading-4 font-medium text-gray-200 uppercase tracking-wider">
|
||||
Job Name
|
||||
</th>
|
||||
<th className="px-6 py-3 bg-cool-gray-500 text-left text-xs leading-4 font-medium text-gray-200 uppercase tracking-wider">
|
||||
Next Execution
|
||||
</th>
|
||||
<th className="px-6 py-3 bg-cool-gray-500"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-cool-gray-600 divide-y divide-cool-gray-700">
|
||||
{data?.map((job, index) => (
|
||||
<tr key={`job-list-${index}`}>
|
||||
<td className="px-6 py-4 whitespace-no-wrap">
|
||||
<div className="text-sm leading-5 text-white">
|
||||
{job.name}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-no-wrap">
|
||||
<div className="text-sm leading-5 text-white">
|
||||
<FormattedRelativeTime
|
||||
value={Math.floor(
|
||||
(new Date(job.nextExecutionTime).getTime() -
|
||||
Date.now()) /
|
||||
1000
|
||||
)}
|
||||
updateIntervalInSeconds={1}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-no-wrap text-right text-sm leading-5 font-medium">
|
||||
<Button buttonType="primary">Run Now</Button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsJobs;
|
@ -0,0 +1,96 @@
|
||||
import React from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import useSWR from 'swr';
|
||||
import LoadingSpinner from '../Common/LoadingSpinner';
|
||||
import type { User } from '../../../server/entity/User';
|
||||
|
||||
const UserProfile: React.FC = () => {
|
||||
const router = useRouter();
|
||||
const { data, error } = useSWR<User>(`/api/v1/user/${router.query.userId}`);
|
||||
|
||||
if (!data && !error) {
|
||||
return <LoadingSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="py-6 px-4 space-y-6 sm:p-6 lg:pb-8">
|
||||
<div className="md:flex md:items-center md:justify-between mt-8 mb-6">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h2 className="text-2xl font-bold leading-7 text-cool-gray-100 sm:text-3xl sm:leading-9 sm:truncate">
|
||||
User Profile
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col space-y-6 lg:flex-row lg:space-y-0 lg:space-x-6 text-white">
|
||||
<div className="flex-grow space-y-6">
|
||||
<div className="space-y-1">
|
||||
<label
|
||||
htmlFor="username"
|
||||
className="block text-sm font-medium leading-5 text-cool-gray-400"
|
||||
>
|
||||
Username
|
||||
</label>
|
||||
<div className="rounded-md shadow-sm flex">
|
||||
<input
|
||||
id="username"
|
||||
className="form-input flex-grow block w-full min-w-0 rounded-md transition duration-150 ease-in-out sm:text-sm sm:leading-5 bg-cool-gray-700 border border-cool-gray-500"
|
||||
value={data?.username}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-medium leading-5 text-cool-gray-400"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<div className="rounded-md shadow-sm flex">
|
||||
<input
|
||||
id="email"
|
||||
className="form-input flex-grow block w-full min-w-0 rounded-md transition duration-150 ease-in-out sm:text-sm sm:leading-5 bg-cool-gray-700 border border-cool-gray-500"
|
||||
value={data?.email}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-grow space-y-1 lg:flex-grow-0 lg:flex-shrink-0">
|
||||
<p
|
||||
className="block text-sm leading-5 font-medium text-cool-gray-400"
|
||||
aria-hidden="true"
|
||||
>
|
||||
Avatar
|
||||
</p>
|
||||
<div className="lg:hidden">
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className="flex-shrink-0 inline-block rounded-full overflow-hidden h-12 w-12"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<img
|
||||
className="rounded-full h-full w-full"
|
||||
src={data?.avatar}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="hidden relative rounded-full overflow-hidden lg:block transition duration-150 ease-in-out">
|
||||
<img
|
||||
className="relative rounded-full w-40 h-40"
|
||||
src={data?.avatar}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserProfile;
|
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import type { NextPage } from 'next';
|
||||
import SettingsLayout from '../../components/Settings/SettingsLayout';
|
||||
import SettingsJobs from '../../components/Settings/SettingsJobs';
|
||||
|
||||
const SettingsMainPage: NextPage = () => {
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<SettingsJobs />
|
||||
</SettingsLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsMainPage;
|
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { NextPage } from 'next';
|
||||
import UserProfile from '../../components/UserProfile';
|
||||
|
||||
const UserProfilePage: NextPage = () => {
|
||||
return <UserProfile />;
|
||||
};
|
||||
|
||||
export default UserProfilePage;
|
Loading…
Reference in new issue